diff -r 9f5ae1728557 -r db3f5fa34ec7 messagingfw/wappushfw/pushwatcher/src/CLWatcher.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/messagingfw/wappushfw/pushwatcher/src/CLWatcher.cpp Wed Nov 03 22:41:46 2010 +0530 @@ -0,0 +1,486 @@ +// Copyright (c) 2000-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: +// + +// System Include +#include +#include +#include "CLWatcher.h" +#include +#include "pushdispatcher.h" +#include +#include + +// User Include +#include "CWapPushMessageFilter.h" +#include "CWapPushFilterUtils.h" +#include "CUriListLookup.h" + + +const TUid KUidWapUriLookup = {0x20009D3F}; + +/** + * Constructor + * @param aLog a interface for run-time logging + * @param aManager a interface for the connection manager + */ +CCLWatcherBase::CCLWatcherBase(MWapPushLog& aLog, MConnManObserver& aManager) : +CActive(CActive::EPriorityStandard), + iState(EWaiting), + iLog(aLog), + iManager(aManager), + iCachedFilter(EFalse) + { + } + +/** + * Destructor + */ +CCLWatcherBase::~CCLWatcherBase() + { + Cancel(); + delete iWapCLServ; + delete iHeaders; + delete iBody; + delete iCurrentMessage; + delete iPushMsgFilter; + delete iServerAddress; + delete static_cast(iUriListLookup); + } + +/** + * Construct the connectionless watcher base class + * Add this object to the active scheduler and make it active. + * A wap stack session is created, construction of the connectionless + * connection is performed in the virtual SetupCLWatcherL() method. + * Concrete unsecure/secure watchers connect to different ports and require + * different setup. + */ +void CCLWatcherBase::ConstructL() + { + CActiveScheduler::Add(this); + iWapCLServ = CWapBoundCLPushService::NewL(); + SetupCLWatcherL(); + + IdleComplete(); + } + + +/** + * Asynchronous request complete + * Utility to make a asynchronous request has been complete synchronously. + */ +void CCLWatcherBase::IdleComplete() + { + if( !IsActive() ) + { + TRequestStatus* pS=&iStatus; + User::RequestComplete(pS,0); + SetActive(); + } + } + +/** + * If RunL() leaves, this gets called + * @param aError Error passed into this function + * + * EWapErrPluginNotFound (-10018) indicates that the plug-in server was unable to + * find the requested plug-in. +*/ +TInt CCLWatcherBase::RunError(TInt aError) + { + __LOG_DEBUG("CCLWatcherBase::RunError called"); + __LOG_ERROR_DEBUG("Error occurred", aError); + // Set to waiting state & reset... + iState = EWaiting; + + delete iHeaders; + iHeaders = NULL; + delete iBody; + iBody = NULL; + delete iCurrentMessage; + iCurrentMessage = NULL; + + IdleComplete(); + aError = KErrNone; + return(aError); + } + +/** + * Handle the completion of a request that is active + * + * CL Watchers are always running. + * States: + * Waiting: Will call the aysnchronous call UnitWaitPush() + * Receiving: Collects the Push Message + * Filtering: Filters the Push Message + * Dispatching: Dispatches the Push Message + * + * The EMadeRequest state is necessary to differentiate whether an async + * request has been made (and therefore should be cancelled). + */ +void CCLWatcherBase::RunL() + { + switch (iState) + { + case EWaiting: + WaitForPushL(); + iState = EReceiving; + break; + case EReceiving: + ReceivePushL(); + break; + case EFiltering: + FilterMessageL(); + iState = EDispatching; + break; + case EDispatching: + if (!iPassedFilter) + { + delete iCurrentMessage; + iCurrentMessage = NULL; + IdleComplete(); + } + else + DispatchMessageL(); + iState = EWaiting; + break; + default: + Panic(EUnknownState); + User::Panic(_L("WapPush ConnectionLess Watcher"), KErrNotSupported); + break; + + } + } + + +/** + * Cancel any asynchronous requests made by this active object + * This shouldn't be called under normal circumstances. If it is called, + * this means that we are no longer running and push messages are no longer + * being collected. + * + * This is called when the testcode destroys the connection manager. + */ +void CCLWatcherBase::DoCancel() + { + switch (iState) + { + case EWaiting: + case EReceiving: + if (iWapCLServ && iStatus.Int() == KRequestPending) + iWapCLServ->CancelAwaitPush(); + break; + case EFiltering: + case EDispatching: + if (iStatus.Int() == KRequestPending && iPushMsgFilter) + { + iPushMsgFilter->CancelFilter(); + } + break; + default: + break; + } + } + + + +/** + * Make an asynchronous request for a push message from the WAP Stack + */ +void CCLWatcherBase::WaitForPushL() + { + __LOG_DEBUG("CLWatcher: UnitWaitPush"); + User::LeaveIfError(iWapCLServ->AwaitPush(iHeadersBuf, iBodyBuf, iPushID, iStatus)); + SetActive(); + } + +/** + * Wrap the message up in a push message + * If there is more data to come, issue another request to run again + * to wait for the rest. + * If it's all here, wrap the message up in a CPushMessage Object and set the state to EFiltering + * + */ +void CCLWatcherBase::ReceivePushL() + { + __LOG_DEBUG("CLWatcher: ReceivePush"); + // If we're returned something unexpected, leave + if (iStatus.Int() != Wap::EMoreData && iStatus.Int() != KErrNone) + User::Leave(iStatus.Int()); + + if ( (!iBody) && (!iHeaders) ) + { + iBody = HBufC8::NewL(iBodyBuf.Length()); + iBody->Des().Copy(iBodyBuf); + iBodyBuf.Zero(); + + iHeaders = HBufC8::NewL(iHeadersBuf.Length()); + iHeaders->Des().Copy(iHeadersBuf); + iHeadersBuf.Zero(); + } + else + { + if (iBody && iBodyBuf.Length()) + { + iBody=iBody->ReAllocL(iBody->Length() + iBodyBuf.Length()); + iBody->Des().Append(iBodyBuf); + iBodyBuf.Zero(); + } + + if (iHeaders && iHeadersBuf.Length()) + { + iHeaders=iHeaders->ReAllocL(iHeaders->Length() + iHeadersBuf.Length()); + iHeaders->Des().Append(iHeadersBuf); + iHeadersBuf.Zero(); + } + } + + // Get the remote server address. + if (!iServerAddress) + { + iWapCLServ->GetServerAddress(iServerAddress); + } + + // we've got a complete message + if (iStatus.Int() == KErrNone) + { + TInt err = KErrNone; + if(!iUriListLookup) + { + //The Uri lookup plugin is not loaded. Load the plugin. + TRAP(err, iUriListLookup = REINTERPRET_CAST(MUriListLookup*, REComSession::CreateImplementationL(KUidWapUriLookup, _FOFF(MUriListLookup,iEcomDtorID)))); + } + if(err == KErrNone && iUriListLookup) // Plugin loading was successful + { + TPtrC8 ptr(iServerAddress->Des()); + InetUriList::TListType listType; + + TInt error = iUriListLookup->GetListType(ptr, listType); + + // Source Uri is in blacklist + if(error != InetUriList::KErrUriNotFound && listType == InetUriList::EBlackList) + { + __LOG_DEBUG("Received a message from blacklisted source"); + + delete iBody; + iBody = NULL; + + delete iHeaders; + iHeaders = NULL; + + delete iServerAddress; + iServerAddress = NULL; + + iState = EWaiting; + + IdleComplete(); + return; + } + + // Source URI is either in whitelist or unknown + if(error == InetUriList::KErrUriNotFound || listType == InetUriList::EWhiteList) + { + iCurrentMessage = CPushMessage::NewL(iHeaders, iBody, iPushID(), iServerAddress); + + if(error != InetUriList::KErrUriNotFound && listType == InetUriList::EWhiteList) + { + __LOG_DEBUG("Received a message from a whitelisted source"); + iCurrentMessage->SetMessageAllowed(ETrue); + } + else if(error == InetUriList::KErrUriNotFound) + { + __LOG_DEBUG("Received a message from unknown source"); + iCurrentMessage->SetMessageAllowed(EFalse); + } + } + + } + + else // Plugin loading was unsuccessful + { + // The URI should be sent as if it were a trusted one. + iCurrentMessage = CPushMessage::NewL(iHeaders, iBody, iPushID(), iServerAddress); + iCurrentMessage->SetMessageAllowed(ETrue); + } + + // Push Message took ownership, so just NULL + iHeaders = NULL; + iBody = NULL; + iServerAddress=NULL; + __LOG_DEBUG("Received complete push message\n:"); + __LOG_MSG_DEBUG(*iCurrentMessage); + } + + // Set next state + if (iStatus.Int() == Wap::EMoreData) + iState = EWaiting; + else + iState = EFiltering; + + IdleComplete(); + } + + +/** + Handles result from the filter plugin. + Load a push message filter if one is available and hold + If the filter plugin accepts the message then it is Dispatched. Otherwise the + message is deleted. + In either case the watcher will then start waiting for the next message +*/ +void CCLWatcherBase::FilterMessageL() + { + // Cache Filter if it exists + if (!iCachedFilter) + { + TRAPD(err, iPushMsgFilter = CWapPushFilterUtils::GetFilterPluginL()); + if (err && err != EWapErrPluginNotFound && err != KEComErrNoInterfaceIdentified) + User::Leave(err); + iCachedFilter = ETrue; + } + + if (iPushMsgFilter) + // only try and filter a message if a filter plugin is available + { + iPassedFilter = EFalse; + iPushMsgFilter->FilterMessage(*iCurrentMessage,iStatus,iPassedFilter); + SetActive(); + } + else + { + iPassedFilter = ETrue; + IdleComplete(); + } + } + +/** + Dispatches the current message being processed and then sets the state to + start waiting for the next message. +*/ +void CCLWatcherBase::DispatchMessageL() + { + __ASSERT_ALWAYS(iCurrentMessage, Panic(ENoMessageExists)); + TPtrC8 rAppURI; + TInt rAppID; + TBool rIsAnInt; + CPushHandlerBase* appHandlerPtr=NULL; + + if(iCurrentMessage->GetAppIdL(rAppURI, rAppID, rIsAnInt)) + { + if(rIsAnInt) + { + CPushHandlerBase& appHandler = PushAppDispatcher::GetHandlerL(rAppID, iLog, iManager); + appHandlerPtr= &appHandler; + } + else + { + CPushHandlerBase& appHandler = PushAppDispatcher::GetHandlerL(rAppURI, iLog, iManager); + appHandlerPtr= &appHandler; + } + } + else + { // If no AppID defined, use the default User Agent + CPushHandlerBase& appHandler = PushAppDispatcher::GetHandlerL(KUserAgentAppHandler, iLog, iManager); + appHandlerPtr= &appHandler; + } + + __ASSERT_DEBUG(appHandlerPtr!=NULL, User::Invariant()); + if (appHandlerPtr) + { + // Plugin (HandleMessageL call) will take complete ownership of the iCurrentMessage. + // The iCurrentMessage needs to be set to NULL before calling HandleMessageL + // otherwise a leave from HandleMessageL will cause it to delete twice, + // one in HandleMessageL and second time in RunError + CPushMessage* tmpCurrentMessage = iCurrentMessage; + iCurrentMessage = NULL; + appHandlerPtr->HandleMessageL(tmpCurrentMessage); + } + + IdleComplete(); + } + + +void CCLWatcherBase::Panic(TCLWatcherBasePanic aPanicCode) + { + _LIT(KCLWatcherBase,"CLWatcherBase"); + User::Panic(KCLWatcherBase,aPanicCode); + } + +/** + * Factory construction method + * Use this method to allocate and construct a new CCLUnsecureWatcher object + * @param aLog a interface for run-time logging + * @param aManager a interface for the connection manager + */ +CCLUnsecureWatcher* CCLUnsecureWatcher::NewL(MWapPushLog& aLog, MConnManObserver& aManager) + { + CCLUnsecureWatcher* self = new (ELeave) CCLUnsecureWatcher(aLog, aManager); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); //self + return self; + } + +/** + * Connect to the Unsecure WAP Push port + */ +void CCLUnsecureWatcher::SetupCLWatcherL() + { + User::LeaveIfError(iWapCLServ->Connect(Wap::EAll, KPushPortUnsecure, EFalse)); + } + + +/** + * Desctructor + */ +CCLUnsecureWatcher::~CCLUnsecureWatcher() + { + } + + + +/** + * Factory construction method + * Use this method to allocate and construct a new CCLSecureWatcher object + * @param aLog a interface for run-time logging + * @param aManager a interface for the connection manager + */ +CCLSecureWatcher* CCLSecureWatcher::NewL(MWapPushLog& aLog, MConnManObserver& aManager) + { + CCLSecureWatcher* self = new (ELeave) CCLSecureWatcher(aLog, aManager); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +CCLSecureWatcher::~CCLSecureWatcher() + { + + } + +/** + * Opens the Connectionless session on the stack. For security, a certificate is not + * negotiated with the Gateway. A message will come in, it will be encrypted, the stack + * decrypts based on the headers in the message. + */ +void CCLSecureWatcher::SetupCLWatcherL() + { + User::LeaveIfError(iWapCLServ->Connect(Wap::EAll,KPushPortSecure, ETrue)); + } + + + +