messagingfw/wappushfw/pushwatcher/src/CLWatcher.cpp
changeset 0 8e480a14352b
equal deleted inserted replaced
-1:000000000000 0:8e480a14352b
       
     1 // Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15     
       
    16 // System Include
       
    17 #include <wapmessage.h>
       
    18 #include <wapmsgerr.h>
       
    19 #include "CLWatcher.h"
       
    20 #include <push/pushmessage.h>
       
    21 #include "pushdispatcher.h"
       
    22 #include <push/cpushhandlerbase.h>
       
    23 #include <ecom/ecom.h>
       
    24 
       
    25 // User Include
       
    26 #include "CWapPushMessageFilter.h"
       
    27 #include "CWapPushFilterUtils.h"
       
    28 #include "CUriListLookup.h"
       
    29 
       
    30 
       
    31 const TUid KUidWapUriLookup = {0x20009D3F};
       
    32 
       
    33 /**
       
    34  * Constructor 
       
    35  * @param aLog a interface for run-time logging
       
    36  * @param aManager a interface for the connection manager
       
    37  */
       
    38 CCLWatcherBase::CCLWatcherBase(MWapPushLog& aLog, MConnManObserver& aManager) :	
       
    39 CActive(CActive::EPriorityStandard), 
       
    40 	iState(EWaiting),
       
    41 	iLog(aLog), 
       
    42 	iManager(aManager),
       
    43 	iCachedFilter(EFalse)
       
    44 	{
       
    45 	}
       
    46 
       
    47 /**
       
    48  * Destructor
       
    49  */
       
    50 CCLWatcherBase::~CCLWatcherBase()
       
    51 	{
       
    52 	Cancel();
       
    53 	delete iWapCLServ;
       
    54 	delete iHeaders;
       
    55 	delete iBody;
       
    56 	delete iCurrentMessage;
       
    57 	delete iPushMsgFilter;
       
    58 	delete iServerAddress;
       
    59 	delete static_cast<CUriListLookup*>(iUriListLookup);
       
    60 	}
       
    61 
       
    62 /**
       
    63  * Construct the connectionless watcher base class
       
    64  * Add this object to the active scheduler and make it active. 
       
    65  * A wap stack session is created, construction of the connectionless 
       
    66  * connection is performed in the virtual SetupCLWatcherL() method. 
       
    67  * Concrete unsecure/secure watchers connect to different ports and require
       
    68  * different setup.
       
    69  */
       
    70 void CCLWatcherBase::ConstructL()
       
    71 	{
       
    72 	CActiveScheduler::Add(this);
       
    73 	iWapCLServ = CWapBoundCLPushService::NewL();
       
    74 	SetupCLWatcherL();
       
    75 	
       
    76 	IdleComplete();
       
    77 	}
       
    78 
       
    79 
       
    80 /**
       
    81  * Asynchronous request complete
       
    82  * Utility to make a asynchronous request has been complete synchronously. 
       
    83  */
       
    84 void CCLWatcherBase::IdleComplete()
       
    85 	{
       
    86 	if( !IsActive() )
       
    87 		{
       
    88 		TRequestStatus* pS=&iStatus;
       
    89 		User::RequestComplete(pS,0);
       
    90 		SetActive();
       
    91 		}
       
    92 	}
       
    93 
       
    94 /**
       
    95  * If RunL() leaves, this gets called
       
    96  * @param aError Error passed into this function
       
    97  *
       
    98  * EWapErrPluginNotFound (-10018) indicates that the plug-in server was unable to
       
    99  * find the requested plug-in. 
       
   100 */
       
   101 TInt CCLWatcherBase::RunError(TInt aError)
       
   102 	{
       
   103 	__LOG_DEBUG("CCLWatcherBase::RunError called");
       
   104 	__LOG_ERROR_DEBUG("Error occurred", aError);
       
   105 	//  Set to waiting state & reset...
       
   106  	iState = EWaiting;
       
   107 
       
   108 	delete iHeaders;
       
   109 	iHeaders = NULL;
       
   110 	delete iBody;
       
   111 	iBody = NULL;
       
   112 	delete iCurrentMessage;
       
   113 	iCurrentMessage = NULL;
       
   114 
       
   115 	IdleComplete();
       
   116 	aError = KErrNone;
       
   117 	return(aError);
       
   118 	}
       
   119 
       
   120 /**
       
   121  * Handle the completion of a request that is active
       
   122  * 
       
   123  * CL Watchers are always running.  
       
   124  * States:
       
   125  * Waiting: Will call the aysnchronous call UnitWaitPush()
       
   126  * Receiving: Collects the Push Message
       
   127  * Filtering: Filters the Push Message
       
   128  * Dispatching: Dispatches the Push Message
       
   129  *
       
   130  * The EMadeRequest state is necessary to differentiate whether an async
       
   131  * request has been made (and therefore should be cancelled).
       
   132  */
       
   133 void CCLWatcherBase::RunL()
       
   134 	{
       
   135 	switch (iState)
       
   136 		{
       
   137 		case EWaiting:
       
   138  			WaitForPushL();
       
   139 			iState = EReceiving;
       
   140 			break;
       
   141 		case EReceiving:
       
   142 			ReceivePushL();	
       
   143 			break;
       
   144 		case EFiltering:
       
   145 			FilterMessageL(); 
       
   146 			iState = EDispatching;
       
   147 			break;
       
   148 		case EDispatching:
       
   149 			if (!iPassedFilter)
       
   150 				{
       
   151 				delete iCurrentMessage;
       
   152 				iCurrentMessage = NULL;
       
   153 				IdleComplete();
       
   154 				}
       
   155 			else	
       
   156 				DispatchMessageL();
       
   157 			iState = EWaiting;
       
   158 			break;
       
   159 		default:
       
   160 			Panic(EUnknownState); 
       
   161 			User::Panic(_L("WapPush ConnectionLess Watcher"), KErrNotSupported); 
       
   162 			break;
       
   163 
       
   164 		}
       
   165 	}
       
   166 
       
   167 
       
   168 /**
       
   169  * Cancel any asynchronous requests made by this active object
       
   170  * This shouldn't be called under normal circumstances. If it is called,
       
   171  * this means that we are no longer running and push messages are no longer
       
   172  * being collected.
       
   173  *
       
   174  * This is called when the testcode destroys the connection manager.
       
   175  */
       
   176 void CCLWatcherBase::DoCancel()
       
   177 	{
       
   178 	switch (iState)
       
   179 		{
       
   180 	case EWaiting:
       
   181 	case EReceiving:
       
   182 		if (iWapCLServ && iStatus.Int() == KRequestPending)
       
   183 			iWapCLServ->CancelAwaitPush();
       
   184 			break;
       
   185 	case EFiltering:
       
   186 	case EDispatching:
       
   187 		if (iStatus.Int() == KRequestPending && iPushMsgFilter)
       
   188 			{
       
   189 			iPushMsgFilter->CancelFilter();
       
   190 			}
       
   191 			break;
       
   192 	default:
       
   193 		break;
       
   194 		}
       
   195 	}
       
   196 
       
   197 
       
   198 
       
   199 /**
       
   200  * Make an asynchronous request for a push message from the WAP Stack
       
   201  */
       
   202 void CCLWatcherBase::WaitForPushL()
       
   203 	{
       
   204 	__LOG_DEBUG("CLWatcher: UnitWaitPush");
       
   205 	User::LeaveIfError(iWapCLServ->AwaitPush(iHeadersBuf, iBodyBuf, iPushID, iStatus));
       
   206 	SetActive();
       
   207 	}
       
   208 
       
   209 /**
       
   210  * Wrap the message up in a push message 
       
   211  * If there is more data to come, issue another request to run again 
       
   212  * to wait for the rest.
       
   213  * If it's all here, wrap the message up in a CPushMessage Object and set the state to EFiltering
       
   214  *
       
   215  */
       
   216 void CCLWatcherBase::ReceivePushL()
       
   217 	{
       
   218 	__LOG_DEBUG("CLWatcher: ReceivePush");
       
   219 	// If we're returned something unexpected, leave
       
   220 	if (iStatus.Int() != Wap::EMoreData && iStatus.Int() != KErrNone)
       
   221 		User::Leave(iStatus.Int());
       
   222 
       
   223 	if ( (!iBody) && (!iHeaders) )
       
   224 		{
       
   225 		iBody = HBufC8::NewL(iBodyBuf.Length());
       
   226 		iBody->Des().Copy(iBodyBuf);
       
   227 		iBodyBuf.Zero();
       
   228 
       
   229 		iHeaders = HBufC8::NewL(iHeadersBuf.Length());
       
   230 		iHeaders->Des().Copy(iHeadersBuf);
       
   231 		iHeadersBuf.Zero();
       
   232 		}
       
   233 	else 
       
   234 		{
       
   235 		if (iBody && iBodyBuf.Length())
       
   236 			{
       
   237 			iBody=iBody->ReAllocL(iBody->Length() + iBodyBuf.Length());
       
   238 			iBody->Des().Append(iBodyBuf);
       
   239 			iBodyBuf.Zero();
       
   240 			}
       
   241 
       
   242 		if (iHeaders && iHeadersBuf.Length())
       
   243 			{
       
   244 			iHeaders=iHeaders->ReAllocL(iHeaders->Length() + iHeadersBuf.Length());
       
   245 			iHeaders->Des().Append(iHeadersBuf);
       
   246 			iHeadersBuf.Zero();
       
   247 			}
       
   248 		}
       
   249 	
       
   250 	// Get the remote server address.
       
   251 	if (!iServerAddress)
       
   252 		{
       
   253 		iWapCLServ->GetServerAddress(iServerAddress);
       
   254 		}
       
   255 	
       
   256 	// we've got a complete message
       
   257 	if (iStatus.Int() == KErrNone) 
       
   258 		{
       
   259 		TInt err = KErrNone; 
       
   260 		if(!iUriListLookup)
       
   261 			{
       
   262 			//The Uri lookup plugin is not loaded. Load the plugin.
       
   263 			TRAP(err, iUriListLookup = REINTERPRET_CAST(MUriListLookup*, REComSession::CreateImplementationL(KUidWapUriLookup, _FOFF(MUriListLookup,iEcomDtorID))));
       
   264 			}
       
   265 			if(err == KErrNone && iUriListLookup) // Plugin loading was successful
       
   266 				{
       
   267 				TPtrC8 ptr(iServerAddress->Des());
       
   268 				InetUriList::TListType listType;
       
   269 		
       
   270 				TInt error = iUriListLookup->GetListType(ptr, listType);
       
   271 			
       
   272 				// Source Uri is in blacklist
       
   273 				if(error != InetUriList::KErrUriNotFound && listType == InetUriList::EBlackList)
       
   274 					{
       
   275 					__LOG_DEBUG("Received a message from blacklisted source");
       
   276 	
       
   277 					delete iBody;
       
   278 					iBody = NULL;
       
   279 				
       
   280 					delete iHeaders;
       
   281 					iHeaders = NULL;
       
   282 				
       
   283 					delete iServerAddress;
       
   284 					iServerAddress = NULL;
       
   285 				
       
   286 					iState = EWaiting;
       
   287 								
       
   288 					IdleComplete();
       
   289 					return;
       
   290 					}
       
   291 						
       
   292 				// Source URI is either in whitelist or unknown
       
   293 				if(error == InetUriList::KErrUriNotFound || listType == InetUriList::EWhiteList)
       
   294 					{
       
   295 					iCurrentMessage = CPushMessage::NewL(iHeaders, iBody, iPushID(), iServerAddress);
       
   296 				
       
   297 					if(error != InetUriList::KErrUriNotFound && listType == InetUriList::EWhiteList)
       
   298 						{
       
   299 						__LOG_DEBUG("Received a message from a whitelisted source");
       
   300 						iCurrentMessage->SetMessageAllowed(ETrue);
       
   301 						}
       
   302 					else if(error == InetUriList::KErrUriNotFound)
       
   303 						{
       
   304 						__LOG_DEBUG("Received a message from unknown source");
       
   305 						iCurrentMessage->SetMessageAllowed(EFalse);	
       
   306 						}
       
   307 					}
       
   308 				
       
   309 				}
       
   310 		
       
   311 			else // Plugin loading was unsuccessful
       
   312 				{
       
   313 				// The URI should be sent as if it were a trusted one.
       
   314 				iCurrentMessage = CPushMessage::NewL(iHeaders, iBody, iPushID(), iServerAddress);
       
   315 				iCurrentMessage->SetMessageAllowed(ETrue);
       
   316 				}
       
   317 			
       
   318 		// Push Message took ownership, so just NULL
       
   319 		iHeaders = NULL;
       
   320 		iBody = NULL;
       
   321 		iServerAddress=NULL;
       
   322 		__LOG_DEBUG("Received complete push message\n:");
       
   323 		__LOG_MSG_DEBUG(*iCurrentMessage);
       
   324 		}
       
   325 		
       
   326 	// Set next state
       
   327 	if (iStatus.Int() == Wap::EMoreData)
       
   328 		iState = EWaiting;
       
   329 	else
       
   330 		iState = EFiltering;
       
   331 	
       
   332 	IdleComplete();
       
   333 	}
       
   334 
       
   335 
       
   336 /** 
       
   337 	Handles result from the filter plugin.
       
   338 	Load a push message filter if one is available and hold
       
   339 	If the filter plugin accepts the message then it is Dispatched. Otherwise the
       
   340 	message is deleted.
       
   341 	In either case the watcher will then start waiting for the next message
       
   342 */
       
   343 void CCLWatcherBase::FilterMessageL()
       
   344 	{
       
   345 	// Cache Filter if it exists
       
   346 	if (!iCachedFilter)
       
   347 		{		
       
   348 		TRAPD(err, iPushMsgFilter = CWapPushFilterUtils::GetFilterPluginL()); 
       
   349 		if (err && err != EWapErrPluginNotFound && err != KEComErrNoInterfaceIdentified)
       
   350 			User::Leave(err);
       
   351 		iCachedFilter = ETrue;
       
   352 		}
       
   353 
       
   354 	if (iPushMsgFilter)
       
   355 	// only try and filter a message if a filter plugin is available
       
   356 		{
       
   357 		iPassedFilter = EFalse;
       
   358 		iPushMsgFilter->FilterMessage(*iCurrentMessage,iStatus,iPassedFilter);
       
   359 		SetActive();
       
   360 		}
       
   361 	else 
       
   362 		{
       
   363 		iPassedFilter = ETrue;
       
   364 		IdleComplete();
       
   365 		}
       
   366 	}
       
   367 
       
   368 /** 
       
   369 	Dispatches the current message being processed and then sets the state to
       
   370 	start waiting for the next message.
       
   371 */
       
   372 void CCLWatcherBase::DispatchMessageL()
       
   373 	{
       
   374 	__ASSERT_ALWAYS(iCurrentMessage, Panic(ENoMessageExists));
       
   375 	TPtrC8 rAppURI;
       
   376 	TInt rAppID;
       
   377 	TBool rIsAnInt;
       
   378 	CPushHandlerBase* appHandlerPtr=NULL;
       
   379 
       
   380 	if(iCurrentMessage->GetAppIdL(rAppURI, rAppID, rIsAnInt))
       
   381 		{
       
   382 		if(rIsAnInt)
       
   383 			{
       
   384 			CPushHandlerBase& appHandler = PushAppDispatcher::GetHandlerL(rAppID, iLog, iManager);
       
   385 			appHandlerPtr= &appHandler;
       
   386 			}
       
   387 		else
       
   388 			{
       
   389 			CPushHandlerBase& appHandler = PushAppDispatcher::GetHandlerL(rAppURI, iLog, iManager); 
       
   390 			appHandlerPtr= &appHandler;
       
   391 			}
       
   392 		}
       
   393 	else
       
   394 		{	// If no AppID defined, use the default User Agent
       
   395 			CPushHandlerBase& appHandler = PushAppDispatcher::GetHandlerL(KUserAgentAppHandler, iLog, iManager); 
       
   396 			appHandlerPtr= &appHandler;
       
   397 		}
       
   398 
       
   399 	__ASSERT_DEBUG(appHandlerPtr!=NULL, User::Invariant());
       
   400 	if (appHandlerPtr)
       
   401 		{
       
   402 		// Plugin (HandleMessageL call) will take complete ownership of the iCurrentMessage.
       
   403 		// The iCurrentMessage needs to be set to NULL before calling HandleMessageL
       
   404 		// otherwise a leave from HandleMessageL will cause it to delete twice, 
       
   405 		// one in HandleMessageL and second time in RunError		
       
   406 		CPushMessage* tmpCurrentMessage = iCurrentMessage;
       
   407 		iCurrentMessage = NULL;
       
   408 		appHandlerPtr->HandleMessageL(tmpCurrentMessage);
       
   409 		}
       
   410 			
       
   411 	IdleComplete();
       
   412 	}
       
   413 
       
   414 
       
   415 void CCLWatcherBase::Panic(TCLWatcherBasePanic aPanicCode)
       
   416 	{
       
   417 	_LIT(KCLWatcherBase,"CLWatcherBase");
       
   418 	User::Panic(KCLWatcherBase,aPanicCode);
       
   419 	}
       
   420 
       
   421 /**
       
   422  * Factory construction method
       
   423  * Use this method to allocate and construct a new CCLUnsecureWatcher object
       
   424  * @param aLog a interface for run-time logging
       
   425  * @param aManager a interface for the connection manager
       
   426  */
       
   427 CCLUnsecureWatcher* CCLUnsecureWatcher::NewL(MWapPushLog& aLog, MConnManObserver& aManager)
       
   428 	{
       
   429 	CCLUnsecureWatcher* self = new (ELeave) CCLUnsecureWatcher(aLog, aManager);
       
   430 	CleanupStack::PushL(self);
       
   431 	self->ConstructL();
       
   432 	CleanupStack::Pop(); //self
       
   433 	return self;
       
   434 	}
       
   435 
       
   436 /**
       
   437  * Connect to the Unsecure WAP Push port
       
   438  */
       
   439 void CCLUnsecureWatcher::SetupCLWatcherL()
       
   440 	{
       
   441 	User::LeaveIfError(iWapCLServ->Connect(Wap::EAll, KPushPortUnsecure, EFalse));
       
   442 	}
       
   443 
       
   444 
       
   445 /**
       
   446  * Desctructor
       
   447  */
       
   448 CCLUnsecureWatcher::~CCLUnsecureWatcher()
       
   449 	{
       
   450 	}
       
   451 
       
   452 
       
   453 
       
   454 /**
       
   455  * Factory construction method
       
   456  * Use this method to allocate and construct a new CCLSecureWatcher object
       
   457  * @param aLog a interface for run-time logging
       
   458  * @param aManager a interface for the connection manager
       
   459  */
       
   460 CCLSecureWatcher* CCLSecureWatcher::NewL(MWapPushLog& aLog, MConnManObserver& aManager)
       
   461 	{
       
   462 	CCLSecureWatcher* self = new (ELeave) CCLSecureWatcher(aLog, aManager);
       
   463 	CleanupStack::PushL(self);
       
   464 	self->ConstructL();
       
   465 	CleanupStack::Pop(self);
       
   466 	return self;
       
   467 	}
       
   468 
       
   469 CCLSecureWatcher::~CCLSecureWatcher()
       
   470 	{
       
   471 
       
   472 	}
       
   473 
       
   474 /**
       
   475  * Opens the Connectionless session on the stack.  For security, a certificate is not
       
   476  * negotiated with the Gateway.  A message will come in, it will be encrypted, the stack
       
   477  * decrypts based on the headers in the message.
       
   478  */
       
   479 void CCLSecureWatcher::SetupCLWatcherL()
       
   480 	{
       
   481 	User::LeaveIfError(iWapCLServ->Connect(Wap::EAll,KPushPortSecure, ETrue));		
       
   482 	}	
       
   483 
       
   484 
       
   485 
       
   486