messagingfw/suplsmshandler/src/LbsSuplWdpWatcher.cpp
changeset 0 8e480a14352b
equal deleted inserted replaced
-1:000000000000 0:8e480a14352b
       
     1 // Copyright (c) 2007-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 // The main SUPL SMS Trigger Plug-in class. It implements the ECOM interface, listens for the incoming messages,
       
    15 // and notifies the SPM via the SUPL Push API.
       
    16 // 
       
    17 //
       
    18 
       
    19 /**
       
    20  @file
       
    21  @internalComponent
       
    22  @prototype
       
    23 */
       
    24 
       
    25 #include <ecom/implementationproxy.h>
       
    26 #include <watcher.h>
       
    27 #include "lbsdevloggermacros.h"
       
    28 
       
    29 #include "LbsSuplWdpWatcher.h"
       
    30 
       
    31 
       
    32 /** The port on which the SMS messages arrives*/
       
    33 const TInt KSuplSmsTriggerWdpPort = 7275;
       
    34 
       
    35 /** The timeout in seconds after which the restart attempts are maid if the connection fails */
       
    36 const TInt KRecoveryInterval = 10;
       
    37 
       
    38 /** The maximal number of messages on reaching which the IP datagrams are not delivered to the Supl Push API any more*/
       
    39 const TUint KMaxMsgLimitForIp = 10;
       
    40 
       
    41 /** ECOM implementation table */
       
    42 const TImplementationProxy ImplementationTable[] = 
       
    43 	{
       
    44 	IMPLEMENTATION_PROXY_ENTRY(0x10283757, CLbsSuplWdpWatcher::NewL)
       
    45 	};
       
    46 
       
    47 /** The only exported ECOM entry point function */
       
    48 EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
       
    49 	{
       
    50 	aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
       
    51 	return ImplementationTable;
       
    52 	}
       
    53 
       
    54 /**
       
    55 Static factory method for creating an instance of the CLbsSuplWdpWatcher class.
       
    56 
       
    57 @param aWatcherParams [In] A pointer on the params the Watcher Framework passes when the object is created. 
       
    58 A reference on the CWatcherLog is passed here.
       
    59 
       
    60 @return An instance of the class. The calling application becomes the
       
    61 owner of the returned instance and is responsible its disposal.
       
    62 
       
    63 @leave If a error happens, it leaves with one of the system error codes.
       
    64 
       
    65 */
       
    66 CLbsSuplWdpWatcher* CLbsSuplWdpWatcher::NewL(TAny* aWatcherParams)
       
    67 	{
       
    68 	TWatcherParams* params = reinterpret_cast<TWatcherParams*>(aWatcherParams);
       
    69 	CLbsSuplWdpWatcher* self= new (ELeave) CLbsSuplWdpWatcher(CActive::EPriorityStandard, params->iLog);
       
    70 	CleanupStack::PushL(self);
       
    71 	self->ConstructL();
       
    72 	CleanupStack::Pop();
       
    73 	return self;
       
    74 	}
       
    75 
       
    76 /**
       
    77 Constructor.
       
    78 
       
    79 @param aPriority [In] The active object's priority
       
    80 @param aLog [In] A refernce on the Watcher logger class
       
    81 
       
    82 @see CLbsSuplWdpWatcher::NewL
       
    83 */
       
    84 CLbsSuplWdpWatcher::CLbsSuplWdpWatcher(TInt aPriority, CWatcherLog& aLog)
       
    85 : CActive(aPriority), iState(EDisconnected), iDataSizePckg(iDataSize),
       
    86 iLocalPort(KSuplSmsTriggerWdpPort), iLog(aLog)
       
    87 	{
       
    88 	CActiveScheduler::Add(this);
       
    89 	}
       
    90 
       
    91 
       
    92 /**
       
    93 Destructor. Cancels the outstanding request for new messages and releases all resources.
       
    94 */
       
    95 CLbsSuplWdpWatcher::~CLbsSuplWdpWatcher()
       
    96 	{
       
    97 	Cancel();
       
    98 	
       
    99 	iData.Close();
       
   100 	
       
   101 	delete iWdpConn;
       
   102 	delete iSuplPush;
       
   103 	delete iTimer;
       
   104 	}
       
   105 
       
   106 /**
       
   107 2nd phase constructor. Creates and assigns all the required internal resources.
       
   108 
       
   109 @leave If a error happens, it leaves with one of the system error codes.
       
   110 
       
   111 @see CLbsSuplWdpWatcher::NewL
       
   112 */
       
   113 void CLbsSuplWdpWatcher::ConstructL()
       
   114 	{
       
   115 	iLog.Printf(_L8("SuplWatcher : ConstructL()"));
       
   116 	LBSLOG(ELogP2, "SuplWatcher : ConstructL()");
       
   117 	iTimer = CLbsCallbackTimer::NewL(*this);
       
   118 	
       
   119 	iSuplPush = CLbsSuplPush::NewL(ELbsSuplPushChannelSMS, *this);
       
   120 	
       
   121 	Restart();
       
   122 	}
       
   123 
       
   124 /**
       
   125 Handles the completition of the AwaitRecvDataSize and RecvFrom asynchronous calls.
       
   126 
       
   127 @leave If a error happens, it leaves with one of the system error codes.
       
   128 
       
   129 @see CActive::RunL
       
   130 @see CWapBoundDatagramService::AwaitRecvDataSize
       
   131 @see CWapBoundDatagramService::RecvFrom
       
   132 */
       
   133 void CLbsSuplWdpWatcher::RunL()
       
   134 	{
       
   135 	__ASSERT_DEBUG(iState==EAwaitingDataSize || iState==EAwaitingData, User::Invariant());
       
   136 	
       
   137 	if(iStatus!=KErrNone)
       
   138 		{
       
   139 		ScheduleRestart(iStatus.Int());
       
   140 		return;
       
   141 		}
       
   142 	
       
   143 	if(iState==EAwaitingDataSize)
       
   144 		{
       
   145 		LBSLOG2(ELogP2,"SuplWatcher : Message size received %d", iDataSize);
       
   146 		iData.CreateL(iDataSize);
       
   147 				
       
   148 		LBSLOG(ELogP2,"SuplWatcher : Receiving message...");
       
   149 		TInt err = iWdpConn->RecvFrom(iRemoteHost, iRemotePort, iData, iTruncated, iStatus, 0);
       
   150 		if(err==KErrNone)
       
   151 			{
       
   152 			iState = EAwaitingData;
       
   153 			SetActive();
       
   154 			}
       
   155 		else
       
   156 			{
       
   157 			ScheduleRestart(err);
       
   158 			}
       
   159 		}
       
   160 	else //iState==EAwaitingData
       
   161 		{
       
   162 		TInt err = KErrNone;
       
   163 						
       
   164 		Wap::TBearer bearer;
       
   165 		err = iWdpConn->GetBearer(bearer);
       
   166 		//If there are KMaxMsgLimitForIp or more messages in the queue, we ignore IP datagrams for security reasons
       
   167 		if(err!=KErrNone || (bearer==Wap::EIP && iPendingMsg>=KMaxMsgLimitForIp)) 
       
   168 			{
       
   169 			return;
       
   170 			}
       
   171 	
       
   172 		
       
   173 		TLbsSuplPushRequestId reqId;
       
   174 		err=iSuplPush->SuplInit(reqId, iData, 0);
       
   175 		iData.Close();
       
   176 		iLog.Printf(_L8("SuplWatcher : Message %d received, resending it to SPM"), reqId);
       
   177 		LBSLOG2(ELogP3,"SuplWatcher : Message %d received, resending it to SPM", reqId);
       
   178 		if(err!=KErrNone)
       
   179 			{
       
   180 			iLog.Printf(_L8("SuplWatcher : Message %d delivery failed, error %d"), reqId, err);
       
   181 			LBSLOG3(ELogP3,"SuplWatcher : Message %d delivery failed, error %d", reqId, err);
       
   182 			}
       
   183 		else
       
   184 			{
       
   185 			iPendingMsg++;
       
   186 			}
       
   187 
       
   188 		LBSLOG(ELogP2,"SuplWatcher : Awaiting next message size...");
       
   189 		err = iWdpConn->AwaitRecvDataSize(iDataSizePckg, iStatus);
       
   190 		if(err==KErrNone)
       
   191 			{
       
   192 			iState = EAwaitingDataSize;
       
   193 			SetActive();
       
   194 			}
       
   195 		else
       
   196 			{
       
   197 			ScheduleRestart(iStatus.Int());
       
   198 			}
       
   199 		}
       
   200 	}
       
   201 
       
   202 /**
       
   203 Called when CActive::Cancel method is called. The Cancel method is not supposed to be called by the Watcher 
       
   204 Framework directly.
       
   205 
       
   206 @see CActive::DoCancel
       
   207 @see CLbsSuplWdpWatcher::~CLbsSuplWdpWatcher
       
   208 */
       
   209 void CLbsSuplWdpWatcher::DoCancel()
       
   210 	{
       
   211 	//This method is not called by the Active Scheduler Framework if there is no request outstanding.
       
   212 	//To have an outsatnding request, we must have non-zero iWdpConn. So, there is no check for null of 
       
   213 	//iWdpConn here.
       
   214 	__ASSERT_DEBUG(iWdpConn, User::Invariant());
       
   215 	iWdpConn->CancelRecv();
       
   216 	}
       
   217 
       
   218 /**
       
   219 Called if the CLbsSuplWdpWatcher::RunL leaves. Restarts the connection.
       
   220 
       
   221 @return KErrNone to inform the ActiveScheduler Framework that the error was hndled by the object itself.
       
   222 
       
   223 @see CActive::RunError
       
   224 */
       
   225 TInt CLbsSuplWdpWatcher::RunError(TInt aError)
       
   226 	{
       
   227 	ScheduleRestart(aError);
       
   228 	return KErrNone;
       
   229 	}
       
   230 
       
   231 
       
   232 /**
       
   233  	From MLbsSuplPushObserver.
       
   234 	Receive notification that the SUPL Init message has been sent to the LBS sub-system.
       
   235 	The call-back is invoked immediately after delivery of the SUPL INIT request and 
       
   236 	does not provide any information about it's outcome, e.g. conflict control results,
       
   237 	host validation results, connection results etc.
       
   238 	
       
   239 	@param aChannel  [In] The channel the call-back is related to.
       
   240 	@param aReqId    [In] An Id of the request the call-back is related to.
       
   241 	@param aError    [In] KErrNone if successful, KErrTimeout if it was not possible to deliver
       
   242 	                      the request before the timeout period, KErrArgument if the structure 
       
   243 	                      or content of the SUPL INIT message was incorrect. 
       
   244 	                      Any system wide error code otherwise.
       
   245 	@param aReserved [In] Reserved for future use.
       
   246 	
       
   247 	@see CLbsSuplPush::SuplInit
       
   248 	@see MLbsSuplPushObserver::OnSuplInitComplete
       
   249 */
       
   250 void CLbsSuplWdpWatcher::OnSuplInitComplete(TLbsSuplPushChannel /*aChannel*/, TLbsSuplPushRequestId aReqId, 
       
   251 			TInt aError, TInt /*aReserved*/)
       
   252 	{
       
   253 	iPendingMsg--;
       
   254 	
       
   255 	if(aError==KErrNone)
       
   256 		{
       
   257 		iLog.Printf(_L8("SuplWatcher : Message %d delivered successfully"), aReqId);
       
   258 		LBSLOG2(ELogP3,"SuplWatcher : Message %d delivered successfully", aReqId);
       
   259 		}
       
   260 	else
       
   261 		{
       
   262 		iLog.Printf(_L8("SuplWatcher : Message %d delivery failed, error %d"), aReqId, aError);
       
   263 		LBSLOG3(ELogP3,"SuplWatcher : Message %d delivery failed, error %d", aReqId, aError);
       
   264 		}
       
   265 	}
       
   266 
       
   267 /**
       
   268 From MLbsSuplWdpConnTimerObserver. Receive notification when the restart event must happen.
       
   269 	
       
   270 @see MLbsSuplWdpConnTimerObserver::Restart
       
   271 */
       
   272 void CLbsSuplWdpWatcher::Restart()
       
   273 	{
       
   274 	__ASSERT_DEBUG(iState==EDisconnected,  User::Invariant());
       
   275 	
       
   276 	LBSLOG(ELogP2,"SuplWatcher : Starting receiving WDP datagrams...");
       
   277 	TRAPD(err,iWdpConn = CWapBoundDatagramService::NewL());
       
   278 	
       
   279 	if(err==KErrNone)
       
   280 		{
       
   281 		LBSLOG(ELogP2,"SuplWatcher : Openning connection...");
       
   282 		//We connect it with Wap::EAll to receive all types of SMS
       
   283 		//The IP bearer is filtered in the release version in the RunL function
       
   284 		err = iWdpConn->Connect(Wap::EAll, iLocalPort);
       
   285 		if(err==KErrNone)
       
   286 			{
       
   287 			LBSLOG(ELogP2,"SuplWatcher : Connected, awaiting message size...");
       
   288 			err = iWdpConn->AwaitRecvDataSize(iDataSizePckg, iStatus);
       
   289 			if(err==KErrNone)
       
   290 				{
       
   291 				iState = EAwaitingDataSize;
       
   292 				SetActive();
       
   293 				}
       
   294 			}
       
   295 		}
       
   296 	
       
   297 	if(err!=KErrNone)
       
   298 		{
       
   299 		ScheduleRestart(err);
       
   300 		}
       
   301 	}
       
   302 
       
   303 /**
       
   304 Schedules the next restart attempt.
       
   305 
       
   306 @param aError [In] The error that causes the restart attempt 
       
   307 */
       
   308 void CLbsSuplWdpWatcher::ScheduleRestart(TInt aError)
       
   309 	{
       
   310 	(void)aError;
       
   311 	
       
   312 	delete iWdpConn;
       
   313 	iWdpConn = 0;
       
   314 	iTimer->Cancel();
       
   315 	iTimer->EventAfter(TTimeIntervalSeconds(KRecoveryInterval), 0);
       
   316 	iData.Close();
       
   317 	iState = EDisconnected;
       
   318 	
       
   319 	LBSLOG3(ELogP3,"SuplWatcher : Error %d, recovery attempt in %d sec", aError, KRecoveryInterval);
       
   320 	}
       
   321 
       
   322 
       
   323 /**
       
   324 From MLbsCallbackTimerObserver. Receive notification when the restart event must happen.
       
   325 
       
   326 @see CLbsSuplWdpWatcher::Restart
       
   327 */
       
   328 void CLbsSuplWdpWatcher::OnTimerEventL(TInt /*aTimerId*/)
       
   329 	{
       
   330 	Restart();
       
   331 	}
       
   332 
       
   333 /**
       
   334 From MLbsCallbackTimerObserver. Normally it is called when OnTimerEventL leaves. Our implementation 
       
   335 of OnTimerEventL does not leave, so this function must not be called.
       
   336 
       
   337 @see MLbsCallbackTimerObserver
       
   338 @see CLbsCallbackTimer
       
   339 */
       
   340 TInt CLbsSuplWdpWatcher::OnTimerError(TInt /*aTimerId*/, TInt /*aError*/)
       
   341 	{
       
   342 	__ASSERT_DEBUG(0, User::Invariant());
       
   343 	return KErrNone;
       
   344 	}
       
   345