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