installationservices/switestfw/test/sntpclient/sntpclientengine.cpp
changeset 0 ba25891c3a9e
equal deleted inserted replaced
-1:000000000000 0:ba25891c3a9e
       
     1 /*
       
     2 * Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "sntpclientengine.h"
       
    20 #include "util.h"
       
    21 
       
    22 // 40 second timeout on operations
       
    23 #define SNTP_ENGINE_TIMEOUT 40000000 
       
    24 
       
    25 // NTP port
       
    26 
       
    27 #define SNTP_REMOTE_PORT 123
       
    28 
       
    29 _LIT(KNTPEpochDate,"19000000:");
       
    30 
       
    31 /* The simplest possible NTP request */
       
    32 
       
    33 static const TUint8 sntpRequest[48] = {
       
    34 	0x23, 0x00, 0x00, 0x00,
       
    35 	0x00, 0x00, 0x00, 0x00,
       
    36 	0x00, 0x00, 0x00, 0x00,
       
    37 	0x00, 0x00, 0x00, 0x00,
       
    38 	0x00, 0x00, 0x00, 0x00,
       
    39 	0x00, 0x00, 0x00, 0x00,
       
    40 	0x00, 0x00, 0x00, 0x00,
       
    41 	0x00, 0x00, 0x00, 0x00,
       
    42 	0x00, 0x00, 0x00, 0x00,
       
    43 	0x00, 0x00, 0x00, 0x00,
       
    44 	0x00, 0x00, 0x00, 0x00,
       
    45 	0x00, 0x00, 0x00, 0x00 };
       
    46 	
       
    47 /* The main engine of the SNTP client */
       
    48 
       
    49 CSNTPClient* CSNTPClient::NewL(TCommandLineArgs& aArgs)
       
    50 	{
       
    51 	CSNTPClient* self = CSNTPClient::NewLC(aArgs);
       
    52 	CleanupStack::Pop(self);
       
    53 	return self;
       
    54 	}
       
    55 	
       
    56 CSNTPClient* CSNTPClient::NewLC(TCommandLineArgs& aArgs)
       
    57 	{
       
    58 	CSNTPClient* self = new (ELeave) CSNTPClient(aArgs);
       
    59 	CleanupStack::PushL(self);
       
    60 	self->ConstructL();
       
    61 	return self;
       
    62 	}
       
    63 	
       
    64 TSNTPClientState CSNTPClient::State()
       
    65 	{
       
    66 	return iState;
       
    67 	}
       
    68 	
       
    69 void CSNTPClient::Start()
       
    70 	{
       
    71 	
       
    72 	iState = EStateResolve;
       
    73 	iResolver.GetByName(*(iArgs.iServers[iServerIndex]), iNameEntry, iStatus);
       
    74 	SetActive();
       
    75 	iTimer->After(SNTP_ENGINE_TIMEOUT);
       
    76 	
       
    77 	}
       
    78 	
       
    79 CSNTPClient::~CSNTPClient()
       
    80 	{
       
    81 	Cancel();
       
    82 	iResolver.Close();
       
    83 	iSock.Close();
       
    84 	iSockServ.Close();
       
    85 	
       
    86 	delete iTimer;
       
    87 	}
       
    88 	
       
    89 CSNTPClient::CSNTPClient(TCommandLineArgs& aArgs)
       
    90 	: CActive(EPriorityStandard), iArgs(aArgs)
       
    91 	{
       
    92 	}
       
    93 	
       
    94 void CSNTPClient::ConstructL()
       
    95 	{
       
    96 	User::LeaveIfError(iSockServ.Connect());
       
    97 	User::LeaveIfError(iSock.Open(iSockServ, KAfInet, KSockDatagram, KProtocolInetUdp));
       
    98 	User::LeaveIfError(iResolver.Open(iSockServ, KAfInet, KProtocolInetUdp));
       
    99 	
       
   100 	iTimer = CTimeOutTimer::NewL(EPriorityHigh, *this);
       
   101 	CActiveScheduler::Add(this);
       
   102 	}
       
   103 	
       
   104 void CSNTPClient::RunL()
       
   105 	{
       
   106 	
       
   107 	if (iStatus.Int() < 0)
       
   108 		{
       
   109 		User::Leave(iStatus.Int());
       
   110 		}
       
   111 
       
   112 	switch (iState)
       
   113 		{
       
   114 	
       
   115 	case EStateResolve:
       
   116 		iTimer->Cancel();
       
   117 		iBuffer.Zero();
       
   118 		iBuffer.Append(sntpRequest, 48);
       
   119 	
       
   120 		// set the port on the address
       
   121 		iNameEntry().iAddr.SetPort(SNTP_REMOTE_PORT);
       
   122 	
       
   123 		iState = EStateWrite;
       
   124 		iSock.SendTo(iBuffer, iNameEntry().iAddr, 0, iStatus);
       
   125 		SetActive();
       
   126 		iTimer->After(SNTP_ENGINE_TIMEOUT);
       
   127 		break;
       
   128 	
       
   129 	case EStateWrite:
       
   130 		iTimer->Cancel();
       
   131 		iState = EStateRead;
       
   132 		iBuffer.Zero();
       
   133 		iSock.RecvFrom(iBuffer, iNameEntry().iAddr, 0, iStatus);
       
   134 		SetActive();
       
   135 		iTimer->After(SNTP_ENGINE_TIMEOUT);
       
   136 		break;
       
   137 		
       
   138 	case EStateRead:
       
   139 		{
       
   140 		iTimer->Cancel();
       
   141 		SetTimeL();
       
   142 		iStatus = KRequestPending;
       
   143 		iState = EStateComplete;
       
   144 		TRequestStatus* status = &iStatus;
       
   145 		SetActive();
       
   146 		User::RequestComplete(status, KErrNone);
       
   147 		break;
       
   148 		}
       
   149 		
       
   150 	case EStateComplete:
       
   151 		CActiveScheduler::Stop();
       
   152 		// done
       
   153 		break;
       
   154 		
       
   155 	default:
       
   156 		// wuh oh. BC break!
       
   157 		User::Leave(KErrArgument);
       
   158 		break;
       
   159 		
       
   160 		}
       
   161 	
       
   162 	}
       
   163 	
       
   164 void CSNTPClient::DoCancel()
       
   165 	{
       
   166 	
       
   167 	iTimer->Cancel();
       
   168 
       
   169 	switch (iState)
       
   170 		{
       
   171 	case EStateResolve:
       
   172 		iResolver.Cancel();
       
   173 		break;
       
   174 	case EStateWrite:
       
   175 		iSock.CancelSend();
       
   176 		break;
       
   177 	case EStateRead:
       
   178 		iSock.CancelRecv();
       
   179 		break;
       
   180 		}
       
   181 		
       
   182 	}
       
   183 	
       
   184 	
       
   185 TInt CSNTPClient::RunError(TInt /* aError */)
       
   186 	{
       
   187 	// The current server didn't work, lets try the next if available.
       
   188 	iTimer->Cancel();
       
   189 	
       
   190 	if (++iServerIndex < iArgs.iServers.Count())
       
   191 		{
       
   192 		Start();
       
   193 		}
       
   194 	else
       
   195 		{
       
   196 		iState = EStateFailed;
       
   197 		CActiveScheduler::Stop();
       
   198 		}
       
   199 	return KErrNone;
       
   200 	}
       
   201 	
       
   202 void CSNTPClient::TimerExpired()
       
   203 	{
       
   204 	Cancel();
       
   205 	
       
   206 	// The current server didn't work, lets try the next if available.
       
   207 	
       
   208 	if (++iServerIndex < iArgs.iServers.Count())
       
   209 		{
       
   210 		Start();
       
   211 		}
       
   212 	else
       
   213 		{
       
   214 		iState = EStateAborted;
       
   215 		CActiveScheduler::Stop();
       
   216 		}
       
   217 	}
       
   218 	
       
   219 void CSNTPClient::SetTimeL()
       
   220 	{
       
   221 	
       
   222 	TUint32 timestamp(0);
       
   223 	
       
   224 	/* Use the seconds from the transmit time field 
       
   225 	   TO DO:
       
   226 	      + Implement proper differential here
       
   227 	 */
       
   228 	
       
   229 	for (TInt i = 40; i < 44; ++i)
       
   230 		{
       
   231 		timestamp = (timestamp << 8) + iBuffer[i];
       
   232 		}
       
   233 	
       
   234 	// Obtain the time, including the specified timezone offset
       
   235 	
       
   236 	TTimeIntervalMinutes mins(timestamp / 60);
       
   237 	TTimeIntervalSeconds secs(timestamp % 60);
       
   238 	
       
   239 	TTime ntpTime;
       
   240 	User::LeaveIfError(ntpTime.Set(KNTPEpochDate));
       
   241 	ntpTime += mins;
       
   242 	ntpTime += secs;
       
   243 	
       
   244 	// Apply offset and (possibly) daylight savings time
       
   245 	
       
   246 	TTimeIntervalHours hours;
       
   247 	
       
   248 	if (iArgs.iApplyDaylightSavings && Util::DaylightSavingsAppliesL(ntpTime))
       
   249 		{
       
   250 		hours = iArgs.iOffset + 1;
       
   251 		}
       
   252 	else
       
   253 		{
       
   254 		hours = iArgs.iOffset;
       
   255 		}
       
   256 		
       
   257 	ntpTime += hours;
       
   258 	
       
   259 	User::LeaveIfError(User::SetHomeTime(ntpTime));
       
   260 	
       
   261 	}
       
   262 	
       
   263 	
       
   264 /* Timeout handler for read/write operations */
       
   265 
       
   266 CTimeOutTimer::CTimeOutTimer(const TInt aPriority)
       
   267     : CTimer(aPriority)
       
   268     {
       
   269     }
       
   270 
       
   271 CTimeOutTimer::~CTimeOutTimer()
       
   272     {
       
   273 	Cancel();
       
   274     }
       
   275 
       
   276 CTimeOutTimer* CTimeOutTimer::NewL(const TInt aPriority, MTimeOutNotify& aTimeOutNotify)
       
   277     {
       
   278     CTimeOutTimer *p = new (ELeave) CTimeOutTimer(aPriority);
       
   279     CleanupStack::PushL(p);
       
   280 	p->ConstructL(aTimeOutNotify);
       
   281 	CleanupStack::Pop();
       
   282     return p;
       
   283     }
       
   284 
       
   285 void CTimeOutTimer::ConstructL(MTimeOutNotify &aTimeOutNotify)
       
   286     {
       
   287 	iNotify=&aTimeOutNotify;
       
   288 	CTimer::ConstructL();
       
   289     CActiveScheduler::Add(this);
       
   290     }
       
   291 
       
   292 void CTimeOutTimer::RunL()
       
   293 // Timer request has completed, so notify the timer's owner
       
   294     {
       
   295 	iNotify->TimerExpired();
       
   296 	}