realtimenetprots/sipfw/ClientResolver/Resolver/src/CSIPClientDataParser.cpp
changeset 0 307788aac0a8
equal deleted inserted replaced
-1:000000000000 0:307788aac0a8
       
     1 // Copyright (c) 2005-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 // Name          : CSIPClientDataParser.cpp
       
    15 // Part of       : SIP Client Resolver
       
    16 // Version       : 1.0
       
    17 //
       
    18 
       
    19 
       
    20 
       
    21 #include "CSIPClientDataParser.h"
       
    22 #include "CSIPClientData.h"
       
    23 #include "SIPHeaderLookup.h"
       
    24 #include "sipacceptcontactheader.h"
       
    25 #include "CSIPFeatureSet.h"
       
    26 #include "sdpdocument.h"
       
    27 #include "sdpmediafield.h"
       
    28 #include "sdpfmtattributefield.h"
       
    29 #include "sdpattributefield.h"
       
    30 #include "sipstrings.h"
       
    31 #include "sipstrconsts.h"
       
    32 
       
    33 
       
    34 // Constants for our XML DTD
       
    35 _LIT8( KTagSIPClient, "SIP_CLIENT" );
       
    36 _LIT8( KTagSIPHeaders, "SIP_HEADERS" );
       
    37 _LIT8( KTagSDPLines, "SDP_LINES" );
       
    38 _LIT8( KTagLine, "LINE" );
       
    39 _LIT8( KTagLineM, "m" );
       
    40 _LIT8( KTagRtpmap, "RTPMAP" );
       
    41 _LIT8( KTagMediaAttribute, "MEDIA_ATTRIBUTE" );
       
    42 _LIT8( KTagAccept, "ACCEPT" );
       
    43 _LIT8( KTagAllowStarting, "ALLOW_STARTING" );
       
    44 _LIT8( KTagAcceptContact, "ACCEPT_CONTACT" );
       
    45 _LIT8( KTagAllowEvents, "ALLOW_EVENTS" );
       
    46 _LIT8( KTagYes, "YES" );
       
    47 
       
    48 _LIT8( KMimeTypeXml, "text/xml" );
       
    49 _LIT8( KSdpMediaFieldStart, "m=" );
       
    50 _LIT8( KSdpAttributeFieldStart, "a=" );
       
    51 _LIT8( KRtpmapName, "rtpmap" );
       
    52 _LIT8( KCrLf, "\r\n" );
       
    53 
       
    54 const TInt KSdpLineAttrCount( 2 );
       
    55 
       
    56 // -----------------------------------------------------------------------------
       
    57 // CSIPClientDataParser::NewL
       
    58 // -----------------------------------------------------------------------------
       
    59 //
       
    60 CSIPClientDataParser* CSIPClientDataParser::NewL()
       
    61 	{
       
    62 	CSIPClientDataParser* self = new( ELeave ) CSIPClientDataParser;
       
    63 	CleanupStack::PushL( self );
       
    64 	self->ConstructL();
       
    65 	CleanupStack::Pop( self );
       
    66 	return self;
       
    67 	}
       
    68 
       
    69 // -----------------------------------------------------------------------------
       
    70 // CSIPClientDataParser::CSIPClientDataParser
       
    71 // -----------------------------------------------------------------------------
       
    72 //
       
    73 CSIPClientDataParser::CSIPClientDataParser() 
       
    74  : iSIPHeaderLookupOpened (EFalse)
       
    75 	{
       
    76 	}
       
    77 
       
    78 // -----------------------------------------------------------------------------
       
    79 // CSIPClientDataParser::ConstructL
       
    80 // -----------------------------------------------------------------------------
       
    81 //
       
    82 void CSIPClientDataParser::ConstructL()
       
    83 	{
       
    84 	iParser = Xml::CParser::NewL( KMimeTypeXml, *this );
       
    85 	SIPHeaderLookup::OpenL();
       
    86 	iSIPHeaderLookupOpened = ETrue;
       
    87 	
       
    88     // Initialize XML strings
       
    89     RStringPool& stringPool = iParser->StringPool();
       
    90     iTagSIPClient = stringPool.OpenStringL(KTagSIPClient);
       
    91     iTagSIPHeaders = stringPool.OpenStringL(KTagSIPHeaders);
       
    92     iTagSDPLines = stringPool.OpenStringL(KTagSDPLines);
       
    93     iTagLine = stringPool.OpenStringL(KTagLine);
       
    94     iTagLineM = stringPool.OpenStringL(KTagLineM);
       
    95     iTagRtpmap = stringPool.OpenStringL(KTagRtpmap);
       
    96     iTagMediaAttribute = stringPool.OpenStringL(KTagMediaAttribute);
       
    97     iTagAccept = stringPool.OpenStringL(KTagAccept);
       
    98     iTagAllowStarting = stringPool.OpenStringL(KTagAllowStarting);
       
    99     iTagAcceptContact = stringPool.OpenStringL(KTagAcceptContact);
       
   100     iTagAllowEvents = stringPool.OpenStringL(KTagAllowEvents);
       
   101     iTagYes = stringPool.OpenStringL(KTagYes);
       
   102     
       
   103 	// Initialize parser states
       
   104 	iStateTransitions.AppendL(
       
   105 	    TStateTransition(iTagSIPClient,EInit,ESIPClient));
       
   106 	    
       
   107 	iStateTransitions.AppendL(
       
   108 	    TStateTransition(iTagSIPClient,ESIPClient,EInit,EFalse));
       
   109 	
       
   110 	iStateTransitions.AppendL(
       
   111 	    TStateTransition(iTagSIPHeaders,ESIPClient,ESIPHeaders));
       
   112 	
       
   113 	iStateTransitions.AppendL(
       
   114 	    TStateTransition(iTagSIPHeaders,ESIPHeaders,ESIPClient,EFalse));	
       
   115 
       
   116 	iStateTransitions.AppendL(
       
   117 	    TStateTransition(iTagAccept,ESIPHeaders,EAccept));
       
   118 	
       
   119 	iStateTransitions.AppendL(
       
   120 	    TStateTransition(iTagAccept,EAccept,ESIPHeaders,EFalse));
       
   121 	
       
   122 	iStateTransitions.AppendL(
       
   123 	    TStateTransition(iTagAcceptContact,ESIPHeaders,EAcceptContact));
       
   124 	
       
   125 	iStateTransitions.AppendL(
       
   126 	    TStateTransition(iTagAcceptContact,EAcceptContact,ESIPHeaders,EFalse));
       
   127 	
       
   128 	iStateTransitions.AppendL(
       
   129 	    TStateTransition(iTagAllowEvents,ESIPHeaders,EAllowEvents));
       
   130 	    
       
   131 	iStateTransitions.AppendL(
       
   132 	    TStateTransition(iTagAllowEvents,EAllowEvents,ESIPHeaders,EFalse));
       
   133 	
       
   134 	iStateTransitions.AppendL(
       
   135 	    TStateTransition(iTagSDPLines,ESIPClient,ESDPLines));
       
   136 
       
   137 	iStateTransitions.AppendL(
       
   138 	    TStateTransition(iTagSDPLines,ESDPLines,ESIPClient,EFalse));
       
   139 	
       
   140 	iStateTransitions.AppendL(
       
   141 	    TStateTransition(iTagLine,ESDPLines,ELine));
       
   142 	
       
   143 	iStateTransitions.AppendL(
       
   144 	    TStateTransition(iTagLine,ELine,ESDPLines,EFalse));
       
   145 	    
       
   146 	iStateTransitions.AppendL(
       
   147 	    TStateTransition(iTagRtpmap,ELine,ERtpmap));
       
   148 	    
       
   149 	iStateTransitions.AppendL(
       
   150 	    TStateTransition(iTagRtpmap,ERtpmap,ELine,EFalse));
       
   151 	    
       
   152 	iStateTransitions.AppendL(
       
   153 	    TStateTransition(iTagMediaAttribute,ELine,EMediaAttribute));
       
   154 	    
       
   155 	iStateTransitions.AppendL(
       
   156 	    TStateTransition(iTagMediaAttribute,EMediaAttribute,ELine,EFalse));	    	    
       
   157 	}
       
   158 
       
   159 // -----------------------------------------------------------------------------
       
   160 // CSIPClientDataParser::~CSIPClientDataParser
       
   161 // -----------------------------------------------------------------------------
       
   162 //
       
   163 CSIPClientDataParser::~CSIPClientDataParser()
       
   164 	{
       
   165 	iStateTransitions.Close();
       
   166     iTagYes.Close();
       
   167     iTagAllowEvents.Close();
       
   168     iTagAcceptContact.Close();
       
   169     iTagAllowStarting.Close();
       
   170     iTagAccept.Close();
       
   171     iTagMediaAttribute.Close();
       
   172     iTagLineM.Close();
       
   173     iTagRtpmap.Close();
       
   174     iTagLine.Close();
       
   175     iTagSDPLines.Close();
       
   176     iTagSIPHeaders.Close();
       
   177     iTagSIPClient.Close();
       
   178 	if( iSIPHeaderLookupOpened )
       
   179 		{
       
   180 		SIPHeaderLookup::Close();
       
   181 		}		
       
   182 	delete iParser;
       
   183 	}
       
   184 
       
   185 // -----------------------------------------------------------------------------
       
   186 // CSIPClientDataParser::ParseL
       
   187 // -----------------------------------------------------------------------------
       
   188 //
       
   189 void CSIPClientDataParser::ParseL ( CSIPClientData* aClientData,
       
   190 								    const TDesC8& aXmlDocument )
       
   191 	{
       
   192     iState = EInit;
       
   193 	iClientData = aClientData;
       
   194 
       
   195 	// Parse the specified document into iClientData
       
   196 	Xml::ParseL( *iParser, aXmlDocument );
       
   197 
       
   198 	iClientData = NULL;
       
   199 	}
       
   200 
       
   201 // -----------------------------------------------------------------------------
       
   202 // CSIPClientDataParser::OnStartElementL
       
   203 // -----------------------------------------------------------------------------
       
   204 //
       
   205 void CSIPClientDataParser::OnStartElementL(
       
   206 									const Xml::RTagInfo& aElement,
       
   207 									const Xml::RAttributeArray& aAttributes,
       
   208 									TInt /*aErrorCode*/ )
       
   209 	{
       
   210 	// Get element name (e.g. "SIP_CLIENT") and change state (Enter)
       
   211 	ChangeStateL( aElement.LocalName(), ETrue );
       
   212 
       
   213 	switch( iState )
       
   214 		{
       
   215 		case ESIPClient:
       
   216 			{
       
   217 			HandleSIPClientL( aAttributes );
       
   218 			break;
       
   219 			}
       
   220 		case EAccept:
       
   221 			{
       
   222 			HandleSIPHeaderL( 
       
   223                 SIPStrings::StringF(SipStrConsts::EAcceptHeader), 
       
   224                 aAttributes );
       
   225 			break;
       
   226 			}
       
   227         case EAcceptContact:
       
   228             {
       
   229             HandleSIPHeaderL(
       
   230                 SIPStrings::StringF(SipStrConsts::EAcceptContactHeader), 
       
   231                 aAttributes );
       
   232             break;
       
   233             }
       
   234         case EAllowEvents:
       
   235             {
       
   236             HandleSIPHeaderL(
       
   237                 SIPStrings::StringF(SipStrConsts::EAllowEventsHeader), 
       
   238                 aAttributes );
       
   239             break;
       
   240             }
       
   241 		case ELine:
       
   242 			{
       
   243 			HandleSdpLineL( aAttributes );
       
   244 			break;
       
   245 			}
       
   246 		case ERtpmap:
       
   247 			{
       
   248 			HandleRtpmapL( aAttributes );
       
   249 			break;
       
   250 			}
       
   251 		case EMediaAttribute:
       
   252 			{
       
   253 			HandleMediaAttributeL( aAttributes );
       
   254 			break;
       
   255 			}
       
   256 		default:
       
   257 			{
       
   258 			// do nothing;
       
   259 			break;
       
   260 			}
       
   261 		}
       
   262 	}
       
   263 
       
   264 // -----------------------------------------------------------------------------
       
   265 // CSIPClientDataParser::OnEndElementL
       
   266 // -----------------------------------------------------------------------------
       
   267 //
       
   268 void CSIPClientDataParser::OnEndElementL(
       
   269 									const Xml::RTagInfo& aElement,
       
   270 									TInt /*aErrorCode*/ )
       
   271 	{
       
   272 	// Get element name (e.g. "SIP_CLIENT") and change state (Exit)
       
   273 	ChangeStateL( aElement.LocalName(), EFalse );
       
   274 	}
       
   275 
       
   276 // -----------------------------------------------------------------------------
       
   277 // CSIPClientDataParser::ChangeStateL
       
   278 // -----------------------------------------------------------------------------
       
   279 //
       
   280 void CSIPClientDataParser::ChangeStateL( const RString& aElementName,
       
   281 										 TBool aEnter )
       
   282 	{
       
   283 	// Try to find a matching entry from the transitions table
       
   284 	TInt count = iStateTransitions.Count();
       
   285 	for( TInt i = 0; i < count; i++ )
       
   286 		{
       
   287 		const TStateTransition& transition = iStateTransitions[ i ];
       
   288 		if( ( iState == transition.iState ) &&
       
   289 			( aElementName == transition.iTag ) &&
       
   290 			( aEnter == transition.iEnter ) )
       
   291 			{
       
   292 			// Match found, do transition
       
   293 			iState = transition.iNextState;
       
   294 			return;
       
   295 			}
       
   296 		}
       
   297 
       
   298 	// No match was found, report error
       
   299 	User::Leave( KErrCorrupt );
       
   300 	}
       
   301 
       
   302 // -----------------------------------------------------------------------------
       
   303 // CSIPClientDataParser::HandleSIPClientL
       
   304 // -----------------------------------------------------------------------------
       
   305 //
       
   306 void CSIPClientDataParser::HandleSIPClientL(
       
   307     const Xml::RAttributeArray& aAttributes )
       
   308 	{
       
   309 	// Verify that we have correct number of attributes
       
   310 	__ASSERT_ALWAYS( aAttributes.Count() == 1, User::Leave( KErrCorrupt ) );
       
   311 	
       
   312 	// Verify that we have the correct attributes
       
   313 	const RString& allowName = aAttributes[ 0 ].Attribute().LocalName();
       
   314 	const RString& allowValue = aAttributes[ 0 ].Value();
       
   315 	if( allowName != iTagAllowStarting )
       
   316 		{
       
   317 		User::Leave( KErrCorrupt );
       
   318 		}
       
   319 	iClientData->SetAllowStarting( ( allowValue == iTagYes ) );
       
   320 	}
       
   321 
       
   322 // -----------------------------------------------------------------------------
       
   323 // CSIPClientDataParser::HandleSIPHeaderL
       
   324 // -----------------------------------------------------------------------------
       
   325 //
       
   326 void CSIPClientDataParser::HandleSIPHeaderL(
       
   327     RStringF aHeaderName,
       
   328     const Xml::RAttributeArray& aAttributes )
       
   329 	{
       
   330 	// Verify that we have correct number of attributes
       
   331 	if( aAttributes.Count() != 1 )
       
   332 		{
       
   333 		User::Leave( KErrCorrupt );
       
   334 		}
       
   335 
       
   336 	// Read header value
       
   337 	const RString& value = aAttributes[ 0 ].Value();
       
   338 
       
   339 	// Create SIP header object
       
   340 	RPointerArray< CSIPHeaderBase > headers = 
       
   341 	    SIPHeaderLookup::CreateHeaderL( aHeaderName, value.DesC() );
       
   342 	// Add created headers to ClientData
       
   343 	CSIPHeaderBase::PushLC( &headers );
       
   344 	while( headers.Count() > 0 )
       
   345 		{
       
   346 		CSIPHeaderBase* header = headers[ 0 ];
       
   347 		if ( header->Name() == 
       
   348 		     SIPStrings::StringF(SipStrConsts::EAcceptContactHeader) )
       
   349 		    {
       
   350 		    CSIPAcceptContactHeader* acceptContact = 
       
   351 		        static_cast< CSIPAcceptContactHeader* >( header );
       
   352 		    iClientData->SIPFeatureSet().AddFeaturesL( *acceptContact );
       
   353 		    delete header;
       
   354 		    }
       
   355 		else
       
   356 		    {
       
   357 		    iClientData->SIPHeaders().AppendL( header );
       
   358 		    }
       
   359 		headers.Remove( 0 );
       
   360 		}
       
   361 	CleanupStack::PopAndDestroy(); // headers
       
   362 	}
       
   363 
       
   364 // -----------------------------------------------------------------------------
       
   365 // CSIPClientDataParser::HandleSdpLineL
       
   366 // -----------------------------------------------------------------------------
       
   367 //
       
   368 void CSIPClientDataParser::HandleSdpLineL(
       
   369     const Xml::RAttributeArray& aAttributes )
       
   370 	{
       
   371 	// Verify that we have correct number of attributes
       
   372 	if( aAttributes.Count() != KSdpLineAttrCount )
       
   373 		{
       
   374 		User::Leave( KErrCorrupt );
       
   375 		}
       
   376 
       
   377 	// Verify that we have the correct attribute(s)
       
   378 	if( aAttributes[ 0 ].Value() != iTagLineM )
       
   379 		{
       
   380 		User::Leave( KErrCorrupt );
       
   381 		}
       
   382 
       
   383 	// Get attribute and convert to a form compatible with CSdpMediaField
       
   384 	// (basically just surround the string with "m=" and "\r\n")
       
   385 	TPtrC8 value( aAttributes[ 1 ].Value().DesC() );	                        
       
   386 	HBufC8* mediaFieldBuf = CreateSdpFieldBufLC( KSdpMediaFieldStart, value );
       
   387 
       
   388 	// Read and decode SDP media field to ClientData
       
   389 	CSdpMediaField* mediaField = CSdpMediaField::DecodeLC( *mediaFieldBuf );
       
   390 	iClientData->AddMediaFieldL( mediaField );
       
   391 	CleanupStack::Pop( mediaField );
       
   392 	
       
   393 	CleanupStack::PopAndDestroy( mediaFieldBuf );
       
   394 	}
       
   395 
       
   396 // -----------------------------------------------------------------------------
       
   397 // CSIPClientDataParser::HandleRtpmapL
       
   398 // -----------------------------------------------------------------------------
       
   399 //	
       
   400 void CSIPClientDataParser::HandleRtpmapL(
       
   401     const Xml::RAttributeArray& aAttributes )
       
   402     {
       
   403     CSdpDocument& sdp = iClientData->SdpDocument();
       
   404     if( aAttributes.Count() != 1 || sdp.MediaFields().Count() == 0 )
       
   405         {
       
   406         User::Leave( KErrCorrupt );
       
   407         }
       
   408         
       
   409 	// Get attribute and convert to a form compatible 
       
   410 	// with CSdpfmtAttributeField
       
   411 	// (basically just surround the string with "a=" and "\r\n")
       
   412 	TPtrC8 value( aAttributes[ 0 ].Value().DesC() );
       
   413 	HBufC8* fieldBuf = CreateSdpFieldBufLC( KSdpAttributeFieldStart, value );
       
   414 	       
       
   415 	// Decode and add rtpmap attribute field
       
   416     CSdpFmtAttributeField* attributeField = 
       
   417         CSdpFmtAttributeField::DecodeL( *fieldBuf );
       
   418     CleanupStack::PopAndDestroy( fieldBuf );
       
   419     CleanupStack::PushL( attributeField );    
       
   420         
       
   421     if( attributeField->Attribute().DesC().Compare( KRtpmapName ) != 0 )
       
   422         {
       
   423         User::Leave( KErrCorrupt );
       
   424         }
       
   425     
       
   426     // Add the rtpmap-attribute to the last added media field
       
   427     const TInt lastIndex = sdp.MediaFields().Count()-1;
       
   428     CSdpMediaField* lastMediaField = sdp.MediaFields()[ lastIndex ];
       
   429     lastMediaField->FormatAttributeFields().AppendL( attributeField );
       
   430     
       
   431     CleanupStack::Pop( attributeField );
       
   432     }
       
   433 
       
   434 // -----------------------------------------------------------------------------
       
   435 // CSIPClientDataParser::HandleMediaAttributeL
       
   436 // -----------------------------------------------------------------------------
       
   437 //
       
   438 void CSIPClientDataParser::HandleMediaAttributeL( 
       
   439     const Xml::RAttributeArray& aAttributes )
       
   440     {
       
   441     CSdpDocument& sdp = iClientData->SdpDocument();
       
   442     if( aAttributes.Count() != 1 || sdp.MediaFields().Count() == 0 )
       
   443         {
       
   444         User::Leave( KErrCorrupt );
       
   445         }
       
   446         
       
   447 	// Get attribute and convert to a form compatible with CSdpAttributeField
       
   448 	// (basically just surround the string with "a=" and "\r\n")
       
   449 	TPtrC8 value( aAttributes[ 0 ].Value().DesC() );
       
   450 	HBufC8* fieldBuf = CreateSdpFieldBufLC( KSdpAttributeFieldStart, value );
       
   451 	       
       
   452 	// Decode and add attribute field
       
   453     CSdpAttributeField* attributeField = 
       
   454         CSdpAttributeField::DecodeL( *fieldBuf );
       
   455     CleanupStack::PopAndDestroy( fieldBuf );
       
   456     CleanupStack::PushL( attributeField );
       
   457     
       
   458     // Add the attribute to the last added media field
       
   459     const TInt lastIndex = sdp.MediaFields().Count()-1;
       
   460     CSdpMediaField* lastMediaField = sdp.MediaFields()[ lastIndex ];
       
   461     lastMediaField->AttributeFields().AppendL( attributeField );
       
   462     
       
   463     CleanupStack::Pop( attributeField );    
       
   464     }
       
   465 
       
   466 // -----------------------------------------------------------------------------
       
   467 // CSIPClientDataParser::CreateSdpFieldBufLC
       
   468 // -----------------------------------------------------------------------------
       
   469 //  
       
   470 HBufC8* CSIPClientDataParser::CreateSdpFieldBufLC(
       
   471     const TDesC8& aFieldStart,
       
   472     const TDesC8& aValue )
       
   473     {
       
   474 	TInt bufLength = aFieldStart.Length() + aValue.Length() + KCrLf().Length();
       
   475 	HBufC8* buf = HBufC8::NewLC( bufLength );
       
   476 	TPtr8 bufPtr = buf->Des();
       
   477 	bufPtr.Copy( aFieldStart );
       
   478 	bufPtr.Append( aValue );
       
   479 	bufPtr.Append( KCrLf );
       
   480 	return buf; 
       
   481     }