cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: round robin DNS without Ares only takes first IP

From: A Nonymous <anon_at_ymous.none>
Date: Thu, 28 Apr 2005 15:49:43 +0200

Daniel Stenberg wrote:

> Right. I'm OK with doing like this.
>
> But is there really a point to add an option for this? Will there ever
> be applications that will want to force the same order as long as the
> address is fetched from the DNS cache? I can't see how it ever can be
> reasonable.

That's true.

> Also, your fix only changes how this is done from the easy interface,
> we need a little patch for the multi interface approach as well
> (especially since the "easy" internal approach is subject for going
> trashcan in a not so distant future). The multi interface uses the
> connect.c:trynextip() function to advanced to the next IP.

I am uncertain, if trynextip() is called several times for a single HTTP
or FTP connection. If not then the following might be OK.
There is a tiny overhead in case of retries by seeking the chain for
every retry, but this way the code is easier to understand than my last
patch.

@@ -452,22 +452,51 @@
   return CURLE_OK;
 }

+/*
+ * return element getindex in Curl_addrinfo chain
+ * this function should be moved to file hostip.c
+ */
+Curl_addrinfo*
+Curl_addr_chain_index(Curl_addrinfo* head,
+ int getindex)
+{
+ int index;
+ Curl_addrinfo* result;
+ Curl_addrinfo* curr_addr;
+
+ result = NULL;
+ for (curr_addr = head, index = 0;
+ curr_addr != NULL; curr_addr = curr_addr->ai_next, index++) {
+
+ if (index == getindex) {
+ result = curr_addr;
+ break;
+ }
+ }
+ return result;
+}
+
 /* Used within the multi interface. Try next IP address, return TRUE if no
    more address exists */
 static bool trynextip(struct connectdata *conn,
                       int sockindex,
                       bool *connected)
 {
+ int num_addr;
+ int retryIndex;
+ int aliasfirst;
   curl_socket_t sockfd;
   Curl_addrinfo *ai;

   if(sockindex != FIRSTSOCKET)
     return TRUE; /* no next */

- /* try the next address */
- ai = conn->ip_addr->ai_next;
+ num_addr = Curl_num_addresses(conn->ip_addr->ai_next);
+ aliasfirst = rand() % num_addr;
+ for (retryindex = 0; retryindex < num_addr; retryindex++) {

- while (ai) {
+ ai = Curl_addr_chain_index(
+ conn->ip_addr->ai_next, ((retryindex + aliasfirst) % num_addr));
     sockfd = singleipconnect(conn, ai, 0L, connected);
     if(sockfd != CURL_SOCKET_BAD) {
       /* store the new socket descriptor */
@@ -477,7 +506,6 @@
       Curl_store_ip_addr(conn);
       return FALSE;
     }
- ai = ai->ai_next;
   }
   return TRUE;
 }
@@ -721,9 +749,9 @@
 {
   struct SessionHandle *data = conn->data;
   curl_socket_t sockfd = CURL_SOCKET_BAD;
- int aliasindex;
+ int aliasfirst;
+ int retryindex;
   int num_addr;
- Curl_addrinfo *ai;
   Curl_addrinfo *curr_addr;

   struct timeval after;
@@ -773,8 +801,6 @@
   num_addr = Curl_num_addresses(remotehost->addr);
   timeout_per_addr = timeout_ms / num_addr;

- ai = remotehost->addr;
-
   /* Below is the loop that attempts to connect to all IP-addresses we
    * know for the given host. One by one until one IP succeeds.
    */
@@ -786,8 +812,13 @@
   /*
    * Connecting with a Curl_addrinfo chain
    */
- for (curr_addr = ai, aliasindex=0; curr_addr;
- curr_addr = curr_addr->ai_next, aliasindex++) {
+ aliasfirst = rand() % num_addr;
+ for (retryindex = 0; retryindex < num_addr; retryindex++) {
+
+ curr_addr = Curl_addr_chain_index(
+ remotehost->addr, ((retryindex + aliasfirst) % num_addr));
+ if (curr_addr == NULL)
+ break;

     /* start connecting to the IP curr_addr points to */
     sockfd = singleipconnect(conn, curr_addr, timeout_per_addr, connected);
Received on 2005-04-28