--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/networkprotocolmodules/suplprotocolmodule/SuplProtocol/src/suplmtlrstatehandler.cpp Fri Jun 04 10:34:15 2010 +0100
@@ -0,0 +1,467 @@
+// 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 SUPL MT-LR procedure state handler
+//
+//
+
+/**
+ @file
+ @internalTechnology
+ @deprecated
+*/
+
+#include "suplmtlrfsmsession.h"
+#include "suplmtlrstatehandler.h"
+#include "suplgatewayinterface.h"
+#include "suplmessagebase.h"
+#include "suplstart.h"
+#include "suplpos.h"
+#include "suplposinit.h"
+#include "suplresponse.h"
+#include "suplend.h"
+#include <etelmm.h>
+#include "supldevloggermacros.h"
+
+
+/** Static constructor.
+@param aMachine A reference to the parent state machine.
+@return A new instance of the CSuplMtLrStateHandler class
+*/
+CSuplMtLrStateHandler* CSuplMtLrStateHandler::NewL(CSuplFsmSessionBase& aMachine)
+ {
+ SUPLLOG(ELogP1, "CSuplMtLrStateHandler::NewL() \n");
+ CSuplMtLrStateHandler* self = new (ELeave) CSuplMtLrStateHandler(aMachine);
+ return self;
+ }
+
+/** Standard constructor.
+@param aMachine A reference to the parent state machine.
+*/
+CSuplMtLrStateHandler::CSuplMtLrStateHandler(CSuplFsmSessionBase& aMachine)
+: CSuplStateHandlerBase(aMachine)
+ {
+ SUPLLOG(ELogP1, "CSuplMtLrStateHandler::CSuplMtLrStateHandler() Begin\n");
+ SUPLLOG(ELogP1, "CSuplMtLrStateHandler::CSuplMtLrStateHandler() End\n");
+ }
+
+
+/** Standard destructor.
+*/
+CSuplMtLrStateHandler::~CSuplMtLrStateHandler()
+ {
+ SUPLLOG(ELogP1, "CSuplMtLrStateHandler::~CSuplMtLrStateHandler() Begin\n");
+ SUPLLOG(ELogP1, "CSuplMtLrStateHandler::~CSuplMtLrStateHandler() End\n");
+ }
+
+
+/** Perform entry actions.
+This is called from the state machine to perform any actions
+associated with entering the current state following an external
+event or an autonomous state transition.
+
+For some states, there is only one possible course of action.
+For other states, the event store has to be checked to see what
+events have occurred and what actions have to be taken to handle
+such events.
+
+If an event conductive to cancelling the state machine had occurred
+(e.g, an explicit client cancel, an error, or a timeout), then the
+state machine would have been set in an state that terminates the
+session before this method is called (either EStateSuplSessionEnded
+or EStatePosSessionEnded).
+
+@return TBool ETrue if any actions have been taken
+*/
+TBool CSuplMtLrStateHandler::EntryActionsL()
+ {
+ SUPLLOG(ELogP1, "CSuplMtLrStateHandler::EntryActionsL() Begin\n");
+ TBool actionsTaken = ETrue;
+ // Retrieve current state and act accordingly
+ switch(iMachine.CurrentState())
+ {
+ case CSuplFsmSessionBase::EStateProcedureNull:
+ // No action required
+ break;
+
+ case CSuplFsmSessionBase::EStateSuplInitReceived:
+ actionsTaken = EntryActionsFromSuplInitReceived();
+ break;
+
+ case CSuplFsmSessionBase::EStateNetConnectionStarted:
+ actionsTaken = EntryActionsFromNetConnectionStarted();
+ break;
+
+ case CSuplFsmSessionBase::EStatePosInitSent:
+ // Build and send a SUPL POS INIT
+ actionsTaken = EntryActionsFromPosInitSentStateL();
+ break;
+
+ case CSuplFsmSessionBase::EStatePositioningInProgress:
+ actionsTaken = EntryActionsFromPositioningInProgressStateL();
+ break;
+
+ case CSuplFsmSessionBase::EStatePositionReceived:
+ actionsTaken = EntryActionsFromPositionReceivedStateL();
+ break;
+
+ case CSuplFsmSessionBase::EStateSuplSessionEnded:
+ // Send SUPL END
+ actionsTaken = EntryActionsFromSuplSessionEndedStateL();
+ break;
+
+ case CSuplFsmSessionBase::EStatePosSessionEnded:
+ // Send to Positioning FSM an instruction to terminate silently
+ //
+ iMachine.PositioningFsm()->CancelMachine(CSuplPositioningProtocolFsm::ESuplFsmCancel, CSuplFsmSessionBase::EReasonNone);
+ break;
+
+ case CSuplFsmSessionBase::EStateLbsSessionEnded:
+ // Send session complete indication to LBS
+ actionsTaken = EntryActionsFromLbsSessionEndedStateL();
+ break;
+
+ case CSuplFsmSessionBase::EStateNetConnectionClosed:
+ // Close the network connection
+ iMachine.CompleteProcedure();
+ break;
+
+ default:
+ ASSERT(EFalse);
+ break;
+ }
+
+ SUPLLOG(ELogP1, "CSuplMtLrStateHandler::EntryActionsL() End\n");
+ return actionsTaken;
+ }
+//---------------------------------------------------------------------------------------------------------------------
+// ----------------------- METHODS FOR ACTIONS AFTER ENTERING STATES ---------------------------------------------
+//---------------------------------------------------------------------------------------------------------------------
+
+/** Actions on entering state EStateSuplInitReceived
+This method sends a LocationRequest and a PrivacyRequest
+to LBS.
+*/
+TBool CSuplMtLrStateHandler::EntryActionsFromSuplInitReceived()
+ {
+ SUPLLOG(ELogP1, "CSuplMtLrStateHandler::EntryActionsFromSuplInitReceived() Begin\n");
+ TLbsNetPosRequestPrivacy privacyAdvice;
+ TLbsExternalRequestInfo requestor;
+ TLbsNetPosRequestMethod posMethods;
+ TLbsNetPosMethod selectedMethod; // only one method is sent to LBS
+ TLbsNetPosRequestQuality quality;
+
+ // Send a PrivacyRequest followed by a Location Request to LBS
+ iMachine.RetrievePrivacyAdvice(privacyAdvice);
+ iMachine.RetrieveRequestorInfo(requestor);
+ iMachine.Observer().PrivacyReq(iMachine.LbsSessionId(), privacyAdvice, requestor);
+
+
+ // Get the pos methods received in a SUPL INIT
+ // (kept in event store).
+ iMachine.RetrieveInitPosMethod(posMethods);
+ TLbsNetPosMethod netPrefMethod;
+ posMethods.GetPosMethod(0, netPrefMethod);
+ if (KLbsPositioningMeansNone != netPrefMethod.PosMeans()) // not a "noPosition" INIT
+ {
+ // Check that there are supported positioning methods different
+ // from Cell Based (Cell-Based can't be requested from LBS).
+ TLbsNetPosCapabilities capabilities;
+ iMachine.Observer().Gateway().GetCapabilities(capabilities);
+ if (iMachine.PosMethodSupported(posMethods, selectedMethod,capabilities) &&
+ KLbsPositioningMeansCell != selectedMethod.PosMeans())
+ {
+ // Method to be presented to LBS
+ posMethods.SetPosMethods(&selectedMethod, 1);
+ }
+ else
+ {
+ // No mutually supported positioning methods.
+ // Send to LBS the positioning method that is preferred
+ // by LBS (the first in the capabilities)
+ capabilities.GetPosMethod(0, selectedMethod);
+ posMethods.SetPosMethods(&selectedMethod, 1);
+ }
+
+ iMachine.RetrieveInitQuality(quality);
+ iMachine.Observer().LocationReq(iMachine.LbsSessionId(), iMachine.LocReqType(),
+ quality, posMethods);
+ }
+
+ SUPLLOG(ELogP1, "CSuplMtLrStateHandler::EntryActionsFromSuplInitReceived() End\n");
+ return ETrue;
+ }
+
+
+/** Actions on entering state EStateNetConnectionStarted
+
+This method obtains an SLP Id from the Host Settings store
+and asks the Connection Manager to provide a connection with it.
+*/
+TBool CSuplMtLrStateHandler::EntryActionsFromNetConnectionStarted()
+ {
+ SUPLLOG(ELogP1, "CSuplMtLrStateHandler::EntryActionsFromNetConnectionStarted() Begin\n");
+ TBool ret = ETrue;
+ TLbsHostSettingsId hostId = TUid::Uid(0);
+ TLbsNetSessionId::TSessionNum sessIdNum = 0;
+ // Request a connection if one has not been set up already
+ if (!iMachine.IsSessionConnected())
+ {
+ TInt err = iMachine.GetHostId(hostId);
+
+ if (KErrNone == err)
+ {
+ // Request a connection from the Connection Manager
+ //
+ sessIdNum = iMachine.SessionId().SessionNum();
+ iMachine.Observer().ConnectionManager().Connect(sessIdNum, hostId, CSuplSessionRecord::EServiceMtlr, iMachine);
+ // start the timer that oversees connection creation
+ iMachine.StartConnectionTimer();
+ }
+ else
+ {
+ // Cancel session as a SUPL server could not be determined
+ iMachine.CancelMachine(CSuplFsmSessionBase::ECancelSuplProt, CSuplFsmSessionBase::EReasonSlpSettingsMissing);
+ }
+ }
+ else
+ {
+ // This will happen if the connection has been created but the state
+ // machine remains in EStateNetConnectionStarted due to being waiting
+ // for an event from LBS (either a position notification or an assistance
+ // data request). Nothing to be done.
+ ret = EFalse;
+ }
+ SUPLLOG(ELogP1, "CSuplMtLrStateHandler::EntryActionsFromNetConnectionStarted() End\n");
+ return ret;
+ }
+
+
+
+/** Actions on entering state EStatePosInitSent
+This method builds a SUPL POS INIT message and hands it over to
+the Connection Manager for sending to the SUPL server.
+*/
+TBool CSuplMtLrStateHandler::EntryActionsFromPosInitSentStateL()
+ {
+ SUPLLOG(ELogP1, "CSuplMtLrStateHandler::EntryActionsFromPosInitSentStateL() Begin\n");
+ TBool err = EFalse;
+ TLbsNetPosRequestQuality quality;
+ TLbsNetPosCapabilities capabilities;
+ TBool actionsTaken = EFalse;
+
+ // There should be either an assistance data request
+ // or a position from LBS in the event store
+ if (iMachine.IsAssistanceDataRequestStored() || iMachine.IsPositionStored())
+ {
+ ASSERT(iMachine.IsSessionConnected()); // should not have transitioned into this state without a connection
+
+ // Create the SUPL POS INIT Message
+ CSuplPosInit* suplPosInit = CSuplPosInit::NewL();
+ CleanupStack::PushL(suplPosInit);
+
+ // Set the Location Id in the message
+ CSuplLocationId* locationId;
+ if (BuildLocationIdL(locationId))
+ {
+ CleanupStack::PushL(locationId);
+
+ suplPosInit->SetLocationId(*locationId);
+ CleanupStack::PopAndDestroy(locationId);
+
+ // Set Capabilities in the message
+ BuildCapabilitiesL(capabilities,quality);
+ User::LeaveIfError(suplPosInit->SetCapabilities(capabilities));
+
+ // Set either a supplied position or assistance data request in the message
+ if (iMachine.IsPositionStored())
+ {
+ TPositionInfoBase* posPtr = iMachine.RetrievePositionL();
+ User::LeaveIfError(suplPosInit->SetPosition(*posPtr));
+ }
+ else if (iMachine.IsAssistanceDataRequestStored())
+ {
+ TLbsAsistanceDataGroup assitDataReqMask;
+ TBool assitDataReqPresent = iMachine.RetrieveAssistanceDataRequest(assitDataReqMask);
+ if (assitDataReqMask != 0)
+ {
+ User::LeaveIfError(suplPosInit->SetRequestedAssistanceData(assitDataReqMask));
+ }
+ else
+ {
+ // This was an empty assistance data request. No need to set it
+ // in the POS INIT message (intentionally no action take here)
+ }
+ }
+
+ // Set in message header the stored session id
+ // after adding to it the SET session ID
+ CSuplSessionId* sessionId = iMachine.MessageSessionId();
+ TUint32 ipAddr = iMachine.RetrieveLocalIpAddress().Address();
+ sessionId->iSetSessionIdPresent = ETrue;
+ sessionId->iSetSessionId->iSessionId = iMachine.SessionId().SessionNum();
+ sessionId->iSetSessionId->iSetId->iSetIdType = ESuplSetIdTypeMsisdn; // TSuplSetIdType
+
+ const TUint8 KMaxMsisdnLength = 8;
+ TDes8& des = sessionId->iSetSessionId->iSetId->iSetId;
+ if(iMachine.Msisdn())
+ {
+ ConvertToBcd(des);
+ }
+ else
+ {
+ //Fill the descriptor with all bits set to 0, then append a 0xFF to the end to indicate the end of the MSISDN
+ des.SetLength(KMaxMsisdnLength);
+ des.Fill(0x00, (KMaxMsisdnLength -1)); //7 0's
+ des.Append(0xFF); //Final 1 FF
+ }
+
+ //sessionId->iSetSessionId->iSetId->iSetIdType = ESuplSetIdTypeIPAddress;
+ //sessionId->iSetSessionId->iSetId->iIpAddress->iIpAddressType = ESuplIpAddressTypeV4;
+ //sessionId->iSetSessionId->iSetId->iIpAddress->iIpAddress.Copy(reinterpret_cast<unsigned char*>(&ipAddr), 4);
+
+ User::LeaveIfError(suplPosInit->SetSessionId(*sessionId));
+
+ // Set in message the Ver field
+ TBuf8<8> ver;
+ iMachine.RetrieveVer(ver);
+ User::LeaveIfError(suplPosInit->SetVer(ver));
+
+ CleanupStack::Pop(suplPosInit);
+ // Ask the Connection Manager to send the SUPL POS INIT message
+ iMachine.Observer().ConnectionManager().SendMessage(suplPosInit, iMachine.SessionId().SessionNum());
+
+ // Start the timer that oversees the arrival of SUPL POS
+ iMachine.StartSuplPosTimer();
+
+ actionsTaken = ETrue;
+ }
+ else
+ {
+ // Failed to build Location Id
+ err = ETrue;
+ CleanupStack::PopAndDestroy(suplPosInit);
+ }
+ }
+ else
+ {
+ err = ETrue;
+ }
+
+ if (err)
+ {
+ iMachine.CancelMachine(CSuplFsmSessionBase::ECancelSuplProt, CSuplFsmSessionBase::EReasonNone);
+ }
+
+ SUPLLOG(ELogP1, "CSuplMtLrStateHandler::EntryActionsFromPosInitSentStateL() End\n");
+ return actionsTaken;
+ }
+
+/**
+Utility method that builds the capabilities to send in a SUPL POS INIT using LBS's supported
+capabilities and network preferred positioning method.
+*/
+TBool CSuplMtLrStateHandler::BuildCapabilitiesL(TLbsNetPosCapabilities& aCapabilities, TLbsNetPosRequestQuality& aQuality)
+{
+ SUPLLOG(ELogP1, "CSuplMtLrStateHandler::BuildCapabilitiesL() Begin\n");
+ TLbsNetPosRequestMethod locReqMethods;
+ TLbsNetPosMethod prefMethod;
+ TInt numMethods;
+ TInt index;
+ TBool ecidSupported = EFalse;
+ TInt additionalMethods = 1; // preferred method
+
+ iMachine.Observer().Gateway().GetCapabilities(aCapabilities);
+ numMethods = aCapabilities.NumPosMethods();
+ // Check if E-CID is possible
+ // (currently this mean Timing Advance only)
+ if(iMachine.IsNetworkInfoAvailable())
+ {
+ RMobilePhone::TMobilePhoneNetworkInfoV1 networkInfo;
+ RMobilePhone::TMobilePhoneLocationAreaV1 locationArea;
+ iMachine.RetrieveStoredNetworkInfo(networkInfo, locationArea);
+ if (RMobilePhone::ENetworkModeGsm == networkInfo.iMode)
+ {
+ RMobilePhone::TMobilePhoneCellInfoV9 cellInfo;
+ if(iMachine.RetrieveStoredCellInfo(cellInfo))
+ {
+ // Timing Advance not supported if negative
+ ecidSupported = (cellInfo.iTimingAdvance >= 0);
+ additionalMethods++;
+ }
+ }
+ }
+
+ // Determine what method has been used for this session (prefMethod).
+ // The positioning method preferred by the SLP had been received in the
+ // SUPL INIT message and is kept in the event store.
+ iMachine.RetrieveInitPosMethod(locReqMethods);
+ TLbsNetPosCapabilities capabilities;
+ iMachine.Observer().Gateway().GetCapabilities(capabilities);
+ if (!iMachine.PosMethodSupported(locReqMethods, prefMethod, capabilities) &&
+ KLbsPositioningMeansCell != prefMethod.PosMeans())
+ {
+ // No pos method received from the SLP was used for the session as
+ // no supported method was found. The first method in
+ // the array of capabilities (LBS's preferred) was used instead. Get it.
+ aCapabilities.GetPosMethod(0, prefMethod);
+ }
+
+ // The prefMethod has to be added at the end of the array of methods in aCapabilities
+ // because that is where the ASN1 encoder expects it to be.
+ // If E-CID is supported and there is room for it in the array, it will also be added to the
+ // array.
+ TLbsNetPosMethod* methods = NULL;
+ if (numMethods + additionalMethods < KLbsMaxNetPosMethods)
+ {
+ TLbsNetPosMethod ecidMethod;
+ ecidMethod.SetPosMethod(KLbsPositioningMeansCell, TPositionModuleInfo::ETechnologyNetwork);
+ methods = new (ELeave) TLbsNetPosMethod[numMethods + additionalMethods];
+
+ for (index =0; index < numMethods; index++)
+ {
+ aCapabilities.GetPosMethod(index, methods[index]);
+ }
+
+ if (ecidSupported)
+ {
+ methods[numMethods] = ecidMethod;
+ }
+
+ // Add preferred method at the end
+ methods[numMethods + additionalMethods - 1] = prefMethod;
+ aCapabilities.SetPosMethods(methods, numMethods + additionalMethods);
+ }
+ else
+ {
+ // There is only additional room for 1 or 0 methods.
+ methods = new (ELeave) TLbsNetPosMethod[KLbsMaxNetPosMethods];
+ for (index =0; index < KLbsMaxNetPosMethods; index++)
+ {
+ aCapabilities.GetPosMethod(index, methods[index]);
+ }
+
+ // Set the preferred method at the end (even if it
+ // overwrites current entry)
+ methods[KLbsMaxNetPosMethods-1] = prefMethod;
+ aCapabilities.SetPosMethods(methods, KLbsMaxNetPosMethods);
+ }
+
+ delete[] methods;
+
+ iMachine.RetrieveInitQuality(aQuality);
+ SUPLLOG(ELogP1, "CSuplMtLrStateHandler::BuildCapabilitiesL() End\n");
+ return ETrue;
+}
+