networkprotocolmodules/suplprotocolmodule/SuplProtocol/src/suplmtlrfsmsession.cpp
changeset 36 b47902b73a93
parent 0 9cfd9a3ee49c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/networkprotocolmodules/suplprotocolmodule/SuplProtocol/src/suplmtlrfsmsession.cpp	Fri Jun 04 10:34:15 2010 +0100
@@ -0,0 +1,794 @@
+// Copyright (c) 2008-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:
+// This file provides the implementation of the class for
+// the MT-LR protocol state machine.
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+ @deprecated
+*/
+
+#include "suplmtlrfsmsession.h"
+#include "suplmtlrstatehandler.h"
+#include "suplrrlpstatemachine.h"
+#include "suplend.h"
+#include "suplinit.h"
+#include "supldevloggermacros.h"
+#include "suplgatewayinterface.h"
+
+
+/** KMaxQueueEntry
+Maximum number of messages waiting to be processed
+in the state machine event store.
+*/
+const TInt KMaxQueueEntry = 5;
+
+
+/** Static constructor.
+@param aObserver Reference to state machine observer.
+@return A new instance of the CSuplMtlrFsmSession class
+*/
+CSuplMtlrFsmSession* CSuplMtlrFsmSession::NewL(MSuplFsmSessionObserver& aObserver)
+	{
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::NewL() Begin\n");
+	CSuplMtlrFsmSession* self = new (ELeave) CSuplMtlrFsmSession(aObserver);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::NewL() End\n");
+	return self;
+	}
+
+/** Standard constructor.
+@param aObserver Reference to state machine observer.
+*/  
+CSuplMtlrFsmSession::CSuplMtlrFsmSession(MSuplFsmSessionObserver& aObserver)
+:CSuplFsmSessionBase(aObserver)
+	{ 
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::CSuplMtlrFsmSession() Begin\n");
+	iLocReqType = MLbsNetworkProtocolObserver::EServiceMobileTerminated;
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::CSuplMtlrFsmSession() End\n");
+	}
+
+
+/** Standard destructor.
+*/ 
+CSuplMtlrFsmSession::~CSuplMtlrFsmSession()
+	{
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::~CSuplMtlrFsmSession() Begin\n");
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::~CSuplMtlrFsmSession() End\n");
+	}
+
+/** Private second-stage constructor.
+*/  
+void CSuplMtlrFsmSession::ConstructL()
+	{
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::ConstructL() Begin\n");
+	CActiveScheduler::Add(this);
+
+	iEventStore = CSuplFsmEventStore::NewL(KMaxQueueEntry);
+
+	// Create state handler
+	iStateHandler = CSuplMtLrStateHandler::NewL(*this);
+
+	// Open up assistance data builder
+	iAssistanceDataBuilderSet.OpenL();
+
+	// Create a Positioning Protocol State Machine
+	iPositioningProtocol = CSuplRrlpFsm::NewL(*this,iAssistanceDataBuilderSet);
+	
+	// Create timers used during MTLR protocol procedure
+	iSuplProtTimer = CLbsCallbackTimer::NewL(*this);
+	
+	iSlpSettingsStore = CLbsHostSettingsStore::NewL(KLbsHostSettingsSuplStoreId);
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::ConstructL() End\n");
+	}
+
+/** GetHostId()
+This method returns the ID of an entry in the HostSettings store
+containing the address of the host (SLP) to connect to.
+For MTLR, and in accordance with the SUPL specifications, only
+a host that has been provisioned by the home network will be used.
+This method retrieves the network-provisioned host that has last
+been modified.
+@param aHostId the ID of the host selected for the MTLR
+@return KErrNone if a valid host ID has been found
+*/
+TInt CSuplMtlrFsmSession::GetHostId(TLbsHostSettingsId& aHostId)
+	{
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::GetHostId() Begin\n");
+	TInt err = KErrNotFound;
+	TBool hostFound = EFalse;
+	if (iSlpSettingsStore)
+		{
+		TLbsHostSettingsSupl slpSettings;
+		TLbsHostSettingsId 	settingsId;
+
+		// Get the network-provisioned SLP that has been 
+		// modified most recently
+		TTime mostRecent = 0;
+		err = iSlpSettingsStore->RewindHostSettings();
+		if (KErrNone == err)
+			{
+			while (KErrNone == err)
+				{
+				err = iSlpSettingsStore->GetNextHostSettingsByCreator(KLbsHostSettingsDevProvCreatorId, slpSettings, settingsId);		
+				if (KErrNone == err)
+					{
+					if (mostRecent < slpSettings.LastModified())
+						{
+						mostRecent = slpSettings.LastModified();
+						aHostId = settingsId;
+						hostFound = ETrue;
+						}
+					}
+				}
+			}			
+		}	
+
+	if(!hostFound)
+		{
+		SUPLLOG(ELogP1, "CSuplMtlrFsmSession::GetHostId(), GenerateHostId() End\n");
+		return GenerateHostId(aHostId);
+		}
+
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::GetHostId() End\n");
+	// If we did not return earlier, we must have found a valid ID
+	return KErrNone;
+	}
+
+
+/** Initialise internal state attributes.
+This is used when new MTLR procedure commences.
+*/
+void CSuplMtlrFsmSession::InitialiseProcedure()
+	{
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::InitialiseProcedure() Begin\n");
+	// Initialise state machine
+	InitialiseMachineBase();	
+	iCurrentState = EStateProcedureNull;
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::InitialiseProcedure() End\n");
+	}
+	
+
+/** State transition.
+This method determines the next state to be adopted by the state machine.
+@return TBool ETrue if the state has changed.
+@param aForceRedo, indicates that the states entry action must be re-performed when there has been no change in state
+*/
+TBool CSuplMtlrFsmSession::SelectNextState(TBool& aForceRedo)
+	{
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::SelectNextState() Begin\n");
+	TBool stateChanged = ETrue;
+	aForceRedo = EFalse;
+	// Regardless of current state, check first if an event has occurred
+	// that implies cancelling the machine (terminate session)
+	if (IsCancelPending())
+		{
+		SetMachineAsCancelling();
+		iCurrentState = (IsSessionConnected() && iSessionInProgress)? EStateSuplSessionEnded : EStatePosSessionEnded;
+		}
+	else
+		{
+		// Set new state	
+		switch (iCurrentState)
+			{
+		case EStateProcedureNull:
+			SUPLLOG(ELogP1, "CSuplMtlrFsmSession::SelectNextState() Entry state: EStateProcedureNull\n");
+			iCurrentState = EStateSuplInitReceived;
+			SUPLLOG(ELogP1, "CSuplMolrFsmSession::SelectNextState() Nex state: EStateSuplInitReceived\n");
+			SetSessionInProgress(ETrue);
+			break;
+			
+		case EStateSuplInitReceived:
+			SUPLLOG(ELogP1, "CSuplMtlrFsmSession::SelectNextState() Entry state: EStateSuplInitReceived\n");
+			stateChanged = DetermineStateFromInitReceived();
+			break;
+
+		case EStateNetConnectionStarted:
+			SUPLLOG(ELogP1, "CSuplMtlrFsmSession::SelectNextState() Entry state: EStateNetConnectionStarted\n");
+			stateChanged = DetermineStateFromConnectionStarted(aForceRedo);
+			break;
+	
+		case EStatePosInitSent:
+			SUPLLOG(ELogP1, "CSuplMtlrFsmSession::SelectNextState() Entry state: EStatePosInitSent\n");
+			stateChanged = DetermineStateFromPosInitSent();
+			break;
+
+		case EStatePositioningInProgress:
+			SUPLLOG(ELogP1, "CSuplMtlrFsmSession::SelectNextState() Entry state: EStatePositioningInProgress\n");
+			stateChanged = DetermineStateFromPositioningInProgress(aForceRedo);
+			break;
+
+		case EStatePositionReceived:
+			SUPLLOG(ELogP1, "CSuplMtlrFsmSession::SelectNextState() Entry state: EStatePositionReceived\n");
+			iCurrentState = EStatePosSessionEnded;
+			SUPLLOG(ELogP1, "CSuplMolrFsmSession::SelectNextState() Nex state: EStatePosSessionEnded\n");
+			SetMachineAsNotCancellable();
+			break;
+			
+		case EStateSuplSessionEnded:
+			SUPLLOG(ELogP1, "CSuplMtlrFsmSession::SelectNextState() Entry state: EStateSuplSessionEnded\n");
+			iCurrentState = EStatePosSessionEnded;
+			SUPLLOG(ELogP1, "CSuplMolrFsmSession::SelectNextState() Nex state: EStateSuplSessionEnded\n");
+			break;
+
+		case EStatePosSessionEnded:
+			SUPLLOG(ELogP1, "CSuplMtlrFsmSession::SelectNextState() Entry state: EStatePosSessionEnded\n");
+			iCurrentState = EStateLbsSessionEnded;
+			SUPLLOG(ELogP1, "CSuplMolrFsmSession::SelectNextState() Nex state: EStateLbsSessionEnded\n");
+			break;
+			
+		case EStateLbsSessionEnded:
+			SUPLLOG(ELogP1, "CSuplMtlrFsmSession::SelectNextState() Entry state: EStateLbsSessionEnded\n");
+			iCurrentState = EStateNetConnectionClosed;
+			SUPLLOG(ELogP1, "CSuplMolrFsmSession::SelectNextState() Nex state: EStateNetConnectionClosed\n");
+			break;
+			
+		case EStateNetConnectionClosed:
+			SUPLLOG(ELogP1, "CSuplMtlrFsmSession::SelectNextState() Entry state: EStateNetConnectionClosed\n");
+			// Procedure has completed
+			iCurrentState = EStateProcedureNull;
+			SUPLLOG(ELogP1, "CSuplMolrFsmSession::SelectNextState() Nex state: EStateProcedureNull\n");
+			break;
+			
+		default:
+			SUPLLOG(ELogP3, "CSuplMtlrFsmSession::SelectNextState() unknown entry state\n");
+			ASSERT(EFalse);
+			break;
+			};
+		}
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::SelectNextState() End\n");
+	return stateChanged;
+	}
+	
+
+/** Complete the procedure.
+*/  
+void CSuplMtlrFsmSession::CompleteProcedure()
+	{
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::CompleteProcedure() Begin\n");
+	// Complete state machine
+	CompleteMachineBase();
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::CompleteProcedure() End\n");
+	}
+	
+/** Complete a state transition.
+This is called by the base class when a state transition has
+concluded and it provides an opportunity for the state machine 
+to perform actions required immediately after this transition.
+
+The method can also initiate a further change of state. This is
+relevant when the state machine is required to perform an autonomous
+transition from one state to another e.g. this occurs when several
+interactions are required arising from a single external trigger.
+*/
+void CSuplMtlrFsmSession::PostTransition()
+	{
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::PostTransition() Begin\n");
+	// Some states are transitory i.e. they require
+	// an automatic transition to the next state
+	if (IsCancelPending() ||
+		EStatePositionReceived		== iCurrentState ||
+	 	EStateSuplSessionEnded		== iCurrentState ||
+	 	EStatePosSessionEnded		== iCurrentState ||
+	 	EStateLbsSessionEnded		== iCurrentState ||
+	 	EStateNetConnectionClosed	== iCurrentState)
+		{
+		// Perform a state transition
+		PerformTransition();
+		}
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::PostTransition() End\n");
+	}
+
+
+/** Cancel the active procedure
+*/  
+void CSuplMtlrFsmSession::CancelProcedure()
+	{
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::CancelProcedure() Begin\n");
+	// Kill all timers
+	iSuplProtTimer->Cancel();
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::CancelProcedure() End\n");
+	}
+
+
+/** Timer expired callback.
+This is called by a CStateTimer object when the timer
+has expired - the event is identified by aEvent parameter.
+@param aTimerId The timer event identifier.
+*/
+void CSuplMtlrFsmSession::OnTimerEventL(TInt aTimerId)
+	{
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::OnTimerEventL() Begin\n");
+	// Perform relevant action for the expired timer
+	switch (aTimerId)
+		{
+		
+	// Connection result timer
+	case KSessionConnectedTimerEvent:
+		CancelMachine(ECancelNetwork,EReasonTimerExpiry);
+		break;
+
+	// SUPL POS timer
+	case KSuplPosTimerEvent:
+		CancelMachine(ECancelSuplProt,EReasonTimerExpiry);
+		break;
+
+	case KSuplEndTimerEvent:
+		CancelMachine(ECancelSuplProt,EReasonTimerExpiry);
+		break;
+
+	// Ignore unknown timer events
+	default:
+		break;
+		};
+
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::OnTimerEventL() End\n");
+	}
+
+
+/** This method stores the parameters received in a SUPL INIT message.
+If any incorrect or unsupported parameter is detected the method returns leaves. 
+*/
+void CSuplMtlrFsmSession::ProcessExternalLocationRequestL(const CSuplInit* aSuplInit)
+	{
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::StoreExternalLocationRequestL() Begin\n");
+	TLbsHostSettingsId hostId;
+	TLbsHostSettingsSupl slpSettings;
+	TLbsHostNameAddress hostNameAddress;
+	
+	// aSuplInit is constant (read-only) but
+	// access to non-constant methods is needed
+	CSuplInit* suplInitPtr = const_cast<CSuplInit*> (aSuplInit);
+	
+	// Store the Session ID
+	CSuplSessionId* sessionId = CSuplSessionId::NewL();
+	
+
+	CleanupStack::PushL(sessionId);
+	User::LeaveIfError(suplInitPtr->GetSessionId(*sessionId));
+	
+	// SLP session ID must be present
+	// SET session ID must not be present
+	if (sessionId->iSetSessionIdPresent ||
+		! sessionId->iSlpSessionIdPresent)
+		{
+		User::Leave(KErrArgument);
+		}
+	
+
+	SetMessageSessionId(sessionId);
+	CleanupStack::Pop(sessionId);
+
+	// Only proxy mode is supported
+	// (SUPL INIT with non-proxy mode is ignored)
+	CSuplInit::TSuplSlpMode slpMode = suplInitPtr->SlpMode();
+	if (CSuplInit::ESuplSlpModeProxy != slpMode)
+		{
+		User::Leave(KErrArgument);
+		}
+
+	TLbsNetPosRequestPrivacy privacy;
+	if (suplInitPtr->NotificationPresent())
+		{
+		User::LeaveIfError(suplInitPtr->GetNotificationType(privacy));
+		
+		// Check for Stealth / Privacy Override. This is not supported by LBS.
+		if (privacy.RequestAdvice() == TLbsNetPosRequestPrivacy::ERequestAdviceStealth)
+			{
+			User::Leave(KErrArgument);
+			}
+		}
+	else
+		{
+		// If notification is not present that means
+		// "no notification and no verification" as per
+		// SUPL specification (but it is up to LBS to
+		// accept such conditions depending on its configuration).	
+		privacy.SetRequestAdvice(TLbsNetPosRequestPrivacy::ERequestAdviceSilent);
+		}
+
+	//External requestor info
+	TLbsExternalRequestInfo requestInfo;
+	if (suplInitPtr->ExternalRequestInfoPresent())
+		{
+		User::LeaveIfError(suplInitPtr->GetExternalRequestInfo(requestInfo));
+		}
+
+	// QOP
+	TLbsNetPosRequestQuality quality;
+	if (suplInitPtr->QopPresent())
+		{
+		User::LeaveIfError(suplInitPtr->GetQop(quality));
+		}
+	else
+		{
+		// Set accuracy to NaN to prompt LBS to
+		// use accuracies from its pre-configured
+		// profiles if available.
+		TRealX nan;
+		nan.SetNaN();
+		quality.SetMinHorizontalAccuracy(nan);
+		quality.SetMinVerticalAccuracy(nan);
+		}
+
+	// Positioning method
+	TLbsNetPosRequestMethod method;
+	User::LeaveIfError(suplInitPtr->GetPosMethod(method));
+
+	// VER
+	User::LeaveIfError(GetHostId(hostId));
+	User::LeaveIfError(iSlpSettingsStore->GetHostSettings(hostId, slpSettings));
+	slpSettings.GetHostNameAddress(hostNameAddress);
+	TPtrC8 ver = suplInitPtr->GetVerL(hostNameAddress);
+
+	iEventStore->StoreExternalLocationRequest(privacy, requestInfo, quality, method, ver);
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::StoreExternalLocationRequestL() End\n");
+	}
+
+
+
+//---------------------------------------------------------------------------------------------------------------------
+// --------------------------------         EVENT HANDLING METHODS          -------------------------------------------
+//---------------------------------------------------------------------------------------------------------------------
+
+//------------------------------------ EVENTS FROM PROTOCOL MANAGER  ---------------------------------------						
+
+/** Handle an MTLR request due to a SUPL INIT received.
+@param aSessionId The session ID supplied by LBS.
+@param aSuplInit The SUPL INIT that triggered the MTLR
+*/
+void CSuplMtlrFsmSession::MtLrReq(const TLbsNetSessionId& aSessionId, const CSuplInit* aSuplInit)
+	{
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::MtLrReq() Begin\n");
+	// Store parameters received in the SUPL INIT message
+	TRAPD(err, ProcessExternalLocationRequestL(aSuplInit))
+	if (KErrNone == err)
+		{
+		// Initialise the new procedure
+		InitialiseProcedure();
+		// Store the supplied ID information
+		SetSessionId(aSessionId);
+		// Perform a state transition
+		PerformTransition();
+		}
+	else
+		{
+		// A problem was found with the parameters
+		// in the SUPL INIT. Ignore the SUPL INIT
+		// and clear the event store.
+		iEventStore->ClearStore();
+		}
+
+	delete aSuplInit;
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::MtLrReq() End\n");
+	}
+
+
+/** Handle a Response from LBS to an earlier Privacy Request
+@param aResponse Privacy response value.
+*/
+void CSuplMtlrFsmSession::PrivacyResp(const TLbsNetSessionId& /*aSessionId */, 
+									  const CLbsNetworkProtocolBase::TLbsPrivacyResponse& aResponse)
+	{
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::PrivacyResp() Begin\n");
+	iEventStore->StoreEvent(aResponse);
+	// Perform a state transition out of EStateSuplInitReceived
+	// (only state expecting this event)
+	if (EStateSuplInitReceived == iCurrentState)
+		PerformTransition();
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::PrivacyResp() End\n");
+	}
+
+/** Handle LBS Location response
+@param aReason Location response error reason.
+@param aPosInfo The location information response from LBS.
+*/	
+void CSuplMtlrFsmSession::LocationResp(TInt aReason, const TPositionInfoBase& aPosInfo)
+	{
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::LocationResp() Begin\n");
+	switch (aReason)
+		{
+		case KErrCancel:
+			// LBS is cancelling the MTLR
+			CancelMachine(CSuplFsmSessionBase::ECancelClient, CSuplFsmSessionBase::EReasonNone);
+			break;
+					
+		case KPositionCalculationFutile:
+			// LBS unable to calculate a position using selected positioning method
+			CancelMachine(CSuplFsmSessionBase::ECancelClient, CSuplFsmSessionBase::EReasonFutilePosCalc);
+			break;
+			
+		case KErrNone:
+			if(EStatePositioningInProgress == iCurrentState)
+				{
+				// While a SUPL POS session is in progress, the recipient of the location update is
+				// the Positioning Protocol state machine.
+				iPositioningProtocol->LocationResp(aReason, aPosInfo);
+				}
+			else if (EStateNetConnectionStarted == iCurrentState)
+				{
+				// The position provided by LBS can be sent to 
+				// the SLP in a SUPL POS INIT. Store it:
+				TInt err = KErrNone;
+				TRAP(err, iEventStore->StoreEventL(aPosInfo));
+
+				// Leave current state if a connection is already up.
+				if (IsSessionConnected())
+						PerformTransition();
+				}
+			break;
+
+		default:
+			// Not one of the reason codes for SUPL to handle. If positioning is ongoing
+			// send the position and the error code to the positioning state machine for
+			// it to handle according to the specifications of the positioning protocol.
+			if(EStatePositioningInProgress == iCurrentState)
+				{
+				// While a SUPL POS session is in progress, the recipient of the location update is
+				// the Positioning Protocol state machine.
+				iPositioningProtocol->LocationResp(aReason, aPosInfo);
+				}
+			else
+				{
+				// Cancel the MTLR except when this location response arrives after a privacy
+				// reject (KErrAccessDenied), in which case the cancel must happen after the connection has been 
+				// created so a SUPL END can be sent
+				CLbsNetworkProtocolBase::TLbsPrivacyResponse response;
+				if (!((KErrAccessDenied == aReason) &&
+					 (iEventStore->GetPrivacyResp(response)) &&
+					 (CLbsNetworkProtocolBase::EPrivacyResponseRejected == response)))
+					{
+					CancelMachine(CSuplFsmSessionBase::ECancelClient, CSuplFsmSessionBase::EReasonNone);					
+					}
+				}
+				
+			break;
+		}
+
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::LocationResp() End\n");
+	}
+
+/** Handle LBS Assistance Data Request
+
+The Protocol Manager calls this method following an assitance data request from
+LBS. However, the PM only does that if a location request had been sent
+to LBS (which signals the point when the state machines can handle a request
+for assitance data). Consequently assistance data requests are only handled
+from states that may have resulted in a Location Request sent to LBS from the
+state machine. 
+
+@param aFilter Assistance data types being requested
+*/
+void CSuplMtlrFsmSession::AssistanceDataReq(const TLbsAssistanceDataGroup& aFilter)
+	{
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::AssistanceDataReq() Begin\n");
+	if (EStatePositioningInProgress == iCurrentState)
+		{
+		// While a SUPL POS session is in progress, the recipient of the assistance data 
+		// request is the Positioning Protocol state machine, but only if the assistance
+		// data request is not empty.
+		if (aFilter != 0)
+			{
+			iPositioningProtocol->AssistanceDataRequest(aFilter);
+			}
+		else
+			{
+			// ignore assistance data request
+			// 	
+			}
+		}
+	 else if (EStateNetConnectionStarted == iCurrentState)
+		{
+		StoreAssistanceDataRequest(aFilter);
+		// If the connection had already been created, this state
+		// was simply waiting for the assistance data. Transition out
+		// of it.
+		if (IsSessionConnected())
+			PerformTransition();		
+		}
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::AssistanceDataReq() End\n");
+	}
+
+
+//----------------------------- EVENTS FROM POSITIONING PROTOCOL (RRLP) ---------------------------
+
+/** Handle a notification of availability of new assistance data from
+	the Positioning Protocol (RRLP) state machine.
+*/
+void CSuplMtlrFsmSession::ProcessAssistanceData(const TLbsAsistanceDataGroup& aGroupMask, TInt aReason)
+	{
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::ProcessAssistanceData() Begin\n");
+    ASSERT(iCurrentState == EStatePositioningInProgress);
+	iObserver.ProcessAssistanceData(aGroupMask, iAssistanceDataBuilderSet, aReason,LocReqType());
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::ProcessAssistanceData() End\n");
+	}
+
+/** Handle a Location Request from the Positioning Protocol.
+@param aQuality  quality parameters for the location request.
+@param aPosMethod positioning method requested by the Positioning Protocol
+*/
+void CSuplMtlrFsmSession::ProcessPositioningRequest(const TLbsNetPosRequestQuality& aQuality, const TLbsNetPosRequestMethod& aPosMethod)
+	{
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::ProcessPositioningRequest() Begin\n");
+	// Disregard this event if MOLR FSM is no longer in positioning state
+	// (this could happen if the  SUPL session has changed state due to
+	// a cancel or error but the Positioning Protocol
+	// state machine has not been notified yet)
+	if (iCurrentState == EStatePositioningInProgress)
+		{
+		// Verify that the positioning method requested by the positioning
+		// state machine is supported by LBS
+		TLbsNetPosMethod selectedMethod;//only one to send to LBS
+		TLbsNetPosCapabilities capabilities;
+		iObserver.Gateway().GetCapabilities(capabilities);
+		if (PosMethodSupported(aPosMethod,selectedMethod,capabilities))
+			{
+			TLbsNetPosRequestMethod posMethod;
+			posMethod.SetPosMethods(&selectedMethod, 1);
+			// SUPL MoLr state machine just passes the request on to Protocol Manager.
+			iObserver.LocationReq(LbsSessionId(), LocReqType(), aQuality, posMethod);
+			}
+		else
+			{
+			// The associated positioning protocol has sent a location request
+			// with an unsupported positioning method. Terminate.
+			CancelMachine(CSuplFsmSessionBase::ECancelSuplProt,CSuplFsmSessionBase::EReasonMethodMismatch);	
+			}
+		}
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::ProcessPositioningRequest() End\n");
+	}
+
+/** Handle a request from the Positioning Protocol state machine to send
+a positioning protocol message to the network as the payload in a SUPL POS
+@param aPositioningPayload Positioning Protocol (RRLP) message that will be payload of a SUPL POS message 
+*/
+void CSuplMtlrFsmSession::PositioningPayloadToNetwork(const CSuplPosPayload* aPositioningPayload)
+	{
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::PositioningPayloadToNetwork() Begin\n");
+
+	// Disregard this event if MTLR FSM is no longer in positioning state
+	// (this could happen if the  SUPL session has changed state due to
+	// a cancel or error but this information the Positioning Protocol
+	// state machine has not been cancelled yet)
+	if (iCurrentState == EStatePositioningInProgress)
+		{
+		// As this event involves sending a SUPL POS to the network,
+		// run it through the MTLR state machine
+		//
+		StorePosPayload(aPositioningPayload);
+		// Perform a state transition
+		PerformTransition();
+		}
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::PositioningPayloadToNetwork() End\n");
+	}
+
+/** Handle error notification from Positioning Protocol
+This is an unrecoverable error. Cancel state machine.
+@param aError Error code reported by Postioning Protocol State Machine.
+*/
+void CSuplMtlrFsmSession::PositioningProtocolError(const TInt& aError)
+	{
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::PositioningProtocolError() Begin\n");
+	(void)aError;
+	ASSERT(iCurrentState == EStatePositioningInProgress);
+	CancelMachine(ECancelPosProt, EReasonNone);
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::PositioningProtocolError() End\n");
+	}
+
+//---------------------------------------------------------------------------------------------------------------------
+// --------------------------------         STATE CHANGE METHODS          ---------------------------------------------
+//---------------------------------------------------------------------------------------------------------------------
+
+/** Decide next state from EStateSuplInitReceived
+@return TBool ETrue if the state has changed
+*/
+TBool CSuplMtlrFsmSession::DetermineStateFromInitReceived()
+	{
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::DetermineStateFromInitReceived() Begin\n");
+	CLbsNetworkProtocolBase::TLbsPrivacyResponse response;
+	
+	// There must be a privacy response in the event store.
+	// If the privacy response is ignore, then cancel session.
+	// If the privacy response says accept or reject, then transition
+	// to the state that connects to the server (EStateNetConnectionStarted).
+	if (iEventStore->GetPrivacyResp(response))
+		{
+		if (CLbsNetworkProtocolBase::EPrivacyResponseIgnored == response)
+			{
+			CancelMachine(CSuplFsmSessionBase::ECancelClient, CSuplFsmSessionBase::EReasonPrivacyIgnored);
+			}
+		else
+			{
+			iCurrentState = EStateNetConnectionStarted;
+			SUPLLOG(ELogP1, "CSuplMolrFsmSession::DetermineStateFromInitReceived() Next state: EStateNetConnectionStarted\n");
+			}
+		}
+	else
+		{
+		// A transition out of EStateSuplInitReceived should not have started
+		// This is only possible if there has been an internal error.
+		CancelMachine(CSuplFsmSessionBase::ECancelSuplProt, CSuplFsmSessionBase::EReasonNone);
+		}
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::DetermineStateFromInitReceived() End\n");
+	return ETrue;
+	}
+
+/** Decide next state from EStateNetConnectionStarted
+@return TBool ETrue if the state has changed
+@param aForceRedo, indicates that the states entry action must be re-performed when there has been no change in state
+*/
+TBool CSuplMtlrFsmSession::DetermineStateFromConnectionStarted(TBool& aForceRedo)
+	{
+	SUPLLOG(ELogP1, "CSuplMtlrFsmSession::DetermineStateFromConnectionStarted() Begin\n");
+	// The next state depends on the value of privacy response kept in the event store:
+	// 1.- If PrivacyReqAccepted: 
+	//     1.1- Transition to the state EStatePosInitSent if LBS has sent an assistance
+	//     		data request or a position.
+	//		or
+	//
+	//     1.2- Transition to EStateSuplSessionEnded if the original request in the SUPL INIT
+	//          was a "no position" one. 
+	// 2.- If PrivacyReqRejected: no new state selected, just Cancel the session after
+	//		receiving a "Connected" indication so SUPL END is sent.
+	
+	
+	// Get the preferred method received in a SUPL INIT
+	// (kept in event store).
+	TLbsNetPosRequestMethod locReqMethods;
+	TLbsNetPosMethod prefMethod;
+	RetrieveInitPosMethod(locReqMethods);
+	locReqMethods.GetPosMethod(0, prefMethod);
+	
+	// always force Entry Actions for this state to be performed on new events,
+	// even if there is not a change in state.
+	aForceRedo =  ETrue;
+	
+	CLbsNetworkProtocolBase::TLbsPrivacyResponse privResponse;
+	iEventStore->GetPrivacyResp(privResponse);
+	if (CLbsNetworkProtocolBase::EPrivacyResponseAccepted == privResponse)
+		{	
+		// Only transition to EStatePosInitSent if LBS has sent an Assistance
+		// Data Request or a Location Response. Otherwise the transition will take place when
+		// the first of those events occurs after the connection has been created.
+		if (iEventStore->IsAssistanceDataReqStored() || iEventStore->IsPositionStored())
+			{
+			iCurrentState = EStatePosInitSent;
+			SUPLLOG(ELogP1, "CSuplMolrFsmSession::DetermineStateFromConnectionStarted() Next state: EStatePosInitSent End\n");
+			return ETrue;
+			}
+		else if (KLbsPositioningMeansNone == prefMethod.PosMeans())	// "no position" in SUPL INIT
+			{
+			iCurrentState = EStateSuplSessionEnded;
+			SUPLLOG(ELogP1, "CSuplMolrFsmSession::DetermineStateFromConnectionStarted() Next state: EStateSuplSessionEnded End\n");
+			return ETrue;			
+			}
+		else
+			{
+			// Nothing to do but wait for new events. Intentionally empty.
+			}
+		}
+	else if((CLbsNetworkProtocolBase::EPrivacyResponseRejected == privResponse) && IsSessionConnected())
+		{
+		CancelMachine(CSuplFsmSessionBase::ECancelClient, CSuplFsmSessionBase::EReasonPrivacyRejected);
+		SUPLLOG(ELogP1, "CSuplMtlrFsmSession::DetermineStateFromConnectionStarted() CancelMachine End\n");
+		return ETrue;
+		}
+		SUPLLOG(ELogP1, "CSuplMtlrFsmSession::DetermineStateFromConnectionStarted() End\n");
+		return EFalse;
+	}