networkprotocolmodules/networkprotocolmodule/LbsSuplTestProtocol/src/lbssupltestmodule.cpp
changeset 0 9cfd9a3ee49c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/networkprotocolmodules/networkprotocolmodule/LbsSuplTestProtocol/src/lbssupltestmodule.cpp	Tue Feb 02 01:50:39 2010 +0200
@@ -0,0 +1,989 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// This file provides the class implementation of the ECOM plug-in 
+// interface for the LBS test Network Protocol Module.
+// 
+//
+
+#include "lbssupltestmodule.h"
+#include "lbssuplsocketlistener.h"
+#include <ecom/implementationproxy.h>
+
+//const TUint32 KInetAddr1 = INET_ADDR(209,172,70,68);//SiRF server
+const TUint32 KInetAddr2 = INET_ADDR(66,230,192,56);//SiRF sever
+const TUint32 KLoopBackAddr = INET_ADDR(127,0,0,1);//Used by SiRF in session ID of SUPL RESPONSE -proxy mode-
+const TUint KSuplPort =  7276; // standard SUPL TCP port.
+const TInt KNetworkTimeout = 45000000;
+const TInt KProtocolTimeout = 50000000;
+const TInt KMaxTxBufferSize = 2048; // 2k Max size of SUPL messages sent
+const TInt KMaxRxBufferSize = 8192; // 8k Max size of SUPL messages received
+
+// --------------------- SUPL TEST MODULE (ECom plug-in) --------------------------
+
+/** The unique ID of this plug-in interface.
+This corresponds to the interface UID specified in the .rss file
+for this SUPL test module.
+*/
+const TInt KPluginUidValue = 0x1028225B;
+
+CSuplProtocolModule* CSuplProtocolModule::NewL(TAny* aInitParams)
+	{
+	CSuplProtocolModule* self=new(ELeave) CSuplProtocolModule(aInitParams);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop();
+	return self;
+	}
+
+CSuplProtocolModule::~CSuplProtocolModule()
+	{
+	iSocketServerSession.Close();
+	}
+
+
+CSuplProtocolModule::CSuplProtocolModule(TAny* aInitParams): 
+	iObserver(REINTERPRET_CAST(
+	          TAssistanceDataSourceModuleConstructionParams*,
+	          aInitParams)->iAssistanceDataSourceObserver),
+	iNextSessionNumber(0)
+	{
+	}
+
+void CSuplProtocolModule::ConstructL()
+	{
+	// Open channel to Socket Server
+	User::LeaveIfError(iSocketServerSession.Connect());
+	}
+
+CAssistanceDataSourceBase* CSuplProtocolModule::NewDataSourceL()
+	{
+	// Create a new number for the session
+	if (iNextSessionNumber == 1000)
+	{
+		iNextSessionNumber = 0;
+	}
+	
+	iNextSessionNumber++;
+	
+	return CSuplProtocolSession::NewL(iObserver, iSocketServerSession, iNextSessionNumber);
+	}
+
+
+/** Defines the plug-in interface implementation UIDs, required by ECOM.
+*/
+const TImplementationProxy ImplementationTable[] = 
+    {
+    IMPLEMENTATION_PROXY_ENTRY(KPluginUidValue, CSuplProtocolModule::NewL)
+    };
+    
+
+/** Exported function for ECOM to retrieve implementations table
+*/
+EXPORT_C 
+const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
+    {
+    aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
+
+    return ImplementationTable;
+    }
+
+
+//--------------------- SUPL Session ---------------------------------------------------------
+
+CSuplProtocolSession::CSuplProtocolSession(MLbsAssistanceDataSourceObserver& aObserver, const TInt16& aSessionNumber): 
+	CActive(EPriorityStandard),
+    iObserver(&aObserver),
+    iBuilderSet(NULL),
+    iSessionNumber(aSessionNumber)
+	{
+	// Attach to active scheduler
+	//
+	CActiveScheduler::Add(this);
+	
+	iAddress.SetPort(KSuplPort);
+	iAddress.SetAddress(KInetAddr2);
+	}
+
+void CSuplProtocolSession::ConstructL(RSocketServ& aSocketServer)
+	{
+	iTxBuf.CreateMaxL(KMaxTxBufferSize);
+	iRxBuf.CreateMaxL(KMaxRxBufferSize);
+	// Open a TCP socket
+	User::LeaveIfError(iSocket.Open(aSocketServer, KAfInet, KSockStream, KProtocolInetTcp));
+
+
+    // Set SUPL port in socket
+    //
+    iSocket.SetLocalPort(KSuplPort);
+    
+	// Create a socket listener for SUPL messages
+	iSuplSocketListener = CSuplSocketListener::NewL(iSocket, iRxBuf);
+
+	// Create the timer
+	iTimer = CPeriodic::NewL(CActive::EPriorityStandard);
+	}
+
+CSuplProtocolSession::~CSuplProtocolSession()
+	{
+		Cancel();
+		iTxBuf.Close();
+		iRxBuf.Close();
+		delete iTimer;
+		delete iSuplSocketListener;
+		iSocket.Close();
+	}
+
+/**
+GetAssistanceData() Called by Network Simulator to request assitance data from the remote
+server.
+
+@parameter aBuilderSet. The CSuplProtocolSession will set the fields of this builder with
+			the assistance data.
+*/
+void CSuplProtocolSession::GetAssistanceData(RLbsAssistanceDataBuilderSet& aBuilderSet, const TLbsAssistanceDataGroup& aAssistanceDataFilter, const TCoordinate& aPosition)
+	{
+
+	iBuilderSet = &aBuilderSet;
+	iAssistanceDataFilter = aAssistanceDataFilter;
+	iPosition = aPosition;
+
+    // Validate parameters
+	if(aAssistanceDataFilter == 0)
+		{
+		iObserver->DataSourceNotification(KErrArgument);
+		}
+	else
+		{
+		// Set the correct state and force a transition of the state machine
+		if(iSessionState == EConnectedAwaitingRequest)
+			{
+			// Transition out of wait state
+			iSessionState = EAssistanceDataRequested;
+			}
+		else
+			{
+			// If in the process of collecting assistance data, cancel previous request and
+			// start over.
+			// Do not notify NetSim that previous assistance data retrieval won't be completed
+			// (it should know)
+			CancelGetAssistanceData();
+
+			// Flag that a request is pending
+			iAssistanceDataRequestPending = true;
+			}
+			
+		// Transition out of inactive states (EIdle and EConnectedAwaitingState)
+		if(!IsActive())
+			{
+			PrepareSelfTransition();
+			}
+		}
+	}
+
+
+CSuplProtocolSession* CSuplProtocolSession::NewL(MLbsAssistanceDataSourceObserver& aObserver,RSocketServ& aSocketServer, const TInt16& aSessionNumber)
+	{
+	CSuplProtocolSession* self= new(ELeave) CSuplProtocolSession(aObserver,aSessionNumber);
+	CleanupStack::PushL(self);
+	self->ConstructL(aSocketServer);
+	CleanupStack::Pop();
+	return self;
+	}
+
+void CSuplProtocolSession::RunL()
+	{
+	iTimer->Cancel();
+	
+	// Deal with errors in socket operations
+	if (iStatus != KErrNone)
+	{
+		if ((iSessionState == EConnectingToRemoteServer) && (!iAssistanceDataRequestPending))
+			{
+			// Disconnect without reporting to NetSim
+			iSessionState = EDisconnectingFromServer;
+			}
+		else if ((iAssistanceDataRequestPending) && (iStatus == KErrCancel))
+			{
+			// Assume the cancellation has been due to a new request from NetSim
+			// Start over without reporting to NetSim.
+			iSessionState = EConnectingToRemoteServer;
+			}
+		else
+			{
+			// start disconnection and report to NetSim
+			iSessionState = ENetworkTimeout;
+			}
+	}
+	
+	switch(iSessionState)
+		{
+		
+		case EIdle:
+			ConnectToRemoteServer();	
+			break;
+		
+		case EConnectingToRemoteServer:
+			TransitionAccordingToRequestAvailability();
+			break;
+		
+		case EConnectedAwaitingRequest:
+			// Nothing to be done in this state.
+			// This state is left when the Network
+			// Simulator requests assistance data
+			// (see GetAssistanceData())
+			break;
+			
+		case EAssistanceDataRequested:
+			iAssistanceDataRequestPending = EFalse;
+			iSessionState = ESendingSuplStart;
+			SendSuplMessageL(ESuplStart);
+			break;
+		
+		case ESendingSuplStart:
+			// SuplStart sent. Wait for SuplResponse
+			iSessionState = EAwaitingSuplResponse;
+			ReadSuplMessage();
+			break;
+			
+		case EAwaitingSuplResponse:
+		    iSessionState = ESuplResponseAvailable;
+			DecodeSuplMessageL(ESuplResponse); //May set error state
+		    break;
+		    
+		case ESuplResponseAvailable:
+			iSessionState = ESendingSuplPosInit;
+			SendSuplMessageL(ESuplPosInit);	
+			break;
+			
+		case ESendingSuplPosInit:
+			iSessionState = EAwaitingSuplPos;
+			ReadSuplMessage();
+			break;
+			
+		case EAwaitingSuplPos:
+			iSessionState = ESuplPosAvailable;
+			DecodeSuplMessageL(ESuplPos);	//May set error state
+			break;
+			
+		case ESuplPosAvailable:
+		    iSessionState = ERrcPayloadDecodeComplete;
+			DecodeRRCPayloadL();
+			PrepareSelfTransition();
+			break;
+			
+		case ERrcPayloadDecodeComplete:
+			iSessionState = EEndingSession;
+			// Notify succesful exit to NetSim
+			iObserver->DataSourceNotification(KErrNone);
+			PrepareSelfTransition();
+			break;
+			
+		case EProtocolError:
+			//Unexpected message. Notify unsuccesfull exit to NetSim
+			iObserver->DataSourceNotification(KErrCancel);
+			iAssistanceDataRequestPending = EFalse;
+			iSessionState = EDisconnectingFromServer;
+			PrepareSelfTransition();
+			break;
+			
+		case ENetworkTimeout:
+			// Report to NetSim that something went wrong
+			iObserver->DataSourceNotification(iStatus.Int());
+			iAssistanceDataRequestPending = EFalse;
+			iSessionState = EDisconnectingFromServer;
+			PrepareSelfTransition();
+			break;
+			
+		case EDisconnectingFromServer:
+			iSessionState = EIdle;
+			iSocket.Shutdown(RSocket::ENormal,iStatus);
+			SetActive();
+			break;
+		
+		case EEndingSession:
+			iSessionState = ESuplEndSent;
+			SendSuplMessageL(ESuplEnd);
+			break;
+
+		case ESuplEndSent:
+ 			iSessionState = EConnectingToRemoteServer;
+			ReadSuplMessage();
+			break;
+
+		default:
+			Cancel();
+			User::Leave(KErrGeneral);
+			break;
+		}
+	}
+
+/**
+CancelGetAssistanceData. Cancels a previous request
+for Assistance Data and starts actions to bring the state
+machine to EConnectedAwaitingRequest again, where a new
+request for assistance data can be serviced.
+
+If the session had been started with the remote server 
+to obtain Assistance Data, the session is first brought
+down and the state machine will autonomously reconnect and
+move on to EConnectedAwaitingRequest state.
+
+The Nework Simulator will not receive a notification of
+cancellation of the previous request for assistance data.
+
+Note this cancelling method is unrelated to
+CActive::Cancel()/DoCancel(). The state machine will remain
+active and method RunL is expected to be called after this
+method completes (unlike DoCancel()).
+
+@return Symbian error code. KErrNone if OK.
+*/
+void CSuplProtocolSession::CancelGetAssistanceData()
+	{
+
+	iTimer->Cancel();
+	// Do not service pending requests
+	iAssistanceDataRequestPending = false;
+	switch (iSessionState)
+		{
+		case EIdle:
+		case EConnectingToRemoteServer:
+		case EConnectedAwaitingRequest:
+		case EDisconnectingFromServer:
+		case ENetworkTimeout:
+		case EProtocolError:
+		case EEndingSession:
+		// nothing to do (session not getting assistance data)
+		break;
+
+		case EAssistanceDataRequested:
+		// Session not started with remote server yet.
+		// RunL will be called shortly as a self transition
+		// was prepared when this state was entered.
+		// Put the state machine in a position of
+		// transitioning towards EConnectedAwaitingRequest state.
+		iSessionState = EConnectingToRemoteServer;			
+		break;
+
+		case ESendingSuplStart:
+		case ESendingSuplPosInit:
+		// Cancel send operation.
+		// RunL will process KErrCancel case,
+		// setting the state to EDisconnectingFromServer.
+		iSocket.CancelWrite();
+		break;
+
+		case EAwaitingSuplResponse:
+		case EAwaitingSuplPos:
+		case ESuplEndSent:
+		// Cancel receive operation
+		// RunL will process KErrCancel case,
+		// setting the state to EDisconnectingFromServer.
+		iSuplSocketListener->Cancel();
+		break;
+
+		case ESuplResponseAvailable:
+		case ESuplPosAvailable:
+		case ERrcPayloadDecodeComplete:
+		// These three states have prepared
+		// self-transaction. When RunL gets
+		// executed, disconnect:
+		iSessionState = EDisconnectingFromServer;
+		break;
+
+		default:
+		// Not a valid state
+		User::Invariant();
+		break;
+		}
+	}
+	
+	
+TInt CSuplProtocolSession::OnTimerEventL(TAny* aPtr)
+	{
+	CSuplProtocolSession* aSession = STATIC_CAST(CSuplProtocolSession*,aPtr);
+	if (aSession)
+		{
+		aSession->DoProcessTimeoutL();
+		}
+	return KErrNone;
+	}
+
+void CSuplProtocolSession::DoProcessTimeoutL()
+{
+	iTimer->Cancel();
+	
+	// Cancel async tasks to re-enter RunL with
+	// error code KErrCancel
+	switch(iSessionState)
+	{
+		case EConnectingToRemoteServer:
+			iSocket.CancelConnect();
+			break;
+		case ESendingSuplStart:
+		case ESendingSuplPosInit:
+			iSocket.CancelWrite();
+			break;
+		case EAwaitingSuplPos:
+		case EAwaitingSuplResponse:
+			iSuplSocketListener->Cancel();
+			break;
+		default:
+			// No other state should have a timer running
+			Cancel();
+			User::Leave(KErrGeneral);
+			break;
+	}
+}
+
+
+void CSuplProtocolSession::CreateSuplStartMessageL()
+	{
+	
+	CSuplMessageContent* suplMsgContent=CSuplMessageContent::NewLC();
+	
+	// Build common part
+	suplMsgContent->iMessageChoice=ESuplStart;	
+	BuildCommonPartL(suplMsgContent);
+	
+	suplMsgContent->iSuplStartContent=CSuplStartContent::NewL();
+
+	// Qop field is optional BUT required for the SiRF server to work with RRC
+	TBool qopPresent = ETrue;
+	suplMsgContent->iSuplStartContent->iQopPresent=qopPresent;
+	
+	// Set capabilities (mandatory)
+	suplMsgContent->iSuplStartContent->iSetCapabilitiesContent=CSuplSetCapabilitiesContent::NewL();
+	BuildSetCapabilitiesL(suplMsgContent->iSuplStartContent->iSetCapabilitiesContent);
+	
+	//LocationId --- CellInfo
+	suplMsgContent->iSuplStartContent->iLocationIdContent=CSuplLocationIdContent::NewL();
+	suplMsgContent->iSuplStartContent->iLocationIdContent->iCellInfoContent=CSuplCellInfoContent::NewL();
+	BuildCellInfoL(suplMsgContent->iSuplStartContent->iLocationIdContent->iCellInfoContent, EGsmCellInformation); // Verify EGsmCellInformation
+	suplMsgContent->iSuplStartContent->iLocationIdContent->iLocationStatus= ECurrent; //TSuplLocationStatus
+
+	// QoP
+	suplMsgContent->iSuplStartContent->iQoPContent=CSuplQoPContent::NewL();
+	suplMsgContent->iSuplStartContent->iQoPContent->iVeraccPresent = EFalse;
+	suplMsgContent->iSuplStartContent->iQoPContent->iMaxLocAgePresent = EFalse;
+	suplMsgContent->iSuplStartContent->iQoPContent->iDelayPresent = EFalse;
+	suplMsgContent->iSuplStartContent->iQoPContent->iHoracc= 20; // Random value !!!
+
+
+	CSuplMessage* suplMessageEncoder=CSuplMessage::NewLC(*suplMsgContent);
+	
+    // Encode message
+    iTxBuf.SetLength(0);
+	suplMessageEncoder->EncodeL(iTxBuf);
+	
+	CleanupStack::PopAndDestroy(suplMessageEncoder);
+	CleanupStack::PopAndDestroy(suplMsgContent);
+	}
+
+void CSuplProtocolSession::CreateSuplEndMessageL()
+	{
+	
+	CSuplMessageContent* suplMsgContent=CSuplMessageContent::NewLC();
+	
+	// Build common part
+	suplMsgContent->iMessageChoice=ESuplEnd;	
+	BuildCommonPartL(suplMsgContent);
+	suplMsgContent->iSuplEndContent=CSuplEndContent::NewL();
+	
+	// Position field should be false
+	suplMsgContent->iSuplEndContent->iPositionPresent=EFalse;
+	
+	// Status Code field should be false
+	suplMsgContent->iSuplEndContent->iStatusCodePresent=EFalse;
+
+	// Ver field should be false
+	suplMsgContent->iSuplEndContent->iVerPresent=EFalse;		
+
+	CSuplMessage* suplMessageEncoder=CSuplMessage::NewLC(*suplMsgContent);
+	
+    // Encode message
+    iTxBuf.SetLength(0);
+	suplMessageEncoder->EncodeL(iTxBuf);
+	
+	CleanupStack::PopAndDestroy(suplMessageEncoder);
+	CleanupStack::PopAndDestroy(suplMsgContent);
+	}
+
+void CSuplProtocolSession::CreatePosInitMessageL()
+	{
+	CSuplMessageContent* suplMsgContent=CSuplMessageContent::NewLC();
+	
+	// Build common part
+	suplMsgContent->iMessageChoice = ESuplPosInit;
+	BuildCommonPartL(suplMsgContent);
+	suplMsgContent->iSuplPosInitContent = CSuplPosInitContent::NewL();
+
+	// Request Assist Data field should be true
+	suplMsgContent->iSuplPosInitContent->iRequestedAssistDataPresent=ETrue;
+	
+	// PosInit field should be false
+	suplMsgContent->iSuplPosInitContent->iSuplPosPresent=EFalse;
+	
+	// Position field should be true
+	suplMsgContent->iSuplPosInitContent->iPositionPresent=ETrue;
+	
+	// Ver field should be false
+	suplMsgContent->iSuplPosInitContent->iVerPresent=EFalse;
+	suplMsgContent->iSuplPosInitContent->iSetCapContent=CSuplSetCapabilitiesContent::NewL();
+	
+	// Build Set Capabilities
+	BuildSetCapabilitiesL(suplMsgContent->iSuplPosInitContent->iSetCapContent);
+	
+	// Set Assistance Data types requested
+	suplMsgContent->iSuplPosInitContent->iRequestedAssistDataContent=CSuplRequestedAssistDataContent::NewL();
+	suplMsgContent->iSuplPosInitContent->iRequestedAssistDataContent->iNavigationModelDataPresent=EFalse;// SiRF unsupported
+	suplMsgContent->iSuplPosInitContent->iRequestedAssistDataContent->iDgpsCorrectionsRequested=EFalse; // NOT SUPPORTED
+	suplMsgContent->iSuplPosInitContent->iRequestedAssistDataContent->iRealTimeIntegrityRequested=EFalse;// NOT SUPPORTED
+	suplMsgContent->iSuplPosInitContent->iRequestedAssistDataContent->iUtcModelRequested=EFalse; // NOT SUPPORTED BY SIRF
+	
+    if(iAssistanceDataFilter & EAssistanceDataAlmanac)
+    	{
+    	suplMsgContent->iSuplPosInitContent->iRequestedAssistDataContent->iAlmanacRequested=ETrue;
+   		}
+   	else
+   		{
+   		suplMsgContent->iSuplPosInitContent->iRequestedAssistDataContent->iAlmanacRequested=EFalse;	
+   		}
+   		
+	if(iAssistanceDataFilter & EAssistanceDataIonosphericModel)
+    	{
+    	suplMsgContent->iSuplPosInitContent->iRequestedAssistDataContent->iIonosphericModelRequested=ETrue;
+   		}
+   	else
+   		{
+		suplMsgContent->iSuplPosInitContent->iRequestedAssistDataContent->iIonosphericModelRequested=EFalse;
+   		}
+   		
+    if(iAssistanceDataFilter &  EAssistanceDataReferenceLocation)
+    	{
+    	suplMsgContent->iSuplPosInitContent->iRequestedAssistDataContent->iReferenceLocationRequested=ETrue;
+   		}
+   	else
+   		{
+		suplMsgContent->iSuplPosInitContent->iRequestedAssistDataContent->iReferenceLocationRequested=ETrue;
+   		}
+
+    if(iAssistanceDataFilter &  EAssistanceDataReferenceTime)
+    	{
+    	suplMsgContent->iSuplPosInitContent->iRequestedAssistDataContent->iReferenceTimeRequested=ETrue;
+   		}
+   	else
+   		{
+		suplMsgContent->iSuplPosInitContent->iRequestedAssistDataContent->iReferenceTimeRequested=EFalse;
+   		}
+
+    if(iAssistanceDataFilter &  EAssistanceDataAquisitionAssistance)
+    	{
+    	suplMsgContent->iSuplPosInitContent->iRequestedAssistDataContent->iAcquisitionAssistanceRequested=ETrue;
+   		}
+   	else
+   		{
+		suplMsgContent->iSuplPosInitContent->iRequestedAssistDataContent->iAcquisitionAssistanceRequested=EFalse;
+   		}
+
+    if(iAssistanceDataFilter &  EAssistanceDataNavigationModel)
+    	{
+    	suplMsgContent->iSuplPosInitContent->iRequestedAssistDataContent->iNavigationModelRequested=ETrue;
+   		}
+   	else
+   		{
+		suplMsgContent->iSuplPosInitContent->iRequestedAssistDataContent->iNavigationModelRequested=EFalse;
+   		}   
+
+	// build cell info	
+	suplMsgContent->iSuplPosInitContent->iLocationIdContent = CSuplLocationIdContent::NewL();
+	suplMsgContent->iSuplPosInitContent->iLocationIdContent->iCellInfoContent=CSuplCellInfoContent::NewL();
+	suplMsgContent->iSuplPosInitContent->iLocationIdContent->iLocationStatus = EStale; //TSuplLocationStatus
+	BuildCellInfoL(suplMsgContent->iSuplPosInitContent->iLocationIdContent->iCellInfoContent,EGsmCellInformation);
+	
+	// build Position info
+	suplMsgContent->iSuplPosInitContent->iPositionContent = CSuplPositionContent::NewL();
+	BuildPositionInfoL(suplMsgContent->iSuplPosInitContent->iPositionContent);
+	
+	CSuplMessage* suplMessageEncoder=CSuplMessage::NewLC(*suplMsgContent);
+
+	// Encode message
+    iTxBuf.SetLength(0);
+	suplMessageEncoder->EncodeL(iTxBuf);
+	
+	CleanupStack::PopAndDestroy(suplMessageEncoder);
+	CleanupStack::PopAndDestroy(suplMsgContent);
+	}
+
+TSuplMessageType CSuplProtocolSession::DoDecodeMessageL()
+	{
+    CSuplMessage* suplMessageDecoder=CSuplMessage::NewLC();
+
+    CSuplMessageContent* suplMessageResultContent=suplMessageDecoder->DecodeL(iRxBuf);
+    CleanupStack::PushL(suplMessageResultContent);
+
+	// Keep in the session the bits of information needed from the messages sent from the remote
+	// server
+	//
+	switch (suplMessageResultContent->iMessageChoice)
+		{
+		case ESuplResponse:
+			// Keep the SLP part of the session ID
+			iSlpSessionId.Copy(suplMessageResultContent->iSuplSessionIdContent->iSlpSessionIdContent->iSessionId);
+			break;
+		case ESuplPos:
+			// Keep the offset into the rx buffer where the RRC payload is
+			iRrcOffset = suplMessageResultContent->iSuplPosContent->iPosPayloadContent->iPayloadStartBitPos;
+			break;
+		}
+	
+	TSuplMessageType messageType = static_cast<TSuplMessageType>(suplMessageResultContent->iMessageChoice);
+
+    CleanupStack::PopAndDestroy(2, suplMessageDecoder);
+
+	return messageType;
+	}
+
+void CSuplProtocolSession::DecodeRRCPayloadL()
+	{
+	CAssistanceDataDeliveryR3IEs* rrcPayLoad=CAssistanceDataDeliveryR3IEs::NewLC(iBuilderSet);
+    rrcPayLoad->DecodeL(iRxBuf, iRrcOffset);
+    CleanupStack::PopAndDestroy(rrcPayLoad);
+	}
+
+void CSuplProtocolSession::PrepareSelfTransition()
+	{
+	TRequestStatus* localStatus = &iStatus;
+	iStatus = KRequestPending;
+	SetActive();
+	User::RequestComplete(localStatus, KErrNone);
+	}
+
+void CSuplProtocolSession::DoCancel()
+	{
+	iSocket.CancelWrite();
+	iSuplSocketListener->Cancel();
+	iTimer->Cancel();
+	}
+
+void CSuplProtocolSession::BuildSetCapabilitiesL(CSuplSetCapabilitiesContent* aContent)
+	{
+	// SETCAPABILITY --- PosTechnology (Set based and autonomous only)
+	aContent->iPosTechnologyContent=CSuplPosTechnologyContent::NewL();
+	aContent->iPosTechnologyContent->iAgpsSETassisted=EFalse;
+	aContent->iPosTechnologyContent->iAgpsSETBased=ETrue;
+	aContent->iPosTechnologyContent->iAutonomousGPS=ETrue;
+	aContent->iPosTechnologyContent->iAFLT=EFalse;	
+	aContent->iPosTechnologyContent->iECID=EFalse;
+	aContent->iPosTechnologyContent->iEOTD=EFalse;	
+	aContent->iPosTechnologyContent->iOTDOA=EFalse;
+
+	// SETCAPABILITY --- PosMethod	 (prefer Set based)
+	aContent->iPrefMethod = EAGpsSETBasedPreferred; //TSuplPrefMethod	
+	
+	// SETCAPABILITY --- PosProtocol (only RRC)
+	aContent->iPosProtocolContent=CSuplPosProtocolContent::NewL();	
+	aContent->iPosProtocolContent->iTia801=EFalse;	
+	aContent->iPosProtocolContent->iRrlp=EFalse;	
+	aContent->iPosProtocolContent->iRrc=ETrue;		
+	}
+
+void CSuplProtocolSession::BuildCellInfoL(CSuplCellInfoContent* aContent, TCellInformationChoice aCellInfoChoice)
+	{
+	
+	aContent->iCellInformation = aCellInfoChoice;
+
+	switch (aCellInfoChoice)
+		{
+		case EGsmCellInformation:
+			{
+			aContent->iGsmCellInformationContent=CSuplGsmCellInformationContent::NewL();
+			TBool nmrPresent = EFalse; //Optional
+			aContent->iGsmCellInformationContent->iNMRPresent=nmrPresent;
+
+			TBool taPresent = EFalse; //Optional
+			aContent->iGsmCellInformationContent->iTAPresent=taPresent;
+
+			TInt refMCC = 234; // UK
+			aContent->iGsmCellInformationContent->iRefMCC=refMCC;
+
+			TInt refMNC = 101; // 101 (O2), 151 (voda), 301(t-mobile), 331 (orange)
+			aContent->iGsmCellInformationContent->iRefMNC=refMNC;
+
+			TInt refLAC = 12049; // Area code (it seems to be dependant on the network!)
+			aContent->iGsmCellInformationContent->iRefLAC=refLAC;
+
+			TInt refCI = 1103; // Entirely dependant on the operator.
+			aContent->iGsmCellInformationContent->iRefCI=refCI;			
+			}
+			break;
+		case EWcdmaCellInformation:
+			{
+			aContent->iWcdmaCellInformationContent=CSuplWcdmaCellInformationContent::NewL();
+			TBool frequencyInfoPresent = EFalse;
+			aContent->iWcdmaCellInformationContent->iFrequencyInfoPresent=frequencyInfoPresent;
+			
+			TBool primaryScramblingCodePresent = EFalse;
+			aContent->iWcdmaCellInformationContent->iPrimaryScramblingCodePresent=primaryScramblingCodePresent;
+
+			TBool measuredResultsListPresent = EFalse;
+			aContent->iWcdmaCellInformationContent->iMeasuredResultsListPresent=measuredResultsListPresent;
+
+			TInt refMCC = 34;
+			aContent->iWcdmaCellInformationContent->iRefMCC=refMCC;
+
+			TInt refMNC = 34; 
+			aContent->iWcdmaCellInformationContent->iRefMNC=refMNC;
+
+			TInt refUC =  1;
+			aContent->iWcdmaCellInformationContent->iRefUC=refUC;				
+			}
+			break;
+		case ECdmaCellInformation:
+			{
+			// All parameters are mandatory
+			//
+			aContent->iCdmaCellInformationContent=CSuplCdmaCellInformationContent::NewL();
+			TInt refNID = 1;
+			aContent->iCdmaCellInformationContent->iRefNID=refNID;
+			
+			TInt refSID = 1;
+			aContent->iCdmaCellInformationContent->iRefSID=refSID;
+			
+			TInt refBASEID = 1;
+			aContent->iCdmaCellInformationContent->iRefBASEID=refBASEID;
+
+			TInt refBASELAT = 1;
+			aContent->iCdmaCellInformationContent->iRefBASELAT=refBASELAT;
+			
+			TInt reBASELONG = 1;
+			aContent->iCdmaCellInformationContent->iReBASELONG=reBASELONG;
+			
+			TInt refREFPN = 1;
+			aContent->iCdmaCellInformationContent->iRefREFPN=refREFPN;
+			
+			TInt refWeekNumber = 1;
+			aContent->iCdmaCellInformationContent->iRefWeekNumber=refWeekNumber;
+			
+			TInt refSeconds = 1;
+			aContent->iCdmaCellInformationContent->iRefSeconds=refSeconds;				
+			}
+			break;
+		}
+	}
+
+void CSuplProtocolSession::BuildPositionInfoL(CSuplPositionContent* posContent)
+	{
+	posContent->iPositionEstimateContent = CSuplPositionEstimateContent::NewL();
+	
+	if (iPosition.Latitude() >= 0)
+		{
+		posContent->iPositionEstimateContent->iLatitudeSign = ENorth;
+		}
+	else
+		{
+		posContent->iPositionEstimateContent->iLatitudeSign = ESouth;
+		}
+	
+	posContent->iVelocityPresent = EFalse;
+	posContent->iUtcTimeStamp.UniversalTime(); // Use the current time. SUPL server ignores actual value.
+	
+	posContent->iPositionEstimateContent->iUncertainty = EFalse;
+	posContent->iPositionEstimateContent->iConfidence = EFalse;
+	posContent->iPositionEstimateContent->iAltitudInfo = EFalse;
+	
+	// Set Location (in the future, get the NetSim to provide this)
+	posContent->iPositionEstimateContent->iLatitude = static_cast<TUint32>((Abs(iPosition.Latitude()) * 8388608.0 + 0.5) / 90.0);
+	posContent->iPositionEstimateContent->iLongitude = static_cast<TInt32>((iPosition.Longitude() * 2097152.0 + 0.5) / 45.0);
+	}
+
+void CSuplProtocolSession::BuildCommonPartL(CSuplMessageContent* aSuplMsgContent)
+	{
+	
+	//Message Version
+	TInt majorVersion =1;
+	TInt minVersion = 0;
+	TInt servindVersion =0;
+	aSuplMsgContent->iSuplVersionContent=CSuplVersionContent::NewL();
+	aSuplMsgContent->iSuplVersionContent->iMaj=majorVersion;
+	aSuplMsgContent->iSuplVersionContent->iMin=minVersion;
+	aSuplMsgContent->iSuplVersionContent->iServind=servindVersion;
+	
+	//SET Session ID
+	TBool setsessionPresent = ETrue;
+	aSuplMsgContent->iSuplSessionIdContent=CSuplSessionIdContent::NewL();
+    aSuplMsgContent->iSuplSessionIdContent->iSetSessionIdPresent=setsessionPresent;
+
+	
+	aSuplMsgContent->iSuplSessionIdContent->iSetSessionIdContent=CSuplSetSessionIdContent::NewL();
+	aSuplMsgContent->iSuplSessionIdContent->iSetSessionIdContent->iSessionId=iSessionNumber;
+	aSuplMsgContent->iSuplSessionIdContent->iSetSessionIdContent->iSetIdContent=CSuplSetIdContent::NewL();
+	aSuplMsgContent->iSuplSessionIdContent->iSetSessionIdContent->iSetIdContent->iSetIdType= ESuplIPAddress; //TSuplSetIdType
+	aSuplMsgContent->iSuplSessionIdContent->iSetSessionIdContent->iSetIdContent->iIpAddressContent=CSuplIpAddressContent::NewL();
+	aSuplMsgContent->iSuplSessionIdContent->iSetSessionIdContent->iSetIdContent->iIpAddressContent->iIpAddressType=ESuplIpV4AddressChoice;//TSuplIpAddressType;
+	
+	
+	// Find out own address from socket
+	//
+	TInetAddr localAddress;
+	iSocket.LocalName(localAddress);
+    TUint32 address = localAddress.Address();
+	//aSuplMsgContent->iSuplSessionIdContent->iSetSessionIdContent->iSetIdContent->iIpAddressContent->iIpAddress.Copy(address);
+	TBuf8<4> theLocalAddress(4);
+	TUint8 aByteOfTheAddress = 0;
+	aByteOfTheAddress = address;
+	theLocalAddress[3]= aByteOfTheAddress;
+	aByteOfTheAddress = address >>8;
+	theLocalAddress[2]= aByteOfTheAddress;
+	aByteOfTheAddress = address >> 16;
+	theLocalAddress[1]= aByteOfTheAddress;
+	aByteOfTheAddress = address >> 24;
+	theLocalAddress[0]= aByteOfTheAddress;
+	aSuplMsgContent->iSuplSessionIdContent->iSetSessionIdContent->iSetIdContent->iIpAddressContent->iIpAddress.Copy(theLocalAddress);
+
+	//SLP Session ID -not sent in START- 
+	if (aSuplMsgContent->iMessageChoice == ESuplStart)
+		{
+		aSuplMsgContent->iSuplSessionIdContent->iSlpSessionIdPresent=EFalse;
+		}
+	else
+		{
+		aSuplMsgContent->iSuplSessionIdContent->iSlpSessionIdPresent=ETrue;
+		aSuplMsgContent->iSuplSessionIdContent->iSlpSessionIdContent=CSuplSlpSessionIdContent::NewL();
+		aSuplMsgContent->iSuplSessionIdContent->iSlpSessionIdContent->iSessionId.Copy(iSlpSessionId);
+
+		aSuplMsgContent->iSuplSessionIdContent->iSlpSessionIdContent->iSlpAddressContent=CSuplSlpAddressContent::NewL();
+
+		// Address provided by SiRF is IPv4
+		//
+		aSuplMsgContent->iSuplSessionIdContent->iSlpSessionIdContent->iSlpAddressContent->iSlpAddressType= ESuplSlpIpAddressChoice;
+		aSuplMsgContent->iSuplSessionIdContent->iSlpSessionIdContent->iSlpAddressContent->iIpAddressContent=CSuplIpAddressContent::NewL();
+		aSuplMsgContent->iSuplSessionIdContent->iSlpSessionIdContent->iSlpAddressContent->iIpAddressContent->iIpAddressType = ESuplIpV4AddressChoice;
+
+    	// Use loopback address 127.0.0.1 (received in RESPONSE, proxy mode).
+		TUint32 serverAddress = KLoopBackAddr;
+		TBuf8<4> theRemoteAddress(4);
+		TUint8 aByteOfTheRemoteAddress = 0;
+		aByteOfTheRemoteAddress = serverAddress;
+		theRemoteAddress[3]= aByteOfTheRemoteAddress;
+		aByteOfTheRemoteAddress = serverAddress >>8;
+		theRemoteAddress[2]= aByteOfTheRemoteAddress;
+		aByteOfTheRemoteAddress = serverAddress >> 16;
+		theRemoteAddress[1]= aByteOfTheRemoteAddress;
+		aByteOfTheRemoteAddress = serverAddress >> 24;
+		theRemoteAddress[0]= aByteOfTheRemoteAddress;
+		aSuplMsgContent->iSuplSessionIdContent->iSlpSessionIdContent->iSlpAddressContent->iIpAddressContent->iIpAddress.Copy(theRemoteAddress);
+		}
+	}
+
+
+void CSuplProtocolSession::ReadSuplMessage()
+	{
+	iTimer->Cancel();
+	// Start "listen" timer
+	iTimer->Start(KProtocolTimeout, KProtocolTimeout, TCallBack(OnTimerEventL,this));
+	iSuplSocketListener->ReadMessage(iStatus);
+	SetActive();
+	}
+
+
+void CSuplProtocolSession::SendSuplMessageL(TSuplMessageType aSuplMessageType)
+	{
+	iTimer->Cancel();
+	
+	switch(aSuplMessageType)
+		{
+		case ESuplStart:
+			CreateSuplStartMessageL();
+			break;
+
+		case ESuplPosInit:
+			CreatePosInitMessageL();
+			break;
+
+		case ESuplEnd:
+			CreateSuplEndMessageL();
+			break;
+						
+		default:
+			// unexpected message type 
+			User::Leave(KErrGeneral);
+			break;
+		}
+
+	// The encoding process does no set the final length of the encoded message
+	// in the first two bytes of the SUPL message. Do it now.
+    TUint16 encodedMessageLength = iTxBuf.Length();
+	TUint8 oneByteOftheLength = encodedMessageLength;
+	iTxBuf[1] = oneByteOftheLength; //Less significant byte
+	oneByteOftheLength = (encodedMessageLength >> 8);
+	iTxBuf[0] = oneByteOftheLength;
+
+	// Start send timer
+	iTimer->Start(KNetworkTimeout, KNetworkTimeout, TCallBack(OnTimerEventL,this));
+	// Send message
+	iSocket.Write(iTxBuf, iStatus);
+	SetActive();	
+	}
+
+void CSuplProtocolSession::DecodeSuplMessageL(TSuplMessageType aExpectedSuplMessageType)
+	{
+	iTimer->Cancel();
+	if (aExpectedSuplMessageType != DoDecodeMessageL())
+		{
+		iSessionState = EProtocolError;
+		}
+	PrepareSelfTransition();
+	}
+
+void CSuplProtocolSession::ConnectToRemoteServer()
+	{
+	iTimer->Cancel();
+	iTimer->Start(KNetworkTimeout, KNetworkTimeout, TCallBack(OnTimerEventL,this));
+	iSocket.Connect(iAddress,iStatus);
+	iSessionState = EConnectingToRemoteServer;
+	SetActive();
+	}
+
+/**
+TransitionAccordingToRequestStatus()
+This method is called by the CSuplProtocolSession after
+having connected to the remote server to decide if the
+next state must be a waiting state (when there is no request
+for assistance data from the NetSim to service).
+*/
+void CSuplProtocolSession::TransitionAccordingToRequestAvailability()
+	{
+	iTimer->Cancel();
+	if(iAssistanceDataRequestPending)
+		{
+		// Start servicing pending request
+		iAssistanceDataRequestPending = EFalse;
+		iSessionState = EAssistanceDataRequested;
+		PrepareSelfTransition();
+		}
+	else
+		{
+		// Go into a waiting state. Do not self-transition.
+		// CSuplProtocolSession will remain inactive until 
+		// GetAssistanceData() is called by NetSim.
+		iSessionState = EConnectedAwaitingRequest;
+		}
+	}
+
+TInt CSuplProtocolSession::RunError(TInt aError)
+{
+	iObserver->DataSourceNotification(aError);
+	return KErrNone;
+}