📄 sntp.cpp
字号:
{
m_Time = time.m_Time;
return *this;
}
double CNtpTime::operator-(const CNtpTime& time) const
{
if (m_Time >= time.m_Time)
{
CNtpTime diff;
diff.m_Time = m_Time - time.m_Time;
return diff.Seconds() + NtpFractionToSecond(diff.Fraction());
}
else
{
CNtpTime diff;
diff.m_Time = time.m_Time - m_Time;
return -(diff.Seconds() + NtpFractionToSecond(diff.Fraction()));
}
}
CNtpTime CNtpTime::operator+(const double& timespan) const
{
CNtpTime rVal;
rVal.m_Time = m_Time;
if (timespan >= 0)
{
unsigned __int64 diff = ((unsigned __int64) timespan) << 32;
double intpart;
double frac = modf(timespan, &intpart);
diff += (unsigned __int64) (frac * 0xFFFFFFFF);
rVal.m_Time += diff;
}
else
{
double d = -timespan;
unsigned __int64 diff = ((unsigned __int64) d) << 32;
double intpart;
double frac = modf(d, &intpart);
diff += (unsigned __int64) (frac * 0xFFFFFFFF);
rVal.m_Time -= diff;
}
return rVal;
}
CNtpTime::operator SYSTEMTIME() const
{
//Currently this function only operates correctly in
//the 1900 - 2036 primary epoch defined by NTP
SYSTEMTIME st;
DWORD s = Seconds();
st.wSecond = (WORD)(s % 60);
s /= 60;
st.wMinute = (WORD)(s % 60);
s /= 60;
st.wHour = (WORD)(s % 24);
s /= 24;
long JD = s + JAN_1ST_1900;
st.wDayOfWeek = (WORD)((JD + 1) % 7);
GetGregorianDate(JD, st.wYear, st.wMonth, st.wDay);
st.wMilliseconds = NtpFractionToMs(Fraction());
return st;
}
DWORD CNtpTime::Seconds() const
{
return (DWORD) ((m_Time & 0xFFFFFFFF00000000) >> 32);
}
DWORD CNtpTime::Fraction() const
{
return (DWORD) (m_Time & 0xFFFFFFFF);
}
CNtpTime::operator CNtpTimePacket() const
{
CNtpTimePacket ntp;
ntp.m_dwInteger = htonl(Seconds());
ntp.m_dwFractional = htonl(Fraction());
return ntp;
}
CNtpTime CNtpTime::GetCurrentTime()
{
SYSTEMTIME st;
GetSystemTime(&st);
CNtpTime t(st);
return t;
}
DWORD CNtpTime::MsToNtpFraction(WORD wMilliSeconds)
{
ASSERT(wMilliSeconds < 1000);
return m_MsToNTP[wMilliSeconds];
}
WORD CNtpTime::NtpFractionToMs(DWORD dwFraction)
{
return (WORD)((((double)dwFraction) * NTP_FRACTIONAL_TO_MS) + 0.5);
}
double CNtpTime::NtpFractionToSecond(DWORD dwFraction)
{
double d = (double)dwFraction;
d *= NTP_TO_SECOND;
return ((double)dwFraction) * NTP_TO_SECOND;
}
CSNTPClient::CSNTPClient()
{
m_dwTimeout = 5000; //Default timeout of 5 seconds
m_nProxyPort = 1080;
m_bProxy = FALSE;
}
BOOL CSNTPClient::GetServerTime(LPCTSTR pszHostName, NtpServerResponse& response, int nPort)
{
//For correct operation of the T2A macro, see MFC Tech Note 59
USES_CONVERSION;
//paramater validity checking
ASSERT(pszHostName);
//Create the socket, Allocated of the heap so we can control
//the time when it's destructor is called. This means that
//we can call SetLastError after its destructor
CWSocket* pSocket = new CWSocket();
try
{
if (m_bProxy)
pSocket->Create(FALSE); //TCP if going thro a proxy
else
pSocket->Create(TRUE); //UDP otherwise
}
catch(CWSocketException* pEx)
{
pEx->Delete();
TRACE(_T("Failed to create client socket, GetLastError returns: %d\n"), GetLastError());
return FALSE;
}
//Connect to the SNTP server (or Socks Proxy)
try
{
if (m_bProxy)
{
if (m_sLocalBoundAddress.GetLength())
{
if (m_sProxyUserName.GetLength())
pSocket->ConnectViaSocks5(pszHostName, nPort, m_sProxyServer, m_nProxyPort, m_sProxyUserName, m_sProxyPassword, m_sLocalBoundAddress, m_dwTimeout, TRUE);
else
pSocket->ConnectViaSocks5(pszHostName, nPort, m_sProxyServer, m_nProxyPort, NULL, NULL, m_sLocalBoundAddress, m_dwTimeout, TRUE);
}
else
{
if (m_sProxyUserName.GetLength())
pSocket->ConnectViaSocks5(pszHostName, nPort, m_sProxyServer, m_nProxyPort, m_sProxyUserName, m_sProxyPassword, NULL, m_dwTimeout, TRUE);
else
pSocket->ConnectViaSocks5(pszHostName, nPort, m_sProxyServer, m_nProxyPort, NULL, NULL, NULL, m_dwTimeout, TRUE);
}
}
else
{
if (m_sLocalBoundAddress.GetLength())
pSocket->Connect(pszHostName, nPort, m_sLocalBoundAddress);
else
pSocket->Connect(pszHostName, nPort);
}
}
catch(CWSocketException* pEx)
{
TRACE(_T("Could not connect to the SNTP server %s on port %d, GetLastError returns: %d\n"), pszHostName, nPort, pEx->m_nError);
//Tidy up prior to returning
delete pSocket;
SetLastError(pEx->m_nError);
pEx->Delete();
return FALSE;
}
//Initialise the NtpBasicInfo packet
NtpBasicInfo nbi;
int nSendSize = sizeof(NtpBasicInfo);
memset(&nbi, 0, nSendSize);
nbi.m_LiVnMode = 27; //Encoded representation which represents NTP Client Request & NTP version 3.0 (i.e. LI=0, VN=3, Mode=3)
nbi.m_TransmitTimestamp = CNtpTime::GetCurrentTime();
//Send off the NtpBasicInfo packet
try
{
pSocket->Send(&nbi, nSendSize);
}
catch(CWSocketException* pEx)
{
TRACE(_T("Failed in call to send NTP request to the SNTP server, GetLastError returns %d\n"), pEx->m_nError);
//Tidy up prior to returning
delete pSocket;
SetLastError(pEx->m_nError);
pEx->Delete();
return FALSE;
}
//Need to use select to determine readibilty of socket
BOOL bReadable = FALSE;
try
{
bReadable = pSocket->IsReadible(m_dwTimeout);
}
catch(CWSocketException* pEx)
{
pEx->Delete();
bReadable = FALSE;
}
if (!bReadable)
{
TRACE(_T("Unable to wait for NTP reply from the SNTP server, GetLastError returns %d\n"), WSAETIMEDOUT);
//Tidy up prior to returning
delete pSocket;
SetLastError(WSAETIMEDOUT);
return FALSE;
}
response.m_DestinationTime = CNtpTime::GetCurrentTime();
//read back the response into the NtpFullPacket struct
NtpFullPacket nfp;
int nReceiveSize = sizeof(NtpFullPacket);
memset(&nfp, 0, nReceiveSize);
try
{
pSocket->Receive(&nfp, nReceiveSize);
}
catch(CWSocketException* pEx)
{
TRACE(_T("Unable to read reply from the SNTP server, Error returns %d\n"), pEx->m_nError);
//Tidy up prior to returning
DWORD dwError = GetLastError();
delete pSocket;
SetLastError(pEx->m_nError);
pEx->Delete();
return FALSE;
}
//Transfer all the useful info into the response structure
response.m_nStratum = nfp.m_Basic.m_Stratum;
response.m_nLeapIndicator = (nfp.m_Basic.m_LiVnMode & 0xC0) >> 6;
response.m_OriginateTime = nfp.m_Basic.m_OriginateTimestamp;
response.m_ReceiveTime = nfp.m_Basic.m_ReceiveTimestamp;
response.m_TransmitTime = nfp.m_Basic.m_TransmitTimestamp;
response.m_RoundTripDelay = (response.m_DestinationTime - response.m_OriginateTime) - (response.m_ReceiveTime - response.m_TransmitTime);
response.m_LocalClockOffset = ((response.m_ReceiveTime - response.m_OriginateTime) + (response.m_TransmitTime - response.m_DestinationTime)) / 2;
//Tidy up prior to returning
delete pSocket;
return TRUE;
}
//AR 22-07-2000
#ifndef _WIN32_WCE
BOOL CSNTPClient::EnableSetTimePriviledge()
{
BOOL bOpenToken = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES |
TOKEN_QUERY, &m_hToken);
m_bTakenPriviledge = FALSE;
if (!bOpenToken)
{
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
{
//Must be running on 95 or 98 not NT. In that case just ignore the error
SetLastError(ERROR_SUCCESS);
return TRUE;
}
TRACE(_T("Failed to get Adjust priviledge token\n"));
return FALSE;
}
ZeroMemory(&m_TokenPriv, sizeof(TOKEN_PRIVILEGES));
if (!LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &m_TokenPriv.Privileges[0].Luid))
{
TRACE(_T("Failed in callup to lookup priviledge\n"));
return FALSE;
}
m_TokenPriv.PrivilegeCount = 1;
m_TokenPriv.Privileges[0].Attributes |= SE_PRIVILEGE_ENABLED;
m_bTakenPriviledge = TRUE;
BOOL bSuccess = AdjustTokenPrivileges(m_hToken, FALSE, &m_TokenPriv, 0, NULL, 0);
if (!bSuccess)
TRACE(_T("Failed to adjust SetTime priviledge\n"));
return bSuccess;
}
#endif
//AR 22-07-2000
#ifndef _WIN32_WCE
void CSNTPClient::RevertSetTimePriviledge()
{
if (m_bTakenPriviledge)
{
m_TokenPriv.Privileges[0].Attributes &= (~SE_PRIVILEGE_ENABLED);
if (!AdjustTokenPrivileges(m_hToken, FALSE, &m_TokenPriv, 0, NULL, 0))
TRACE(_T("Failed to reset SetTime priviledge\n"));
CloseHandle(m_hToken);
}
}
#endif
BOOL CSNTPClient::SetClientTime(const CNtpTime& NewTime)
{
BOOL bSuccess = FALSE;
//AR 22-07-2000
#ifndef _WIN32_WCE
if (EnableSetTimePriviledge())
{
#endif
SYSTEMTIME st = NewTime;
bSuccess = SetSystemTime(&st);
if (!bSuccess)
TRACE(_T("Failed in call to set the system time\n"));
//AR 22-07-2000
#ifndef _WIN32_WCE
}
RevertSetTimePriviledge();
#endif
return bSuccess;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -