diff --git a/0004-ProvieClearDnsCacheAPI.patch b/0004-ProvieClearDnsCacheAPI.patch new file mode 100644 index 0000000000000000000000000000000000000000..8e54205bb1658ff68370adc63abd2f59c10affd5 --- /dev/null +++ b/0004-ProvieClearDnsCacheAPI.patch @@ -0,0 +1,55 @@ +diff --git a/curl.map b/curl.map +index d20bfbbfc..31260c893 100644 +--- a/curl.map ++++ b/curl.map +@@ -11,6 +11,7 @@ + curl_multi_poll; + curl_multi_wakeup; + curl_multi_perform; ++ curl_multi_clear_dns_cache; + curl_multi_cleanup; + curl_multi_info_read; + curl_multi_strerror; +diff --git a/curl_without_http3.map b/curl_without_http3.map +index a10fb64f8..e7dc327dc 100644 +--- a/curl_without_http3.map ++++ b/curl_without_http3.map +@@ -11,6 +11,7 @@ global: + curl_multi_poll; + curl_multi_wakeup; + curl_multi_perform; ++ curl_multi_clear_dns_cache; + curl_multi_cleanup; + curl_multi_info_read; + curl_multi_strerror; +diff --git a/include/curl/multi.h b/include/curl/multi.h +index df5d8c549..73b6c7c27 100644 +--- a/include/curl/multi.h ++++ b/include/curl/multi.h +@@ -221,6 +221,8 @@ CURL_EXTERN CURLMcode curl_multi_wakeup(CURLM *multi_handle); + CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle, + int *running_handles); + ++CURL_EXTERN void curl_multi_clear_dns_cache(CURLM *multi_handle); ++ + /* + * Name: curl_multi_cleanup() + * +diff --git a/lib/multi.c b/lib/multi.c +index 642882768..ae3e72d66 100644 +--- a/lib/multi.c ++++ b/lib/multi.c +@@ -2798,6 +2798,13 @@ static void unlink_all_msgsent_handles(struct Curl_multi *multi) + } + } + ++void curl_multi_clear_dns_cache(CURLM *multi) ++{ ++ if (GOOD_MULTI_HANDLE(multi)) { ++ Curl_hash_destroy(&multi->hostcache); ++ } ++} ++ + CURLMcode curl_multi_cleanup(struct Curl_multi *multi) + { + struct Curl_easy *data; diff --git a/include/curl/curl.h b/include/curl/curl.h index 51c654e32f83b54cc21a65cfc7f5cd75534e7577..c6eb0f5dcfd15c9d0355b32706367e9ae29a1308 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -414,6 +414,7 @@ typedef enum { typedef int (*curl_sockopt_callback)(void *clientp, curl_socket_t curlfd, curlsocktype purpose); +typedef bool (*curl_connreuse_callback)(void *userdata, curl_socket_t curlfd); struct curl_sockaddr { int family; @@ -475,6 +476,7 @@ typedef enum { CURLINFO_DATA_OUT, /* 4 */ CURLINFO_SSL_DATA_IN, /* 5 */ CURLINFO_SSL_DATA_OUT, /* 6 */ + CURLINFO_STATE, /* 7 */ CURLINFO_END } curl_infotype; @@ -2215,6 +2217,14 @@ typedef enum { /* set ECH configuration */ CURLOPT(CURLOPT_ECH, CURLOPTTYPE_STRINGPOINT, 325), + CURLOPT(CURLOPT_OHOS_SOCKET_BIND_NET_ID, CURLOPTTYPE_LONG, 1000), + + /* Callback function for deciding url connection reuse */ + CURLOPT(CURLOPT_CONNREUSEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 1001), + + /* Data passed to the CURLOPT_CONNREUSEFUNCTION callback */ + CURLOPT(CURLOPT_CONNREUSEDATA, CURLOPTTYPE_CBPOINT, 1002), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c index 8fed61760b128bc9918ca98a49f46dc52b4c3c06..be67ab447dfcc9de9a88679bbc578355d2b000d2 100644 --- a/lib/asyn-ares.c +++ b/lib/asyn-ares.c @@ -164,6 +164,28 @@ static void sock_state_cb(void *data, ares_socket_t socket_fd, } } +#ifdef OHOS_BIND_NET_BY_FWMARK +int32_t BindSocket(int32_t fd, uint32_t netId); +static int bindohosnetid(ares_socket_t socket_fd, int type, void *data) +{ + struct Curl_easy *easy = (struct Curl_easy *)data; + if (!easy || socket_fd <= 0) { + return -1; + } + unsigned int netid = easy->set.socket_bind_netid; + if (netid > 0) { + int ret = BindSocket(socket_fd, netid); + if (ret == 0) { + return 0; + } else { + // try bind but failed + return -1; + } + } + return 0; +} +#endif + /* * Curl_resolver_init() * @@ -201,6 +223,11 @@ CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver) else return CURLE_FAILED_INIT; } +#ifdef OHOS_BIND_NET_BY_FWMARK + if (easy->set.sock_bind_netid > 0) { + ares_set_socket_configure_callback(resolver, bindohosnetid, easy); + } +#endif return CURLE_OK; /* make sure that all other returns from this function should destroy the ares channel before returning error! */ diff --git a/lib/cf-socket.c b/lib/cf-socket.c index 1340d09515da9ec43660e83feabd4dd0a77e1c0f..9e66c7852e23c7f24fe91309d6d252ad09f5e20b 100644 --- a/lib/cf-socket.c +++ b/lib/cf-socket.c @@ -398,6 +398,25 @@ void Curl_sndbufset(curl_socket_t sockfd) #endif #ifndef CURL_DISABLE_BINDLOCAL +#ifdef OHOS_BIND_NET_BY_FWMARK +int32_t BindSocket(int32_t fd, uint32_t netId); +static CURLcode bindohosnetid(struct Curl_easy *data, struct connectdata *conn, curl_socket_t sockfd) +{ + unsigned int netid = data->set.socket_bind_netid; + if (netid > 0) { + int ret = BindSocket(socket_fd, netid); + if (ret == 0) { + conn->socket_bind_netid = netid; + return CURLE_OK; + } else { + // try bind but failed + return CURLE_INTERFACE_FAILED; + } + } + return CURLE_OK; +} +#endif + static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn, curl_socket_t sockfd, int af, unsigned int scope) { @@ -426,10 +445,16 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn, /************************************************************* * Select device to bind socket to *************************************************************/ +#ifdef OHOS_BIND_NET_BY_FWMARK + if (!dev && !port) { + /*no local kind of binding was requested */ + return data->set.socket_bind_netid > 0 ? bindohosnetid(data, conn, sockfd): CURLE_OK; + } +#else if(!dev && !port) /* no local kind of binding was requested */ return CURLE_OK; - +#endif memset(&sa, 0, sizeof(struct Curl_sockaddr_storage)); if(dev && (strlen(dev)<255) ) { diff --git a/lib/easyoptions.c b/lib/easyoptions.c index c79d136707e4d41c23f0b90a094bdba450bdcef8..7ab966785e01b5fdea952f1821a8c3d92480da1c 100644 --- a/lib/easyoptions.c +++ b/lib/easyoptions.c @@ -366,6 +366,11 @@ struct curl_easyoption Curl_easyopts[] = { {"XFERINFODATA", CURLOPT_XFERINFODATA, CURLOT_CBPTR, 0}, {"XFERINFOFUNCTION", CURLOPT_XFERINFOFUNCTION, CURLOT_FUNCTION, 0}, {"XOAUTH2_BEARER", CURLOPT_XOAUTH2_BEARER, CURLOT_STRING, 0}, +#ifdef OHOS_BIND_NET_BY_FWMARK + {"OHOS_SOCKET_BIND_NET_ID", CURLOPT_OHOS_SOCKET_BIND_NET_ID, CURLOPT_LONG, 0}, +#endif + {"CONNREUSEFUNCTION", CURLOPT_CONNREUSEFUNCTION, CURLOT_FUNCTION, 0}, + {"CONNREUSEDATA", CURLOPT_CONNREUSEDATA, CURLOT_CBPTR, 0}, {NULL, CURLOPT_LASTENTRY, CURLOT_LONG, 0} /* end of table */ }; diff --git a/lib/multi.c b/lib/multi.c index d780be2bdfa10840bada95d397aaf99237fe0109..0ac57a9e08c155e53c8dffc8e0c9c869eb19a005 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -86,8 +86,6 @@ ((x) && (x)->magic == CURL_MULTI_HANDLE) #endif -static void move_pending_to_connect(struct Curl_multi *multi, - struct Curl_easy *data); static CURLMcode singlesocket(struct Curl_multi *multi, struct Curl_easy *data); static CURLMcode add_next_timeout(struct curltime now, @@ -98,11 +96,9 @@ static CURLMcode multi_timeout(struct Curl_multi *multi, static void process_pending_handles(struct Curl_multi *multi); static void multi_xfer_bufs_free(struct Curl_multi *multi); -#ifdef DEBUGBUILD static const char * const multi_statename[]={ "INIT", "PENDING", - "SETUP", "CONNECT", "RESOLVING", "CONNECTING", @@ -119,7 +115,6 @@ static const char * const multi_statename[]={ "COMPLETED", "MSGSENT", }; -#endif /* function pointer called once when switching TO a state */ typedef void (*init_multistate_func)(struct Curl_easy *data); @@ -152,7 +147,6 @@ static void mstate(struct Curl_easy *data, CURLMstate state static const init_multistate_func finit[MSTATE_LAST] = { NULL, /* INIT */ NULL, /* PENDING */ - NULL, /* SETUP */ Curl_init_CONNECT, /* CONNECT */ NULL, /* RESOLVING */ NULL, /* CONNECTING */ @@ -189,6 +183,17 @@ static void mstate(struct Curl_easy *data, CURLMstate state (void *)data, lineno); } #endif + char address[32]; + snprintf(address, sizeof(address), "%p", data); + char buff[64]; + const int reserve_digits = 4; + snprintf(buff, + sizeof(buff), + "STATE: %s => %s handle %s", + multi_statename[oldstate], + multi_statename[data->mstate], + address + strlen(address) - reserve_digits); + Curl_debug(data, CURLINFO_STATE, buff, strlen(buff)); if(state == MSTATE_COMPLETED) { /* changing to COMPLETED means there's one less easy handle 'alive' */ @@ -1116,7 +1121,6 @@ static void multi_getsock(struct Curl_easy *data, switch(data->mstate) { case MSTATE_INIT: case MSTATE_PENDING: - case MSTATE_SETUP: case MSTATE_CONNECT: /* nothing to poll for yet */ break; @@ -1961,41 +1965,30 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, switch(data->mstate) { case MSTATE_INIT: - /* Transitional state. init this transfer. A handle never comes - back to this state. */ + /* init this transfer. */ result = Curl_pretransfer(data); - if(result) - break; - - /* after init, go SETUP */ - multistate(data, MSTATE_SETUP); - (void)Curl_pgrsTime(data, TIMER_STARTOP); - FALLTHROUGH(); + if(!result) { + /* after init, go CONNECT */ + multistate(data, MSTATE_CONNECT); + *nowp = Curl_pgrsTime(data, TIMER_STARTOP); + rc = CURLM_CALL_MULTI_PERFORM; + } + break; - case MSTATE_SETUP: - /* Transitional state. Setup things for a new transfer. The handle - can come back to this state on a redirect. */ + case MSTATE_CONNECT: + /* Connect. We want to get a connection identifier filled in. */ + /* init this transfer. */ *nowp = Curl_pgrsTime(data, TIMER_STARTSINGLE); if(data->set.timeout) Curl_expire(data, data->set.timeout, EXPIRE_TIMEOUT); + if(data->set.connecttimeout) - /* Since a connection might go to pending and back to CONNECT several - times before it actually takes off, we need to set the timeout once - in SETUP before we enter CONNECT the first time. */ Curl_expire(data, data->set.connecttimeout, EXPIRE_CONNECTTIMEOUT); - - multistate(data, MSTATE_CONNECT); - FALLTHROUGH(); - - case MSTATE_CONNECT: - /* Connect. We want to get a connection identifier filled in. This state - can be entered from SETUP and from PENDING. */ result = Curl_connect(data, &async, &connected); if(CURLE_NO_CONNECTION_AVAILABLE == result) { /* There was no connection available. We will go to the pending state and wait for an available connection. */ multistate(data, MSTATE_PENDING); - /* add this handle to the list of connect-pending handles */ Curl_llist_append(&multi->pending, data, &data->connect_queue); /* unlink from the main list */ @@ -2003,9 +1996,11 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, result = CURLE_OK; break; } - else + else if(data->state.previouslypending) { + /* this transfer comes from the pending queue so try move another */ + infof(data, "Transfer was pending, now try another"); process_pending_handles(data->multi); - + } if(!result) { *nowp = Curl_pgrsTime(data, TIMER_POSTQUEUE); if(async) @@ -2016,7 +2011,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, protocol connect is already done and we can go directly to WAITDO or DO! */ rc = CURLM_CALL_MULTI_PERFORM; - if(connected) multistate(data, MSTATE_PROTOCONNECT); else { @@ -2285,7 +2279,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, follow = FOLLOW_RETRY; drc = Curl_follow(data, newurl, follow); if(!drc) { - multistate(data, MSTATE_SETUP); + multistate(data, MSTATE_CONNECT); rc = CURLM_CALL_MULTI_PERFORM; result = CURLE_OK; } @@ -2545,7 +2539,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, /* multi_done() might return CURLE_GOT_NOTHING */ result = Curl_follow(data, newurl, follow); if(!result) { - multistate(data, MSTATE_SETUP); + multistate(data, MSTATE_CONNECT); rc = CURLM_CALL_MULTI_PERFORM; } } @@ -2638,7 +2632,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, * (i.e. CURLM_CALL_MULTI_PERFORM == TRUE) then we should do that before * declaring the connection timed out as we may almost have a completed * connection. */ - multi_handle_timeout(data, nowp, &stream_error, &result, FALSE); + multi_handle_timeout(data, nowp, &stream_error, &result, TRUE); } statemachine_end: @@ -2777,20 +2771,9 @@ CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles) */ do { multi->timetree = Curl_splaygetbest(now, multi->timetree, &t); - if(t) { + if(t) /* the removed may have another timeout in queue */ - data = t->payload; - if(data->mstate == MSTATE_PENDING) { - bool stream_unused; - CURLcode result_unused; - if(multi_handle_timeout(data, &now, &stream_unused, &result_unused, - FALSE)) { - infof(data, "PENDING handle timeout"); - move_pending_to_connect(multi, data); - } - } (void)add_next_timeout(now, multi, t->payload); - } } while(t); *running_handles = multi->num_alive; @@ -3759,43 +3742,29 @@ void Curl_multiuse_state(struct Curl_easy *data, process_pending_handles(data->multi); } -static void move_pending_to_connect(struct Curl_multi *multi, - struct Curl_easy *data) +/* process_pending_handles() moves all handles from PENDING + back into the main list and change state to CONNECT */ +static void process_pending_handles(struct Curl_multi *multi) { - DEBUGASSERT(data->mstate == MSTATE_PENDING); - - /* put it back into the main list */ - link_easy(multi, data); - - multistate(data, MSTATE_CONNECT); + struct Curl_llist_element *e = multi->pending.head; + if(e) { + struct Curl_easy *data = e->ptr; - /* Remove this node from the pending list */ - Curl_llist_remove(&multi->pending, &data->connect_queue, NULL); + DEBUGASSERT(data->mstate == MSTATE_PENDING); - /* Make sure that the handle will be processed soonish. */ - Curl_expire(data, 0, EXPIRE_RUN_NOW); -} + /* put it back into the main list */ + link_easy(multi, data); -/* process_pending_handles() moves a handle from PENDING back into the main - list and change state to CONNECT. + multistate(data, MSTATE_CONNECT); - We do not move all transfers because that can be a significant amount. - Since this is tried every now and then doing too many too often becomes a - performance problem. + /* Remove this node from the list */ + Curl_llist_remove(&multi->pending, e, NULL); - When there is a change for connection limits like max host connections etc, - this likely only allows one new transfer. When there is a pipewait change, - it can potentially allow hundreds of new transfers. + /* Make sure that the handle will be processed soonish. */ + Curl_expire(data, 0, EXPIRE_RUN_NOW); - We could consider an improvement where we store the queue reason and allow - more pipewait rechecks than others. -*/ -static void process_pending_handles(struct Curl_multi *multi) -{ - struct Curl_llist_element *e = multi->pending.head; - if(e) { - struct Curl_easy *data = e->ptr; - move_pending_to_connect(multi, data); + /* mark this as having been in the pending queue */ + data->state.previouslypending = TRUE; } } diff --git a/lib/multihandle.h b/lib/multihandle.h index add9a05184a7e4c20180f468095aafc9aa9ed698..82e868c663df512271e7018e6f6ed4920c6c7692 100644 --- a/lib/multihandle.h +++ b/lib/multihandle.h @@ -44,25 +44,24 @@ struct Curl_message { typedef enum { MSTATE_INIT, /* 0 - start in this state */ MSTATE_PENDING, /* 1 - no connections, waiting for one */ - MSTATE_SETUP, /* 2 - start a new transfer */ - MSTATE_CONNECT, /* 3 - resolve/connect has been sent off */ - MSTATE_RESOLVING, /* 4 - awaiting the resolve to finalize */ - MSTATE_CONNECTING, /* 5 - awaiting the TCP connect to finalize */ - MSTATE_TUNNELING, /* 6 - awaiting HTTPS proxy SSL initialization to + MSTATE_CONNECT, /* 2 - resolve/connect has been sent off */ + MSTATE_RESOLVING, /* 3 - awaiting the resolve to finalize */ + MSTATE_CONNECTING, /* 4 - awaiting the TCP connect to finalize */ + MSTATE_TUNNELING, /* 5 - awaiting HTTPS proxy SSL initialization to complete and/or proxy CONNECT to finalize */ - MSTATE_PROTOCONNECT, /* 7 - initiate protocol connect procedure */ - MSTATE_PROTOCONNECTING, /* 8 - completing the protocol-specific connect + MSTATE_PROTOCONNECT, /* 6 - initiate protocol connect procedure */ + MSTATE_PROTOCONNECTING, /* 7 - completing the protocol-specific connect phase */ - MSTATE_DO, /* 9 - start send off the request (part 1) */ - MSTATE_DOING, /* 10 - sending off the request (part 1) */ - MSTATE_DOING_MORE, /* 11 - send off the request (part 2) */ - MSTATE_DID, /* 12 - done sending off request */ - MSTATE_PERFORMING, /* 13 - transfer data */ - MSTATE_RATELIMITING, /* 14 - wait because limit-rate exceeded */ - MSTATE_DONE, /* 15 - post data transfer operation */ - MSTATE_COMPLETED, /* 16 - operation complete */ - MSTATE_MSGSENT, /* 17 - the operation complete message is sent */ - MSTATE_LAST /* 18 - not a true state, never use this */ + MSTATE_DO, /* 8 - start send off the request (part 1) */ + MSTATE_DOING, /* 9 - sending off the request (part 1) */ + MSTATE_DOING_MORE, /* 10 - send off the request (part 2) */ + MSTATE_DID, /* 11 - done sending off request */ + MSTATE_PERFORMING, /* 12 - transfer data */ + MSTATE_RATELIMITING, /* 13 - wait because limit-rate exceeded */ + MSTATE_DONE, /* 14 - post data transfer operation */ + MSTATE_COMPLETED, /* 15 - operation complete */ + MSTATE_MSGSENT, /* 16 - the operation complete message is sent */ + MSTATE_LAST /* 17 - not a true state, never use this */ } CURLMstate; /* we support N sockets per easy handle. Set the corresponding bit to what diff --git a/lib/setopt.c b/lib/setopt.c index e8b25454b2f9df4f426d64a4a3f6e715e9e3ecff..27bedc9fb86a3e44a77285f241b268f24f39d1e5 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -3174,6 +3174,21 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) case CURLOPT_QUICK_EXIT: data->set.quick_exit = (0 != va_arg(param, long)) ? 1L:0L; break; +#ifdef OHOS_BIND_NET_BY_FWMARK + case CURLOPT_OHOS_SOCKET_BIND_NET_ID: + uarg = va_arg(param, unsigned long); +#define MAX_NET_ID (0xFFF - 0x400) + if (uarg > MAX_NET_ID) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.socket_bint_netid = uarg; +#endif + break; + case CURLOPT_CONNREUSEFUNCTION: + data->set.fconnreuse = va_arg(param, curl_connreuse_callback); + break; + case CURLOPT_CONNREUSEDATA: + data->set.connreuse_userp = va_arg(param, void *); + break; default: /* unknown tag and its companion, just ignore: */ result = CURLE_UNKNOWN_OPTION; diff --git a/lib/url.c b/lib/url.c index 342049a6490a55e096073a244155c915bed0c8a3..46d8a6a4047af6c92bee193c0d1cb870345fd670 100644 --- a/lib/url.c +++ b/lib/url.c @@ -490,6 +490,11 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data) memset(&set->priority, 0, sizeof(set->priority)); #endif set->quick_exit = 0L; +#ifdef OHOS_BIND_NET_BY_FWMARK + set->socket_bind_netid = 0; /* OHOS default network */ +#endif + set->fconnreuse = ZERO_NULL; + set->connreuse_userp = ZERO_NULL; return result; } @@ -1325,7 +1330,15 @@ ConnectionExists(struct Curl_easy *data, Curl_disconnect(data, check, TRUE); continue; } - +#ifdef OHOS_BIND_NET_BY_FWMARK + if (check->socket_bind_netid != data->set.socket_bind_netid) { + continue; + } +#endif + if (data->set.fconnreuse && !data->set.fconnreuse(data->set.connreuse_userp, check->sockfd)) { + // no reuse + continue; + } /* We have found a connection. Let's stop searching. */ chosen = check; break; @@ -1454,7 +1467,9 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) conn->closesocket_client = data->set.closesocket_client; conn->lastused = conn->created; conn->gssapi_delegation = data->set.gssapi_delegation; - +#if OHOS_BIND_NET_BY_FWMARK + conn->socket_bind_netid = 0; /* OHOS default net id*/ +#endif return conn; error: diff --git a/lib/urldata.h b/lib/urldata.h index 02e3bcf9c9bb697652ab2b6e721b86567a477c3d..1863d6ac350ede02c7b26377e1c95b38c9eae68d 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -1014,6 +1014,10 @@ struct connectdata { unsigned char httpversion; /* the HTTP version*10 reported by the server */ unsigned char connect_only; unsigned char gssapi_delegation; /* inherited from set.gssapi_delegation */ + +#ifdef OHOS_BIND_NET_BY_FWMARK + unsigned int socket_bind_netid; /* OHOS net id*/ +#endif }; #ifndef CURL_DISABLE_PROXY @@ -1400,6 +1404,7 @@ struct UrlState { BIT(done); /* set to FALSE when Curl_init_do() is called and set to TRUE when multi_done() is called, to prevent multi_done() to get invoked twice when the multi interface is used. */ + BIT(previouslypending); /* this transfer WAS in the multi->pending queue */ #ifndef CURL_DISABLE_COOKIES BIT(cookie_engine); #endif @@ -1875,6 +1880,11 @@ struct UserDefined { #ifdef USE_WEBSOCKETS BIT(ws_raw_mode); #endif +#ifdef OHOS_BIND_NET_BY_FWMARK + unsigned int socket_bind_netid; /* OHOS net id*/ +#endif + curl_connreuse_callback fconnreuse; + void *connreuse_userp; #ifdef USE_ECH int tls_ech; /* TLS ECH configuration */ #endif