version: make curl_version* thread-safe without using global context
Closes #5010
This commit is contained in:
parent
310dc709ff
commit
e364546fb3
@ -83,8 +83,6 @@
|
|||||||
#include "curl_memory.h"
|
#include "curl_memory.h"
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
|
|
||||||
void Curl_version_init(void);
|
|
||||||
|
|
||||||
/* true globals -- for curl_global_init() and curl_global_cleanup() */
|
/* true globals -- for curl_global_init() and curl_global_cleanup() */
|
||||||
static unsigned int initialized;
|
static unsigned int initialized;
|
||||||
static long init_flags;
|
static long init_flags;
|
||||||
@ -201,8 +199,6 @@ static CURLcode global_init(long flags, bool memoryfuncs)
|
|||||||
|
|
||||||
init_flags = flags;
|
init_flags = flags;
|
||||||
|
|
||||||
Curl_version_init();
|
|
||||||
|
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
|||||||
@ -333,7 +333,7 @@ static const struct Curl_handler Curl_handler_http2_ssl = {
|
|||||||
int Curl_http2_ver(char *p, size_t len)
|
int Curl_http2_ver(char *p, size_t len)
|
||||||
{
|
{
|
||||||
nghttp2_info *h2 = nghttp2_version(0);
|
nghttp2_info *h2 = nghttp2_version(0);
|
||||||
return msnprintf(p, len, " nghttp2/%s", h2->version_str);
|
return msnprintf(p, len, "nghttp2/%s", h2->version_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
194
lib/version.c
194
lib/version.c
@ -66,16 +66,6 @@
|
|||||||
#include <brotli/decode.h>
|
#include <brotli/decode.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Curl_version_init(void);
|
|
||||||
|
|
||||||
/* For thread safety purposes this function is called by global_init so that
|
|
||||||
the static data in both version functions is initialized. */
|
|
||||||
void Curl_version_init(void)
|
|
||||||
{
|
|
||||||
curl_version();
|
|
||||||
curl_version_info(CURLVERSION_NOW);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_BROTLI
|
#ifdef HAVE_BROTLI
|
||||||
static size_t brotli_version(char *buf, size_t bufsz)
|
static size_t brotli_version(char *buf, size_t bufsz)
|
||||||
{
|
{
|
||||||
@ -88,95 +78,108 @@ static size_t brotli_version(char *buf, size_t bufsz)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* curl_version() returns a pointer to a static buffer.
|
||||||
|
*
|
||||||
|
* It is implemented to work multi-threaded by making sure repeated invokes
|
||||||
|
* generate the exact same string and never write any temporary data like
|
||||||
|
* zeros in the data.
|
||||||
|
*/
|
||||||
char *curl_version(void)
|
char *curl_version(void)
|
||||||
{
|
{
|
||||||
static bool initialized;
|
static char out[250];
|
||||||
static char version[250];
|
char *outp;
|
||||||
char *ptr = version;
|
size_t outlen;
|
||||||
size_t len;
|
const char *src[14];
|
||||||
size_t left = sizeof(version);
|
#ifdef USE_SSL
|
||||||
|
char ssl_version[40];
|
||||||
if(initialized)
|
#endif
|
||||||
return version;
|
|
||||||
|
|
||||||
strcpy(ptr, LIBCURL_NAME "/" LIBCURL_VERSION);
|
|
||||||
len = strlen(ptr);
|
|
||||||
left -= len;
|
|
||||||
ptr += len;
|
|
||||||
|
|
||||||
len = Curl_ssl_version(ptr + 1, left - 1);
|
|
||||||
|
|
||||||
if(len > 0) {
|
|
||||||
*ptr = ' ';
|
|
||||||
left -= ++len;
|
|
||||||
ptr += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_LIBZ
|
#ifdef HAVE_LIBZ
|
||||||
len = msnprintf(ptr, left, " zlib/%s", zlibVersion());
|
char z_version[40];
|
||||||
left -= len;
|
|
||||||
ptr += len;
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_BROTLI
|
#ifdef HAVE_BROTLI
|
||||||
len = msnprintf(ptr, left, "%s", " brotli/");
|
char br_version[40] = "brotli/";
|
||||||
left -= len;
|
|
||||||
ptr += len;
|
|
||||||
len = brotli_version(ptr, left);
|
|
||||||
left -= len;
|
|
||||||
ptr += len;
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_ARES
|
#ifdef USE_ARES
|
||||||
/* this function is only present in c-ares, not in the original ares */
|
char cares_version[40];
|
||||||
len = msnprintf(ptr, left, " c-ares/%s", ares_version(NULL));
|
#endif
|
||||||
left -= len;
|
#if defined(USE_LIBIDN2) || defined(USE_WIN32_IDN)
|
||||||
ptr += len;
|
char idn_version[40];
|
||||||
|
#endif
|
||||||
|
#ifdef USE_LIBPSL
|
||||||
|
char psl_version[40];
|
||||||
|
#endif
|
||||||
|
#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS)
|
||||||
|
char iconv_version[40]="iconv";
|
||||||
|
#endif
|
||||||
|
#ifdef USE_SSH
|
||||||
|
char ssh_version[40];
|
||||||
|
#endif
|
||||||
|
#ifdef USE_NGHTTP2
|
||||||
|
char h2_version[40];
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_QUIC
|
||||||
|
char h3_version[40];
|
||||||
|
#endif
|
||||||
|
#ifdef USE_LIBRTMP
|
||||||
|
char rtmp_version[40];
|
||||||
|
#endif
|
||||||
|
int i = 0;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
src[i++] = LIBCURL_NAME "/" LIBCURL_VERSION;
|
||||||
|
#ifdef USE_SSL
|
||||||
|
Curl_ssl_version(ssl_version, sizeof(ssl_version));
|
||||||
|
src[i++] = ssl_version;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_LIBZ
|
||||||
|
msnprintf(z_version, sizeof(z_version), "zlib/%s", zlibVersion());
|
||||||
|
src[i++] = z_version;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_BROTLI
|
||||||
|
brotli_version(&br_version[7], sizeof(br_version) - 7);
|
||||||
|
src[i++] = br_version;
|
||||||
|
#endif
|
||||||
|
#ifdef USE_ARES
|
||||||
|
msnprintf(cares_version, sizeof(cares_version),
|
||||||
|
"c-ares/%s", ares_version(NULL));
|
||||||
|
src[i++] = cares_version;
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_LIBIDN2
|
#ifdef USE_LIBIDN2
|
||||||
if(idn2_check_version(IDN2_VERSION)) {
|
if(idn2_check_version(IDN2_VERSION)) {
|
||||||
len = msnprintf(ptr, left, " libidn2/%s", idn2_check_version(NULL));
|
msnprintf(idn_version, sizeof(idn_version),
|
||||||
left -= len;
|
"libidn2/%s", idn2_check_version(NULL));
|
||||||
ptr += len;
|
src[i++] = idn_version;
|
||||||
}
|
}
|
||||||
|
#elif defined(USE_WIN32_IDN)
|
||||||
|
msnprintf(idn_version, sizeof(idn_version), "WinIDN");
|
||||||
|
src[i++] = idn_version;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_LIBPSL
|
#ifdef USE_LIBPSL
|
||||||
len = msnprintf(ptr, left, " libpsl/%s", psl_get_version());
|
msnprintf(psl_version, sizeof(psl_version), "libpsl/%s", psl_get_version());
|
||||||
left -= len;
|
src[i++] = psl_version;
|
||||||
ptr += len;
|
|
||||||
#endif
|
|
||||||
#ifdef USE_WIN32_IDN
|
|
||||||
len = msnprintf(ptr, left, " WinIDN");
|
|
||||||
left -= len;
|
|
||||||
ptr += len;
|
|
||||||
#endif
|
#endif
|
||||||
#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS)
|
#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS)
|
||||||
#ifdef _LIBICONV_VERSION
|
#ifdef _LIBICONV_VERSION
|
||||||
len = msnprintf(ptr, left, " iconv/%d.%d",
|
msnprintf(iconv_version, sizeof(iconv_version), "iconv/%d.%d",
|
||||||
_LIBICONV_VERSION >> 8, _LIBICONV_VERSION & 255);
|
_LIBICONV_VERSION >> 8, _LIBICONV_VERSION & 255);
|
||||||
#else
|
#else
|
||||||
/* version unknown */
|
/* version unknown, let the default stand */
|
||||||
len = msnprintf(ptr, left, " iconv");
|
|
||||||
#endif /* _LIBICONV_VERSION */
|
#endif /* _LIBICONV_VERSION */
|
||||||
left -= len;
|
src[i++] = iconv_version;
|
||||||
ptr += len;
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_SSH
|
#ifdef USE_SSH
|
||||||
if(left) {
|
Curl_ssh_version(ssh_version, sizeof(ssh_version));
|
||||||
*ptr++=' ';
|
src[i++] = ssh_version;
|
||||||
left--;
|
|
||||||
}
|
|
||||||
len = Curl_ssh_version(ptr, left);
|
|
||||||
left -= len;
|
|
||||||
ptr += len;
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_NGHTTP2
|
#ifdef USE_NGHTTP2
|
||||||
len = Curl_http2_ver(ptr, left);
|
Curl_http2_ver(h2_version, sizeof(h2_version));
|
||||||
left -= len;
|
src[i++] = h2_version;
|
||||||
ptr += len;
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_QUIC
|
#ifdef ENABLE_QUIC
|
||||||
len = Curl_quic_ver(ptr, left);
|
Curl_quic_ver(h3_version, sizeof(h3_version));
|
||||||
left -= len;
|
src[i++] = h3_version;
|
||||||
ptr += len;
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_LIBRTMP
|
#ifdef USE_LIBRTMP
|
||||||
{
|
{
|
||||||
@ -188,27 +191,32 @@ char *curl_version(void)
|
|||||||
else
|
else
|
||||||
suff[0] = '\0';
|
suff[0] = '\0';
|
||||||
|
|
||||||
msnprintf(ptr, left, " librtmp/%d.%d%s",
|
msnprintf(rtmp_version, sizeof(rtmp_version), "librtmp/%d.%d%s",
|
||||||
RTMP_LIB_VERSION >> 16, (RTMP_LIB_VERSION >> 8) & 0xff,
|
RTMP_LIB_VERSION >> 16, (RTMP_LIB_VERSION >> 8) & 0xff,
|
||||||
suff);
|
suff);
|
||||||
/*
|
src[i++] = rtmp_version;
|
||||||
If another lib version is added below this one, this code would
|
|
||||||
also have to do:
|
|
||||||
|
|
||||||
len = what msnprintf() returned
|
|
||||||
|
|
||||||
left -= len;
|
|
||||||
ptr += len;
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Silent scan-build even if librtmp is not enabled. */
|
outp = &out[0];
|
||||||
(void) left;
|
outlen = sizeof(out);
|
||||||
(void) ptr;
|
for(j = 0; j < i; j++) {
|
||||||
|
size_t n = strlen(src[j]);
|
||||||
|
/* we need room for a space, the string and the final zero */
|
||||||
|
if(outlen <= (n + 2))
|
||||||
|
break;
|
||||||
|
if(j) {
|
||||||
|
/* prepend a space if not the first */
|
||||||
|
*outp++ = ' ';
|
||||||
|
outlen--;
|
||||||
|
}
|
||||||
|
memcpy(outp, src[j], n);
|
||||||
|
outp += n;
|
||||||
|
outlen -= n;
|
||||||
|
}
|
||||||
|
*outp = 0;
|
||||||
|
|
||||||
initialized = true;
|
return out;
|
||||||
return version;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* data for curl_version_info
|
/* data for curl_version_info
|
||||||
@ -391,7 +399,6 @@ static curl_version_info_data version_info = {
|
|||||||
|
|
||||||
curl_version_info_data *curl_version_info(CURLversion stamp)
|
curl_version_info_data *curl_version_info(CURLversion stamp)
|
||||||
{
|
{
|
||||||
static bool initialized;
|
|
||||||
#if defined(USE_SSH)
|
#if defined(USE_SSH)
|
||||||
static char ssh_buffer[80];
|
static char ssh_buffer[80];
|
||||||
#endif
|
#endif
|
||||||
@ -406,9 +413,6 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
|
|||||||
static char brotli_buffer[80];
|
static char brotli_buffer[80];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(initialized)
|
|
||||||
return &version_info;
|
|
||||||
|
|
||||||
#ifdef USE_SSL
|
#ifdef USE_SSL
|
||||||
Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer));
|
Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer));
|
||||||
version_info.ssl_version = ssl_buffer;
|
version_info.ssl_version = ssl_buffer;
|
||||||
@ -476,7 +480,5 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
(void)stamp; /* avoid compiler warnings, we don't use this */
|
(void)stamp; /* avoid compiler warnings, we don't use this */
|
||||||
|
|
||||||
initialized = true;
|
|
||||||
return &version_info;
|
return &version_info;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -641,7 +641,7 @@ int Curl_quic_ver(char *p, size_t len)
|
|||||||
{
|
{
|
||||||
ngtcp2_info *ng2 = ngtcp2_version(0);
|
ngtcp2_info *ng2 = ngtcp2_version(0);
|
||||||
nghttp3_info *ht3 = nghttp3_version(0);
|
nghttp3_info *ht3 = nghttp3_version(0);
|
||||||
return msnprintf(p, len, " ngtcp2/%s nghttp3/%s",
|
return msnprintf(p, len, "ngtcp2/%s nghttp3/%s",
|
||||||
ng2->version_str, ht3->version_str);
|
ng2->version_str, ht3->version_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -532,7 +532,7 @@ static ssize_t h3_stream_send(struct connectdata *conn,
|
|||||||
*/
|
*/
|
||||||
int Curl_quic_ver(char *p, size_t len)
|
int Curl_quic_ver(char *p, size_t len)
|
||||||
{
|
{
|
||||||
return msnprintf(p, len, " quiche/%s", quiche_version());
|
return msnprintf(p, len, "quiche/%s", quiche_version());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Index where :authority header field will appear in request header
|
/* Index where :authority header field will appear in request header
|
||||||
|
|||||||
@ -262,7 +262,6 @@ bool Curl_ssl_false_start(void);
|
|||||||
#define Curl_ssl_send(a,b,c,d,e) -1
|
#define Curl_ssl_send(a,b,c,d,e) -1
|
||||||
#define Curl_ssl_recv(a,b,c,d,e) -1
|
#define Curl_ssl_recv(a,b,c,d,e) -1
|
||||||
#define Curl_ssl_initsessions(x,y) CURLE_OK
|
#define Curl_ssl_initsessions(x,y) CURLE_OK
|
||||||
#define Curl_ssl_version(x,y) 0
|
|
||||||
#define Curl_ssl_data_pending(x,y) 0
|
#define Curl_ssl_data_pending(x,y) 0
|
||||||
#define Curl_ssl_check_cxn(x) 0
|
#define Curl_ssl_check_cxn(x) 0
|
||||||
#define Curl_ssl_free_certinfo(x) Curl_nop_stmt
|
#define Curl_ssl_free_certinfo(x) Curl_nop_stmt
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user