a47e7117745b18388f54ebb9a85a55550d88788f galt Wed Oct 23 09:56:36 2013 -0700 set network default read write timeout for tcp connections to browser defaults -- around 2 minutes=120 seconds. Specific applications can call the new function setReadWriteTimeouts on an open socket if they need them to be longer or shorter. diff --git src/lib/net.c src/lib/net.c index 2804ac4..8654d31 100644 --- src/lib/net.c +++ src/lib/net.c @@ -24,72 +24,95 @@ extern int errno; static int netStreamSocket() /* Create a TCP/IP streaming socket. Complain and return something * negative if can't */ { int sd = socket(AF_INET, SOCK_STREAM, 0); if (sd < 0) warn("Couldn't make AF_INET socket."); return sd; } static int setSocketNonBlocking(int sd, boolean set) /* Use socket control flags to set O_NONBLOCK if set==TRUE, * or clear it if set==FALSE. - * Return -1 if there are any errors, 0 if successful. i - * Also closes sd if error. */ + * Return -1 if there are any errors, 0 if successful. */ { long fcntlFlags; // Set or clear non-blocking if ((fcntlFlags = fcntl(sd, F_GETFL, NULL)) < 0) { warn("Error fcntl(..., F_GETFL) (%s)", strerror(errno)); return -1; } if (set) fcntlFlags |= O_NONBLOCK; else fcntlFlags &= (~O_NONBLOCK); if (fcntl(sd, F_SETFL, fcntlFlags) < 0) { warn("Error fcntl(..., F_SETFL) (%s)", strerror(errno)); return -1; } return 0; } +int setReadWriteTimeouts(int sd, int seconds) +/* Set read and write timeouts on socket sd + * Return -1 if there are any errors, 0 if successful. */ +{ +struct timeval timeout; +timeout.tv_sec = seconds; +timeout.tv_usec = 0; + +if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0) + { + warn("setsockopt failed setting socket receive timeout\n"); + return -1; + } + +if (setsockopt(sd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) < 0) + { + warn("setsockopt failed setting socket send timeout\n"); + return -1; + } +return 0; +} + + static struct timeval tvMinus(struct timeval a, struct timeval b) /* Return the result of a - b; this handles wrapping of milliseconds. * result.tv_usec will always be positive. * result.tv_sec will be negative if b > a. */ { // subtract b from a. if (a.tv_usec < b.tv_usec) { a.tv_usec += 1000000; a.tv_sec--; } a.tv_usec -= b.tv_usec; a.tv_sec -= b.tv_sec; return a; } static int netConnectWithTimeout(char *hostName, int port, long msTimeout) /* In order to avoid a very long default timeout (several minutes) for hosts that will * not answer the port, we are forced to connect non-blocking. - * After the connection has been established, we return to blocking mode. */ + * After the connection has been established, we return to blocking mode. + * Also closes sd if error. */ { int sd; struct sockaddr_in sai; /* Some system socket info. */ int res; fd_set mySet; if (hostName == NULL) { warn("NULL hostName in netConnect"); return -1; } if (!internetFillInAddress(hostName, port, &sai)) return -1; if ((sd = netStreamSocket()) < 0) return sd; @@ -175,30 +198,36 @@ else { warn("TCP non-blocking connect() error %d - %s", errno, strerror(errno)); close(sd); return -1; } } // Set to blocking mode again if (setSocketNonBlocking(sd, FALSE) < 0) { close(sd); return -1; } +if (setReadWriteTimeouts(sd, DEFAULTREADWRITETTIMEOUTSEC) < 0) + { + close(sd); + return -1; + } + return sd; } int netConnect(char *hostName, int port) /* Start connection with a server. */ { return netConnectWithTimeout(hostName, port, DEFAULTCONNECTTIMEOUTMSEC); // 10 seconds connect timeout } int netMustConnect(char *hostName, int port) /* Start connection with server or die. */ { int sd = netConnect(hostName, port);