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