From d7b5499013188ddc78f2b770cce78543b3b7c48c Mon Sep 17 00:00:00 2001 From: venaas Date: Thu, 5 Feb 2009 10:09:14 +0000 Subject: timeout for connect git-svn-id: https://svn.testnett.uninett.no/radsecproxy/trunk@467 e88ac4ed-0b26-0410-9574-a7f39faa03bf --- hostport.c | 2 +- list.c | 14 +++++++++++--- list.h | 12 +++++++++++- radsecproxy.c | 1 - util.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- util.h | 3 ++- 6 files changed, 68 insertions(+), 9 deletions(-) diff --git a/hostport.c b/hostport.c index 238af0e..22ff2dc 100644 --- a/hostport.c +++ b/hostport.c @@ -285,7 +285,7 @@ int connecttcphostlist(struct list *hostports, struct addrinfo *src) { for (entry = list_first(hostports); entry; entry = list_next(entry)) { hp = (struct hostportres *)entry->data; debug(DBG_WARN, "connecttcphostlist: trying to open TCP connection to %s port %s", hp->host, hp->port); - if ((s = connecttcp(hp->addrinfo, src)) >= 0) { + if ((s = connecttcp(hp->addrinfo, src, list_count(hostports) > 1 ? 5 : 30)) >= 0) { debug(DBG_WARN, "connecttcphostlist: TCP connection to %s port %s up", hp->host, hp->port); return s; } diff --git a/list.c b/list.c index 269ce09..ad0f8d0 100644 --- a/list.c +++ b/list.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2008 Stig Venaas + * Copyright (C) 2006-2009 Stig Venaas * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -49,7 +49,8 @@ int list_push(struct list *list, void *data) { else list->first = node; list->last = node; - + + list->count++; return 1; } @@ -67,7 +68,7 @@ void *list_shift(struct list *list) { list->last = NULL; data = node->data; free(node); - + list->count--; return data; } @@ -82,6 +83,7 @@ void list_removedata(struct list *list, void *data) { while (node->data == data) { list->first = node->next; free(node); + list->count--; node = list->first; if (!node) { list->last = NULL; @@ -93,6 +95,7 @@ void list_removedata(struct list *list, void *data) { t = node->next; node->next = t->next; free(t); + list->count--; if (!node->next) { /* we removed the last one */ list->last = node; return; @@ -109,3 +112,8 @@ struct list_node *list_first(struct list *list) { struct list_node *list_next(struct list_node *node) { return node->next; } + +/* returns number of nodes */ +uint32_t list_count(struct list *list) { + return list->count; +} diff --git a/list.h b/list.h index 777ed78..4607317 100644 --- a/list.h +++ b/list.h @@ -1,11 +1,17 @@ /* - * Copyright (C) 2006-2008 Stig Venaas + * Copyright (C) 2006-2009 Stig Venaas * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. */ +#ifdef SYS_SOLARIS9 +#include +#else +#include +#endif + struct list_node { struct list_node *next; void *data; @@ -13,6 +19,7 @@ struct list_node { struct list { struct list_node *first, *last; + uint32_t count; }; /* allocates and initialises list structure; returns NULL if malloc fails */ @@ -35,3 +42,6 @@ struct list_node *list_first(struct list *list); /* returns the next node after the argument */ struct list_node *list_next(struct list_node *node); + +/* returns number of nodes */ +uint32_t list_count(struct list *list); diff --git a/radsecproxy.c b/radsecproxy.c index 79625ca..5aae539 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -53,7 +53,6 @@ #endif #include #include -#include #include #include #include diff --git a/util.c b/util.c index ed093df..f41bf65 100644 --- a/util.c +++ b/util.c @@ -13,6 +13,9 @@ #include #include #include +#include +#include +#include #include #include "debug.h" #include "util.h" @@ -157,18 +160,56 @@ int bindtoaddr(struct addrinfo *addrinfo, int family, int reuse, int v6only) { return -1; } -int connecttcp(struct addrinfo *addrinfo, struct addrinfo *src) { +int connectnonblocking(int s, const struct sockaddr *addr, socklen_t addrlen, struct timeval *timeout) { + int origflags, error = 0, r = -1; + fd_set writefds; + socklen_t len; + + origflags = fcntl(s, F_GETFL, 0); + fcntl(s, F_SETFL, origflags | O_NONBLOCK); + if (!connect(s, addr, addrlen)) { + r = 0; + goto exit; + } + if (errno != EINPROGRESS) + goto exit; + + FD_ZERO(&writefds); + FD_SET(s, &writefds); + if (select(s + 1, NULL, &writefds, NULL, timeout) < 1) + goto exit; + + len = sizeof(error); + if (!getsockopt(s, SOL_SOCKET, SO_ERROR, (char*)&error, &len) && !error) + r = 0; + + exit: + fcntl(s, F_SETFL, origflags); + return r; +} + +int connecttcp(struct addrinfo *addrinfo, struct addrinfo *src, uint16_t timeout) { int s; struct addrinfo *res; + struct timeval to; s = -1; + if (timeout) { + if (res && res->ai_next && timeout > 5) + timeout = 5; + to.tv_sec = timeout; + to.tv_usec = 0; + } + for (res = addrinfo; res; res = res->ai_next) { s = bindtoaddr(src, res->ai_family, 1, 1); if (s < 0) { debug(DBG_WARN, "connecttoserver: socket failed"); continue; } - if (connect(s, res->ai_addr, res->ai_addrlen) == 0) + if ((timeout + ? connectnonblocking(s, res->ai_addr, res->ai_addrlen, &to) + : connect(s, res->ai_addr, res->ai_addrlen)) == 0) break; debug(DBG_WARN, "connecttoserver: connect failed"); close(s); diff --git a/util.h b/util.h index d87befd..1272b74 100644 --- a/util.h +++ b/util.h @@ -16,4 +16,5 @@ void port_set(struct sockaddr *sa, uint16_t port); void printfchars(char *prefixfmt, char *prefix, char *charfmt, char *chars, int len); int bindtoaddr(struct addrinfo *addrinfo, int family, int reuse, int v6only); -int connecttcp(struct addrinfo *addrinfo, struct addrinfo *src); +int connecttcp(struct addrinfo *addrinfo, struct addrinfo *src, uint16_t timeout); + -- cgit v1.2.3