diff -r 000000000000 -r af10295192d8 networkcontrol/pfqoslib/src/pfqosparser.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/networkcontrol/pfqoslib/src/pfqosparser.cpp Tue Jan 26 15:23:49 2010 +0200 @@ -0,0 +1,1436 @@ +// Copyright (c) 2006-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: +// + +#include "pfqosparser.h" +#include "qosvariables.h" +#include "pfqosliblog.h" + +_LIT(Ksyntax_error, "Syntax error"); + +EXPORT_C TVariableBase::~TVariableBase() + { + } + + +EXPORT_C TIntVariable::TIntVariable(const TDesC& aName, TInt aValue) + : iValue(aValue) + { + //??This makes no check against overflow -- either check or use TName& + //??instead of of TDesC& in parameter list. + iName.Copy(aName); + iType = KPfqosTypeInteger; + } + +EXPORT_C TRealVariable::TRealVariable(const TDesC& aName, TReal aValue) + : iValue(aValue) + { + //??This makes no check against overflow -- either check or use TName& + //??instead of of TDesC& in parameter list. + iName.Copy(aName); + iType = KPfqosTypeReal; + } + +EXPORT_C TStringVariable::TStringVariable(const TDesC& aName, + const TDesC& aValue) + { + //??This makes no check against overflow -- either check or use TName& + //??instead of of TDesC& in parameter list. + iName.Copy(aName); + //??This makes no check against overflow -- either check or use TName& + //??instead of of TDesC& in parameter list. + iValue.Copy(aValue); + iType = KPfqosTypeString; + } + + +// +// CSelectorBase +// +EXPORT_C CSelectorBase::CSelectorBase(TUint aType) + : iType(aType) + { + iProtocol = 0; + iPolicyOptions = 0; + TUidType uid_type(TUid::Uid(0), TUid::Uid(0), TUid::Uid(0)); + iUid.Set(uid_type); + iIapId = 0; + iSrcPortMax = 0; + iDstPortMax = 0; + iDst.SetAddress(KInet6AddrNone); + iSrc.SetAddress(KInet6AddrNone); + iSrcMask.SetAddress(KInet6AddrNone); + iDstMask.SetAddress(KInet6AddrNone); + iName.FillZ(); + iOwner = 0; + } + +//lint -e{1538} It's safe to copy CBase (I think...?) +EXPORT_C CSelectorBase::CSelectorBase(CSelectorBase& aSel) + { + iDstPortMax = aSel.iDstPortMax; + iDst = aSel.iDst; + iDstMask = aSel.iDstMask; + iSrcPortMax = aSel.iSrcPortMax; + iSrc = aSel.iSrc; + iSrcMask = aSel.iSrcMask; + iProtocol = aSel.iProtocol; + iUid.Set(aSel.iUid.UidType()); + iIapId = aSel.iIapId; + iPolicyOptions = aSel.iPolicyOptions; + iPriority = aSel.iPriority; + iType = aSel.iType; + iName.Copy(aSel.iName); + iOwner = 0; + } + + +EXPORT_C CSelectorBase::CSelectorBase(TPfqosBase& aBase, + TPfqosSelector& aSel, + TPfqosAddress& aSrc, + TPfqosAddress& aDst, + TUint aType) : iType(aType) + { + iProtocol = (TUint8)aSel.iExt->protocol; + TCheckedUid uid; + aSel.GetUid(uid); + iUid.Set(uid.UidType()); + iIapId = aSel.iExt->iap_id; + iPolicyOptions = aBase.iMsg->pfqos_msg_options; + iPriority = aSel.iExt->priority; + TPtrC8 tmp((TUint8*)aSel.iExt->name); + iName.Copy(tmp); + + if (aSrc.iAddr != NULL) + { + iSrc = *aSrc.iAddr; + iSrcMask = *aSrc.iPrefix; + + if (aSrc.iExt->pfqos_port_max > iSrc.Port() && + aSrc.iExt->pfqos_port_max < 65535) + { + iSrcPortMax = aSrc.iExt->pfqos_port_max; + } + else + { + iSrcPortMax = (TUint16)iSrc.Port(); + } + } + else + { + iSrc.SetAddress(KInet6AddrNone); + iSrcMask.SetAddress(KInet6AddrNone); + } + + if (aDst.iAddr != NULL) + { + iDst = *aDst.iAddr; + iDstMask = *aDst.iPrefix; + + if (aDst.iExt->pfqos_port_max > iDst.Port() && + aDst.iExt->pfqos_port_max < 65535) + { + iDstPortMax = aDst.iExt->pfqos_port_max; + } + else + { + iDstPortMax = (TUint16)iDst.Port(); + } + } + else + { + iDst.SetAddress(KInet6AddrNone); + iDstMask.SetAddress(KInet6AddrNone); + } + iOwner = 0; + } + +EXPORT_C CSelectorBase::~CSelectorBase() + { + } + + +// +// CExtensionPolicy +// +EXPORT_C CExtensionPolicy::CExtensionPolicy(TPfqosBase& aBase, + TPfqosSelector& aSel, + TPfqosAddress& aSrc, + TPfqosAddress& aDst, + TInt aType) + : CSelectorBase(aBase, aSel, aSrc, aDst, aType) + { + iExtensions.SetOffset(_FOFF(CExtension, iNext)); + }; + +EXPORT_C CExtensionPolicy::CExtensionPolicy() + : CSelectorBase(EPfqosExtensionPolicy) + { + iExtensions.SetOffset(_FOFF(CExtension, iNext)); + iType = EPfqosExtensionPolicy; + } + +EXPORT_C CExtensionPolicy::~CExtensionPolicy() + { + TExtensionQueueIter iter(iExtensions); + CExtension* ext; + while ((ext = iter++) != NULL) + { + ext->iNext.Deque(); + delete ext; + } + } + +EXPORT_C void CExtensionPolicy::AddExtensionL(CExtension& aExtension) + { + CExtension* ext = CExtension::NewL(); + /* Dynamically allocated memory node has been assigned to the list and managed through the list. + So CleanupStack::PopAndDestroy() will deallocate that memory. But, Coverity has misinterpreted it an issue.*/ + // coverity [SYMBIAN.CLEANUP STACK] + // coverity [leave_without_push] + aExtension.CopyL(*ext); + iExtensions.AddLast(*ext); + } + + +EXPORT_C void CExtensionPolicy::AddExtensionL(const TDesC8& aExtension) + { + CExtension* ext = CExtension::NewL(aExtension); + iExtensions.AddLast(*ext); + } + + +// +// QoS Policy db parser +// +EXPORT_C TPolicyParser::TPolicyParser(const TDesC &aPolicy) : iLine(0) + { + Assign(aPolicy); + iExtensions.SetOffset(_FOFF(CExtension, iNext)); + iPolicies.SetOffset(_FOFF(CExtensionPolicy, iNext)); + } + +EXPORT_C TPolicyParser::~TPolicyParser() + { + TExtensionQueueIter iter(iExtensions); + CExtension *ext; + while ((ext = iter++) != NULL) + { + ext->iNext.Deque(); + delete ext; + } + + TQoSPolicyQueueIter policy_iter(iPolicies); + CExtensionPolicy* policy; + while ((policy = policy_iter++) != NULL) + { + policy->iNext.Deque(); + delete policy; + } + } + + +EXPORT_C TInt TPolicyParser::ParseL() + { + LOG(Log::Printf(_L("ParseL called..."))); + TInt error = KErrNone; + iLine = 1; + + while (!Eos()) + { + if (NextToken() == ETokenString) + { + _LIT(Kmodulespec, "modulespec"); + _LIT(Kflowspec, "flowspec"); + _LIT(Kextension_spec, "extension_spec"); + _LIT(Kmodule_policy, "module_policy"); + _LIT(Kflowspec_policy, "flowspec_policy"); + _LIT(Kextension_policy, "extension_policy"); + + _LIT(KUnknown, "Unknown token '%S'"); + + if (iToken.Compare(Kmodulespec) == 0) + { + error = ParseExtensionSpecL(); + } + else if (iToken.Compare(Kflowspec) == 0) + { + error = ParseExtensionSpecL(); + } + else if (iToken.Compare(Kextension_spec) == 0) + { + error = ParseExtensionSpecL(); + } + else if (iToken.Compare(Kmodule_policy) == 0) + { + error = ParsePolicyL(EPfqosModulespecPolicy); + } + else if (iToken.Compare(Kflowspec_policy) == 0) + { + error = ParsePolicyL(EPfqosFlowspecPolicy); + } + else if (iToken.Compare(Kextension_policy) == 0) + { + error = ParsePolicyL(EPfqosExtensionPolicy); + } + else + { + Error(KUnknown, &iToken); + error = KErrGeneral; + } + } + } + return error; + } + + + +// Dummy error routines for now +void TPolicyParser::Error(TRefByValue aFmt, ...) + { + //coverity[var_decl]; + VA_LIST list; + VA_START(list, aFmt); + + _LIT(KatLine, " at line "); + //coverity[uninit_use_in_call]; + iMsg.FormatList(aFmt, list); + iMsg += KatLine; + //lint -e{747} int -> long long + iMsg.AppendNum(iLine); + } + + +// +// Skip white space and mark, including comments! +// +void TPolicyParser::SkipSpaceAndMark() + { + TChar ch; + TInt comment = 0; + + while (!Eos()) + { + ch = Get(); + //lint -e{961} Missing else is OK + if (ch =='\n') + { + iLine++; + comment = 0; + } + else if (comment || ch == '#') + { + comment = 1; + } + else if (!ch.IsSpace()) + { + UnGet(); + break; + } + } + Mark(); + } + + +// +// +TTokenType TPolicyParser::NextToken() + { + TChar ch; + TTokenType val; + + SkipSpaceAndMark(); + if (Eos()) + { + val = ETokenEof; + } + else + { + ch = Get(); + if (ch == '{') + { + val = ETokenBraceLeft; + } + else if (ch == '}') + { + val = ETokenBraceRight; + } + else if (ch == '(') + { + val = ETokenParLeft; + } + else if (ch == ')') + { + val = ETokenParRight; + } + else if (ch == '=') + { + val = ETokenEqual; + } + else if (ch == ',') + { + val = ETokenComma; + } + else + { + val = ETokenString; + while (!Eos()) + { + ch = Peek(); + if (ch == '{' || ch == '}' || + ch == '(' || ch == ')' || + ch == '=' || ch == '#' || ch.IsSpace()) + { + break; + } + Inc(); + } + } + } + iToken.Set(MarkedToken()); + SkipSpaceAndMark(); + return val; + } + + +TTokenType TPolicyParser::GetStringValue() + { + TChar ch('\0'); + TTokenType val; + + SkipSpaceAndMark(); + if (Eos()) + { + val = ETokenEof; + } + else + { + TBool quoted = EFalse; + ch = Get(); + if (ch == '"') + { + quoted = ETrue; + Mark(); + } + if (ch == '{') + { + val = ETokenBraceLeft; + } + else if (ch == '}') + { + val = ETokenBraceRight; + } + else if (ch == '(') + { + val = ETokenParLeft; + } + else if (ch == ')') + { + val = ETokenParRight; + } + else if (ch == '=') + { + val = ETokenEqual; + } + else if (ch == ',') + { + val = ETokenComma; + } + else + { + val = ETokenString; + while (!Eos()) + { + ch = Peek(); + if (ch == '"' && quoted) + { + quoted = EFalse; + } + if ((ch == '{' || ch == '}' || + ch == '(' || ch == ')' || + ch == '=' || ch == '#' || + ch == '"' || ch.IsSpace()) && !quoted) + { + break; + } + Inc(); + } + } + } + iToken.Set(MarkedToken()); + if (ch == '"') + { + Inc(); + } + SkipSpaceAndMark(); + return val; + } + +// +// Extension spec +// +TInt TPolicyParser::ParseExtensionSpecL() + { + if (NextToken() != ETokenString) + { + Error(Ksyntax_error); + } + + CExtension* spec = CExtension::NewL(); + iExtensions.AddLast(*spec); + spec->SetName(iToken); + + if (NextToken() != ETokenEqual || NextToken() != ETokenBraceLeft) + { + Error(Ksyntax_error); + } + else + { + if (ParseExtensionParams(*spec)) + { + Error(Ksyntax_error); + } + else + { + return KErrNone; + } + } + spec->iNext.Deque(); + delete spec; + return KErrGeneral; + } + +// +// Parse extension parameters +// +TInt TPolicyParser::ParseExtensionParams(CExtension& aBuf) + { + LOG(Log::Printf(_L("ParseL called..."))); + TInt error = KErrNone; + TTokenType val; + + while ((val = NextToken()) == ETokenString && error == KErrNone) + { + _LIT(KINTEGER, "INTEGER"); + _LIT(KREAL, "REAL"); + _LIT(KSTRING, "STRING"); + + if (iToken.Compare(KINTEGER) == 0) + { + if (NextToken() != ETokenString) + { + return KErrGeneral; + } + + // parameter name + TName parameterName; + parameterName.FillZ(); + parameterName = iToken; + + if (NextToken() != ETokenEqual) + { + return KErrGeneral; + } + + TInt value; + error = Val(value); + if (error == KErrNone) + { + TRAP(error, aBuf.AddIntegerL(parameterName,value)); + } + + // Set the extension type here + _LIT(KDescExtensionType, "extension_type"); + if (parameterName.Compare(KDescExtensionType) == 0) + { + aBuf.SetType(value); + } + } + else if (iToken.Compare(KREAL) == 0) + { + if (NextToken() != ETokenString) + { + return KErrGeneral; + } + + // parameter name + TName parameterName; + parameterName.FillZ(); + parameterName = iToken; + + if (NextToken() != ETokenEqual) + { + return KErrGeneral; + } + + TReal value; + error = Val(value); + if (error == KErrNone) + { + TRAP(error, aBuf.AddRealL(parameterName,value)); + } + } + else if (iToken.Compare(KSTRING) == 0) + { + if ((val = NextToken()) != ETokenString) + { + return KErrGeneral; + } + + // parameter name + TName parameterName; + parameterName.FillZ(); + parameterName = iToken; + + if (NextToken() != ETokenEqual) + { + return KErrGeneral; + } + + if ((val = GetStringValue()) == ETokenString) + { + TName value = iToken; + TRAP(error, aBuf.AddStringL(parameterName, value)); + } + else + { + error = KErrGeneral; + break; + } + } + else + { + _LIT(KUnknownType, "Unknown variable type"); + Error(KUnknownType); + return KErrGeneral; + } + } + + if (error != KErrNone) + { + _LIT(KInvalidValue, "invalid value"); + Error(KInvalidValue); + return error; + } + + if (val != ETokenBraceRight) + { + _LIT(KBraceNotFound, "right brace not found"); + Error(KBraceNotFound); + return KErrGeneral; + } + + return KErrNone; + } + + +// +// Find extension policy data for a selector. +// +TInt TPolicyParser::FindExtensionPolicy(CExtensionPolicy *aSel) + { + TExtensionQueueIter iter(iExtensions); + CExtension *policy; + + // Find extension data + while ((policy = iter++) != NULL) + { + if (policy->Name().Compare(iToken)==0) + { + break; + } + } + if (policy == NULL) + { + _LIT(KModule, "module not defined"); + Error(KModule); + return KErrGeneral; + } + + // + // Set Data + // + TRAPD(err, aSel->AddExtensionL(*policy)); + return err; + } + + + + +TInt TPolicyParser::ParseIPAddrAndMask(TInetAddr& aAddr, TInetAddr& aMask) + { + TInt error; + + if (NextToken() != ETokenString) + { + _LIT(KNoIpAddress, "ip address not found"); + Error(KNoIpAddress); + return KErrGeneral; + } + + error = aAddr.Input(iToken); + + if (error != 0) + { + _LIT(KInvalidIp, "invalid ip address "); + Error(KInvalidIp); + return error; + } + if (NextToken() != ETokenString) + { + _LIT(KNoMask, "address mask not found"); + Error(KNoMask); + return KErrGeneral; + } + + error = aMask.Input(iToken); + + if (error != 0) + { + _LIT(KInvalidMask, "invalid address mask "); + Error(KInvalidMask); + return error; + } + return KErrNone; + } + + + +TInt TPolicyParser::ParsePolicyL(TInt aPolicyType) + { + CSelectorBase* policy; + TInt error = KErrNone; + TTokenType val; + TUint port; + + switch (aPolicyType) + { + case EPfqosFlowspecPolicy: + { + LOG(Log::Printf(_L("ParsePolicy FlowspecPolicy"))); + policy = new (ELeave) CExtensionPolicy(); + policy->iType = EPfqosFlowspecPolicy; + break; + } + + case EPfqosModulespecPolicy: + { + LOG(Log::Printf(_L("ParsePolicy ModulespecPolicy"))); + policy = new (ELeave) CExtensionPolicy(); + policy->iType = EPfqosModulespecPolicy; + break; + } + + default: + { + LOG(Log::Printf(_L("ParsePolicy ExtensionPolicy"))); + policy = new (ELeave) CExtensionPolicy(); + break; + } + } + policy->iPriority = EPfqosDefaultPriority; + + if (NextToken() != ETokenString) + { + Error(Ksyntax_error); + } + + TInt32 uid1=0; + TInt32 uid2=0; + TInt32 uid3=0; + + do + { + _LIT(Kdst, "dst"); + _LIT(Kremote, "remote"); + _LIT(Ksrc, "src"); + _LIT(Klocal, "local"); + _LIT(Kuser_id, "user_id"); + _LIT(Kprotocol, "protocol"); + _LIT(Ksrc_port, "src_port"); + _LIT(Klocal_port, "local_port"); + _LIT(Ksrc_port_max, "src_port_max"); + _LIT(Klocal_port_max, "local_port_max"); + _LIT(Kdst_port, "dst_port"); + _LIT(Kremote_port, "remote_port"); + _LIT(Kdst_port_max, "dst_port_max"); + _LIT(Kremote_port_max, "remote_port_max"); + _LIT(Kiap_id, "iap_id"); + _LIT(Kuid1, "uid1"); + _LIT(Kuid2, "uid2"); + _LIT(Kuid3, "uid3"); + _LIT(Kpriority, "priority"); + _LIT(Kname, "name"); + + if ((iToken.Compare(Kdst) == 0) || + (iToken.Compare(Kremote) == 0)) + { + error = ParseIPAddrAndMask(policy->iDst, policy->iDstMask); + } + else if ((iToken.Compare(Ksrc) == 0) || + (iToken.Compare(Klocal) == 0)) + { + error = ParseIPAddrAndMask(policy->iSrc, policy->iSrcMask); + } + else if (iToken.Compare(Kuser_id) == 0) + { + ; // Needs to be examined, TIdentity? -- msa + } + else if (iToken.Compare(Kprotocol) == 0) + { + error = Val(port); + policy->iProtocol = (TUint8)port; + } + else if ((iToken.Compare(Ksrc_port) == 0) || + (iToken.Compare(Klocal_port) == 0)) + { + error = Val(port); + policy->iSrc.SetPort(port); + if (policy->iSrcPortMax == 0) + { + policy->iSrcPortMax = (TUint16)port; + } + } + else if ((iToken.Compare(Ksrc_port_max) == 0) || + (iToken.Compare(Klocal_port_max) == 0)) + { + error = Val(port); + policy->iSrcPortMax = (TUint16)port; + } + else if ((iToken.Compare(Kdst_port) == 0) || + (iToken.Compare(Kremote_port) == 0)) + { + error = Val(port); + policy->iDst.SetPort(port); + if (policy->iDstPortMax == 0) + { + policy->iDstPortMax = (TUint16)port; + } + } + else if ((iToken.Compare(Kdst_port_max) == 0) || + (iToken.Compare(Kremote_port_max) == 0)) + { + error = Val(port); + policy->iDstPortMax = (TUint16)port; + } + else if (iToken.Compare(Kiap_id) == 0) + { + error = Val(port); + policy->iIapId = (TUint8)port; + } + else if (iToken.Compare(Kuid1) == 0) + { + error = Val(port); + uid1 = port; + } + else if (iToken.Compare(Kuid2) == 0) + { + error = Val(port); + uid2 = port; + } + else if (iToken.Compare(Kuid3) == 0) + { + error = Val(port); + uid3 = port; + } + else if (iToken.Compare(Kpriority) == 0) + { + error = Val(port); + policy->iPriority = port; + } + else if (iToken.Compare(Kname) == 0) + { + if (NextToken() != ETokenString) + { + delete policy; + return KErrGeneral; + } + policy->iName = iToken; + } + else + { + _LIT(Kinvalid_keyword, "invalid keyword "); + Error(Kinvalid_keyword); + delete policy; + return KErrGeneral; + } + + if (error != KErrNone) + { + _LIT(KErrorFormat, "Error = %d"); + Error(KErrorFormat, error); + delete policy; + return error; + } + } + while ((val = NextToken()) == ETokenString); + + TUidType uid_type(TUid::Uid(uid1), TUid::Uid(uid2), TUid::Uid(uid3)); + policy->iUid.Set(uid_type); + + // Update this to support multiple extension blocks + if (val != ETokenEqual || NextToken() != ETokenBraceLeft) + { + Error(Ksyntax_error); + error = KErrGeneral; + delete policy; + return error; + } + else + { + while ((val = NextToken()) == ETokenString && error == KErrNone) + { + switch (aPolicyType) + { + case EPfqosFlowspecPolicy: + { + error = FindExtensionPolicy((CExtensionPolicy*)policy); + break; + } + + case EPfqosModulespecPolicy: + { + error = FindExtensionPolicy((CExtensionPolicy*)policy); + break; + } + + default: + { + error = FindExtensionPolicy((CExtensionPolicy*)policy); + break; + } + } + } + } + + if (val != ETokenBraceRight || error != KErrNone) + { + if (error == KErrNone) + { + error = KErrGeneral; + } + delete policy; + } + else + { + AddPolicy(*(CExtensionPolicy*)policy); + } + + return error; + } + + +EXPORT_C CExtension* CExtension::NewL() + { + CExtension* extension = new (ELeave) CExtension(); + CleanupStack::PushL(extension); + extension->ConstructL(); + CleanupStack::Pop(); + return extension; + } + +EXPORT_C CExtension* CExtension::NewL(const TDesC8& aData) + { + CExtension* extension = new (ELeave) CExtension(); + CleanupStack::PushL(extension); + extension->ConstructL(); + extension->CopyL(aData); + CleanupStack::Pop(); + return extension; + } + + +CExtension::CExtension() + { + iVariables.SetOffset(_FOFF(TVariableBase, iNext)); + iBuf = NULL; + } + + +EXPORT_C CExtension::~CExtension() + { + TVariableQueueIter iter(iVariables); + TVariableBase* var; + while ((var = iter++) != NULL) + { + var->iNext.Deque(); + delete var; + } + delete iBuf; + } + +void CExtension::ConstructL() + { + iBuf = CBufFlat::NewL(KBufSize); + } + +EXPORT_C void CExtension::SetName(const TDesC& aName) + { + iName = aName; + } + + +EXPORT_C TVariableBase* CExtension::FindVariable(const TDesC& aName) + { + TVariableQueueIter iter(iVariables); + TVariableBase* var; + + while ((var = iter++) != NULL) + { + if (!aName.Compare(var->Name())) + { + return var; + } + } + return NULL; + } + + +EXPORT_C TInt CExtension::AddIntegerL(const TDesC& aName, TInt aValue) + { + TVariableBase *tmp = FindVariable(aName); + + /* + * Don't check for the existing variable names, + * if it is an SBLP variable. + */ + if (!(aName.Compare(KDescSblpMediaComponentNumber) == 0 || + aName.Compare(KDescSblpIPFlowNumber) == 0 )) + { + if (tmp) + { + return KErrAlreadyExists; + } + } + + TIntVariable *var = new (ELeave) TIntVariable(aName, aValue); + //lint --e{429} Lint doesn't understand AddLast semantics. + iVariables.AddLast(*var); + return KErrNone; + } + +EXPORT_C TInt CExtension::AddRealL(const TDesC& aName, TReal aValue) + { + TVariableBase *tmp = FindVariable(aName); + if (tmp) + { + return KErrAlreadyExists; + } + TRealVariable *var = new (ELeave) TRealVariable(aName, aValue); + //lint --e{429} Lint doesn't understand AddLast semantics. + iVariables.AddLast(*var); + return KErrNone; + } + +EXPORT_C TInt CExtension::AddStringL(const TDesC& aName, const TDesC& aValue) + { + TVariableBase *tmp = FindVariable(aName); + + /* + * Don't check for the existing variable names, + * if it is an SBLP variable. + */ + if (!(aName.Compare(KDescSblpMediaAuthorizationToken) == 0)) + { + if (tmp) + { + return KErrAlreadyExists; + } + } + + TStringVariable *var = new (ELeave) TStringVariable(aName, aValue); + //lint --e{429} Lint doesn't understand AddLast semantics. + iVariables.AddLast(*var); + return KErrNone; + } + +EXPORT_C TInt CExtension::Copy(TDes8& aData) + { + TVariableQueueIter iter(iVariables); + TVariableBase* var; + + TRAPD(err, InitL()); + while ((var = iter++) != NULL && err == KErrNone) + { + switch (var->Type()) + { + case KPfqosTypeInteger: + { + TIntVariable* intVar = (TIntVariable*) var; + TRAP(err, SetIntValueL(intVar->Value(), intVar->Name())); + } + break; + + case KPfqosTypeString: + { + TStringVariable* stringVar = (TStringVariable*) var; + TRAP(err, SetStringValueL(stringVar->Value(), + stringVar->Name())); + } + break; + + default: + break; + } + } + + if (err != KErrNone) + { + return err; + } + + TRAP(err, SetLengthL()); + if (err != KErrNone) + { + return err; + } + + if (aData.MaxLength() < iPos) + { + return KErrNoMemory; + } + iBuf->Read(0, aData, iPos); + return KErrNone; + } + + +EXPORT_C TInt CExtension::CopyL(const TDesC8& aData) + //??This is leaving function with status return? + //??Noone seems to check the return value, so + //??all errors are now changed to leaves. + { + Reset(); + + const TUint8 *p = aData.Ptr(); + TInt length = aData.Length(); + //lint -e{826} typecast OK + struct pfqos_configure *ext = (struct pfqos_configure *) p; + + if (length < (TInt)sizeof(pfqos_configure)) + { + User::Leave(KErrGeneral); // EMSGSIZE (impossible message size) + } + + if (ext->pfqos_configure_len * 8 != length) + { + User::Leave(KErrGeneral); // EMSGSIZE (incorrect message length) + } + + if (ext->pfqos_ext_type == EPfqosExtExtension) + { + p += sizeof(struct pfqos_configure); + //lint -e{826} typecast OK + pfqos_extension *extensionType = (pfqos_extension *) p; + + SetType(extensionType->pfqos_extension_type); + TPtrC8 extensionName((TUint8*) extensionType->extension_name); + if (iName.MaxLength() > extensionName.Length()) + { + // Need to have room for zero termination! + iName.Copy(extensionName); + } + iName.ZeroTerminate(); + + //lint -e{826} odd typecasts are OK + while (length > 0) + { + struct pfqos_configblock *block = (struct pfqos_configblock *) + (p + sizeof(pfqos_extension)); + int block_len = block->len; + + if (block_len < 1) + { + break; + } + block_len *= 8; + + if (block_len > length) + { + break; + } + //lint -e{961} Missing final 'else' is OK + if (block->type == KPfqosTypeInteger) + { + TPtrC8 tmp((TUint8 *)&block->id[0]); + struct pfqos_configblock_int *block_int = + (struct pfqos_configblock_int*) block; + + TName aName; + aName.Copy(tmp); + AddIntegerL(aName, block_int->value); + } + else if (block->type == KPfqosTypeReal) + { + TPtrC8 tmp((TUint8 *)&block->id[0]); + struct pfqos_configblock_real *block_real = + (struct pfqos_configblock_real*) block; + + TName name; + name.Copy(tmp); + //lint -e{747} float -> double + AddRealL(name, block_real->value); + } + else if (block->type == KPfqosTypeString) + { + TPtrC8 tmp((TUint8 *)&block->id[0]); + TPtrC8 value((TUint8 *)(((TUint8*)block)+ + sizeof(struct pfqos_configblock))); + + TName name, val; + + if (tmp.Length() > name.MaxLength() || + value.Length() > val.MaxLength()) + User::Leave(KErrArgument); + + name.Copy(tmp); + val.Copy(value); + AddStringL(name, val); + } + p += block_len; + length -= block_len; + } + } + + return KErrNone; + } + +EXPORT_C TInt CExtension::CopyL(CExtension& aExtension) + { + TVariableQueueIter iter(iVariables); + TVariableBase* var; + + aExtension.SetName(iName); + aExtension.SetType(iType); + + while ((var = iter++) != NULL) + { + switch (var->Type()) + { + case KPfqosTypeInteger: + { + TIntVariable* intVar = (TIntVariable*) var; + aExtension.AddIntegerL(intVar->Name(), intVar->Value()); + } + break; + + case KPfqosTypeReal: + { + TRealVariable* realVar = (TRealVariable*) var; + aExtension.AddRealL(realVar->Name(), realVar->Value()); + } + break; + + case KPfqosTypeString: + { + TStringVariable* stringVar = (TStringVariable*) var; + aExtension.AddStringL(stringVar->Name(), stringVar->Value()); + } + break; + + default: + break; + } + } + return KErrNone; + } + +EXPORT_C const TPtrC8 CExtension::Data() + { + if (!iBuf) + { + return TPtr8(0,0); + } + + TVariableQueueIter iter(iVariables); + TVariableBase* var; + + TRAPD(err, InitL()); + while ((var = iter++) != NULL && err == KErrNone) + { + switch (var->Type()) + { + case KPfqosTypeInteger: + { + TIntVariable* intVar = (TIntVariable*) var; + TRAP(err, SetIntValueL(intVar->Value(), intVar->Name())); + } + break; + + case KPfqosTypeString: + { + TStringVariable* stringVar = (TStringVariable*) var; + TRAP(err, SetStringValueL(stringVar->Value(), + stringVar->Name())); + } + break; + + default: + break; + } + } + + if (err != KErrNone) + { + return TPtr8(0,0); + } + + TRAP(err, SetLengthL()); + if (err != KErrNone) + { + return TPtr8(0,0); + } + + return iBuf->Ptr(0); + } + +EXPORT_C TInt CExtension::Length() const + { + if (iBuf) + { + return iBuf->Capacity(); + } + return 0; + } + +void CExtension::Reset() + { + TVariableQueueIter iter(iVariables); + TVariableBase* var; + while ((var = iter++) != NULL) + { + var->iNext.Deque(); + delete var; + } + iBuf->Reset(); + iPos=0; + } + +void CExtension::InitL() + { + iBuf->Reset(); + iPos=0; + + pfqos_configure header; + header.pfqos_configure_len = 0; + header.pfqos_ext_type = EPfqosExtExtension; + header.reserved = 0; + header.protocol_id = 0; + iBuf->InsertL(iPos, &header, sizeof(header)); + iPos += sizeof(header); + + pfqos_extension extensionType; + extensionType.pfqos_ext_len = 0; + extensionType.pfqos_ext_type = EPfqosExtExtension; + extensionType.pfqos_extension_type = iType; + TPtr8 name((TUint8*)extensionType.extension_name, 0, KMaxName); + if (name.MaxLength() > iName.Length()) + { + // Need to leave room for the zero termination! + name.Copy(iName); + } + name.ZeroTerminate(); + iBuf->InsertL(iPos, &extensionType, sizeof(extensionType)); + iPos += sizeof(extensionType); + } + + +void CExtension::SetIntValueL(TInt aValue, const TDesC& aName) + { + pfqos_configblock_int data; + TPtr8 ptr((TUint8 *)&data, sizeof(pfqos_configblock_int), + sizeof(pfqos_configblock_int)); + data.len = sizeof(pfqos_configblock_int)/8; + data.padding = data.reserved = 0; + data.type = KPfqosTypeInteger; + data.value = aValue; + TPtr8 tmpPtr((TUint8*)&data.id[0], 0, KMaxName); + if (tmpPtr.MaxLength() > aName.Length()) + { + // Need to leave room for the zero termination! + tmpPtr.Copy(aName); + } + tmpPtr.ZeroTerminate(); + iBuf->InsertL(iPos, ptr); + iPos += ptr.Length(); + } + + +void CExtension::SetReal32ValueL(TReal32 aValue, const TDesC& aName) + { + pfqos_configblock_real data; + TPtr8 ptr((TUint8 *)&data, sizeof(pfqos_configblock_real), + sizeof(pfqos_configblock_real)); + data.len = sizeof(pfqos_configblock_real)/8; + data.padding = data.reserved = 0; + data.type = KPfqosTypeReal; + data.value = aValue; + TPtr8 tmpPtr((TUint8*)data.id, 0, KMaxName); + if (tmpPtr.MaxLength() > aName.Length()) + { + // Need to leave room for the zero termination! + tmpPtr.Copy(aName); + } + tmpPtr.ZeroTerminate(); + iBuf->InsertL(iPos, ptr); + iPos += ptr.Length(); + } + + +void CExtension::SetStringValueL(const TDesC& aValue, const TDesC& aName) + { + pfqos_configblock data; + TPtr8 ptr((TUint8 *)&data, sizeof(pfqos_configblock), + sizeof(pfqos_configblock)); + data.len = (TUint16)((sizeof(pfqos_configblock) + aValue.Length() + 7)/8); + data.reserved = 0; + data.type = KPfqosTypeString; + TPtr8 tmpPtr((TUint8*) data.id, 0, KMaxName); + if (tmpPtr.MaxLength() > aName.Length()) + { + // Need to leave room for the zero termination! + tmpPtr.Copy(aName); + } + tmpPtr.ZeroTerminate(); + iBuf->InsertL(iPos, ptr); + iPos += ptr.Length(); + +#ifdef _UNICODE + HBufC8 *tmp = HBufC8::NewL(aValue.Length()); + tmp->Des().Copy(aValue); + iBuf->InsertL(iPos, *tmp); + delete tmp; +#else + iBuf->InsertL(iPos, aValue); +#endif + + iPos += aValue.Length(); + } + + +void CExtension::SetLengthL() + { + TUint16 length16 = (TUint16)((iPos +7) / 8); + TPtrC8 len = TPtrC8((TUint8 *)&length16, sizeof(length16)); + iBuf->Write(_FOFF(struct pfqos_configure, pfqos_configure_len), len); + + TInt pad = (length16 * 8 - iPos); + TUint8 dummy=0; + TPtrC8 dummy2 = TPtrC8((TUint8 *)&dummy, sizeof(dummy)); + for (TInt i = 0; i < pad; i++) + { + iBuf->InsertL(iPos, dummy2); + iPos++; + } + } +