diff -r 000000000000 -r 1bce908db942 multimediacommsengine/tsrc/testdriver/siptester/src/TTcSIPCommandBase.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/multimediacommsengine/tsrc/testdriver/siptester/src/TTcSIPCommandBase.cpp Tue Feb 02 01:04:58 2010 +0200 @@ -0,0 +1,711 @@ +/* +* Copyright (c) 2004 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: Implementation. +* +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <_sipcodecdefs.h> +#include +#include +#include +#include + +#include "CleanupResetAndDestroy.h" +#include "CTcSIPContext.h" +#include "SIPConstants.h" +#include "SipStrConsts.h" +#include "TcLog.h" +#include "TTcSIPCommandBase.h" + +#include "CTcSIPProfileContainer.h" + +TTcSIPCommandBase::TTcSIPCommandBase( MTcTestContext& aContext ) + : TTcCommandBase( static_cast< CTcContextBase& >( aContext ) ), + iContext( static_cast< CTcSIPContext& >( aContext ) ), + iPushed( 0 ) + { + } + +// +// - Header extraction functions ---------------------------------------------- +// + +CSIPToHeader* TTcSIPCommandBase::ExtractToHeaderLC( TBool aIsMandatory ) + { + return static_cast< CSIPToHeader* >( + ExtractHeaderLC( KHeaderTo, aIsMandatory ) ); + } + +CSIPContactHeader* TTcSIPCommandBase::ExtractContactHeaderLC( + TBool aIsMandatory ) + { + CSIPContactHeader* contact = + static_cast< CSIPContactHeader* >( + ExtractHeaderLC( KHeaderContact, aIsMandatory ) ); + return contact; + } + +CSIPRouteHeader* TTcSIPCommandBase::ExtractRouteHeaderLC( TBool aIsMandatory ) + { + return static_cast< CSIPRouteHeader* >( + ExtractHeaderLC( KHeaderRoute, aIsMandatory ) ); + } + +CSIPFromHeader* TTcSIPCommandBase::ExtractFromHeaderLC( TBool aIsMandatory ) + { + CSIPFromHeader* from = + static_cast< CSIPFromHeader* >( + ExtractHeaderLC( KHeaderFrom, aIsMandatory ) ); + return from; + } + +CSIPExpiresHeader* TTcSIPCommandBase::ExtractExpiresHeaderLC( TBool aIsMandatory ) + { + return static_cast< CSIPExpiresHeader* >( + ExtractHeaderLC( KHeaderExpires, aIsMandatory ) ); + } + +CSIPReferToHeader* TTcSIPCommandBase::ExtractReferToHeaderLC( TBool aIsMandatory ) + { + return static_cast< CSIPReferToHeader* >( + ExtractHeaderLC( KHeaderReferTo, aIsMandatory ) ); + } + + +CSIPSubscriptionStateHeader* TTcSIPCommandBase::ExtractSubStateHeaderLC( TBool aIsMandatory ) + { + return static_cast< CSIPSubscriptionStateHeader* >( + ExtractHeaderLC( KHeaderSubState, aIsMandatory ) ); + } + +CSIPEventHeader* TTcSIPCommandBase::ExtractEventHeaderLC( TBool aIsMandatory ) + { + return static_cast< CSIPEventHeader* >( + ExtractHeaderLC( KHeaderEvent, aIsMandatory ) ); + } + +CSIPContentTypeHeader* TTcSIPCommandBase::ExtractContentTypeHeaderLC( TBool aIsMandatory ) + { + return static_cast< CSIPContentTypeHeader* >( + ExtractHeaderLC( KHeaderContentType, aIsMandatory ) ); + } + + +CSIPMessageElements* TTcSIPCommandBase::ExtractHeadersAndContentLC() + { + // Construct message elements container + CSIPMessageElements* elements = CSIPMessageElements::NewLC(); + + ExtractHeadersAndContentL( *elements ); + + return elements; + } + +void TTcSIPCommandBase::ExtractHeadersAndContentL( CSIPMessageElements& aElements ) + { + // Extract Content + Content-Type to elements. + ExtractContentL( aElements ); + + CTcArray* headers = FindArrayL( KResponseHeaders, EFalse ); + if( !headers ) + { + return; + } + + // Extract any headers still left in the request into userHeaders + RPointerArray< CSIPHeaderBase > userHeaders; + ExtractUserHeadersL( *headers, userHeaders ); + + // Give userHeaders to elements + CleanupResetAndDestroyPushL( userHeaders ); + aElements.SetUserHeadersL( userHeaders ); + CleanupStack::Pop(); // userHeaders + } + +// +// - Parameter extraction functions ------------------------------------------- +// + +CSIPRefresh* TTcSIPCommandBase::ExtractRefreshLC() + { + TPtrC8 value = ExtractTextL( KParamRefresh, EFalse ); + if( value.CompareF( KTcTrue ) == 0 ) + { + CSIPRefresh* refresh = CSIPRefresh::NewLC(); + iPushed++; + return refresh; + } + + return NULL; + } + +CUri8* TTcSIPCommandBase::ExtractRemoteURILC( TBool aIsMandatory ) + { + TPtrC8 value = ExtractTextL( KParamRemoteURI, aIsMandatory ); + if( value != KNullDesC8 ) + { + TUriParser8 parser; + User::LeaveIfError(parser.Parse(value)); + CUri8* uri8 = CUri8::NewLC(parser); + iPushed++; + return uri8; + } + + return NULL; + } + +CSIPRouteHeader* TTcSIPCommandBase::ExtractProxyLC() + { + CSIPRouteHeader* proxy = NULL; + + TPtrC8 value = ExtractTextL( KParamProxy, EFalse ); + if( value != KNullDesC8 ) + { + RPointerArray proxies = CSIPRouteHeader::DecodeL( value ); + + // First of the proxy parameter addresses will be used altought there + // shouldn't be more + if ( proxies.Count() > 0 ) + { + proxy = proxies[ 0 ]; + // Used proxy is not deleted over here + proxies.Remove( 0 ); + // Others can be deleted + proxies.ResetAndDestroy(); + + CleanupStack::PushL( proxy ); + iPushed++; + } + } + return proxy; + } + +CTcSIPConnectionContainer& TTcSIPCommandBase::SelectConnectionL() + { + TPtrC8 value = ExtractIdL( KConnectionId, EFalse ); + if( value != KNullDesC8 ) + { + CTcSIPConnectionContainer* conn + = reinterpret_cast< CTcSIPConnectionContainer* >( + iContext.Registry().ObjectPtrL( value ) ); + return *conn; + } + else + { + return iContext.Connection(); + } + } +CTcSIPProfileContainer& TTcSIPCommandBase::SelectProfileL() + { + TPtrC8 value = ExtractIdL( KRegistryId, EFalse ); + if( value != KNullDesC8 ) + { + CTcSIPProfileContainer* conn + = reinterpret_cast< CTcSIPProfileContainer* >( + iContext.Registry().ObjectPtrL( value ) ); + return *conn; + } + else + { + return iContext.Profile(); + } + } +// +// - Response creation functions ---------------------------------------------- +// +void TTcSIPCommandBase::AddIdResponseL( const TDesC8& aName, + const CBase* aObject ) + { + // Register object and fetch its name + iContext.Registry().AddObjectL( const_cast< CBase* >( aObject ) ); + TPtrC8 idName = iContext.Registry().ObjectNameL( aObject ); + + CTcStructure& tcIDs = FindCreateTestClientIdsL(); + CTcNameValue* idNameValue = tcIDs.ItemL( aName ); + idNameValue->SetValueL( idName ); + } + +void TTcSIPCommandBase::AddIdResponseL( const TDesC8& aName, + const CBase& aObject ) + { + // Register object and fetch its name + iContext.Registry().AddObjectL( aObject ); + TPtrC8 idName = iContext.Registry().ObjectNameL( &aObject ); + + CTcStructure& tcIDs = FindCreateTestClientIdsL(); + CTcNameValue* idNameValue = tcIDs.ItemL( aName ); + idNameValue->SetValueL( idName ); + } + +void TTcSIPCommandBase::AddProfileIdResponseL( CSIPProfile* aProfile ) + { + // Register object + iContext.Registry().AddObjectL( aProfile ); + TBuf8< KTcMaxIntConversion > idName; + + TUint32 id( 0 ); + User::LeaveIfError( aProfile->GetParameter( KSIPProfileId, id ) ); + idName.AppendNum( (TInt)id ); + + CTcStructure& tcIDs = FindCreateTestClientIdsL(); + CTcNameValue* profileId = + const_cast< CTcNameValue* >( tcIDs.ItemL( KProfileId ) ); + profileId->SetValueL( idName ); + } + +void TTcSIPCommandBase::AddProfileIdResponseL( CSIPProfile& aProfile ) + { + // Register object + iContext.Registry().AddObjectL( aProfile ); + TBuf8< KTcMaxIntConversion > idName; + + TUint32 id( 0 ); + User::LeaveIfError( aProfile.GetParameter( KSIPProfileId, id ) ); + idName.AppendNum( (TInt)id ); + + CTcStructure& tcIDs = FindCreateTestClientIdsL(); + CTcNameValue* profileId = + const_cast< CTcNameValue* >( tcIDs.ItemL( KProfileId ) ); + profileId->SetValueL( idName ); + } + +CTcStructure& TTcSIPCommandBase::FindCreateTestClientIdsL() + { + // Find the TestClientIds structure, it may be in several places + // (there might already be a ReceivedMsg item in the return list) + // It may also be missing altogether, if this is the first time + // AddIdResponseL() is called. + TInt pos = iContext.ReturnList().FindParameter( KResponseTestClientIds, + MTcTyped::EStructure ); + if( pos == KErrNotFound ) + { + // Figure out the correct position for the structure: just + // after the ReceivedMsg if it exists. + pos = iContext.ReturnList().FindParameter( KResponseHeaders, + MTcTyped::EArray ); + if( pos == KErrNotFound ) + { + pos = 0; // no headers, insert at the beginning + } + else + { + pos++; // insert after headers + } + + // Add a structure to the response parameter list for TestClient Ids + CTcStructure* tcIDs = CTcStructure::NewLC(); + tcIDs->SetName( KResponseTestClientIds ); + iContext.ReturnList().InsertParameterL( tcIDs, pos ); + CleanupStack::Pop(); // tcIDs + + // All IDs, in alphabetical order + // (this has to be function-local in order to compile for THUMB) + const TDesC8* const TIdNames[] = { + &KConnectionId, + &KDialogId, + &KInviteDialogId, + &KNotifyDialogId, + &KProfileId, + &KReferDialogId, + &KRefreshId, + &KRegistryId, + &KRegistrationId, + &KServerTransactionId, + &KSubscribeDialogId, + &KTransactionId + }; + + // Add an entry for ALL possible Ids. This is done to go around + // a Telelogic Tau logging problem related to template mismatches + TInt count = sizeof( TIdNames ) / sizeof( const TDesC8* ); + for( TInt i = 0; i < count; i++ ) + { + CTcNameValue* nameValue = CTcNameValue::NewLC(); + nameValue->SetL( *TIdNames[ i ], 0 ); + tcIDs->AddItemL( nameValue ); + CleanupStack::Pop( nameValue ); + } + } + + return iContext.ReturnList().AsStructure( pos ); + } +// +// -- SIP object / registry access functions ---------------------------------- +// + +CSIPDialog* TTcSIPCommandBase::GetDialogL( TBool aIsMandatory ) + { + return reinterpret_cast< CSIPDialog* >( + GetObjectForIdL( KDialogId, aIsMandatory ) ); + } + +CSIPDialogAssocBase* TTcSIPCommandBase::GetAnyDialogAssocL( + TBool aIsMandatory ) + { + CSIPDialogAssocBase* dialogAssoc = GetInviteDialogAssocL( EFalse ); + if( dialogAssoc ) + { + return dialogAssoc; + } + + dialogAssoc = GetSubscribeDialogAssocL( EFalse ); + if( dialogAssoc ) + { + return dialogAssoc; + } + + dialogAssoc = GetReferDialogAssocL( EFalse ); + if( dialogAssoc ) + { + return dialogAssoc; + } + + dialogAssoc = GetNotifyDialogAssocL( EFalse ); + if( dialogAssoc ) + { + return dialogAssoc; + } + + if( aIsMandatory ) + { + User::Leave( KTcErrMandatoryIdNotFound ); + } + return NULL; + } + +CSIPInviteDialogAssoc* TTcSIPCommandBase::GetInviteDialogAssocL( TBool aIsMandatory ) + { + return reinterpret_cast< CSIPInviteDialogAssoc* >( + GetObjectForIdL( KInviteDialogId, aIsMandatory ) ); + } + +CSIPSubscribeDialogAssoc* TTcSIPCommandBase::GetSubscribeDialogAssocL( TBool aIsMandatory ) + { + return reinterpret_cast< CSIPSubscribeDialogAssoc* >( + GetObjectForIdL( KSubscribeDialogId, aIsMandatory ) ); + } + +CSIPNotifyDialogAssoc* TTcSIPCommandBase::GetNotifyDialogAssocL( TBool aIsMandatory ) + { + return reinterpret_cast< CSIPNotifyDialogAssoc* >( + GetObjectForIdL( KNotifyDialogId, aIsMandatory ) ); + } + +CSIPReferDialogAssoc* TTcSIPCommandBase::GetReferDialogAssocL( TBool aIsMandatory ) + { + return reinterpret_cast< CSIPReferDialogAssoc* >( + GetObjectForIdL( KReferDialogId, aIsMandatory ) ); + } + +CSIPClientTransaction* TTcSIPCommandBase::GetClientTransactionL( TBool aIsMandatory ) + { + return reinterpret_cast< CSIPClientTransaction* >( + GetObjectForIdL( KTransactionId, aIsMandatory ) ); + } + +CSIPServerTransaction* TTcSIPCommandBase::GetServerTransactionL( TBool aIsMandatory ) + { + return reinterpret_cast< CSIPServerTransaction* >( + GetObjectForIdL( KServerTransactionId, aIsMandatory ) ); + } + +CSIPRegistrationBinding* TTcSIPCommandBase::GetRegistrationL( TBool aIsMandatory ) + { + return reinterpret_cast< CSIPRegistrationBinding* >( + GetObjectForIdL( KRegistrationId, aIsMandatory ) ); + } + +CSIPRefresh* TTcSIPCommandBase::GetRefreshL( TBool aIsMandatory ) + { + return reinterpret_cast< CSIPRefresh* >( + GetObjectForIdL( KRefreshId, aIsMandatory ) ); + } + +CSIPManagedProfile& TTcSIPCommandBase::GetManagedProfileL( CTcSIPProfileContainer& aProfileContainer ) + { + // Get profile from the registry + return aProfileContainer.GetManagedProfileByIdL( ExtractProfileIdL() ); + } + +CSIPProfile& TTcSIPCommandBase::GetProfileL( CTcSIPProfileContainer& aProfileContainer ) + { + // Get profile from the registry + return aProfileContainer.GetProfileByIdL( ExtractProfileIdL() ); + } + +CSIPProfile* TTcSIPCommandBase::GetProfileL( CTcSIPProfileContainer& aProfileContainer, TBool aIsMandatory ) + { + // Get profile from the registry + TPtrC8 profileIdStr = ExtractIdL( KParamProfileId, aIsMandatory ); + + CSIPProfile* profile = 0; + + if ( profileIdStr != KNullDesC8 ) + { + TInt profileId( 0 ); + TLex8 lexer( profileIdStr ); + User::LeaveIfError( lexer.Val( profileId ) ); + profile = &aProfileContainer.GetProfileByIdL( profileId ); + } + + return profile; + } + +CSIPProfile* TTcSIPCommandBase::GetProfileL() + { + CSIPProfile* profile = NULL; + TPtrC8 profileIdStr = ExtractIdL( KParamProfileId, EFalse ); + if ( profileIdStr.Length() > 0 ) + { + TInt profileId( 0 ); + TLex8 lexer( profileIdStr ); + User::LeaveIfError( lexer.Val( profileId ) ); + CTcSIPProfileContainer& conn = SelectProfileL(); + profile = &( conn.GetProfileByIdL( profileId ) ); + } + return profile; + } +// +// - Internal header utility functions ---------------------------------------- +// + +void TTcSIPCommandBase::ExtractContentL( CSIPMessageElements& aElements ) + { + // Extract content type, if any + CSIPContentTypeHeader* contentType = static_cast< CSIPContentTypeHeader* >( + ExtractHeaderLC( KHeaderContentType, EFalse ) ); + if( !contentType ) + { + return; + } + + // Extract content, if any + HBufC8* content = ExtractHBufLC( KParamContent ); + if( !content ) + { + // If content didn't exist use empty content + content = KNullDesC8().AllocLC(); + iPushed++; + } + + aElements.SetContentL( content, contentType ); + + CleanupStack::Pop( 2 ); // content, contentType + iPushed -= 2; // content, contentType + } + +CSIPHeaderBase* TTcSIPCommandBase::ExtractHeaderLC( const TDesC8& aHeaderName, + TBool aIsMandatory ) + { + TBuf8< KTcMaxTypeName > objectName( aHeaderName ); + TBuf8< KTcOptionalLength > optional; if( aIsMandatory ) optional = KTcMandatory; else optional = KTcOptional; + TcLog::WriteFormat( _L8("-- Extract %s header \"%s\""), optional.PtrZ(), objectName.PtrZ() ); + + CTcArray* headers = FindArrayL( KResponseHeaders, aIsMandatory ); + if( !headers ) + { + // no headers + return NULL; + } + + TInt count = headers->Count(); + for( TInt i = 0; i < count; i++ ) + { + TPtrC8 header = headers->Item( i ); + if( NameFromHeader( header ).CompareF( aHeaderName ) == 0 ) + { + // Get headername from stringpool + TPtrC8 headerPtr = NameFromHeader( header ); + RStringF headerStr = SIPStrings::Pool().OpenFStringL(headerPtr); + CleanupClosePushL(headerStr); + + RPointerArray< CSIPHeaderBase > headerArray = + SIPHeaderLookup::CreateHeaderL( headerStr, + ValueFromHeader( header ) ); + CSIPHeaderBase* headerObject = headerArray[ 0 ]; + headerArray.Close(); + CleanupStack::PopAndDestroy(); // headerStr + CleanupStack::PushL( headerObject ); + // header was extracted, remove it from original array + headers->RemoveItem( i ); + iPushed++; + TcLog::Write( KLogOk ); + return headerObject; + } + } + + TcLog::Write( KLogNotFound ); + if( aIsMandatory ) + { + User::Leave( KTcErrMandatoryHeaderNotFound ); + } + return NULL; + } + +void TTcSIPCommandBase::ExtractUserHeadersL( + CTcArray& aHeaders, + RPointerArray< CSIPHeaderBase >& aHeaderArray ) + { + TInt count = aHeaders.Count(); + for( TInt i = 0; i < count; i++ ) + { + // Instantiate correct SIP header object by using the Header factory + TPtrC8 header = aHeaders.Item( i ); + + TBuf8< KTcMaxTypeName > headerName( NameFromHeader( header ) ); + TcLog::WriteFormat( _L8("-- Extract user header \"%s\""), headerName.PtrZ() ); + + // Get headername from stringpool + RStringF headerNameStr = SIPStrings::Pool().OpenFStringL(headerName); + CleanupClosePushL(headerNameStr); + + if( IsHeaderAllowed( headerNameStr ) ) + { + RPointerArray< CSIPHeaderBase > newArray = + SIPHeaderLookup::CreateHeaderL( headerNameStr, + ValueFromHeader( header ) ); + CleanupResetAndDestroyPushL( newArray ); + + // The factory might have created a bunch of headers, move them to + // our array. + TInt newCount = newArray.Count(); + for( TInt j = 0; j < newCount; j++ ) + { + User::LeaveIfError( aHeaderArray.Append( newArray[ 0 ] ) ); + newArray.Remove( 0 ); + } + CleanupStack::PopAndDestroy(); // newArray + + TcLog::Write( KLogOk ); + } + else + { + TcLog::Write( KLogNotAllowed ); + User::Leave( KTcErrHeaderNotAllowed ); + } + CleanupStack::PopAndDestroy(); // headerNameStr + } + } + +HBufC8* TTcSIPCommandBase::ExtractHBufLC( const TDesC8& aParamName ) + { + TPtrC8 value = ExtractTextL( aParamName, EFalse ); + if( value != KNullDesC8 ) + { + HBufC8* buf = value.AllocLC(); + iPushed++; + return buf; + } + + return NULL; + } + +TInt TTcSIPCommandBase::ExtractProfileIdL() + { + TPtrC8 profileIdStr = ExtractIdL( KParamProfileId ); + TInt profileId( 0 ); + TLex8 lexer( profileIdStr ); + User::LeaveIfError( lexer.Val( profileId ) ); + return profileId; + } + +TUid TTcSIPCommandBase::ExtractUidL( const TDesC8& aName,TBool aIsMandatory ) + { + const TInt KHexAsTextValueStartPos = 2; + + TPtrC8 uidStr = ExtractTextL( aName, aIsMandatory ); + + if ( !aIsMandatory && uidStr.Length() == 0 ) + { + return TUid::Uid( 0 ); + } + + __ASSERT_ALWAYS( uidStr.Length() > KHexAsTextValueStartPos, User::Leave( KErrArgument ) ); + TUint uidVal( 0 ); + TLex8 lexer( uidStr.Mid( KHexAsTextValueStartPos ) ); + User::LeaveIfError( lexer.Val( uidVal, EHex ) ); + return TUid::Uid( static_cast( uidVal ) ); + } + +TPtrC8 TTcSIPCommandBase::NameFromHeader( const TDesC8& aHeader ) const + { + TInt pos = aHeader.Locate( KHeaderSeparator ); + if( pos == KErrNotFound ) + { + // return an empty pointer descriptor + return TPtrC8(); + } + return aHeader.Left( pos ); + } + +TPtrC8 TTcSIPCommandBase::ValueFromHeader( const TDesC8& aHeader ) const + { + TInt pos = aHeader.Locate( KHeaderSeparator ); + if( pos == KErrNotFound ) + { + // return an empty pointer descriptor + return TPtrC8( 0 ); + } + pos++; // skip the separator + return aHeader.Mid( pos ); + } + +TBool TTcSIPCommandBase::IsHeaderAllowed( RStringF aName ) + { + // The SIP headers can be divided to two sets: + // Supported headers and extension headers. + // The supported headers can be further divided into two subsets: + // API headers and private headers. + // Private headers cannot be set by the application. + if( SIPHeaderLookup::IsAPIHeader( aName )) + { + if( aName == SIPStrings::StringF( SipStrConsts::EFromHeader ) || + aName == SIPStrings::StringF( SipStrConsts::EToHeader ) || + aName == SIPStrings::StringF( SipStrConsts::ECSeqHeader ) || + aName == SIPStrings::StringF( SipStrConsts::EContentTypeHeader ) ) + { + return EFalse; + } + } + else + { + if( SIPHeaderLookup::IsSupported( aName ) ) // Private header + { + return EFalse; + } + } + return ETrue; + }