diff -r 000000000000 -r dfb7c4ff071f datacommsserver/esockserver/csock/cs_subconn.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/datacommsserver/esockserver/csock/cs_subconn.cpp Thu Dec 17 09:22:25 2009 +0200 @@ -0,0 +1,1367 @@ +// 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: +// + +/** + @file cs_subconn.cpp +*/ + +#include +#include +#include + +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include +#include +#endif + + +#include +#include +#include +#include +#include + + +#ifdef _DEBUG +// Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module +// (if it could happen through user error then you should give it an explicit, documented, category + code) +_LIT(KSpecAssert_ESockCSockcssbcn, "ESockCSockcssbcn"); +#endif + +using Meta::STypeId; + +EXPORT_C CSubConParameterSet* CSubConParameterSet::NewL(const STypeId& aTypeId) +/** Creates a new sub-connection parameter set using ECOM to load the DLL plugin + that implements the set. + +@param aTypeId Id of the class (Composed of Uid of the implementation and an integer sub-type +@return a generic pointer to a specific parameter set if successful, otherwise leaves with system error code. +*/ + { + return static_cast(Meta::SMetaDataECom::NewInstanceL(aTypeId)); + } + +CSubConParameterSet::~CSubConParameterSet() +/** Empty (virtual) sub-connection parameter set destructor +*/ + { + } + +CSubConParameterSet::CSubConParameterSet() +/** Empty sub-connection parameter set constructor +*/ + { + } + +EXPORT_C CSubConGenericParameterSet::~CSubConGenericParameterSet() +/** Empty (virtual) sub-connection generic parameter set destructor +*/ + { + LOG( ESockLog::Printf(_L8("CSubConGenericParameterSet::~CSubConGenericParameterSet() %08x"), this);); + } + +EXPORT_C CSubConGenericParameterSet::CSubConGenericParameterSet() +/** Empty sub-connection generic parameter set constructor +*/ + { + LOG( ESockLog::Printf(_L8("CSubConGenericParameterSet::CSubConGenericParameterSet() %08x"), this);); + } + +EXPORT_C CSubConExtensionParameterSet::~CSubConExtensionParameterSet() +/** Empty (virtual) sub-connection extension parameter set destructor +*/ + { + } + +EXPORT_C CSubConExtensionParameterSet::CSubConExtensionParameterSet() +/** Empty sub-connection extension parameter set constructor +*/ + { + } + +EXPORT_C CSubConParameterFamily* CSubConParameterFamily::NewL(RSubConParameterBundle& aBundle, TUint32 aFamilyId) +/** Creates a new sub-connection parameter set family. This class is used as a container for a number of parameter + sets (generic and extension) that make up a family. It is a specific instantiatable class and therefore creates + an instance of CSubConParameterFamily without using ECOM. + +Note: +The aBundle parameter that is passed into this method will take ownership of the newly created +CSubConParameterFamily object. When the bundle is destroyed, this family object will also be +destroyed (along with any parameter sets that are owned by the family). + +@param aBundle Family container (bundle) that this family is to be added to +@param aFamilyId identifier for the specific family type, currently only 4, QoS (KSubConQoSFamily),Authorisation (KSubConAuthorisationFamily), +CallDescrParams (KSubConnCallDescrParamsFamily) and ContextDescrParams (KSubConnContextDescrParamsFamily), are defined. +@return a pointer to a sub-connection parameter family if successful, otherwise leaves with system error code. +*/ + { + CSubConParameterFamily* family = new (ELeave) CSubConParameterFamily(aFamilyId); + CleanupStack::PushL(family); + family->ConstructL(aBundle); + CleanupStack::Pop(family); + return family; + } + +EXPORT_C CSubConParameterFamily* CSubConParameterFamily::NewL(CSubConParameterBundle& aBundle, TUint32 aFamilyId) +/** Creates a new sub-connection parameter set family. This class is used as a container for a number of parameter + sets (generic and extension) that make up a family. It is a specific instantiatable class and therefore creates + an instance of CSubConParameterFamily without using ECOM. + +Note: +The aBundle parameter that is passed into this method will take ownership of the newly created +CSubConParameterFamily object. When the bundle is destroyed, this family object will also be +destroyed (along with any parameter sets that are owned by the family). + +@param aBundle Family container (bundle) that this family is to be added to. +@param aFamilyId identifier for the specific family type, currently only 4, QoS (KSubConQoSFamily),Authorisation (KSubConAuthorisationFamily), +CallDescrParams (KSubConnCallDescrParamsFamily) and ContextDescrParams (KSubConnContextDescrParamsFamily), are defined. +@return a pointer to a sub-connection parameter family if successful, otherwise leaves with system error code. +*/ + { + CSubConParameterFamily* family = new (ELeave) CSubConParameterFamily(aFamilyId); + CleanupStack::PushL(family); + family->ConstructL(aBundle); + CleanupStack::Pop(family); + return family; + } + +EXPORT_C TInt32 CSubConParameterFamily::ExtractFamilyAndCreateBufferL(TPtrC8& aBuffer, TPtrC8& aContainerBuffer) +/** Used internally to extract the family id for the descriptor storing the serialised version of this object (and others). + It also sets up a new buffer that is the section of the original buffer that represents this object only. + +@param aBuffer Source buffer containing mulitple serialised objects (family at the start) +@param aContainerBuffer Set up by this method and represents only the serialised data of the family object. +@return the family Id, otherwise leaves with system error code. +*/ + { + const TInt KDataHdrLen = 2 * static_cast(sizeof(TUint32)); + + // Guard to ensure length of data, pointed to by the descriptor, is not too small, + // I.e. we are pointing to something! + if (aBuffer.Length() < KDataHdrLen) + { + User::Leave(KErrArgument); + } + + // Obtain the 'length' value of the data pointed to by the descriptor + // Has to be at least size of header! + TInt32 dataLength; + Mem::Copy(&dataLength, aBuffer.Ptr(),sizeof(TInt32)); + + + // Guard to ensure 'length' value of data contains enough data to read. + // i.e. aBuffer.Length() could point to some data whose 'length' is zero. + // + // Guard to ensure length of data, pointed to by the descriptor and specified by that + // descriptor, is not smaller that the length stated in the data itself. + // i.e. could be an array of objects. + if ((dataLength < KDataHdrLen) || (aBuffer.Length() < dataLength)) + { + User::Leave(KErrArgument); + } + + // Obtain the 'familyId' value of the data pointed to by the descriptor + TInt32 familyId; + Mem::Copy(&familyId, aBuffer.Ptr() + sizeof(TInt32),sizeof(TInt32)); + + // Set up the container buffer + // Point it past the 'length' & 'familyId' fields (header). + // The data pointed to may be an array of user defined datatypes, and each datatype + // may have arbitrary data following the header fields. + // Point aContainerBuffer to that arbitrary data. + aContainerBuffer.Set(aBuffer.Ptr() + KDataHdrLen, dataLength - KDataHdrLen); + + // Move source buffer ptr on to the next family, plus any following data + aBuffer.Set(aBuffer.Ptr() + dataLength, aBuffer.Length() - dataLength); + + return familyId; + } + +EXPORT_C CSubConParameterFamily* CSubConParameterFamily::LoadL(RSubConParameterBundle& aBundle, TPtrC8& aBuffer) +/** Creates a new sub-connection parameter set family from a buffer containing the serialised object. + +Note: +The aBundle parameter that is passed into this method will take ownership of the newly created +CSubConParameterFamily object. When the bundle is destroyed, this family object will also be +destroyed (along with any parameter sets that are owned by the family). + +@param aBundle Family container (bundle) that this family is to be added to +@param aBuffer Buffer containing the serialised object information +@return a pointer to a sub-connection parameter family if successful, otherwise leaves with system error code. +*/ + { + TInt32 familyId = 0; + TPtrC8 containerBuffer(aBuffer.Ptr(), aBuffer.Length()); + familyId = ExtractFamilyAndCreateBufferL(aBuffer, containerBuffer); + CSubConParameterFamily* family = new (ELeave) CSubConParameterFamily(familyId); + CleanupStack::PushL(family); + family->ConstructL(aBundle); + User::LeaveIfError(family->Load(containerBuffer)); + CleanupStack::Pop(family); + return family; + } + +EXPORT_C CSubConParameterFamily* CSubConParameterFamily::LoadL(CSubConParameterBundle& aBundle, TPtrC8& aBuffer) +/** Creates a new sub-connection parameter set family from a buffer containing the serialised object. + +Note: +The aBundle parameter that is passed into this method will take ownership of the newly created +CSubConParameterFamily object. When the bundle is destroyed, this family object will also be +destroyed (along with any parameter sets that are owned by the family). + +@param aBundle Family container (bundle) that this family is to be added to +@param aBuffer Buffer containing the serialised object information +@return a pointer to a sub-connection parameter family if successful, otherwise leaves with system error code. +*/ + { + TInt32 familyId = 0; + TPtrC8 containerBuffer(aBuffer.Ptr(), aBuffer.Length()); + familyId = ExtractFamilyAndCreateBufferL(aBuffer, containerBuffer); + CSubConParameterFamily* family = new (ELeave) CSubConParameterFamily(familyId); + CleanupStack::PushL(family); + family->ConstructL(aBundle); + User::LeaveIfError(family->Load(containerBuffer)); + CleanupStack::Pop(family); + return family; + } + +EXPORT_C CSubConParameterFamily::~CSubConParameterFamily() +/** Sub-connection parameter family destructor. It cleans up the arrays deleting all + the paarmeter sets it ownes +*/ + { + iGenericSets.ResetAndDestroy(); + iExtensionSets[ERequested].ResetAndDestroy(); + iExtensionSets[EAcceptable].ResetAndDestroy(); + iExtensionSets[EGranted].ResetAndDestroy(); + } + +EXPORT_C void CSubConParameterFamily::SetGenericSetL(CSubConGenericParameterSet& aGenericSet, TParameterSetType aType) +/** Assigns the generic parameter set of a sub-connection parameter set family. + +Note: +The CSubConParameterFamily object takes ownership of the parameter set that is passed into +this method. When the family object is destroyed, any parameter sets owned by this object +will also be destroyed. + +@param aGenericSet Generic Parameter Set to be assigned to the family (family takes ownership) +@param aType The type of the set (requested, acceptable or granted) +@exception leaves with KAlreadyExists if a set is already assigned to the family. +*/ + { + if (iGenericSets[aType] != NULL) + { + User::Leave(KErrAlreadyExists); + } + iGenericSets[aType] = &aGenericSet; + } + + +/** +Adds an extension parameter set to a sub-connection parameter set family. + +Note: +The CSubConParameterFamily object takes ownership of the parameter set that is passed into +this method. When the family object is destroyed, any parameter sets owned by this object +will also be destroyed. + +@param aExtensionSet Extension Parameter Set to be added to the family (family takes ownership) +@param aType The type of the set (requested, acceptable or granted) +@exception leaves with KErrNoMemory in out of memeory conditions. +*/ +EXPORT_C void CSubConParameterFamily::AddExtensionSetL(CSubConExtensionParameterSet& aExtensionSet, TParameterSetType aType) + { + iExtensionSets[aType].AppendL(&aExtensionSet); + } + + +/** +Searches a sub-connection parameter family for an extension parameter set. +DO NOT USE this form of the method. It is broken. This is only capable of finding extension sets +contained within IP Subconnection Provider, and these extension sets have been deprecated. + +@param aSetId Although a TUid, this is the extension class Id +@param aType The type of the set from TParameterSetType (ERequested, EAcceptable or EGranted) +@return Pointer to the extension set if found, otherwise a NULL pointer. +*/ +EXPORT_C CSubConExtensionParameterSet* CSubConParameterFamily::FindExtensionSet(TUid aSetId, TParameterSetType aType) + { + // Old Ipscpr Factory IUD = 0x10204309 + STypeId type = STypeId::CreateSTypeId(0x10204309, aSetId.iUid); + + TUint length = iExtensionSets[aType].Count(); + for (TUint i = 0; i < length; ++i) + { + if (iExtensionSets[aType][i]->GetTypeId() == type) + { + return static_cast(iExtensionSets[aType][i]); + } + } + + return NULL; + } + + +/** +Searches a sub-connection parameter family for an extension parameter set. +@param aSetId The STypeId of the extension set +@param aType The type of the set from TParameterSetType (ERequested, EAcceptable or EGranted) +@return Pointer to the extension set if found, otherwise a NULL pointer. +*/ +EXPORT_C CSubConExtensionParameterSet* CSubConParameterFamily::FindExtensionSet(STypeId aSetId, TParameterSetType aType) + { + TUint length = iExtensionSets[aType].Count(); + for (TUint i = 0; i < length; ++i) + { + if (iExtensionSets[aType][i]->GetTypeId() == aSetId) + { + return static_cast(iExtensionSets[aType][i]); + } + } + +/* + * This is a workaround for the relocated QoS extension parameter set classes. If an + * extension set class is requested from the new factory and it can't be found another + * check needs to be made to see if the equivalent deprecated class is there. + * + * Normally this couldn't be done, but in this case its Ok since the classes + * we're searching on are actually identical. + * + * This can be removed once the deprecated class CSubConQosIPLinkR99ParamSet and + * its friends are removed from ipscpr. + * + * Hardcoded values are being used here since; + * i) They shouldn't be changing + * ii) It avoids having to include two unnecessary header files + * + * New Umts Factory UID = 0x1020D460 + * Old Ipscpr Factory IUD = 0x10204309 + * +*/ + if (aSetId.iUid == TUid::Uid(0x1020D460)) + { + STypeId alternateTypeId = STypeId::CreateSTypeId(0x10204309, aSetId.iType); + for (TUint i = 0; i < length; ++i) + { + if (iExtensionSets[aType][i]->GetTypeId() == alternateTypeId) + { + return static_cast(iExtensionSets[aType][i]); + } + } + } + + return NULL; + } + +EXPORT_C CSubConGenericParameterSet* CSubConParameterFamily::GetGenericSet(TParameterSetType aType) +/** Accessor for the sub-connection generic parameter set of a family. + +@param aType The type of the set (requested, acceptable or granted) +@return Pointer to the generic set if set, otherwise a NULL pointer. +*/ + { + return static_cast(iGenericSets[aType]); + } + +EXPORT_C TUint CSubConParameterFamily::Length() const +/** Calculates the length of buffer required to serialise this parameter set family. + +@return Length of buffer required. +*/ + { + return sizeof(TInt32) + sizeof(TInt32) + iGenericSets.Length() + iExtensionSets[ERequested].Length() + iExtensionSets[EAcceptable].Length() + iExtensionSets[EGranted].Length(); + } + +EXPORT_C TInt CSubConParameterFamily::Load(TPtrC8& aBuffer) +/** Instructs this sub-connection family to set its members based on the serialiesd data + in the buffer passed. + +@param aBuffer Buffer containing the serialised family object +@return KErrNone if successful, otherwise system wide error +*/ + { + TInt ret = iGenericSets.GetTypeId().Check(aBuffer); + if (ret == KErrNone) + { + ret = iGenericSets.Load(aBuffer); + } + + if (ret != KErrNone) + { + return ret; + } + + if (aBuffer.Length() == 0) + { + iGenericSets.ResetAndDestroy(); + return KErrArgument; + } + + ret = iExtensionSets[ERequested].GetTypeId().Check(aBuffer); + if (ret == KErrNone) + { + ret = iExtensionSets[ERequested].Load(aBuffer); + } + if (ret != KErrNone) + { + iGenericSets.ResetAndDestroy(); + return ret; + } + + if (aBuffer.Length() > 0) + { + ret = iExtensionSets[EAcceptable].GetTypeId().Check(aBuffer); + if (ret == KErrNone) + { + ret = iExtensionSets[EAcceptable].Load(aBuffer); + } + if (ret != KErrNone) + { + iGenericSets.ResetAndDestroy(); + iExtensionSets[ERequested].ResetAndDestroy(); + return ret; + } + } + + if (aBuffer.Length() > 0) + { + ret = iExtensionSets[EGranted].GetTypeId().Check(aBuffer); + if (ret == KErrNone) + { + ret = iExtensionSets[EGranted].Load(aBuffer); + } + if (ret != KErrNone) + { + iGenericSets.ResetAndDestroy(); + iExtensionSets[ERequested].ResetAndDestroy(); + iExtensionSets[EAcceptable].ResetAndDestroy(); + return ret; + } + } + return KErrNone; + } + +EXPORT_C TInt CSubConParameterFamily::Store(TDes8& aDes) const +/** Instructs this sub-connection family to create a serialised version of itself + and append it to the buffer that has been passed. + +@param aDes Buffer to append the serialised object to +@return KErrNone if successful, otherwise system wide error (e.g. KErrOverflow if the descriptor is too small) +If unsuccessful, there is no guarantee as to the buffer or data stored in it. +*/ + { + // Needs to be at least this size to store len and familyId ptrs + // aDes can only grow upto MaxLength. + if (aDes.MaxLength() < (2 * static_cast(sizeof(TUint32)))) + { + return KErrOverflow; + } + + TUint len = Length(); + + aDes.Append((TUint8*)&len, sizeof(TUint32)); + aDes.Append((TUint8*)&iFamilyId, sizeof(TUint32)); + + TInt ret = iGenericSets.Store(aDes); + if (ret != KErrNone) + { + return ret; + } + + ret = iExtensionSets[ERequested].Store(aDes); + if (ret != KErrNone) + { + return ret; + } + + ret = iExtensionSets[EAcceptable].Store(aDes); + if (ret != KErrNone) + { + return ret; + } + + return iExtensionSets[EGranted].Store(aDes); + } + +EXPORT_C void CSubConParameterFamily::ClearAllParameters(TParameterSetType aType) +/** Clears (removes and deletes) all parameter sets with the type specified + +@param aType The type of the set to be deleted(requested, acceptable or granted) +*/ + { + if (iGenericSets[aType] != NULL) + { + delete iGenericSets[aType]; + iGenericSets[aType] = NULL; + } + iExtensionSets[aType].ResetAndDestroy(); + } + +void CSubConParameterFamily::CopyToFamilyL(RParameterFamily& aDest) const + { + __ASSERT_DEBUG((TInt)CSubConParameterFamily::ENumValues == (TInt)RParameterFamily::ENumValues, User::Panic(KSpecAssert_ESockCSockcssbcn, 1)); + + TInt type=0; + for ( ; type(iGenericSets[type]); + if(srcSet) + { + XParameterSetBase* newSet = + static_cast + (XParameterSetBase::NewInstanceL(srcSet->GetTypeId())); + newSet->Copy(*srcSet); + aDest.AddParameterSetL(newSet,RParameterFamily::TParameterSetType(type)); + } + } + + for (type=0; type(srcContainer[srcidx]); + if(srcSet) + { + XParameterSetBase* newSet = + static_cast + (XParameterSetBase::NewInstanceL(srcSet->GetTypeId())); + newSet->Copy(*srcSet); + aDest.AddParameterSetL(newSet,RParameterFamily::TParameterSetType(type)); + } + } + } + } + +void CSubConParameterFamily::CopyFromFamilyL(RParameterFamily& aSrc) + { + __ASSERT_DEBUG((TInt)CSubConParameterFamily::ENumValues == (TInt)RParameterFamily::ENumValues, User::Panic(KSpecAssert_ESockCSockcssbcn, 2)); + + // The excuse for quoting the following UIds is: + // They are the only types defined before the switchover to generic + // RFamilyBundles so are the only ones which will be subject to the + // differentiation between "Generic" slot and "Extension" list. + // + + //STypeId gentype_1(CSubConIPAddressInfoParamSet::EUid,CSubConIPAddressInfoParamSet::EType); // CSubConIPAddressInfoParamSet + STypeId gentype_1 = STypeId::CreateSTypeId(0x102822D5,1); // CSubConIPAddressInfoParamSet + + //STypeId gentype_2(KSubConnGenericParamsImplUid,KSubConnQosGenericParamsType); // CSubConQosGenericParamSet + STypeId gentype_2 = STypeId::CreateSTypeId(KSubConnGenericParamsImplUid,1); // CSubConQosGenericParamSet + + //STypeId gentype_3(KSubConnGenericParamsImplUid,KSubConnAuthorisationGenericParamsType); // CSubConAuthorisationGenericParamSet + STypeId gentype_3 = STypeId::CreateSTypeId(KSubConnGenericParamsImplUid,2); // CSubConAuthorisationGenericParamSet + + //STypeId gentype_4(KSubConnGenericParamsImplUid,KFlowRequestParametersType); // CFlowRequestParameters + STypeId gentype_4 = STypeId::CreateSTypeId(KSubConnGenericParamsImplUid,3); // CFlowRequestParameters + + //STypeId gentype_5(KSubConnGenericParamsImplUid,KSubConnProtocolGenericParamsType); // CSubConnectionProtocolParameterSet + STypeId gentype_5 = STypeId::CreateSTypeId(KSubConnGenericParamsImplUid,4); // CSubConnectionProtocolParameterSet + + //STypeId gentype_6(KSubConChannelParamsImplUid,KSubConChannelParamsType); // CSubConChannelParamSet + STypeId gentype_6 = STypeId::CreateSTypeId(0x20019D42,9); // CSubConChannelParamSet + + for(TInt type=0; typeIsTypeOf(gentype_1) || + srcSet->IsTypeOf(gentype_2) || + srcSet->IsTypeOf(gentype_3) || + srcSet->IsTypeOf(gentype_4) || + srcSet->IsTypeOf(gentype_5) || + srcSet->IsTypeOf(gentype_6) ) ; + + XParameterSetBase* newSet = + static_cast + (XParameterSetBase::NewInstanceL(srcSet->GetTypeId())); + + newSet->Copy(*srcSet); + if(isGenericSet) + { + CSubConGenericParameterSet &genPs = + static_cast(*newSet); + SetGenericSetL(genPs,TParameterSetType(type)); + } + else + { + CSubConExtensionParameterSet &extPs = + static_cast(*newSet); + AddExtensionSetL(extPs,TParameterSetType(type)); + } + } + } + } + + +EXPORT_C CSubConParameterFamily::CSubConParameterFamily(TUint32 aFamilyId) + : iFamilyId(aFamilyId) +/** Empty sub-connection parameter family constructor + +@param aFamilyId identifier for the specific family type, currently only 4, QoS (KSubConQoSFamily),Authorisation (KSubConAuthorisationFamily), +CallDescrParams (KSubConnCallDescrParamsFamily) and ContextDescrParams (KSubConnContextDescrParamsFamily), are defined. +*/ + { + } + +EXPORT_C void CSubConParameterFamily::ConstructL(RSubConParameterBundle& aBundle) +/** Set up the sub-connection family with empty sets + +Note: +The aBundle parameter that is passed into this method will take ownership of the newly created +CSubConParameterFamily object. When the bundle is destroyed, this family object will also be +destroyed (along with any parameter sets that are owned by the family). + +@param aBundle Bundle (container) the family is to be added to +@exception leaves with KErrNoMemory in out of memory conditions +*/ + { + iGenericSets.AppendL(NULL); + iGenericSets.AppendL(NULL); + iGenericSets.AppendL(NULL); + aBundle.AddFamilyL(this); + } + +EXPORT_C void CSubConParameterFamily::ConstructL(CSubConParameterBundle& aBundle) +/** Set up the sub-connection family with empty sets + +Note: +The aBundle parameter that is passed into this method will take ownership of the newly created +CSubConParameterFamily object. When the bundle is destroyed, this family object will also be +destroyed (along with any parameter sets that are owned by the family). + +@param aBundle Bundle (container) the family is to be added to +@exception leaves with KErrNoMemory in out of memory conditions +*/ + { + iGenericSets.AppendL(NULL); + iGenericSets.AppendL(NULL); + iGenericSets.AppendL(NULL); + aBundle.AddFamilyL(this); + } + +CSubConParameterBundle::CSubConParameterBundle(const CSubConParameterBundle& /*aBundle*/) +/** Copy Constructor +*/ + { + __ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockCSockcssbcn, 3));//can be Unreachable in future + } + +CSubConParameterBundle& CSubConParameterBundle::operator=(const CSubConParameterBundle& /*aBundle*/) +/** Assignment operator +*/ + { + __ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockCSockcssbcn, 4));//can be Unreachable in future + return *this; + } + +TInt RSubConParameterBundle::CheckBundle() const +/** Check to see if the handle has a heap object. If it hasn't, it creates one + +@return KErrNone if successful, otherwise a system wide error +*/ + { + if (!iBundle) + { + TRAPD(ret, iBundle = CSubConParameterBundle::NewL()); + return ret; + } + return KErrNone; + } + +EXPORT_C RSubConParameterBundle::RSubConParameterBundle() + : iBundle(NULL) +/** Empty sub-connection parameter bundle constructor +*/ + { + } + +RSubConParameterBundle::RSubConParameterBundle(const RSubConParameterBundle& /*aBundle*/) +/** Copy Constructor +*/ + { + __ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockCSockcssbcn, 5));//can be Unreachable in future + } + +RSubConParameterBundle& RSubConParameterBundle::operator=(const RSubConParameterBundle& /*aBundle*/) +/** Assignment operator +*/ + { + __ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockCSockcssbcn, 6));//can be Unreachable in future + return *this; + } + +EXPORT_C void RSubConParameterBundle::Close() +/** Close the parameter bundle handle +*/ + { + if (iBundle) + { + iBundle->Close(); + iBundle = NULL; + } + } + +EXPORT_C TUint RSubConParameterBundle::Length() const +/** Calculates the length of buffer required to serialise this parameter set bundle. + +@return Length of buffer required. +*/ + { + TInt err = CheckBundle(); + return (err==KErrNone)? iBundle->Length() : 0; + } + +EXPORT_C TInt RSubConParameterBundle::Load(const TDesC8& aDes) +/** Instructs this sub-connection bundle to set its members based on the serialiesd data + in the buffer passed. + +@param aDes Buffer containing the serialised bundle object +@return KErrNone if successful, otherwise system wide error +*/ + { + TInt ret = CheckBundle(); + if (ret == KErrNone) + ret = iBundle->Load(aDes); + return ret; + } + +EXPORT_C TInt RSubConParameterBundle::Store(TDes8& aDes) const +/** Instructs this sub-connection parameter bundle to create a serilised version of itself + and append it to the buffer that has been passed. + +@param aDes Buffer to append the serialised object to +@return KErrNone if successful, otherwise system wide error (e.g. EKrrOverflow if the descriptor is too small) +If unsuccessful, there is no guarantee as to the buffer or data stored in it. +*/ + { + TInt ret = CheckBundle(); + if (ret == KErrNone) + ret = iBundle->Store(aDes); + return ret; + } + +EXPORT_C void RSubConParameterBundle::AddFamilyL(CSubConParameterFamily* aFamily) +/** Add a sub-connection parameter family to the bundle. + +Note: +The RSubConParameterBundle object takes ownership of the parameter family that is passed +into this method. When the bundle object is destroyed, any family owned by this object +will also be destroyed. + +@param aFamily Family to be added (bundle takes ownership) +@exception leaves with KErrNoMemory in out of memory conditions +*/ + { + User::LeaveIfError(CheckBundle()); + iBundle->AddFamilyL(aFamily); + } + +EXPORT_C CSubConParameterFamily* RSubConParameterBundle::FindFamily(TUint32 aFamilyId) +/** Search the sub-connection parameter bundle for a parameter family + +@param aFamilyId Id of the family to match against. It is an identifier for the specific family type, currently only 4, QoS (KSubConQoSFamily),Authorisation (KSubConAuthorisationFamily), +CallDescrParams (KSubConnCallDescrParamsFamily) and ContextDescrParams (KSubConnContextDescrParamsFamily), are defined. +@return Matching family or NULL pointer if not found +*/ + { + if (CheckBundle() != KErrNone) + return NULL; + else + return iBundle->FindFamily(aFamilyId); + } + +EXPORT_C void RSubConParameterBundle::ClearAllParameters(CSubConParameterFamily::TParameterSetType aType) +/** Clears (removes and deletes) all parameter sets with the type specified (delegated to the families) + +@param aType The type of the set to be deleted(requested, acceptable or granted) +*/ + { + if (iBundle != NULL) + { + iBundle->ClearAllParameters(aType); + } + } + + +EXPORT_C void RSubConParameterBundle::CopyToFamilyBundleL(RParameterFamilyBundle& aDest) const + { + aDest.CreateL(); + User::LeaveIfError(CheckBundle()); + + TUint length = iBundle->iFamilies.Count(); + for (TUint i = 0; i < length; ++i) + { + CSubConParameterFamily* srcScpf = iBundle->iFamilies[i]; + RParameterFamily newPf; + newPf.CreateL(aDest,srcScpf->Id()); + srcScpf->CopyToFamilyL(newPf); + } + } + +EXPORT_C void RSubConParameterBundle::CopyFromFamilyBundleL(RParameterFamilyBundle& aSrc) + { + if (aSrc.IsNull()) + { + User::Leave(KErrNotReady); + } + + RParameterFamily srcPf; + TInt index=0; + while( ! (srcPf=aSrc.GetFamilyAtIndex(index++)).IsNull() ) + { + CSubConParameterFamily* newScpf = CSubConParameterFamily::NewL(*this,srcPf.Id()); + newScpf->CopyFromFamilyL(srcPf); + } + } + +EXPORT_C CSubConParameterBundle* CSubConParameterBundle::NewL() +/** Creates a new instance of a sub-connection parameter bundle (heap object) + Can be used directly as a CObject or via the RSubConParameterBundle handle. + +@return newly created instance of a sub-connection parameter bundle +@exception leaves with KErrNoMemory in out of memory conditions +*/ + { + return new (ELeave) CSubConParameterBundle(); + } + +EXPORT_C CSubConParameterBundle* CSubConParameterBundle::LoadL(TDesC8& aDes) +/** Creates a new sub-connection parameter set bunlde from a buffer containing the serialised object. + +@param aDes Buffer containing the serialised object information +@return a pointer to a sub-connection parameter bundle if successful, otherwise leaves with system error code. +*/ + { + CSubConParameterBundle* obj = new (ELeave) CSubConParameterBundle(); + CleanupStack::PushL(obj); + User::LeaveIfError(obj->Load(aDes)); + CleanupStack::Pop(obj); + return obj; + } + +EXPORT_C CSubConParameterBundle::~CSubConParameterBundle() +/** Sub-connection parameter bundle destructor, clear up the families +*/ + { + iFamilies.ResetAndDestroy(); + } + +EXPORT_C TUint CSubConParameterBundle::Length() const +/** Calculates the length of buffer required to serialise this parameter set bundle. + +@return Length of buffer required. +*/ + { + TInt length = 0; + TUint count = iFamilies.Count(); + for (TUint i = 0; i < count; ++i) + { + length += iFamilies[i]->Length(); + } + return length; + } + +EXPORT_C TInt CSubConParameterBundle::Load(const TDesC8& aDes) +/** Instructs this sub-connection bundle to set its members based on the serialiesd data + in the buffer passed. + +@param aDes Buffer containing the serialised bundle object +@return KErrNone if successful, otherwise system wide error +*/ + { + TPtrC8 buf(aDes); + + while (buf.Length() > 0) + { + TRAPD(ret, CSubConParameterFamily::LoadL(*this, buf)); + if (ret != KErrNone) + { + iFamilies.ResetAndDestroy(); + return ret; + } + } + return KErrNone; + } + +EXPORT_C TInt CSubConParameterBundle::Store(TDes8& aDes) const +/** Instructs this sub-connection parameter bundle to create a serilised version of itself + and append it to the buffer that has been passed. + +@param aDes Buffer to append the serialised object to +@return KErrNone if successful, otherwise system wide error (e.g. EKrrOverflow if the descriptor is too small) +If unsuccessful, there is no guarantee as to the buffer or data stored in it. +*/ + { + TUint length = iFamilies.Count(); + + for (TUint i = 0; i < length; ++i) + { + TInt ret = iFamilies[i]->Store(aDes); + if (ret != KErrNone) + { + aDes.Zero(); + return ret; + } + } + return KErrNone; + } + +EXPORT_C void CSubConParameterBundle::AddFamilyL(CSubConParameterFamily* aFamily) +/** Add a sub-connection parameter family to the bundle. + +Note: +The CSubConParameterBundle object takes ownership of the parameter family that is passed +into this method. When the bundle object is destroyed, any family owned by this object +will also be destroyed. + +@param aFamily Family to be added (bundle takes ownership) +@exception leaves with KErrNoMemory in out of memory conditions +*/ + { + iFamilies.AppendL(aFamily); + } + +EXPORT_C CSubConParameterFamily* CSubConParameterBundle::FindFamily(TUint32 aFamilyId) +/** Search the sub-connection parameter bundle for a parameter family + +@param aFamilyId Id of the family to match against. It is an identifier for the specific family type, currently only 4, QoS (KSubConQoSFamily),Authorisation (KSubConAuthorisationFamily), +CallDescrParams (KSubConnCallDescrParamsFamily) and ContextDescrParams (KSubConnContextDescrParamsFamily), are defined. +@return Matching family or NULL pointer if not found +*/ + { + TUint length = iFamilies.Count(); + for (TUint i = 0; i < length; ++i) + { + if (iFamilies[i]->Id() == aFamilyId) + { + return iFamilies[i]; + } + } + return NULL; + } + +EXPORT_C CSubConParameterFamily* CSubConParameterBundle::FindFamily(TUint32 aFamilyId) const +/** Search the sub-connection parameter bundle for a parameter family + +@param aFamilyId Id of the family to match against. It is an identifier for the specific family type, currently only 4, QoS (KSubConQoSFamily),Authorisation (KSubConAuthorisationFamily), +CallDescrParams (KSubConnCallDescrParamsFamily) and ContextDescrParams (KSubConnContextDescrParamsFamily), are defined. +@return Matching family or NULL pointer if not found +*/ + { + TUint length = iFamilies.Count(); + for (TUint i = 0; i < length; ++i) + { + if (iFamilies[i]->Id() == aFamilyId) + { + return iFamilies[i]; + } + } + return NULL; + } + +EXPORT_C void CSubConParameterBundle::ClearAllParameters(CSubConParameterFamily::TParameterSetType aType) +/** Clears (removes and deletes) all parameter sets with the type specified (delegated to the families) + +@param aType The type of the set to be deleted(requested, acceptable or granted) +*/ + { + TUint length = iFamilies.Count(); + for (TUint i = 0; i < length; ++i) + { + iFamilies[i]->ClearAllParameters(aType); + } + } + +EXPORT_C CSubConParameterBundle::CSubConParameterBundle() +/** Empty sub-connection generic parameter bundle constructor +*/ + { + } + +EXPORT_C TNotificationEventBuf::TNotificationEventBuf() + { + SetLength(this->MaxLength()); + FillZ(); + } + +EXPORT_C TNotificationEventBuf::~TNotificationEventBuf() + { + } + +EXPORT_C TBool TNotificationEventBuf::IsGeneric() const +/** Check whether an event is a generic event (not an extension) + +@return ETrue if the event is generic, otherwise EFalse +*/ + { + return GroupId() == KSubConnGenericEventsImplUid; + } + +EXPORT_C TInt32 TNotificationEventBuf::GroupId() const +/** Provides the group id (Uid) of the event + +@return Group id in the form of a UId (Could be generic or any extension uid) +*/ + { + return *((TInt32*)Ptr()); + } + +EXPORT_C TUint32 TNotificationEventBuf::Id() const +/** Provides the sub-type Id of the event + +@return sub-type id +*/ + { + return *((TUint32*)(Ptr() + sizeof(TUint32))); + } + +EXPORT_C CSubConNotificationEvent* CSubConNotificationEvent::NewL(const STypeId& aTypeId) +/** Creates a new sub-connection event using ECOM to load the DLL plugin + that implements the event. + +@param aTypeId Id of the class (Composed of Uid of the implementation and an integer sub-type) +@return a generic pointer to a specific event if successful, otherwise leaves with system error code. +*/ + { + return static_cast(Meta::SMetaDataECom::NewInstanceL(aTypeId)); + } + +EXPORT_C CSubConNotificationEvent* CSubConNotificationEvent::NewL(const TNotificationEventBuf& aEventBuffer) +/** Creates a new sub-connection event using ECOM to load the DLL plugin + that implements the event. + +@param aEventBuffer A Buffer containing the serialised form of the event object +@return a generic pointer to a specific event if successful, otherwise leaves with system error code. +*/ + { + TPtrC8 buf(aEventBuffer.Ptr(), aEventBuffer.Length()); + return static_cast(Meta::SMetaDataECom::LoadL(buf)); + } + +EXPORT_C TBool CSubConNotificationEvent::IsGeneric() const +/** Check whether an event is a generic event (not an extension) + +@return ETrue if the event is generic, otherwise EFalse +*/ + { + return GetTypeId().iUid.iUid == KSubConnGenericEventsImplUid; + } + +EXPORT_C TInt32 CSubConNotificationEvent::GroupId() const +/** Provides the group id (Uid) of the event + +@return Group id in the form of a UId (Could be generic or any extension uid) +*/ + { + return static_cast(GetTypeId().iUid.iUid); + } + +EXPORT_C TUint32 CSubConNotificationEvent::Id() const +/** Provides the sub-type Id of the event + +@return sub-type id +*/ + { + return GetTypeId().iType; + } + +EXPORT_C RSubConnection::RSubConnection() +/** Empty sub-connection handle constructor +*/ + { + } + +EXPORT_C TInt RSubConnection::Open(RSocketServ& aServer, TSubConnType aSubConnType, RConnection& aConnection) +/** Opens a new RSubConnection instance. + +@param aSocketServer Socket Server session. +@param aSubConnType specifies the type of sub connection, the different available types are defined by TSubConnType. +@param aConnection Parent Connection that is to be sub divided by this sub-connection +@return KErrNone if successful, otherwise another of the system wide error codes. +*/ + { + return Open(aServer, static_cast(aSubConnType), aConnection); + } + +EXPORT_C void RSubConnection::Close() +/** Closes the sub-connection. + +The sub-connection will not be dropped immediately: it will be dropped when there +is no more data traffic on the sub-connection. +*/ + { + LOG( ESockLog::Printf(_L8("RSubConnection %08x:\tClose() tid %d"), this, (TUint)RThread().Id());); + CloseSubSession(ESCClose); + REComSession::FinalClose(); + } + +EXPORT_C void RSubConnection::Start(TRequestStatus& aStatus) +/** +Unused +*/ + { + LOG( ESockLog::Printf(_L8("RSubConnection %08x:\tStart() async tid %d"), this, (TUint)RThread().Id());); + SendReceive(ESCStart, TIpcArgs(), aStatus); + } + +EXPORT_C TInt RSubConnection::Start() +/** +Unused +*/ + { + LOG( ESockLog::Printf(_L8("RSubConnection %08x:\tStart() sync tid %d"), this, (TUint)RThread().Id());); + TRequestStatus status; + Start(status); + User::WaitForRequest(status); + return status.Int(); + } + +EXPORT_C TInt RSubConnection::Stop() +/** +Unused +*/ + { + LOG( ESockLog::Printf(_L8("RSubConnection %08x:\tStop() tid %d"), this, (TUint)RThread().Id());); + return SendReceive(ESCStop, TIpcArgs()); + } + + +EXPORT_C TInt RSubConnection::Open(RSocketServ& aServer, TSubConnOpen::TSubConnType aSubConnType, RConnection& aConnection) +/** Opens a new RSubConnection instance. + +@param aServer Socket Server session. +@param aSubConnType EAttachToDefault when attaching to default or ECreateNew for new one +@param aConnection Parent Connection that is to be sub divided by this sub-connection +@return KErrNone if successful, otherwise another of the system wide error codes. +*/ + { + + if(SubSessionHandle() == KNullHandle) + { + // passing an RConnection which doesn't belong to the same session is an error + if (!aConnection.SameSession(aServer.Handle())) + { + return KErrArgument; + } + + TSubConnOpen arg; + arg.iType = aSubConnType; + arg.iHandle = aConnection.SubSessionHandle(); + TPckgC buf(arg); + + + const TInt ret = CreateSubSession(aServer, ESCCreate,TIpcArgs(&buf)); + LOG( ESockLog::Printf(_L8("RSubConnection %08x:\tOpen() tid %d"), this, (TUint)RThread().Id());); + return ret; + } + else + { + return KErrInUse; + } + } + +EXPORT_C void RSubConnection::Add(RSocket& aSocket, TRequestStatus& aStatus) +/** Associate a socket with a subconnection. The socket must already be using the same connection + or the association attempt will fail. The completion of this method does not indicate that the + socket is now running over the sub-connection, it only indicates that the association is complete + and a negotiation has started to move the socket onto the subconnection. An event (via eventNotification) + will be sent once the socket is running on the sub-connection. + +@param aSocket Socket to be associated with the Sub-Connection +@param aStatus Status to complete when socket has been added (or failed to add) +@return KErrNone if successful, otherwise a system wide error +*/ + { + LOG( ESockLog::Printf(_L8("RSubConnection %08x:\tAdd(RSocket id=%d) tid %d"), this, aSocket.SubSessionHandle(), (TUint)RThread().Id());); + SendReceive(ESCAddSocket, TIpcArgs(aSocket.SubSessionHandle()), aStatus); + } + +EXPORT_C void RSubConnection::Remove(RSocket& aSocket, TRequestStatus& aStatus) +/** Remove a socket from a subconnection. The socket will be moved back to the default sub-connection. + The successful completion of this method does not indicate that the socket has moved back to the + default sub-connection, it only indicates that the move negotiation has been successful. An event + (via eventNotification) will be sent once the socket is running on the default sub-connection. + +@param aSocket Socket to be removed from the Sub-Connection +@param aStatus Status to complete when socket has been removed (or failed to remove) +@return KErrNone if successful, otherwise a system wide error +*/ + { + LOG( ESockLog::Printf(_L8("RSubConnection %08x:\tRemove(RSocket id=%d) tid %d"), this, aSocket.SubSessionHandle(), (TUint)RThread().Id());); + SendReceive(ESCRemoveSocket, TIpcArgs(aSocket.SubSessionHandle()), aStatus); + } + +EXPORT_C TInt RSubConnection::SetParameters(const RSubConParameterBundle& aParameterBundle) +/** Set Parameters of the sub-connection. Successful completion of this method only indicates that + the negotiation has been successfully started. An event via eventNotification) will be sent once + the granted parameters are available. + +@param aParameterBundle bundle of parameters to be applied to the sub-connection +@return KErrNone if successful, otherwise a system wide error +*/ + { + RParameterFamilyBundle pfb; + TRAPD(ret,aParameterBundle.CopyToFamilyBundleL(pfb)); + if(ret==KErrNone) + { + ret=SetParameters(pfb); + } + pfb.Destroy(); + return ret; + } + +EXPORT_C TInt RSubConnection::GetParameters(RSubConParameterBundle& aParameterBundle) +/** Fetch the sub-connection's current parameters (Requested, Acceptable and Granted) + +@param aParameterBundle bundle of parameters to write the current parameters into +@return KErrNone if successful, otherwise a system wide error +*/ + { + RParameterFamilyBundle pfb; + TInt ret = GetParameters(pfb); + if(ret==KErrNone) + { + TRAP(ret,aParameterBundle.CopyFromFamilyBundleL(pfb)); + } + pfb.Destroy(); + return ret; + } + +EXPORT_C TInt RSubConnection::SetParameters(const RParameterFamilyBundle& aParameterBundle) +/** Set Parameters of the sub-connection. Successful completion of this method only indicates that + the negotiation has been successfully started. An event via eventNotification) will be sent once + the granted parameters are available. + +@param aParameterBundle bundle of parameters to be applied to the sub-connection +@return KErrNone if successful, otherwise a system wide error +*/ + { + const_cast(aParameterBundle).ClearAllParameters(RParameterFamily::EGranted); + + HBufC8* buffer = HBufC8::New(aParameterBundle.Length()); + if(buffer == NULL) + { + return KErrNoMemory; + } + + TPtr8 ptr = buffer->Des(); + TInt ret = aParameterBundle.Store(ptr); + if (ret == KErrNone) + { + ret = SendReceive(ESCSetParameters, TIpcArgs(&ptr)); + } + + delete buffer; + return ret; + } + +EXPORT_C TInt RSubConnection::GetParameters(RParameterFamilyBundle& aParameterBundle) +/** Fetch the sub-connection's current parameters (Requested, Acceptable and Granted) + +@param aParameterBundle bundle of parameters to write the current parameters into +@return KErrNone if successful, otherwise a system wide error +*/ + { + TInt lengthOrError = SendReceive(ESCGetParametersLength, TIpcArgs()); + if (lengthOrError < KErrNone) + { + return lengthOrError; + } + + HBufC8* buffer = HBufC8::New(lengthOrError); + if (buffer == NULL) + { + return KErrNoMemory; + } + + TPtr8 ptr = buffer->Des(); + TInt ret = SendReceive(ESCGetParameters, TIpcArgs(&ptr)); + if (ret == KErrNone) + { + TRAP(ret,aParameterBundle.LoadL(ptr)); + } + + delete buffer; + return ret; + } + +EXPORT_C void RSubConnection::EventNotification(TNotificationEventBuf& aEventBuffer, TBool aGenericEventsOnly, TRequestStatus& aStatus) +/** Requests asynchronous event notification for the sub-connection. + +@param aEventBuffer A buffer to receive event notification. +@param aStatus On return, the status of the request. +*/ + { + SendReceive(ESCEventAllNotifications, TIpcArgs(&aEventBuffer, aGenericEventsOnly), aStatus); + } + +EXPORT_C void RSubConnection::EventNotification(TNotificationEventBuf& aEventBuffer, TEventFilter aEventFilterList[], TUint aEventListLength, TRequestStatus& aStatus) +/** Requests asynchronous notification of a specific list of events for the sub-connection. + +@param aEventBuffer A buffer to receive event notification. +@param aEventFilterList list of event filters specifying a subset of events of interest. +@param aEventListLength Length of the filter list provided +@param aStatus On return, the status of the request. +*/ + { + //Since we are creating the descriptor on the stack we need to ensure that buffer is around for when the reading + //takes place. We therefore have to upload the buffer synchronously and only then can we ask for the asynchronous + //notification + TPtrC8 buffer((const unsigned char*)aEventFilterList, aEventListLength * sizeof(TEventFilter)); + TInt ret = SendReceive(ESCEventNotificationSetup, TIpcArgs(&buffer)); + if (ret == KErrNone) + { + SendReceive(ESCEventNotification, TIpcArgs(&aEventBuffer), aStatus); + } + else + { + TRequestStatus* statPtr = &aStatus; + User::RequestComplete(statPtr, ret); + } + + } + +EXPORT_C void RSubConnection::CancelEventNotification() +/** Cancel an outstanding Event Notification request +*/ + { + SendReceive(ESCEventNotificationCancel); + } + +EXPORT_C TInt RSubConnection::Control(TUint aOptionLevel, TUint aOptionName, TDes8& aOption) + { + return SendReceive(ESCControl, TIpcArgs(aOptionLevel, aOptionName, &aOption)); + } + +TBool RSubConnection::SameSession(TInt aSessionHandle) +/** Checks that the Session Handle passed is the same as that of this RSubConnection. + +Use to verify the RSubConnection argument passed to the RSocket and RHostResolver +Open(..., RSubConnection& aSubConnection) methods. + +@param aSessionHandle The handle which is to be checked against that of this RSubConnection +@returns ETrue if handle is the same, else EFalse +@internalComponent +*/ + { + return (Session().Handle() == aSessionHandle); + } +