diff -r 6b1d113cdff3 -r 6638e7f4bd8f telephonyprotocols/gprsumtsqosprt/src/async_request.cpp --- a/telephonyprotocols/gprsumtsqosprt/src/async_request.cpp Mon May 03 13:37:20 2010 +0300 +++ b/telephonyprotocols/gprsumtsqosprt/src/async_request.cpp Thu May 06 15:10:38 2010 +0100 @@ -1,1056 +1,1056 @@ -// Copyright (c) 2007-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 "iface.h" -#include "context.h" -#include "tc.h" -#include -#include "guqos_err.h" -#include "async_request.h" -#include "guqos_log.h" - - - -// Open Channel Machine -const SActionStep COpenChannel::iActionList[] = - { - &COpenChannel::ActionRemovePacketFilter, // iState=0 - &COpenChannel::ActionCommit, // iState=1 - &COpenChannel::ActionNewContext, // iState=2 - &COpenChannel::DoRememberCreatedContext, // iState=3 - &COpenChannel::ActionAddPacketFilter, // iState=4 - &COpenChannel::ActionAddSblpParameter, // iState=5 == KStateReuseOldContext! - &COpenChannel::ActionSetQoS, - &COpenChannel::ActionCommit, - &COpenChannel::DoAddFlowToContext, - &COpenChannel::ActionNegotiationComplete - }; -const TInt KStateReuseOldContext = 5; // *KEEP THIS IN SYNCH WITH ABOVE!* - - - -// Negotiate Channel Machine -const SActionStep CNegotiateChannel::iActionList[] = - { - &CNegotiateChannel::ActionAddSblpParameter, - &CNegotiateChannel::ActionSetQoS, - &CNegotiateChannel::ActionCommit, - &CNegotiateChannel::ActionNegotiationComplete, - }; - -// Join Channel Machine -const SActionStep CJoinRequest::iActionList[] = - { - &CJoinRequest::ActionRemovePacketFilter, - &CJoinRequest::ActionCommit, - &CJoinRequest::DoStartWithTargetContext, - &CJoinRequest::ActionAddPacketFilter, - &CJoinRequest::DoAddFlowToContext, - &CJoinRequest::ActionRemovePacketFilter, // Cleanup extra filters away, if present - &CJoinRequest::ActionCommit, - &CJoinRequest::ActionRequestComplete - }; - -// Leave Channel Machine -const SActionStep CLeaveRequest::iActionList[] = - { - &CLeaveRequest::ActionRemovePacketFilter, - &CLeaveRequest::ActionCommit, - &CLeaveRequest::ActionRequestComplete - }; - -// Update Channel Machine (misnamed as "Close") -const SActionStep CClose::iActionList[] = - { - &CClose::ActionRemovePacketFilter, - &CClose::ActionCommit, - &CClose::ActionRequestComplete - }; - - -#ifdef _LOG -// -// Logging help classes -// - -class TLogContextInfo : public TBuf<100> - { -public: - TLogContextInfo(const CPdpContext* aContext); - }; - -TLogContextInfo::TLogContextInfo(const CPdpContext* aContext) - { - if (aContext) - { - Format(_L("context[%u] id=%d"), (TInt)aContext, aContext->ContextId()); // + 32 - switch (aContext->ContextType()) - { - case EPrimaryContext: Append(_L(" primary")); break; - case ESecondaryContext: Append(_L(" secondary")); break; // + 10 - case ENetworkInitiatedContext: Append(_L(" network")); break; - default: Append(_L(" unknown")); break; - } - switch (aContext->ContextStatus()) - { - case RPacketContext::EStatusInactive: Append(_L(" inactive")); break; - case RPacketContext::EStatusActivating: Append(_L(" activating")); break; - case RPacketContext::EStatusActive: Append(_L(" active")); break; - case RPacketContext::EStatusDeactivating: Append(_L(" deactivating")); break; // + 12 - case RPacketContext::EStatusSuspended: Append(_L(" suspended")); break; - case RPacketContext::EStatusDeleted: Append(_L(" deleted")); break; - default: Append(_L(" unknown")); break; - } - AppendFormat(_L("(%d)"), (TInt)aContext->ContextStatus()); // + 4 - - if (aContext->ChannelId()) - { - AppendFormat(_L(" channel=%d"), aContext->ChannelId()); // + 18 - } - AppendFormat(_L(", %d flows"), aContext->RefCount()); // + 11; - } - else - { - Append(_L("context NONE")); - } - } - -#endif - - -CRequestBase::CRequestBase(CNif& aNif) : iNif(aNif) - { -#ifdef _LOG - // This is only fallback, and should be overriden by the - // derived classes! - _LIT(KLogName, "Base"); - iName = &KLogName(); -#endif - } - -CRequestBase::~CRequestBase() - { - LOG(Log::Printf(_L("~\trequest %S[%u] destructed"), iName, (TInt)this)); - } - -void CRequestBase::SetContext(CPdpContext *aContext) - /** - * Set/clear the current context for the state machine. - */ - { - LOG(TLogContextInfo info(aContext)); - LOG(Log::Printf(_L("\trequest %S[%u] -- %S set"), iName, (TInt)this, &info)); - if (iContext != aContext) - { - iContext = aContext; - // Context has been changed, need to clear modified flag. - iContextModified = EFalse; - } - iParams = NULL; // Paremeters can only come from NIF event. - } - -void CRequestBase::SetExpected(const TRequest aRequest) - { - /** - * Define the expected result of the next asynchronous operation. - */ - iExpected = aRequest; - // Assume that SetExpected is only used when a request to NIF - // has been passed. Thus, any call to SetExpected implies that - // the context will be modified by NIF. - iContextModified = ETrue; - } - - -static TBool CheckSblpErrorInPcoBuffer(const TContextParameters& aParams, TUint8& parsedSblpErrorValue) - { - TBool retValue = EFalse; - TInt ret = KErrNone; - - // create the PCO id for rejection code - RPacketContext::TPcoId sblpRejectionCodePcoId( - RPacketContext::EEtelPcktPolicyControlRejectionCode); - /* - * get the value of the RPacketContext::TContextConfigGPRS - * object from the TContextParameters object passed by the nif - */ - RPacketContext::TContextConfigGPRS configGPRS; - aParams.iContextConfig.GetContextConfig(configGPRS); - - // adjust the PCO buffer - TPtr8 pcoBufferPtr(const_cast - (configGPRS.iProtocolConfigOption.iMiscBuffer.Ptr()), - configGPRS.iProtocolConfigOption.iMiscBuffer.Length(), - configGPRS.iProtocolConfigOption.iMiscBuffer.Length()); - - // attach TTlv to the buffer - TTlvStruct - pcoTLV(pcoBufferPtr,pcoBufferPtr.Length()); - - // Retreive the sblp rejection code value from the buffer - TBuf8<253> sblpRejectionCodeBuf; - sblpRejectionCodeBuf.SetLength(pcoBufferPtr.Length()); - TPtr8 sblpRejectionCodePtr(const_cast(sblpRejectionCodeBuf.Ptr()), - sblpRejectionCodeBuf.Length(),sblpRejectionCodeBuf.MaxLength()); - - pcoTLV.ResetCursorPos(); - TRAPD(err1, ret=pcoTLV.NextItemL(sblpRejectionCodePcoId,sblpRejectionCodePtr) ); - if (err1 !=KErrNone || ret!=KErrNone) - { - return EFalse; - } - - // sblpRejectionCodeBuf[0] shall contain SBLP Rejection code ( values 1-7)) - parsedSblpErrorValue = sblpRejectionCodePtr[0]; - if(parsedSblpErrorValue >= ESblpSubErrorValueMinimum && - parsedSblpErrorValue <= ESblpSubErrorValueMaximum) - { - retValue = ETrue; - } - return retValue; - } - - -void CRequestBase::Run(const TRequest aRequest, CPdpContext* aContext, const TContextParameters& aParams) - { - LOG(const TDesC* const name(iName)); // because request can get destroyed from under us, save the name here! - LOG(TLogContextInfo info(aContext)); - LOG(Log::Printf(_L("Run\trequest %S[%u] Actions on event=%d reason=%d expected event=%d on %S"), - name, (TInt)this, (TInt)aRequest, aParams.iReasonCode, (TInt)iExpected, &info)); - - iContext = aContext; - iParams = &aParams; - - if (iExpected != aRequest && iExpected != EPendingAny) - { - CompleteAndDestruct(KErrCancel, NULL); - } - else if (aParams.iReasonCode == KErrNone) - { - // Reset to accepting any, actions must use SetExpected, - // when they activate asynchronous operation with - // a specific responce. - iExpected = EPendingAny; - do - { - ++iState; // Last state done OK, try next one. - } - while (!Action(iContext, iParams)); - // Note: there is no special terminating test, it is excepted that - // the builder of action list guarantees that it always ends with - // action which unconditionally returns ETrue. - } - else - { - // The expected request has failed. - TInt reason = aParams.iReasonCode; - - iExtension.SetUmtsType(); - - /* - * if there is KErrGprsUserAuthenticationFailure error code returned by - * the etel via nif, then we must check for the possible specific sblp - * errors in the Protocol Configuration Option PCO buffer. - * - * If the buffer has a value for the - * TPcoIDNetworkToMS::EEtelPcktPolicyControlRejectionCode id, then we can - * decide that sblp specific error has been occured if one of the the - * possible sub error codes (totally six!) matches. - */ - - if (reason == KErrGprsUserAuthenticationFailure) - { - TUint8 parsedSblpErrorValue = KErrNone; - /* - * check if PCO buffer has sblp rejection code error value - * calling CheckSblpErrorInPcoBuffer() returns true only - * if there is error in the buffer and if the error range - * is between (1-7) - */ - if (CheckSblpErrorInPcoBuffer(aParams,parsedSblpErrorValue)) - { - /* - * it is definitely a sblp error - * Set the sblp error flag - */ - iExtension.SetSblpType(); - - // figure out the sub error type - switch (parsedSblpErrorValue) - { - case 1: - // Use the sblp error code to create Failure() - reason = EGuqosSblpAuthorizationFailureOfRequest; - break; - case 2: - reason = EGuqosSblpMissingBindingInfo; - break; - case 3: - reason = EGuqosSblpInvalidBindingInfo; - break; - case 4: - reason = EGuqosSblpBindingInfoNotAllowed; - break; - case 5: - reason = EGuqosSblpAuthorizingEntityTemporarilyUnavailable; - break; - case 6: - reason = EGuqosSblpNoCorrespondingSession; - break; - case 7: - reason = EGuqosSblpInvalidBundling; - break; - default: - /* - * it will never reach here! - * because the range checking is already done in - * CheckSblpErrorInPcoBuffer(aParams,parsedSblpErrorValue) - */ - LOG(Log::Printf(_L("\trequest%S[%u] SBLP error value range fault!"), name, (TInt)this)); - break; - } - } - } - // Deliver failure to the actual request implementation. - Failure(aContext, reason); - } - LOG(Log::Printf(_L("\trequest %S[%u] Run Actions Exit"), name, (TInt)this)); - } - - -void CRequestBase::Start() - { - LOG(const TDesC* const name(iName)); // because request can get destroyed from under us, save the name here! - LOG(TLogContextInfo info(iContext)); - LOG(Log::Printf(_L("\trequest %S[%u] Start Actions with %S"), name, (TInt)this, &info)); - // Rely on C-class 0-fill. Initially all state variables - // are zero, e.g. - // iContext = NULL; - // iParams = NULL; - // iExpected = EPendingAny; - // iState = 0 - // This start does not touch those values and allows derived - // class to override this function with something that may initialize - // state, before calling the base implementation of the Start. - - // Excecute actions until something catches or request terminates. - while (!Action(iContext, iParams)) - { - ++iState; - } - // Note: there is no special terminating test, it is excepted that - // the builder of action list guarantees that it always ends with - // action which unconditionally returns ETrue. - LOG(Log::Printf(_L("\trequest %S[%u] Start Actions Exit"), name, (TInt)this)); - } - -void CRequestBase::CompleteAndDestruct(TInt aErrorCode, const TQoSParameters* aParams, const TExtensionData& aExtension) - { - LOG(Log::Printf(_L("\trequest %S[%u] CompleteAndDestruct ErrorCode=%d"), iName, (TInt)this, aErrorCode)); - // Remove all references to this request... - iNif.CloseRequest(this); - // ...before delivering the completion. The delivery may call - // back, and this request must be totally removed by then, or - // bad things can happen (like, duplicate delete). - if (iNotify) - iNotify->RequestComplete(aErrorCode, aParams, aExtension); - delete this; - } - - -TBool CRequestBase::IsOk(TInt aResult, CPdpContext *aContext) - { - if (aResult >= 0) - return ETrue; - LOG(TLogContextInfo info(aContext)); - LOG(Log::Printf(_L("\trequest %S[%u] IsOk(%d) is not OK %S"), iName, (TInt)this, aResult, &info)); - Failure(aContext, aResult); - return EFalse; - } - -TBool CRequestBase::ActionRemovePacketFilter(CPdpContext* aContext, const TContextParameters*) - /** - * Activate leaving flow from a context. - */ - { - LOG(TLogContextInfo info(aContext)); - LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionRemovePacketFilter from %S"), iName, (TInt)this, iState, &info)); - if (aContext) - { - // This branch is needed for the primary too, but only in rare case - // where a secondary is being changed into a primary. - if (iFlow) - { - // Move the flow to default context. If remove - // fails, it is higly likely that this flow was - // not included in TFT. - iFlow->SetContext(iNif.DefaultPdpContext()); - } - if (aContext->RefCount() > 0 || aContext->IsPrimary()) - { - // Context has remaining flows or is a Primary, collect unused filters. - // (in case of primary, all filters will be unused, if any present). - TTFTInfo tft; - TInt ret = aContext->RemovePacketFilter(tft, iFlow); - if (ret > 0) - { - LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionRemovePacketFilter -- removing %d filter(s)"), iName, (TInt)this, iState, ret)); - SetExpected(EPendingPacketFilterRemove); - (void)IsOk(aContext->ModifyTft(KRemoveFilters, tft), aContext); - return ETrue; - } - else if (ret < 0) - { - LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionRemovePacketFilter -- TFT construct failed with %d"), iName, (TInt)this, iState, ret)); - CompleteAndDestruct(ret, NULL); - return ETrue; - } - } - else - { - // All flows have been removed from the context. In the current implementation - // the context has been scheduled for destruction, and there is no need for - // removing any existing TFT... - LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionRemovePacketFilter -- No flows left"), iName, (TInt)this, iState)); - } - } - // No TFT changes need to be done, - LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionRemovePacketFilter -- no filters to remove"), iName, (TInt)this, iState)); - return EFalse; - } - - -TBool CRequestBase::ActionAddPacketFilter(CPdpContext* aContext, const TContextParameters* /*aParams*/) - { - LOG(TLogContextInfo info(aContext)); - LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionAddPacketFilter on %S"), iName, (TInt)this, iState, &info)); - if (aContext && iFlow) - { - TTFTInfo tft; - TInt err = aContext->AddPacketFilter(*iFlow, tft); - if (err < 0) - { - LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionAddPacketFilter -- TFT construct failed with %d"), iName, (TInt)this, iState, err)); - Failure(aContext, err); - return ETrue; - } - else if (err > 0) - { - LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionAddPacketFilter -- adding %d filter(s)"), iName, (TInt)this, iState, err)); - SetExpected(EPendingPacketFilterAdd); - (void)IsOk(aContext->ModifyTft(KAddFilters, tft), aContext); - return ETrue; - } - // Filter does not need modification, start some other operation... - } - LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionAddPacketFilter -- no filters added"), iName, (TInt)this, iState)); - return EFalse; - } - -TBool CRequestBase::ActionCommit(CPdpContext* aContext, const TContextParameters* /*aParams*/) - /** - * Activate changes made to a context. - * - * This action can be run after a sequence of context modifying - * actions (filter, QoS, etc.). Depending on the state of the - * context, this calls either ModifyActive or Activate. - */ - { - if (aContext) - { - LOG(TLogContextInfo info(aContext)); - - if (!aContext->ContextActive()) - { - LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionCommit -- start Activate %S"), iName, (TInt)this, iState, &info)); - SetExpected(EPendingActivate); - (void)IsOk(aContext->Activate(), aContext); - } - else if (iContextModified) - { - LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionCommit -- start ModifyActive %S"), iName, (TInt)this, iState, &info)); - SetExpected(EPendingModifyActive); - (void)IsOk(aContext->ModifyActive(), aContext); - } - else - { - // For example all flows go into same tunnel and filter is same for everyone. - // A flow leaving context does not affect the filter. - LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionCommit -- skip ModifyActive, not modified %S"), iName, (TInt)this, iState, &info)); - return EFalse; - } - return ETrue; - } - LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionCommit -- nothing to do, no context"), iName, (TInt)this, iState)); - return EFalse; - } - - -TBool CRequestBase::ActionRequestComplete(CPdpContext* /*aContext*/, const TContextParameters* /*aParams*/) - { - /** - * Default termination of the request. - * - * This action can be used as a default terminator of the request, - */ - LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionRequestComplete"), iName, (TInt)this, iState)); - CompleteAndDestruct(KErrNone, NULL); - return ETrue; - } - -TBool CRequestBase::DoAddFlowToContext(CPdpContext* aContext, const TContextParameters*) - /** - * Set add current flow to current context. - * - * Add current flow to current context internally (e.g. add CFlowData object to - * CPdpContext object). - */ - { - LOG(TLogContextInfo info(aContext)); - if (iFlow && aContext) - { - LOG(Log::Printf(_L("\trequest %S[%u] %2d.DoAddFlowToContext to %S"), iName, (TInt)this, iState, &info)); - iFlow->SetContext(aContext); - } - else - { - LOG(Log::Printf(_L("\trequest %S[%u] %2d.DoAddFlowToContext to %S [not done]"), iName, (TInt)this, iState, &info)); - } - // This allows the use ActionRemovePacketFilter to be used after this - // to clean out unnecessary filters. This is required in Join, because - // when the last flow leaves, the filters are not updated (cannot be - // removed because PDP Context cannot exist without filters, and just - // deleting the context would be too drastic). Thus, when the same flow - // or new flow joins back to existing context, we need to check and - // clean out stale filters. - iFlow = NULL; - return EFalse; - } - -void CRequestBase::Cancel(CFlowData* aFlowData) - /** - * Default cancel based on flow. - * - * If the only CFlowData pointer in request is stored in iFlow, - * then this default Cancel should be enough for most cases. - */ - { - if (iFlow == aFlowData) - { - LOG(Log::Printf(_L("\trequest %S[%u] Cancel due flow[%u] -- only detach the flow"), iName, (TInt)this, (TInt)iFlow)); - // A running request is hard to cancel, because there is no way - // to tell NIF about it. Thus, when flow is cancelled, just detach - // it from the request and let the state machine run to completion - // without the flow (the machine should adapt!) - iFlow = NULL; - } - } - -void CRequestBase::Failure(CPdpContext* aContext, TInt aErrorCode) - /** - * The default Failure handler. - * - * Load the error code into iExtension and destruct. - */ - { - LOG(TLogContextInfo info(aContext)); - (void)aContext; // silence warning in MARM release compile. - TInt ret = iExtension.SetErrorCode(aErrorCode); - LOG(Log::Printf(_L("\trequest %S[%u] Failure %S errorcode=%d ret=%d"), iName, (TInt)this, &info, aErrorCode, ret)); - CompleteAndDestruct(ret == KErrNone ? aErrorCode : ret, NULL); - } - -// CNegotiationBase -CNegotiationBase::CNegotiationBase(CNif& aNif) : CRequestBase(aNif) - { -#ifdef _LOG - // This is only fallback, and should be ovvrriden by the - // derived classes! - _LIT(KLogName, "Negotiation"); - iName = &KLogName(); -#endif - } - -void CNegotiationBase::SetParameters(const TQoSParameters& aParams, CExtensionPolicy& aPolicy) - { - LOG(Log::Printf(_L("\trequest %S[%u] SetParamaters"), iName, (TInt)this)); - iGeneric = aParams; - iUmts.ParsePolicyData(&aPolicy); - } - -void CNegotiationBase::SetParametersFlowExtn(CExtensionPolicy &aPolicy) - { - // ParsePolicyData will return true if SBLP presents - if (iFlowExtnParams.ParsePolicyDataForSblp(&aPolicy)) - { - // SBLP presents - // so, set the Sblp flag for the channel - iSblp = ETrue; - LOG(Log::Printf(_L("\trequest %S[%u] SetParametersFlowExtn -- SBLP"), iName, (TInt)this)); - } - } - -// CNegotiationBase -TBool CNegotiationBase::ActionAddSblpParameter(CPdpContext *aContext, const TContextParameters* /*aParams*/) - { - /* - * if SBLP is supported, sblp parameter is added after setting the - * Qos parameters - * - * once sblp parameter is added, the operations continue in the same - * way as it was - */ - if(aContext && iSblp) // the negotiations requests sblp context - { - // call modifytft to add sblp - LOG(TLogContextInfo info(aContext)); - TTFTInfo tft; - if (IsOk(tft.AddSblpToken(iFlowExtnParams.iAuthorizationToken, iFlowExtnParams.iFlowIds), aContext)) - { - LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionAddSblpParameter -- Adding SBLP for %S"), iName, (TInt)this, iState, &info)); - SetExpected(EPendingSblpParameterAdd); - (void)IsOk(aContext->ModifyTft(KAddSblpParameter, tft), aContext); - } - else - { - LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionAddSblpParameter -- Failed constructing TFT for SBLP for %S"), - iName, (TInt)this, iState, &info)); - } - return ETrue; - } - LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionAddSblpParameter -- no SBLP"), iName, (TInt)this, iState)); - return EFalse; - } - -TBool CNegotiationBase::ActionSetQoS(CPdpContext *aContext, const TContextParameters* /*aParams*/) - { - if (aContext) - { - LOG(TLogContextInfo info(aContext)); - LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionSetQoS -- request %S"), iName, (TInt)this, iState, &info)); - SetExpected(EPendingSetQoS); - (void)IsOk(aContext->SetQoS(iGeneric, iUmts), aContext); - return ETrue; - } - LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionSetQoS -- skipping"), iName, (TInt)this, iState)); - return EFalse; - } - - -TBool CNegotiationBase::ActionNegotiationComplete(CPdpContext *aContext, const TContextParameters* aParams) - { - LOG(TLogContextInfo info(aContext)); - LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionNegotiationComplete %S"), iName, (TInt)this, iState, &info)); - if (aParams) - { - // Return results of the negotiation to upper layers. - TInt ret = iExtension.CreateExtension(aParams->iContextConfig, aParams->iReasonCode); - if (ret != KErrNone) - { - LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionNegotiationComplete -- CreateExtension fail=%d"), iName, (TInt)this, iState, ret)); - // Ugh.. can't construct the return value (probably out of memory) - // Try plain error instead (if that does not work, then nothing can - // be done about it...) - (void)iExtension.SetErrorCode(ret); - } - } - - if (iFlow && aContext) - { - // If there is assocated flow, assume it will need to be moved - // to the current context (nothing happens, if this is already - // true. - iFlow->SetContext(aContext); - } - - CompleteAndDestruct(KErrNone, &iGeneric, iExtension); - return ETrue; - } - -void CNegotiationBase::Failure(CPdpContext* /*aPdpContext*/, TInt aErrorCode) - { - // If allocation space for extn fails, there not much - // that can be done, the request must be completed anyway - // with empty extn. - LOG(Log::Printf(_L("\trequest %S[%u] Failure code=%d"), iName, (TInt)this, aErrorCode)); - (void)iExtension.SetErrorCode(aErrorCode); - CompleteAndDestruct(aErrorCode, &iGeneric, iExtension); - } - - -// CClose - -CClose* CClose::New(CPdpContext& aContext) - { - return new CClose(aContext); - } - -CClose::CClose(CPdpContext& aContext) : CRequestBase(aContext.Nif()), iClosing(aContext) - { -#ifdef _LOG - _LIT(KLogName, "Close"); - iName = &KLogName(); -#endif - LOG(Log::Printf(_L("new\trequest %S[%u] size=%d"), iName, (TInt)this, sizeof(*this))); - iNotify = NULL; - } - -void CClose::Start() - { - LOG(TLogContextInfo info(&iClosing)); - LOG(Log::Printf(_L("Start\trequest %S[%u] %S"), iName, (TInt)this, &info)); - // Give the context to the state machine. - SetContext(&iClosing); - // Note: iFlow is NULL. This means that the packet - // filter is just recomputed based on currenly - // joined flows. - CRequestBase::Start(); - } - -CClose::~CClose() - { - } - -void CClose::Cancel(CPdpContext* aContext) - { - if (&iClosing == aContext) - { - LOG(TLogContextInfo info(aContext)); - LOG(Log::Printf(_L("Cancel\trequest %S[%u] for %S"), iName, (TInt)this, &info)); - Failure(aContext, KErrDied); - } - } - - -CDeleteRequest* CDeleteRequest::NewL(CPdpContext *aContext) - { - return new (ELeave) CDeleteRequest(aContext); - } - -CDeleteRequest::CDeleteRequest(CPdpContext* aContext) : CRequestBase(aContext->Nif()), iDelete(aContext) - { -#ifdef _LOG - _LIT(KLogName, "Delete"); - iName = &KLogName(); -#endif - LOG(Log::Printf(_L("new\trequest %S[%u] size=%d"), iName, (TInt)this, sizeof(*this))); - iNotify = NULL; - } - -void CDeleteRequest::Start() - { - LOG(TLogContextInfo info(iDelete)); - LOG(Log::Printf(_L("Start\trequest %S[%u] %S"), iName, (TInt)this, &info)); - // Issue a context delete for this context to NIF - if (iDelete) - { - CPdpContext* context = iDelete; - iDelete = NULL; // Prevent Cancel() from triggering... - context->Delete(); // Send delete request to NIF - context->Nif().DeletePdpContext(context); // Destroys the object (.. this calls my Cancel!) - } - CompleteAndDestruct(KErrNone, NULL); - } - -void CDeleteRequest::Cancel(CPdpContext* aContext) - { - if (aContext == iDelete) - { - LOG(TLogContextInfo info(aContext)); - LOG(Log::Printf(_L("Cancel\trequest %S[%u] for %S"), iName, (TInt)this, &info)); - Failure(aContext, KErrDied); - } - } - - -// COpenChannel - -COpenChannel* COpenChannel::New(TUint aChannelId, CFlowData &aFlow, MQoSNegotiateEvent* aNotify) - { - return new COpenChannel(aChannelId, aFlow, aNotify); - } - -COpenChannel::COpenChannel(TInt aChannelId, CFlowData& aFlow, MQoSNegotiateEvent* aNotify) : - CNegotiationBase(aFlow.Nif()), - iChannelId(aChannelId) - { -#ifdef _LOG - _LIT(KLogName, "Open"); - iName = &KLogName(); -#endif - LOG(Log::Printf(_L("new\trequest %S[%u] size=%d"), iName, (TInt)this, sizeof(*this))); - iNotify = aNotify; - iFlow = &aFlow; - } - -COpenChannel::~COpenChannel() - { - } - -TBool COpenChannel::ActionNewContext(CPdpContext */*aContext*/, const TContextParameters* /*aParams*/) - { - LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionNewContext"), iName, (TInt)this, iState)); - SetExpected(EPendingCreate); - (void)IsOk(iNif.NewPdpContext(), NULL); - return ETrue; - } - -TBool COpenChannel::DoRememberCreatedContext(CPdpContext* aContext, const TContextParameters*) - { - iNewContext = aContext; - if (aContext) - { - // ..and bind it to the channel id. - aContext->SetChannelId(iChannelId); - LOG(TLogContextInfo info(aContext)); - LOG(Log::Printf(_L("\trequest %S[%u] %2d.DoRememberCreatedContext -- %S"), iName, (TInt)this, iState, &info)); - } - else - { - LOG(Log::Printf(_L("\trequest %S[%u] %2d.DoRememberCreatedContext -- No context created for channel=%d"), - iName, (TInt)this, iState, iChannelId)); - } - return EFalse; - } - -void COpenChannel::Start() - { - LOG(Log::Printf(_L("Start\trequest %S[%u] -- COpenChannel Begin"), iName, (TInt)this)); - if (!iFlow) - { - LOG(Log::Printf(_L("\trequest %S[%u] Flow has been cancelled"), iName, (TInt)this)); - CompleteAndDestruct(KErrNone, NULL); - return; - } - - // First check if currently used Pdp context can be modified!! - CPdpContext* context = iFlow->PdpContext(); - SetContext(context); - if (context && context != iNif.DefaultPdpContext()) - { - if (context->RefCount() == 1) - { - LOG(TLogContextInfo info(context)); - LOG(Log::Printf(_L("\trequest %S[%u] -- reuse existsing %S"), iName, (TInt)this, &info)); - // Start state machine at different point. - iState = KStateReuseOldContext; - } - } - // If not reusing old, the machine starts by trying - // to remove the TFT from old context, if any... - CRequestBase::Start(); - } - - -void COpenChannel::Failure(CPdpContext* aPdpContext, TInt aErrorCode) - { - LOG(Log::Printf(_L("\trequest %S[%u] Failure code=%d"), iName, (TInt)this, aErrorCode)); - - if (aPdpContext && aPdpContext == iNewContext) - { - iNewContext = NULL; - aPdpContext->Delete(); - CNif& nif = aPdpContext->Nif(); - nif.DeletePdpContext(aPdpContext); - } - CNegotiationBase::Failure(aPdpContext, aErrorCode); - } - -void COpenChannel::Cancel(CPdpContext* aContext) - { - if (aContext == iNewContext) - { - // Prevent Failure from deleting the context (the caller of Cancel is - // just doing that). - iNewContext = NULL; - LOG(TLogContextInfo info(aContext)); - LOG(Log::Printf(_L("Cancel\trequest %S[%u] Cancelled for "), iName, (TInt)this, &info)); - Failure(aContext, KErrDied); - } - } - - -// CNegotiateChannel - -CNegotiateChannel* CNegotiateChannel::New(CPdpContext* aContext, MQoSNegotiateEvent* aNotify) - { - return new CNegotiateChannel(aContext, aNotify); - } - -CNegotiateChannel::CNegotiateChannel(CPdpContext *aContext, MQoSNegotiateEvent* aNotify) : - CNegotiationBase(aContext->Nif()) - { -#ifdef _LOG - _LIT(KLogName, "Negotiate"); - iName = &KLogName(); -#endif - LOG(Log::Printf(_L("new\trequest %S[%u] size=%d"), iName, (TInt)this, sizeof(*this))); - iNotify = aNotify; - iChannel = aContext; - } - -CNegotiateChannel::~CNegotiateChannel() - { - } - - -void CNegotiateChannel::Start() - { - LOG(Log::Printf(_L("Start\trequest %S[%u] -- CNegotiateChannel Begin"), iName, (TInt)this)); - SetContext(iChannel); - CRequestBase::Start(); - } - - -void CNegotiateChannel::Cancel(CPdpContext* aContext) - { - if (iChannel == aContext) - { - LOG(TLogContextInfo info(aContext)); - LOG(Log::Printf(_L("Cancel\trequest %S[%u] Cancelled for %S"), iName, (TInt)this, &info)); - iChannel = NULL; - - //??Where does this go? - Failure(aContext, KErrDied); - } - } - - - -// CJoinRequest -CJoinRequest* CJoinRequest::New(CPdpContext* aContext, CFlowData* aFlowData, MQoSNegotiateEvent* aNotify) - { - return new CJoinRequest(aContext, aFlowData, aNotify); - } - -CJoinRequest::CJoinRequest(CPdpContext* aContext, CFlowData* aFlowData, MQoSNegotiateEvent* aNotify) : - CRequestBase(aFlowData->Nif()) - { -#ifdef _LOG - _LIT(KLogName, "Join"); - iName = &KLogName(); -#endif - LOG(Log::Printf(_L("new\trequest %S[%u] size=%d"), iName, (TInt)this, sizeof(*this))); - iNotify = aNotify; - iChannel = aContext; - iFlow = aFlowData; - } - -CJoinRequest::~CJoinRequest() - { - } - -void CJoinRequest::Start() - { - LOG(Log::Printf(_L("Start\trequest %S[%u] -- CJoinRequest Begin"), iName, (TInt)this)); - if (!iFlow) - { - LOG(Log::Printf(_L("\trequest %S[%u] Flow has been cancelled"), iName, (TInt)this)); - CompleteAndDestruct(KErrNone, NULL); - return; - } - CPdpContext* context = iFlow->PdpContext(); - LOG(TLogContextInfo info(context)); - if (context == iChannel) - { - // Already joined to the target context - LOG(Log::Printf(_L("\trequest %S[%u] already joined to %S"), iName, (TInt)this, &info)); - CompleteAndDestruct(KErrNone, NULL, iExtension); - return; - } - // Start with removal of the TFT from old context. - SetContext(context); - CRequestBase::Start(); - } - - -TBool CJoinRequest::DoStartWithTargetContext(CPdpContext */*aContext*/, const TContextParameters* /*aParams*/) - { - LOG(TLogContextInfo info(iChannel)); - LOG(Log::Printf(_L("\trequest %S[%u] %2d.DoStartWithTargetContext -- target %S"), iName, (TInt)this, iState, &info)); - SetContext(iChannel); - return EFalse; - } - - -void CJoinRequest::Failure(CPdpContext* /*aPdpContext*/, TInt aErrorCode) - { - LOG(Log::Printf(_L("\trequest %S[%u] Failure code=%d"), iName, (TInt)this, aErrorCode)); - iExtension.SetErrorCode(aErrorCode); - CompleteAndDestruct(EQoSJoinFailure, NULL, iExtension); - } - -void CJoinRequest::Cancel(CPdpContext* aContext) - { - if (iChannel == aContext) - { - LOG(TLogContextInfo info(aContext)); - LOG(Log::Printf(_L("Cancel\trequest %S[%u] Cancelled for %S"), iName, (TInt)this, &info)); - Failure(aContext, KErrDied); - } - } - -// CLeaveRequest -CLeaveRequest* CLeaveRequest::New(CPdpContext* aContext, CFlowData* aFlowData, MQoSNegotiateEvent* aNotify) - { - return new CLeaveRequest(aContext, aFlowData, aNotify); - } - -CLeaveRequest::CLeaveRequest(CPdpContext* aContext, CFlowData* aFlowData, MQoSNegotiateEvent* aNotify) : - CRequestBase(aContext->Nif()) - { -#ifdef _LOG - _LIT(KLogName, "Leave"); - iName = &KLogName(); -#endif - LOG(Log::Printf(_L("new\trequest %S[%u] size=%d"), iName, (TInt)this, sizeof(*this))); - iNotify = aNotify; - iChannel = aContext; - iFlow = aFlowData; - //?? Why channel? it should be same as flow currently joined? - //?? Or just use channel and recompute, leave == close? - } - -void CLeaveRequest::Start() - { - LOG(Log::Printf(_L("Start\trequest %S[%u] -- CLeaveRequest Begin"), iName, (TInt)this)); - // Start with removal of the TFT from old context. - // The flow has nothing to do with this anymore? - SetContext(iChannel); - CRequestBase::Start(); - } - -CLeaveRequest::~CLeaveRequest() - { - LOG(Log::Printf(_L("CLeaveRequest::~CLeaveRequest()"))); - } - - -void CLeaveRequest::Failure(CPdpContext* /*aPdpContext*/, TInt aErrorCode) - { - LOG(Log::Printf(_L("\trequest %S[%u] Failure code=%d"), iName, (TInt)this, aErrorCode)); - iExtension.SetErrorCode(aErrorCode); - CompleteAndDestruct(EQoSLeaveFailure, NULL, iExtension); - } - -void CLeaveRequest::Cancel(CPdpContext* aContext) - { - if (iChannel == aContext) - { - LOG(TLogContextInfo info(aContext)); - LOG(Log::Printf(_L("Cancel\trequest %S[%u] Cancelled for %S"), iName, (TInt)this, &info)); - Failure(aContext, KErrDied); - } - } +// Copyright (c) 2007-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 "iface.h" +#include "context.h" +#include "tc.h" +#include +#include "guqos_err.h" +#include "async_request.h" +#include "guqos_log.h" + + + +// Open Channel Machine +const SActionStep COpenChannel::iActionList[] = + { + &COpenChannel::ActionRemovePacketFilter, // iState=0 + &COpenChannel::ActionCommit, // iState=1 + &COpenChannel::ActionNewContext, // iState=2 + &COpenChannel::DoRememberCreatedContext, // iState=3 + &COpenChannel::ActionAddPacketFilter, // iState=4 + &COpenChannel::ActionAddSblpParameter, // iState=5 == KStateReuseOldContext! + &COpenChannel::ActionSetQoS, + &COpenChannel::ActionCommit, + &COpenChannel::DoAddFlowToContext, + &COpenChannel::ActionNegotiationComplete + }; +const TInt KStateReuseOldContext = 5; // *KEEP THIS IN SYNCH WITH ABOVE!* + + + +// Negotiate Channel Machine +const SActionStep CNegotiateChannel::iActionList[] = + { + &CNegotiateChannel::ActionAddSblpParameter, + &CNegotiateChannel::ActionSetQoS, + &CNegotiateChannel::ActionCommit, + &CNegotiateChannel::ActionNegotiationComplete, + }; + +// Join Channel Machine +const SActionStep CJoinRequest::iActionList[] = + { + &CJoinRequest::ActionRemovePacketFilter, + &CJoinRequest::ActionCommit, + &CJoinRequest::DoStartWithTargetContext, + &CJoinRequest::ActionAddPacketFilter, + &CJoinRequest::DoAddFlowToContext, + &CJoinRequest::ActionRemovePacketFilter, // Cleanup extra filters away, if present + &CJoinRequest::ActionCommit, + &CJoinRequest::ActionRequestComplete + }; + +// Leave Channel Machine +const SActionStep CLeaveRequest::iActionList[] = + { + &CLeaveRequest::ActionRemovePacketFilter, + &CLeaveRequest::ActionCommit, + &CLeaveRequest::ActionRequestComplete + }; + +// Update Channel Machine (misnamed as "Close") +const SActionStep CClose::iActionList[] = + { + &CClose::ActionRemovePacketFilter, + &CClose::ActionCommit, + &CClose::ActionRequestComplete + }; + + +#ifdef _LOG +// +// Logging help classes +// + +class TLogContextInfo : public TBuf<100> + { +public: + TLogContextInfo(const CPdpContext* aContext); + }; + +TLogContextInfo::TLogContextInfo(const CPdpContext* aContext) + { + if (aContext) + { + Format(_L("context[%u] id=%d"), (TInt)aContext, aContext->ContextId()); // + 32 + switch (aContext->ContextType()) + { + case EPrimaryContext: Append(_L(" primary")); break; + case ESecondaryContext: Append(_L(" secondary")); break; // + 10 + case ENetworkInitiatedContext: Append(_L(" network")); break; + default: Append(_L(" unknown")); break; + } + switch (aContext->ContextStatus()) + { + case RPacketContext::EStatusInactive: Append(_L(" inactive")); break; + case RPacketContext::EStatusActivating: Append(_L(" activating")); break; + case RPacketContext::EStatusActive: Append(_L(" active")); break; + case RPacketContext::EStatusDeactivating: Append(_L(" deactivating")); break; // + 12 + case RPacketContext::EStatusSuspended: Append(_L(" suspended")); break; + case RPacketContext::EStatusDeleted: Append(_L(" deleted")); break; + default: Append(_L(" unknown")); break; + } + AppendFormat(_L("(%d)"), (TInt)aContext->ContextStatus()); // + 4 + + if (aContext->ChannelId()) + { + AppendFormat(_L(" channel=%d"), aContext->ChannelId()); // + 18 + } + AppendFormat(_L(", %d flows"), aContext->RefCount()); // + 11; + } + else + { + Append(_L("context NONE")); + } + } + +#endif + + +CRequestBase::CRequestBase(CNif& aNif) : iNif(aNif) + { +#ifdef _LOG + // This is only fallback, and should be overriden by the + // derived classes! + _LIT(KLogName, "Base"); + iName = &KLogName(); +#endif + } + +CRequestBase::~CRequestBase() + { + LOG(Log::Printf(_L("~\trequest %S[%u] destructed"), iName, (TInt)this)); + } + +void CRequestBase::SetContext(CPdpContext *aContext) + /** + * Set/clear the current context for the state machine. + */ + { + LOG(TLogContextInfo info(aContext)); + LOG(Log::Printf(_L("\trequest %S[%u] -- %S set"), iName, (TInt)this, &info)); + if (iContext != aContext) + { + iContext = aContext; + // Context has been changed, need to clear modified flag. + iContextModified = EFalse; + } + iParams = NULL; // Paremeters can only come from NIF event. + } + +void CRequestBase::SetExpected(const TRequest aRequest) + { + /** + * Define the expected result of the next asynchronous operation. + */ + iExpected = aRequest; + // Assume that SetExpected is only used when a request to NIF + // has been passed. Thus, any call to SetExpected implies that + // the context will be modified by NIF. + iContextModified = ETrue; + } + + +static TBool CheckSblpErrorInPcoBuffer(const TContextParameters& aParams, TUint8& parsedSblpErrorValue) + { + TBool retValue = EFalse; + TInt ret = KErrNone; + + // create the PCO id for rejection code + RPacketContext::TPcoId sblpRejectionCodePcoId( + RPacketContext::EEtelPcktPolicyControlRejectionCode); + /* + * get the value of the RPacketContext::TContextConfigGPRS + * object from the TContextParameters object passed by the nif + */ + RPacketContext::TContextConfigGPRS configGPRS; + aParams.iContextConfig.GetContextConfig(configGPRS); + + // adjust the PCO buffer + TPtr8 pcoBufferPtr(const_cast + (configGPRS.iProtocolConfigOption.iMiscBuffer.Ptr()), + configGPRS.iProtocolConfigOption.iMiscBuffer.Length(), + configGPRS.iProtocolConfigOption.iMiscBuffer.Length()); + + // attach TTlv to the buffer + TTlvStruct + pcoTLV(pcoBufferPtr,pcoBufferPtr.Length()); + + // Retreive the sblp rejection code value from the buffer + TBuf8<253> sblpRejectionCodeBuf; + sblpRejectionCodeBuf.SetLength(pcoBufferPtr.Length()); + TPtr8 sblpRejectionCodePtr(const_cast(sblpRejectionCodeBuf.Ptr()), + sblpRejectionCodeBuf.Length(),sblpRejectionCodeBuf.MaxLength()); + + pcoTLV.ResetCursorPos(); + TRAPD(err1, ret=pcoTLV.NextItemL(sblpRejectionCodePcoId,sblpRejectionCodePtr) ); + if (err1 !=KErrNone || ret!=KErrNone) + { + return EFalse; + } + + // sblpRejectionCodeBuf[0] shall contain SBLP Rejection code ( values 1-7)) + parsedSblpErrorValue = sblpRejectionCodePtr[0]; + if(parsedSblpErrorValue >= ESblpSubErrorValueMinimum && + parsedSblpErrorValue <= ESblpSubErrorValueMaximum) + { + retValue = ETrue; + } + return retValue; + } + + +void CRequestBase::Run(const TRequest aRequest, CPdpContext* aContext, const TContextParameters& aParams) + { + LOG(const TDesC* const name(iName)); // because request can get destroyed from under us, save the name here! + LOG(TLogContextInfo info(aContext)); + LOG(Log::Printf(_L("Run\trequest %S[%u] Actions on event=%d reason=%d expected event=%d on %S"), + name, (TInt)this, (TInt)aRequest, aParams.iReasonCode, (TInt)iExpected, &info)); + + iContext = aContext; + iParams = &aParams; + + if (iExpected != aRequest && iExpected != EPendingAny) + { + CompleteAndDestruct(KErrCancel, NULL); + } + else if (aParams.iReasonCode == KErrNone) + { + // Reset to accepting any, actions must use SetExpected, + // when they activate asynchronous operation with + // a specific responce. + iExpected = EPendingAny; + do + { + ++iState; // Last state done OK, try next one. + } + while (!Action(iContext, iParams)); + // Note: there is no special terminating test, it is excepted that + // the builder of action list guarantees that it always ends with + // action which unconditionally returns ETrue. + } + else + { + // The expected request has failed. + TInt reason = aParams.iReasonCode; + + iExtension.SetUmtsType(); + + /* + * if there is KErrGprsUserAuthenticationFailure error code returned by + * the etel via nif, then we must check for the possible specific sblp + * errors in the Protocol Configuration Option PCO buffer. + * + * If the buffer has a value for the + * TPcoIDNetworkToMS::EEtelPcktPolicyControlRejectionCode id, then we can + * decide that sblp specific error has been occured if one of the the + * possible sub error codes (totally six!) matches. + */ + + if (reason == KErrGprsUserAuthenticationFailure) + { + TUint8 parsedSblpErrorValue = KErrNone; + /* + * check if PCO buffer has sblp rejection code error value + * calling CheckSblpErrorInPcoBuffer() returns true only + * if there is error in the buffer and if the error range + * is between (1-7) + */ + if (CheckSblpErrorInPcoBuffer(aParams,parsedSblpErrorValue)) + { + /* + * it is definitely a sblp error + * Set the sblp error flag + */ + iExtension.SetSblpType(); + + // figure out the sub error type + switch (parsedSblpErrorValue) + { + case 1: + // Use the sblp error code to create Failure() + reason = EGuqosSblpAuthorizationFailureOfRequest; + break; + case 2: + reason = EGuqosSblpMissingBindingInfo; + break; + case 3: + reason = EGuqosSblpInvalidBindingInfo; + break; + case 4: + reason = EGuqosSblpBindingInfoNotAllowed; + break; + case 5: + reason = EGuqosSblpAuthorizingEntityTemporarilyUnavailable; + break; + case 6: + reason = EGuqosSblpNoCorrespondingSession; + break; + case 7: + reason = EGuqosSblpInvalidBundling; + break; + default: + /* + * it will never reach here! + * because the range checking is already done in + * CheckSblpErrorInPcoBuffer(aParams,parsedSblpErrorValue) + */ + LOG(Log::Printf(_L("\trequest%S[%u] SBLP error value range fault!"), name, (TInt)this)); + break; + } + } + } + // Deliver failure to the actual request implementation. + Failure(aContext, reason); + } + LOG(Log::Printf(_L("\trequest %S[%u] Run Actions Exit"), name, (TInt)this)); + } + + +void CRequestBase::Start() + { + LOG(const TDesC* const name(iName)); // because request can get destroyed from under us, save the name here! + LOG(TLogContextInfo info(iContext)); + LOG(Log::Printf(_L("\trequest %S[%u] Start Actions with %S"), name, (TInt)this, &info)); + // Rely on C-class 0-fill. Initially all state variables + // are zero, e.g. + // iContext = NULL; + // iParams = NULL; + // iExpected = EPendingAny; + // iState = 0 + // This start does not touch those values and allows derived + // class to override this function with something that may initialize + // state, before calling the base implementation of the Start. + + // Excecute actions until something catches or request terminates. + while (!Action(iContext, iParams)) + { + ++iState; + } + // Note: there is no special terminating test, it is excepted that + // the builder of action list guarantees that it always ends with + // action which unconditionally returns ETrue. + LOG(Log::Printf(_L("\trequest %S[%u] Start Actions Exit"), name, (TInt)this)); + } + +void CRequestBase::CompleteAndDestruct(TInt aErrorCode, const TQoSParameters* aParams, const TExtensionData& aExtension) + { + LOG(Log::Printf(_L("\trequest %S[%u] CompleteAndDestruct ErrorCode=%d"), iName, (TInt)this, aErrorCode)); + // Remove all references to this request... + iNif.CloseRequest(this); + // ...before delivering the completion. The delivery may call + // back, and this request must be totally removed by then, or + // bad things can happen (like, duplicate delete). + if (iNotify) + iNotify->RequestComplete(aErrorCode, aParams, aExtension); + delete this; + } + + +TBool CRequestBase::IsOk(TInt aResult, CPdpContext *aContext) + { + if (aResult >= 0) + return ETrue; + LOG(TLogContextInfo info(aContext)); + LOG(Log::Printf(_L("\trequest %S[%u] IsOk(%d) is not OK %S"), iName, (TInt)this, aResult, &info)); + Failure(aContext, aResult); + return EFalse; + } + +TBool CRequestBase::ActionRemovePacketFilter(CPdpContext* aContext, const TContextParameters*) + /** + * Activate leaving flow from a context. + */ + { + LOG(TLogContextInfo info(aContext)); + LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionRemovePacketFilter from %S"), iName, (TInt)this, iState, &info)); + if (aContext) + { + // This branch is needed for the primary too, but only in rare case + // where a secondary is being changed into a primary. + if (iFlow) + { + // Move the flow to default context. If remove + // fails, it is higly likely that this flow was + // not included in TFT. + iFlow->SetContext(iNif.DefaultPdpContext()); + } + if (aContext->RefCount() > 0 || aContext->IsPrimary()) + { + // Context has remaining flows or is a Primary, collect unused filters. + // (in case of primary, all filters will be unused, if any present). + TTFTInfo tft; + TInt ret = aContext->RemovePacketFilter(tft, iFlow); + if (ret > 0) + { + LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionRemovePacketFilter -- removing %d filter(s)"), iName, (TInt)this, iState, ret)); + SetExpected(EPendingPacketFilterRemove); + (void)IsOk(aContext->ModifyTft(KRemoveFilters, tft), aContext); + return ETrue; + } + else if (ret < 0) + { + LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionRemovePacketFilter -- TFT construct failed with %d"), iName, (TInt)this, iState, ret)); + CompleteAndDestruct(ret, NULL); + return ETrue; + } + } + else + { + // All flows have been removed from the context. In the current implementation + // the context has been scheduled for destruction, and there is no need for + // removing any existing TFT... + LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionRemovePacketFilter -- No flows left"), iName, (TInt)this, iState)); + } + } + // No TFT changes need to be done, + LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionRemovePacketFilter -- no filters to remove"), iName, (TInt)this, iState)); + return EFalse; + } + + +TBool CRequestBase::ActionAddPacketFilter(CPdpContext* aContext, const TContextParameters* /*aParams*/) + { + LOG(TLogContextInfo info(aContext)); + LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionAddPacketFilter on %S"), iName, (TInt)this, iState, &info)); + if (aContext && iFlow) + { + TTFTInfo tft; + TInt err = aContext->AddPacketFilter(*iFlow, tft); + if (err < 0) + { + LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionAddPacketFilter -- TFT construct failed with %d"), iName, (TInt)this, iState, err)); + Failure(aContext, err); + return ETrue; + } + else if (err > 0) + { + LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionAddPacketFilter -- adding %d filter(s)"), iName, (TInt)this, iState, err)); + SetExpected(EPendingPacketFilterAdd); + (void)IsOk(aContext->ModifyTft(KAddFilters, tft), aContext); + return ETrue; + } + // Filter does not need modification, start some other operation... + } + LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionAddPacketFilter -- no filters added"), iName, (TInt)this, iState)); + return EFalse; + } + +TBool CRequestBase::ActionCommit(CPdpContext* aContext, const TContextParameters* /*aParams*/) + /** + * Activate changes made to a context. + * + * This action can be run after a sequence of context modifying + * actions (filter, QoS, etc.). Depending on the state of the + * context, this calls either ModifyActive or Activate. + */ + { + if (aContext) + { + LOG(TLogContextInfo info(aContext)); + + if (!aContext->ContextActive()) + { + LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionCommit -- start Activate %S"), iName, (TInt)this, iState, &info)); + SetExpected(EPendingActivate); + (void)IsOk(aContext->Activate(), aContext); + } + else if (iContextModified) + { + LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionCommit -- start ModifyActive %S"), iName, (TInt)this, iState, &info)); + SetExpected(EPendingModifyActive); + (void)IsOk(aContext->ModifyActive(), aContext); + } + else + { + // For example all flows go into same tunnel and filter is same for everyone. + // A flow leaving context does not affect the filter. + LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionCommit -- skip ModifyActive, not modified %S"), iName, (TInt)this, iState, &info)); + return EFalse; + } + return ETrue; + } + LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionCommit -- nothing to do, no context"), iName, (TInt)this, iState)); + return EFalse; + } + + +TBool CRequestBase::ActionRequestComplete(CPdpContext* /*aContext*/, const TContextParameters* /*aParams*/) + { + /** + * Default termination of the request. + * + * This action can be used as a default terminator of the request, + */ + LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionRequestComplete"), iName, (TInt)this, iState)); + CompleteAndDestruct(KErrNone, NULL); + return ETrue; + } + +TBool CRequestBase::DoAddFlowToContext(CPdpContext* aContext, const TContextParameters*) + /** + * Set add current flow to current context. + * + * Add current flow to current context internally (e.g. add CFlowData object to + * CPdpContext object). + */ + { + LOG(TLogContextInfo info(aContext)); + if (iFlow && aContext) + { + LOG(Log::Printf(_L("\trequest %S[%u] %2d.DoAddFlowToContext to %S"), iName, (TInt)this, iState, &info)); + iFlow->SetContext(aContext); + } + else + { + LOG(Log::Printf(_L("\trequest %S[%u] %2d.DoAddFlowToContext to %S [not done]"), iName, (TInt)this, iState, &info)); + } + // This allows the use ActionRemovePacketFilter to be used after this + // to clean out unnecessary filters. This is required in Join, because + // when the last flow leaves, the filters are not updated (cannot be + // removed because PDP Context cannot exist without filters, and just + // deleting the context would be too drastic). Thus, when the same flow + // or new flow joins back to existing context, we need to check and + // clean out stale filters. + iFlow = NULL; + return EFalse; + } + +void CRequestBase::Cancel(CFlowData* aFlowData) + /** + * Default cancel based on flow. + * + * If the only CFlowData pointer in request is stored in iFlow, + * then this default Cancel should be enough for most cases. + */ + { + if (iFlow == aFlowData) + { + LOG(Log::Printf(_L("\trequest %S[%u] Cancel due flow[%u] -- only detach the flow"), iName, (TInt)this, (TInt)iFlow)); + // A running request is hard to cancel, because there is no way + // to tell NIF about it. Thus, when flow is cancelled, just detach + // it from the request and let the state machine run to completion + // without the flow (the machine should adapt!) + iFlow = NULL; + } + } + +void CRequestBase::Failure(CPdpContext* aContext, TInt aErrorCode) + /** + * The default Failure handler. + * + * Load the error code into iExtension and destruct. + */ + { + LOG(TLogContextInfo info(aContext)); + (void)aContext; // silence warning in MARM release compile. + TInt ret = iExtension.SetErrorCode(aErrorCode); + LOG(Log::Printf(_L("\trequest %S[%u] Failure %S errorcode=%d ret=%d"), iName, (TInt)this, &info, aErrorCode, ret)); + CompleteAndDestruct(ret == KErrNone ? aErrorCode : ret, NULL); + } + +// CNegotiationBase +CNegotiationBase::CNegotiationBase(CNif& aNif) : CRequestBase(aNif) + { +#ifdef _LOG + // This is only fallback, and should be ovvrriden by the + // derived classes! + _LIT(KLogName, "Negotiation"); + iName = &KLogName(); +#endif + } + +void CNegotiationBase::SetParameters(const TQoSParameters& aParams, CExtensionPolicy& aPolicy) + { + LOG(Log::Printf(_L("\trequest %S[%u] SetParamaters"), iName, (TInt)this)); + iGeneric = aParams; + iUmts.ParsePolicyData(&aPolicy); + } + +void CNegotiationBase::SetParametersFlowExtn(CExtensionPolicy &aPolicy) + { + // ParsePolicyData will return true if SBLP presents + if (iFlowExtnParams.ParsePolicyDataForSblp(&aPolicy)) + { + // SBLP presents + // so, set the Sblp flag for the channel + iSblp = ETrue; + LOG(Log::Printf(_L("\trequest %S[%u] SetParametersFlowExtn -- SBLP"), iName, (TInt)this)); + } + } + +// CNegotiationBase +TBool CNegotiationBase::ActionAddSblpParameter(CPdpContext *aContext, const TContextParameters* /*aParams*/) + { + /* + * if SBLP is supported, sblp parameter is added after setting the + * Qos parameters + * + * once sblp parameter is added, the operations continue in the same + * way as it was + */ + if(aContext && iSblp) // the negotiations requests sblp context + { + // call modifytft to add sblp + LOG(TLogContextInfo info(aContext)); + TTFTInfo tft; + if (IsOk(tft.AddSblpToken(iFlowExtnParams.iAuthorizationToken, iFlowExtnParams.iFlowIds), aContext)) + { + LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionAddSblpParameter -- Adding SBLP for %S"), iName, (TInt)this, iState, &info)); + SetExpected(EPendingSblpParameterAdd); + (void)IsOk(aContext->ModifyTft(KAddSblpParameter, tft), aContext); + } + else + { + LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionAddSblpParameter -- Failed constructing TFT for SBLP for %S"), + iName, (TInt)this, iState, &info)); + } + return ETrue; + } + LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionAddSblpParameter -- no SBLP"), iName, (TInt)this, iState)); + return EFalse; + } + +TBool CNegotiationBase::ActionSetQoS(CPdpContext *aContext, const TContextParameters* /*aParams*/) + { + if (aContext) + { + LOG(TLogContextInfo info(aContext)); + LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionSetQoS -- request %S"), iName, (TInt)this, iState, &info)); + SetExpected(EPendingSetQoS); + (void)IsOk(aContext->SetQoS(iGeneric, iUmts), aContext); + return ETrue; + } + LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionSetQoS -- skipping"), iName, (TInt)this, iState)); + return EFalse; + } + + +TBool CNegotiationBase::ActionNegotiationComplete(CPdpContext *aContext, const TContextParameters* aParams) + { + LOG(TLogContextInfo info(aContext)); + LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionNegotiationComplete %S"), iName, (TInt)this, iState, &info)); + if (aParams) + { + // Return results of the negotiation to upper layers. + TInt ret = iExtension.CreateExtension(aParams->iContextConfig, aParams->iReasonCode); + if (ret != KErrNone) + { + LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionNegotiationComplete -- CreateExtension fail=%d"), iName, (TInt)this, iState, ret)); + // Ugh.. can't construct the return value (probably out of memory) + // Try plain error instead (if that does not work, then nothing can + // be done about it...) + (void)iExtension.SetErrorCode(ret); + } + } + + if (iFlow && aContext) + { + // If there is assocated flow, assume it will need to be moved + // to the current context (nothing happens, if this is already + // true. + iFlow->SetContext(aContext); + } + + CompleteAndDestruct(KErrNone, &iGeneric, iExtension); + return ETrue; + } + +void CNegotiationBase::Failure(CPdpContext* /*aPdpContext*/, TInt aErrorCode) + { + // If allocation space for extn fails, there not much + // that can be done, the request must be completed anyway + // with empty extn. + LOG(Log::Printf(_L("\trequest %S[%u] Failure code=%d"), iName, (TInt)this, aErrorCode)); + (void)iExtension.SetErrorCode(aErrorCode); + CompleteAndDestruct(aErrorCode, &iGeneric, iExtension); + } + + +// CClose + +CClose* CClose::New(CPdpContext& aContext) + { + return new CClose(aContext); + } + +CClose::CClose(CPdpContext& aContext) : CRequestBase(aContext.Nif()), iClosing(aContext) + { +#ifdef _LOG + _LIT(KLogName, "Close"); + iName = &KLogName(); +#endif + LOG(Log::Printf(_L("new\trequest %S[%u] size=%d"), iName, (TInt)this, sizeof(*this))); + iNotify = NULL; + } + +void CClose::Start() + { + LOG(TLogContextInfo info(&iClosing)); + LOG(Log::Printf(_L("Start\trequest %S[%u] %S"), iName, (TInt)this, &info)); + // Give the context to the state machine. + SetContext(&iClosing); + // Note: iFlow is NULL. This means that the packet + // filter is just recomputed based on currenly + // joined flows. + CRequestBase::Start(); + } + +CClose::~CClose() + { + } + +void CClose::Cancel(CPdpContext* aContext) + { + if (&iClosing == aContext) + { + LOG(TLogContextInfo info(aContext)); + LOG(Log::Printf(_L("Cancel\trequest %S[%u] for %S"), iName, (TInt)this, &info)); + Failure(aContext, KErrDied); + } + } + + +CDeleteRequest* CDeleteRequest::NewL(CPdpContext *aContext) + { + return new (ELeave) CDeleteRequest(aContext); + } + +CDeleteRequest::CDeleteRequest(CPdpContext* aContext) : CRequestBase(aContext->Nif()), iDelete(aContext) + { +#ifdef _LOG + _LIT(KLogName, "Delete"); + iName = &KLogName(); +#endif + LOG(Log::Printf(_L("new\trequest %S[%u] size=%d"), iName, (TInt)this, sizeof(*this))); + iNotify = NULL; + } + +void CDeleteRequest::Start() + { + LOG(TLogContextInfo info(iDelete)); + LOG(Log::Printf(_L("Start\trequest %S[%u] %S"), iName, (TInt)this, &info)); + // Issue a context delete for this context to NIF + if (iDelete) + { + CPdpContext* context = iDelete; + iDelete = NULL; // Prevent Cancel() from triggering... + context->Delete(); // Send delete request to NIF + context->Nif().DeletePdpContext(context); // Destroys the object (.. this calls my Cancel!) + } + CompleteAndDestruct(KErrNone, NULL); + } + +void CDeleteRequest::Cancel(CPdpContext* aContext) + { + if (aContext == iDelete) + { + LOG(TLogContextInfo info(aContext)); + LOG(Log::Printf(_L("Cancel\trequest %S[%u] for %S"), iName, (TInt)this, &info)); + Failure(aContext, KErrDied); + } + } + + +// COpenChannel + +COpenChannel* COpenChannel::New(TUint aChannelId, CFlowData &aFlow, MQoSNegotiateEvent* aNotify) + { + return new COpenChannel(aChannelId, aFlow, aNotify); + } + +COpenChannel::COpenChannel(TInt aChannelId, CFlowData& aFlow, MQoSNegotiateEvent* aNotify) : + CNegotiationBase(aFlow.Nif()), + iChannelId(aChannelId) + { +#ifdef _LOG + _LIT(KLogName, "Open"); + iName = &KLogName(); +#endif + LOG(Log::Printf(_L("new\trequest %S[%u] size=%d"), iName, (TInt)this, sizeof(*this))); + iNotify = aNotify; + iFlow = &aFlow; + } + +COpenChannel::~COpenChannel() + { + } + +TBool COpenChannel::ActionNewContext(CPdpContext */*aContext*/, const TContextParameters* /*aParams*/) + { + LOG(Log::Printf(_L("\trequest %S[%u] %2d.ActionNewContext"), iName, (TInt)this, iState)); + SetExpected(EPendingCreate); + (void)IsOk(iNif.NewPdpContext(), NULL); + return ETrue; + } + +TBool COpenChannel::DoRememberCreatedContext(CPdpContext* aContext, const TContextParameters*) + { + iNewContext = aContext; + if (aContext) + { + // ..and bind it to the channel id. + aContext->SetChannelId(iChannelId); + LOG(TLogContextInfo info(aContext)); + LOG(Log::Printf(_L("\trequest %S[%u] %2d.DoRememberCreatedContext -- %S"), iName, (TInt)this, iState, &info)); + } + else + { + LOG(Log::Printf(_L("\trequest %S[%u] %2d.DoRememberCreatedContext -- No context created for channel=%d"), + iName, (TInt)this, iState, iChannelId)); + } + return EFalse; + } + +void COpenChannel::Start() + { + LOG(Log::Printf(_L("Start\trequest %S[%u] -- COpenChannel Begin"), iName, (TInt)this)); + if (!iFlow) + { + LOG(Log::Printf(_L("\trequest %S[%u] Flow has been cancelled"), iName, (TInt)this)); + CompleteAndDestruct(KErrNone, NULL); + return; + } + + // First check if currently used Pdp context can be modified!! + CPdpContext* context = iFlow->PdpContext(); + SetContext(context); + if (context && context != iNif.DefaultPdpContext()) + { + if (context->RefCount() == 1) + { + LOG(TLogContextInfo info(context)); + LOG(Log::Printf(_L("\trequest %S[%u] -- reuse existsing %S"), iName, (TInt)this, &info)); + // Start state machine at different point. + iState = KStateReuseOldContext; + } + } + // If not reusing old, the machine starts by trying + // to remove the TFT from old context, if any... + CRequestBase::Start(); + } + + +void COpenChannel::Failure(CPdpContext* aPdpContext, TInt aErrorCode) + { + LOG(Log::Printf(_L("\trequest %S[%u] Failure code=%d"), iName, (TInt)this, aErrorCode)); + + if (aPdpContext && aPdpContext == iNewContext) + { + iNewContext = NULL; + aPdpContext->Delete(); + CNif& nif = aPdpContext->Nif(); + nif.DeletePdpContext(aPdpContext); + } + CNegotiationBase::Failure(aPdpContext, aErrorCode); + } + +void COpenChannel::Cancel(CPdpContext* aContext) + { + if (aContext == iNewContext) + { + // Prevent Failure from deleting the context (the caller of Cancel is + // just doing that). + iNewContext = NULL; + LOG(TLogContextInfo info(aContext)); + LOG(Log::Printf(_L("Cancel\trequest %S[%u] Cancelled for "), iName, (TInt)this, &info)); + Failure(aContext, KErrDied); + } + } + + +// CNegotiateChannel + +CNegotiateChannel* CNegotiateChannel::New(CPdpContext* aContext, MQoSNegotiateEvent* aNotify) + { + return new CNegotiateChannel(aContext, aNotify); + } + +CNegotiateChannel::CNegotiateChannel(CPdpContext *aContext, MQoSNegotiateEvent* aNotify) : + CNegotiationBase(aContext->Nif()) + { +#ifdef _LOG + _LIT(KLogName, "Negotiate"); + iName = &KLogName(); +#endif + LOG(Log::Printf(_L("new\trequest %S[%u] size=%d"), iName, (TInt)this, sizeof(*this))); + iNotify = aNotify; + iChannel = aContext; + } + +CNegotiateChannel::~CNegotiateChannel() + { + } + + +void CNegotiateChannel::Start() + { + LOG(Log::Printf(_L("Start\trequest %S[%u] -- CNegotiateChannel Begin"), iName, (TInt)this)); + SetContext(iChannel); + CRequestBase::Start(); + } + + +void CNegotiateChannel::Cancel(CPdpContext* aContext) + { + if (iChannel == aContext) + { + LOG(TLogContextInfo info(aContext)); + LOG(Log::Printf(_L("Cancel\trequest %S[%u] Cancelled for %S"), iName, (TInt)this, &info)); + iChannel = NULL; + + //??Where does this go? + Failure(aContext, KErrDied); + } + } + + + +// CJoinRequest +CJoinRequest* CJoinRequest::New(CPdpContext* aContext, CFlowData* aFlowData, MQoSNegotiateEvent* aNotify) + { + return new CJoinRequest(aContext, aFlowData, aNotify); + } + +CJoinRequest::CJoinRequest(CPdpContext* aContext, CFlowData* aFlowData, MQoSNegotiateEvent* aNotify) : + CRequestBase(aFlowData->Nif()) + { +#ifdef _LOG + _LIT(KLogName, "Join"); + iName = &KLogName(); +#endif + LOG(Log::Printf(_L("new\trequest %S[%u] size=%d"), iName, (TInt)this, sizeof(*this))); + iNotify = aNotify; + iChannel = aContext; + iFlow = aFlowData; + } + +CJoinRequest::~CJoinRequest() + { + } + +void CJoinRequest::Start() + { + LOG(Log::Printf(_L("Start\trequest %S[%u] -- CJoinRequest Begin"), iName, (TInt)this)); + if (!iFlow) + { + LOG(Log::Printf(_L("\trequest %S[%u] Flow has been cancelled"), iName, (TInt)this)); + CompleteAndDestruct(KErrNone, NULL); + return; + } + CPdpContext* context = iFlow->PdpContext(); + LOG(TLogContextInfo info(context)); + if (context == iChannel) + { + // Already joined to the target context + LOG(Log::Printf(_L("\trequest %S[%u] already joined to %S"), iName, (TInt)this, &info)); + CompleteAndDestruct(KErrNone, NULL, iExtension); + return; + } + // Start with removal of the TFT from old context. + SetContext(context); + CRequestBase::Start(); + } + + +TBool CJoinRequest::DoStartWithTargetContext(CPdpContext */*aContext*/, const TContextParameters* /*aParams*/) + { + LOG(TLogContextInfo info(iChannel)); + LOG(Log::Printf(_L("\trequest %S[%u] %2d.DoStartWithTargetContext -- target %S"), iName, (TInt)this, iState, &info)); + SetContext(iChannel); + return EFalse; + } + + +void CJoinRequest::Failure(CPdpContext* /*aPdpContext*/, TInt aErrorCode) + { + LOG(Log::Printf(_L("\trequest %S[%u] Failure code=%d"), iName, (TInt)this, aErrorCode)); + iExtension.SetErrorCode(aErrorCode); + CompleteAndDestruct(EQoSJoinFailure, NULL, iExtension); + } + +void CJoinRequest::Cancel(CPdpContext* aContext) + { + if (iChannel == aContext) + { + LOG(TLogContextInfo info(aContext)); + LOG(Log::Printf(_L("Cancel\trequest %S[%u] Cancelled for %S"), iName, (TInt)this, &info)); + Failure(aContext, KErrDied); + } + } + +// CLeaveRequest +CLeaveRequest* CLeaveRequest::New(CPdpContext* aContext, CFlowData* aFlowData, MQoSNegotiateEvent* aNotify) + { + return new CLeaveRequest(aContext, aFlowData, aNotify); + } + +CLeaveRequest::CLeaveRequest(CPdpContext* aContext, CFlowData* aFlowData, MQoSNegotiateEvent* aNotify) : + CRequestBase(aContext->Nif()) + { +#ifdef _LOG + _LIT(KLogName, "Leave"); + iName = &KLogName(); +#endif + LOG(Log::Printf(_L("new\trequest %S[%u] size=%d"), iName, (TInt)this, sizeof(*this))); + iNotify = aNotify; + iChannel = aContext; + iFlow = aFlowData; + //?? Why channel? it should be same as flow currently joined? + //?? Or just use channel and recompute, leave == close? + } + +void CLeaveRequest::Start() + { + LOG(Log::Printf(_L("Start\trequest %S[%u] -- CLeaveRequest Begin"), iName, (TInt)this)); + // Start with removal of the TFT from old context. + // The flow has nothing to do with this anymore? + SetContext(iChannel); + CRequestBase::Start(); + } + +CLeaveRequest::~CLeaveRequest() + { + LOG(Log::Printf(_L("CLeaveRequest::~CLeaveRequest()"))); + } + + +void CLeaveRequest::Failure(CPdpContext* /*aPdpContext*/, TInt aErrorCode) + { + LOG(Log::Printf(_L("\trequest %S[%u] Failure code=%d"), iName, (TInt)this, aErrorCode)); + iExtension.SetErrorCode(aErrorCode); + CompleteAndDestruct(EQoSLeaveFailure, NULL, iExtension); + } + +void CLeaveRequest::Cancel(CPdpContext* aContext) + { + if (iChannel == aContext) + { + LOG(TLogContextInfo info(aContext)); + LOG(Log::Printf(_L("Cancel\trequest %S[%u] Cancelled for %S"), iName, (TInt)this, &info)); + Failure(aContext, KErrDied); + } + }