From 03faadc0d045a9683d1ce0b8aca6af7f7b287767 Mon Sep 17 00:00:00 2001 From: CryptoManiac Date: Thu, 17 Sep 2015 05:56:04 -0700 Subject: [PATCH] Use non-blocking socket for recvfrom. --- src/ntp.cpp | 38 ++++++++++++++++++++++++++++++++++++-- src/rpcnet.cpp | 20 +++++++++++++++----- 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/src/ntp.cpp b/src/ntp.cpp index 19146ca..b125e35 100644 --- a/src/ntp.cpp +++ b/src/ntp.cpp @@ -13,6 +13,7 @@ #endif #include "netbase.h" +#include "util.h" extern int GetRandInt(int nMax); @@ -248,6 +249,7 @@ bool InitWithHost(std::string &strHostName, SOCKET &sockfd, socklen_t &servlen, return false; // "connection" error } + *pcliaddr = *((struct sockaddr *) &servaddr); servlen = sizeof(servaddr); @@ -257,6 +259,20 @@ bool InitWithHost(std::string &strHostName, SOCKET &sockfd, socklen_t &servlen, int64_t DoReq(SOCKET sockfd, socklen_t servlen, struct sockaddr cliaddr) { + +#ifdef WIN32 + u_long nOne = 1; + if (ioctlsocket(sockfd, FIONBIO, &nOne) == SOCKET_ERROR) + { + printf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %d\n", WSAGetLastError()); +#else + if (fcntl(sockfd, F_SETFL, O_NONBLOCK) == SOCKET_ERROR) + { + printf("ConnectSocket() : fcntl non-blocking setting failed, error %d\n", errno); +#endif + return -2; + } + struct pkt *msg = new pkt; struct pkt *prt = new pkt; @@ -277,8 +293,26 @@ int64_t DoReq(SOCKET sockfd, socklen_t servlen, struct sockaddr cliaddr) msg->xmt.Ul_f.Xl_f=0; int len=48; - sendto(sockfd, (char *) msg, len, 0, &cliaddr, servlen); - int n = recvfrom(sockfd, (char *) msg, len, 0, NULL, NULL); + int retcode = sendto(sockfd, (char *) msg, len, 0, &cliaddr, servlen); + if (retcode < 0) { + printf("sendto() failed: %d", retcode); + return -3; + } + + retcode = 0; + int nWait = 0; + + while(retcode <= 0) { + Sleep(1000); + retcode = recvfrom(sockfd, (char *) msg, len, 0, NULL, NULL); + + if (nWait > 4) { + printf("recvfrom() timeout"); + return -4; + } + + nWait++; + } ntohl_fp(&msg->rec, &prt->rec); ntohl_fp(&msg->xmt, &prt->xmt); diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index d0f4516..ab3f281 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -363,11 +363,21 @@ Value ntptime(const Array& params, bool fHelp) else nTime = NtpGetTime(); - if (nTime < 0) - throw runtime_error("Request error"); - Object obj; - obj.push_back(Pair("epoch", nTime)); - obj.push_back(Pair("time", DateTimeStrFormat(nTime))); + switch (nTime) + { + case -1: + throw runtime_error("Socket initialization error"); + case -2: + throw runtime_error("Switching socket mode to non-blocking failed"); + case -3: + throw runtime_error("Unable to send data"); + case -4: + throw runtime_error("Receive timed out"); + default: + obj.push_back(Pair("epoch", nTime)); + obj.push_back(Pair("time", DateTimeStrFormat(nTime))); + } + return obj; } -- 1.7.1