1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/security/cryptomgmtlibs/securitytestfw/test/sntpclient/sntpclientengine.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,295 @@
1.4 +/*
1.5 +* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
1.6 +* All rights reserved.
1.7 +* This component and the accompanying materials are made available
1.8 +* under the terms of the License "Eclipse Public License v1.0"
1.9 +* which accompanies this distribution, and is available
1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.11 +*
1.12 +* Initial Contributors:
1.13 +* Nokia Corporation - initial contribution.
1.14 +*
1.15 +* Contributors:
1.16 +*
1.17 +* Description:
1.18 +*
1.19 +*/
1.20 +
1.21 +
1.22 +#include "sntpclientengine.h"
1.23 +#include "util.h"
1.24 +
1.25 +// 40 second timeout on operations
1.26 +#define SNTP_ENGINE_TIMEOUT 40000000
1.27 +
1.28 +// NTP port
1.29 +
1.30 +#define SNTP_REMOTE_PORT 123
1.31 +
1.32 +_LIT(KNTPEpochDate,"19000000:");
1.33 +
1.34 +/* The simplest possible NTP request */
1.35 +
1.36 +static const TUint8 sntpRequest[48] = {
1.37 + 0x23, 0x00, 0x00, 0x00,
1.38 + 0x00, 0x00, 0x00, 0x00,
1.39 + 0x00, 0x00, 0x00, 0x00,
1.40 + 0x00, 0x00, 0x00, 0x00,
1.41 + 0x00, 0x00, 0x00, 0x00,
1.42 + 0x00, 0x00, 0x00, 0x00,
1.43 + 0x00, 0x00, 0x00, 0x00,
1.44 + 0x00, 0x00, 0x00, 0x00,
1.45 + 0x00, 0x00, 0x00, 0x00,
1.46 + 0x00, 0x00, 0x00, 0x00,
1.47 + 0x00, 0x00, 0x00, 0x00,
1.48 + 0x00, 0x00, 0x00, 0x00 };
1.49 +
1.50 +/* The main engine of the SNTP client */
1.51 +
1.52 +CSNTPClient* CSNTPClient::NewL(TCommandLineArgs& aArgs)
1.53 + {
1.54 + CSNTPClient* self = CSNTPClient::NewLC(aArgs);
1.55 + CleanupStack::Pop(self);
1.56 + return self;
1.57 + }
1.58 +
1.59 +CSNTPClient* CSNTPClient::NewLC(TCommandLineArgs& aArgs)
1.60 + {
1.61 + CSNTPClient* self = new (ELeave) CSNTPClient(aArgs);
1.62 + CleanupStack::PushL(self);
1.63 + self->ConstructL();
1.64 + return self;
1.65 + }
1.66 +
1.67 +TSNTPClientState CSNTPClient::State()
1.68 + {
1.69 + return iState;
1.70 + }
1.71 +
1.72 +void CSNTPClient::Start()
1.73 + {
1.74 +
1.75 + iState = EStateResolve;
1.76 + iResolver.GetByName(*(iArgs.iServers[iServerIndex]), iNameEntry, iStatus);
1.77 + SetActive();
1.78 + iTimer->After(SNTP_ENGINE_TIMEOUT);
1.79 +
1.80 + }
1.81 +
1.82 +CSNTPClient::~CSNTPClient()
1.83 + {
1.84 + Cancel();
1.85 + iResolver.Close();
1.86 + iSock.Close();
1.87 + iSockServ.Close();
1.88 +
1.89 + delete iTimer;
1.90 + }
1.91 +
1.92 +CSNTPClient::CSNTPClient(TCommandLineArgs& aArgs)
1.93 + : CActive(EPriorityStandard), iArgs(aArgs)
1.94 + {
1.95 + }
1.96 +
1.97 +void CSNTPClient::ConstructL()
1.98 + {
1.99 + User::LeaveIfError(iSockServ.Connect());
1.100 + User::LeaveIfError(iSock.Open(iSockServ, KAfInet, KSockDatagram, KProtocolInetUdp));
1.101 + User::LeaveIfError(iResolver.Open(iSockServ, KAfInet, KProtocolInetUdp));
1.102 +
1.103 + iTimer = CTimeOutTimer::NewL(EPriorityHigh, *this);
1.104 + CActiveScheduler::Add(this);
1.105 + }
1.106 +
1.107 +void CSNTPClient::RunL()
1.108 + {
1.109 +
1.110 + if (iStatus.Int() < 0)
1.111 + {
1.112 + User::Leave(iStatus.Int());
1.113 + }
1.114 +
1.115 + switch (iState)
1.116 + {
1.117 +
1.118 + case EStateResolve:
1.119 + iTimer->Cancel();
1.120 + iBuffer.Zero();
1.121 + iBuffer.Append(sntpRequest, 48);
1.122 +
1.123 + // set the port on the address
1.124 + iNameEntry().iAddr.SetPort(SNTP_REMOTE_PORT);
1.125 +
1.126 + iState = EStateWrite;
1.127 + iSock.SendTo(iBuffer, iNameEntry().iAddr, 0, iStatus);
1.128 + SetActive();
1.129 + iTimer->After(SNTP_ENGINE_TIMEOUT);
1.130 + break;
1.131 +
1.132 + case EStateWrite:
1.133 + iTimer->Cancel();
1.134 + iState = EStateRead;
1.135 + iBuffer.Zero();
1.136 + iSock.RecvFrom(iBuffer, iNameEntry().iAddr, 0, iStatus);
1.137 + SetActive();
1.138 + iTimer->After(SNTP_ENGINE_TIMEOUT);
1.139 + break;
1.140 +
1.141 + case EStateRead:
1.142 + {
1.143 + iTimer->Cancel();
1.144 + SetTimeL();
1.145 + iStatus = KRequestPending;
1.146 + iState = EStateComplete;
1.147 + TRequestStatus* status = &iStatus;
1.148 + SetActive();
1.149 + User::RequestComplete(status, KErrNone);
1.150 + break;
1.151 + }
1.152 +
1.153 + case EStateComplete:
1.154 + CActiveScheduler::Stop();
1.155 + // done
1.156 + break;
1.157 +
1.158 + default:
1.159 + // wuh oh. BC break!
1.160 + User::Leave(KErrArgument);
1.161 + break;
1.162 +
1.163 + }
1.164 +
1.165 + }
1.166 +
1.167 +void CSNTPClient::DoCancel()
1.168 + {
1.169 +
1.170 + iTimer->Cancel();
1.171 +
1.172 + switch (iState)
1.173 + {
1.174 + case EStateResolve:
1.175 + iResolver.Cancel();
1.176 + break;
1.177 + case EStateWrite:
1.178 + iSock.CancelSend();
1.179 + break;
1.180 + case EStateRead:
1.181 + iSock.CancelRecv();
1.182 + break;
1.183 + }
1.184 +
1.185 + }
1.186 +
1.187 +
1.188 +TInt CSNTPClient::RunError(TInt /* aError */)
1.189 + {
1.190 + // The current server didn't work, lets try the next if available.
1.191 + iTimer->Cancel();
1.192 +
1.193 + if (++iServerIndex < iArgs.iServers.Count())
1.194 + {
1.195 + Start();
1.196 + }
1.197 + else
1.198 + {
1.199 + iState = EStateFailed;
1.200 + CActiveScheduler::Stop();
1.201 + }
1.202 + return KErrNone;
1.203 + }
1.204 +
1.205 +void CSNTPClient::TimerExpired()
1.206 + {
1.207 + Cancel();
1.208 +
1.209 + // The current server didn't work, lets try the next if available.
1.210 +
1.211 + if (++iServerIndex < iArgs.iServers.Count())
1.212 + {
1.213 + Start();
1.214 + }
1.215 + else
1.216 + {
1.217 + iState = EStateAborted;
1.218 + CActiveScheduler::Stop();
1.219 + }
1.220 + }
1.221 +
1.222 +void CSNTPClient::SetTimeL()
1.223 + {
1.224 +
1.225 + TUint32 timestamp(0);
1.226 +
1.227 + /* Use the seconds from the transmit time field
1.228 +
1.229 + */
1.230 +
1.231 + for (TInt i = 40; i < 44; ++i)
1.232 + {
1.233 + timestamp = (timestamp << 8) + iBuffer[i];
1.234 + }
1.235 +
1.236 + // Obtain the time, including the specified timezone offset
1.237 +
1.238 + TTimeIntervalMinutes mins(timestamp / 60);
1.239 + TTimeIntervalSeconds secs(timestamp % 60);
1.240 +
1.241 + TTime ntpTime;
1.242 + User::LeaveIfError(ntpTime.Set(KNTPEpochDate));
1.243 + ntpTime += mins;
1.244 + ntpTime += secs;
1.245 +
1.246 + // Apply offset and (possibly) daylight savings time
1.247 +
1.248 + TTimeIntervalHours hours;
1.249 +
1.250 + if (iArgs.iApplyDaylightSavings && Util::DaylightSavingsAppliesL(ntpTime))
1.251 + {
1.252 + hours = iArgs.iOffset + 1;
1.253 + }
1.254 + else
1.255 + {
1.256 + hours = iArgs.iOffset;
1.257 + }
1.258 +
1.259 + ntpTime += hours;
1.260 +
1.261 + User::LeaveIfError(User::SetHomeTime(ntpTime));
1.262 +
1.263 + }
1.264 +
1.265 +
1.266 +/* Timeout handler for read/write operations */
1.267 +
1.268 +CTimeOutTimer::CTimeOutTimer(const TInt aPriority)
1.269 + : CTimer(aPriority)
1.270 + {
1.271 + }
1.272 +
1.273 +CTimeOutTimer::~CTimeOutTimer()
1.274 + {
1.275 + Cancel();
1.276 + }
1.277 +
1.278 +CTimeOutTimer* CTimeOutTimer::NewL(const TInt aPriority, MTimeOutNotify& aTimeOutNotify)
1.279 + {
1.280 + CTimeOutTimer *p = new (ELeave) CTimeOutTimer(aPriority);
1.281 + CleanupStack::PushL(p);
1.282 + p->ConstructL(aTimeOutNotify);
1.283 + CleanupStack::Pop();
1.284 + return p;
1.285 + }
1.286 +
1.287 +void CTimeOutTimer::ConstructL(MTimeOutNotify &aTimeOutNotify)
1.288 + {
1.289 + iNotify=&aTimeOutNotify;
1.290 + CTimer::ConstructL();
1.291 + CActiveScheduler::Add(this);
1.292 + }
1.293 +
1.294 +void CTimeOutTimer::RunL()
1.295 +// Timer request has completed, so notify the timer's owner
1.296 + {
1.297 + iNotify->TimerExpired();
1.298 + }