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

Committer:
sjalloq
Date:
2019-05-26
Revision:
2:a3aec199dc7c
Parent:
1:099750f42b02

File content as of revision 2:a3aec199dc7c:

#include "ntp-client/NTPClient.h"
#include "mbed.h"

NTPClient::NTPClient(NetworkInterface *iface) :	iface(iface), 
												nist_server_address((char *)NTP_DEFULT_NIST_SERVER_ADDRESS), 
												nist_server_port(NTP_DEFULT_NIST_SERVER_PORT) {
}

void NTPClient::set_server(char* server, int port) {
    nist_server_address = server;
    nist_server_port    = port;
}

/* The timeout value is in uS.  A sensible positive value is >5K to 
	avoid the timeout firing on slow responses.  Note that this is UDP
	so there is the likely possibility that the packet will be lost. 
	
	A timeout value of 0 corresponds to set_blocking(false).
	A timeout value of -1 corresponds to set_blocking(true).
*/
time_t NTPClient::get_timestamp(int timeout) {
	const time_t TIME1970 = (time_t)2208988800UL;
	int ntp_send_values[12] = {0};
	int ntp_recv_values[12] = {0};

	SocketAddress nist;
	UDPSocket sock;
	SocketAddress source;
	
	nsapi_size_or_error_t szerr;

	int ret_gethostbyname = iface->gethostbyname(nist_server_address, &nist);
	if (ret_gethostbyname < 0) {
		// Network error on DNS lookup
		printf("Error on DNS lookup : %d\n" , ret_gethostbyname);
		return ret_gethostbyname;
	}
	nist.set_port(nist_server_port);

	memset(ntp_recv_values, 0x00, sizeof(ntp_recv_values));
	memset(ntp_send_values, 0x00, sizeof(ntp_send_values));
	ntp_send_values[0] = '\x1b';

	sock.open(iface);
	sock.set_timeout(timeout);
	
	szerr = sock.sendto(nist, (void*)ntp_send_values, sizeof(ntp_send_values));
	if(szerr < 0) {
		sock.close();
		printf("sock.sendto() error code = %d\n\r", szerr);
		return szerr;
	}

    szerr = sock.recvfrom(&source, (void*)ntp_recv_values, sizeof(ntp_recv_values));
	if(szerr < 0) {
		sock.close();
		printf("sock.sendto() error code = %d\n\r", szerr);
		return szerr;
	}

    if (szerr > 10) {
        return ntohl(ntp_recv_values[10]) - TIME1970;
    } else {
		// No or partial data returned
		printf("No or partial data returned: bytes=%d\n\r", szerr);
        return -1;
	}
}

uint32_t NTPClient::ntohl(uint32_t x) {
    uint32_t ret = (x & 0xff) << 24;
    ret |= (x & 0xff00) << 8;
    ret |= (x & 0xff0000UL) >> 8;
    ret |= (x & 0xff000000UL) >> 24;
    return ret;
}