--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommscontroller/mmccrtpwrapper/src/rtp_wrapper.cpp Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,1895 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// class for the rtpwrapper unit test cases
+//
+//
+
+/**
+ @file
+*/
+
+#include <e32math.h>
+#include <commdbconnpref.h>
+#include <rtp.h>
+#include <rtcp.h>
+#include <COMMDB.H>
+#include <srtpsession.h>
+#include "rtpheader.h"
+#include "rtpmanager.h"
+
+TInt RtpSessionLinearOrderFunc(const CRtpSessionInfo& aNew, const CRtpSessionInfo &aArrElem)
+ {
+ return aNew.iPortNumber - aArrElem.iPortNumber;
+ }
+
+CRtpSessionInfo* CRtpSessionInfo::NewL()
+ {
+ LOG_FUNC_ENTRY("CRtpSessionInfo::NewL");
+ CRtpSessionInfo *self = new(ELeave) CRtpSessionInfo();
+
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+
+ LOG_FUNC_EXIT("CRtpSessionInfo::NewL");
+ return self;
+ }
+
+void CRtpSessionInfo::ConstructL()
+ {
+ LOG_FUNC_ENTRY("CRtpSessionInfo::ConstructL");
+ }
+
+/* Creates a CrtpManager object */
+CRtpManager* CRtpManager::NewL(MRtpErrNotify& aErrNotify )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::NewL");
+ CRtpManager *self = new(ELeave) CRtpManager();
+
+ CleanupStack::PushL(self);
+ self->ConstructL(aErrNotify);
+ CleanupStack::Pop();
+
+ LOG_FUNC_EXIT("CRtpManager::NewL");
+ return self;
+ }
+
+CRtpManager::CRtpManager( )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::CRtpManager");
+ iOwnsConnection = EFalse;
+ iOwnsSocketServer = EFalse;
+ LOG_FUNC_EXIT("CRtpManager::CRtpManager");
+ }
+
+CRtpManager::~CRtpManager( )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::~CRtpManager");
+
+ Close();
+
+ /* Clean up the Arrays */
+ iRtpSessionArr.Close();
+ iRtpStreamsArr.Close();
+
+ if(iOwnsConnection)
+ delete iConnection;
+ if(iOwnsSocketServer)
+ delete iSocketServ;
+
+ LOG_FUNC_EXIT("CRtpManager::~CRtpManager");
+ }
+
+void CRtpManager::ConstructL(MRtpErrNotify& aErrNotify )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::ConstructL");
+ iRtpErrNotify = &aErrNotify;
+ LOG_FUNC_EXIT("CRtpManager::ConstructL");
+ }
+
+
+TInt CRtpManager::OpenL( const TRtpSdesParams& aSdesInfo, const TDesC* aRtpPacketDll,
+ const RSocketServ* aSocketServPtr, const RConnection* aConnPtr )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::OpenL");
+ /* The current implementation do not support having a different
+ * aRtpPacketDll
+ * So the argument is ignored */
+ (void)aRtpPacketDll;
+
+ if(aSocketServPtr)
+ {
+ iSocketServ = const_cast<RSocketServ*>(aSocketServPtr);
+ }
+ else
+ {
+ iSocketServ = new(ELeave) RSocketServ();
+ iOwnsSocketServer = ETrue;
+ }
+
+ if(aConnPtr)
+ {
+ iConnection = const_cast<RConnection*>(aConnPtr);
+ }
+ else
+ {
+ iConnection = new(ELeave) RConnection();
+ iOwnsConnection = ETrue;
+ }
+
+ iSdesInfo = aSdesInfo;
+
+ User::LeaveIfError(iSocketServ->Connect());
+
+ User::LeaveIfError(iConnection->Open(*iSocketServ));
+
+ LOG_FUNC_EXIT("CRtpManager::OpenL");
+ return KErrNone;
+ }
+
+
+ /**
+ * Open and initialize the CRtpAPI object.
+ * @param aIapId - [input] IAP ID. If -1, no IAP selection dialog
+ * will pop up. Instead, the default IAP will be used.
+ * @return KErrNone if successful; system wide error code otherwise
+ */
+TInt CRtpManager::StartConnection( TInt aIapId )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::StartConnection");
+ __RTP_LOG1("IapId = %d",aIapId)
+ if(aIapId != -1)
+ {
+ TCommDbConnPref prefs;
+ prefs.SetDialogPreference(ECommDbDialogPrefDoNotPrompt);
+ prefs.SetDirection(ECommDbConnectionDirectionOutgoing);
+ prefs.SetIapId(aIapId);
+ iIapId = aIapId;
+ return iConnection->Start(prefs);
+ }
+ else
+ {
+ TRAPD(err,iIapId = GetDefaultIapIdL());
+ if(KErrNone != err)
+ {
+ __RTP_LOG1("GetDefaultIapIdL returned %d",err)
+ return err;
+ }
+ __RTP_LOG1("GetDefaultIapIdL default Iap: %d",iIapId)
+ LOG_FUNC_EXIT("CRtpManager::StartConnection");
+ return iConnection->Start();
+ }
+ }
+
+TInt CRtpManager::StartConnection( TRequestStatus& aStatus, TInt aIapId)
+ {
+ LOG_FUNC_ENTRY("CRtpManager::StartConnection-Async");
+ __RTP_LOG1("aIapId = %d",aIapId);
+
+ TCommDbConnPref prefs;
+ prefs.SetDialogPreference(ECommDbDialogPrefDoNotPrompt);
+ prefs.SetDirection(ECommDbConnectionDirectionOutgoing);
+
+ if(aIapId != -1)
+ {
+ prefs.SetIapId(aIapId);
+ iConnection->Start(prefs, aStatus);
+ iIapId = aIapId;
+ }
+ else
+ {
+ TRAPD(err,iIapId = GetDefaultIapIdL());
+ if(KErrNone != err)
+ {
+ __RTP_LOG1("GetDefaultIapIdL returned %d",err)
+ return err;
+ }
+ __RTP_LOG1("GetDefaultIapIdL default Iap: %d",iIapId)
+ prefs.SetIapId(iIapId);
+ iConnection->Start(prefs, aStatus);
+ }
+ LOG_FUNC_EXIT("CRtpManager::StartConnection-Async");
+ return KErrNone;
+ }
+
+
+/**
+* Cancels asynchoronous start of connection.
+* Any open requests will be completed with KErrCancel.
+* @return None
+*/
+void CRtpManager::CancelStart()
+ {
+ LOG_FUNC_ENTRY("CRtpManager::CancelStart");
+ return;
+ }
+
+
+void CRtpManager::Close()
+ {
+ LOG_FUNC_ENTRY("CRtpManager::Close");
+ /* Iterate through the session array and close */
+ for(int i=0; i < iRtpSessionArr.Count(); i++)
+ {
+ __RTP_LOG1("Closing Session Key %u",iRtpSessionArr[i]->iKey);
+ iRtpSessionArr[i]->iRtpSession.Close();
+ ASSERT(iRtpSessionArr[i]->iPendingReqQue->IsEmpty());
+ delete iRtpSessionArr[i]->iPendingReqQue;
+ iRtpSessionArr[i]->iPendingReqQue = NULL;
+ }
+ if(iConnection)
+ iConnection->Close();
+
+ if(iSocketServ)
+ iSocketServ->Close();
+
+ LOG_FUNC_EXIT("CRtpManager::Close");
+ }
+
+/**
+* Set SDES (Source Description) information of the local participant.
+* Participant is defined as an application program and
+* only one local participant is allowed.
+*/
+ void CRtpManager::SetLocalSdes( const TRtpSdesParams& aSDES)
+ {
+ /* Should the SDES list be updated again here ? */
+ LOG_FUNC_ENTRY("CRtpManager::SetLocalSdes");
+ iSdesInfo = aSDES;
+ }
+
+/**
+* Get the local IP address
+* @param None
+* @return local ip address.
+*/
+ TInetAddr& CRtpManager::GetLocalIPAddressL()
+ {
+ LOG_FUNC_ENTRY("CRtpManager::GetLocalIPAddressL");
+ /* Open an RSocket and find its address */
+ RSocket socket;
+ User::LeaveIfError(socket.Open(*iSocketServ, KAfInet, KSockDatagram, KProtocolInetUdp,*iConnection));
+
+ CleanupClosePushL(socket);
+
+ TSoInetInterfaceInfo networkInfo;
+ TPckg<TSoInetInterfaceInfo> opt(networkInfo);
+ User::LeaveIfError(socket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl));
+ TSoInetIfQuery query;
+ TPckg<TSoInetIfQuery> queryBuf(query);
+ TInt res = KErrNone;
+ do
+ {
+ res = socket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, opt);
+ if (!res && opt().iState == EIfUp)
+ {
+ query.iName = opt().iName;
+ res = socket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, queryBuf);
+ if (!res && query.iZone[1] == iIapId)
+ {
+ networkInfo = opt();
+ break;
+ }
+ }
+ }
+ while (res == KErrNone);
+ if(res!= KErrNone)
+ {
+ __RTP_LOG1("Found nothing! ret %d",res)
+ /* Didn't find :( */
+ User::Leave(res);
+ }
+ CleanupStack::PopAndDestroy(1);
+ iSockAddr = networkInfo.iAddress;
+ LOG_FUNC_EXIT("CRtpManager::GetLocalIPAddressL");
+ return iSockAddr;
+ }
+ /**
+ * Makes a CName that is unique for a given seesion
+ */
+void CRtpManager::MakeACnameL(TDes8 &aCname)
+ {
+ /* As of now putting the IP Address. But this is not enough.
+ * multiple sessions should have unique CNAMES
+ * */
+ TBuf<50> ipAddr;
+ TInetAddr locAddr = GetLocalIPAddressL();
+ locAddr.Output(ipAddr);
+ aCname.Format(_L8("%d@"),iRtpSessionArr.Count()+1);
+ aCname.Append(ipAddr);
+ }
+/**
+* Create a new RTP Session and return the Session ID as well as the
+* local port number assigned for RTP. RTP uses an even port number and
+* RTCP, if enabled, uses the next higher (odd) port number.
+*/
+ TRtpId CRtpManager::CreateSessionL(const TCreateSessionParams& aSessionParams,
+ TUint& aPort, TBool aEnableRtcp, const TRtcpParams* aRtcpParams )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::CreateSessionL");
+ __RTP_LOG1("RTCP stat %d",aEnableRtcp)
+ TInt localPort;
+ /* The RTP Session create takes in the LocalPort.*/
+ if(iRtpSessionArr.Count() == 0)
+ {
+ //In this case start from begining. Start by using the default Even RTP
+ //Port.
+ localPort = KDefaultStartRtpAddress;
+ __RTP_LOG1("LocalPort used %d",localPort)
+ }
+ else
+ {
+ /* Pick the next highest port number */
+ localPort = iRtpSessionArr[iRtpSessionArr.Count()-1]->iPortNumber + 2;
+ __RTP_LOG1("LocalPort used %d",localPort)
+ }
+
+ //if the user has specified a port then override our selection
+ if(aPort)
+ {
+ localPort = aPort;
+ }
+
+ //Now use this Port and try opening the RTP Session. If the Session Open
+ //fails try opening with the next even port.
+ //Its much more easier to use the API which takes RSocket directly here. But
+ //ths would mean we cannot use the New CFRTP API.
+ TInetAddr locAddr(0,localPort);
+
+ /* Remote address is uninitialized. Unfortunately its required by Symbian
+ * RTP stack. */
+ TInetAddr remAddr;
+
+ #ifndef SYMBIAN_ENABLE_SPLIT_HEADERS
+ RRtpSession rtpSession;
+ #else
+ RRtpSession_Internal rtpSession;
+ #endif
+
+ TPtrC8 cnameTptr((TUint8*)"", 0);;
+ if(aEnableRtcp)
+ {
+ TBuf8<50> cnameBuf;
+ if(iSdesInfo.iCName == KNullDesC8)
+ {
+ MakeACnameL(cnameBuf);
+ iSdesInfo.iCName.Set(cnameBuf);
+ }
+ cnameTptr.Set(iSdesInfo.iCName);
+ }
+ else
+ {
+ cnameTptr.Set(KNullDesC8);
+ }
+
+ TInt tryCount = 0;
+ TInt errOpenl = KErrNone;
+
+ __RTP_LOG1("Starting Port alloc and OpenL tryCount %d",tryCount);
+ __RTP_LOG1("aSessionParams.iSocketBufSize %d",aSessionParams.iSocketBufSize);
+ aPort = locAddr.Port();
+
+ while(tryCount < 5 )
+ {
+ TRAP(errOpenl,rtpSession.OpenL(*iSocketServ, locAddr, remAddr, aSessionParams.iSocketBufSize, *iConnection, EPriorityNormal, cnameTptr));
+ if(errOpenl != KErrNone)
+ {
+ __RTP_LOG2("OpenL Failed with Error Code %d TryCount %d",errOpenl, tryCount);
+ tryCount ++;
+ locAddr.SetPort(locAddr.Port()+tryCount+1);
+ localPort += tryCount+1;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ User::LeaveIfError(errOpenl);
+
+ __RTP_LOG(",rtpSession.OpenL Success!!");
+
+ TTimeIntervalMicroSeconds32 rtcpInterval;
+ if(aEnableRtcp && aRtcpParams)
+ {
+ rtpSession.SetBandwidth(aRtcpParams->iSessionBWidth);
+ __RTP_LOG1(" aRtcpParams->iRtcpTimeOut %d", aRtcpParams->iRtcpTimeOut.Int());
+ if(aRtcpParams->iRtcpTimeOut.Int())
+ {
+ rtcpInterval = aRtcpParams->iRtcpTimeOut.Int();
+ }
+ else
+ {
+ //TODO fix me!
+ //default 500 ms
+ rtcpInterval = 1000000;
+ }
+ rtpSession.SetRtcpInterval(rtcpInterval);
+ }
+ else
+ {
+ __RTP_LOG("Setting default RTCP Properties!!");
+ //Default Bandwidth.
+ rtpSession.SetBandwidth(KRtpDefaultBandWidth);
+ rtcpInterval = 1000000;
+ rtpSession.SetRtcpInterval(rtcpInterval);
+ }
+
+ //Phew! Now put these in our Array
+ CRtpSessionInfo* sessionInfo = CRtpSessionInfo::NewL();
+ //Assign a Key for this session.
+ sessionInfo->iKey = Math::Random();
+ sessionInfo->iPortNumber = localPort;
+ sessionInfo->iRtpSession = rtpSession;
+ sessionInfo->iRtpManager = this;
+ sessionInfo->iRtcpEnabled = aEnableRtcp;
+ sessionInfo->iPendingReqQue = new(ELeave) TSglQue<TRtpSendReqNode>(_FOFF(TRtpSendReqNode,iLink));
+ iRtpSessionArr.InsertInOrder(sessionInfo, TLinearOrder<CRtpSessionInfo>(RtpSessionLinearOrderFunc)); //InsertInOrder(sessionInfo,TLinearOrder<CRtpSessionInfo>(RtpSessionLinearOrderFunc));
+
+ __RTP_LOG1("Session Created Key %u",sessionInfo->iKey)
+ //Get back the reference to the object in Array.
+ TInt idx = FindSessionL(sessionInfo->iKey);
+
+ //Register for the Events
+ RegisterEventsOnSessionL(iRtpSessionArr[idx]);
+
+ aPort = localPort;
+
+ //TODO: Fix this in RTP Stack.
+ /* Remote Address is uninitialized now. So if RTCP is enabled disable autosend so that
+ * no data is send to incorrect address.
+ */
+ if(aEnableRtcp)
+ {
+ rtpSession.SetRTCPAutoSend(EFalse);
+ }
+
+
+ LOG_FUNC_EXIT("CRtpManager::CreateSessionL");
+
+ return sessionInfo->iKey;
+ }
+
+
+/**
+ *Create a new, secure RTP Session and return the Session ID as well as the
+* local port number assigned for RTP. RTP uses an even port number and
+* RTCP, if enabled, uses the next higher (odd) port number.
+* User is expected to create corresponding SRTP session prior to calling this
+* function.
+*/
+ TRtpId CRtpManager::CreateSessionL( const TCreateSessionParams& aSessionParams, TUint& aPort,
+ TBool aEnableRtcp, const TRtcpParams* aRtcpParams, CSRTPSession& aSRTPSession)
+ {
+ LOG_FUNC_ENTRY("CRtpManager::CreateSessionL");
+ __RTP_LOG("SRTP is not supported Leaving..!!")
+
+ TUint32 key = CreateSessionL(aSessionParams, aPort, aEnableRtcp, aRtcpParams);
+ TInt idx = FindSessionL(key);
+ iRtpSessionArr[idx]->iSRTPSession = &aSRTPSession;
+ iRtpSessionArr[idx]->iRtpSession.SetPrePostProcessingRegisterCallback(iRtpSessionArr[idx]);
+ return key;
+ }
+
+/**
+* Start an RTP Session. If enabled, RTCP associated with the given
+* session is also started.
+*/
+ TInt CRtpManager::StartSession( TRtpId aSessionId )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::StartSession");
+ if(FindSession(aSessionId)!= KErrNotFound)
+ {
+ /* Well we found the session. But Really nothing to do */
+ //TODO verify
+ return KErrNone;
+ }
+ else
+ {
+ return KErrNotFound;
+ }
+ }
+
+/**
+* Close an RTP Session.
+*/
+ void CRtpManager::CloseSession( TRtpId aSessionId )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::CloseSession");
+ __RTP_LOG1("SessID %u",aSessionId)
+ TInt idx;
+ idx = FindSession(aSessionId);
+ if(KErrNotFound != idx)
+ {
+ /* This takes care of all cleaning up */
+ iRtpSessionArr[idx]->iRtpSession.Close();
+ /* There should be no more Pending requests on this session */
+ ASSERT(iRtpSessionArr[idx]->iPendingReqQue->IsEmpty());
+ delete iRtpSessionArr[idx]->iPendingReqQue;
+ CRtpSessionInfo *session = iRtpSessionArr[idx];
+ iRtpSessionArr.Remove(idx);
+ delete session;
+ }
+ else
+ {
+ __RTP_LOG("Session not found")
+ //So already cleaned?
+ }
+ LOG_FUNC_EXIT("CRtpManager::CloseSession");
+ }
+
+/**
+* Set remote IP address and port number to RTP Session.
+* Port number for RTP must be an even number and the corresponding
+* RTCP, if enabled, will be set to use the next higher (odd) port.
+*/
+ TInt CRtpManager::SetRemoteAddress( TRtpId aSessionId,const TInetAddr& aRemoteAddr )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::SetRemoteAddress");
+ __RTP_LOG1("SessID %u",aSessionId)
+ __RTP_LOG_STMT(TBuf<50> buf; aRemoteAddr.Output(buf););
+ __RTP_LOG2("RemoteAddressAddress %S, Port %u", &buf, aRemoteAddr.Port());
+ TInt ret;
+ TInetAddr addr = aRemoteAddr;
+ if((ret =FindSession(aSessionId))!= KErrNotFound)
+ {
+ iRtpSessionArr[ret]->iRtpSession.SetRemoteAddress(addr);
+ iRtpSessionArr[ret]->iRemoteAddress = aRemoteAddr;
+ /* SET the RTCP address as well here */
+ iRtpSessionArr[ret]->iRemoteRTCPAddress = aRemoteAddr;
+ iRtpSessionArr[ret]->iRemoteRTCPAddress.SetPort(aRemoteAddr.Port()+1);
+
+ return KErrNone;
+ }
+ else
+ {
+ return KErrNotFound;
+ }
+ }
+
+/**
+* Set remote RTCP IP address and port number to RTP Session accoring to RFC 3605
+* i.e. this should be used if RTCP port is different than RTP port + 1
+*/
+TInt CRtpManager::SetRemoteRtcpAddress( TRtpId aSessionId, const TInetAddr& aRemoteAddr)
+ {
+ LOG_FUNC_ENTRY("CRtpManager::SetRemoteRtcpAddress");
+ __RTP_LOG1("SessID %u",aSessionId)
+ __RTP_LOG_STMT(TBuf<50> buf; aRemoteAddr.Output(buf););
+ __RTP_LOG2("RemoteAddressAddress %S, Port %u", &buf, aRemoteAddr.Port());
+ TInt ret;
+ TInt port = aRemoteAddr.Port();
+ if((ret =FindSession(aSessionId))!= KErrNotFound)
+ {
+ iRtpSessionArr[ret]->iRtpSession.SetRemoteRtcpPort(port);
+ iRtpSessionArr[ret]->iRemoteRTCPAddress = aRemoteAddr;
+
+ /*
+ //VS Experiment. Try sending Door opener here to Remote end
+ TRequestStatus stat;
+ __RTP_LOG("CRtpManager::SetRemoteAddress -- Sending DoorOpener --RTCP");
+ RSocket *sock = NULL;
+ sock = GetRtcpSocket(aSessionId);
+ sock->SendTo(_L8("OpenSesame"),iRtpSessionArr[ret]->iRemoteAddress,0,stat);
+ User::WaitForRequest(stat);
+ __RTP_LOG1("DoorOpener --RTCP sent retCode %d", stat.Int());
+ LOG_FUNC_EXIT("CRtpManager::SetRemoteRtcpAddress");
+ */
+ return KErrNone;
+ }
+ else
+ {
+ return KErrNotFound;
+ }
+ }
+
+/**
+* Create a Receive stream for an RTP Session and return the stream
+* ID which is unique for all RTP Sessions.
+*/
+ TRtpId CRtpManager::CreateReceiveStreamL( TRtpId aSessionId, const TRcvStreamParams& aParams )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::CreateReceiveStreamL");
+ __RTP_LOG1("SessID %u",aSessionId)
+ /* Valide the session */
+ FindSessionL(aSessionId);
+
+ /* Check for Post-Created Streams. If present use it */
+ for(TInt i=0; i < iRtpStreamsArr.Count(); i++)
+ {
+ if(iRtpStreamsArr[i].iSessionKey == aSessionId &&
+ iRtpStreamsArr[i].iState == TRtpStreamInfo::eStreamPostCreated &&
+ iRtpStreamsArr[i].iPayloadType == aParams.iPayloadType )
+ {
+ __RTP_LOG1("Found Post Created Stream Key %u",iRtpStreamsArr[i].iKey)
+ /* Post created stream exists. Return it */
+ iRtpStreamsArr[i].iState = TRtpStreamInfo::eStreamReadyToUse;
+ return iRtpStreamsArr[i].iKey;
+ }
+ }
+
+ /* OK found nothing. So create a Pre-Created stream and return its ID */
+ TRtpStreamInfo strmInfo;
+ strmInfo.iKey = Math::Random();
+ strmInfo.iSessionKey = aSessionId;
+ strmInfo.iState = TRtpStreamInfo::eStreamPreCreated;
+ strmInfo.iPayloadType = aParams.iPayloadType;
+ strmInfo.iRtpManager = this;
+
+ iRtpStreamsArr.AppendL(strmInfo);
+ __RTP_LOG1("Created PreCreated Stream Key %u",strmInfo.iKey)
+
+ LOG_FUNC_EXIT("CRtpManager::CreateReceiveStreamL");
+ return strmInfo.iKey;
+ }
+
+ /**
+ * Create a Transmit stream for an RTP Session and return the stream
+ * ID which is unique for all RTP Sessions. SSRC value assigned for the
+ * very first Transmit stream will be the same as the default SSRC
+ * value reserved internally by CreateSession function. This function
+ * is normally used to create a transmit stream where SSRC value is
+ * randomly generated.
+ */
+ TRtpId CRtpManager::CreateTransmitStreamL( TRtpId aSessionId,
+ const TTranStreamParams& aParams,
+ TRtpSSRC& aSSRC )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::CreateTransmitStreamL");
+ __RTP_LOG1("SessID %u",aSessionId)
+ TInt idx = FindSessionL(aSessionId);
+ if(!iRtpSessionArr[idx]->iRtpSendSource.IsOpen())
+ {
+ iRtpSessionArr[idx]->iRtpSendSource = iRtpSessionArr[idx]->iRtpSession.NewSendSourceL();
+ /* Now register for events in this session */
+ iRtpSessionArr[idx]->iRtpSendSource.RegisterEventCallbackL(ERtpSendSucceeded,
+ RtpSessionLevelCB,
+ iRtpSessionArr[idx],
+ ERtpNotOneShot);
+ iRtpSessionArr[idx]->iRtpSendSource.RegisterEventCallbackL(ERtpSendFail,
+ RtpSessionLevelCB,
+ iRtpSessionArr[idx],
+ ERtpNotOneShot);
+ aSSRC = iRtpSessionArr[idx]->iRtpSendSource.GetLocalSSRC();
+
+ iRtpSessionArr[idx]->iPayloadType = aParams.iPayloadType;
+
+ iRtpSessionArr[idx]->iRtpSendSource.SetPayloadType(aParams.iPayloadType);
+
+
+ //Note: The key is same as the SessionKey. We donot support
+ //more than one Transmit Streams in one Session.
+ LOG_FUNC_EXIT("CRtpManager::CreateTransmitStreamL");
+
+ return iRtpSessionArr[idx]->iKey;
+ }
+ __RTP_LOG("A SendStream was already Opened!")
+ //Already called still there might be Applications calling this
+ //API twice
+ //
+ LOG_FUNC_EXIT("CRtpManager::CreateTransmitStreamL");
+ return 0;
+ }
+
+ /**
+ * Create a Transmit stream, with a given SSRC value, for an RTP Session
+ * and return the stream ID which is unique for all RTP Sessions. This
+ * extended function is used for a special case where a specific SSRC
+ * value needs to be associated with the transmit stream being created,
+ * e.g. for retransmission purpose.
+ */
+ TRtpId CRtpManager::CreateTransmitStreamExtL( TRtpId , const TTranStreamParams& ,
+ const TRtpSSRC )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::CreateTransmitStreamL");
+ __RTP_LOG("NotSuppoted SSRC cannot be changed")
+ //This is not supported as of now.
+ //SSRC cannot be specified by Applications.
+ return 0;
+ }
+
+
+ /**
+ * Close a Transmit or Receive stream.
+ */
+void CRtpManager::CloseStream( TRtpId aRtpID)
+ {
+ LOG_FUNC_ENTRY("CRtpManager::CloseStream");
+ __RTP_LOG1("Stream ID %u",aRtpID)
+ (void)aRtpID;
+ //Streams are closed when session is closed.
+ //so no requirement for an explicit close
+ //TODO Verify Requirements
+ return;
+ }
+
+/**
+ * Register a callback object for receiving RTP data packets from an RTP
+ * Session. Only one receiver callback object is allowed to be
+ * registered for one Session.
+ */
+TInt CRtpManager::RegisterRtpObserver( TRtpId aSessionId, MRtpObserver& aRtpObserver )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::RegisterRtpObserver");
+ __RTP_LOG1("SessID %u",aSessionId)
+ TInt ret = FindSession(aSessionId);
+ if(ret < 0)
+ return ret;
+ iRtpSessionArr[ret]->iRtpObserver = &aRtpObserver;
+ return KErrNone;
+ }
+
+ /**
+ * Unregister RTP observer callback object associated with an RTP
+ * session.
+ */
+void CRtpManager::UnregisterRtpObserver(TRtpId aSessionId)
+ {
+ LOG_FUNC_ENTRY("CRtpManager::UnregisterRtpObserver");
+ __RTP_LOG1("SessID %u",aSessionId)
+
+ TInt ret = FindSession(aSessionId);
+ if(ret >= 0)
+ iRtpSessionArr[ret]->iRtpObserver = NULL;
+ }
+
+/**
+* Sets/resets the observer for the non-RTP data.
+* Only one receiver callback object is allowed to be
+* registered for one Session.
+* called when a non-RTP data packet is received.
+*/
+ TInt CRtpManager::SetNonRTPDataObserver( TRtpId aSessionId, MNonRTPDataObserver* aNonRtpObserver)
+ {
+ LOG_FUNC_ENTRY("CRtpManager::SetNonRTPDataObserver");
+ __RTP_LOG1("SessID %u",aSessionId);
+
+ TInt ret = FindSession(aSessionId);
+ if(ret < 0)
+ return ret;
+ iRtpSessionArr[ret]->iNonRtpDataObserver = aNonRtpObserver;
+
+ TRAPD(err,iRtpSessionArr[ret]->iRtpSession.RegisterEventCallbackL(ENonRtpDataReceived,
+ RtpSessionLevelCB,
+ iRtpSessionArr[ret],
+ ERtpOneShot));
+ if(KErrNone != err)
+ {
+ __RTP_LOG1("err %d",err);
+ return err;
+ }
+
+ TRAP(err,iRtpSessionArr[ret]->iRtpSession.RegisterEventCallbackL(ENonRtcpDataReceived,
+ RtpSessionLevelCB,
+ iRtpSessionArr[ret],
+ ERtpOneShot));
+
+ if(KErrNone != err)
+ {
+ /* The already registered callback will be deleted when the first
+ * NonRtp data comes
+ */
+ iRtpSessionArr[ret]->iNonRtpDataObserver = 0;
+ }
+ return err;
+ }
+
+/**
+* Send an RTP data packet in a Transmit stream synchronously.
+*/
+ TInt CRtpManager::SendRtpPacket( TRtpId aTranStreamId,
+ const TRtpSendHeader& aHeaderInfo,
+ const TDesC8& aPayloadData )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::SendRtpPacket");
+ __RTP_LOG1("aTranStreamId: %u",aTranStreamId)
+
+ /* The Transmit Id and Session ID are same. So
+ * find the session */
+ TInt ret = FindSession(aTranStreamId);
+ if(ret<0)
+ return ret;
+ ASSERT(iRtpSessionArr[ret]->iRtpSendSource.IsOpen());
+
+ RRtpSendPacket sendPkt;
+ TInt pktLen = 0;
+ pktLen += aPayloadData.Length();
+ __RTP_LOG1("pktLen: %d", pktLen );
+ if(iRtpSessionArr[ret]->iSRTPSession)
+ {
+ /* SRTP is enabled so allocate more bytes for MKI and AuthTag */
+ pktLen += ( KSrtpMaxAuthTagLength + KSrtpMaxMKILen );
+ __RTP_LOG1("Added extra bytes for SRTP new pktLen: %d", pktLen );
+ }
+ TRAPD(err,sendPkt = iRtpSessionArr[ret]->iRtpSendSource.NewSendPacketL(pktLen, aHeaderInfo.iHeaderExtension?aHeaderInfo.iHeaderExtension->iLength:KRtpNoExtension));
+ if(err != KErrNone)
+ return err;
+
+ __RTP_LOG2("TS: %u, PayloadType %d",aHeaderInfo.iTimestamp, aHeaderInfo.iPayloadType)
+ sendPkt.SetTimestamp(aHeaderInfo.iTimestamp);
+ sendPkt.SetMarker(aHeaderInfo.iMarker);
+ sendPkt.SetPayloadType(aHeaderInfo.iPayloadType);
+
+ if(iRtpSessionArr[ret]->iFirstPacketSent == EFalse)
+ {
+ iRtpSessionArr[ret]->iRtpSession.SetRTPTimeConversion(aHeaderInfo.iTimestamp, iRtpSessionArr[ret]->iSamplingRate/1000);
+ iRtpSessionArr[ret]->iFirstPacketSent = ETrue;
+ }
+
+ TDes8 &wrtPayload = sendPkt.WritePayload();
+ wrtPayload = aPayloadData;
+
+ ret = sendPkt.SendSync();
+
+ //TODO pre allocate a Max Size
+ sendPkt.Close();
+
+ LOG_FUNC_EXIT("CRtpManager::SendRtpPacket");
+ return ret;
+ }
+
+
+ /**
+ * Send an RTP data packet in a Transmit stream asynchronously.
+ */
+ TInt CRtpManager::SendRtpPacket( TRtpId aTranStreamId,
+ const TRtpSendHeader& aHeaderInfo,
+ const TDesC8& aPayloadData,
+ TRequestStatus& aStatus )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::SendRtpPacket");
+ __RTP_LOG1("aTranStreamId: %u",aTranStreamId)
+ /* The Transmit Id and Session ID are same. So
+ * find the session */
+ TInt ret = FindSession(aTranStreamId);
+ if(ret<0)
+ return ret;
+ ASSERT(iRtpSessionArr[ret]->iRtpSendSource.IsOpen());
+
+ RRtpSendPacket sendPkt;
+ TInt pktLen = 0;
+ pktLen += aPayloadData.Length();
+ __RTP_LOG1("pktLen: %d", pktLen );
+ if(iRtpSessionArr[ret]->iSRTPSession)
+ {
+ /* SRTP is enabled so allocate more bytes for MKI and AuthTag */
+ pktLen += ( KSrtpMaxAuthTagLength + KSrtpMaxMKILen );
+ __RTP_LOG1("Added extra bytes for SRTP new pktLen: %d", pktLen );
+ }
+ TRAPD(err,sendPkt = iRtpSessionArr[ret]->iRtpSendSource.NewSendPacketL(pktLen,aHeaderInfo.iHeaderExtension?aHeaderInfo.iHeaderExtension->iLength:KRtpNoExtension));
+ if(err != KErrNone)
+ return err;
+
+ __RTP_LOG2("TS: %u, PayloadType %d",aHeaderInfo.iTimestamp, aHeaderInfo.iPayloadType);
+ sendPkt.SetTimestamp(aHeaderInfo.iTimestamp);
+ sendPkt.SetMarker(aHeaderInfo.iMarker);
+ sendPkt.SetPayloadType(aHeaderInfo.iPayloadType);
+
+
+ if(iRtpSessionArr[ret]->iFirstPacketSent == EFalse)
+ {
+ iRtpSessionArr[ret]->iRtpSession.SetRTPTimeConversion(aHeaderInfo.iTimestamp, 1000*1000/iRtpSessionArr[ret]->iSamplingRate);
+ iRtpSessionArr[ret]->iFirstPacketSent = ETrue;
+ }
+
+
+ TDes8 &wrtPayload = sendPkt.WritePayload();
+ wrtPayload = aPayloadData;
+
+ /* This is an Async Send. So insert this packet in to the
+ * the send queue.
+ */
+ TRtpSendReqNode *sendReqNode = NULL;
+ sendReqNode = new TRtpSendReqNode();
+ if(!sendReqNode)
+ {
+ sendPkt.Close();
+ return KErrNoMemory;
+ }
+
+ sendReqNode->iPktToSend = sendPkt;
+ sendReqNode->iStatus = &aStatus;
+ iRtpSessionArr[ret]->iPendingReqQue->AddFirst(*sendReqNode);
+ *sendReqNode->iStatus = KRequestPending;
+ /* If this is the only pending element in the queue schedule immediately */
+ if(iRtpSessionArr[ret]->iPendingReqQue->IsLast(sendReqNode))
+ {
+ __RTP_LOG("Async Send ..Sending Immediately!");
+ return SendRtpDataFromPendingQueue(iRtpSessionArr[ret]);
+ }
+
+ __RTP_LOG("Async Send ..Packet Queued!");
+ //TODO pre allocate a Max Size
+ // The packet will be closed when Send is completed
+ return KErrNone;
+ }
+
+ /**
+ * Send an RTP data packet asynchronously, with a given sequence number,
+ * in a Transmit stream mainly for retransmission purpose.
+ */
+ TInt CRtpManager::SendRtpPacket( TRtpId aTranStreamId,
+ TRtpSequence ,
+ const TRtpSendHeader& aHeaderInfo,
+ const TDesC8& aPayloadData,
+ TRequestStatus& aStatus )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::SendRtpPacket - With Sequence Called!!");
+ //TODO We SHOULD consider the Sequence number as well!
+ return SendRtpPacket(aTranStreamId, aHeaderInfo, aPayloadData, aStatus) ;
+ }
+
+
+/**
+ * Send a non-RTP (control) data packet asynchronously
+*/
+ void CRtpManager::SendDataL( TRtpId aSessionId, TBool aUseRTPSocket,
+ const TDesC8& aData, TRequestStatus& aStatus)
+ {
+ LOG_FUNC_ENTRY("CRtpManager::SendDataL");
+ __RTP_LOG1("aSessionId: %u",aSessionId)
+ TInt ret = FindSessionL(aSessionId);
+ RSocket *sock = NULL;
+ TInetAddr remAddr = iRtpSessionArr[ret]->iRemoteAddress;
+ if(aUseRTPSocket)
+ {
+ sock = GetRtpSocket(aSessionId);
+ }
+ else
+ {
+ if(!iRtpSessionArr[ret]->iRtcpEnabled)
+ User::Leave(KErrNotSupported);
+ sock = GetRtcpSocket(aSessionId);
+ remAddr = iRtpSessionArr[ret]->iRemoteRTCPAddress;
+ }
+ /* Send the data out through the Socket */
+ sock->SendTo(aData,remAddr,0,aStatus);
+ return;
+ }
+
+ /**
+ * Cancel an outstanding SendRtpPacket() operation.
+ */
+ void CRtpManager::CancelSend( TRtpId aSessId)
+ {
+ /* Its a Bit tricky here.
+ * We have two levels of Active Objects and the Symbian stack
+ * do not provide any API to cancel the Send request. As a workarnd we accesses the
+ * RTP Socket directly and cancels the send ( RSocket::CancelSend())
+ * Internal statistics are not rolled back in this case, but surely we can
+ * live with that.
+ *
+ * The Active object who issued this call will do a User::WaitForRequest()
+ * immediatly after calling Cancel. (See CActive::Cancel() implementation).
+ * This means we should complete the request with KErrCancel here itself or
+ * thread will block (Because we are not exactly an Async Service provider).
+ * Once the request is completed we can expect a ESendFail callback or an
+ * ESendSuccess callback from stack ( Second one beacuse the request might have
+ * been completed already).
+ */
+ LOG_FUNC_ENTRY("CRtpManager::CancelSend");
+ __RTP_LOG1("SessId: %u",aSessId)
+
+ TInt ret = FindSession(aSessId);
+ if(ret < 0)
+ {
+ ASSERT(ret!=KErrNone);
+ return;
+ }
+ if(iRtpSessionArr[ret]->iPendingReqQue->IsEmpty())
+ {
+ /* There is no pending request. This probably means the request was
+ * already completed but the App is yet to see it..
+ */
+ __RTP_LOG("NO pending request .. Returning!")
+ return;
+ }
+
+ TRtpSendReqNode *reqNode = iRtpSessionArr[ret]->iPendingReqQue->Last();
+ /* Once send is canceled complete Applications request. Also if the pending
+ * queue is not empty schedule a new transmission here itself */
+ iRtpSessionArr[ret]->iRtpSendSource.Cancel();
+ User::RequestComplete(reqNode->iStatus, KErrCancel);
+ iRtpSessionArr[ret]->iPendingReqQue->Remove(*reqNode);
+ reqNode->iPktToSend.Close();
+ delete reqNode;
+
+ if(!iRtpSessionArr[ret]->iPendingReqQue->IsEmpty())
+ {
+ __RTP_LOG("Scheduling another send from PendingQueue")
+ SendRtpDataFromPendingQueue(iRtpSessionArr[ret]);
+ }
+
+ return;
+ }
+
+ /**
+ * Register a callback object for receiving RTCP packets associated with
+ * a given RTP Session. Only one observer callback object is allowed to
+ * be registered. One of aRtcpObserver object's callback functions is
+ * called when an RTCP packet of that type is received.
+ */
+ TInt CRtpManager::RegisterRtcpObserver( TRtpId aSessionId, MRtcpObserver& aRtcpObserver )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::RegisterRtcpObserver");
+ __RTP_LOG1("SessId: %u",aSessionId)
+
+ TInt ret = FindSession(aSessionId);
+ if(ret < 0)
+ return ret;
+ iRtpSessionArr[ret]->iRtcpObserver = &aRtcpObserver;
+ return KErrNone;
+ }
+
+ /**
+ * Unregister RTCP observer callback object associated with an RTP
+ * session.
+ */
+ void CRtpManager::UnregisterRtcpObserver( TRtpId aSessionId )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::UnregisterRtcpObserver");
+ __RTP_LOG1("SessId: %u",aSessionId)
+
+ TInt ret = FindSession(aSessionId);
+ if(ret >= 0)
+ iRtpSessionArr[ret]->iRtcpObserver = NULL;
+ return;
+ }
+ /**
+ * Send an RTCP APP packet for a Transmit stream.
+ */
+ TInt CRtpManager::SendRtcpAppPacket( TRtpId aTranStreamId, const TRtcpApp& aApp )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::SendRtcpAppPacket");
+ __RTP_LOG1("aTranStreamId: %u",aTranStreamId)
+
+ /* A send stream should be open to send an RTCP Bye packet */
+ //Transmit Stream ID and Session Id are same
+ TInt ret = FindSession(aTranStreamId);
+ if(ret < 0)
+ return ret;
+ ASSERT(iRtpSessionArr[ret]->iRtcpEnabled);
+
+ TPtrC8 appName;
+ appName.Set(aApp.iName,4); //Name is 4 Characters RFC 3550 Sec 6.7
+
+ TPtrC8 appData;
+ appData.Set(aApp.iAppData,aApp.iAppDataLen);
+
+ TUint8 subType = aApp.iSubType;
+
+ TRAPD(err,iRtpSessionArr[ret]->iRtpSession.SendAPPL(appName,appData, subType));
+
+ return err;
+ }
+
+ /**
+ * Send an RTCP BYE packet for a Transmit stream.
+ */
+ TInt CRtpManager::SendRtcpByePacket( TRtpId aTranStreamId, const TDesC8& aReason)
+ {
+ LOG_FUNC_ENTRY("CRtpManager::SendRtcpByePacket");
+ __RTP_LOG1("aTranStreamId: %u",aTranStreamId)
+
+ /* A send stream should be open to send an RTCP Bye packet */
+ //Transmit Stream ID and Session Id are same
+ TInt ret = FindSession(aTranStreamId);
+ if(ret < 0)
+ return ret;
+ ASSERT(iRtpSessionArr[ret]->iRtpSendSource.IsOpen());
+ TRAPD(err,iRtpSessionArr[ret]->iRtpSendSource.ByeL(const_cast<TDesC8&>(aReason)));
+ return err;
+ }
+
+/**
+ * Send an RTCP RR packet for a Reception stream.
+*/
+TInt CRtpManager::SendRtcpRrPacket( TRtpId aRcvStreamId )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::SendRtcpRrPacket");
+ __RTP_LOG1("aRcvStreamId: %u",aRcvStreamId)
+
+ /* No specific way to Send an RR Report alone */
+ //Do we need to?
+ TInt ret = FindStream(aRcvStreamId);
+ if(ret<0)
+ {
+ return ret;
+ }
+
+ ret = FindSession(iRtpStreamsArr[ret].iSessionKey);
+ TUint8 flg = 0x81;
+ TBuf8<1> flags;
+ flags.Copy(&flg,1);
+ TRAP(ret, iRtpSessionArr[ret]->iRtpSession.SendRTCPPacketL(flags));
+ return ret;
+ }
+
+ /**
+ * Send an RTCP SR packet for a Transmit stream.
+ */
+ TInt CRtpManager::SendRtcpSrPacket( TRtpId aTranStreamId )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::SendRtcpSrPacket");
+ __RTP_LOG1("aTranStreamId: %u",aTranStreamId)
+
+ //NOTE: TransID same as SessionId
+ TInt ret = FindSession(aTranStreamId);
+ if(ret<0)
+ return ret;
+
+ TUint8 flg = 0x81;
+ TBuf8<1> flags;
+ flags.Copy(&flg,1);
+ TRAP(ret, iRtpSessionArr[ret]->iRtpSession.SendRTCPPacketL(flags));
+ return ret;
+ }
+
+/**
+ * Suspend RTCP sending on/off, calculations will continue.
+*/
+TInt CRtpManager::SuspendRtcpSending( TRtpId aSessionId, TBool aAutoSending )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::SuspendRtcpSending");
+ __RTP_LOG2("aSessionId: %u aAutoSending %d",aSessionId,aAutoSending)
+
+ //NOTE: TransID same as SessionId
+ TInt ret = FindSession(aSessionId);
+ if(ret<0)
+ return ret;
+ if(iRtpSessionArr[ret]->iRtcpEnabled)
+ {
+ iRtpSessionArr[ret]->iRtpSession.SetRTCPAutoSend(aAutoSending);
+ return KErrNone;
+ }
+ else
+ {
+ return KErrNotSupported;
+ }
+ }
+
+/**
+ * Gets the status of automatic RTCP sending.
+ */
+TInt CRtpManager::IsRtcpSendingSuspended( TRtpId aSessionId, TBool& aAutoSending )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::IsRtcpSendingSuspended");
+
+ TInt ret = FindSession(aSessionId);
+ if(ret<0)
+ return ret;
+ if(iRtpSessionArr[ret]->iRtcpEnabled)
+ {
+ aAutoSending = iRtpSessionArr[ret]->iRtpSession.RTCPAutoSend();
+ return KErrNone;
+ }
+ else
+ {
+ return KErrNotSupported;
+ }
+ }
+
+/**
+* Get the session ID of a stream, which belongs to that session.
+*/
+ TRtpId CRtpManager::GetSessionId( TRtpId aStreamId )
+ {
+ TInt ret = FindStream(aStreamId);
+ if(ret<0)
+ {
+ TInt idx = FindSession(aStreamId);
+ if(idx < 0)
+ {
+ return idx;
+ }
+ if(iRtpSessionArr[idx]->iRtpSendSource.IsOpen())
+ {
+ return iRtpSessionArr[idx]->iKey;
+ }
+ return ret;
+ }
+ return iRtpStreamsArr[ret].iSessionKey;
+ }
+
+
+/**
+* Get address of Socket object used by a given RTP Session
+* to send/receive RTP data packets.
+*/
+ RSocket* CRtpManager::GetRtpSocket( TRtpId aSessionId )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::GetRtpSocket");
+ __RTP_LOG1("aSessId %u",aSessionId)
+
+ TInt ret = FindSession(aSessionId);
+ if( ret<0 )
+ return NULL;
+ return iRtpSessionArr[ret]->iRtpSession.RtpSocket();
+ }
+
+/**
+* Get address of Socket object used by a given RTP Session
+* to send/receive RTCP control packets.
+*/
+ RSocket* CRtpManager::GetRtcpSocket( TRtpId aSessionId)
+ {
+ LOG_FUNC_ENTRY("CRtpManager::GetRtcpSocket");
+ __RTP_LOG1("aSessId %u",aSessionId)
+
+ TInt ret = FindSession(aSessionId);
+ if(ret<0 || !iRtpSessionArr[ret]->iRtcpEnabled)
+ return NULL;
+ return iRtpSessionArr[ret]->iRtpSession.RtcpSocket();
+ }
+
+ /**
+ * Retrieve statistical information for a stream
+ * based on the reports from RTCP SR & RR packets.
+ * @param aStreamId - [input] ID of stream
+ * @param aStat - [output] Statistical information
+ * @return KErrNone if successful; system wide error code otherwise
+ */
+ TInt CRtpManager::GetStreamStatistics( TRtpId aStreamId, TRtpPeerStat& aStat )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::GetStreamStatistics");
+ /* Find the session and the stream */
+ TInt ret = FindStream(aStreamId);
+ if(ret<0)
+ {
+ return ret;
+ }
+
+ RRtcpSRPart srPart = iRtpStreamsArr[ret].iRecvSource.GetSR();
+ //Filling up the SR part first
+ aStat.iNumPacketsSent = srPart.PacketCount();
+ aStat.iCumNumOctetsSent = srPart.ByteCount();
+ aStat.iRoundTripDelay = 0; //TODO To be supported
+ aStat.iTxBandwidth = 0; //TODO find the use cases
+
+ return KErrNone;
+ }
+
+ /**
+ * Get sampling rate setting for a payload type.
+ */
+ TUint32 CRtpManager::GetSamplingRate( TUint8 aPayloadType )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::GetSamplingRate");
+ __RTP_LOG1("PayLoadType %d",aPayloadType);
+ /* Iterate through the sessions and return its sampling rate*/
+ for(int i=0; i< iRtpSessionArr.Count(); i++)
+ {
+ __RTP_LOG1("iPayloadtype -->> :%d", iRtpSessionArr[i]->iPayloadType);
+ __RTP_LOG1("aPayloadtype -->> :%d", aPayloadType);
+ if(iRtpSessionArr[i]->iPayloadType == aPayloadType)
+ {
+ return iRtpSessionArr[i]->iSamplingRate;
+ }
+ }
+ //Not found
+ return 0;
+ }
+
+ /**
+ * Set sampling rate for a payload type.
+ */
+ TInt CRtpManager::SetSamplingRate( TUint8 aPayloadType, TUint32 aSamplingRate )
+ {
+ LOG_FUNC_ENTRY("CRtpManager::SetSamplingRate");
+ __RTP_LOG2("PayloadType %d SamplingRate %u",aPayloadType,aSamplingRate)
+ /* Iterate through the sessions and set its sampling rate*/
+ for(int i=0; i< iRtpSessionArr.Count(); i++)
+ {
+ if(iRtpSessionArr[i]->iPayloadType == aPayloadType || KRtpPayloadTypeUnspecified == iRtpSessionArr[i]->iPayloadType)
+ {
+ iRtpSessionArr[i]->iPayloadType = aPayloadType;
+ iRtpSessionArr[i]->iSamplingRate = aSamplingRate;
+ iRtpSessionArr[i]->iRtpSession.SetRTPTimeConversion(0,aSamplingRate/1000);
+ }
+ /* Also update the Sampling rates so that received streams are properly handled */
+ iRtpSessionArr[i]->iRtpSession.SetSamplingRate(aPayloadType,aSamplingRate);
+ }
+ return KErrNone;
+ }
+
+ /**
+ * Set RTCP parameters for a given RTP Session.
+ * This function does nothing if RTCP was not enabled previously.
+ */
+ TInt CRtpManager::SetRtcpParameters( TRtpId aSessionId, const TRtcpParams& aRtcpParams )
+ {
+ TInt ret = FindSession(aSessionId);
+ if(ret<0)
+ return ret;
+ ASSERT(iRtpSessionArr[ret]->iRtcpEnabled);
+ iRtpSessionArr[ret]->iRtpSession.SetRtcpInterval(const_cast<TTimeIntervalMicroSeconds32&>(aRtcpParams.iRtcpTimeOut));
+ iRtpSessionArr[ret]->iRtpSession.SetBandwidth(aRtcpParams.iSessionBWidth);
+
+ return KErrNone;
+ }
+
+
+ /**
+ * Synchronous custom command interface for future extensions.
+ * Input/output data and return value are defined by each custom command
+ */
+ TInt CRtpManager::CustomCommandSync( TInt , const TDesC8& ,
+ const TDesC8& , TDes8& )
+ {
+ /* Not Supported. But is it ok to Fail? */
+ return KErrNotSupported;
+ }
+
+ /**
+ * ASynchronous custom command interface for future extensions.
+ * Input/output data and return value are defined by each custom command
+ */
+ TInt CRtpManager::CustomCommandAsync( TInt , const TDesC8& , const TDesC8& ,
+ TDes8& ,TRequestStatus& )
+ {
+ /* Not Supported. But is it ok to Fail? */
+ return KErrNotSupported;
+ }
+
+
+ TInt CRtpManager::FindSession(TRtpId aSessionId)
+ {
+ /* A simple iteration to find the session */
+ for(TInt i=0; i < iRtpSessionArr.Count(); i++)
+ {
+ if(iRtpSessionArr[i]->iKey == aSessionId)
+ {
+ return i;
+ }
+ }
+ __RTP_LOG("****FindSession Session Not Found!****")
+ return KErrNotFound;
+ }
+
+TInt CRtpManager::FindSessionL(TRtpId aSessionId)
+ {
+ TInt ret = FindSession(aSessionId);
+ User::LeaveIfError(ret);
+ return ret;
+ }
+
+TInt CRtpManager::FindStream(TRtpId aStreamId)
+ {
+ /* A simple iteration to find the session */
+ for(TInt i=0; i < iRtpStreamsArr.Count(); i++)
+ {
+ if(iRtpStreamsArr[i].iKey == aStreamId)
+ {
+ return i;
+ }
+ }
+ __RTP_LOG("****FindStream Stream Not Found!****")
+ return KErrNotFound;
+ }
+
+TInt CRtpManager::FindStreamL(TRtpId aStreamId)
+ {
+ TInt ret = FindStream(aStreamId);
+ User::LeaveIfError(ret);
+ return ret;
+ }
+
+TInt CRtpManager::GetDefaultIapIdL()
+ {
+ LOG_FUNC_ENTRY("CRtpManager::GetDefaultIapIdL");
+ TInt apId;
+ CCommsDatabase* db = CCommsDatabase::NewL(EDatabaseTypeIAP);
+ CleanupStack::PushL(db);
+ CCommsDbConnectionPrefTableView* view= db->OpenConnectionPrefTableInRankOrderLC(ECommDbConnectionDirectionOutgoing);
+ CCommsDbConnectionPrefTableView::TCommDbIapConnectionPref Pref;
+ view->GotoFirstRecord();
+ view->ReadConnectionPreferenceL(Pref);
+ apId = Pref.iBearer.iIapId;
+ CleanupStack::PopAndDestroy(2);
+ __RTP_LOG1("IapId %d",apId)
+ LOG_FUNC_EXIT("CRtpManager::GetDefaultIapIdL");
+ return apId;
+ }
+
+/* Schedules RTP transmission from the Head of the pending queue
+ */
+TInt CRtpManager::SendRtpDataFromPendingQueue(CRtpSessionInfo *aSessInfo)
+ {
+ ASSERT(!aSessInfo->iPendingReqQue->IsEmpty());
+ TRtpSendReqNode *reqNode = aSessInfo->iPendingReqQue->Last();
+ reqNode->iPktToSend.Send();
+ return KErrNone;
+ }
+
+void CRtpManager::RegisterEventsOnSessionL(CRtpSessionInfo *aSessionInfo)
+ {
+ RRtpSession session = aSessionInfo->iRtpSession;
+
+ session.RegisterEventCallbackL(ERtpSessionFail,
+ RtpSessionLevelCB,
+ aSessionInfo,
+ ERtpNotOneShot);
+
+ session.RegisterEventCallbackL(ERtpNewSource,
+ RtpSessionLevelCB,
+ aSessionInfo,
+ ERtpNotOneShot);
+
+ session.RegisterEventCallbackL(ERtpNewRR,
+ RtpSessionLevelCB,
+ aSessionInfo,
+ ERtpNotOneShot);
+
+ session.RegisterEventCallbackL(ERtpBufferOverflow,
+ RtpSessionLevelCB,
+ aSessionInfo,
+ ERtpNotOneShot);
+
+ session.RegisterEventCallbackL(ERtpUndersizedPacket,
+ RtpSessionLevelCB,
+ aSessionInfo,
+ ERtpNotOneShot);
+ }
+
+
+void CRtpManager::RegisterEventsOnRtpRcvSourceL(RRtpReceiveSource &aRcvSrc, TRtpStreamInfo *apStrmInfo)
+ {
+ aRcvSrc.RegisterEventCallbackL(ERtpPacketReceived,
+ CRtpManager::RtpStreamLevelCB,
+ apStrmInfo,
+ ERtpNotOneShot);
+
+ aRcvSrc.RegisterEventCallbackL(ERtpSourceFail,
+ CRtpManager::RtpStreamLevelCB,
+ apStrmInfo,
+ ERtpNotOneShot);
+
+ aRcvSrc.RegisterEventCallbackL(ERtpAPP,
+ CRtpManager::RtpStreamLevelCB,
+ apStrmInfo,
+ ERtpNotOneShot);
+
+
+ aRcvSrc.RegisterEventCallbackL(ERtpBYE,
+ CRtpManager::RtpStreamLevelCB,
+ apStrmInfo,
+ ERtpNotOneShot);
+
+ aRcvSrc.RegisterEventCallbackL(ERtpSR,
+ CRtpManager::RtpStreamLevelCB,
+ apStrmInfo,
+ ERtpNotOneShot);
+
+ aRcvSrc.RegisterEventCallbackL(ERtpRR,
+ CRtpManager::RtpStreamLevelCB,
+ apStrmInfo,
+ ERtpNotOneShot);
+
+ aRcvSrc.RegisterEventCallbackL(ERtpSDES,
+ CRtpManager::RtpStreamLevelCB,
+ apStrmInfo,
+ ERtpNotOneShot);
+ }
+
+void CRtpManager::HandleNonRtpDataL(CRtpSessionInfo *apSessionInfo)
+ {
+ apSessionInfo->iNonRtpDataObserver->NonRTPDataReceived(apSessionInfo->iPortNumber,
+ ETrue,
+ apSessionInfo->iRtpSession.NonRtpDataL());
+ apSessionInfo->iRtpSession.RegisterEventCallbackL(ENonRtpDataReceived,
+ RtpSessionLevelCB,
+ apSessionInfo,
+ ERtpOneShot);
+ }
+
+void CRtpManager::HandleNonRtcpDataL(CRtpSessionInfo *apSessionInfo)
+ {
+ apSessionInfo->iNonRtpDataObserver->NonRTPDataReceived(apSessionInfo->iPortNumber+1,
+ EFalse,
+ apSessionInfo->iRtpSession.NonRtcpDataL());
+ apSessionInfo->iRtpSession.RegisterEventCallbackL(ENonRtcpDataReceived,
+ RtpSessionLevelCB,
+ apSessionInfo,
+ ERtpOneShot);
+ }
+
+void CRtpManager::RtpSessionLevelCB(CRtpSessionInfo* apSessionInfo, const TRtpEvent& aEvent)
+ {
+ LOG_FUNC_ENTRY("CRtpManager::RtpSessionLevelCB");
+ __RTP_LOG1("EventType %x",aEvent.Type())
+ CRtpManager *pSelf = apSessionInfo->iRtpManager;
+
+ /* Event Send succeded or Failed */
+ if(ERtpSendSucceeded == aEvent.Type() || ERtpSendFail == aEvent.Type())
+ {
+ /* We are here only if Async Send was initiated */
+ TInt retCode = (aEvent.Type()==ERtpSendFail)?aEvent.Status():KErrNone;
+
+ /* An Async send is Complete. Notify the Application and schedule for next
+ * transmission if send queue is not empty */
+ ASSERT(!apSessionInfo->iPendingReqQue->IsEmpty());
+ TRtpSendReqNode *reqNode = apSessionInfo->iPendingReqQue->First();
+ reqNode->iPktToSend.Close();
+
+ __RTP_LOG("Complete Async Request")
+ /* Complete the Async Request */
+ User::RequestComplete(reqNode->iStatus,retCode);
+ apSessionInfo->iPendingReqQue->Remove(*reqNode);
+ delete reqNode;
+
+ if(!apSessionInfo->iPendingReqQue->IsEmpty())
+ {
+ //OK to ignore Send Errors ?
+ apSessionInfo->iRtpManager->SendRtpDataFromPendingQueue(apSessionInfo);
+ }
+ }
+ /* A new source was detected */
+ if(ERtpNewSource == aEvent.Type())
+ {
+ /* Create a ReceiveSource for this stream. */
+ RRtpReceiveSource rtpRcvSrc;
+ TRAPD(err, rtpRcvSrc = apSessionInfo->iRtpSession.NewReceiveSourceL());
+ if(err)
+ {
+ __RTP_LOG1("Receive source could not be created %d Returning", err)
+ return;
+ }
+
+ /* See if there is a Pre-Created stream that will accept this PayloadType.
+ If there are no Pre Created stream that accepts this PayloadType just
+ Blindly latch on to the First PreCreated Stream. This behaviour is not
+ really correct but is inline with the S60 RTP Stack behaviour. */
+ TUint32 strmKey = 0;
+ TInt tmpIdx = -1; //Used to remember the last index of a eStreamPreCreated stream
+
+ TUint payloadType = 0;
+ TRAP(err, payloadType=rtpRcvSrc.PayLoadTypeL());
+ if(err == KErrNotFound)
+ {
+ __RTP_LOG1("Payload type was not found", err)
+ }
+
+ __RTP_LOG1("PayloadType %d",payloadType)
+
+ for(int i=0; i<pSelf->iRtpStreamsArr.Count();i++)
+ {
+ if(pSelf->iRtpStreamsArr[i].iState == TRtpStreamInfo::eStreamPreCreated)
+ {
+ /* To make later access easier */
+ tmpIdx = i;
+ }
+
+ /* Try to match the Payload type first */
+ if(pSelf->iRtpStreamsArr[i].iPayloadType == payloadType
+ && pSelf->iRtpStreamsArr[i].iState == TRtpStreamInfo::eStreamPreCreated)
+ {
+ __RTP_LOG1("Found PreCreated Stream at %d",i);
+ /* Ok so there is a PreCreated stream available */
+ pSelf->iRtpStreamsArr[i].iIsRecvStream = ETrue;
+ pSelf->iRtpStreamsArr[i].iRecvSource = rtpRcvSrc;
+ pSelf->iRtpStreamsArr[i].iState = TRtpStreamInfo::eStreamReadyToUse;
+ strmKey = pSelf->iRtpStreamsArr[i].iKey;
+ break;
+ }
+ }
+
+ if(!strmKey && tmpIdx>=0)
+ {
+ __RTP_LOG1("No PreCreated Stream : Using ID %d",tmpIdx)
+ /* Latch on to the unspecified stream */
+ pSelf->iRtpStreamsArr[tmpIdx].iIsRecvStream = ETrue;
+ pSelf->iRtpStreamsArr[tmpIdx].iRecvSource = rtpRcvSrc;
+ pSelf->iRtpStreamsArr[tmpIdx].iState = TRtpStreamInfo::eStreamReadyToUse;
+ strmKey = pSelf->iRtpStreamsArr[tmpIdx].iKey;
+ /* Because we ignored the original user selection */
+ pSelf->iRtpStreamsArr[tmpIdx].iPayloadType = payloadType;
+ }
+
+ if(!strmKey)
+ {
+ __RTP_LOG("No PreCreated Stream : Creating a New Stream")
+ /* Create a new stream */
+ TRtpStreamInfo strmInfo;
+ strmInfo.iKey = Math::Random();
+ strmInfo.iSessionKey = apSessionInfo->iKey;
+ strmInfo.iState = TRtpStreamInfo::eStreamPostCreated;
+ strmInfo.iRecvSource = rtpRcvSrc;
+ TRAPD(error, strmInfo.iPayloadType = rtpRcvSrc.PayLoadTypeL());
+ if(error == KErrNotFound)
+ {
+ __RTP_LOG1("Payload type was not found", error)
+ }
+ strmInfo.iRtpManager = pSelf;
+ /* Append to the Array */
+ pSelf->iRtpStreamsArr.Append(strmInfo); //TODO handle append failures
+ strmKey = strmInfo.iKey;
+ __RTP_LOG1("Session Did not have a PreCreated Stream New StreamID %u",strmInfo.iKey)
+ }
+ /* Get a reference to the Strm from Array for Callback Registration */
+ TInt idx = pSelf->FindStream(strmKey);
+
+ TRAP_IGNORE(pSelf->RegisterEventsOnRtpRcvSourceL(rtpRcvSrc, &(pSelf->iRtpStreamsArr[idx])));
+ }
+ if(ERtpNewRR == aEvent.Type())
+ {
+ /* Session Level RTCP RR . An Empty RR was received */
+ if(apSessionInfo->iRtcpObserver)
+ {
+ apSessionInfo->iRtcpObserver->RrReceived(apSessionInfo->iKey,aEvent.Status());
+ }
+ }
+
+ if(ENonRtpDataReceived == aEvent.Type())
+ {
+ /* Session Level CB. A non rtp data was received */
+ if(apSessionInfo->iNonRtpDataObserver)
+ {
+ TRAP_IGNORE(pSelf->HandleNonRtpDataL(apSessionInfo));
+ }
+ }
+ if(ENonRtcpDataReceived == aEvent.Type())
+ {
+ /* Session Level CB. A non rtp data was received */
+ if(apSessionInfo->iNonRtpDataObserver)
+ {
+ __RTP_LOG("CRtpManager::RtpSessionLevelCB");
+ __RTP_LOG("Non rtcp data - issuing non rtp data received callback");
+ TRAP_IGNORE(pSelf->HandleNonRtcpDataL(apSessionInfo));
+ }
+ }
+ }
+
+void CRtpManager::RtpStreamLevelCB(TRtpStreamInfo* apStrmInfo, const TRtpEvent& aEvent)
+ {
+ LOG_FUNC_ENTRY("CRtpManager::RtpStreamLevelCB");
+ __RTP_LOG1("EventType %x",aEvent.Type())
+
+ TInt ret;
+ if(ERtpPacketReceived == aEvent.Type())
+ {
+ /* New Packet Arrived. Issue callback */
+ TRtpRecvHeader rcvHeader;
+ RRtpReceivePacket pkt = apStrmInfo->iRecvSource.Packet();
+ rcvHeader.iMarker = pkt.Marker();
+ rcvHeader.iPadding = 0; //TODO Pading bits are stripped by Stack? Verify
+ rcvHeader.iPayloadType = pkt.PayloadType();
+ rcvHeader.iSeqNum = pkt.SequenceNumber();
+ rcvHeader.iTimestamp = pkt.Timestamp();
+
+ ret = apStrmInfo->iRtpManager->FindSession(apStrmInfo->iSessionKey);
+ ASSERT(ret>=0);
+ if(apStrmInfo->iRtpManager->iRtpSessionArr[ret]->iRtpObserver)
+ {
+ __RTP_LOG("Issuing RtpReceived callback")
+ apStrmInfo->iRtpManager->iRtpSessionArr[ret]->iRtpObserver->RtpPacketReceived(apStrmInfo->iKey,rcvHeader,pkt.Payload());
+ }
+ else
+ {
+ __RTP_LOG("Session Did not have RTP Observer Registered")
+ }
+ pkt.Close();
+ }
+ if(ERtpRR == aEvent.Type())
+ {
+ /* Fetch the information on the RR Received from specif SSRC */
+ ret = apStrmInfo->iRtpManager->FindSession(apStrmInfo->iSessionKey);
+ ASSERT(ret>=0);
+ if(apStrmInfo->iRtpManager->iRtpSessionArr[ret]->iRtcpObserver)
+ {
+ __RTP_LOG("Issuing RtcpRrReceived callback")
+ apStrmInfo->iRtpManager->iRtpSessionArr[ret]->iRtcpObserver->RrReceived(apStrmInfo->iKey, aEvent.Status());
+ }
+ else
+ {
+ __RTP_LOG("Session Did not have RCTP Observer Reqistered")
+ }
+ }
+ if(ERtpSDES == aEvent.Type())
+ {
+ /* Fetch the information on the SDES Received from specif SSRC */
+ ret = apStrmInfo->iRtpManager->FindSession(apStrmInfo->iSessionKey);
+ ASSERT(ret>=0);
+ if(apStrmInfo->iRtpManager->iRtpSessionArr[ret]->iRtcpObserver)
+ {
+ TBuf8<100> cname;
+ TBuf8<100> name;
+ TBuf8<100> email;
+
+ /* Extract the SDES information and pass it up */
+ TRtpSdesParams sdesParams;
+ if(KErrNotFound != apStrmInfo->iRecvSource.GetSDES(1,cname))
+ {
+ sdesParams.iCName.Set(cname);
+ }
+ if(KErrNotFound != apStrmInfo->iRecvSource.GetSDES(2,name))
+ {
+ sdesParams.iUserName.Set(name);
+ }
+ if(KErrNotFound != apStrmInfo->iRecvSource.GetSDES(3,email))
+ {
+ sdesParams.iEmail.Set(name);
+ }
+ __RTP_LOG("Issuing SdesReceived callback")
+ apStrmInfo->iRtpManager->iRtpSessionArr[ret]->iRtcpObserver->SdesReceived(aEvent.Status(),sdesParams);
+ }
+ else
+ {
+ __RTP_LOG("RTCP Observer was not registered. Callback not issued")
+ }
+ }
+ if(ERtpSR == aEvent.Type())
+ {
+ /* Fetch the information on the SR Received from specific SSRC */
+ ret = apStrmInfo->iRtpManager->FindSession(apStrmInfo->iSessionKey);
+ ASSERT(ret>=0);
+ if(apStrmInfo->iRtpManager->iRtpSessionArr[ret]->iRtcpObserver)
+ {
+ RRtcpSRPart srPart(apStrmInfo->iRecvSource.GetSR());
+
+ TTimeStamps timeStamps;
+ srPart.NTPTimestamp(timeStamps.iNTPTimeStampSec, timeStamps.iNTPTimeStampFrac);
+ timeStamps.iTimeStamp = srPart.RTPTimestamp();
+
+ __RTP_LOG("Issuing SrReceived callback")
+ apStrmInfo->iRtpManager->iRtpSessionArr[ret]->iRtcpObserver->SrReceived(apStrmInfo->iKey, apStrmInfo->iRecvSource.SSRC(), timeStamps);
+ }
+ else
+ {
+ __RTP_LOG("RTCP Observer was not registered. Callback not issued")
+ }
+ }
+ if(ERtpAPP == aEvent.Type())
+ {
+ /* Fetch the information on the RR Received from specif SSRC */
+ ret = apStrmInfo->iRtpManager->FindSession(apStrmInfo->iSessionKey);
+ ASSERT(ret>=0);
+ if(apStrmInfo->iRtpManager->iRtpSessionArr[ret]->iRtcpObserver)
+ {
+ TRtcpApp app;
+ TPtrC8 name;
+ TPtrC8 appData;
+ TUint subType;
+
+ apStrmInfo->iRecvSource.GetLastApp(name, appData, subType );
+
+ //Create Tpr8 from TRtcpApp ..Duh!!
+ TPtr8 name1(app.iName,4);
+ TPtr8 appData1(app.iAppData,KMaxRtcpAppData);
+ name1 = name;
+ appData1 = appData;
+ app.iAppDataLen = appData.Length();
+ app.iSubType = subType;
+
+ __RTP_LOG("Issuing SrReceived callback")
+ apStrmInfo->iRtpManager->iRtpSessionArr[ret]->iRtcpObserver->AppReceived(apStrmInfo->iKey, aEvent.Status(),app );
+ }
+ else
+ {
+ __RTP_LOG("RTCP Observer was not registered. Callback not issued")
+ }
+ }
+ }
+
+
+// Decrypting RTP Packet recieved from network
+TInt CRtpSessionInfo::PreRtpProcessing(TDes8 &aRTPPacket)
+ {
+ __RTP_LOG("CRtpSessionInfo::PreRtpProcessing")
+ //SSRC of recieved packet KRtpSSRCOffset (8)
+ const TUint KRtpSSRCOffset = 8;
+ HBufC8 *rtpPacket = NULL;
+ TUint8* packet = const_cast<TUint8*>(aRTPPacket.Ptr());
+ TUint32 ssrc = (*(packet+KRtpSSRCOffset+3))+
+ (*(packet+KRtpSSRCOffset+2)<<8)+
+ (*(packet+KRtpSSRCOffset+1)<<16)+
+ (*(packet+KRtpSSRCOffset)<<24);
+
+ TRAPD(error, rtpPacket = iSRTPSession->UnprotectRTPL(ssrc, aRTPPacket));
+ if(error == KErrNone)
+ {
+ __RTP_LOG("RTP Packet Decrypted sucessfully")
+ aRTPPacket.Copy(rtpPacket->Des());
+ }
+ else
+ {
+ __RTP_LOG("RTP Packet Decrypted Failed")
+ error = KErrCorrupt;
+ }
+ delete rtpPacket;
+ return error;
+ }
+
+// Encrypting RTP packet before sending
+void CRtpSessionInfo::PostRtpProcessing(TDes8 &aRTPPacket)
+ {
+ __RTP_LOG("CRtpSessionInfo::PostRtpProcessing")
+ //SSRC of recieved packet KRtpSSRCOffset (8)
+ const TUint KRtpSSRCOffset = 8;
+ HBufC8 *rtpPacket = NULL;
+ TUint8* packet = const_cast<TUint8*>(aRTPPacket.Ptr());
+ TUint32 ssrc = (*(packet+KRtpSSRCOffset+3))+
+ (*(packet+KRtpSSRCOffset+2)<<8)+
+ (*(packet+KRtpSSRCOffset+1)<<16)+
+ (*(packet+KRtpSSRCOffset)<<24);
+
+ TRAPD(error, rtpPacket = iSRTPSession->ProtectRTPL(ssrc, aRTPPacket));
+ if(error != KErrNone)
+ {
+ __RTP_LOG("RTP Packet was not encrypted")
+ aRTPPacket.FillZ();
+ }
+ else
+ {
+ __RTP_LOG("RTP Packet was encrypted successfully")
+ aRTPPacket.Copy(rtpPacket->Des());
+ delete rtpPacket;
+ }
+ }
+
+// DeCrypting RTCP Packet recieved from network
+TInt CRtpSessionInfo::PreRtcpProcessing(TDes8 &aRTCPPacket)
+ {
+ __RTP_LOG("CRtpSessionInfo::PreRtcpProcessing")
+ //SSRC of recieved packet KRtcpSSRCOffset (4)
+ const TUint KRtcpSSRCOffset = 4;
+ HBufC8 *rtcpPacket = NULL;
+ TUint8* packet = const_cast<TUint8*>(aRTCPPacket.Ptr());
+ TUint32 ssrc = (*(packet+KRtcpSSRCOffset+3))+
+ (*(packet+KRtcpSSRCOffset+2)<<8)+
+ (*(packet+KRtcpSSRCOffset+1)<<16)+
+ (*(packet+KRtcpSSRCOffset)<<24);
+
+ TRAPD(error, rtcpPacket = iSRTPSession->UnprotectRTCPL(ssrc, aRTCPPacket));
+ if(error == KErrNone)
+ {
+ __RTP_LOG("RTCP Packet Decrypted sucessfully")
+ aRTCPPacket.Copy(rtcpPacket->Des());
+ }
+ else
+ {
+ __RTP_LOG("RTCP Packet Decrypted Failed")
+ error = KErrCorrupt;
+ }
+ delete rtcpPacket;
+ return error;
+ }
+
+// Encrypting RTCP Packet before sending
+void CRtpSessionInfo::PostRtcpProcessing(TDes8 &aRTCPPacket)
+ {
+ __RTP_LOG("CRtpSessionInfo::PostRtcpProcessing")
+ //SSRC of recieved packet KRtcpSSRCOffset (4)
+ const TUint KRtcpSSRCOffset = 4;
+ HBufC8 *rtcpPacket = NULL;
+ // Assign a pointer to a packet
+ TUint8* packet = const_cast<TUint8*>(aRTCPPacket.Ptr());
+ TUint32 ssrc = (*(packet+KRtcpSSRCOffset+3))+
+ (*(packet+KRtcpSSRCOffset+2)<<8)+
+ (*(packet+KRtcpSSRCOffset+1)<<16)+
+ (*(packet+KRtcpSSRCOffset)<<24);
+
+ TRAPD(error, rtcpPacket = iSRTPSession->ProtectRTCPL(ssrc, aRTCPPacket));
+ if(error != KErrNone)
+ {
+ __RTP_LOG("RCTP Packet was not encrypted")
+ aRTCPPacket.FillZ();
+ }
+ else
+ {
+ __RTP_LOG("RCTP Packet was encrypted Successfully")
+ aRTCPPacket.Copy(rtcpPacket->Des());
+ delete rtcpPacket;
+ }
+ }
+