Last active
August 29, 2015 14:04
-
-
Save icedac/15b232931b92ec6fb36b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Timesync.cpp : time resync from NTP server | |
// ref: http://www.abnormal.com/~thogard/ntp/ | |
// ref: http://stackoverflow.com/a/19815921 | |
#include <winsock2.h> | |
#include <time.h> | |
#include <strsafe.h> | |
#pragma comment( lib, "ws2_32.lib" ) | |
#include <stdio.h> | |
#include <sys/types.h> | |
#include <stdint.h> | |
#include <math.h> | |
//#include <sys/socket.h> | |
//#include <arpa/inet.h> | |
//#include <netinet/in.h> | |
//#include <netdb.h> | |
#define NTP_MODE_CLIENT 3 | |
#define NTP_VERSION 3 | |
#define TRANSMIT_TIME_OFFSET 40 | |
#define REFERENCE_TIME_OFFSET 16 | |
#define ORIGINATE_TIME_OFFSET 24 | |
#define RECEIVE_TIME_OFFSET 32 | |
//#define OFFSET_1900_TO_1970 ((uint64_t)((365 * 70) + 17) * 24 * 60 * 60) | |
#define OFFSET_1900_TO_1970 2208988800U | |
uint32_t read32(char* buffer, int offset) { | |
char b0 = buffer[offset]; | |
char b1 = buffer[offset + 1]; | |
char b2 = buffer[offset + 2]; | |
char b3 = buffer[offset + 3]; | |
// convert signed bytes to unsigned values | |
uint32_t i0 = ((b0 & 0x80) == 0x80 ? (b0 & 0x7F) + 0x80 : b0); | |
uint32_t i1 = ((b1 & 0x80) == 0x80 ? (b1 & 0x7F) + 0x80 : b1); | |
uint32_t i2 = ((b2 & 0x80) == 0x80 ? (b2 & 0x7F) + 0x80 : b2); | |
uint32_t i3 = ((b3 & 0x80) == 0x80 ? (b3 & 0x7F) + 0x80 : b3); | |
uint32_t v = (i0 << 24) + (i1 << 16) + (i2 << 8) + i3; | |
return v; | |
} | |
uint64_t readTimeStamp(char *buffer, int offset) { | |
uint32_t seconds = read32(buffer, offset); | |
uint32_t fraction = read32(buffer, offset + 4); | |
uint64_t v = ((int64_t)seconds - OFFSET_1900_TO_1970) * 1000 + (int64_t)fraction * 1000 / (int64_t)0x100000000; | |
// printf ("%llu\n", v); | |
return v; | |
} | |
void writeTimeStamp(char* buffer, int offset, long long int time) { | |
uint64_t seconds = (time / 1000); | |
uint64_t milliseconds = time - (uint64_t)seconds * 1000; | |
seconds += OFFSET_1900_TO_1970; | |
// write seconds in big endian format | |
buffer[offset++] = (char)(seconds >> 24); | |
buffer[offset++] = (char)(seconds >> 16); | |
buffer[offset++] = (char)(seconds >> 8); | |
buffer[offset++] = (char)(seconds >> 0); | |
uint64_t fraction = ((uint64_t)milliseconds * 0x100000000 / 1000); | |
// write fraction in big endian format | |
buffer[offset++] = (char)(fraction >> 24); | |
buffer[offset++] = (char)(fraction >> 16); | |
buffer[offset++] = (char)(fraction >> 8); | |
// low order bits should be random data | |
buffer[offset++] = (char)(rand() * 255.0); | |
} | |
void ErrorExit( const TCHAR* functionName ) | |
{ | |
// Retrieve the system error message for the last-error code | |
LPVOID lpMsgBuf; | |
LPVOID lpDisplayBuf; | |
DWORD dw = GetLastError(); | |
FormatMessage( | |
FORMAT_MESSAGE_ALLOCATE_BUFFER | | |
FORMAT_MESSAGE_FROM_SYSTEM | | |
FORMAT_MESSAGE_IGNORE_INSERTS, | |
NULL, | |
dw, | |
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | |
(LPTSTR)&lpMsgBuf, | |
0, NULL); | |
// Display the error message and exit the process | |
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, | |
(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)functionName) + 40) * sizeof(TCHAR)); | |
StringCchPrintf((LPTSTR)lpDisplayBuf, | |
LocalSize(lpDisplayBuf) / sizeof(TCHAR), | |
TEXT("%s failed with error %d: %s"), | |
functionName, dw, lpMsgBuf); | |
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK); | |
LocalFree(lpMsgBuf); | |
LocalFree(lpDisplayBuf); | |
ExitProcess(dw); | |
} | |
void print_time(int64_t milliseconds_from_1970 ) | |
{ | |
time_t tt = (milliseconds_from_1970 / 1000); | |
int msec = tt % 1000; | |
// printf("%s", ctime(&tt)); | |
tm* t = localtime(&tt); | |
printf("%04d-%02d-%02d %02d:%02d:%02d.%03d\n", 1900+t->tm_year, 1+t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, msec ); | |
} | |
int64_t ntpdate(const char* ntp_hostname) | |
{ | |
const int NTP_PORT = 123; //NTP is port 123 | |
const int MAXLEN = 1024; //check our buffers | |
int i; // misc var i | |
char msg[48]; | |
memset(msg, 0, sizeof(msg)); | |
msg[0] = NTP_MODE_CLIENT | (NTP_VERSION << 3); | |
writeTimeStamp(msg, TRANSMIT_TIME_OFFSET, GetTickCount64()); | |
char buf[MAXLEN] = { 0, }; // the buffer we get back | |
//struct in_addr ipaddr; // | |
struct protoent *proto; // | |
struct sockaddr_in server_addr; | |
int s; // socket | |
time_t tmit; // the time -- This is a time_t sort of | |
//use Socket; | |
// | |
//#we use the system call to open a UDP socket | |
//socket(SOCKET, PF_INET, SOCK_DGRAM, getprotobyname("udp")) or die "socket: $!"; | |
proto = getprotobyname("udp"); | |
if (nullptr == proto) ErrorExit(_T("getprotobyname")); | |
s = socket(PF_INET, SOCK_DGRAM, proto->p_proto); | |
if (s == SOCKET_ERROR) ErrorExit(_T("socket")); | |
memset(&server_addr, 0, sizeof(server_addr)); | |
server_addr.sin_family = AF_INET; | |
server_addr.sin_addr.s_addr = inet_addr(ntp_hostname); | |
server_addr.sin_port = htons(NTP_PORT); | |
/* | |
* build a message. Our message is all zeros except for a one in the | |
* protocol version field | |
* msg[] in binary is 00 001 000 00000000 | |
* it should be a total of 48 bytes long | |
*/ | |
DWORD tickStart = GetTickCount(); | |
// send the data | |
i = sendto(s, msg, sizeof(msg), 0, (struct sockaddr *)&server_addr, sizeof(server_addr)); | |
if (-1 == i) ErrorExit(_T("sendto")); | |
// get the data back | |
i = recv(s, (char*)buf, sizeof(buf), 0); | |
if (-1 == i) ErrorExit(_T("recv")); | |
DWORD rtt = GetTickCount() - tickStart; | |
//We get 12 long words back in Network order | |
/* | |
for(i=0;i<12;i++) | |
printf("%d\t%-8x\n",i,ntohl(buf[i])); | |
*/ | |
/* | |
* The high word of transmit time is the 10th word we get back | |
* tmit is the time in seconds not accounting for network delays which | |
* should be way less than a second if this is a local NTP server | |
*/ | |
int64_t originateTime = readTimeStamp(buf, ORIGINATE_TIME_OFFSET); | |
int64_t receiveTime = readTimeStamp(buf, RECEIVE_TIME_OFFSET); | |
int64_t transmitTime = readTimeStamp(buf, TRANSMIT_TIME_OFFSET); | |
/* | |
print_time(transmitTime); | |
print_time(receiveTime); | |
print_time(transmitTime); | |
time_t tt = time(nullptr); | |
print_time(tt*1000); | |
*/ | |
printf("Round trip time from %s is <%d> msec.\n", ntp_hostname, rtt); | |
int64_t transmitTime_with_rtt_adjust = transmitTime + (rtt / 2); | |
return transmitTime_with_rtt_adjust; | |
} | |
int _tmain(int argc, _TCHAR* argv[]) | |
{ | |
const WORD WINSOCK_VERSION_ID = 0x202; | |
WSADATA wsaData; | |
WSAStartup(WINSOCK_VERSION_ID, &wsaData); | |
//ntpdate("time-b.nist.gov"); = 129.6.15.29 | |
const char* ntpserver_ip = "129.6.15.29"; | |
int64_t tt_msec = ntpdate("129.6.15.29"); | |
time_t tt = tt_msec / 1000; | |
int msec = tt_msec % 1000; | |
tm* t = nullptr; | |
t = localtime(&tt); | |
if (nullptr == t) ErrorExit(_T("localtime")); | |
printf("%04d-%02d-%02d %02d:%02d:%02d.%03d[LOCAL] time from NTP[%s]\n", 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, msec, ntpserver_ip); | |
t = gmtime(&tt); | |
if (nullptr == t) ErrorExit(_T("gmtime")); | |
printf("%04d-%02d-%02d %02d:%02d:%02d.%03d[UTC+0] time from NTP[%s]\n", 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, msec, ntpserver_ip); | |
SYSTEMTIME st; | |
GetLocalTime(&st); | |
printf("%04d-%02d-%02d %02d:%02d:%02d.%03d[LOCAL] time from LOCAL\n", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds); | |
GetSystemTime(&st); | |
printf("%04d-%02d-%02d %02d:%02d:%02d.%03d[UTC+0] time from LOCAL\n", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds); | |
st.wYear = 1900 + t->tm_year; | |
st.wMonth = 1 + t->tm_mon; | |
st.wDay = t->tm_mday; | |
st.wHour = t->tm_hour; | |
st.wMinute = t->tm_min; | |
st.wSecond = t->tm_sec; | |
st.wMilliseconds = msec; | |
BOOL success = SetSystemTime(&st); | |
if (!success) ErrorExit(_T("SetSystemTime")); | |
printf("Time setted from %s.\n", ntpserver_ip); | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment