locationrequestmgmt/networkrequesthandler/src/ngmessageswitch.cpp
changeset 0 9cfd9a3ee49c
child 52 29dbbeac905d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/locationrequestmgmt/networkrequesthandler/src/ngmessageswitch.cpp	Tue Feb 02 01:50:39 2010 +0200
@@ -0,0 +1,632 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <e32base.h>
+
+// LBS-specific
+#include <lbs.h>
+#include <lbs/lbslocerrors.h>
+#include "lbsdevloggermacros.h"
+
+#include "lbsprocessuiddefs.h"
+#include "ngmessageswitch.h"
+#include "lbsnetinternalapi.h"
+#include "nrhpanic.h"
+
+
+//
+// CNGMessageSendBufferBase
+//
+
+CNGMessageSendBufferBase::CNGMessageSendBufferBase(RLbsNetChannel& aGatewayChannel, CLbsAdmin& aAdmin) :
+	CActive(EPriorityStandard),
+	iAdmin(aAdmin),
+	iNetGatewayChannel(aGatewayChannel)
+	
+	{
+	CActiveScheduler::Add(this);
+	}
+	
+CNGMessageSendBufferBase::~CNGMessageSendBufferBase()
+	{
+	Cancel();
+	}
+
+void CNGMessageSendBufferBase::RunL()
+	{
+	// This must be implemented by the child class, so leave here
+	User::Leave(KErrNotSupported);
+	}
+
+void CNGMessageSendBufferBase::DoCancel()
+	{
+	iNetGatewayChannel.CancelSendMessageNotification();
+	}
+
+void CNGMessageSendBufferBase::SendMessageToNetwork(const TLbsNetInternalMsgBase& aMessage)
+	{
+	iNetGatewayChannel.SendMessage(aMessage, iStatus);
+	SetActive();
+	}
+	
+//
+// CNGMessageSendBuffer
+//
+
+// Dummy params used for initialising member variables
+const TLbsNetSessionIdInt KInvalidSessionId;
+const TPositionInfo KInvalidPosInfo;
+const TTime KInvalidTTime(0);
+
+
+//
+// CNGMessageSendBuffer
+//
+
+	
+CNGMessageSendBuffer::CNGMessageSendBuffer(RLbsNetChannel& aGatewayChannel, CLbsAdmin& aAdmin) :
+	CNGMessageSendBufferBase(aGatewayChannel, aAdmin),
+	iEmergencyBuffer(2), // two spaces allocated - all we need to process an emergency
+	iEmergencyPrivacyResponseData(KInvalidSessionId, TLbsNetworkEnumInt::EPrivacyResponseUnknown, KErrNone),
+	iEmergencyLocationResponseData(KInvalidSessionId, KErrNone, KInvalidPosInfo, KInvalidTTime)
+	{
+	}
+	
+CNGMessageSendBuffer::~CNGMessageSendBuffer()
+	{
+	iEmergencyBuffer.Reset();
+	iBuffer.ResetAndDestroy();
+	}
+
+CNGMessageSendBuffer* CNGMessageSendBuffer::NewL(RLbsNetChannel& aGatewayChannel, CLbsAdmin& aAdmin)
+	{
+	CNGMessageSendBuffer* self = new (ELeave) CNGMessageSendBuffer(aGatewayChannel, aAdmin);
+	return self;
+	}
+	
+void CNGMessageSendBuffer::RunL()
+	{
+	User::LeaveIfError(iStatus.Int());
+	
+	// Send the next message in the buffer,
+	// if there is one there.
+	if (iEmergencyBuffer.Count() > 0)
+		{
+		// Send the emergency related message to the Network Gateway
+		TLbsNetInternalMsgBase* msg = iEmergencyBuffer[0];
+		SendMessageToNetwork(*msg);
+		iEmergencyBuffer.Remove(0);
+		}
+	else if (iBuffer.Count() > 0)
+		{
+		// Send the message to the Network Gateway
+		TLbsNetInternalMsgBase* msg = iBuffer[0];
+		SendMessageToNetwork(*msg);
+		
+		// Remove and delete the item from the buffer if it was a "newed" one
+		iBuffer.Remove(0);
+		delete msg;
+		}
+	}
+
+/* Error function that catches the leave from RunL.
+
+For this class, it is not a fatal error if the property
+returns an error, so only log the error with LBS devlogger.
+*/
+TInt CNGMessageSendBuffer::RunError(TInt aError)
+	{
+	LBSLOG_ERR2(ELogP3, "CNGMessageSendBuffer::RunError : %d", aError);
+	return KErrNone;
+	}
+
+void CNGMessageSendBuffer::BufferData(TLbsNetInternalMsgBase* aData)
+	{	
+	// Add the data to the buffer
+	iBuffer.Append(aData);
+	}
+
+void CNGMessageSendBuffer::BufferEmergencyData(TLbsNetInternalMsgBase* aData)
+	{	
+	// Add the data to the emergency buffer
+	TInt err = iEmergencyBuffer.Append(aData);
+	// there should always be enough space in this array of pointers because we pre-alloated
+	__ASSERT_DEBUG(KErrNone == err, Panic(ENrhPanicOOMWhenProcessingEmergency));
+
+	}
+	
+	
+void CNGMessageSendBuffer::SendNetLocResponseToNetwork(
+		const TLbsNetSessionIdInt& aSessionId, 
+		TInt aCompletionCode,
+		const TPositionInfoBase& aPosInfo,
+		const TTime& aTimeStamp,
+		TBool aEmergency)
+	{
+	TLbsNetLocationResponseMsg msg(aSessionId,
+								   aCompletionCode,
+								   aPosInfo,
+								   aTimeStamp);
+
+	if (!IsActive())
+		{
+		SendMessageToNetwork(msg);
+		}
+	else
+		{
+		TLbsNetLocationResponseMsg* bufMsg = NULL;
+		if (aEmergency)
+			{
+			iEmergencyLocationResponseData = msg;
+			bufMsg = &iEmergencyLocationResponseData;
+			BufferEmergencyData(bufMsg);	
+			}
+		else
+			{
+			bufMsg = new TLbsNetLocationResponseMsg(msg);
+			if (bufMsg)
+				{
+				BufferData(bufMsg);	
+				}
+			else
+				{
+				LBSLOG_ERR(ELogP3, "CNGMessageSendBuffer::SendNetLocResponseToNetwork: Failed to allocate memory.");
+				}
+			}
+				
+		// coverity [memory_leak]
+		// we do not delete bufMsg here as it is now owned by iBuffer
+		}
+	}
+	
+void CNGMessageSendBuffer::SendMtlrResponseToNetwork(
+		const TLbsNetSessionIdInt& aSessionId, 
+		TLbsNetworkEnumInt::TLbsPrivacyResponseInt aResult,
+		TInt /* aReason */,
+		TBool aEmergency)
+	{
+	
+	TLbsNetMtLrReponseMsg* bufMsg = NULL;
+	
+	TLbsNetMtLrReponseMsg msg(aSessionId, aResult, KErrNone);
+	
+	if (!IsActive())
+		{
+		SendMessageToNetwork(msg);
+		}
+	else
+		{
+
+		if (aEmergency)
+			{
+			iEmergencyPrivacyResponseData = msg;
+			bufMsg = &iEmergencyPrivacyResponseData;
+			BufferEmergencyData(bufMsg);	
+			}
+		else
+			{
+			bufMsg = new TLbsNetMtLrReponseMsg(msg);
+			if (bufMsg)
+				{
+				BufferData(bufMsg);	
+				}
+			else
+				{
+				LBSLOG_ERR(ELogP3, "CNGMessageSendBuffer::SendMtlrResponseToNetwork: Failed to allocate memory.");
+				}
+			}
+	
+		// coverity [memory_leak]
+		// we do not delete bufMsg here as it is now owned by iBuffer
+		}	
+	}
+	
+void CNGMessageSendBuffer::SendX3pRequestToNetwork(
+		const TLbsNetSessionIdInt& aSessionId,
+		const TDesC& aDestId,
+		TUint aTransmitPriority,
+		const TLbsNetPosRequestOptionsTechnologyInt& aOptions)
+	{
+	TLbsNetTransmitLocationRequestMsg msg(aSessionId, 
+										  aDestId, 
+										  aTransmitPriority,
+										  aOptions);	
+	
+
+	if (!IsActive())
+		{
+		SendMessageToNetwork(msg);
+		}
+	else
+		{
+		TLbsNetTransmitLocationRequestMsg* bufMsg = new TLbsNetTransmitLocationRequestMsg(msg);
+		if (bufMsg)
+			{
+			BufferData(bufMsg);	
+			}
+		else
+			{
+			LBSLOG_ERR(ELogP3, "CNGMessageSendBuffer::SendX3pRequestToNetwork: Failed to allocate memory.");
+			}
+		
+		// coverity [memory_leak]
+		// we do not delete bufMsg here as it is now owned by iBuffer
+		}	
+	}
+	
+void CNGMessageSendBuffer::SendX3pCancelToNetwork(
+		const TLbsNetSessionIdInt& aSessionId,
+		TInt aReason)
+	{
+	TLbsNetTransmitLocationCancelMsg msg(aSessionId, aReason);
+
+	if (!IsActive())
+		{
+		SendMessageToNetwork(msg);
+		}
+	else
+		{
+		TLbsNetTransmitLocationCancelMsg* bufMsg = new TLbsNetTransmitLocationCancelMsg(msg);
+		if (bufMsg)
+			{
+			BufferData(bufMsg);	
+			}
+		else
+			{
+			LBSLOG_ERR(ELogP3, "CNGMessageSendBuffer::SendX3pCancelToNetwork: Failed to allocate memory.");
+			}
+		
+		// coverity [memory_leak]
+		// we do not delete bufMsg here as it is now owned by iBuffer
+		}	
+	}
+
+void CNGMessageSendBuffer::SendExternalLocateCancelToNetwork(const TLbsNetSessionIdInt& aSessionId,
+												  TInt aReason)
+	{
+	TLbsNetCancelFromPrivacyControllerMsg msg(aSessionId, 
+											 aReason);
+
+	if (!IsActive())
+		{
+		SendMessageToNetwork(msg);
+		}
+	else
+		{
+		TLbsNetCancelFromPrivacyControllerMsg* bufMsg = new TLbsNetCancelFromPrivacyControllerMsg(msg);
+		if (bufMsg)
+			{
+			BufferData(bufMsg);	
+			}
+		else
+			{
+			LBSLOG_ERR(ELogP3, "CNGMessageSendBuffer::SendExternalLocateCancelToNetwor: Failed to allocate memory.");
+			}
+        
+		// coverity [memory_leak]
+        // we do not delete bufMsg here as it is now owned by iBuffer
+		}	
+	}
+
+
+//
+// CNGMessageSwitch
+//	
+
+CNGMessageSwitch::CNGMessageSwitch(CLbsAdmin& aAdmin):	
+	iAdmin(aAdmin)
+    {	
+    }
+    
+CNGMessageSwitch* CNGMessageSwitch::NewL(CLbsAdmin& aAdmin)
+    {
+	CNGMessageSwitch* self = new (ELeave) CNGMessageSwitch(aAdmin);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);	
+	return(self);
+    }
+        
+void CNGMessageSwitch::ConstructL()
+    {
+    iObservers.ReserveL(2);
+    iNetworkGateway.OpenL(RLbsNetChannel::EChannelNRH2NG, *this);
+    	
+    iNetworkGatewaySendBuffer = CNGMessageSendBuffer::NewL(iNetworkGateway, iAdmin);
+
+    }
+    
+CNGMessageSwitch::~CNGMessageSwitch()
+    {
+
+    iRefPosBuffer.Close();
+    
+    iFNPPosBuffer.ResetAndDestroy();
+
+    delete iNetworkGatewaySendBuffer;
+
+    iNetworkGateway.Close();
+    
+    iObservers.Close();
+    }
+    
+TInt CNGMessageSwitch::RegisterObserver(MNGMessageSwitchObserver* aObserver)
+    {
+	return iObservers.Append(aObserver);
+    }
+
+void CNGMessageSwitch::SendX3pRequest(const TLbsNetSessionIdInt& aSessionId,
+									  const TDesC& aDestId,
+									  TUint aTransmitPriority,
+									  const TLbsNetPosRequestOptionsTechnologyInt& aOptions)
+    {
+    iNetworkGatewaySendBuffer->SendX3pRequestToNetwork(aSessionId, aDestId, aTransmitPriority, aOptions);
+    }
+
+void CNGMessageSwitch::SendX3pCancel(const TLbsNetSessionIdInt& aSessionId,
+									 TInt aReason)
+    {
+    iNetworkGatewaySendBuffer->SendX3pCancelToNetwork(aSessionId, aReason);
+    }
+        
+void CNGMessageSwitch::SendMTLRResponse(const TLbsNetSessionIdInt& aSessionId, 
+										TLbsNetworkEnumInt::TLbsPrivacyResponseInt aResult,
+										TInt aReason,
+										TBool aEmergency)
+    {
+    iNetworkGatewaySendBuffer->SendMtlrResponseToNetwork(aSessionId, aResult, aReason, aEmergency);
+    }
+void CNGMessageSwitch::SendExternalLocateCancel(const TLbsNetSessionIdInt& aSessionId, TInt aReason)
+	{
+	iNetworkGatewaySendBuffer->SendExternalLocateCancelToNetwork(aSessionId, aReason);
+	}
+
+void CNGMessageSwitch::SendNetLocResponse(
+		const TLbsNetSessionIdInt& aSessionId, 
+		TInt aCompletionCode,
+		const TLbsNetPosRequestQualityInt& aRequestQuality,
+		const TPositionInfoBase& aPosInfo,
+		const TTime& aTimeStamp,
+		TBool aEmergency)
+	{
+	// Send a Network Location Response to the network
+	iNetworkGatewaySendBuffer->SendNetLocResponseToNetwork(aSessionId, 
+														aCompletionCode,
+														aPosInfo, 
+														aTimeStamp,
+														aEmergency);
+	
+	// Let the observers know what the quality criteria were, so that if
+	// the network modifies teht final position the client can see if it
+	// matches the orignal criteria.
+	const TInt count = iObservers.Count();
+	for (TInt i = 0; i < count; i++)
+		{
+		iObservers[i]->OnNetLocResponse(aSessionId,aRequestQuality);
+		}
+	}
+
+/**
+ From MLbsNetChannelObserver.
+ Called when a message is sent by the Network Gateway.
+ */    
+void CNGMessageSwitch::ProcessNetChannelMessage(RLbsNetChannel::TLbsNetChannelId aChannelId, const TLbsNetInternalMsgBase& aMessage)
+	{
+	__ASSERT_DEBUG(aChannelId == RLbsNetChannel::EChannelNRH2NG, Panic(ENrhPanicUnexpectedNetChannelId));
+	(void) aChannelId;
+    
+	switch(aMessage.Type())
+		{
+		case TLbsNetInternalMsgBase::ELocationRequest:
+			{
+			const TLbsNetLocationRequestMsg* msg = 
+							static_cast<const TLbsNetLocationRequestMsg*>(&aMessage);
+			const TInt count = iObservers.Count();
+			// for an NI the REF location may arrive before the location request
+			TPositionInfo posInfo;
+			TInt err = GetNetworkReferencePosition(msg->SessionId(), posInfo);
+
+			for (TInt i = 0; i < count; i++)
+				{
+				iObservers[i]->OnNetLocRequest(msg->SessionId(), 
+														msg->Method(),
+														msg->Service(), 
+														msg->IsEmergency(), 
+														msg->Quality());
+				if (KErrNone == err) // if no error then there is a reference position so pass it on
+					{
+					iObservers[i]->OnNetLocReferenceUpdate(msg->SessionId(), posInfo);
+					}
+				}
+			break;
+			}
+		   
+		case TLbsNetInternalMsgBase::ESessionComplete:
+			{
+			const TLbsNetSessionCompleteMsg* msg = 
+						static_cast<const TLbsNetSessionCompleteMsg*>(&aMessage);
+
+			const TInt count = iObservers.Count();
+			for (TInt i = 0; i < count; i++)
+				{
+				iObservers[i]->OnSessionComplete(msg->SessionId(), 
+												 msg->Reason());
+				}
+
+			// We know the request session has finished now, so remove
+			// any buffered reference or final network positions.
+			RemoveBufferedNetworkPositions(msg->SessionId());
+			break;
+			}
+		   
+		case TLbsNetInternalMsgBase::EPrivacyRequest: 
+			{
+			const TLbsNetMtLrRequestMsg* msg = 
+						static_cast<const TLbsNetMtLrRequestMsg*>(&aMessage);
+
+			const TInt count = iObservers.Count();
+			for (TInt i = 0; i < count; i++)
+				{
+				iObservers[i]->OnMTLRRequest(msg->SessionId(), 
+										 	 TLbsNetworkEnumInt::EServiceMobileTerminated, 
+										 	 msg->IsEmergency(),
+											 msg->RequestInfo(),
+											 msg->Privacy());
+				}
+			break;
+			}
+
+		case TLbsNetInternalMsgBase::ENetworkLocationUpdate:
+				{
+				const TLbsNetLocationUpdateMsg * msg = 
+							static_cast<const TLbsNetLocationUpdateMsg*>(&aMessage);
+				// its either a REF location or a FNP
+				const TPositionInfoBase& positionInfo =  msg->PositionInfo();
+				
+				TPositionModuleInfo::TTechnologyType techType = positionInfo.PositionMode();
+			
+				const TInt count = iObservers.Count();
+				
+						
+				if (TPositionModuleInfo::ETechnologyNetwork == techType)
+					{ // reference position add to ref pos list 
+					TNetPosItem item;
+					item.iSessionId = msg->SessionId();
+					Mem::Copy(&item.iPosInfo, &positionInfo, positionInfo.PositionClassSize());
+					
+					// OOM  - do nothing here - just ignore the error which results in the REF pos 
+					// not being saved. Note we do enure that the mobiles position
+					// does get sent out to the network - its juts means that the callback
+					// that delivers the REF pos to the privacy system does not happen!
+					iRefPosBuffer.Append(item);
+					
+					for (TInt i = 0; i < count; i++)
+						{
+						iObservers[i]->OnNetLocReferenceUpdate(msg->SessionId(), positionInfo);
+						}
+					}
+				else
+					{ 
+					// save  FNP here - for processing 
+					// completion of X3Ps when session completes
+					TNetFNPPosItem* item = new TNetFNPPosItem();
+					if (item == NULL)
+						{
+						// OOM  - do nothing here - just discard the FNP.. 
+						// Note thats OK becuase we don't need to save the FNP for tp process 
+						// emergencies just X3Ps. 
+						}
+					else
+						{
+						item->iSessionId = msg->SessionId();
+					
+						Mem::Copy(&item->iPosInfo, &positionInfo, positionInfo.PositionClassSize());
+						iFNPPosBuffer.Append(item); // here, ownership passes to pointer array!
+						}
+					for (TInt i = 0; i < count; i++)
+						{
+						iObservers[i]->OnNetLocFinalUpdate(msg->SessionId(), positionInfo);
+						}
+					}
+				break;
+				}
+		case TLbsNetInternalMsgBase::ETransmitLocationRequest:// outgoing only
+		case TLbsNetInternalMsgBase::ELocationResponse:       // outgoing only
+		case TLbsNetInternalMsgBase::EPrivacyResponse:        // outgoing only
+		default:
+			{
+			break;
+			}
+		}
+    }
+
+
+/** SessionId comparison for RArray<TNetPosItem>::Find().
+*/
+TBool CNGMessageSwitch::IsSessionIdEqual(
+		const TLbsNetSessionIdInt* aSessionId,
+    	const TNetPosItem& aItem)
+	{
+	return (*aSessionId == aItem.iSessionId);
+	}
+/** SessionId comparison for RPointerArray<TNetFNPPosItem>::Find().
+*/
+TBool CNGMessageSwitch::IsFNPSessionIdEqual(
+		const TLbsNetSessionIdInt* aSessionId,
+    	const TNetFNPPosItem& aItem)
+	{
+	return (*aSessionId == aItem.iSessionId);
+	}
+ 
+/**
+*/
+TInt CNGMessageSwitch::GetNetworkReferencePosition(
+		const TLbsNetSessionIdInt& aSessionId,
+		TPositionInfoBase& aPosInfo)
+	{
+	// Try to find the update if it has already happened.
+	TInt index = iRefPosBuffer.Find(aSessionId, IsSessionIdEqual);
+	if (index >= 0)
+		{
+		const TNetPosItem& item = iRefPosBuffer[index];
+		Mem::Copy(&aPosInfo, &item.iPosInfo, item.iPosInfo.PositionClassSize());
+		return KErrNone;
+		}
+	else
+		{
+		return KErrNotFound;
+		}
+	}
+
+/**
+*/
+TInt CNGMessageSwitch::GetNetworkFinalPosition(
+		const TLbsNetSessionIdInt& aSessionId,
+		TPositionInfoBase& aPosInfo)
+	{
+	// Try to find the update if it has already happened.
+	TInt index = iFNPPosBuffer.Find(aSessionId, IsFNPSessionIdEqual);
+	if (index >= 0)
+		{
+		const TNetFNPPosItem* item = iFNPPosBuffer[index];
+		Mem::Copy(&aPosInfo, &item->iPosInfo, item->iPosInfo.PositionClassSize());
+		return KErrNone;
+		}
+	else
+		{
+		return KErrNotFound;
+		}
+	}
+
+void CNGMessageSwitch::RemoveBufferedNetworkPositions(const TLbsNetSessionIdInt& aSessionId)
+	{
+	// Remove any reference positions
+	TInt index = iRefPosBuffer.Find(aSessionId, IsSessionIdEqual);
+	while (index >= 0)
+		{
+		iRefPosBuffer.Remove(index);
+		index = iRefPosBuffer.Find(aSessionId, IsSessionIdEqual);
+		}
+	
+	index = iFNPPosBuffer.Find(aSessionId, IsFNPSessionIdEqual);
+	while (index >= 0)
+		{
+		TNetFNPPosItem* fnpPsItem = iFNPPosBuffer[index];
+		delete fnpPsItem;
+		iFNPPosBuffer.Remove(index);
+		index = iFNPPosBuffer.Find(aSessionId, IsFNPSessionIdEqual);
+		}
+	}
+