os/security/cryptomgmtlibs/securitytestfw/test/sntpclient/sntpclientengine.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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 	   
   226 	 */
   227 	
   228 	for (TInt i = 40; i < 44; ++i)
   229 		{
   230 		timestamp = (timestamp << 8) + iBuffer[i];
   231 		}
   232 	
   233 	// Obtain the time, including the specified timezone offset
   234 	
   235 	TTimeIntervalMinutes mins(timestamp / 60);
   236 	TTimeIntervalSeconds secs(timestamp % 60);
   237 	
   238 	TTime ntpTime;
   239 	User::LeaveIfError(ntpTime.Set(KNTPEpochDate));
   240 	ntpTime += mins;
   241 	ntpTime += secs;
   242 	
   243 	// Apply offset and (possibly) daylight savings time
   244 	
   245 	TTimeIntervalHours hours;
   246 	
   247 	if (iArgs.iApplyDaylightSavings && Util::DaylightSavingsAppliesL(ntpTime))
   248 		{
   249 		hours = iArgs.iOffset + 1;
   250 		}
   251 	else
   252 		{
   253 		hours = iArgs.iOffset;
   254 		}
   255 		
   256 	ntpTime += hours;
   257 	
   258 	User::LeaveIfError(User::SetHomeTime(ntpTime));
   259 	
   260 	}
   261 	
   262 	
   263 /* Timeout handler for read/write operations */
   264 
   265 CTimeOutTimer::CTimeOutTimer(const TInt aPriority)
   266     : CTimer(aPriority)
   267     {
   268     }
   269 
   270 CTimeOutTimer::~CTimeOutTimer()
   271     {
   272 	Cancel();
   273     }
   274 
   275 CTimeOutTimer* CTimeOutTimer::NewL(const TInt aPriority, MTimeOutNotify& aTimeOutNotify)
   276     {
   277     CTimeOutTimer *p = new (ELeave) CTimeOutTimer(aPriority);
   278     CleanupStack::PushL(p);
   279 	p->ConstructL(aTimeOutNotify);
   280 	CleanupStack::Pop();
   281     return p;
   282     }
   283 
   284 void CTimeOutTimer::ConstructL(MTimeOutNotify &aTimeOutNotify)
   285     {
   286 	iNotify=&aTimeOutNotify;
   287 	CTimer::ConstructL();
   288     CActiveScheduler::Add(this);
   289     }
   290 
   291 void CTimeOutTimer::RunL()
   292 // Timer request has completed, so notify the timer's owner
   293     {
   294 	iNotify->TimerExpired();
   295 	}