diff -r a2efdd544abf -r b47902b73a93 locationrequestmgmt/networkrequesthandler/src/ngmessageswitch.cpp --- /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 + +// LBS-specific +#include +#include +#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(&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(&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(&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(&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::Find(). +*/ +TBool CNGMessageSwitch::IsSessionIdEqual( + const TLbsNetSessionIdInt* aSessionId, + const TNetPosItem& aItem) + { + return (*aSessionId == aItem.iSessionId); + } +/** SessionId comparison for RPointerArray::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); + } + } +