diff options
author | venaas <venaas> | 2009-02-05 10:09:14 +0000 |
---|---|---|
committer | venaas <venaas@e88ac4ed-0b26-0410-9574-a7f39faa03bf> | 2009-02-05 10:09:14 +0000 |
commit | d7b5499013188ddc78f2b770cce78543b3b7c48c (patch) | |
tree | 1139d0482f53ee32a461cdc9658b88f1b03420f6 | |
parent | 3c0a3e22536d009f3d4cc1faa37007058f51431b (diff) |
timeout for connect
git-svn-id: https://svn.testnett.uninett.no/radsecproxy/trunk@467 e88ac4ed-0b26-0410-9574-a7f39faa03bf
-rw-r--r-- | hostport.c | 2 | ||||
-rw-r--r-- | list.c | 14 | ||||
-rw-r--r-- | list.h | 12 | ||||
-rw-r--r-- | radsecproxy.c | 1 | ||||
-rw-r--r-- | util.c | 45 | ||||
-rw-r--r-- | util.h | 3 |
6 files changed, 68 insertions, 9 deletions
@@ -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; } @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2008 Stig Venaas <venaas@uninett.no> + * Copyright (C) 2006-2009 Stig Venaas <venaas@uninett.no> * * 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; +} @@ -1,11 +1,17 @@ /* - * Copyright (C) 2006-2008 Stig Venaas <venaas@uninett.no> + * Copyright (C) 2006-2009 Stig Venaas <venaas@uninett.no> * * 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 <sys/inttypes.h> +#else +#include <stdint.h> +#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 <sys/time.h> #include <sys/types.h> -#include <sys/select.h> #include <ctype.h> #include <sys/wait.h> #include <arpa/inet.h> @@ -13,6 +13,9 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/select.h> #include <stdarg.h> #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); @@ -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); + |