Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

curl_multi_get_handles - get all easy handles in a multi handle #11750

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/libcurl/Makefile.inc
Expand Up @@ -73,6 +73,7 @@ man_MANS = \
curl_multi_assign.3 \
curl_multi_cleanup.3 \
curl_multi_fdset.3 \
curl_multi_get_handles.3 \
curl_multi_info_read.3 \
curl_multi_init.3 \
curl_multi_perform.3 \
Expand Down
73 changes: 73 additions & 0 deletions docs/libcurl/curl_multi_get_handles.3
@@ -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) "
11 changes: 11 additions & 0 deletions include/curl/multi.h
Expand Up @@ -426,6 +426,17 @@ CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle,
CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle,
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
Expand Down
1 change: 1 addition & 0 deletions lib/conncache.c
Expand Up @@ -107,6 +107,7 @@ int Curl_conncache_init(struct conncache *connc, int size)
connc->closure_handle = curl_easy_init();
if(!connc->closure_handle)
return 1; /* bad */
connc->closure_handle->internal = true;

Curl_hash_init(&connc->hash, size, Curl_hash_str,
Curl_str_key_compare, free_bundle_hash_entry);
Expand Down
1 change: 1 addition & 0 deletions lib/doh.c
Expand Up @@ -242,6 +242,7 @@ static CURLcode dohprobe(struct Curl_easy *data,
/* pass in the struct pointer via a local variable to please coverity and
the gcc typecheck helpers */
struct dynbuf *resp = &p->serverdoh;
doh->internal = true;
ERROR_CHECK_SETOPT(CURLOPT_URL, url);
ERROR_CHECK_SETOPT(CURLOPT_DEFAULT_PROTOCOL, "https");
ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_write_cb);
Expand Down
18 changes: 18 additions & 0 deletions lib/multi.c
Expand Up @@ -3788,3 +3788,21 @@ unsigned int Curl_multi_max_concurrent_streams(struct Curl_multi *multi)
DEBUGASSERT(multi);
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;
}
6 changes: 5 additions & 1 deletion lib/urldata.h
Expand Up @@ -1950,7 +1950,7 @@ struct Curl_easy {
other using the same cache. For easier tracking
in log output.
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;

/* first, two fields for the linked list of these */
Expand Down Expand Up @@ -2013,6 +2013,10 @@ struct Curl_easy {
#ifdef USE_HYPER
struct hyptransfer hyp;
#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"
Expand Down
1 change: 1 addition & 0 deletions libcurl.def
Expand Up @@ -51,6 +51,7 @@ curl_multi_add_handle
curl_multi_assign
curl_multi_cleanup
curl_multi_fdset
curl_multi_get_handles
curl_multi_info_read
curl_multi_init
curl_multi_perform
Expand Down
1 change: 1 addition & 0 deletions scripts/singleuse.pl
Expand Up @@ -96,6 +96,7 @@
'curl_multi_assign' => 'API',
'curl_multi_cleanup' => 'API',
'curl_multi_fdset' => 'API',
'curl_multi_get_handles' => 'API',
'curl_multi_info_read' => 'API',
'curl_multi_init' => 'API',
'curl_multi_perform' => 'API',
Expand Down
1 change: 1 addition & 0 deletions tests/data/test1135
Expand Up @@ -106,6 +106,7 @@ curl_multi_socket_all
curl_multi_timeout
curl_multi_setopt
curl_multi_assign
curl_multi_get_handles
curl_pushheader_bynum
curl_pushheader_byname
curl_easy_option_by_name
Expand Down