Hello,

I am currently working on the nut scanner. For detecting available upsd
on the network, I rely on upscli_connect. The problem with this function
is that it calls a blocking "connect" function. So the nut-scanner is
blocked while waiting for the TCP timeout when trying to connect to an
IP without upsd available . Since this timeout may be rather long (3
minutes on my host), I would like to add a timeout parameter to
upscli_connect.
I propose to add a upscli_tryconnect function accepting a timeout
parameter, which will be the copy of the current upscli_connect + the
management of the timeout. The upscli_connect will be only a wrapper on
top of upscli_tryconnect, calling it without timeout.
Please let me know if this makes sense to you.

See a diff in attachment.

Regards,
Fred

-- 
Team Open Source Eaton - http://powerquality.eaton.com

--------------------------------------------------------------------------
Index: upsclient.c
===================================================================
--- upsclient.c	(revision 3026)
+++ upsclient.c	(working copy)
@@ -393,12 +393,16 @@
 
 #endif	/* HAVE_SSL */
 
-int upscli_connect(UPSCONN_t *ups, const char *host, int port, int flags)
+int upscli_tryconnect(UPSCONN_t *ups, const char *host, int port, int flags,struct timeval * timeout)
 {
 	int	sock_fd;
 	struct addrinfo	hints, *res, *ai;
 	char			sport[NI_MAXSERV];
 	int			v;
+	fd_set 			wfds;
+	int			ret;
+	int			error;
+	socklen_t		error_size;
 
 	if (!ups) {
 		return -1;
@@ -450,6 +454,9 @@
 	}
 
 	for (ai = res; ai != NULL; ai = ai->ai_next) {
+		if(timeout != NULL) {
+			ai->ai_socktype |= SOCK_NONBLOCK;
+		}
 
 		sock_fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
 
@@ -467,7 +474,32 @@
 		}
 
 		while ((v = connect(sock_fd, ai->ai_addr, ai->ai_addrlen)) < 0) {
-			switch (errno)
+			error = errno;
+
+			if(error == EINPROGRESS) {
+				FD_ZERO(&wfds);
+				FD_SET(sock_fd, &wfds);
+				ret = select(sock_fd+1,NULL,&wfds,NULL,
+						timeout);
+				if (FD_ISSET(sock_fd, &wfds)) {
+					error_size = sizeof(error);
					getsockopt(sock_fd,SOL_SOCKET,SO_ERROR,
+							&error,&error_size);
+					if( error == 0) {
+						/* connect successful */
+						v = 0;
+						break;
+					}
+		
+				}
+				else {
+					/* Timeout */
+					v = -1;
+					break;
+				}
+			}
+
+			switch (error)
 			{
 			case EAFNOSUPPORT:
 				break;
@@ -476,9 +508,10 @@
 				continue;
 			default:
 				ups->upserror = UPSCLI_ERR_CONNFAILURE;
-				ups->syserrno = errno;
+				ups->syserrno = error;
 			}
 			break;
+
 		}
 
 		if (v < 0) {
@@ -529,6 +562,10 @@
 	return 0;
 }
 
+int upscli_connect(UPSCONN_t *ups, const char *host, int port, int flags)
+{
+	return upscli_tryconnect(ups,host,port,flags,NULL);
+}
 /* map upsd error strings back to upsclient internal numbers */
 static struct {
 	int	errnum;
_______________________________________________
Nut-upsdev mailing list
[email protected]
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/nut-upsdev

Reply via email to