diff -r 000000000000 -r 307788aac0a8 realtimenetprots/sipfw/SDP/src/SdpConnectionField.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/realtimenetprots/sipfw/SDP/src/SdpConnectionField.cpp Tue Feb 02 01:03:15 2010 +0200 @@ -0,0 +1,1155 @@ +// 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 : SdpConnectionField.cpp +// Part of : SDP Codec +// Version : 1.0 +// + + + + +#include +#include +#include +#include "SdpConnectionField.h" +#include "sdpcodecstringconstants.h" +#include "SdpCodecConstants.h" +#include "SdpCodecStringPool.h" +#include "SdpUtil.h" +#include "SdpCodecErr.h" +#include "SDPCodec.pan" +#include "_sdpdefs.h" +#include "uriutils.h" + +// LOCAL CONSTANTS +const TInt KHeaderIndex = 0; +const TInt KNetworkTypeIndex = 1; +const TInt KAddressTypeIndex = 2; +const TInt KAddressIndex = 3; +const TInt KTokenCount = 4; +const TInt KMaxAddressLength = 256; +const TUint KMaxIPDesLength = 39; +_LIT16(KWildAddr, "0.0.0.0"); +_LIT16(KWildAddrIPv6, "::"); + + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::CSdpConnectionField +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CSdpConnectionField::CSdpConnectionField() : + iTTL( KErrNotFound ), + iNumOfAddress( KDefaultNumOfAddress ) + { + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CSdpConnectionField::ConstructL( + const TDesC8& aText ) + { + // aText should be in format + // c=
+ iPool = SdpCodecStringPool::StringPoolL(); + + RArray array = + SdpUtil::GetElementsFromLineL( aText, KErrSdpCodecConnectionField ); + CleanupClosePushL( array ); + + if ( array.Count() != KTokenCount ) + { + User::Leave( KErrSdpCodecConnectionField ); + } + + RStringF origHeader = iPool.StringF( SdpCodecStringConstants::EConnection, + SdpCodecStringConstants::Table ); + if ( origHeader.DesC().CompareF( array[KHeaderIndex] ) != 0 ) + { + // Header didn't match + User::Leave( KErrSdpCodecConnectionField ); + } + + // + CopyNetTypeL( array[KNetworkTypeIndex] ); + + //
+ CopyAddressTypeL( array[KAddressTypeIndex] ); + + //
+ CopyAddressL( array[KAddressIndex], iPool ); + + CleanupStack::PopAndDestroy(); // array + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CSdpConnectionField::ConstructL( + const TInetAddr& aAddress, + TInt aTTL, + TUint aNumOfAddress ) + { + __ASSERT_ALWAYS( IsValidAddress(aAddress, aTTL, aNumOfAddress) == KErrNone, + User::Leave( KErrSdpCodecConnectionField ) ); + + iPool = SdpCodecStringPool::StringPoolL(); + TBuf addr; + //If aAddress is IPv4-Mapped IPv6,the result of Output is IPv4 + aAddress.Output( addr ); + + // Copy address + iAddress = HBufC8::NewL( addr.Length() ); + iAddress->Des().Copy( addr ); + + // TTL + iTTL = aTTL; + // Num of addresses + iNumOfAddress = aNumOfAddress; + // Network type + iNetType = iPool.StringF( SdpCodecStringConstants::ENetType, + SdpCodecStringConstants::Table ).Copy(); + // Address type + if ( UriUtils::HostType( addr ) == UriUtils::EIPv4Host ) + { + //addresstype for IPv4 + iAddressType = iPool.StringF( SdpCodecStringConstants::EAddressTypeIP4, + SdpCodecStringConstants::Table ).Copy(); + } + else if ( UriUtils::HostType( addr ) == UriUtils::EIPv6Host ) + { + //addresstype IPv6 + iAddressType = iPool.StringF( SdpCodecStringConstants::EAddressType, + SdpCodecStringConstants::Table ).Copy(); + } + else + { + User::Leave(KErrArgument); + } + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CSdpConnectionField::ConstructL( + RStringF aNetType, + RStringF aAddressType, + const TDesC8& aAddress ) + { + iPool = SdpCodecStringPool::StringPoolL(); + + // Network type + CopyNetTypeL( aNetType.DesC() ); + + // Address type + CopyAddressTypeL( aAddressType.DesC() ); + + // Address + TTL + numOfAddress + CopyAddressL( aAddress, aNetType.Pool() ); + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::DecodeL +// Two-phased constructor +// ----------------------------------------------------------------------------- +// +EXPORT_C CSdpConnectionField* CSdpConnectionField::DecodeL( + const TDesC8& aText ) + { + CSdpConnectionField* obj = CSdpConnectionField::DecodeLC( aText ); + CleanupStack::Pop(); + return obj; + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::DecodeLC +// Two-phased constructor +// ----------------------------------------------------------------------------- +// +EXPORT_C CSdpConnectionField* CSdpConnectionField::DecodeLC( + const TDesC8& aText ) + { + CSdpConnectionField* obj = new ( ELeave ) CSdpConnectionField; + CleanupStack::PushL( obj ); + obj->ConstructL( aText ); + return obj; + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::NewL +// Two-phased constructor +// ----------------------------------------------------------------------------- +// +EXPORT_C CSdpConnectionField* CSdpConnectionField::NewL( + const TInetAddr& aAddress, + TInt aTTL, + TUint aNumOfAddress ) + { + CSdpConnectionField* obj = CSdpConnectionField::NewLC( + aAddress, aTTL, aNumOfAddress ); + CleanupStack::Pop(); + return obj; + } +// ----------------------------------------------------------------------------- +// CSdpConnectionField::NewLC +// Two-phased constructor +// ----------------------------------------------------------------------------- +// +EXPORT_C CSdpConnectionField* CSdpConnectionField::NewLC( + const TInetAddr& aAddress, + TInt aTTL, + TUint aNumOfAddress ) + { + CSdpConnectionField* obj = new ( ELeave ) CSdpConnectionField; + CleanupStack::PushL( obj ); + obj->ConstructL( aAddress, aTTL, aNumOfAddress ); + return obj; + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::NewL +// Two-phased constructor +// ----------------------------------------------------------------------------- +// +EXPORT_C CSdpConnectionField* CSdpConnectionField::NewL( + RStringF aNetType, + RStringF aAddressType, + const TDesC8& aAddress ) + { + CSdpConnectionField* obj = CSdpConnectionField::NewLC( + aNetType, aAddressType, aAddress ); + CleanupStack::Pop(); + return obj; + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::NewLC +// Two-phased constructor +// ----------------------------------------------------------------------------- +// +EXPORT_C CSdpConnectionField* CSdpConnectionField::NewLC( + RStringF aNetType, + RStringF aAddressType, + const TDesC8& aAddress ) + { + CSdpConnectionField* obj = new ( ELeave ) CSdpConnectionField; + CleanupStack::PushL( obj ); + obj->ConstructL( aNetType, aAddressType, aAddress ); + return obj; + } + +// Destructor +EXPORT_C CSdpConnectionField::~CSdpConnectionField() + { + delete iAddress; + iNetType.Close(); + iAddressType.Close(); + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::EncodeL +// Writes attributes in proper format to the stream +// ----------------------------------------------------------------------------- +// +EXPORT_C void CSdpConnectionField::EncodeL( + RWriteStream& aStream ) const + { + __TEST_INVARIANT; + TBuf8<20> number; // Is enough for addr as well + + // c=
+ RStringF header = iPool.StringF( SdpCodecStringConstants::EConnection, + SdpCodecStringConstants::Table ); + aStream.WriteL( header.DesC() ); + + // Network type + aStream.WriteL( iNetType.DesC() ); + aStream.WriteL( KSPStr ); + + // Address type + aStream.WriteL( iAddressType.DesC() ); + aStream.WriteL( KSPStr ); + + // Connection address + aStream.WriteL( *iAddress ); + if ( iTTL != KErrNotFound ) + { + number.Zero(); + number.Append( KSlashStr ); + number.AppendFormat( _L8("%d"), iTTL ); + aStream.WriteL( number ); + } + + if ( iNumOfAddress > 1 ) + { + number.Zero(); + number.Append( KSlashStr ); + number.AppendFormat( _L8("%u"), iNumOfAddress ); + aStream.WriteL( number ); + } + + // End-of-Line mark + aStream.WriteL( KCRLFStr ); + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::CloneL +// Clones an exact copy of this object +// ----------------------------------------------------------------------------- +// +EXPORT_C CSdpConnectionField* CSdpConnectionField::CloneL() const + { + __TEST_INVARIANT; + + CSdpConnectionField* obj = NULL; + const TInetAddr* addr = InetAddress(); + + if ( addr ) + { + // Could be anything + obj = CSdpConnectionField::NewL( *addr, iTTL, iNumOfAddress ); + } + else + { + // Unicast FQDN address + obj = CSdpConnectionField::NewL( iNetType, iAddressType, *iAddress ); + } + + __ASSERT_DEBUG( *this == *obj, User::Panic( + KSdpCodecPanicCat, KSdpCodecPanicInternal)); + return obj; + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::operator== +// Checks if two origin fields are equal +// ----------------------------------------------------------------------------- +// +EXPORT_C TBool CSdpConnectionField::operator== ( + const CSdpConnectionField& aObj ) const + { + __TEST_INVARIANT; + + TBool equal( EFalse ); + + if ( (*iAddress).CompareF( aObj.Address() ) == 0 && + NetType() == aObj.NetType() && + AddressType() == aObj.AddressType() && + TTLValue() == aObj.TTLValue() && + NumOfAddress() == aObj.NumOfAddress() ) + { + // All attributes match, two fields are equal + equal = ETrue; + } + + return equal; + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::NetType +// Returns network type +// ----------------------------------------------------------------------------- +// +EXPORT_C RStringF CSdpConnectionField::NetType() const + { + __TEST_INVARIANT; + return iNetType; + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::AddressType +// Returns address type +// ----------------------------------------------------------------------------- +// +EXPORT_C RStringF CSdpConnectionField::AddressType() const + { + __TEST_INVARIANT; + return iAddressType; + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::InetAddress +// Returns address in TInetAddr format if possible +// ----------------------------------------------------------------------------- +// +EXPORT_C const TInetAddr* CSdpConnectionField::InetAddress() const + { + __TEST_INVARIANT; + + TInetAddr* addr = NULL; + TBuf addr16; + + addr16.Copy( iAddress->Des() ); + TInt err = iInetAddress.Input( addr16 ); + + if ( err == KErrNone ) + { + addr = &iInetAddress; + } + + return addr; + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::Address +// Returns address in TDesC8 format +// ----------------------------------------------------------------------------- +// +EXPORT_C const TDesC8& CSdpConnectionField::Address() const + { + return *iAddress; + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::SetInetAddressL +// Sets address from TInetAddr +// ----------------------------------------------------------------------------- +// +EXPORT_C void CSdpConnectionField::SetInetAddressL( + const TInetAddr& aAddress, + TInt aTTL, + TUint aNumOfAddress ) + { + __TEST_INVARIANT; + + if ( IsValidAddress( aAddress, aTTL, aNumOfAddress ) == KErrNone ) + { + TBuf addr16; + //If aAddress IPv4-Mapped IPv6, result of Output IPv4 + aAddress.Output( addr16 ); + + HBufC8* tempBuf = HBufC8::NewL( addr16.Length() ); + tempBuf->Des().Copy( addr16 ); + + SdpUtil::SetDefaultNetTypeAndAddrType( + iPool, aAddress, iNetType, iAddressType ); + if(aAddress.Address() && aAddress.IsV4Mapped()) + { + iAddressType.Close(); + iAddressType = iPool.StringF( SdpCodecStringConstants::EAddressTypeIP4, + SdpCodecStringConstants::Table ).Copy(); + } + // Set address + delete iAddress; + iAddress = tempBuf; + // Set attributes for address + iTTL = aTTL; + iNumOfAddress = aNumOfAddress; + } + else + { + User::Leave( KErrSdpCodecConnectionField ); + } + + __TEST_INVARIANT; + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::SetAddressL +// Sets new address and types, leaves on error +// ----------------------------------------------------------------------------- +// +EXPORT_C void CSdpConnectionField::SetAddressL( + RStringF aNetType, + RStringF aAddressType, + const TDesC8& aAddress ) + { + __TEST_INVARIANT; + TInt err( KErrNone ); + RStringF netTypeBackup = iNetType.Copy(); + RStringF addressTypeBackup = iAddressType.Copy(); + CleanupClosePushL( netTypeBackup ); + CleanupClosePushL( addressTypeBackup ); + + TRAP( err, CopyNetTypeL( aNetType.DesC() ) ); + if ( !err ) + { + // Netowrk type changed successfully + TRAP( err, CopyAddressTypeL( aAddressType.DesC() ) ); + if ( !err ) + { + // Address type & network type changed successfully + TRAP( err, CopyAddressL( aAddress, iAddressType.Pool() ) ); + + if ( err ) + { + // Place back old netType & address + iNetType.Close(); + iNetType = netTypeBackup.Copy(); + + iAddressType.Close(); + iAddressType = addressTypeBackup.Copy(); + + User::LeaveIfError( err ); + } + // Everything changed succesfully + } + else + { + // Place back old netType + iNetType.Close(); + iNetType = netTypeBackup.Copy(); + + User::LeaveIfError( err ); + } + } + else + { + User::LeaveIfError( err ); + } + + CleanupStack::PopAndDestroy( 2 ); // netTypeBackup, addressTypeBackup + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::TTLValue +// Returns TTL attribute +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt CSdpConnectionField::TTLValue() const + { + __TEST_INVARIANT; + return iTTL; + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::SetTTLL +// Sets new TTL attribute value, leaves on error +// ----------------------------------------------------------------------------- +// +EXPORT_C void CSdpConnectionField::SetTTLL( + TInt aTTL ) + { + __TEST_INVARIANT; + + const TInetAddr* addr = InetAddress(); + + // FQDN; Unicast, can be only KErrNotFound + // IP4 Multicast: 0 <= TTL <= 255 + // IP4 Unicast, can be only KErrNotFound + // IP6 can be only KErrNotFound + + if ( ( !addr && aTTL != KErrNotFound ) || + ( addr && addr->Address() && addr->IsMulticast() && + ( aTTL < 0 || aTTL > 255 ) ) || + ( addr && addr->Address() && !addr->IsMulticast() && + aTTL != KErrNotFound ) || + ( addr && !addr->Address() && aTTL != KErrNotFound ) ) + { + User::Leave( KErrSdpCodecConnectionField ); + } + + iTTL = aTTL; + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::NumOfAddress +// Returns number of continuous addresses for multicast +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt CSdpConnectionField::NumOfAddress() const + { + return iNumOfAddress; + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::SetNumOfAddressL +// Sets number of addresses +// ----------------------------------------------------------------------------- +// +EXPORT_C void CSdpConnectionField::SetNumOfAddressL( + TUint aNumOfAddress ) + { + const TInetAddr* addr = InetAddress(); + if ( aNumOfAddress < 1 || ( !addr && aNumOfAddress != 1 ) || + ( addr && !addr->IsMulticast() && aNumOfAddress != 1 ) ) + { + User::Leave( KErrSdpCodecConnectionField ); + } + + iNumOfAddress = aNumOfAddress; + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::ExternalizeL +// Externalizes the object to stream +// ----------------------------------------------------------------------------- +// +void CSdpConnectionField::ExternalizeL( + RWriteStream& aStream ) const + { + __TEST_INVARIANT; + + // Address + aStream.WriteUint32L( iAddress->Des().Length() ); + aStream.WriteL( iAddress->Des(), iAddress->Des().Length() ); + // TTL + aStream.WriteInt32L( iTTL ); + // Number of addresses + aStream.WriteInt32L( iNumOfAddress ); + // + aStream.WriteUint32L( iNetType.DesC().Length() ); + aStream.WriteL( iNetType.DesC() ); + //
+ aStream.WriteUint32L( iAddressType.DesC().Length() ); + aStream.WriteL( iAddressType.DesC() ); + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::InternalizeL +// Internalizes the object from stream +// ----------------------------------------------------------------------------- +// +CSdpConnectionField* CSdpConnectionField::InternalizeL( + RReadStream& aStream ) + { + TUint32 length; + CSdpConnectionField* obj = NULL; + RStringPool pool = SdpCodecStringPool::StringPoolL(); + + // address + length = aStream.ReadUint32L(); + HBufC8* address = HBufC8::NewLC( length ); + TPtr8 ptr( address->Des() ); + aStream.ReadL( ptr, length ); + // TTL + TInt ttl = aStream.ReadInt32L(); + // Number of addresses + TInt numOfAddr = aStream.ReadInt32L(); + // Network type + length = aStream.ReadUint32L(); + HBufC8* netType = HBufC8::NewLC( length ); + ptr.Set( netType->Des() ); + aStream.ReadL( ptr, length ); + // Address type + length = aStream.ReadUint32L(); + HBufC8* addrType = HBufC8::NewLC( length ); + ptr.Set( addrType->Des() ); + aStream.ReadL( ptr, length ); + + TInetAddr addr; + HBufC* address16 = HBufC::NewLC( address->Length() ) ; + address16->Des().Copy( *address ); + TInt err = addr.Input( *address16 ); + + if ( !err ) + { + // Create connection field based on TInetAddr + obj = CSdpConnectionField::NewL( addr, ttl, numOfAddr ); + } + else + { + // Create connection field from buffer, ttl & numOfAddr + // are in this case irrelevant + RStringF netTypeStr = pool.OpenFStringL( *netType ); + CleanupClosePushL( netTypeStr ); + RStringF addrTypeStr = pool.OpenFStringL( *addrType ); + CleanupClosePushL( addrTypeStr ); + obj = CSdpConnectionField::NewL( netTypeStr, addrTypeStr, *address ); + CleanupStack::PopAndDestroy( 2 ); // netTypeStr, addrTypeStr + } + + CleanupStack::PopAndDestroy( 4 ); // address, netType, addrType, address16 + return obj; + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::IsValidAddress +// Checks if the given address is valid +// ----------------------------------------------------------------------------- +// +TInt CSdpConnectionField::IsValidAddress( + TBool aAddressTypeIP4, + const TDesC8& aAddress ) const + { + HBufC8* address = NULL; + TInt ttl( 0 ); + TUint num( 0 ); + + TRAPD( err, address = + ParseAddressFieldL( aAddressTypeIP4, aAddress, ttl, num ) ); + delete address; + + return err; + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::IsValidAddress +// Checks if the given address is valid +// ----------------------------------------------------------------------------- +// +TInt CSdpConnectionField::IsValidAddress( + const TInetAddr& aAddress, + TInt aTTL, + TUint aNumOfAddress ) const + { + TInt err( KErrSdpCodecConnectionField ); + // 0 <= TTL <= 255 or KErrNotFound if not defined + // Number of addresses > 0 + if ( ( aTTL == KErrNotFound || ( aTTL >= 0 && aTTL <= 255 ) ) && + aNumOfAddress > 0 ) + { + TBuf16 output; + aAddress.Output(output); + + // Address has to be either of type IP4 or IP6 + // If IP4 and multicast then it must contain TTL attribute + // If IP4 and unicast then it must NOT contain TTL and must have 1 address + // If IP6 and multicast then it must NOT contain TTL + // If IP6 and unicast then it must NOT contain TTL and must have 1 address + if ( ( aAddress.Address() && + ( ( aAddress.IsMulticast() && aTTL != KErrNotFound ) || + ( aAddress.IsUnicast() && aTTL == KErrNotFound && + aNumOfAddress == 1 ) ) ) || + ( !aAddress.Address() && + ( ( aAddress.IsMulticast() && aTTL == KErrNotFound ) || + ( aAddress.IsUnicast() && aTTL == KErrNotFound && + aNumOfAddress == 1 ) ) || + ( aAddress.IsWildAddr() && + ( output.Match(KWildAddr) == 0|| + output.Match(KWildAddrIPv6) == 0 )) ) ) + { + err = KErrNone; + } + } + + return err; + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::ParseAddressFieldL +// Format the address field +// ----------------------------------------------------------------------------- +// +HBufC8* CSdpConnectionField::ParseAddressFieldL( + TBool aAddressTypeIP4, + const TDesC8& aAddress, + TInt& aTTL, + TUint& aNumberOfAddresses ) const + { + HBufC8* address = NULL; + + if ( aAddress.Length() > 0 && aAddress.Length() <= KMaxAddressLength ) + { + // IP4 address + TInetAddr addr; + TBuf buf16; + + // IP address lasts till first separator mark + TInt pos = aAddress.Locate( KSlashChar ); + if ( pos == KErrNotFound ) + { + pos = aAddress.Length(); + } + buf16.Copy( aAddress.Left( pos ) ); + + // Try to convert the string to TInetAddr + TInt err = addr.Input( buf16 ); + + //Type and address check + TBuf16 output; + addr.Output(output); + if (err == KErrNone) + { + if (addr.Address() ) + { + if ( (addr.IsV4Mapped() && aAddressTypeIP4) || + (!addr.IsV4Mapped() && !aAddressTypeIP4) ) + { + User::Leave( KErrSdpCodecConnectionField ); + } + else + { + // IP4 address + address = ParseIP4AddressL( pos, addr, aAddress, aTTL, + aNumberOfAddresses ); + } + } + else + { + if ( !aAddressTypeIP4) + { + // IP6 address + address = ParseIP6AddressL( pos, addr, aAddress, aTTL, + aNumberOfAddresses ); + } + else if ( addr.IsWildAddr() && output.Match(KWildAddr) == 0 ) + { + // 0.0.0.0 + address = ParseIP4AddressL( pos, addr, aAddress, aTTL, + aNumberOfAddresses ); + } + else + { + User::Leave( KErrSdpCodecConnectionField ); + } + } + } + else + { + // FQDN + // Clarify that the address contains only valid FQDN chars + // This is always unicast + for ( TInt i( 0 ); i < aAddress.Length(); i++ ) + { + if ( KValidFQDNChars().Locate( aAddress[i] ) == + KErrNotFound ) + { + User::Leave( KErrSdpCodecConnectionField ); + } + } + address = aAddress.AllocL(); + aTTL = KErrNotFound; + aNumberOfAddresses = 1; + } + + } + else + { + User::Leave( KErrSdpCodecConnectionField ); + } + + return address; + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::ParseIP4AddressL +// Parses IP4 address and checks that it is valid +// ----------------------------------------------------------------------------- +// +HBufC8* CSdpConnectionField::ParseIP4AddressL( + TInt aPos, + TInetAddr& aAddr, + const TDesC8& aAddress, + TInt& aTTL, + TUint& aNumberOfAddresses ) const + { + HBufC8* address = NULL; + + if ( aAddr.IsMulticast() ) + { + // Multicast address - MUST contain TTL and possibly + // number of addresses + if ( aPos != aAddress.Length() ) + { + TInt pos2 = aAddress.Right( aAddress.Length() - aPos - 1 ).Locate( + KSlashChar ); + + if ( pos2 != KErrNotFound ) + { + pos2 += aPos + 1; + + // Validity check for number strings + TBool digit = SdpUtil::IsDigit( + aAddress.Mid( aPos + 1, pos2 - aPos - 1 ) ); + digit = digit && SdpUtil::IsDigit( + aAddress.Mid( pos2 + 1, aAddress.Length() - pos2 - 1 ) ); + if ( !digit ) + { + User::Leave( KErrSdpCodecConnectionField ); + } + + // TTL & number of addresses + User::LeaveIfError( + TLex8( aAddress.Mid( aPos + 1, pos2 - aPos - 1 ) ).Val( + aTTL ) ); + User::LeaveIfError( + TLex8( aAddress.Mid( + pos2 + 1, aAddress.Length() - pos2 - 1 ) ).Val( + aNumberOfAddresses, EDecimal ) ); + + __ASSERT_ALWAYS( aTTL >= 0 + && aTTL <= 255 + && aNumberOfAddresses > 0, + User::Leave( KErrSdpCodecConnectionField ) ); + } + else + { + // Validity check for number strings + TBool digit = SdpUtil::IsDigit( + aAddress.Mid( aPos + 1, aAddress.Length() - aPos - 1 ) ); + if ( !digit ) + { + User::Leave( KErrSdpCodecConnectionField ); + } + + // Plain TTL + User::LeaveIfError( + TLex8( aAddress.Mid( + aPos + 1, aAddress.Length() - aPos - 1 ) ).Val( + aTTL ) ); + aNumberOfAddresses = 1; + + __ASSERT_ALWAYS( aTTL >= 0 && aTTL <= 255, + User::Leave( KErrSdpCodecConnectionField ) ); + } + + address = aAddress.Left( aPos ).AllocL(); + } + else + { + User::Leave( KErrSdpCodecConnectionField ); + } + } + else + { + // Unicast address - cannot contain any multicast TTLs etc. + if ( aPos == aAddress.Length() ) + { + address = aAddress.AllocL(); + aTTL = KErrNotFound; + aNumberOfAddresses = 1; + } + else + { + User::Leave( KErrSdpCodecConnectionField ); + } + } + + return address; + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::ParseIP6AddressL +// Parses IP6 address and checks that it is valid +// ----------------------------------------------------------------------------- +// +HBufC8* CSdpConnectionField::ParseIP6AddressL( + TInt aPos, + TInetAddr& aAddr, + const TDesC8& aAddress, + TInt& aTTL, + TUint& aNumberOfAddresses ) const + { + HBufC8* address = NULL; + + if ( aAddr.IsMulticast() ) + { + // Multicast address - CAN contain one extra attribute, + // number of addresses + if ( aPos != aAddress.Length() ) + { + // Validity check for number strings + + TBool digit = SdpUtil::IsDigit( + aAddress.Mid( aPos + 1, aAddress.Length() - aPos - 1 ) ); + if ( !digit ) + { + User::Leave( KErrSdpCodecConnectionField ); + } + + User::LeaveIfError( TLex8( aAddress.Mid( + aPos + 1, aAddress.Length() - aPos - 1 ) ).Val( + aNumberOfAddresses, EDecimal ) ); + + __ASSERT_ALWAYS( aNumberOfAddresses > 0, + User::Leave( KErrSdpCodecConnectionField ) ); + } + else + { + aNumberOfAddresses = 1; + } + + aTTL = KErrNotFound; // IP6 does not use TTL + address = aAddress.Left( aPos ).AllocL(); + } + else + { + // Unicast address - cannot contain any multicast TTLs etc. + if ( aPos == aAddress.Length() ) + { + address = aAddress.AllocL(); + aTTL = KErrNotFound; + aNumberOfAddresses = 1; + } + else + { + User::Leave( KErrSdpCodecConnectionField ); + } + } + + return address; + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::CopyNetTypeL +// Copies network type to object after checking that it is valid +// ----------------------------------------------------------------------------- +// +void CSdpConnectionField::CopyNetTypeL( + const TDesC8& aNetType ) + { + if ( !SdpUtil::IsToken( aNetType ) ) + { + User::Leave( KErrSdpCodecConnectionField ); + } + else + { + RStringF netType = iPool.OpenFStringL( aNetType ); + iNetType.Close(); + iNetType = netType; + } + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::CopyAddressTypeL +// Copies address type after checking that it is valid +// ----------------------------------------------------------------------------- +// +void CSdpConnectionField::CopyAddressTypeL( + const TDesC8& aAddrType ) + { + if ( !SdpUtil::IsToken( aAddrType ) ) + { + User::Leave( KErrSdpCodecConnectionField ); + } + else + { + RStringF addrType = iPool.OpenFStringL( aAddrType ); + iAddressType.Close(); + iAddressType = addrType; + } + } + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::CopyAddressL +// Copies address after checking that it is valid +// ----------------------------------------------------------------------------- +// +void CSdpConnectionField::CopyAddressL( + const TDesC8& aAddress, + RStringPool aPool ) + { + RStringF addrTypeIP4 = aPool.StringF( + SdpCodecStringConstants::EAddressTypeIP4, + SdpCodecStringConstants::Table ); + RStringF addrTypeIP6 = aPool.StringF( + SdpCodecStringConstants::EAddressType, + SdpCodecStringConstants::Table ); + HBufC8* addr = NULL; + + if ( iAddressType == addrTypeIP4 || iAddressType == addrTypeIP6 ) + { + User::LeaveIfError( + IsValidAddress( iAddressType == addrTypeIP4, aAddress ) ); + + addr = ParseAddressFieldL( iAddressType == addrTypeIP4, aAddress, + iTTL, iNumOfAddress ); + //If address is IPv4-Mapped IPv6 , it is changed to IPv4 + TInetAddr inetaddr; + TBuf address; + address.Copy(*addr); + TInt err = inetaddr.Input(address); + TBuf16 output; + inetaddr.Output(output); + if(!err && + ( ( inetaddr.Address() && inetaddr.IsV4Mapped() ) || + ( inetaddr.IsWildAddr() && output.Match(KWildAddr) != KErrNotFound ) + ) ) + {//IPv4-Mapped IPv6 is changed to IPv4 address + TBuf buf; + inetaddr.Output( buf ); + // Copy new address to safe + delete addr; + addr = NULL; + addr = HBufC8::NewL(buf.Length()); + addr->Des().Copy(buf); + iAddressType.Close(); + iAddressType = + iPool.StringF(SdpCodecStringConstants::EAddressTypeIP4, + SdpCodecStringConstants::Table ).Copy(); + } + + } + else + { + // Address not IP4 or IP6, must be then non-ws-string + if ( SdpUtil::IsNonWhitespace( aAddress ) ) + { + addr = aAddress.AllocL(); + } + else + { + User::Leave( KErrSdpCodecConnectionField ); + } + } + + delete iAddress; + iAddress = addr; + } + +// For DEBUG builds + +// ----------------------------------------------------------------------------- +// CSdpConnectionField::__DbgTestInvariant +// Test invariant +// ----------------------------------------------------------------------------- +// + +void CSdpConnectionField::__DbgTestInvariant() const + { + TBool validAddr = EFalse; + + RStringF addrTypeIP4 = iPool.StringF( + SdpCodecStringConstants::EAddressTypeIP4, + SdpCodecStringConstants::Table ); + RStringF addrTypeIP6 = iPool.StringF( + SdpCodecStringConstants::EAddressType, + SdpCodecStringConstants::Table ); + + if ( iAddress && + ( iAddressType == addrTypeIP4 || iAddressType == addrTypeIP6 ) ) + { + TInetAddr addr; + TBuf buf16; + buf16.Copy( *iAddress ); + TInt err = addr.Input( buf16 ); + if ( !err ) + { + validAddr = IsValidAddress(addr, iTTL, iNumOfAddress) == KErrNone; + } + else + { + // FQDN unicast + if ( iTTL == KErrNotFound && iNumOfAddress == 1 ) + { + validAddr = ETrue; + } + } + } + + TBool invariant = ( SdpUtil::IsToken( iNetType.DesC() ) && + SdpUtil::IsToken( iAddressType.DesC() ) && + iAddress && SdpUtil::IsNonWhitespace( *iAddress ) && + validAddr ); + + if ( !invariant ) + { + User::Invariant(); + } + } + +