Published in <sxs8zcsfemf.fsf@florida.arsdigita.de>.
+2001-11-27 Hrvoje Niksic <hniksic@arsdigita.com>
+
+ * connect.c (connect_to_many): Use address_list_set_faulty to
+ prevent the faulty address from being reused.
+
+ * host.c (address_list_set_faulty): New function.
+ (address_list_get_bounds): New function, instead of
+ address_list_count.
+
2001-11-27 Hrvoje Niksic <hniksic@arsdigita.com>
* url.c (convert_links): Don't translate %d-%d.
int
connect_to_many (struct address_list *al, unsigned short port, int silent)
{
- int i;
+ int i, start, end;
- for (i = 0; i < address_list_count (al); i++)
+ address_list_get_bounds (al, &start, &end);
+ for (i = start; i < end; i++)
{
unsigned char addr[4];
int sock;
sock = connect_to_one (addr, port, silent);
if (sock >= 0)
+ /* Success. */
return sock;
- /* Perhaps we should have a way of removing the failing entry
- from the address list? */
+ address_list_set_faulty (al, i);
/* The attempt to connect has failed. Continue with the loop
and try next address. */
int count; /* number of adrresses */
unsigned char *buffer; /* buffer which holds all of them. */
+ int faulty; /* number of addresses known not to
+ work. */
int refcount; /* so we know whether to free it or
not. */
};
#define ADDR_LOCATION(al, index) ((al)->buffer + index * IP4_ADDRESS_LENGTH)
-/* Return the number of addresses in the list. */
+/* Get the bounds of the address list. */
-int
-address_list_count (struct address_list *al)
+void
+address_list_get_bounds (struct address_list *al, int *start, int *end)
{
- return al->count;
+ *start = al->faulty;
+ *end = al->count;
}
/* Copy address number INDEX to IP_STORE. */
address_list_copy_one (struct address_list *al, int index,
unsigned char *ip_store)
{
+ assert (index >= al->faulty && index < al->count);
memcpy (ip_store, ADDR_LOCATION (al, index), IP4_ADDRESS_LENGTH);
}
al1->count * IP4_ADDRESS_LENGTH);
}
+/* Mark the INDEXth element of AL as faulty, so that the next time
+ this address list is used, the faulty element will be skipped. */
+
+void
+address_list_set_faulty (struct address_list *al, int index)
+{
+ ++al->faulty;
+ if (al->faulty >= al->count)
+ /* All addresses have been proven faulty. Since there's not much
+ sense in returning the user an empty address list the next
+ time, we'll rather make them all clean, so that they can be
+ retried anew. */
+ al->faulty = 0;
+}
+
/* Create an address_list out of a NULL-terminated list of addresses,
as returned by gethostbyname. */
struct address_list *lookup_host PARAMS ((const char *, int));
char *herrmsg PARAMS ((int));
-int address_list_count PARAMS ((struct address_list *));
+void address_list_get_bounds PARAMS ((struct address_list *, int *, int *));
void address_list_copy_one PARAMS ((struct address_list *, int,
unsigned char *));
-void address_list_release PARAMS ((struct address_list *));
int address_list_match_all PARAMS ((struct address_list *,
struct address_list *));
+void address_list_set_faulty PARAMS ((struct address_list *, int));
+void address_list_release PARAMS ((struct address_list *));
/* This was originally going to be a macro, but then every caller
would have to #include the netinet stuff. */