--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/sipfw/ClientResolver/Resolver/src/CSIPClientDataParser.cpp Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,481 @@
+// Copyright (c) 2005-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:
+// Name : CSIPClientDataParser.cpp
+// Part of : SIP Client Resolver
+// Version : 1.0
+//
+
+
+
+#include "CSIPClientDataParser.h"
+#include "CSIPClientData.h"
+#include "SIPHeaderLookup.h"
+#include "sipacceptcontactheader.h"
+#include "CSIPFeatureSet.h"
+#include "sdpdocument.h"
+#include "sdpmediafield.h"
+#include "sdpfmtattributefield.h"
+#include "sdpattributefield.h"
+#include "sipstrings.h"
+#include "sipstrconsts.h"
+
+
+// Constants for our XML DTD
+_LIT8( KTagSIPClient, "SIP_CLIENT" );
+_LIT8( KTagSIPHeaders, "SIP_HEADERS" );
+_LIT8( KTagSDPLines, "SDP_LINES" );
+_LIT8( KTagLine, "LINE" );
+_LIT8( KTagLineM, "m" );
+_LIT8( KTagRtpmap, "RTPMAP" );
+_LIT8( KTagMediaAttribute, "MEDIA_ATTRIBUTE" );
+_LIT8( KTagAccept, "ACCEPT" );
+_LIT8( KTagAllowStarting, "ALLOW_STARTING" );
+_LIT8( KTagAcceptContact, "ACCEPT_CONTACT" );
+_LIT8( KTagAllowEvents, "ALLOW_EVENTS" );
+_LIT8( KTagYes, "YES" );
+
+_LIT8( KMimeTypeXml, "text/xml" );
+_LIT8( KSdpMediaFieldStart, "m=" );
+_LIT8( KSdpAttributeFieldStart, "a=" );
+_LIT8( KRtpmapName, "rtpmap" );
+_LIT8( KCrLf, "\r\n" );
+
+const TInt KSdpLineAttrCount( 2 );
+
+// -----------------------------------------------------------------------------
+// CSIPClientDataParser::NewL
+// -----------------------------------------------------------------------------
+//
+CSIPClientDataParser* CSIPClientDataParser::NewL()
+ {
+ CSIPClientDataParser* self = new( ELeave ) CSIPClientDataParser;
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CSIPClientDataParser::CSIPClientDataParser
+// -----------------------------------------------------------------------------
+//
+CSIPClientDataParser::CSIPClientDataParser()
+ : iSIPHeaderLookupOpened (EFalse)
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CSIPClientDataParser::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CSIPClientDataParser::ConstructL()
+ {
+ iParser = Xml::CParser::NewL( KMimeTypeXml, *this );
+ SIPHeaderLookup::OpenL();
+ iSIPHeaderLookupOpened = ETrue;
+
+ // Initialize XML strings
+ RStringPool& stringPool = iParser->StringPool();
+ iTagSIPClient = stringPool.OpenStringL(KTagSIPClient);
+ iTagSIPHeaders = stringPool.OpenStringL(KTagSIPHeaders);
+ iTagSDPLines = stringPool.OpenStringL(KTagSDPLines);
+ iTagLine = stringPool.OpenStringL(KTagLine);
+ iTagLineM = stringPool.OpenStringL(KTagLineM);
+ iTagRtpmap = stringPool.OpenStringL(KTagRtpmap);
+ iTagMediaAttribute = stringPool.OpenStringL(KTagMediaAttribute);
+ iTagAccept = stringPool.OpenStringL(KTagAccept);
+ iTagAllowStarting = stringPool.OpenStringL(KTagAllowStarting);
+ iTagAcceptContact = stringPool.OpenStringL(KTagAcceptContact);
+ iTagAllowEvents = stringPool.OpenStringL(KTagAllowEvents);
+ iTagYes = stringPool.OpenStringL(KTagYes);
+
+ // Initialize parser states
+ iStateTransitions.AppendL(
+ TStateTransition(iTagSIPClient,EInit,ESIPClient));
+
+ iStateTransitions.AppendL(
+ TStateTransition(iTagSIPClient,ESIPClient,EInit,EFalse));
+
+ iStateTransitions.AppendL(
+ TStateTransition(iTagSIPHeaders,ESIPClient,ESIPHeaders));
+
+ iStateTransitions.AppendL(
+ TStateTransition(iTagSIPHeaders,ESIPHeaders,ESIPClient,EFalse));
+
+ iStateTransitions.AppendL(
+ TStateTransition(iTagAccept,ESIPHeaders,EAccept));
+
+ iStateTransitions.AppendL(
+ TStateTransition(iTagAccept,EAccept,ESIPHeaders,EFalse));
+
+ iStateTransitions.AppendL(
+ TStateTransition(iTagAcceptContact,ESIPHeaders,EAcceptContact));
+
+ iStateTransitions.AppendL(
+ TStateTransition(iTagAcceptContact,EAcceptContact,ESIPHeaders,EFalse));
+
+ iStateTransitions.AppendL(
+ TStateTransition(iTagAllowEvents,ESIPHeaders,EAllowEvents));
+
+ iStateTransitions.AppendL(
+ TStateTransition(iTagAllowEvents,EAllowEvents,ESIPHeaders,EFalse));
+
+ iStateTransitions.AppendL(
+ TStateTransition(iTagSDPLines,ESIPClient,ESDPLines));
+
+ iStateTransitions.AppendL(
+ TStateTransition(iTagSDPLines,ESDPLines,ESIPClient,EFalse));
+
+ iStateTransitions.AppendL(
+ TStateTransition(iTagLine,ESDPLines,ELine));
+
+ iStateTransitions.AppendL(
+ TStateTransition(iTagLine,ELine,ESDPLines,EFalse));
+
+ iStateTransitions.AppendL(
+ TStateTransition(iTagRtpmap,ELine,ERtpmap));
+
+ iStateTransitions.AppendL(
+ TStateTransition(iTagRtpmap,ERtpmap,ELine,EFalse));
+
+ iStateTransitions.AppendL(
+ TStateTransition(iTagMediaAttribute,ELine,EMediaAttribute));
+
+ iStateTransitions.AppendL(
+ TStateTransition(iTagMediaAttribute,EMediaAttribute,ELine,EFalse));
+ }
+
+// -----------------------------------------------------------------------------
+// CSIPClientDataParser::~CSIPClientDataParser
+// -----------------------------------------------------------------------------
+//
+CSIPClientDataParser::~CSIPClientDataParser()
+ {
+ iStateTransitions.Close();
+ iTagYes.Close();
+ iTagAllowEvents.Close();
+ iTagAcceptContact.Close();
+ iTagAllowStarting.Close();
+ iTagAccept.Close();
+ iTagMediaAttribute.Close();
+ iTagLineM.Close();
+ iTagRtpmap.Close();
+ iTagLine.Close();
+ iTagSDPLines.Close();
+ iTagSIPHeaders.Close();
+ iTagSIPClient.Close();
+ if( iSIPHeaderLookupOpened )
+ {
+ SIPHeaderLookup::Close();
+ }
+ delete iParser;
+ }
+
+// -----------------------------------------------------------------------------
+// CSIPClientDataParser::ParseL
+// -----------------------------------------------------------------------------
+//
+void CSIPClientDataParser::ParseL ( CSIPClientData* aClientData,
+ const TDesC8& aXmlDocument )
+ {
+ iState = EInit;
+ iClientData = aClientData;
+
+ // Parse the specified document into iClientData
+ Xml::ParseL( *iParser, aXmlDocument );
+
+ iClientData = NULL;
+ }
+
+// -----------------------------------------------------------------------------
+// CSIPClientDataParser::OnStartElementL
+// -----------------------------------------------------------------------------
+//
+void CSIPClientDataParser::OnStartElementL(
+ const Xml::RTagInfo& aElement,
+ const Xml::RAttributeArray& aAttributes,
+ TInt /*aErrorCode*/ )
+ {
+ // Get element name (e.g. "SIP_CLIENT") and change state (Enter)
+ ChangeStateL( aElement.LocalName(), ETrue );
+
+ switch( iState )
+ {
+ case ESIPClient:
+ {
+ HandleSIPClientL( aAttributes );
+ break;
+ }
+ case EAccept:
+ {
+ HandleSIPHeaderL(
+ SIPStrings::StringF(SipStrConsts::EAcceptHeader),
+ aAttributes );
+ break;
+ }
+ case EAcceptContact:
+ {
+ HandleSIPHeaderL(
+ SIPStrings::StringF(SipStrConsts::EAcceptContactHeader),
+ aAttributes );
+ break;
+ }
+ case EAllowEvents:
+ {
+ HandleSIPHeaderL(
+ SIPStrings::StringF(SipStrConsts::EAllowEventsHeader),
+ aAttributes );
+ break;
+ }
+ case ELine:
+ {
+ HandleSdpLineL( aAttributes );
+ break;
+ }
+ case ERtpmap:
+ {
+ HandleRtpmapL( aAttributes );
+ break;
+ }
+ case EMediaAttribute:
+ {
+ HandleMediaAttributeL( aAttributes );
+ break;
+ }
+ default:
+ {
+ // do nothing;
+ break;
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CSIPClientDataParser::OnEndElementL
+// -----------------------------------------------------------------------------
+//
+void CSIPClientDataParser::OnEndElementL(
+ const Xml::RTagInfo& aElement,
+ TInt /*aErrorCode*/ )
+ {
+ // Get element name (e.g. "SIP_CLIENT") and change state (Exit)
+ ChangeStateL( aElement.LocalName(), EFalse );
+ }
+
+// -----------------------------------------------------------------------------
+// CSIPClientDataParser::ChangeStateL
+// -----------------------------------------------------------------------------
+//
+void CSIPClientDataParser::ChangeStateL( const RString& aElementName,
+ TBool aEnter )
+ {
+ // Try to find a matching entry from the transitions table
+ TInt count = iStateTransitions.Count();
+ for( TInt i = 0; i < count; i++ )
+ {
+ const TStateTransition& transition = iStateTransitions[ i ];
+ if( ( iState == transition.iState ) &&
+ ( aElementName == transition.iTag ) &&
+ ( aEnter == transition.iEnter ) )
+ {
+ // Match found, do transition
+ iState = transition.iNextState;
+ return;
+ }
+ }
+
+ // No match was found, report error
+ User::Leave( KErrCorrupt );
+ }
+
+// -----------------------------------------------------------------------------
+// CSIPClientDataParser::HandleSIPClientL
+// -----------------------------------------------------------------------------
+//
+void CSIPClientDataParser::HandleSIPClientL(
+ const Xml::RAttributeArray& aAttributes )
+ {
+ // Verify that we have correct number of attributes
+ __ASSERT_ALWAYS( aAttributes.Count() == 1, User::Leave( KErrCorrupt ) );
+
+ // Verify that we have the correct attributes
+ const RString& allowName = aAttributes[ 0 ].Attribute().LocalName();
+ const RString& allowValue = aAttributes[ 0 ].Value();
+ if( allowName != iTagAllowStarting )
+ {
+ User::Leave( KErrCorrupt );
+ }
+ iClientData->SetAllowStarting( ( allowValue == iTagYes ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CSIPClientDataParser::HandleSIPHeaderL
+// -----------------------------------------------------------------------------
+//
+void CSIPClientDataParser::HandleSIPHeaderL(
+ RStringF aHeaderName,
+ const Xml::RAttributeArray& aAttributes )
+ {
+ // Verify that we have correct number of attributes
+ if( aAttributes.Count() != 1 )
+ {
+ User::Leave( KErrCorrupt );
+ }
+
+ // Read header value
+ const RString& value = aAttributes[ 0 ].Value();
+
+ // Create SIP header object
+ RPointerArray< CSIPHeaderBase > headers =
+ SIPHeaderLookup::CreateHeaderL( aHeaderName, value.DesC() );
+ // Add created headers to ClientData
+ CSIPHeaderBase::PushLC( &headers );
+ while( headers.Count() > 0 )
+ {
+ CSIPHeaderBase* header = headers[ 0 ];
+ if ( header->Name() ==
+ SIPStrings::StringF(SipStrConsts::EAcceptContactHeader) )
+ {
+ CSIPAcceptContactHeader* acceptContact =
+ static_cast< CSIPAcceptContactHeader* >( header );
+ iClientData->SIPFeatureSet().AddFeaturesL( *acceptContact );
+ delete header;
+ }
+ else
+ {
+ iClientData->SIPHeaders().AppendL( header );
+ }
+ headers.Remove( 0 );
+ }
+ CleanupStack::PopAndDestroy(); // headers
+ }
+
+// -----------------------------------------------------------------------------
+// CSIPClientDataParser::HandleSdpLineL
+// -----------------------------------------------------------------------------
+//
+void CSIPClientDataParser::HandleSdpLineL(
+ const Xml::RAttributeArray& aAttributes )
+ {
+ // Verify that we have correct number of attributes
+ if( aAttributes.Count() != KSdpLineAttrCount )
+ {
+ User::Leave( KErrCorrupt );
+ }
+
+ // Verify that we have the correct attribute(s)
+ if( aAttributes[ 0 ].Value() != iTagLineM )
+ {
+ User::Leave( KErrCorrupt );
+ }
+
+ // Get attribute and convert to a form compatible with CSdpMediaField
+ // (basically just surround the string with "m=" and "\r\n")
+ TPtrC8 value( aAttributes[ 1 ].Value().DesC() );
+ HBufC8* mediaFieldBuf = CreateSdpFieldBufLC( KSdpMediaFieldStart, value );
+
+ // Read and decode SDP media field to ClientData
+ CSdpMediaField* mediaField = CSdpMediaField::DecodeLC( *mediaFieldBuf );
+ iClientData->AddMediaFieldL( mediaField );
+ CleanupStack::Pop( mediaField );
+
+ CleanupStack::PopAndDestroy( mediaFieldBuf );
+ }
+
+// -----------------------------------------------------------------------------
+// CSIPClientDataParser::HandleRtpmapL
+// -----------------------------------------------------------------------------
+//
+void CSIPClientDataParser::HandleRtpmapL(
+ const Xml::RAttributeArray& aAttributes )
+ {
+ CSdpDocument& sdp = iClientData->SdpDocument();
+ if( aAttributes.Count() != 1 || sdp.MediaFields().Count() == 0 )
+ {
+ User::Leave( KErrCorrupt );
+ }
+
+ // Get attribute and convert to a form compatible
+ // with CSdpfmtAttributeField
+ // (basically just surround the string with "a=" and "\r\n")
+ TPtrC8 value( aAttributes[ 0 ].Value().DesC() );
+ HBufC8* fieldBuf = CreateSdpFieldBufLC( KSdpAttributeFieldStart, value );
+
+ // Decode and add rtpmap attribute field
+ CSdpFmtAttributeField* attributeField =
+ CSdpFmtAttributeField::DecodeL( *fieldBuf );
+ CleanupStack::PopAndDestroy( fieldBuf );
+ CleanupStack::PushL( attributeField );
+
+ if( attributeField->Attribute().DesC().Compare( KRtpmapName ) != 0 )
+ {
+ User::Leave( KErrCorrupt );
+ }
+
+ // Add the rtpmap-attribute to the last added media field
+ const TInt lastIndex = sdp.MediaFields().Count()-1;
+ CSdpMediaField* lastMediaField = sdp.MediaFields()[ lastIndex ];
+ lastMediaField->FormatAttributeFields().AppendL( attributeField );
+
+ CleanupStack::Pop( attributeField );
+ }
+
+// -----------------------------------------------------------------------------
+// CSIPClientDataParser::HandleMediaAttributeL
+// -----------------------------------------------------------------------------
+//
+void CSIPClientDataParser::HandleMediaAttributeL(
+ const Xml::RAttributeArray& aAttributes )
+ {
+ CSdpDocument& sdp = iClientData->SdpDocument();
+ if( aAttributes.Count() != 1 || sdp.MediaFields().Count() == 0 )
+ {
+ User::Leave( KErrCorrupt );
+ }
+
+ // Get attribute and convert to a form compatible with CSdpAttributeField
+ // (basically just surround the string with "a=" and "\r\n")
+ TPtrC8 value( aAttributes[ 0 ].Value().DesC() );
+ HBufC8* fieldBuf = CreateSdpFieldBufLC( KSdpAttributeFieldStart, value );
+
+ // Decode and add attribute field
+ CSdpAttributeField* attributeField =
+ CSdpAttributeField::DecodeL( *fieldBuf );
+ CleanupStack::PopAndDestroy( fieldBuf );
+ CleanupStack::PushL( attributeField );
+
+ // Add the attribute to the last added media field
+ const TInt lastIndex = sdp.MediaFields().Count()-1;
+ CSdpMediaField* lastMediaField = sdp.MediaFields()[ lastIndex ];
+ lastMediaField->AttributeFields().AppendL( attributeField );
+
+ CleanupStack::Pop( attributeField );
+ }
+
+// -----------------------------------------------------------------------------
+// CSIPClientDataParser::CreateSdpFieldBufLC
+// -----------------------------------------------------------------------------
+//
+HBufC8* CSIPClientDataParser::CreateSdpFieldBufLC(
+ const TDesC8& aFieldStart,
+ const TDesC8& aValue )
+ {
+ TInt bufLength = aFieldStart.Length() + aValue.Length() + KCrLf().Length();
+ HBufC8* buf = HBufC8::NewLC( bufLength );
+ TPtr8 bufPtr = buf->Des();
+ bufPtr.Copy( aFieldStart );
+ bufPtr.Append( aValue );
+ bufPtr.Append( KCrLf );
+ return buf;
+ }