A port and bug fix of Alix955/code/ntp-client. The socket would hang as it was defined both with a timeout and as blocking.
NTPClient.cpp@2:a3aec199dc7c, 2019-05-26 (annotated)
- Committer:
- sjalloq
- Date:
- Sun May 26 08:46:35 2019 +0100
- Revision:
- 2:a3aec199dc7c
- Parent:
- 1:099750f42b02
ntp-client : fork from Alix955/code/ntp-client
- sockets should not be setup as blocking if you want to use a timeout. This
resulted in the socket hanging when packets went missing.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Alix955 | 0:3c1170035e2b | 1 | #include "ntp-client/NTPClient.h" |
Alix955 | 0:3c1170035e2b | 2 | #include "mbed.h" |
Alix955 | 0:3c1170035e2b | 3 | |
sjalloq | 2:a3aec199dc7c | 4 | NTPClient::NTPClient(NetworkInterface *iface) : iface(iface), |
sjalloq | 2:a3aec199dc7c | 5 | nist_server_address((char *)NTP_DEFULT_NIST_SERVER_ADDRESS), |
sjalloq | 2:a3aec199dc7c | 6 | nist_server_port(NTP_DEFULT_NIST_SERVER_PORT) { |
Alix955 | 0:3c1170035e2b | 7 | } |
Alix955 | 0:3c1170035e2b | 8 | |
sjalloq | 2:a3aec199dc7c | 9 | void NTPClient::set_server(char* server, int port) { |
Alix955 | 0:3c1170035e2b | 10 | nist_server_address = server; |
sjalloq | 2:a3aec199dc7c | 11 | nist_server_port = port; |
Alix955 | 0:3c1170035e2b | 12 | } |
Alix955 | 0:3c1170035e2b | 13 | |
sjalloq | 2:a3aec199dc7c | 14 | /* The timeout value is in uS. A sensible positive value is >5K to |
sjalloq | 2:a3aec199dc7c | 15 | avoid the timeout firing on slow responses. Note that this is UDP |
sjalloq | 2:a3aec199dc7c | 16 | so there is the likely possibility that the packet will be lost. |
sjalloq | 2:a3aec199dc7c | 17 | |
sjalloq | 2:a3aec199dc7c | 18 | A timeout value of 0 corresponds to set_blocking(false). |
sjalloq | 2:a3aec199dc7c | 19 | A timeout value of -1 corresponds to set_blocking(true). |
sjalloq | 2:a3aec199dc7c | 20 | */ |
Alix955 | 0:3c1170035e2b | 21 | time_t NTPClient::get_timestamp(int timeout) { |
sjalloq | 2:a3aec199dc7c | 22 | const time_t TIME1970 = (time_t)2208988800UL; |
sjalloq | 2:a3aec199dc7c | 23 | int ntp_send_values[12] = {0}; |
sjalloq | 2:a3aec199dc7c | 24 | int ntp_recv_values[12] = {0}; |
Alix955 | 0:3c1170035e2b | 25 | |
sjalloq | 2:a3aec199dc7c | 26 | SocketAddress nist; |
sjalloq | 2:a3aec199dc7c | 27 | UDPSocket sock; |
sjalloq | 2:a3aec199dc7c | 28 | SocketAddress source; |
sjalloq | 2:a3aec199dc7c | 29 | |
sjalloq | 2:a3aec199dc7c | 30 | nsapi_size_or_error_t szerr; |
Alix955 | 0:3c1170035e2b | 31 | |
sjalloq | 2:a3aec199dc7c | 32 | int ret_gethostbyname = iface->gethostbyname(nist_server_address, &nist); |
sjalloq | 2:a3aec199dc7c | 33 | if (ret_gethostbyname < 0) { |
sjalloq | 2:a3aec199dc7c | 34 | // Network error on DNS lookup |
sjalloq | 2:a3aec199dc7c | 35 | printf("Error on DNS lookup : %d\n" , ret_gethostbyname); |
sjalloq | 2:a3aec199dc7c | 36 | return ret_gethostbyname; |
sjalloq | 2:a3aec199dc7c | 37 | } |
sjalloq | 2:a3aec199dc7c | 38 | nist.set_port(nist_server_port); |
Alix955 | 0:3c1170035e2b | 39 | |
sjalloq | 2:a3aec199dc7c | 40 | memset(ntp_recv_values, 0x00, sizeof(ntp_recv_values)); |
sjalloq | 2:a3aec199dc7c | 41 | memset(ntp_send_values, 0x00, sizeof(ntp_send_values)); |
sjalloq | 2:a3aec199dc7c | 42 | ntp_send_values[0] = '\x1b'; |
Alix955 | 0:3c1170035e2b | 43 | |
sjalloq | 2:a3aec199dc7c | 44 | sock.open(iface); |
sjalloq | 2:a3aec199dc7c | 45 | sock.set_timeout(timeout); |
sjalloq | 2:a3aec199dc7c | 46 | |
sjalloq | 2:a3aec199dc7c | 47 | szerr = sock.sendto(nist, (void*)ntp_send_values, sizeof(ntp_send_values)); |
sjalloq | 2:a3aec199dc7c | 48 | if(szerr < 0) { |
sjalloq | 2:a3aec199dc7c | 49 | sock.close(); |
sjalloq | 2:a3aec199dc7c | 50 | printf("sock.sendto() error code = %d\n\r", szerr); |
sjalloq | 2:a3aec199dc7c | 51 | return szerr; |
sjalloq | 2:a3aec199dc7c | 52 | } |
Alix955 | 0:3c1170035e2b | 53 | |
sjalloq | 2:a3aec199dc7c | 54 | szerr = sock.recvfrom(&source, (void*)ntp_recv_values, sizeof(ntp_recv_values)); |
sjalloq | 2:a3aec199dc7c | 55 | if(szerr < 0) { |
sjalloq | 2:a3aec199dc7c | 56 | sock.close(); |
sjalloq | 2:a3aec199dc7c | 57 | printf("sock.sendto() error code = %d\n\r", szerr); |
sjalloq | 2:a3aec199dc7c | 58 | return szerr; |
sjalloq | 2:a3aec199dc7c | 59 | } |
Alix955 | 0:3c1170035e2b | 60 | |
sjalloq | 2:a3aec199dc7c | 61 | if (szerr > 10) { |
Alix955 | 0:3c1170035e2b | 62 | return ntohl(ntp_recv_values[10]) - TIME1970; |
Alix955 | 0:3c1170035e2b | 63 | } else { |
sjalloq | 2:a3aec199dc7c | 64 | // No or partial data returned |
sjalloq | 2:a3aec199dc7c | 65 | printf("No or partial data returned: bytes=%d\n\r", szerr); |
sjalloq | 2:a3aec199dc7c | 66 | return -1; |
sjalloq | 2:a3aec199dc7c | 67 | } |
Alix955 | 0:3c1170035e2b | 68 | } |
Alix955 | 0:3c1170035e2b | 69 | |
Alix955 | 0:3c1170035e2b | 70 | uint32_t NTPClient::ntohl(uint32_t x) { |
Alix955 | 0:3c1170035e2b | 71 | uint32_t ret = (x & 0xff) << 24; |
Alix955 | 0:3c1170035e2b | 72 | ret |= (x & 0xff00) << 8; |
Alix955 | 0:3c1170035e2b | 73 | ret |= (x & 0xff0000UL) >> 8; |
Alix955 | 0:3c1170035e2b | 74 | ret |= (x & 0xff000000UL) >> 24; |
Alix955 | 0:3c1170035e2b | 75 | return ret; |
sjalloq | 2:a3aec199dc7c | 76 | } |