diff -r 000000000000 -r 307788aac0a8 realtimenetprots/sipfw/SDP/src/SdpOriginField.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/realtimenetprots/sipfw/SDP/src/SdpOriginField.cpp Tue Feb 02 01:03:15 2010 +0200 @@ -0,0 +1,1038 @@ +// Copyright (c) 2003-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 : SdpOriginField.cpp +// Part of : SDP Codec +// Version : 1.0 +// + + + +#include +#include +#include "SdpOriginField.h" +#include "SdpOriginFieldPtrs.h" +#include "SdpUtil.h" +#include "sdpcodecstringconstants.h" +#include "SdpCodecConstants.h" +#include "SdpCodecStringPool.h" +#include "SdpCodecErr.h" +#include "SDPCodec.pan" +#include "_sdpdefs.h" + +// LOCAL CONSTANTS AND MACROS +const TUint KMaxIPDesLength = 39; +const TUint KHeaderIndex = 0; +const TUint KUserNameIndex = 1; +const TUint KSessionIdIndex = 2; +const TUint KSessionVersionIndex = 3; +const TUint KNetworkTypeIndex = 4; +const TUint KAddressTypeIndex = 5; +const TUint KAddressIndex = 6; +const TInt KTokenCount = 7; +const TInt64 KDummyValue = 1; + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CSdpOriginField::CSdpOriginField +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CSdpOriginField::CSdpOriginField() + { + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CSdpOriginField::ConstructL( + const TDesC8& aText ) + { + // aText should be of format: + // o= + //
+ iPool = SdpCodecStringPool::StringPoolL(); + + RArray array; + array = SdpUtil::GetElementsFromLineL( aText, KErrSdpCodecOriginField ); + + CleanupClosePushL( array ); + + if ( array.Count() != KTokenCount ) + { + User::Leave( KErrSdpCodecOriginField ); + } + + // Check that the line contains valid header + RStringF origHeader = iPool.StringF( SdpCodecStringConstants::EOrigin, + SdpCodecStringConstants::Table ); + if ( origHeader.DesC().CompareF( array[KHeaderIndex] ) != 0 ) + { + // Header didn't match + User::Leave( KErrSdpCodecOriginField ); + } + + iUserName = + reinterpret_cast< HBufC8* >( CSdpOriginFieldPtrs::NewL( 0, 0 ) ); + + + // + ParseUserNameL( array ); + + // & + ParseSessionIDAndVersionL( array ); + + // &
+ ParseNetTypeAndAddressTypeL( array ); + + //
+ ParseAddressL( array ); + + //If address is IPv4-Mapped IPv6 , it is changed to IPv4 + TInetAddr addr; + TBuf address; + address.Copy(iAddress); + + TInt err = addr.Input( address ); + if ( err == KErrNone ) + { + // Valid IP address + TBuf buf; + addr.Output( buf ); + iAddress.Copy(buf); + + SetIPAddressType( addr ); + } + + + + CleanupStack::PopAndDestroy(); // array + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CSdpOriginField::ConstructL( + const TDesC8& aUserName, + TInt64 aSessionId, + TInt64 aSessionVersion, + TInetAddr& aUnicastAddress ) + { + iPool = SdpCodecStringPool::StringPoolL(); + + __ASSERT_ALWAYS( + IsValidUserName( aUserName ) + && IsValidAddress( aUnicastAddress ) + && aSessionId >= 0 && aSessionVersion >= 0, + User::Leave( KErrSdpCodecOriginField ) ); + + iUserName = reinterpret_cast< HBufC8* > + ( CSdpOriginFieldPtrs::NewL( aSessionId, aSessionVersion ) ); + OriginFieldPtrs().SetUserNameL( aUserName ); + + TBuf des; + aUnicastAddress.Output( des ); + //if aUnicastAddress was IPv4-Mapped IPv6 address, + // the result of Output is IPv4 + // the address is stored in IPv4 format, so the iAddressType + // must also be IPv4. + iAddress.Copy( des ); + SetIPAddressType( aUnicastAddress ); + + iNetType = iPool.StringF( SdpCodecStringConstants::ENetType, + SdpCodecStringConstants::Table ).Copy(); + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CSdpOriginField::ConstructL( + const TDesC8& aUserName, + TInt64 aSessionId, + TInt64 aSessionVersion, + RStringF aNetType, + RStringF aAddressType, + const TDesC8& aAddress ) + { + iPool = SdpCodecStringPool::StringPoolL(); + + __ASSERT_ALWAYS( + IsValidUserName( aUserName ) + && IsValidAddress( aAddress ) && + TypeMatchesWithFormat( aAddress, aAddressType.DesC(), iPool ) + && ( SdpUtil::IsToken( aNetType.DesC() ) ) + && ( SdpUtil::IsToken( aAddressType.DesC() ) ) + && aSessionId >= 0 && aSessionVersion >= 0, + User::Leave( KErrSdpCodecOriginField ) ); + + iUserName = reinterpret_cast< HBufC8* > + ( CSdpOriginFieldPtrs::NewL( aSessionId, aSessionVersion ) ); + OriginFieldPtrs().SetUserNameL( aUserName ); + + iNetType = aNetType.Copy(); + TInetAddr addr; + TBuf address; + address.Copy(aAddress); + TInt err = addr.Input(address); + if ( err == KErrNone ) + { + // Valid IP address + TBuf< KMaxIPDesLength > buf; + addr.Output( buf ); + iAddress.Copy( buf ); + SetIPAddressType( addr ); + } + else + { + iAddress = aAddress; + iAddressType = aAddressType.Copy(); + } + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::DecodeL +// Two-phased constructor +// ----------------------------------------------------------------------------- +// +EXPORT_C CSdpOriginField* CSdpOriginField::DecodeL( + const TDesC8& aText ) + { + CSdpOriginField* obj = CSdpOriginField::DecodeLC( aText ); + CleanupStack::Pop(); + return obj; + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::DecodeLC +// Two-phased constructor +// ----------------------------------------------------------------------------- +// +EXPORT_C CSdpOriginField* CSdpOriginField::DecodeLC( + const TDesC8& aText ) + { + CSdpOriginField* obj = new ( ELeave ) CSdpOriginField; + CleanupStack::PushL( obj ); + obj->ConstructL(aText ); + return obj; + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::NewL +// Two-phased constructor +// ----------------------------------------------------------------------------- +// +EXPORT_C CSdpOriginField* CSdpOriginField::NewL( + const TDesC8& aUserName, + TInt64 aSessionId, + TInt64 aSessionVersion, + TInetAddr& aAddress ) + { + CSdpOriginField* obj = CSdpOriginField::NewLC( + aUserName, aSessionId, aSessionVersion, aAddress ); + CleanupStack::Pop(); + return obj; + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::NewLC +// Two-phased constructor +// ----------------------------------------------------------------------------- +// +EXPORT_C CSdpOriginField* CSdpOriginField::NewLC( + const TDesC8& aUserName, + TInt64 aSessionId, + TInt64 aSessionVersion, + TInetAddr& aAddress ) + { + CSdpOriginField* obj = new ( ELeave ) CSdpOriginField; + CleanupStack::PushL(obj); + obj->ConstructL( aUserName, aSessionId, aSessionVersion, aAddress ); + return obj; + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::NewL +// Two-phased constructor +// ----------------------------------------------------------------------------- +// +EXPORT_C CSdpOriginField* CSdpOriginField::NewL( + const TDesC8& aUserName, + TInt64 aSessionId, + TInt64 aSessionVersion, + RStringF aNetType, + RStringF aAddressType, + const TDesC8& aAddress ) + { + CSdpOriginField* obj = CSdpOriginField::NewLC( + aUserName, aSessionId, aSessionVersion, aNetType, + aAddressType, aAddress ); + CleanupStack::Pop(); + return obj; + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::NewLC +// Two-phased constructor +// ----------------------------------------------------------------------------- +// +EXPORT_C CSdpOriginField* CSdpOriginField::NewLC( + const TDesC8& aUserName, + TInt64 aSessionId, + TInt64 aSessionVersion, + RStringF aNetType, + RStringF aAddressType, + const TDesC8& aAddress ) + { + CSdpOriginField* obj = new ( ELeave ) CSdpOriginField; + CleanupStack::PushL( obj ); + obj->ConstructL( aUserName, aSessionId, aSessionVersion, aNetType, + aAddressType, aAddress ); + return obj; + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::~CSdpOriginField +// ----------------------------------------------------------------------------- +// +EXPORT_C CSdpOriginField::~CSdpOriginField() + { + CSdpOriginFieldPtrs* tmp = + reinterpret_cast< CSdpOriginFieldPtrs* >( iUserName ); + delete tmp; + + iNetType.Close(); + iAddressType.Close(); + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::EncodeL +// Writes attributes in proper format to the stream +// ----------------------------------------------------------------------------- +// +EXPORT_C void CSdpOriginField::EncodeL( + RWriteStream& aStream ) const + { + __TEST_INVARIANT; + + // o=
+ //
+ + // "o=" + RStringF header = iPool.StringF( SdpCodecStringConstants::EOrigin, + SdpCodecStringConstants::Table ); + aStream.WriteL( header.DesC() ); + + // + aStream.WriteL( OriginFieldPtrs().UserName() ); + aStream.WriteL( KSPStr ); + + // + aStream.WriteL( OriginFieldPtrs().SessionId() ); + aStream.WriteL( KSPStr ); + + // + aStream.WriteL( OriginFieldPtrs().SessionVersion() ); + aStream.WriteL( KSPStr ); + + // + aStream.WriteL( iNetType.DesC() ); + aStream.WriteL( KSPStr ); + + //
+ aStream.WriteL( iAddressType.DesC() ); + aStream.WriteL( KSPStr ); + + //
+ aStream.WriteL( iAddress ); + + // End-of-Line mark + aStream.WriteL( KCRLFStr ); + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::CloneL +// Creates an exact copy of the origin field +// ----------------------------------------------------------------------------- +// +EXPORT_C CSdpOriginField* CSdpOriginField::CloneL() const + { + __TEST_INVARIANT; + + CSdpOriginField* obj = 0; + + if ( InetAddress() ) + { + // Clones instance with TInetAddr + TInetAddr addr( *InetAddress() ); + obj = CSdpOriginField::NewLC( UserName(), KDummyValue, + KDummyValue, addr ); + } + else + { + // Clones instance with Internet address as a standard string + obj = CSdpOriginField::NewLC( UserName(), KDummyValue, KDummyValue, + iNetType, iAddressType, Address() ); + } + + // Set the real values + obj->OriginFieldPtrs().SetSessionIdL( OriginFieldPtrs().SessionId() ); + obj->OriginFieldPtrs().SetSessionVersionL( + OriginFieldPtrs().SessionVersion() ); + CleanupStack::Pop( obj ); + + __ASSERT_DEBUG( *this == *obj, User::Panic( KSdpCodecPanicCat, + KSdpCodecPanicInternal ) ); + return obj; + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::operator == +// Checks if two origin fields are equal +// ----------------------------------------------------------------------------- +// +EXPORT_C TBool CSdpOriginField::operator == ( + const CSdpOriginField& aObj) const + { + __TEST_INVARIANT; + + TBool equalFields = EFalse; + + // Check that username, session ID and address type match before + // going to internet address + if ( ( UserName().CompareF( aObj.UserName() ) == 0 ) && + ( SessionId() == aObj.SessionId() ) && + ( AddressType() == aObj.AddressType() ) && + ( Version() == aObj.Version() ) && + ( NetType() == aObj.NetType() ) ) + { + if ( InetAddress() && aObj.InetAddress() ) + { + if ( (*InetAddress()).Match( *aObj.InetAddress() ) ) + { + equalFields = ETrue; + } + } + else if ( !InetAddress() && !aObj.InetAddress() ) + { + if ( iAddress.CompareF( aObj.Address() ) == 0 ) + { + equalFields = ETrue; + } + } + else + { + // These two are not the same + } + } + + return equalFields; + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::UserName +// Returns username +// ----------------------------------------------------------------------------- +// +EXPORT_C const TDesC8& CSdpOriginField::UserName() const + { + __TEST_INVARIANT; + return OriginFieldPtrs().UserName(); + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::SetUserNameL +// Sets a new username +// ----------------------------------------------------------------------------- +// +EXPORT_C void CSdpOriginField::SetUserNameL( + const TDesC8& aValue ) + { + __TEST_INVARIANT; + if ( IsValidUserName( aValue ) ) + { + OriginFieldPtrs().SetUserNameL( aValue ); + } + else + { + User::Leave( KErrSdpCodecOriginField ); + } + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::SessionId +// Returns current session id +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt64 CSdpOriginField::SessionId() const + { + __TEST_INVARIANT; + + return Get63Msbs( OriginFieldPtrs().SessionId() ); + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::SetSessionId +// Sets new session ID +// ----------------------------------------------------------------------------- +// +EXPORT_C void CSdpOriginField::SetSessionId( + TInt64 aValue ) + { + __TEST_INVARIANT; + if ( aValue >= 0 ) + { + TRAP_IGNORE( OriginFieldPtrs().SetSessionIdL( aValue ) ) + } + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::Version +// Returns version number of the announcement +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt64 CSdpOriginField::Version() const + { + __TEST_INVARIANT; + + return Get63Msbs( OriginFieldPtrs().SessionVersion() ); + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::SetVersion +// Sets new version for this session's announcement +// ----------------------------------------------------------------------------- +// +EXPORT_C void CSdpOriginField::SetVersion( + TInt64 aValue ) + { + __TEST_INVARIANT; + if ( aValue >= 0 ) + { + TRAP_IGNORE( OriginFieldPtrs().SetSessionVersionL( aValue ) ) + } + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::NetType +// Returns net type (always Internet) +// ----------------------------------------------------------------------------- +// +EXPORT_C RStringF CSdpOriginField::NetType() const + { + __TEST_INVARIANT; + return iNetType; + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::AddressType +// Returns address type (IP4/IP6) +// ----------------------------------------------------------------------------- +// +EXPORT_C RStringF CSdpOriginField::AddressType() const + { + __TEST_INVARIANT; + return iAddressType; + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::InetAddress +// Returns the unicast address +// ----------------------------------------------------------------------------- +// +EXPORT_C const TInetAddr* CSdpOriginField::InetAddress() const + { + __TEST_INVARIANT; + + TBuf address16; + address16.Copy( iAddress ); + TInt err = iUnicastAddress.Input( address16 ); + + if ( !err ) + { + return &iUnicastAddress; + } + else + { + return NULL; + } + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::Address +// Returns the address +// ----------------------------------------------------------------------------- +// +EXPORT_C const TDesC8& CSdpOriginField::Address() const + { + __TEST_INVARIANT; + return iAddress; + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::SetInetAddress +// Sets Internet Address +// ----------------------------------------------------------------------------- +// +EXPORT_C void CSdpOriginField::SetInetAddress( + const TInetAddr& aValue ) + { + __TEST_INVARIANT; + + if ( IsValidAddress( aValue ) ) + { + TBuf buf; + aValue.Output( buf ); + // Copy new address to safe + iAddress.Copy( buf ); + + // Copy network type and address type + SdpUtil::SetDefaultNetTypeAndAddrType( + iPool, aValue, iNetType, iAddressType ); + SetIPAddressType( aValue ); + } + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::SetAddressL +// Sets address from the buffer +// ----------------------------------------------------------------------------- +// +EXPORT_C void CSdpOriginField::SetAddressL( + const TDesC8& aAddress, + RStringF aNetType, + RStringF aAddressType ) + { + __TEST_INVARIANT; + + __ASSERT_ALWAYS( SdpUtil::IsToken( aNetType.DesC() ) && + SdpUtil::IsToken( aAddressType.DesC() ) && + IsValidAddress( aAddress ) && + TypeMatchesWithFormat( aAddress, + aAddressType.DesC(), iPool ), + User::Leave( KErrSdpCodecOriginField ) ); + + iAddress = aAddress; + iAddressType.Close(); + iAddressType = aAddressType.Copy(); + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::ExternalizeL +// Externalizes the field back to string +// ----------------------------------------------------------------------------- +// +void CSdpOriginField::ExternalizeL( + RWriteStream& aStream ) const + { + __TEST_INVARIANT; + + // + aStream.WriteUint32L( UserName().Length() ); + aStream.WriteL( UserName(), UserName().Length() ); + // + aStream.WriteUint32L( OriginFieldPtrs().SessionId().Length() ); + aStream.WriteL( OriginFieldPtrs().SessionId(), + OriginFieldPtrs().SessionId().Length() ); + // + aStream.WriteUint32L( OriginFieldPtrs().SessionVersion().Length() ); + aStream.WriteL( OriginFieldPtrs().SessionVersion(), + OriginFieldPtrs().SessionVersion().Length() ); + // + aStream.WriteUint32L( iNetType.DesC().Length() ); + aStream.WriteL( iNetType.DesC() ); + //
+ aStream.WriteUint32L( iAddressType.DesC().Length() ); + aStream.WriteL( iAddressType.DesC() ); + //
+ aStream.WriteUint32L( iAddress.Length() ); + aStream.WriteL( iAddress ); + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::InternalizeL +// Internalizes from stream +// ----------------------------------------------------------------------------- +// +CSdpOriginField* CSdpOriginField::InternalizeL( + RReadStream& aStream ) + { + RStringPool pool = SdpCodecStringPool::StringPoolL(); + + // + TUint32 length = aStream.ReadUint32L(); + HBufC8* userName = HBufC8::NewLC( length ); + TPtr8 ptr( userName->Des() ); + aStream.ReadL( ptr, length ); + + // + length = aStream.ReadUint32L(); + HBufC8* sessionId = HBufC8::NewLC( length ); + ptr.Set( sessionId->Des() ); + aStream.ReadL( ptr, length ); + + // + length = aStream.ReadUint32L(); + HBufC8* version = HBufC8::NewLC( length ); + ptr.Set( version->Des() ); + aStream.ReadL( ptr, length ); + + // + length = aStream.ReadUint32L(); + HBufC8* netType = HBufC8::NewLC( length ); + ptr.Set( netType->Des() ); + aStream.ReadL( ptr, length ); + + //
+ length = aStream.ReadUint32L(); + HBufC8* addrType = HBufC8::NewLC( length ); + ptr.Set( addrType->Des() ); + aStream.ReadL( ptr, length ); + + //
+ length = aStream.ReadUint32L(); + HBufC8* address = HBufC8::NewLC( length ); + TPtr8 ptr2( address->Des() ); + aStream.ReadL( ptr2, length ); + + RStringF netTypeStr = pool.OpenFStringL( *netType ); + RStringF addrTypeStr = pool.OpenFStringL( *addrType ); + CleanupClosePushL( netTypeStr ); + CleanupClosePushL( addrTypeStr ); + + CSdpOriginField* obj = CSdpOriginField::NewLC( *userName, KDummyValue, + KDummyValue, netTypeStr, + addrTypeStr, *address ); + // Set the real values + obj->OriginFieldPtrs().SetSessionIdL( *sessionId ); + obj->OriginFieldPtrs().SetSessionVersionL( *version ); + CleanupStack::Pop( obj ); + CleanupStack::Pop( 2 ); // addrTypeStr, netTypeStr + CleanupStack::PopAndDestroy( address ); + CleanupStack::PopAndDestroy( addrType ); + CleanupStack::PopAndDestroy( netType ); + CleanupStack::PopAndDestroy( version ); + CleanupStack::PopAndDestroy( sessionId ); + CleanupStack::PopAndDestroy( userName ); + + return obj; + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::IsValidAddress +// Checks if the address is valid +// ----------------------------------------------------------------------------- +// +TBool CSdpOriginField::IsValidAddress( + const TDesC8& aAddress ) const + { + TInetAddr addr; + TBool valid = ETrue; + + if ( aAddress.Length() > 0 && aAddress.Length() <= KMaxAddressLength ) + { + TBuf address16; + address16.Copy( aAddress ); + TInt err = addr.Input( address16 ); + + if ( !err ) + { + valid = ( addr.IsUnicast() || addr.IsUnspecified() ); + } + else + { + RStringF addrTypeIP4 = + iPool.StringF( SdpCodecStringConstants::EAddressTypeIP4, + SdpCodecStringConstants::Table ); + RStringF addrTypeIP6 = + iPool.StringF( SdpCodecStringConstants::EAddressType, + SdpCodecStringConstants::Table ); + + if ( iAddressType == addrTypeIP4 || iAddressType == addrTypeIP6 ) + { + // FQDN address, check that it has only valid characters + // 0..9, a..z, A..Z, '.', '-' + + for ( TInt i( 0 ); i < aAddress.Length() && valid; i++ ) + { + if (KValidFQDNChars().Locate(aAddress[i]) == KErrNotFound) + { + valid = EFalse; + } + } + } + else + { + valid = SdpUtil::IsNonWhitespace( aAddress ); + } + } + } + else + { + valid = EFalse; + } + + return valid; + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::IsValidAddress +// Checks if the address is valid +// ----------------------------------------------------------------------------- +// +TBool CSdpOriginField::IsValidAddress( + const TInetAddr& addr ) const + { + TBuf buf16; + TBuf8 buf; + //if addr is IPv4-Mapped IPv6, buf value will be IPv4 after Output + addr.Output( buf16 ); + buf.Copy( buf16 ); + + return IsValidAddress( buf ); + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::TypeMatchesWithFormat +// Checks if address type is aligned with the address format +// ----------------------------------------------------------------------------- +// +TBool CSdpOriginField::TypeMatchesWithFormat( + const TDesC8& aAddress, + const TDesC8& aType, + RStringPool aPool ) const + { + RStringF addrTypeIP4 = + aPool.StringF( SdpCodecStringConstants::EAddressTypeIP4, + SdpCodecStringConstants::Table ); + RStringF addrTypeIP6 = + aPool.StringF( SdpCodecStringConstants::EAddressType, + SdpCodecStringConstants::Table ); + + TBool valid( ETrue ); + + // Check that address type and address matches together + TInetAddr addr; + TBuf address16; + address16.Copy( aAddress ); + TInt err = addr.Input( address16 ); + if ( err == KErrNone && !addr.IsUnspecified()) + { + TBool ip4Type = ( addrTypeIP4.DesC().CompareF( aType ) == 0 ); + TBool ip6Type = ( addrTypeIP6.DesC().CompareF( aType ) == 0 ); + + if ( ip4Type || ip6Type ) + { + if ( ( addr.Address() && !addr.IsV4Mapped() && !ip4Type ) || + (addr.Address() && addr.IsV4Mapped() && !ip6Type) || + ( !addr.Address() && !ip6Type ) ) + { + valid = EFalse; + } + } + } + + return valid; + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::IsValidUserName +// Checks if the given username is valid +// ----------------------------------------------------------------------------- +// +TBool CSdpOriginField::IsValidUserName( + const TDesC8& aUserName ) const + { + TBool valid = EFalse; + + if ( aUserName.Length() > 0 && SdpUtil::IsNonWhitespace( aUserName ) ) + { + valid = ETrue; + } + + return valid; + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::ParseUserNameL +// Parses username. Can't use CSdpOriginField::SetUserNameL, as invariant would +// fail. +// ----------------------------------------------------------------------------- +// +void CSdpOriginField::ParseUserNameL( + RArray& aArray ) + { + __ASSERT_ALWAYS( IsValidUserName( aArray[KUserNameIndex] ), + User::Leave( KErrSdpCodecOriginField ) ); + OriginFieldPtrs().SetUserNameL( aArray[KUserNameIndex] ); + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::ParseSessionIDAndVersionL +// Parses session ID and version +// ----------------------------------------------------------------------------- +// +void CSdpOriginField::ParseSessionIDAndVersionL( + RArray& aArray ) + { + __ASSERT_ALWAYS( SdpUtil::IsDigit( aArray[KSessionIdIndex] ) && + SdpUtil::IsDigit( aArray[KSessionVersionIndex] ), + User::Leave( KErrSdpCodecOriginField ) ); + + OriginFieldPtrs().SetSessionIdL( aArray[KSessionIdIndex] ); + OriginFieldPtrs().SetSessionVersionL( aArray[KSessionVersionIndex] ); + } + + // ----------------------------------------------------------------------------- +// CSdpOriginField::ParseNetTypeAndAddressTypeL +// Parses network type and address type +// ----------------------------------------------------------------------------- +// +void CSdpOriginField::ParseNetTypeAndAddressTypeL( + RArray& aArray ) + { + if ( !SdpUtil::IsToken( aArray[KNetworkTypeIndex] ) || + !SdpUtil::IsToken( aArray[KAddressTypeIndex] ) ) + { + User::Leave( KErrSdpCodecOriginField ); + } + + iNetType = iPool.OpenFStringL( aArray[KNetworkTypeIndex] ); + iAddressType = iPool.OpenFStringL( aArray[KAddressTypeIndex] ); + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::ParseAddressL +// Parses address +// ----------------------------------------------------------------------------- +// +void CSdpOriginField::ParseAddressL( + RArray& aArray ) + { + if ( !IsValidAddress( aArray[KAddressIndex] ) ) + { + User::Leave( KErrSdpCodecOriginField ); + } + else + { + iAddress = aArray[KAddressIndex]; + } + + // Check that address type and address matches together + if ( !TypeMatchesWithFormat( + aArray[KAddressIndex], aArray[KAddressTypeIndex], iPool ) ) + { + User::Leave( KErrSdpCodecOriginField ); + } + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::OriginFieldPtrs +// ----------------------------------------------------------------------------- +// +inline CSdpOriginFieldPtrs& CSdpOriginField::OriginFieldPtrs() + { + return *( reinterpret_cast< CSdpOriginFieldPtrs* >( iUserName ) ); + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::OriginFieldPtrs +// ----------------------------------------------------------------------------- +// +inline const CSdpOriginFieldPtrs& CSdpOriginField::OriginFieldPtrs() const + { + return *( reinterpret_cast< CSdpOriginFieldPtrs* >( iUserName ) ); + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::Get63Msbs +// Returns a maximum of 63 bits of information from the descriptor containing a +// decimal number. +// ----------------------------------------------------------------------------- +// +TInt64 CSdpOriginField::Get63Msbs( const TDesC8& aDecimalValue ) const + { + // The maximum amount of digits in a decimal number, that is guaranteed to + // fit into 63 bits, is 18. Even if all the 18 digits are 9, the decimal + // number is 999999999999999999. + const TInt64 KMaxAmountOfDecimalDigits = 18; + + TInt64 value( 0 ); + TPtrC8 msbPart = aDecimalValue.Left( KMaxAmountOfDecimalDigits ); + TLex8( msbPart ).Val( value ); + return value; + } + +// ----------------------------------------------------------------------------- +// CSdpOriginField::SetIPAddressType +// ----------------------------------------------------------------------------- +// +void CSdpOriginField::SetIPAddressType( const TInetAddr& aAddr ) + { + iAddressType.Close(); + if ( aAddr.Address() || aAddr.IsUnspecified() ) + { + //IPv4, IPv4-Mapped IPv6 and 0.0.0.0 + iAddressType = + iPool.StringF( SdpCodecStringConstants::EAddressTypeIP4, + SdpCodecStringConstants::Table ).Copy(); + } + else + { + //IPv6 + iAddressType = + iPool.StringF( SdpCodecStringConstants::EAddressType, + SdpCodecStringConstants::Table ).Copy(); + } + } + +// For DEBUG builds + +// ----------------------------------------------------------------------------- +// CSdpOriginField::__DbgTestInvariant +// Test invariant +// ----------------------------------------------------------------------------- +// +void CSdpOriginField::__DbgTestInvariant() const + { + TBool invariant = + iUserName != NULL + && SdpUtil::IsToken( iAddressType.DesC() ) + && SdpUtil::IsToken( iNetType.DesC() ) + && IsValidAddress( iAddress ) + && IsValidUserName( OriginFieldPtrs().UserName() ) + && TypeMatchesWithFormat(iAddress, iAddressType.DesC(), iPool) + && SdpUtil::IsNonWhitespace( OriginFieldPtrs().UserName() ); + + if ( !invariant ) + { + User::Invariant(); + } + } +