--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/locationrequestmgmt/networkrequesthandler/src/ngmessageswitch.cpp Fri Jun 04 10:34:15 2010 +0100
@@ -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);
+ }
+ }
+