curl-library
Re: round robin DNS without Ares only takes first IP
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