Buy commercial curl support from WolfSSL. We help you work
out your issues, debug your libcurl applications, use the API, port to new
platforms, add new features and more. With a team lead by the curl founder
himself.
Feature request: provide ability to set a global callback function telling libcurl if IPv6 works on the system
- Contemporary messages sorted: [ by date ] [ by thread ] [ by subject ] [ by author ] [ by messages with attachments ]
From: Dmitry Karpov via curl-library <curl-library_at_lists.haxx.se>
Date: Mon, 19 Sep 2022 23:53:23 +0000
Hi All,
Working with IPv6-enabled dual-stack libcurl, I noticed that for some Linux kernel configurations, it takes ~15-30ms more for dual-stack libcurl to establish IPv4 connections than for IPv4 single-stack libcurl.
After looking into this issue, it turned out that the regression was caused by Curl_ipv6works() function enabled in IPv6-on builds.
This function is called on every multi handle initialization and it uses successful IPv6 socket creation call as an indicator that IPv6 actually works on the system.
And in some cases, it takes ~15-30ms for IPv6 socket creation to fail, thus creating IPv4 connection delay.
I propose to define a global callback which libcurl client application can use to tell libcurl whether IPv6 works on the system or not - thus allowing to eliminate delays caused by failed IPv6 socket creations.
And client app can set this callback in a special flavor of curl_global_init_xxx() function (i.e. curl_global_init_ipv6()) similar to curl_global_init_mem().
So, the prototype may look like:
/*
* callback function for checking if IPv6 is enabled on the system or
* for the application.
*
*/
typedef enum {
CURLIPV6_NO = 0, /* ipv6 is disabled and shouldn't be used. */
CURLIPV6_YES, /* ipv6 is enabled and can be used. */
CURLIPV6_AUTO /* use default libcurl mechanism to detect if IPv6 works */
} CURLipv6;
typedef CURLipv6(*curl_ipv6works_callback)();
/*
* NAME curl_global_init_ipv6()
*
* DESCRIPTION
*
* curl_global_init() or curl_global_init_ipv6() should be invoked exactly once
* for each application that uses libcurl. This function can be used to
* initialize libcurl and set user defined callback checking if IPv6 works
* on the system.
* Users can implement IPv6 checking routines to tell libcurl if it can use
* IPv6 in its transfers.
*/
CURL_EXTERN CURLcode curl_global_init_ipv6(long flags,
curl_ipv6works_callback ipv6_works_cb);
This approach is flexible enough to allow clients to specify special conditions where they know when they do or don't want to use IPv6 with conditions where they want to rely on libcurl default mechanism.
Example:
CURLipv6 check_ipv6() {
if (client_disables_ipv6) // We know that IPv6 doesn't work here.
return CURLipv6::CURLIPV6_NO;
// Use default check when we are not sure if IPv6 works or not.
return CURLipv6::CURLIPV6_AUTO;
}
// Init libcurl with "IPv6 works" callback.
curl_global_init_ipv6(CURL_GLOBAL_ALL, check_ipv6);
I am also attaching a patch file implementing this approach in libcurl.
Thanks,
Dmitry Karpov
Received on 2022-09-20
Date: Mon, 19 Sep 2022 23:53:23 +0000
Hi All,
Working with IPv6-enabled dual-stack libcurl, I noticed that for some Linux kernel configurations, it takes ~15-30ms more for dual-stack libcurl to establish IPv4 connections than for IPv4 single-stack libcurl.
After looking into this issue, it turned out that the regression was caused by Curl_ipv6works() function enabled in IPv6-on builds.
This function is called on every multi handle initialization and it uses successful IPv6 socket creation call as an indicator that IPv6 actually works on the system.
And in some cases, it takes ~15-30ms for IPv6 socket creation to fail, thus creating IPv4 connection delay.
I propose to define a global callback which libcurl client application can use to tell libcurl whether IPv6 works on the system or not - thus allowing to eliminate delays caused by failed IPv6 socket creations.
And client app can set this callback in a special flavor of curl_global_init_xxx() function (i.e. curl_global_init_ipv6()) similar to curl_global_init_mem().
So, the prototype may look like:
/*
* callback function for checking if IPv6 is enabled on the system or
* for the application.
*
*/
typedef enum {
CURLIPV6_NO = 0, /* ipv6 is disabled and shouldn't be used. */
CURLIPV6_YES, /* ipv6 is enabled and can be used. */
CURLIPV6_AUTO /* use default libcurl mechanism to detect if IPv6 works */
} CURLipv6;
typedef CURLipv6(*curl_ipv6works_callback)();
/*
* NAME curl_global_init_ipv6()
*
* DESCRIPTION
*
* curl_global_init() or curl_global_init_ipv6() should be invoked exactly once
* for each application that uses libcurl. This function can be used to
* initialize libcurl and set user defined callback checking if IPv6 works
* on the system.
* Users can implement IPv6 checking routines to tell libcurl if it can use
* IPv6 in its transfers.
*/
CURL_EXTERN CURLcode curl_global_init_ipv6(long flags,
curl_ipv6works_callback ipv6_works_cb);
This approach is flexible enough to allow clients to specify special conditions where they know when they do or don't want to use IPv6 with conditions where they want to rely on libcurl default mechanism.
Example:
CURLipv6 check_ipv6() {
if (client_disables_ipv6) // We know that IPv6 doesn't work here.
return CURLipv6::CURLIPV6_NO;
// Use default check when we are not sure if IPv6 works or not.
return CURLipv6::CURLIPV6_AUTO;
}
// Init libcurl with "IPv6 works" callback.
curl_global_init_ipv6(CURL_GLOBAL_ALL, check_ipv6);
I am also attaching a patch file implementing this approach in libcurl.
Thanks,
Dmitry Karpov
-- Unsubscribe: https://lists.haxx.se/listinfo/curl-library Etiquette: https://curl.se/mail/etiquette.html
- application/octet-stream attachment: curl_global_init_ipv6-global-function.patch