curl_multi_get_handles: get easy handles from a multi handle

Closes #11750
This commit is contained in:
Daniel Stenberg 2023-09-25 17:08:41 +02:00
parent bb4032a152
commit 9ffd411735
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
10 changed files with 113 additions and 1 deletions

View File

@ -73,6 +73,7 @@ man_MANS = \
curl_multi_assign.3 \ curl_multi_assign.3 \
curl_multi_cleanup.3 \ curl_multi_cleanup.3 \
curl_multi_fdset.3 \ curl_multi_fdset.3 \
curl_multi_get_handles.3 \
curl_multi_info_read.3 \ curl_multi_info_read.3 \
curl_multi_init.3 \ curl_multi_init.3 \
curl_multi_perform.3 \ curl_multi_perform.3 \

View File

@ -0,0 +1,73 @@
.\" **************************************************************************
.\" * _ _ ____ _
.\" * Project ___| | | | _ \| |
.\" * / __| | | | |_) | |
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
.\" * are also available at https://curl.se/docs/copyright.html.
.\" *
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
.\" * copies of the Software, and permit persons to whom the Software is
.\" * furnished to do so, under the terms of the COPYING file.
.\" *
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
.\" * KIND, either express or implied.
.\" *
.\" * SPDX-License-Identifier: curl
.\" *
.\" **************************************************************************
.TH curl_multi_get_handles 3 "28 August 2023" "libcurl" "libcurl"
.SH NAME
curl_multi_get_handles - returns all added easy handles
.SH SYNOPSIS
.nf
#include <curl/curl.h>
CURL **curl_multi_get_handles(CURLM *multi_handle);
.fi
.SH DESCRIPTION
Returns an array with pointers to all added easy handles. The end of the list
is marked with a NULL pointer.
Even if there is not a single easy handle added, this still returns an array
but with only a single NULL pointer entry.
The returned array contains all the handles that are present at the time of
the call. As soon as a handle has been removed from or a handle has been added
to the multi handle after the handle array was returned, the two data points
are out of sync.
The order of the easy handles within the array is not guaranteed.
The returned array must be freed with a call to \fIcurl_free(3)\fP after use.
.SH EXAMPLE
.nf
/* init a multi stack */
multi_handle = curl_multi_init();
/* add a transfer */
curl_multi_add_handle(multi_handle, http_handle);
/* extract all added handles */
CURL **list = curl_multi_get_handles(multi_handle);
if(list) {
/* remove all added handles */
for(i = 0; list[i]; i++) {
curl_multi_remove_handle(multi_handle, list[i]);
}
curl_free(list);
}
.fi
.SH AVAILABILITY
Added in 8.4.0
.SH RETURN VALUE
Returns NULL on failure. Otherwise it returns a pointer to an allocated array.
.SH "SEE ALSO"
.BR curl_multi_cleanup "(3)," curl_multi_init "(3), "
.BR curl_multi_add_handle "(3), " curl_multi_remove_handle "(3) "

View File

@ -426,6 +426,17 @@ CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle,
CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle, CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle,
curl_socket_t sockfd, void *sockp); curl_socket_t sockfd, void *sockp);
/*
* Name: curl_multi_get_handles()
*
* Desc: Returns an allocated array holding all handles currently added to
* the multi handle. Marks the final entry with a NULL pointer. If
* there is no easy handle added to the multi handle, this function
* returns an array with the first entry as a NULL pointer.
*
* Returns: NULL on failure, otherwise a CURL **array pointer
*/
CURL_EXTERN CURL **curl_multi_get_handles(CURLM *multi_handle);
/* /*
* Name: curl_push_callback * Name: curl_push_callback

View File

@ -107,6 +107,7 @@ int Curl_conncache_init(struct conncache *connc, int size)
connc->closure_handle = curl_easy_init(); connc->closure_handle = curl_easy_init();
if(!connc->closure_handle) if(!connc->closure_handle)
return 1; /* bad */ return 1; /* bad */
connc->closure_handle->internal = true;
Curl_hash_init(&connc->hash, size, Curl_hash_str, Curl_hash_init(&connc->hash, size, Curl_hash_str,
Curl_str_key_compare, free_bundle_hash_entry); Curl_str_key_compare, free_bundle_hash_entry);

View File

@ -242,6 +242,7 @@ static CURLcode dohprobe(struct Curl_easy *data,
/* pass in the struct pointer via a local variable to please coverity and /* pass in the struct pointer via a local variable to please coverity and
the gcc typecheck helpers */ the gcc typecheck helpers */
struct dynbuf *resp = &p->serverdoh; struct dynbuf *resp = &p->serverdoh;
doh->internal = true;
ERROR_CHECK_SETOPT(CURLOPT_URL, url); ERROR_CHECK_SETOPT(CURLOPT_URL, url);
ERROR_CHECK_SETOPT(CURLOPT_DEFAULT_PROTOCOL, "https"); ERROR_CHECK_SETOPT(CURLOPT_DEFAULT_PROTOCOL, "https");
ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_write_cb); ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_write_cb);

View File

@ -3788,3 +3788,21 @@ unsigned int Curl_multi_max_concurrent_streams(struct Curl_multi *multi)
DEBUGASSERT(multi); DEBUGASSERT(multi);
return multi->max_concurrent_streams; return multi->max_concurrent_streams;
} }
struct Curl_easy **curl_multi_get_handles(struct Curl_multi *multi)
{
struct Curl_easy **a = malloc(sizeof(struct Curl_easy *) *
(multi->num_easy + 1));
if(a) {
int i = 0;
struct Curl_easy *e = multi->easyp;
while(e) {
DEBUGASSERT(i < multi->num_easy);
if(!e->internal)
a[i++] = e;
e = e->next;
}
a[i] = NULL; /* last entry is a NULL */
}
return a;
}

View File

@ -1950,7 +1950,7 @@ struct Curl_easy {
other using the same cache. For easier tracking other using the same cache. For easier tracking
in log output. in log output.
This may wrap around after LONG_MAX to 0 again, so it This may wrap around after LONG_MAX to 0 again, so it
has no uniqueness guarantuee for very large processings. */ has no uniqueness guarantee for very large processings. */
curl_off_t id; curl_off_t id;
/* first, two fields for the linked list of these */ /* first, two fields for the linked list of these */
@ -2013,6 +2013,10 @@ struct Curl_easy {
#ifdef USE_HYPER #ifdef USE_HYPER
struct hyptransfer hyp; struct hyptransfer hyp;
#endif #endif
/* internal: true if this easy handle was created for internal use and the
user does not have ownership of the handle. */
bool internal;
}; };
#define LIBCURL_NAME "libcurl" #define LIBCURL_NAME "libcurl"

View File

@ -51,6 +51,7 @@ curl_multi_add_handle
curl_multi_assign curl_multi_assign
curl_multi_cleanup curl_multi_cleanup
curl_multi_fdset curl_multi_fdset
curl_multi_get_handles
curl_multi_info_read curl_multi_info_read
curl_multi_init curl_multi_init
curl_multi_perform curl_multi_perform

View File

@ -96,6 +96,7 @@ my %api = (
'curl_multi_assign' => 'API', 'curl_multi_assign' => 'API',
'curl_multi_cleanup' => 'API', 'curl_multi_cleanup' => 'API',
'curl_multi_fdset' => 'API', 'curl_multi_fdset' => 'API',
'curl_multi_get_handles' => 'API',
'curl_multi_info_read' => 'API', 'curl_multi_info_read' => 'API',
'curl_multi_init' => 'API', 'curl_multi_init' => 'API',
'curl_multi_perform' => 'API', 'curl_multi_perform' => 'API',

View File

@ -106,6 +106,7 @@ curl_multi_socket_all
curl_multi_timeout curl_multi_timeout
curl_multi_setopt curl_multi_setopt
curl_multi_assign curl_multi_assign
curl_multi_get_handles
curl_pushheader_bynum curl_pushheader_bynum
curl_pushheader_byname curl_pushheader_byname
curl_easy_option_by_name curl_easy_option_by_name