In message <[email protected]>, David Conrad
 writes:
> On Jun 24, 2010, at 4:48 PM, Mark Andrews wrote:
> > The third choice is to do a non-blocking connect to IPv6 then if that =
> does
> > not succeed in 1 or 2 seconds (most successful connects are within =
> this
> > peroid but connect failures are considerably longer) initiate a non =
> blocking
> > IPv4 connection and keep whichever completes first and abort the =
> other.
> 
> That sounds like a variation of the v6-then-v4 serial case, just =
> slightly accelerated.  But maybe I'm missing something...

This starts out as serial but finishes as parallel.  You don't
hammer the server initially but you don't wait a long time either
if one of the addresses is unreachable.  You can adjust the rate
at which you try new addresses.

Mark


        fdset set1, set2;
        struct timeval timeout = { 1, 0 };      /* 1 second */
        int fd = -1, min = -1, max = -1;
        int active = 0;
        struct addrinfo *res0 = NULL, res0;

        getaddrinfo(...., &res0):
        res = res0;
        while (res != NULL || active > 0) {
                int r;
                if (res != NULL) {
                        int tmpfd = socket();
                        makenonblocking(tmpfd);
                        connect(tmpfd);
                        if (tmpfd < min || min == -1)
                                min = tmpfd;
                        if (tmpfd > max || max == -1)
                                max = tmpfd;
                        FD_SET(tmpfd, set1);
                        res = res->ai_next
                        active++;
                }
                set2 = set1;

                r = select(NULL, &set2, NULL, (res == NULL) ? NULL : &timeout);
                if (r == 0) {
                        /* adjust the next timeout here if you want */
                        continue;
                }
                if (r > 0) {
                        int i;
                        for (i = min; i <= max; i++) {
                                if (FD_ISSET(i, set2)) {
                                        if (success) {
                                                fd = i;
                                                close other fds;
                                                goto done;
                                        }
                                        /* Connect failed. */
                                        close(i);
                                        FD_CLR(i, &set1);
                                        active--;
                                }
                        }
                        continue;
                }       
                /* handle errors */
        }
 done:
        freeaddrinfo(res0);
        return fd;

> Regards,
> -drc
-- 
Mark Andrews, ISC
1 Seymour St., Dundas Valley, NSW 2117, Australia
PHONE: +61 2 9871 4742                 INTERNET: [email protected]
_______________________________________________
Ietf mailing list
[email protected]
https://www.ietf.org/mailman/listinfo/ietf

Reply via email to