[CMAKE]
[reactos.git] / dll / cpl / timedate / ntpclient.c
1 /*
2 * PROJECT: ReactOS Timedate Control Panel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: lib/cpl/timedate/ntpclient.c
5 * PURPOSE: Queries the NTP server
6 * COPYRIGHT: Copyright 2006 Ged Murphy <gedmurphy@gmail.com>
7 *
8 */
9
10 #include <timedate.h>
11
12 #define TIMEOUT 4000 /* 4 second timeout */
13
14 typedef struct _INFO
15 {
16 SOCKET Sock;
17 SOCKADDR_IN myAddr;
18 SOCKADDR_IN ntpAddr;
19 NTPPACKET SendPacket;
20 NTPPACKET RecvPacket;
21 } INFO, *PINFO;
22
23
24 static BOOL
25 InitConnection(PINFO pInfo,
26 LPSTR lpAddress)
27 {
28 WSADATA wsaData;
29 HOSTENT *he;
30 INT Ret;
31
32 Ret = WSAStartup(MAKEWORD(2, 2),
33 &wsaData);
34 if (Ret != 0)
35 return FALSE;
36
37 pInfo->Sock = socket(AF_INET,
38 SOCK_DGRAM,
39 0);
40 if (pInfo->Sock == INVALID_SOCKET)
41 return FALSE;
42
43 /* setup server info */
44 he = gethostbyname(lpAddress);
45 if (he != NULL)
46 {
47 /* setup server socket info */
48 ZeroMemory(&pInfo->ntpAddr, sizeof(SOCKADDR_IN));
49 pInfo->ntpAddr.sin_family = AF_INET; //he->h_addrtype;
50 pInfo->ntpAddr.sin_port = htons(NTPPORT);
51 pInfo->ntpAddr.sin_addr = *((struct in_addr *)he->h_addr);
52 }
53 else
54 return FALSE;
55
56 return TRUE;
57 }
58
59
60 static VOID
61 DestroyConnection(VOID)
62 {
63 WSACleanup();
64 }
65
66
67 static BOOL
68 GetTransmitTime(PTIMEPACKET ptp)
69 {
70 return TRUE;
71 }
72
73
74 /* send some data to wake the server up */
75 static BOOL
76 SendData(PINFO pInfo)
77 {
78 TIMEPACKET tp = { 0, 0 };
79 INT Ret;
80
81 ZeroMemory(&pInfo->SendPacket, sizeof(pInfo->SendPacket));
82 pInfo->SendPacket.LiVnMode = 27;
83 if (!GetTransmitTime(&tp))
84 return FALSE;
85 pInfo->SendPacket.TransmitTimestamp = tp;
86
87 Ret = sendto(pInfo->Sock,
88 (char *)&pInfo->SendPacket,
89 sizeof(pInfo->SendPacket),
90 0,
91 (SOCKADDR *)&pInfo->ntpAddr,
92 sizeof(SOCKADDR_IN));
93
94 if (Ret == SOCKET_ERROR)
95 return FALSE;
96
97 return TRUE;
98 }
99
100
101 static ULONG
102 RecieveData(PINFO pInfo)
103 {
104 TIMEVAL timeVal;
105 FD_SET readFDS;
106 INT Ret;
107 ULONG ulTime = 0;
108
109 /* monitor socket for incomming connections */
110 FD_ZERO(&readFDS);
111 FD_SET(pInfo->Sock, &readFDS);
112
113 /* set timeout values */
114 timeVal.tv_sec = TIMEOUT / 1000;
115 timeVal.tv_usec = TIMEOUT % 1000;
116
117 /* check for data on the socket for TIMEOUT millisecs*/
118 Ret = select(0, &readFDS, NULL, NULL, &timeVal);
119
120 if ((Ret != SOCKET_ERROR) && (Ret != 0))
121 {
122
123 Ret = recvfrom(pInfo->Sock,
124 (char *)&pInfo->RecvPacket,
125 sizeof(pInfo->RecvPacket),
126 0,
127 NULL,
128 NULL);
129 if (Ret != SOCKET_ERROR)
130 ulTime = ntohl(ulTime);
131 }
132
133 return ulTime;
134 }
135
136
137 ULONG
138 GetServerTime(LPWSTR lpAddress)
139 {
140 PINFO pInfo;
141 LPSTR lpAddr;
142 DWORD dwSize = wcslen(lpAddress) + 1;
143 ULONG ulTime = 0;
144
145 pInfo = (PINFO)HeapAlloc(GetProcessHeap(),
146 0,
147 sizeof(INFO));
148 lpAddr = (LPSTR)HeapAlloc(GetProcessHeap(),
149 0,
150 dwSize);
151
152 if (pInfo && lpAddr)
153 {
154 if (WideCharToMultiByte(CP_ACP,
155 0,
156 lpAddress,
157 -1,
158 lpAddr,
159 dwSize,
160 NULL,
161 NULL))
162 {
163 if (InitConnection(pInfo, lpAddr))
164 {
165 if (SendData(pInfo))
166 {
167 ulTime = RecieveData(pInfo);
168 }
169 }
170
171 DestroyConnection();
172 }
173 }
174
175 if (pInfo)
176 HeapFree(GetProcessHeap(), 0, pInfo);
177 if (lpAddr)
178 HeapFree(GetProcessHeap(), 0, lpAddr);
179
180 return ulTime;
181 }