|
1 // Copyright (c) 2007-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 // class for the rtpwrapper unit test cases |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file |
|
20 */ |
|
21 |
|
22 #include <e32math.h> |
|
23 #include <commdbconnpref.h> |
|
24 #include <rtp.h> |
|
25 #include <rtcp.h> |
|
26 #include <COMMDB.H> |
|
27 #include <srtpsession.h> |
|
28 #include "rtpheader.h" |
|
29 #include "rtpmanager.h" |
|
30 |
|
31 TInt RtpSessionLinearOrderFunc(const CRtpSessionInfo& aNew, const CRtpSessionInfo &aArrElem) |
|
32 { |
|
33 return aNew.iPortNumber - aArrElem.iPortNumber; |
|
34 } |
|
35 |
|
36 CRtpSessionInfo* CRtpSessionInfo::NewL() |
|
37 { |
|
38 LOG_FUNC_ENTRY("CRtpSessionInfo::NewL"); |
|
39 CRtpSessionInfo *self = new(ELeave) CRtpSessionInfo(); |
|
40 |
|
41 CleanupStack::PushL(self); |
|
42 self->ConstructL(); |
|
43 CleanupStack::Pop(); |
|
44 |
|
45 LOG_FUNC_EXIT("CRtpSessionInfo::NewL"); |
|
46 return self; |
|
47 } |
|
48 |
|
49 void CRtpSessionInfo::ConstructL() |
|
50 { |
|
51 LOG_FUNC_ENTRY("CRtpSessionInfo::ConstructL"); |
|
52 } |
|
53 |
|
54 /* Creates a CrtpManager object */ |
|
55 CRtpManager* CRtpManager::NewL(MRtpErrNotify& aErrNotify ) |
|
56 { |
|
57 LOG_FUNC_ENTRY("CRtpManager::NewL"); |
|
58 CRtpManager *self = new(ELeave) CRtpManager(); |
|
59 |
|
60 CleanupStack::PushL(self); |
|
61 self->ConstructL(aErrNotify); |
|
62 CleanupStack::Pop(); |
|
63 |
|
64 LOG_FUNC_EXIT("CRtpManager::NewL"); |
|
65 return self; |
|
66 } |
|
67 |
|
68 CRtpManager::CRtpManager( ) |
|
69 { |
|
70 LOG_FUNC_ENTRY("CRtpManager::CRtpManager"); |
|
71 iOwnsConnection = EFalse; |
|
72 iOwnsSocketServer = EFalse; |
|
73 LOG_FUNC_EXIT("CRtpManager::CRtpManager"); |
|
74 } |
|
75 |
|
76 CRtpManager::~CRtpManager( ) |
|
77 { |
|
78 LOG_FUNC_ENTRY("CRtpManager::~CRtpManager"); |
|
79 |
|
80 Close(); |
|
81 |
|
82 /* Clean up the Arrays */ |
|
83 iRtpSessionArr.Close(); |
|
84 iRtpStreamsArr.Close(); |
|
85 |
|
86 if(iOwnsConnection) |
|
87 delete iConnection; |
|
88 if(iOwnsSocketServer) |
|
89 delete iSocketServ; |
|
90 |
|
91 LOG_FUNC_EXIT("CRtpManager::~CRtpManager"); |
|
92 } |
|
93 |
|
94 void CRtpManager::ConstructL(MRtpErrNotify& aErrNotify ) |
|
95 { |
|
96 LOG_FUNC_ENTRY("CRtpManager::ConstructL"); |
|
97 iRtpErrNotify = &aErrNotify; |
|
98 LOG_FUNC_EXIT("CRtpManager::ConstructL"); |
|
99 } |
|
100 |
|
101 |
|
102 TInt CRtpManager::OpenL( const TRtpSdesParams& aSdesInfo, const TDesC* aRtpPacketDll, |
|
103 const RSocketServ* aSocketServPtr, const RConnection* aConnPtr ) |
|
104 { |
|
105 LOG_FUNC_ENTRY("CRtpManager::OpenL"); |
|
106 /* The current implementation do not support having a different |
|
107 * aRtpPacketDll |
|
108 * So the argument is ignored */ |
|
109 (void)aRtpPacketDll; |
|
110 |
|
111 if(aSocketServPtr) |
|
112 { |
|
113 iSocketServ = const_cast<RSocketServ*>(aSocketServPtr); |
|
114 } |
|
115 else |
|
116 { |
|
117 iSocketServ = new(ELeave) RSocketServ(); |
|
118 iOwnsSocketServer = ETrue; |
|
119 } |
|
120 |
|
121 if(aConnPtr) |
|
122 { |
|
123 iConnection = const_cast<RConnection*>(aConnPtr); |
|
124 } |
|
125 else |
|
126 { |
|
127 iConnection = new(ELeave) RConnection(); |
|
128 iOwnsConnection = ETrue; |
|
129 } |
|
130 |
|
131 iSdesInfo = aSdesInfo; |
|
132 |
|
133 User::LeaveIfError(iSocketServ->Connect()); |
|
134 |
|
135 User::LeaveIfError(iConnection->Open(*iSocketServ)); |
|
136 |
|
137 LOG_FUNC_EXIT("CRtpManager::OpenL"); |
|
138 return KErrNone; |
|
139 } |
|
140 |
|
141 |
|
142 /** |
|
143 * Open and initialize the CRtpAPI object. |
|
144 * @param aIapId - [input] IAP ID. If -1, no IAP selection dialog |
|
145 * will pop up. Instead, the default IAP will be used. |
|
146 * @return KErrNone if successful; system wide error code otherwise |
|
147 */ |
|
148 TInt CRtpManager::StartConnection( TInt aIapId ) |
|
149 { |
|
150 LOG_FUNC_ENTRY("CRtpManager::StartConnection"); |
|
151 __RTP_LOG1("IapId = %d",aIapId) |
|
152 if(aIapId != -1) |
|
153 { |
|
154 TCommDbConnPref prefs; |
|
155 prefs.SetDialogPreference(ECommDbDialogPrefDoNotPrompt); |
|
156 prefs.SetDirection(ECommDbConnectionDirectionOutgoing); |
|
157 prefs.SetIapId(aIapId); |
|
158 iIapId = aIapId; |
|
159 return iConnection->Start(prefs); |
|
160 } |
|
161 else |
|
162 { |
|
163 TRAPD(err,iIapId = GetDefaultIapIdL()); |
|
164 if(KErrNone != err) |
|
165 { |
|
166 __RTP_LOG1("GetDefaultIapIdL returned %d",err) |
|
167 return err; |
|
168 } |
|
169 __RTP_LOG1("GetDefaultIapIdL default Iap: %d",iIapId) |
|
170 LOG_FUNC_EXIT("CRtpManager::StartConnection"); |
|
171 return iConnection->Start(); |
|
172 } |
|
173 } |
|
174 |
|
175 TInt CRtpManager::StartConnection( TRequestStatus& aStatus, TInt aIapId) |
|
176 { |
|
177 LOG_FUNC_ENTRY("CRtpManager::StartConnection-Async"); |
|
178 __RTP_LOG1("aIapId = %d",aIapId); |
|
179 |
|
180 TCommDbConnPref prefs; |
|
181 prefs.SetDialogPreference(ECommDbDialogPrefDoNotPrompt); |
|
182 prefs.SetDirection(ECommDbConnectionDirectionOutgoing); |
|
183 |
|
184 if(aIapId != -1) |
|
185 { |
|
186 prefs.SetIapId(aIapId); |
|
187 iConnection->Start(prefs, aStatus); |
|
188 iIapId = aIapId; |
|
189 } |
|
190 else |
|
191 { |
|
192 TRAPD(err,iIapId = GetDefaultIapIdL()); |
|
193 if(KErrNone != err) |
|
194 { |
|
195 __RTP_LOG1("GetDefaultIapIdL returned %d",err) |
|
196 return err; |
|
197 } |
|
198 __RTP_LOG1("GetDefaultIapIdL default Iap: %d",iIapId) |
|
199 prefs.SetIapId(iIapId); |
|
200 iConnection->Start(prefs, aStatus); |
|
201 } |
|
202 LOG_FUNC_EXIT("CRtpManager::StartConnection-Async"); |
|
203 return KErrNone; |
|
204 } |
|
205 |
|
206 |
|
207 /** |
|
208 * Cancels asynchoronous start of connection. |
|
209 * Any open requests will be completed with KErrCancel. |
|
210 * @return None |
|
211 */ |
|
212 void CRtpManager::CancelStart() |
|
213 { |
|
214 LOG_FUNC_ENTRY("CRtpManager::CancelStart"); |
|
215 return; |
|
216 } |
|
217 |
|
218 |
|
219 void CRtpManager::Close() |
|
220 { |
|
221 LOG_FUNC_ENTRY("CRtpManager::Close"); |
|
222 /* Iterate through the session array and close */ |
|
223 for(int i=0; i < iRtpSessionArr.Count(); i++) |
|
224 { |
|
225 __RTP_LOG1("Closing Session Key %u",iRtpSessionArr[i]->iKey); |
|
226 iRtpSessionArr[i]->iRtpSession.Close(); |
|
227 ASSERT(iRtpSessionArr[i]->iPendingReqQue->IsEmpty()); |
|
228 delete iRtpSessionArr[i]->iPendingReqQue; |
|
229 iRtpSessionArr[i]->iPendingReqQue = NULL; |
|
230 } |
|
231 if(iConnection) |
|
232 iConnection->Close(); |
|
233 |
|
234 if(iSocketServ) |
|
235 iSocketServ->Close(); |
|
236 |
|
237 LOG_FUNC_EXIT("CRtpManager::Close"); |
|
238 } |
|
239 |
|
240 /** |
|
241 * Set SDES (Source Description) information of the local participant. |
|
242 * Participant is defined as an application program and |
|
243 * only one local participant is allowed. |
|
244 */ |
|
245 void CRtpManager::SetLocalSdes( const TRtpSdesParams& aSDES) |
|
246 { |
|
247 /* Should the SDES list be updated again here ? */ |
|
248 LOG_FUNC_ENTRY("CRtpManager::SetLocalSdes"); |
|
249 iSdesInfo = aSDES; |
|
250 } |
|
251 |
|
252 /** |
|
253 * Get the local IP address |
|
254 * @param None |
|
255 * @return local ip address. |
|
256 */ |
|
257 TInetAddr& CRtpManager::GetLocalIPAddressL() |
|
258 { |
|
259 LOG_FUNC_ENTRY("CRtpManager::GetLocalIPAddressL"); |
|
260 /* Open an RSocket and find its address */ |
|
261 RSocket socket; |
|
262 User::LeaveIfError(socket.Open(*iSocketServ, KAfInet, KSockDatagram, KProtocolInetUdp,*iConnection)); |
|
263 |
|
264 CleanupClosePushL(socket); |
|
265 |
|
266 TSoInetInterfaceInfo networkInfo; |
|
267 TPckg<TSoInetInterfaceInfo> opt(networkInfo); |
|
268 User::LeaveIfError(socket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl)); |
|
269 TSoInetIfQuery query; |
|
270 TPckg<TSoInetIfQuery> queryBuf(query); |
|
271 TInt res = KErrNone; |
|
272 do |
|
273 { |
|
274 res = socket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, opt); |
|
275 if (!res && opt().iState == EIfUp) |
|
276 { |
|
277 query.iName = opt().iName; |
|
278 res = socket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, queryBuf); |
|
279 if (!res && query.iZone[1] == iIapId) |
|
280 { |
|
281 networkInfo = opt(); |
|
282 break; |
|
283 } |
|
284 } |
|
285 } |
|
286 while (res == KErrNone); |
|
287 if(res!= KErrNone) |
|
288 { |
|
289 __RTP_LOG1("Found nothing! ret %d",res) |
|
290 /* Didn't find :( */ |
|
291 User::Leave(res); |
|
292 } |
|
293 CleanupStack::PopAndDestroy(1); |
|
294 iSockAddr = networkInfo.iAddress; |
|
295 LOG_FUNC_EXIT("CRtpManager::GetLocalIPAddressL"); |
|
296 return iSockAddr; |
|
297 } |
|
298 /** |
|
299 * Makes a CName that is unique for a given seesion |
|
300 */ |
|
301 void CRtpManager::MakeACnameL(TDes8 &aCname) |
|
302 { |
|
303 /* As of now putting the IP Address. But this is not enough. |
|
304 * multiple sessions should have unique CNAMES |
|
305 * */ |
|
306 TBuf<50> ipAddr; |
|
307 TInetAddr locAddr = GetLocalIPAddressL(); |
|
308 locAddr.Output(ipAddr); |
|
309 aCname.Format(_L8("%d@"),iRtpSessionArr.Count()+1); |
|
310 aCname.Append(ipAddr); |
|
311 } |
|
312 /** |
|
313 * Create a new RTP Session and return the Session ID as well as the |
|
314 * local port number assigned for RTP. RTP uses an even port number and |
|
315 * RTCP, if enabled, uses the next higher (odd) port number. |
|
316 */ |
|
317 TRtpId CRtpManager::CreateSessionL(const TCreateSessionParams& aSessionParams, |
|
318 TUint& aPort, TBool aEnableRtcp, const TRtcpParams* aRtcpParams ) |
|
319 { |
|
320 LOG_FUNC_ENTRY("CRtpManager::CreateSessionL"); |
|
321 __RTP_LOG1("RTCP stat %d",aEnableRtcp) |
|
322 TInt localPort; |
|
323 /* The RTP Session create takes in the LocalPort.*/ |
|
324 if(iRtpSessionArr.Count() == 0) |
|
325 { |
|
326 //In this case start from begining. Start by using the default Even RTP |
|
327 //Port. |
|
328 localPort = KDefaultStartRtpAddress; |
|
329 __RTP_LOG1("LocalPort used %d",localPort) |
|
330 } |
|
331 else |
|
332 { |
|
333 /* Pick the next highest port number */ |
|
334 localPort = iRtpSessionArr[iRtpSessionArr.Count()-1]->iPortNumber + 2; |
|
335 __RTP_LOG1("LocalPort used %d",localPort) |
|
336 } |
|
337 |
|
338 //if the user has specified a port then override our selection |
|
339 if(aPort) |
|
340 { |
|
341 localPort = aPort; |
|
342 } |
|
343 |
|
344 //Now use this Port and try opening the RTP Session. If the Session Open |
|
345 //fails try opening with the next even port. |
|
346 //Its much more easier to use the API which takes RSocket directly here. But |
|
347 //ths would mean we cannot use the New CFRTP API. |
|
348 TInetAddr locAddr(0,localPort); |
|
349 |
|
350 /* Remote address is uninitialized. Unfortunately its required by Symbian |
|
351 * RTP stack. */ |
|
352 TInetAddr remAddr; |
|
353 |
|
354 #ifndef SYMBIAN_ENABLE_SPLIT_HEADERS |
|
355 RRtpSession rtpSession; |
|
356 #else |
|
357 RRtpSession_Internal rtpSession; |
|
358 #endif |
|
359 |
|
360 TPtrC8 cnameTptr((TUint8*)"", 0);; |
|
361 if(aEnableRtcp) |
|
362 { |
|
363 TBuf8<50> cnameBuf; |
|
364 if(iSdesInfo.iCName == KNullDesC8) |
|
365 { |
|
366 MakeACnameL(cnameBuf); |
|
367 iSdesInfo.iCName.Set(cnameBuf); |
|
368 } |
|
369 cnameTptr.Set(iSdesInfo.iCName); |
|
370 } |
|
371 else |
|
372 { |
|
373 cnameTptr.Set(KNullDesC8); |
|
374 } |
|
375 |
|
376 TInt tryCount = 0; |
|
377 TInt errOpenl = KErrNone; |
|
378 |
|
379 __RTP_LOG1("Starting Port alloc and OpenL tryCount %d",tryCount); |
|
380 __RTP_LOG1("aSessionParams.iSocketBufSize %d",aSessionParams.iSocketBufSize); |
|
381 aPort = locAddr.Port(); |
|
382 |
|
383 while(tryCount < 5 ) |
|
384 { |
|
385 TRAP(errOpenl,rtpSession.OpenL(*iSocketServ, locAddr, remAddr, aSessionParams.iSocketBufSize, *iConnection, EPriorityNormal, cnameTptr)); |
|
386 if(errOpenl != KErrNone) |
|
387 { |
|
388 __RTP_LOG2("OpenL Failed with Error Code %d TryCount %d",errOpenl, tryCount); |
|
389 tryCount ++; |
|
390 locAddr.SetPort(locAddr.Port()+tryCount+1); |
|
391 localPort += tryCount+1; |
|
392 } |
|
393 else |
|
394 { |
|
395 break; |
|
396 } |
|
397 } |
|
398 |
|
399 User::LeaveIfError(errOpenl); |
|
400 |
|
401 __RTP_LOG(",rtpSession.OpenL Success!!"); |
|
402 |
|
403 TTimeIntervalMicroSeconds32 rtcpInterval; |
|
404 if(aEnableRtcp && aRtcpParams) |
|
405 { |
|
406 rtpSession.SetBandwidth(aRtcpParams->iSessionBWidth); |
|
407 __RTP_LOG1(" aRtcpParams->iRtcpTimeOut %d", aRtcpParams->iRtcpTimeOut.Int()); |
|
408 if(aRtcpParams->iRtcpTimeOut.Int()) |
|
409 { |
|
410 rtcpInterval = aRtcpParams->iRtcpTimeOut.Int(); |
|
411 } |
|
412 else |
|
413 { |
|
414 //TODO fix me! |
|
415 //default 500 ms |
|
416 rtcpInterval = 1000000; |
|
417 } |
|
418 rtpSession.SetRtcpInterval(rtcpInterval); |
|
419 } |
|
420 else |
|
421 { |
|
422 __RTP_LOG("Setting default RTCP Properties!!"); |
|
423 //Default Bandwidth. |
|
424 rtpSession.SetBandwidth(KRtpDefaultBandWidth); |
|
425 rtcpInterval = 1000000; |
|
426 rtpSession.SetRtcpInterval(rtcpInterval); |
|
427 } |
|
428 |
|
429 //Phew! Now put these in our Array |
|
430 CRtpSessionInfo* sessionInfo = CRtpSessionInfo::NewL(); |
|
431 //Assign a Key for this session. |
|
432 sessionInfo->iKey = Math::Random(); |
|
433 sessionInfo->iPortNumber = localPort; |
|
434 sessionInfo->iRtpSession = rtpSession; |
|
435 sessionInfo->iRtpManager = this; |
|
436 sessionInfo->iRtcpEnabled = aEnableRtcp; |
|
437 sessionInfo->iPendingReqQue = new(ELeave) TSglQue<TRtpSendReqNode>(_FOFF(TRtpSendReqNode,iLink)); |
|
438 iRtpSessionArr.InsertInOrder(sessionInfo, TLinearOrder<CRtpSessionInfo>(RtpSessionLinearOrderFunc)); //InsertInOrder(sessionInfo,TLinearOrder<CRtpSessionInfo>(RtpSessionLinearOrderFunc)); |
|
439 |
|
440 __RTP_LOG1("Session Created Key %u",sessionInfo->iKey) |
|
441 //Get back the reference to the object in Array. |
|
442 TInt idx = FindSessionL(sessionInfo->iKey); |
|
443 |
|
444 //Register for the Events |
|
445 RegisterEventsOnSessionL(iRtpSessionArr[idx]); |
|
446 |
|
447 aPort = localPort; |
|
448 |
|
449 //TODO: Fix this in RTP Stack. |
|
450 /* Remote Address is uninitialized now. So if RTCP is enabled disable autosend so that |
|
451 * no data is send to incorrect address. |
|
452 */ |
|
453 if(aEnableRtcp) |
|
454 { |
|
455 rtpSession.SetRTCPAutoSend(EFalse); |
|
456 } |
|
457 |
|
458 |
|
459 LOG_FUNC_EXIT("CRtpManager::CreateSessionL"); |
|
460 |
|
461 return sessionInfo->iKey; |
|
462 } |
|
463 |
|
464 |
|
465 /** |
|
466 *Create a new, secure RTP Session and return the Session ID as well as the |
|
467 * local port number assigned for RTP. RTP uses an even port number and |
|
468 * RTCP, if enabled, uses the next higher (odd) port number. |
|
469 * User is expected to create corresponding SRTP session prior to calling this |
|
470 * function. |
|
471 */ |
|
472 TRtpId CRtpManager::CreateSessionL( const TCreateSessionParams& aSessionParams, TUint& aPort, |
|
473 TBool aEnableRtcp, const TRtcpParams* aRtcpParams, CSRTPSession& aSRTPSession) |
|
474 { |
|
475 LOG_FUNC_ENTRY("CRtpManager::CreateSessionL"); |
|
476 __RTP_LOG("SRTP is not supported Leaving..!!") |
|
477 |
|
478 TUint32 key = CreateSessionL(aSessionParams, aPort, aEnableRtcp, aRtcpParams); |
|
479 TInt idx = FindSessionL(key); |
|
480 iRtpSessionArr[idx]->iSRTPSession = &aSRTPSession; |
|
481 iRtpSessionArr[idx]->iRtpSession.SetPrePostProcessingRegisterCallback(iRtpSessionArr[idx]); |
|
482 return key; |
|
483 } |
|
484 |
|
485 /** |
|
486 * Start an RTP Session. If enabled, RTCP associated with the given |
|
487 * session is also started. |
|
488 */ |
|
489 TInt CRtpManager::StartSession( TRtpId aSessionId ) |
|
490 { |
|
491 LOG_FUNC_ENTRY("CRtpManager::StartSession"); |
|
492 if(FindSession(aSessionId)!= KErrNotFound) |
|
493 { |
|
494 /* Well we found the session. But Really nothing to do */ |
|
495 //TODO verify |
|
496 return KErrNone; |
|
497 } |
|
498 else |
|
499 { |
|
500 return KErrNotFound; |
|
501 } |
|
502 } |
|
503 |
|
504 /** |
|
505 * Close an RTP Session. |
|
506 */ |
|
507 void CRtpManager::CloseSession( TRtpId aSessionId ) |
|
508 { |
|
509 LOG_FUNC_ENTRY("CRtpManager::CloseSession"); |
|
510 __RTP_LOG1("SessID %u",aSessionId) |
|
511 TInt idx; |
|
512 idx = FindSession(aSessionId); |
|
513 if(KErrNotFound != idx) |
|
514 { |
|
515 /* This takes care of all cleaning up */ |
|
516 iRtpSessionArr[idx]->iRtpSession.Close(); |
|
517 /* There should be no more Pending requests on this session */ |
|
518 ASSERT(iRtpSessionArr[idx]->iPendingReqQue->IsEmpty()); |
|
519 delete iRtpSessionArr[idx]->iPendingReqQue; |
|
520 CRtpSessionInfo *session = iRtpSessionArr[idx]; |
|
521 iRtpSessionArr.Remove(idx); |
|
522 delete session; |
|
523 } |
|
524 else |
|
525 { |
|
526 __RTP_LOG("Session not found") |
|
527 //So already cleaned? |
|
528 } |
|
529 LOG_FUNC_EXIT("CRtpManager::CloseSession"); |
|
530 } |
|
531 |
|
532 /** |
|
533 * Set remote IP address and port number to RTP Session. |
|
534 * Port number for RTP must be an even number and the corresponding |
|
535 * RTCP, if enabled, will be set to use the next higher (odd) port. |
|
536 */ |
|
537 TInt CRtpManager::SetRemoteAddress( TRtpId aSessionId,const TInetAddr& aRemoteAddr ) |
|
538 { |
|
539 LOG_FUNC_ENTRY("CRtpManager::SetRemoteAddress"); |
|
540 __RTP_LOG1("SessID %u",aSessionId) |
|
541 __RTP_LOG_STMT(TBuf<50> buf; aRemoteAddr.Output(buf);); |
|
542 __RTP_LOG2("RemoteAddressAddress %S, Port %u", &buf, aRemoteAddr.Port()); |
|
543 TInt ret; |
|
544 TInetAddr addr = aRemoteAddr; |
|
545 if((ret =FindSession(aSessionId))!= KErrNotFound) |
|
546 { |
|
547 iRtpSessionArr[ret]->iRtpSession.SetRemoteAddress(addr); |
|
548 iRtpSessionArr[ret]->iRemoteAddress = aRemoteAddr; |
|
549 /* SET the RTCP address as well here */ |
|
550 iRtpSessionArr[ret]->iRemoteRTCPAddress = aRemoteAddr; |
|
551 iRtpSessionArr[ret]->iRemoteRTCPAddress.SetPort(aRemoteAddr.Port()+1); |
|
552 |
|
553 return KErrNone; |
|
554 } |
|
555 else |
|
556 { |
|
557 return KErrNotFound; |
|
558 } |
|
559 } |
|
560 |
|
561 /** |
|
562 * Set remote RTCP IP address and port number to RTP Session accoring to RFC 3605 |
|
563 * i.e. this should be used if RTCP port is different than RTP port + 1 |
|
564 */ |
|
565 TInt CRtpManager::SetRemoteRtcpAddress( TRtpId aSessionId, const TInetAddr& aRemoteAddr) |
|
566 { |
|
567 LOG_FUNC_ENTRY("CRtpManager::SetRemoteRtcpAddress"); |
|
568 __RTP_LOG1("SessID %u",aSessionId) |
|
569 __RTP_LOG_STMT(TBuf<50> buf; aRemoteAddr.Output(buf);); |
|
570 __RTP_LOG2("RemoteAddressAddress %S, Port %u", &buf, aRemoteAddr.Port()); |
|
571 TInt ret; |
|
572 TInt port = aRemoteAddr.Port(); |
|
573 if((ret =FindSession(aSessionId))!= KErrNotFound) |
|
574 { |
|
575 iRtpSessionArr[ret]->iRtpSession.SetRemoteRtcpPort(port); |
|
576 iRtpSessionArr[ret]->iRemoteRTCPAddress = aRemoteAddr; |
|
577 |
|
578 /* |
|
579 //VS Experiment. Try sending Door opener here to Remote end |
|
580 TRequestStatus stat; |
|
581 __RTP_LOG("CRtpManager::SetRemoteAddress -- Sending DoorOpener --RTCP"); |
|
582 RSocket *sock = NULL; |
|
583 sock = GetRtcpSocket(aSessionId); |
|
584 sock->SendTo(_L8("OpenSesame"),iRtpSessionArr[ret]->iRemoteAddress,0,stat); |
|
585 User::WaitForRequest(stat); |
|
586 __RTP_LOG1("DoorOpener --RTCP sent retCode %d", stat.Int()); |
|
587 LOG_FUNC_EXIT("CRtpManager::SetRemoteRtcpAddress"); |
|
588 */ |
|
589 return KErrNone; |
|
590 } |
|
591 else |
|
592 { |
|
593 return KErrNotFound; |
|
594 } |
|
595 } |
|
596 |
|
597 /** |
|
598 * Create a Receive stream for an RTP Session and return the stream |
|
599 * ID which is unique for all RTP Sessions. |
|
600 */ |
|
601 TRtpId CRtpManager::CreateReceiveStreamL( TRtpId aSessionId, const TRcvStreamParams& aParams ) |
|
602 { |
|
603 LOG_FUNC_ENTRY("CRtpManager::CreateReceiveStreamL"); |
|
604 __RTP_LOG1("SessID %u",aSessionId) |
|
605 /* Valide the session */ |
|
606 FindSessionL(aSessionId); |
|
607 |
|
608 /* Check for Post-Created Streams. If present use it */ |
|
609 for(TInt i=0; i < iRtpStreamsArr.Count(); i++) |
|
610 { |
|
611 if(iRtpStreamsArr[i].iSessionKey == aSessionId && |
|
612 iRtpStreamsArr[i].iState == TRtpStreamInfo::eStreamPostCreated && |
|
613 iRtpStreamsArr[i].iPayloadType == aParams.iPayloadType ) |
|
614 { |
|
615 __RTP_LOG1("Found Post Created Stream Key %u",iRtpStreamsArr[i].iKey) |
|
616 /* Post created stream exists. Return it */ |
|
617 iRtpStreamsArr[i].iState = TRtpStreamInfo::eStreamReadyToUse; |
|
618 return iRtpStreamsArr[i].iKey; |
|
619 } |
|
620 } |
|
621 |
|
622 /* OK found nothing. So create a Pre-Created stream and return its ID */ |
|
623 TRtpStreamInfo strmInfo; |
|
624 strmInfo.iKey = Math::Random(); |
|
625 strmInfo.iSessionKey = aSessionId; |
|
626 strmInfo.iState = TRtpStreamInfo::eStreamPreCreated; |
|
627 strmInfo.iPayloadType = aParams.iPayloadType; |
|
628 strmInfo.iRtpManager = this; |
|
629 |
|
630 iRtpStreamsArr.AppendL(strmInfo); |
|
631 __RTP_LOG1("Created PreCreated Stream Key %u",strmInfo.iKey) |
|
632 |
|
633 LOG_FUNC_EXIT("CRtpManager::CreateReceiveStreamL"); |
|
634 return strmInfo.iKey; |
|
635 } |
|
636 |
|
637 /** |
|
638 * Create a Transmit stream for an RTP Session and return the stream |
|
639 * ID which is unique for all RTP Sessions. SSRC value assigned for the |
|
640 * very first Transmit stream will be the same as the default SSRC |
|
641 * value reserved internally by CreateSession function. This function |
|
642 * is normally used to create a transmit stream where SSRC value is |
|
643 * randomly generated. |
|
644 */ |
|
645 TRtpId CRtpManager::CreateTransmitStreamL( TRtpId aSessionId, |
|
646 const TTranStreamParams& aParams, |
|
647 TRtpSSRC& aSSRC ) |
|
648 { |
|
649 LOG_FUNC_ENTRY("CRtpManager::CreateTransmitStreamL"); |
|
650 __RTP_LOG1("SessID %u",aSessionId) |
|
651 TInt idx = FindSessionL(aSessionId); |
|
652 if(!iRtpSessionArr[idx]->iRtpSendSource.IsOpen()) |
|
653 { |
|
654 iRtpSessionArr[idx]->iRtpSendSource = iRtpSessionArr[idx]->iRtpSession.NewSendSourceL(); |
|
655 /* Now register for events in this session */ |
|
656 iRtpSessionArr[idx]->iRtpSendSource.RegisterEventCallbackL(ERtpSendSucceeded, |
|
657 RtpSessionLevelCB, |
|
658 iRtpSessionArr[idx], |
|
659 ERtpNotOneShot); |
|
660 iRtpSessionArr[idx]->iRtpSendSource.RegisterEventCallbackL(ERtpSendFail, |
|
661 RtpSessionLevelCB, |
|
662 iRtpSessionArr[idx], |
|
663 ERtpNotOneShot); |
|
664 aSSRC = iRtpSessionArr[idx]->iRtpSendSource.GetLocalSSRC(); |
|
665 |
|
666 iRtpSessionArr[idx]->iPayloadType = aParams.iPayloadType; |
|
667 |
|
668 iRtpSessionArr[idx]->iRtpSendSource.SetPayloadType(aParams.iPayloadType); |
|
669 |
|
670 |
|
671 //Note: The key is same as the SessionKey. We donot support |
|
672 //more than one Transmit Streams in one Session. |
|
673 LOG_FUNC_EXIT("CRtpManager::CreateTransmitStreamL"); |
|
674 |
|
675 return iRtpSessionArr[idx]->iKey; |
|
676 } |
|
677 __RTP_LOG("A SendStream was already Opened!") |
|
678 //Already called still there might be Applications calling this |
|
679 //API twice |
|
680 // |
|
681 LOG_FUNC_EXIT("CRtpManager::CreateTransmitStreamL"); |
|
682 return 0; |
|
683 } |
|
684 |
|
685 /** |
|
686 * Create a Transmit stream, with a given SSRC value, for an RTP Session |
|
687 * and return the stream ID which is unique for all RTP Sessions. This |
|
688 * extended function is used for a special case where a specific SSRC |
|
689 * value needs to be associated with the transmit stream being created, |
|
690 * e.g. for retransmission purpose. |
|
691 */ |
|
692 TRtpId CRtpManager::CreateTransmitStreamExtL( TRtpId , const TTranStreamParams& , |
|
693 const TRtpSSRC ) |
|
694 { |
|
695 LOG_FUNC_ENTRY("CRtpManager::CreateTransmitStreamL"); |
|
696 __RTP_LOG("NotSuppoted SSRC cannot be changed") |
|
697 //This is not supported as of now. |
|
698 //SSRC cannot be specified by Applications. |
|
699 return 0; |
|
700 } |
|
701 |
|
702 |
|
703 /** |
|
704 * Close a Transmit or Receive stream. |
|
705 */ |
|
706 void CRtpManager::CloseStream( TRtpId aRtpID) |
|
707 { |
|
708 LOG_FUNC_ENTRY("CRtpManager::CloseStream"); |
|
709 __RTP_LOG1("Stream ID %u",aRtpID) |
|
710 (void)aRtpID; |
|
711 //Streams are closed when session is closed. |
|
712 //so no requirement for an explicit close |
|
713 //TODO Verify Requirements |
|
714 return; |
|
715 } |
|
716 |
|
717 /** |
|
718 * Register a callback object for receiving RTP data packets from an RTP |
|
719 * Session. Only one receiver callback object is allowed to be |
|
720 * registered for one Session. |
|
721 */ |
|
722 TInt CRtpManager::RegisterRtpObserver( TRtpId aSessionId, MRtpObserver& aRtpObserver ) |
|
723 { |
|
724 LOG_FUNC_ENTRY("CRtpManager::RegisterRtpObserver"); |
|
725 __RTP_LOG1("SessID %u",aSessionId) |
|
726 TInt ret = FindSession(aSessionId); |
|
727 if(ret < 0) |
|
728 return ret; |
|
729 iRtpSessionArr[ret]->iRtpObserver = &aRtpObserver; |
|
730 return KErrNone; |
|
731 } |
|
732 |
|
733 /** |
|
734 * Unregister RTP observer callback object associated with an RTP |
|
735 * session. |
|
736 */ |
|
737 void CRtpManager::UnregisterRtpObserver(TRtpId aSessionId) |
|
738 { |
|
739 LOG_FUNC_ENTRY("CRtpManager::UnregisterRtpObserver"); |
|
740 __RTP_LOG1("SessID %u",aSessionId) |
|
741 |
|
742 TInt ret = FindSession(aSessionId); |
|
743 if(ret >= 0) |
|
744 iRtpSessionArr[ret]->iRtpObserver = NULL; |
|
745 } |
|
746 |
|
747 /** |
|
748 * Sets/resets the observer for the non-RTP data. |
|
749 * Only one receiver callback object is allowed to be |
|
750 * registered for one Session. |
|
751 * called when a non-RTP data packet is received. |
|
752 */ |
|
753 TInt CRtpManager::SetNonRTPDataObserver( TRtpId aSessionId, MNonRTPDataObserver* aNonRtpObserver) |
|
754 { |
|
755 LOG_FUNC_ENTRY("CRtpManager::SetNonRTPDataObserver"); |
|
756 __RTP_LOG1("SessID %u",aSessionId); |
|
757 |
|
758 TInt ret = FindSession(aSessionId); |
|
759 if(ret < 0) |
|
760 return ret; |
|
761 iRtpSessionArr[ret]->iNonRtpDataObserver = aNonRtpObserver; |
|
762 |
|
763 TRAPD(err,iRtpSessionArr[ret]->iRtpSession.RegisterEventCallbackL(ENonRtpDataReceived, |
|
764 RtpSessionLevelCB, |
|
765 iRtpSessionArr[ret], |
|
766 ERtpOneShot)); |
|
767 if(KErrNone != err) |
|
768 { |
|
769 __RTP_LOG1("err %d",err); |
|
770 return err; |
|
771 } |
|
772 |
|
773 TRAP(err,iRtpSessionArr[ret]->iRtpSession.RegisterEventCallbackL(ENonRtcpDataReceived, |
|
774 RtpSessionLevelCB, |
|
775 iRtpSessionArr[ret], |
|
776 ERtpOneShot)); |
|
777 |
|
778 if(KErrNone != err) |
|
779 { |
|
780 /* The already registered callback will be deleted when the first |
|
781 * NonRtp data comes |
|
782 */ |
|
783 iRtpSessionArr[ret]->iNonRtpDataObserver = 0; |
|
784 } |
|
785 return err; |
|
786 } |
|
787 |
|
788 /** |
|
789 * Send an RTP data packet in a Transmit stream synchronously. |
|
790 */ |
|
791 TInt CRtpManager::SendRtpPacket( TRtpId aTranStreamId, |
|
792 const TRtpSendHeader& aHeaderInfo, |
|
793 const TDesC8& aPayloadData ) |
|
794 { |
|
795 LOG_FUNC_ENTRY("CRtpManager::SendRtpPacket"); |
|
796 __RTP_LOG1("aTranStreamId: %u",aTranStreamId) |
|
797 |
|
798 /* The Transmit Id and Session ID are same. So |
|
799 * find the session */ |
|
800 TInt ret = FindSession(aTranStreamId); |
|
801 if(ret<0) |
|
802 return ret; |
|
803 ASSERT(iRtpSessionArr[ret]->iRtpSendSource.IsOpen()); |
|
804 |
|
805 RRtpSendPacket sendPkt; |
|
806 TInt pktLen = 0; |
|
807 pktLen += aPayloadData.Length(); |
|
808 __RTP_LOG1("pktLen: %d", pktLen ); |
|
809 if(iRtpSessionArr[ret]->iSRTPSession) |
|
810 { |
|
811 /* SRTP is enabled so allocate more bytes for MKI and AuthTag */ |
|
812 pktLen += ( KSrtpMaxAuthTagLength + KSrtpMaxMKILen ); |
|
813 __RTP_LOG1("Added extra bytes for SRTP new pktLen: %d", pktLen ); |
|
814 } |
|
815 TRAPD(err,sendPkt = iRtpSessionArr[ret]->iRtpSendSource.NewSendPacketL(pktLen, aHeaderInfo.iHeaderExtension?aHeaderInfo.iHeaderExtension->iLength:KRtpNoExtension)); |
|
816 if(err != KErrNone) |
|
817 return err; |
|
818 |
|
819 __RTP_LOG2("TS: %u, PayloadType %d",aHeaderInfo.iTimestamp, aHeaderInfo.iPayloadType) |
|
820 sendPkt.SetTimestamp(aHeaderInfo.iTimestamp); |
|
821 sendPkt.SetMarker(aHeaderInfo.iMarker); |
|
822 sendPkt.SetPayloadType(aHeaderInfo.iPayloadType); |
|
823 |
|
824 if(iRtpSessionArr[ret]->iFirstPacketSent == EFalse) |
|
825 { |
|
826 iRtpSessionArr[ret]->iRtpSession.SetRTPTimeConversion(aHeaderInfo.iTimestamp, iRtpSessionArr[ret]->iSamplingRate/1000); |
|
827 iRtpSessionArr[ret]->iFirstPacketSent = ETrue; |
|
828 } |
|
829 |
|
830 TDes8 &wrtPayload = sendPkt.WritePayload(); |
|
831 wrtPayload = aPayloadData; |
|
832 |
|
833 ret = sendPkt.SendSync(); |
|
834 |
|
835 //TODO pre allocate a Max Size |
|
836 sendPkt.Close(); |
|
837 |
|
838 LOG_FUNC_EXIT("CRtpManager::SendRtpPacket"); |
|
839 return ret; |
|
840 } |
|
841 |
|
842 |
|
843 /** |
|
844 * Send an RTP data packet in a Transmit stream asynchronously. |
|
845 */ |
|
846 TInt CRtpManager::SendRtpPacket( TRtpId aTranStreamId, |
|
847 const TRtpSendHeader& aHeaderInfo, |
|
848 const TDesC8& aPayloadData, |
|
849 TRequestStatus& aStatus ) |
|
850 { |
|
851 LOG_FUNC_ENTRY("CRtpManager::SendRtpPacket"); |
|
852 __RTP_LOG1("aTranStreamId: %u",aTranStreamId) |
|
853 /* The Transmit Id and Session ID are same. So |
|
854 * find the session */ |
|
855 TInt ret = FindSession(aTranStreamId); |
|
856 if(ret<0) |
|
857 return ret; |
|
858 ASSERT(iRtpSessionArr[ret]->iRtpSendSource.IsOpen()); |
|
859 |
|
860 RRtpSendPacket sendPkt; |
|
861 TInt pktLen = 0; |
|
862 pktLen += aPayloadData.Length(); |
|
863 __RTP_LOG1("pktLen: %d", pktLen ); |
|
864 if(iRtpSessionArr[ret]->iSRTPSession) |
|
865 { |
|
866 /* SRTP is enabled so allocate more bytes for MKI and AuthTag */ |
|
867 pktLen += ( KSrtpMaxAuthTagLength + KSrtpMaxMKILen ); |
|
868 __RTP_LOG1("Added extra bytes for SRTP new pktLen: %d", pktLen ); |
|
869 } |
|
870 TRAPD(err,sendPkt = iRtpSessionArr[ret]->iRtpSendSource.NewSendPacketL(pktLen,aHeaderInfo.iHeaderExtension?aHeaderInfo.iHeaderExtension->iLength:KRtpNoExtension)); |
|
871 if(err != KErrNone) |
|
872 return err; |
|
873 |
|
874 __RTP_LOG2("TS: %u, PayloadType %d",aHeaderInfo.iTimestamp, aHeaderInfo.iPayloadType); |
|
875 sendPkt.SetTimestamp(aHeaderInfo.iTimestamp); |
|
876 sendPkt.SetMarker(aHeaderInfo.iMarker); |
|
877 sendPkt.SetPayloadType(aHeaderInfo.iPayloadType); |
|
878 |
|
879 |
|
880 if(iRtpSessionArr[ret]->iFirstPacketSent == EFalse) |
|
881 { |
|
882 iRtpSessionArr[ret]->iRtpSession.SetRTPTimeConversion(aHeaderInfo.iTimestamp, 1000*1000/iRtpSessionArr[ret]->iSamplingRate); |
|
883 iRtpSessionArr[ret]->iFirstPacketSent = ETrue; |
|
884 } |
|
885 |
|
886 |
|
887 TDes8 &wrtPayload = sendPkt.WritePayload(); |
|
888 wrtPayload = aPayloadData; |
|
889 |
|
890 /* This is an Async Send. So insert this packet in to the |
|
891 * the send queue. |
|
892 */ |
|
893 TRtpSendReqNode *sendReqNode = NULL; |
|
894 sendReqNode = new TRtpSendReqNode(); |
|
895 if(!sendReqNode) |
|
896 { |
|
897 sendPkt.Close(); |
|
898 return KErrNoMemory; |
|
899 } |
|
900 |
|
901 sendReqNode->iPktToSend = sendPkt; |
|
902 sendReqNode->iStatus = &aStatus; |
|
903 iRtpSessionArr[ret]->iPendingReqQue->AddFirst(*sendReqNode); |
|
904 *sendReqNode->iStatus = KRequestPending; |
|
905 /* If this is the only pending element in the queue schedule immediately */ |
|
906 if(iRtpSessionArr[ret]->iPendingReqQue->IsLast(sendReqNode)) |
|
907 { |
|
908 __RTP_LOG("Async Send ..Sending Immediately!"); |
|
909 return SendRtpDataFromPendingQueue(iRtpSessionArr[ret]); |
|
910 } |
|
911 |
|
912 __RTP_LOG("Async Send ..Packet Queued!"); |
|
913 //TODO pre allocate a Max Size |
|
914 // The packet will be closed when Send is completed |
|
915 return KErrNone; |
|
916 } |
|
917 |
|
918 /** |
|
919 * Send an RTP data packet asynchronously, with a given sequence number, |
|
920 * in a Transmit stream mainly for retransmission purpose. |
|
921 */ |
|
922 TInt CRtpManager::SendRtpPacket( TRtpId aTranStreamId, |
|
923 TRtpSequence , |
|
924 const TRtpSendHeader& aHeaderInfo, |
|
925 const TDesC8& aPayloadData, |
|
926 TRequestStatus& aStatus ) |
|
927 { |
|
928 LOG_FUNC_ENTRY("CRtpManager::SendRtpPacket - With Sequence Called!!"); |
|
929 //TODO We SHOULD consider the Sequence number as well! |
|
930 return SendRtpPacket(aTranStreamId, aHeaderInfo, aPayloadData, aStatus) ; |
|
931 } |
|
932 |
|
933 |
|
934 /** |
|
935 * Send a non-RTP (control) data packet asynchronously |
|
936 */ |
|
937 void CRtpManager::SendDataL( TRtpId aSessionId, TBool aUseRTPSocket, |
|
938 const TDesC8& aData, TRequestStatus& aStatus) |
|
939 { |
|
940 LOG_FUNC_ENTRY("CRtpManager::SendDataL"); |
|
941 __RTP_LOG1("aSessionId: %u",aSessionId) |
|
942 TInt ret = FindSessionL(aSessionId); |
|
943 RSocket *sock = NULL; |
|
944 TInetAddr remAddr = iRtpSessionArr[ret]->iRemoteAddress; |
|
945 if(aUseRTPSocket) |
|
946 { |
|
947 sock = GetRtpSocket(aSessionId); |
|
948 } |
|
949 else |
|
950 { |
|
951 if(!iRtpSessionArr[ret]->iRtcpEnabled) |
|
952 User::Leave(KErrNotSupported); |
|
953 sock = GetRtcpSocket(aSessionId); |
|
954 remAddr = iRtpSessionArr[ret]->iRemoteRTCPAddress; |
|
955 } |
|
956 /* Send the data out through the Socket */ |
|
957 sock->SendTo(aData,remAddr,0,aStatus); |
|
958 return; |
|
959 } |
|
960 |
|
961 /** |
|
962 * Cancel an outstanding SendRtpPacket() operation. |
|
963 */ |
|
964 void CRtpManager::CancelSend( TRtpId aSessId) |
|
965 { |
|
966 /* Its a Bit tricky here. |
|
967 * We have two levels of Active Objects and the Symbian stack |
|
968 * do not provide any API to cancel the Send request. As a workarnd we accesses the |
|
969 * RTP Socket directly and cancels the send ( RSocket::CancelSend()) |
|
970 * Internal statistics are not rolled back in this case, but surely we can |
|
971 * live with that. |
|
972 * |
|
973 * The Active object who issued this call will do a User::WaitForRequest() |
|
974 * immediatly after calling Cancel. (See CActive::Cancel() implementation). |
|
975 * This means we should complete the request with KErrCancel here itself or |
|
976 * thread will block (Because we are not exactly an Async Service provider). |
|
977 * Once the request is completed we can expect a ESendFail callback or an |
|
978 * ESendSuccess callback from stack ( Second one beacuse the request might have |
|
979 * been completed already). |
|
980 */ |
|
981 LOG_FUNC_ENTRY("CRtpManager::CancelSend"); |
|
982 __RTP_LOG1("SessId: %u",aSessId) |
|
983 |
|
984 TInt ret = FindSession(aSessId); |
|
985 if(ret < 0) |
|
986 { |
|
987 ASSERT(ret!=KErrNone); |
|
988 return; |
|
989 } |
|
990 if(iRtpSessionArr[ret]->iPendingReqQue->IsEmpty()) |
|
991 { |
|
992 /* There is no pending request. This probably means the request was |
|
993 * already completed but the App is yet to see it.. |
|
994 */ |
|
995 __RTP_LOG("NO pending request .. Returning!") |
|
996 return; |
|
997 } |
|
998 |
|
999 TRtpSendReqNode *reqNode = iRtpSessionArr[ret]->iPendingReqQue->Last(); |
|
1000 /* Once send is canceled complete Applications request. Also if the pending |
|
1001 * queue is not empty schedule a new transmission here itself */ |
|
1002 iRtpSessionArr[ret]->iRtpSendSource.Cancel(); |
|
1003 User::RequestComplete(reqNode->iStatus, KErrCancel); |
|
1004 iRtpSessionArr[ret]->iPendingReqQue->Remove(*reqNode); |
|
1005 reqNode->iPktToSend.Close(); |
|
1006 delete reqNode; |
|
1007 |
|
1008 if(!iRtpSessionArr[ret]->iPendingReqQue->IsEmpty()) |
|
1009 { |
|
1010 __RTP_LOG("Scheduling another send from PendingQueue") |
|
1011 SendRtpDataFromPendingQueue(iRtpSessionArr[ret]); |
|
1012 } |
|
1013 |
|
1014 return; |
|
1015 } |
|
1016 |
|
1017 /** |
|
1018 * Register a callback object for receiving RTCP packets associated with |
|
1019 * a given RTP Session. Only one observer callback object is allowed to |
|
1020 * be registered. One of aRtcpObserver object's callback functions is |
|
1021 * called when an RTCP packet of that type is received. |
|
1022 */ |
|
1023 TInt CRtpManager::RegisterRtcpObserver( TRtpId aSessionId, MRtcpObserver& aRtcpObserver ) |
|
1024 { |
|
1025 LOG_FUNC_ENTRY("CRtpManager::RegisterRtcpObserver"); |
|
1026 __RTP_LOG1("SessId: %u",aSessionId) |
|
1027 |
|
1028 TInt ret = FindSession(aSessionId); |
|
1029 if(ret < 0) |
|
1030 return ret; |
|
1031 iRtpSessionArr[ret]->iRtcpObserver = &aRtcpObserver; |
|
1032 return KErrNone; |
|
1033 } |
|
1034 |
|
1035 /** |
|
1036 * Unregister RTCP observer callback object associated with an RTP |
|
1037 * session. |
|
1038 */ |
|
1039 void CRtpManager::UnregisterRtcpObserver( TRtpId aSessionId ) |
|
1040 { |
|
1041 LOG_FUNC_ENTRY("CRtpManager::UnregisterRtcpObserver"); |
|
1042 __RTP_LOG1("SessId: %u",aSessionId) |
|
1043 |
|
1044 TInt ret = FindSession(aSessionId); |
|
1045 if(ret >= 0) |
|
1046 iRtpSessionArr[ret]->iRtcpObserver = NULL; |
|
1047 return; |
|
1048 } |
|
1049 /** |
|
1050 * Send an RTCP APP packet for a Transmit stream. |
|
1051 */ |
|
1052 TInt CRtpManager::SendRtcpAppPacket( TRtpId aTranStreamId, const TRtcpApp& aApp ) |
|
1053 { |
|
1054 LOG_FUNC_ENTRY("CRtpManager::SendRtcpAppPacket"); |
|
1055 __RTP_LOG1("aTranStreamId: %u",aTranStreamId) |
|
1056 |
|
1057 /* A send stream should be open to send an RTCP Bye packet */ |
|
1058 //Transmit Stream ID and Session Id are same |
|
1059 TInt ret = FindSession(aTranStreamId); |
|
1060 if(ret < 0) |
|
1061 return ret; |
|
1062 ASSERT(iRtpSessionArr[ret]->iRtcpEnabled); |
|
1063 |
|
1064 TPtrC8 appName; |
|
1065 appName.Set(aApp.iName,4); //Name is 4 Characters RFC 3550 Sec 6.7 |
|
1066 |
|
1067 TPtrC8 appData; |
|
1068 appData.Set(aApp.iAppData,aApp.iAppDataLen); |
|
1069 |
|
1070 TUint8 subType = aApp.iSubType; |
|
1071 |
|
1072 TRAPD(err,iRtpSessionArr[ret]->iRtpSession.SendAPPL(appName,appData, subType)); |
|
1073 |
|
1074 return err; |
|
1075 } |
|
1076 |
|
1077 /** |
|
1078 * Send an RTCP BYE packet for a Transmit stream. |
|
1079 */ |
|
1080 TInt CRtpManager::SendRtcpByePacket( TRtpId aTranStreamId, const TDesC8& aReason) |
|
1081 { |
|
1082 LOG_FUNC_ENTRY("CRtpManager::SendRtcpByePacket"); |
|
1083 __RTP_LOG1("aTranStreamId: %u",aTranStreamId) |
|
1084 |
|
1085 /* A send stream should be open to send an RTCP Bye packet */ |
|
1086 //Transmit Stream ID and Session Id are same |
|
1087 TInt ret = FindSession(aTranStreamId); |
|
1088 if(ret < 0) |
|
1089 return ret; |
|
1090 ASSERT(iRtpSessionArr[ret]->iRtpSendSource.IsOpen()); |
|
1091 TRAPD(err,iRtpSessionArr[ret]->iRtpSendSource.ByeL(const_cast<TDesC8&>(aReason))); |
|
1092 return err; |
|
1093 } |
|
1094 |
|
1095 /** |
|
1096 * Send an RTCP RR packet for a Reception stream. |
|
1097 */ |
|
1098 TInt CRtpManager::SendRtcpRrPacket( TRtpId aRcvStreamId ) |
|
1099 { |
|
1100 LOG_FUNC_ENTRY("CRtpManager::SendRtcpRrPacket"); |
|
1101 __RTP_LOG1("aRcvStreamId: %u",aRcvStreamId) |
|
1102 |
|
1103 /* No specific way to Send an RR Report alone */ |
|
1104 //Do we need to? |
|
1105 TInt ret = FindStream(aRcvStreamId); |
|
1106 if(ret<0) |
|
1107 { |
|
1108 return ret; |
|
1109 } |
|
1110 |
|
1111 ret = FindSession(iRtpStreamsArr[ret].iSessionKey); |
|
1112 TUint8 flg = 0x81; |
|
1113 TBuf8<1> flags; |
|
1114 flags.Copy(&flg,1); |
|
1115 TRAP(ret, iRtpSessionArr[ret]->iRtpSession.SendRTCPPacketL(flags)); |
|
1116 return ret; |
|
1117 } |
|
1118 |
|
1119 /** |
|
1120 * Send an RTCP SR packet for a Transmit stream. |
|
1121 */ |
|
1122 TInt CRtpManager::SendRtcpSrPacket( TRtpId aTranStreamId ) |
|
1123 { |
|
1124 LOG_FUNC_ENTRY("CRtpManager::SendRtcpSrPacket"); |
|
1125 __RTP_LOG1("aTranStreamId: %u",aTranStreamId) |
|
1126 |
|
1127 //NOTE: TransID same as SessionId |
|
1128 TInt ret = FindSession(aTranStreamId); |
|
1129 if(ret<0) |
|
1130 return ret; |
|
1131 |
|
1132 TUint8 flg = 0x81; |
|
1133 TBuf8<1> flags; |
|
1134 flags.Copy(&flg,1); |
|
1135 TRAP(ret, iRtpSessionArr[ret]->iRtpSession.SendRTCPPacketL(flags)); |
|
1136 return ret; |
|
1137 } |
|
1138 |
|
1139 /** |
|
1140 * Suspend RTCP sending on/off, calculations will continue. |
|
1141 */ |
|
1142 TInt CRtpManager::SuspendRtcpSending( TRtpId aSessionId, TBool aAutoSending ) |
|
1143 { |
|
1144 LOG_FUNC_ENTRY("CRtpManager::SuspendRtcpSending"); |
|
1145 __RTP_LOG2("aSessionId: %u aAutoSending %d",aSessionId,aAutoSending) |
|
1146 |
|
1147 //NOTE: TransID same as SessionId |
|
1148 TInt ret = FindSession(aSessionId); |
|
1149 if(ret<0) |
|
1150 return ret; |
|
1151 if(iRtpSessionArr[ret]->iRtcpEnabled) |
|
1152 { |
|
1153 iRtpSessionArr[ret]->iRtpSession.SetRTCPAutoSend(aAutoSending); |
|
1154 return KErrNone; |
|
1155 } |
|
1156 else |
|
1157 { |
|
1158 return KErrNotSupported; |
|
1159 } |
|
1160 } |
|
1161 |
|
1162 /** |
|
1163 * Gets the status of automatic RTCP sending. |
|
1164 */ |
|
1165 TInt CRtpManager::IsRtcpSendingSuspended( TRtpId aSessionId, TBool& aAutoSending ) |
|
1166 { |
|
1167 LOG_FUNC_ENTRY("CRtpManager::IsRtcpSendingSuspended"); |
|
1168 |
|
1169 TInt ret = FindSession(aSessionId); |
|
1170 if(ret<0) |
|
1171 return ret; |
|
1172 if(iRtpSessionArr[ret]->iRtcpEnabled) |
|
1173 { |
|
1174 aAutoSending = iRtpSessionArr[ret]->iRtpSession.RTCPAutoSend(); |
|
1175 return KErrNone; |
|
1176 } |
|
1177 else |
|
1178 { |
|
1179 return KErrNotSupported; |
|
1180 } |
|
1181 } |
|
1182 |
|
1183 /** |
|
1184 * Get the session ID of a stream, which belongs to that session. |
|
1185 */ |
|
1186 TRtpId CRtpManager::GetSessionId( TRtpId aStreamId ) |
|
1187 { |
|
1188 TInt ret = FindStream(aStreamId); |
|
1189 if(ret<0) |
|
1190 { |
|
1191 TInt idx = FindSession(aStreamId); |
|
1192 if(idx < 0) |
|
1193 { |
|
1194 return idx; |
|
1195 } |
|
1196 if(iRtpSessionArr[idx]->iRtpSendSource.IsOpen()) |
|
1197 { |
|
1198 return iRtpSessionArr[idx]->iKey; |
|
1199 } |
|
1200 return ret; |
|
1201 } |
|
1202 return iRtpStreamsArr[ret].iSessionKey; |
|
1203 } |
|
1204 |
|
1205 |
|
1206 /** |
|
1207 * Get address of Socket object used by a given RTP Session |
|
1208 * to send/receive RTP data packets. |
|
1209 */ |
|
1210 RSocket* CRtpManager::GetRtpSocket( TRtpId aSessionId ) |
|
1211 { |
|
1212 LOG_FUNC_ENTRY("CRtpManager::GetRtpSocket"); |
|
1213 __RTP_LOG1("aSessId %u",aSessionId) |
|
1214 |
|
1215 TInt ret = FindSession(aSessionId); |
|
1216 if( ret<0 ) |
|
1217 return NULL; |
|
1218 return iRtpSessionArr[ret]->iRtpSession.RtpSocket(); |
|
1219 } |
|
1220 |
|
1221 /** |
|
1222 * Get address of Socket object used by a given RTP Session |
|
1223 * to send/receive RTCP control packets. |
|
1224 */ |
|
1225 RSocket* CRtpManager::GetRtcpSocket( TRtpId aSessionId) |
|
1226 { |
|
1227 LOG_FUNC_ENTRY("CRtpManager::GetRtcpSocket"); |
|
1228 __RTP_LOG1("aSessId %u",aSessionId) |
|
1229 |
|
1230 TInt ret = FindSession(aSessionId); |
|
1231 if(ret<0 || !iRtpSessionArr[ret]->iRtcpEnabled) |
|
1232 return NULL; |
|
1233 return iRtpSessionArr[ret]->iRtpSession.RtcpSocket(); |
|
1234 } |
|
1235 |
|
1236 /** |
|
1237 * Retrieve statistical information for a stream |
|
1238 * based on the reports from RTCP SR & RR packets. |
|
1239 * @param aStreamId - [input] ID of stream |
|
1240 * @param aStat - [output] Statistical information |
|
1241 * @return KErrNone if successful; system wide error code otherwise |
|
1242 */ |
|
1243 TInt CRtpManager::GetStreamStatistics( TRtpId aStreamId, TRtpPeerStat& aStat ) |
|
1244 { |
|
1245 LOG_FUNC_ENTRY("CRtpManager::GetStreamStatistics"); |
|
1246 /* Find the session and the stream */ |
|
1247 TInt ret = FindStream(aStreamId); |
|
1248 if(ret<0) |
|
1249 { |
|
1250 return ret; |
|
1251 } |
|
1252 |
|
1253 RRtcpSRPart srPart = iRtpStreamsArr[ret].iRecvSource.GetSR(); |
|
1254 //Filling up the SR part first |
|
1255 aStat.iNumPacketsSent = srPart.PacketCount(); |
|
1256 aStat.iCumNumOctetsSent = srPart.ByteCount(); |
|
1257 aStat.iRoundTripDelay = 0; //TODO To be supported |
|
1258 aStat.iTxBandwidth = 0; //TODO find the use cases |
|
1259 |
|
1260 return KErrNone; |
|
1261 } |
|
1262 |
|
1263 /** |
|
1264 * Get sampling rate setting for a payload type. |
|
1265 */ |
|
1266 TUint32 CRtpManager::GetSamplingRate( TUint8 aPayloadType ) |
|
1267 { |
|
1268 LOG_FUNC_ENTRY("CRtpManager::GetSamplingRate"); |
|
1269 __RTP_LOG1("PayLoadType %d",aPayloadType); |
|
1270 /* Iterate through the sessions and return its sampling rate*/ |
|
1271 for(int i=0; i< iRtpSessionArr.Count(); i++) |
|
1272 { |
|
1273 __RTP_LOG1("iPayloadtype -->> :%d", iRtpSessionArr[i]->iPayloadType); |
|
1274 __RTP_LOG1("aPayloadtype -->> :%d", aPayloadType); |
|
1275 if(iRtpSessionArr[i]->iPayloadType == aPayloadType) |
|
1276 { |
|
1277 return iRtpSessionArr[i]->iSamplingRate; |
|
1278 } |
|
1279 } |
|
1280 //Not found |
|
1281 return 0; |
|
1282 } |
|
1283 |
|
1284 /** |
|
1285 * Set sampling rate for a payload type. |
|
1286 */ |
|
1287 TInt CRtpManager::SetSamplingRate( TUint8 aPayloadType, TUint32 aSamplingRate ) |
|
1288 { |
|
1289 LOG_FUNC_ENTRY("CRtpManager::SetSamplingRate"); |
|
1290 __RTP_LOG2("PayloadType %d SamplingRate %u",aPayloadType,aSamplingRate) |
|
1291 /* Iterate through the sessions and set its sampling rate*/ |
|
1292 for(int i=0; i< iRtpSessionArr.Count(); i++) |
|
1293 { |
|
1294 if(iRtpSessionArr[i]->iPayloadType == aPayloadType || KRtpPayloadTypeUnspecified == iRtpSessionArr[i]->iPayloadType) |
|
1295 { |
|
1296 iRtpSessionArr[i]->iPayloadType = aPayloadType; |
|
1297 iRtpSessionArr[i]->iSamplingRate = aSamplingRate; |
|
1298 iRtpSessionArr[i]->iRtpSession.SetRTPTimeConversion(0,aSamplingRate/1000); |
|
1299 } |
|
1300 /* Also update the Sampling rates so that received streams are properly handled */ |
|
1301 iRtpSessionArr[i]->iRtpSession.SetSamplingRate(aPayloadType,aSamplingRate); |
|
1302 } |
|
1303 return KErrNone; |
|
1304 } |
|
1305 |
|
1306 /** |
|
1307 * Set RTCP parameters for a given RTP Session. |
|
1308 * This function does nothing if RTCP was not enabled previously. |
|
1309 */ |
|
1310 TInt CRtpManager::SetRtcpParameters( TRtpId aSessionId, const TRtcpParams& aRtcpParams ) |
|
1311 { |
|
1312 TInt ret = FindSession(aSessionId); |
|
1313 if(ret<0) |
|
1314 return ret; |
|
1315 ASSERT(iRtpSessionArr[ret]->iRtcpEnabled); |
|
1316 iRtpSessionArr[ret]->iRtpSession.SetRtcpInterval(const_cast<TTimeIntervalMicroSeconds32&>(aRtcpParams.iRtcpTimeOut)); |
|
1317 iRtpSessionArr[ret]->iRtpSession.SetBandwidth(aRtcpParams.iSessionBWidth); |
|
1318 |
|
1319 return KErrNone; |
|
1320 } |
|
1321 |
|
1322 |
|
1323 /** |
|
1324 * Synchronous custom command interface for future extensions. |
|
1325 * Input/output data and return value are defined by each custom command |
|
1326 */ |
|
1327 TInt CRtpManager::CustomCommandSync( TInt , const TDesC8& , |
|
1328 const TDesC8& , TDes8& ) |
|
1329 { |
|
1330 /* Not Supported. But is it ok to Fail? */ |
|
1331 return KErrNotSupported; |
|
1332 } |
|
1333 |
|
1334 /** |
|
1335 * ASynchronous custom command interface for future extensions. |
|
1336 * Input/output data and return value are defined by each custom command |
|
1337 */ |
|
1338 TInt CRtpManager::CustomCommandAsync( TInt , const TDesC8& , const TDesC8& , |
|
1339 TDes8& ,TRequestStatus& ) |
|
1340 { |
|
1341 /* Not Supported. But is it ok to Fail? */ |
|
1342 return KErrNotSupported; |
|
1343 } |
|
1344 |
|
1345 |
|
1346 TInt CRtpManager::FindSession(TRtpId aSessionId) |
|
1347 { |
|
1348 /* A simple iteration to find the session */ |
|
1349 for(TInt i=0; i < iRtpSessionArr.Count(); i++) |
|
1350 { |
|
1351 if(iRtpSessionArr[i]->iKey == aSessionId) |
|
1352 { |
|
1353 return i; |
|
1354 } |
|
1355 } |
|
1356 __RTP_LOG("****FindSession Session Not Found!****") |
|
1357 return KErrNotFound; |
|
1358 } |
|
1359 |
|
1360 TInt CRtpManager::FindSessionL(TRtpId aSessionId) |
|
1361 { |
|
1362 TInt ret = FindSession(aSessionId); |
|
1363 User::LeaveIfError(ret); |
|
1364 return ret; |
|
1365 } |
|
1366 |
|
1367 TInt CRtpManager::FindStream(TRtpId aStreamId) |
|
1368 { |
|
1369 /* A simple iteration to find the session */ |
|
1370 for(TInt i=0; i < iRtpStreamsArr.Count(); i++) |
|
1371 { |
|
1372 if(iRtpStreamsArr[i].iKey == aStreamId) |
|
1373 { |
|
1374 return i; |
|
1375 } |
|
1376 } |
|
1377 __RTP_LOG("****FindStream Stream Not Found!****") |
|
1378 return KErrNotFound; |
|
1379 } |
|
1380 |
|
1381 TInt CRtpManager::FindStreamL(TRtpId aStreamId) |
|
1382 { |
|
1383 TInt ret = FindStream(aStreamId); |
|
1384 User::LeaveIfError(ret); |
|
1385 return ret; |
|
1386 } |
|
1387 |
|
1388 TInt CRtpManager::GetDefaultIapIdL() |
|
1389 { |
|
1390 LOG_FUNC_ENTRY("CRtpManager::GetDefaultIapIdL"); |
|
1391 TInt apId; |
|
1392 CCommsDatabase* db = CCommsDatabase::NewL(EDatabaseTypeIAP); |
|
1393 CleanupStack::PushL(db); |
|
1394 CCommsDbConnectionPrefTableView* view= db->OpenConnectionPrefTableInRankOrderLC(ECommDbConnectionDirectionOutgoing); |
|
1395 CCommsDbConnectionPrefTableView::TCommDbIapConnectionPref Pref; |
|
1396 view->GotoFirstRecord(); |
|
1397 view->ReadConnectionPreferenceL(Pref); |
|
1398 apId = Pref.iBearer.iIapId; |
|
1399 CleanupStack::PopAndDestroy(2); |
|
1400 __RTP_LOG1("IapId %d",apId) |
|
1401 LOG_FUNC_EXIT("CRtpManager::GetDefaultIapIdL"); |
|
1402 return apId; |
|
1403 } |
|
1404 |
|
1405 /* Schedules RTP transmission from the Head of the pending queue |
|
1406 */ |
|
1407 TInt CRtpManager::SendRtpDataFromPendingQueue(CRtpSessionInfo *aSessInfo) |
|
1408 { |
|
1409 ASSERT(!aSessInfo->iPendingReqQue->IsEmpty()); |
|
1410 TRtpSendReqNode *reqNode = aSessInfo->iPendingReqQue->Last(); |
|
1411 reqNode->iPktToSend.Send(); |
|
1412 return KErrNone; |
|
1413 } |
|
1414 |
|
1415 void CRtpManager::RegisterEventsOnSessionL(CRtpSessionInfo *aSessionInfo) |
|
1416 { |
|
1417 RRtpSession session = aSessionInfo->iRtpSession; |
|
1418 |
|
1419 session.RegisterEventCallbackL(ERtpSessionFail, |
|
1420 RtpSessionLevelCB, |
|
1421 aSessionInfo, |
|
1422 ERtpNotOneShot); |
|
1423 |
|
1424 session.RegisterEventCallbackL(ERtpNewSource, |
|
1425 RtpSessionLevelCB, |
|
1426 aSessionInfo, |
|
1427 ERtpNotOneShot); |
|
1428 |
|
1429 session.RegisterEventCallbackL(ERtpNewRR, |
|
1430 RtpSessionLevelCB, |
|
1431 aSessionInfo, |
|
1432 ERtpNotOneShot); |
|
1433 |
|
1434 session.RegisterEventCallbackL(ERtpBufferOverflow, |
|
1435 RtpSessionLevelCB, |
|
1436 aSessionInfo, |
|
1437 ERtpNotOneShot); |
|
1438 |
|
1439 session.RegisterEventCallbackL(ERtpUndersizedPacket, |
|
1440 RtpSessionLevelCB, |
|
1441 aSessionInfo, |
|
1442 ERtpNotOneShot); |
|
1443 } |
|
1444 |
|
1445 |
|
1446 void CRtpManager::RegisterEventsOnRtpRcvSourceL(RRtpReceiveSource &aRcvSrc, TRtpStreamInfo *apStrmInfo) |
|
1447 { |
|
1448 aRcvSrc.RegisterEventCallbackL(ERtpPacketReceived, |
|
1449 CRtpManager::RtpStreamLevelCB, |
|
1450 apStrmInfo, |
|
1451 ERtpNotOneShot); |
|
1452 |
|
1453 aRcvSrc.RegisterEventCallbackL(ERtpSourceFail, |
|
1454 CRtpManager::RtpStreamLevelCB, |
|
1455 apStrmInfo, |
|
1456 ERtpNotOneShot); |
|
1457 |
|
1458 aRcvSrc.RegisterEventCallbackL(ERtpAPP, |
|
1459 CRtpManager::RtpStreamLevelCB, |
|
1460 apStrmInfo, |
|
1461 ERtpNotOneShot); |
|
1462 |
|
1463 |
|
1464 aRcvSrc.RegisterEventCallbackL(ERtpBYE, |
|
1465 CRtpManager::RtpStreamLevelCB, |
|
1466 apStrmInfo, |
|
1467 ERtpNotOneShot); |
|
1468 |
|
1469 aRcvSrc.RegisterEventCallbackL(ERtpSR, |
|
1470 CRtpManager::RtpStreamLevelCB, |
|
1471 apStrmInfo, |
|
1472 ERtpNotOneShot); |
|
1473 |
|
1474 aRcvSrc.RegisterEventCallbackL(ERtpRR, |
|
1475 CRtpManager::RtpStreamLevelCB, |
|
1476 apStrmInfo, |
|
1477 ERtpNotOneShot); |
|
1478 |
|
1479 aRcvSrc.RegisterEventCallbackL(ERtpSDES, |
|
1480 CRtpManager::RtpStreamLevelCB, |
|
1481 apStrmInfo, |
|
1482 ERtpNotOneShot); |
|
1483 } |
|
1484 |
|
1485 void CRtpManager::HandleNonRtpDataL(CRtpSessionInfo *apSessionInfo) |
|
1486 { |
|
1487 apSessionInfo->iNonRtpDataObserver->NonRTPDataReceived(apSessionInfo->iPortNumber, |
|
1488 ETrue, |
|
1489 apSessionInfo->iRtpSession.NonRtpDataL()); |
|
1490 apSessionInfo->iRtpSession.RegisterEventCallbackL(ENonRtpDataReceived, |
|
1491 RtpSessionLevelCB, |
|
1492 apSessionInfo, |
|
1493 ERtpOneShot); |
|
1494 } |
|
1495 |
|
1496 void CRtpManager::HandleNonRtcpDataL(CRtpSessionInfo *apSessionInfo) |
|
1497 { |
|
1498 apSessionInfo->iNonRtpDataObserver->NonRTPDataReceived(apSessionInfo->iPortNumber+1, |
|
1499 EFalse, |
|
1500 apSessionInfo->iRtpSession.NonRtcpDataL()); |
|
1501 apSessionInfo->iRtpSession.RegisterEventCallbackL(ENonRtcpDataReceived, |
|
1502 RtpSessionLevelCB, |
|
1503 apSessionInfo, |
|
1504 ERtpOneShot); |
|
1505 } |
|
1506 |
|
1507 void CRtpManager::RtpSessionLevelCB(CRtpSessionInfo* apSessionInfo, const TRtpEvent& aEvent) |
|
1508 { |
|
1509 LOG_FUNC_ENTRY("CRtpManager::RtpSessionLevelCB"); |
|
1510 __RTP_LOG1("EventType %x",aEvent.Type()) |
|
1511 CRtpManager *pSelf = apSessionInfo->iRtpManager; |
|
1512 |
|
1513 /* Event Send succeded or Failed */ |
|
1514 if(ERtpSendSucceeded == aEvent.Type() || ERtpSendFail == aEvent.Type()) |
|
1515 { |
|
1516 /* We are here only if Async Send was initiated */ |
|
1517 TInt retCode = (aEvent.Type()==ERtpSendFail)?aEvent.Status():KErrNone; |
|
1518 |
|
1519 /* An Async send is Complete. Notify the Application and schedule for next |
|
1520 * transmission if send queue is not empty */ |
|
1521 ASSERT(!apSessionInfo->iPendingReqQue->IsEmpty()); |
|
1522 TRtpSendReqNode *reqNode = apSessionInfo->iPendingReqQue->First(); |
|
1523 reqNode->iPktToSend.Close(); |
|
1524 |
|
1525 __RTP_LOG("Complete Async Request") |
|
1526 /* Complete the Async Request */ |
|
1527 User::RequestComplete(reqNode->iStatus,retCode); |
|
1528 apSessionInfo->iPendingReqQue->Remove(*reqNode); |
|
1529 delete reqNode; |
|
1530 |
|
1531 if(!apSessionInfo->iPendingReqQue->IsEmpty()) |
|
1532 { |
|
1533 //OK to ignore Send Errors ? |
|
1534 apSessionInfo->iRtpManager->SendRtpDataFromPendingQueue(apSessionInfo); |
|
1535 } |
|
1536 } |
|
1537 /* A new source was detected */ |
|
1538 if(ERtpNewSource == aEvent.Type()) |
|
1539 { |
|
1540 /* Create a ReceiveSource for this stream. */ |
|
1541 RRtpReceiveSource rtpRcvSrc; |
|
1542 TRAPD(err, rtpRcvSrc = apSessionInfo->iRtpSession.NewReceiveSourceL()); |
|
1543 if(err) |
|
1544 { |
|
1545 __RTP_LOG1("Receive source could not be created %d Returning", err) |
|
1546 return; |
|
1547 } |
|
1548 |
|
1549 /* See if there is a Pre-Created stream that will accept this PayloadType. |
|
1550 If there are no Pre Created stream that accepts this PayloadType just |
|
1551 Blindly latch on to the First PreCreated Stream. This behaviour is not |
|
1552 really correct but is inline with the S60 RTP Stack behaviour. */ |
|
1553 TUint32 strmKey = 0; |
|
1554 TInt tmpIdx = -1; //Used to remember the last index of a eStreamPreCreated stream |
|
1555 |
|
1556 TUint payloadType = 0; |
|
1557 TRAP(err, payloadType=rtpRcvSrc.PayLoadTypeL()); |
|
1558 if(err == KErrNotFound) |
|
1559 { |
|
1560 __RTP_LOG1("Payload type was not found", err) |
|
1561 } |
|
1562 |
|
1563 __RTP_LOG1("PayloadType %d",payloadType) |
|
1564 |
|
1565 for(int i=0; i<pSelf->iRtpStreamsArr.Count();i++) |
|
1566 { |
|
1567 if(pSelf->iRtpStreamsArr[i].iState == TRtpStreamInfo::eStreamPreCreated) |
|
1568 { |
|
1569 /* To make later access easier */ |
|
1570 tmpIdx = i; |
|
1571 } |
|
1572 |
|
1573 /* Try to match the Payload type first */ |
|
1574 if(pSelf->iRtpStreamsArr[i].iPayloadType == payloadType |
|
1575 && pSelf->iRtpStreamsArr[i].iState == TRtpStreamInfo::eStreamPreCreated) |
|
1576 { |
|
1577 __RTP_LOG1("Found PreCreated Stream at %d",i); |
|
1578 /* Ok so there is a PreCreated stream available */ |
|
1579 pSelf->iRtpStreamsArr[i].iIsRecvStream = ETrue; |
|
1580 pSelf->iRtpStreamsArr[i].iRecvSource = rtpRcvSrc; |
|
1581 pSelf->iRtpStreamsArr[i].iState = TRtpStreamInfo::eStreamReadyToUse; |
|
1582 strmKey = pSelf->iRtpStreamsArr[i].iKey; |
|
1583 break; |
|
1584 } |
|
1585 } |
|
1586 |
|
1587 if(!strmKey && tmpIdx>=0) |
|
1588 { |
|
1589 __RTP_LOG1("No PreCreated Stream : Using ID %d",tmpIdx) |
|
1590 /* Latch on to the unspecified stream */ |
|
1591 pSelf->iRtpStreamsArr[tmpIdx].iIsRecvStream = ETrue; |
|
1592 pSelf->iRtpStreamsArr[tmpIdx].iRecvSource = rtpRcvSrc; |
|
1593 pSelf->iRtpStreamsArr[tmpIdx].iState = TRtpStreamInfo::eStreamReadyToUse; |
|
1594 strmKey = pSelf->iRtpStreamsArr[tmpIdx].iKey; |
|
1595 /* Because we ignored the original user selection */ |
|
1596 pSelf->iRtpStreamsArr[tmpIdx].iPayloadType = payloadType; |
|
1597 } |
|
1598 |
|
1599 if(!strmKey) |
|
1600 { |
|
1601 __RTP_LOG("No PreCreated Stream : Creating a New Stream") |
|
1602 /* Create a new stream */ |
|
1603 TRtpStreamInfo strmInfo; |
|
1604 strmInfo.iKey = Math::Random(); |
|
1605 strmInfo.iSessionKey = apSessionInfo->iKey; |
|
1606 strmInfo.iState = TRtpStreamInfo::eStreamPostCreated; |
|
1607 strmInfo.iRecvSource = rtpRcvSrc; |
|
1608 TRAPD(error, strmInfo.iPayloadType = rtpRcvSrc.PayLoadTypeL()); |
|
1609 if(error == KErrNotFound) |
|
1610 { |
|
1611 __RTP_LOG1("Payload type was not found", error) |
|
1612 } |
|
1613 strmInfo.iRtpManager = pSelf; |
|
1614 /* Append to the Array */ |
|
1615 pSelf->iRtpStreamsArr.Append(strmInfo); //TODO handle append failures |
|
1616 strmKey = strmInfo.iKey; |
|
1617 __RTP_LOG1("Session Did not have a PreCreated Stream New StreamID %u",strmInfo.iKey) |
|
1618 } |
|
1619 /* Get a reference to the Strm from Array for Callback Registration */ |
|
1620 TInt idx = pSelf->FindStream(strmKey); |
|
1621 |
|
1622 TRAP_IGNORE(pSelf->RegisterEventsOnRtpRcvSourceL(rtpRcvSrc, &(pSelf->iRtpStreamsArr[idx]))); |
|
1623 } |
|
1624 if(ERtpNewRR == aEvent.Type()) |
|
1625 { |
|
1626 /* Session Level RTCP RR . An Empty RR was received */ |
|
1627 if(apSessionInfo->iRtcpObserver) |
|
1628 { |
|
1629 apSessionInfo->iRtcpObserver->RrReceived(apSessionInfo->iKey,aEvent.Status()); |
|
1630 } |
|
1631 } |
|
1632 |
|
1633 if(ENonRtpDataReceived == aEvent.Type()) |
|
1634 { |
|
1635 /* Session Level CB. A non rtp data was received */ |
|
1636 if(apSessionInfo->iNonRtpDataObserver) |
|
1637 { |
|
1638 TRAP_IGNORE(pSelf->HandleNonRtpDataL(apSessionInfo)); |
|
1639 } |
|
1640 } |
|
1641 if(ENonRtcpDataReceived == aEvent.Type()) |
|
1642 { |
|
1643 /* Session Level CB. A non rtp data was received */ |
|
1644 if(apSessionInfo->iNonRtpDataObserver) |
|
1645 { |
|
1646 __RTP_LOG("CRtpManager::RtpSessionLevelCB"); |
|
1647 __RTP_LOG("Non rtcp data - issuing non rtp data received callback"); |
|
1648 TRAP_IGNORE(pSelf->HandleNonRtcpDataL(apSessionInfo)); |
|
1649 } |
|
1650 } |
|
1651 } |
|
1652 |
|
1653 void CRtpManager::RtpStreamLevelCB(TRtpStreamInfo* apStrmInfo, const TRtpEvent& aEvent) |
|
1654 { |
|
1655 LOG_FUNC_ENTRY("CRtpManager::RtpStreamLevelCB"); |
|
1656 __RTP_LOG1("EventType %x",aEvent.Type()) |
|
1657 |
|
1658 TInt ret; |
|
1659 if(ERtpPacketReceived == aEvent.Type()) |
|
1660 { |
|
1661 /* New Packet Arrived. Issue callback */ |
|
1662 TRtpRecvHeader rcvHeader; |
|
1663 RRtpReceivePacket pkt = apStrmInfo->iRecvSource.Packet(); |
|
1664 rcvHeader.iMarker = pkt.Marker(); |
|
1665 rcvHeader.iPadding = 0; //TODO Pading bits are stripped by Stack? Verify |
|
1666 rcvHeader.iPayloadType = pkt.PayloadType(); |
|
1667 rcvHeader.iSeqNum = pkt.SequenceNumber(); |
|
1668 rcvHeader.iTimestamp = pkt.Timestamp(); |
|
1669 |
|
1670 ret = apStrmInfo->iRtpManager->FindSession(apStrmInfo->iSessionKey); |
|
1671 ASSERT(ret>=0); |
|
1672 if(apStrmInfo->iRtpManager->iRtpSessionArr[ret]->iRtpObserver) |
|
1673 { |
|
1674 __RTP_LOG("Issuing RtpReceived callback") |
|
1675 apStrmInfo->iRtpManager->iRtpSessionArr[ret]->iRtpObserver->RtpPacketReceived(apStrmInfo->iKey,rcvHeader,pkt.Payload()); |
|
1676 } |
|
1677 else |
|
1678 { |
|
1679 __RTP_LOG("Session Did not have RTP Observer Registered") |
|
1680 } |
|
1681 pkt.Close(); |
|
1682 } |
|
1683 if(ERtpRR == aEvent.Type()) |
|
1684 { |
|
1685 /* Fetch the information on the RR Received from specif SSRC */ |
|
1686 ret = apStrmInfo->iRtpManager->FindSession(apStrmInfo->iSessionKey); |
|
1687 ASSERT(ret>=0); |
|
1688 if(apStrmInfo->iRtpManager->iRtpSessionArr[ret]->iRtcpObserver) |
|
1689 { |
|
1690 __RTP_LOG("Issuing RtcpRrReceived callback") |
|
1691 apStrmInfo->iRtpManager->iRtpSessionArr[ret]->iRtcpObserver->RrReceived(apStrmInfo->iKey, aEvent.Status()); |
|
1692 } |
|
1693 else |
|
1694 { |
|
1695 __RTP_LOG("Session Did not have RCTP Observer Reqistered") |
|
1696 } |
|
1697 } |
|
1698 if(ERtpSDES == aEvent.Type()) |
|
1699 { |
|
1700 /* Fetch the information on the SDES Received from specif SSRC */ |
|
1701 ret = apStrmInfo->iRtpManager->FindSession(apStrmInfo->iSessionKey); |
|
1702 ASSERT(ret>=0); |
|
1703 if(apStrmInfo->iRtpManager->iRtpSessionArr[ret]->iRtcpObserver) |
|
1704 { |
|
1705 TBuf8<100> cname; |
|
1706 TBuf8<100> name; |
|
1707 TBuf8<100> email; |
|
1708 |
|
1709 /* Extract the SDES information and pass it up */ |
|
1710 TRtpSdesParams sdesParams; |
|
1711 if(KErrNotFound != apStrmInfo->iRecvSource.GetSDES(1,cname)) |
|
1712 { |
|
1713 sdesParams.iCName.Set(cname); |
|
1714 } |
|
1715 if(KErrNotFound != apStrmInfo->iRecvSource.GetSDES(2,name)) |
|
1716 { |
|
1717 sdesParams.iUserName.Set(name); |
|
1718 } |
|
1719 if(KErrNotFound != apStrmInfo->iRecvSource.GetSDES(3,email)) |
|
1720 { |
|
1721 sdesParams.iEmail.Set(name); |
|
1722 } |
|
1723 __RTP_LOG("Issuing SdesReceived callback") |
|
1724 apStrmInfo->iRtpManager->iRtpSessionArr[ret]->iRtcpObserver->SdesReceived(aEvent.Status(),sdesParams); |
|
1725 } |
|
1726 else |
|
1727 { |
|
1728 __RTP_LOG("RTCP Observer was not registered. Callback not issued") |
|
1729 } |
|
1730 } |
|
1731 if(ERtpSR == aEvent.Type()) |
|
1732 { |
|
1733 /* Fetch the information on the SR Received from specific SSRC */ |
|
1734 ret = apStrmInfo->iRtpManager->FindSession(apStrmInfo->iSessionKey); |
|
1735 ASSERT(ret>=0); |
|
1736 if(apStrmInfo->iRtpManager->iRtpSessionArr[ret]->iRtcpObserver) |
|
1737 { |
|
1738 RRtcpSRPart srPart(apStrmInfo->iRecvSource.GetSR()); |
|
1739 |
|
1740 TTimeStamps timeStamps; |
|
1741 srPart.NTPTimestamp(timeStamps.iNTPTimeStampSec, timeStamps.iNTPTimeStampFrac); |
|
1742 timeStamps.iTimeStamp = srPart.RTPTimestamp(); |
|
1743 |
|
1744 __RTP_LOG("Issuing SrReceived callback") |
|
1745 apStrmInfo->iRtpManager->iRtpSessionArr[ret]->iRtcpObserver->SrReceived(apStrmInfo->iKey, apStrmInfo->iRecvSource.SSRC(), timeStamps); |
|
1746 } |
|
1747 else |
|
1748 { |
|
1749 __RTP_LOG("RTCP Observer was not registered. Callback not issued") |
|
1750 } |
|
1751 } |
|
1752 if(ERtpAPP == aEvent.Type()) |
|
1753 { |
|
1754 /* Fetch the information on the RR Received from specif SSRC */ |
|
1755 ret = apStrmInfo->iRtpManager->FindSession(apStrmInfo->iSessionKey); |
|
1756 ASSERT(ret>=0); |
|
1757 if(apStrmInfo->iRtpManager->iRtpSessionArr[ret]->iRtcpObserver) |
|
1758 { |
|
1759 TRtcpApp app; |
|
1760 TPtrC8 name; |
|
1761 TPtrC8 appData; |
|
1762 TUint subType; |
|
1763 |
|
1764 apStrmInfo->iRecvSource.GetLastApp(name, appData, subType ); |
|
1765 |
|
1766 //Create Tpr8 from TRtcpApp ..Duh!! |
|
1767 TPtr8 name1(app.iName,4); |
|
1768 TPtr8 appData1(app.iAppData,KMaxRtcpAppData); |
|
1769 name1 = name; |
|
1770 appData1 = appData; |
|
1771 app.iAppDataLen = appData.Length(); |
|
1772 app.iSubType = subType; |
|
1773 |
|
1774 __RTP_LOG("Issuing SrReceived callback") |
|
1775 apStrmInfo->iRtpManager->iRtpSessionArr[ret]->iRtcpObserver->AppReceived(apStrmInfo->iKey, aEvent.Status(),app ); |
|
1776 } |
|
1777 else |
|
1778 { |
|
1779 __RTP_LOG("RTCP Observer was not registered. Callback not issued") |
|
1780 } |
|
1781 } |
|
1782 } |
|
1783 |
|
1784 |
|
1785 // Decrypting RTP Packet recieved from network |
|
1786 TInt CRtpSessionInfo::PreRtpProcessing(TDes8 &aRTPPacket) |
|
1787 { |
|
1788 __RTP_LOG("CRtpSessionInfo::PreRtpProcessing") |
|
1789 //SSRC of recieved packet KRtpSSRCOffset (8) |
|
1790 const TUint KRtpSSRCOffset = 8; |
|
1791 HBufC8 *rtpPacket = NULL; |
|
1792 TUint8* packet = const_cast<TUint8*>(aRTPPacket.Ptr()); |
|
1793 TUint32 ssrc = (*(packet+KRtpSSRCOffset+3))+ |
|
1794 (*(packet+KRtpSSRCOffset+2)<<8)+ |
|
1795 (*(packet+KRtpSSRCOffset+1)<<16)+ |
|
1796 (*(packet+KRtpSSRCOffset)<<24); |
|
1797 |
|
1798 TRAPD(error, rtpPacket = iSRTPSession->UnprotectRTPL(ssrc, aRTPPacket)); |
|
1799 if(error == KErrNone) |
|
1800 { |
|
1801 __RTP_LOG("RTP Packet Decrypted sucessfully") |
|
1802 aRTPPacket.Copy(rtpPacket->Des()); |
|
1803 } |
|
1804 else |
|
1805 { |
|
1806 __RTP_LOG("RTP Packet Decrypted Failed") |
|
1807 error = KErrCorrupt; |
|
1808 } |
|
1809 delete rtpPacket; |
|
1810 return error; |
|
1811 } |
|
1812 |
|
1813 // Encrypting RTP packet before sending |
|
1814 void CRtpSessionInfo::PostRtpProcessing(TDes8 &aRTPPacket) |
|
1815 { |
|
1816 __RTP_LOG("CRtpSessionInfo::PostRtpProcessing") |
|
1817 //SSRC of recieved packet KRtpSSRCOffset (8) |
|
1818 const TUint KRtpSSRCOffset = 8; |
|
1819 HBufC8 *rtpPacket = NULL; |
|
1820 TUint8* packet = const_cast<TUint8*>(aRTPPacket.Ptr()); |
|
1821 TUint32 ssrc = (*(packet+KRtpSSRCOffset+3))+ |
|
1822 (*(packet+KRtpSSRCOffset+2)<<8)+ |
|
1823 (*(packet+KRtpSSRCOffset+1)<<16)+ |
|
1824 (*(packet+KRtpSSRCOffset)<<24); |
|
1825 |
|
1826 TRAPD(error, rtpPacket = iSRTPSession->ProtectRTPL(ssrc, aRTPPacket)); |
|
1827 if(error != KErrNone) |
|
1828 { |
|
1829 __RTP_LOG("RTP Packet was not encrypted") |
|
1830 aRTPPacket.FillZ(); |
|
1831 } |
|
1832 else |
|
1833 { |
|
1834 __RTP_LOG("RTP Packet was encrypted successfully") |
|
1835 aRTPPacket.Copy(rtpPacket->Des()); |
|
1836 delete rtpPacket; |
|
1837 } |
|
1838 } |
|
1839 |
|
1840 // DeCrypting RTCP Packet recieved from network |
|
1841 TInt CRtpSessionInfo::PreRtcpProcessing(TDes8 &aRTCPPacket) |
|
1842 { |
|
1843 __RTP_LOG("CRtpSessionInfo::PreRtcpProcessing") |
|
1844 //SSRC of recieved packet KRtcpSSRCOffset (4) |
|
1845 const TUint KRtcpSSRCOffset = 4; |
|
1846 HBufC8 *rtcpPacket = NULL; |
|
1847 TUint8* packet = const_cast<TUint8*>(aRTCPPacket.Ptr()); |
|
1848 TUint32 ssrc = (*(packet+KRtcpSSRCOffset+3))+ |
|
1849 (*(packet+KRtcpSSRCOffset+2)<<8)+ |
|
1850 (*(packet+KRtcpSSRCOffset+1)<<16)+ |
|
1851 (*(packet+KRtcpSSRCOffset)<<24); |
|
1852 |
|
1853 TRAPD(error, rtcpPacket = iSRTPSession->UnprotectRTCPL(ssrc, aRTCPPacket)); |
|
1854 if(error == KErrNone) |
|
1855 { |
|
1856 __RTP_LOG("RTCP Packet Decrypted sucessfully") |
|
1857 aRTCPPacket.Copy(rtcpPacket->Des()); |
|
1858 } |
|
1859 else |
|
1860 { |
|
1861 __RTP_LOG("RTCP Packet Decrypted Failed") |
|
1862 error = KErrCorrupt; |
|
1863 } |
|
1864 delete rtcpPacket; |
|
1865 return error; |
|
1866 } |
|
1867 |
|
1868 // Encrypting RTCP Packet before sending |
|
1869 void CRtpSessionInfo::PostRtcpProcessing(TDes8 &aRTCPPacket) |
|
1870 { |
|
1871 __RTP_LOG("CRtpSessionInfo::PostRtcpProcessing") |
|
1872 //SSRC of recieved packet KRtcpSSRCOffset (4) |
|
1873 const TUint KRtcpSSRCOffset = 4; |
|
1874 HBufC8 *rtcpPacket = NULL; |
|
1875 // Assign a pointer to a packet |
|
1876 TUint8* packet = const_cast<TUint8*>(aRTCPPacket.Ptr()); |
|
1877 TUint32 ssrc = (*(packet+KRtcpSSRCOffset+3))+ |
|
1878 (*(packet+KRtcpSSRCOffset+2)<<8)+ |
|
1879 (*(packet+KRtcpSSRCOffset+1)<<16)+ |
|
1880 (*(packet+KRtcpSSRCOffset)<<24); |
|
1881 |
|
1882 TRAPD(error, rtcpPacket = iSRTPSession->ProtectRTCPL(ssrc, aRTCPPacket)); |
|
1883 if(error != KErrNone) |
|
1884 { |
|
1885 __RTP_LOG("RCTP Packet was not encrypted") |
|
1886 aRTCPPacket.FillZ(); |
|
1887 } |
|
1888 else |
|
1889 { |
|
1890 __RTP_LOG("RCTP Packet was encrypted Successfully") |
|
1891 aRTCPPacket.Copy(rtcpPacket->Des()); |
|
1892 delete rtcpPacket; |
|
1893 } |
|
1894 } |
|
1895 |