#ifndef CURLINC_MULTI_H1#define CURLINC_MULTI_H2/***************************************************************************3* _ _ ____ _4* Project ___| | | | _ \| |5* / __| | | | |_) | |6* | (__| |_| | _ <| |___7* \___|\___/|_| \_\_____|8*9* Copyright (C) Daniel Stenberg, <[email protected]>, et al.10*11* This software is licensed as described in the file COPYING, which12* you should have received as part of this distribution. The terms13* are also available at https://curl.se/docs/copyright.html.14*15* You may opt to use, copy, modify, merge, publish, distribute and/or sell16* copies of the Software, and permit persons to whom the Software is17* furnished to do so, under the terms of the COPYING file.18*19* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY20* KIND, either express or implied.21*22* SPDX-License-Identifier: curl23*24***************************************************************************/25/*26This is an "external" header file. Do not give away any internals here!2728GOALS2930o Enable a "pull" interface. The application that uses libcurl decides where31and when to ask libcurl to get/send data.3233o Enable multiple simultaneous transfers in the same thread without making it34complicated for the application.3536o Enable the application to select() on its own file descriptors and curl's37file descriptors simultaneous easily.3839*/4041/*42* This header file should not really need to include "curl.h" since curl.h43* itself includes this file and we expect user applications to do #include44* <curl/curl.h> without the need for especially including multi.h.45*46* For some reason we added this include here at one point, and rather than to47* break existing (wrongly written) libcurl applications, we leave it as-is48* but with this warning attached.49*/50#include "curl.h"5152#ifdef __cplusplus53extern "C" {54#endif5556typedef void CURLM;5758typedef enum {59CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or60curl_multi_socket*() soon */61CURLM_OK,62CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */63CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */64CURLM_OUT_OF_MEMORY, /* if you ever get this, you are in deep sh*t */65CURLM_INTERNAL_ERROR, /* this is a libcurl bug */66CURLM_BAD_SOCKET, /* the passed in socket argument did not match */67CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */68CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was69attempted to get added - again */70CURLM_RECURSIVE_API_CALL, /* an api function was called from inside a71callback */72CURLM_WAKEUP_FAILURE, /* wakeup is unavailable or failed */73CURLM_BAD_FUNCTION_ARGUMENT, /* function called with a bad parameter */74CURLM_ABORTED_BY_CALLBACK,75CURLM_UNRECOVERABLE_POLL,76CURLM_LAST77} CURLMcode;7879/* just to make code nicer when using curl_multi_socket() you can now check80for CURLM_CALL_MULTI_SOCKET too in the same style it works for81curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */82#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM8384/* bitmask bits for CURLMOPT_PIPELINING */85#define CURLPIPE_NOTHING 0L86#define CURLPIPE_HTTP1 1L87#define CURLPIPE_MULTIPLEX 2L8889typedef enum {90CURLMSG_NONE, /* first, not used */91CURLMSG_DONE, /* This easy handle has completed. 'result' contains92the CURLcode of the transfer */93CURLMSG_LAST /* last, not used */94} CURLMSG;9596struct CURLMsg {97CURLMSG msg; /* what this message means */98CURL *easy_handle; /* the handle it concerns */99union {100void *whatever; /* message-specific data */101CURLcode result; /* return code for transfer */102} data;103};104typedef struct CURLMsg CURLMsg;105106/* Based on poll(2) structure and values.107* We do not use pollfd and POLL* constants explicitly108* to cover platforms without poll(). */109#define CURL_WAIT_POLLIN 0x0001110#define CURL_WAIT_POLLPRI 0x0002111#define CURL_WAIT_POLLOUT 0x0004112113struct curl_waitfd {114curl_socket_t fd;115short events;116short revents;117};118119/*120* Name: curl_multi_init()121*122* Desc: initialize multi-style curl usage123*124* Returns: a new CURLM handle to use in all 'curl_multi' functions.125*/126CURL_EXTERN CURLM *curl_multi_init(void);127128/*129* Name: curl_multi_add_handle()130*131* Desc: add a standard curl handle to the multi stack132*133* Returns: CURLMcode type, general multi error code.134*/135CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle,136CURL *curl_handle);137138/*139* Name: curl_multi_remove_handle()140*141* Desc: removes a curl handle from the multi stack again142*143* Returns: CURLMcode type, general multi error code.144*/145CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle,146CURL *curl_handle);147148/*149* Name: curl_multi_fdset()150*151* Desc: Ask curl for its fd_set sets. The app can use these to select() or152* poll() on. We want curl_multi_perform() called as soon as one of153* them are ready.154*155* Returns: CURLMcode type, general multi error code.156*/157CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle,158fd_set *read_fd_set,159fd_set *write_fd_set,160fd_set *exc_fd_set,161int *max_fd);162163/*164* Name: curl_multi_wait()165*166* Desc: Poll on all fds within a CURLM set as well as any167* additional fds passed to the function.168*169* Returns: CURLMcode type, general multi error code.170*/171CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle,172struct curl_waitfd extra_fds[],173unsigned int extra_nfds,174int timeout_ms,175int *ret);176177/*178* Name: curl_multi_poll()179*180* Desc: Poll on all fds within a CURLM set as well as any181* additional fds passed to the function.182*183* Returns: CURLMcode type, general multi error code.184*/185CURL_EXTERN CURLMcode curl_multi_poll(CURLM *multi_handle,186struct curl_waitfd extra_fds[],187unsigned int extra_nfds,188int timeout_ms,189int *ret);190191/*192* Name: curl_multi_wakeup()193*194* Desc: wakes up a sleeping curl_multi_poll call.195*196* Returns: CURLMcode type, general multi error code.197*/198CURL_EXTERN CURLMcode curl_multi_wakeup(CURLM *multi_handle);199200/*201* Name: curl_multi_perform()202*203* Desc: When the app thinks there is data available for curl it calls this204* function to read/write whatever there is right now. This returns205* as soon as the reads and writes are done. This function does not206* require that there actually is data available for reading or that207* data can be written, it can be called just in case. It returns208* the number of handles that still transfer data in the second209* argument's integer-pointer.210*211* Returns: CURLMcode type, general multi error code. *NOTE* that this only212* returns errors etc regarding the whole multi stack. There might213* still have occurred problems on individual transfers even when214* this returns OK.215*/216CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle,217int *running_handles);218219/*220* Name: curl_multi_cleanup()221*222* Desc: Cleans up and removes a whole multi stack. It does not free or223* touch any individual easy handles in any way. We need to define224* in what state those handles will be if this function is called225* in the middle of a transfer.226*227* Returns: CURLMcode type, general multi error code.228*/229CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle);230231/*232* Name: curl_multi_info_read()233*234* Desc: Ask the multi handle if there is any messages/informationals from235* the individual transfers. Messages include informationals such as236* error code from the transfer or just the fact that a transfer is237* completed. More details on these should be written down as well.238*239* Repeated calls to this function will return a new struct each240* time, until a special "end of msgs" struct is returned as a signal241* that there is no more to get at this point.242*243* The data the returned pointer points to will not survive calling244* curl_multi_cleanup().245*246* The 'CURLMsg' struct is meant to be simple and only contain basic247* information. If more involved information is wanted, we will248* provide the particular "transfer handle" in that struct and that249* should/could/would be used in subsequent curl_easy_getinfo() calls250* (or similar). The point being that we must never expose complex251* structs to applications, as then we will undoubtably get backwards252* compatibility problems in the future.253*254* Returns: A pointer to a filled-in struct, or NULL if it failed or ran out255* of structs. It also writes the number of messages left in the256* queue (after this read) in the integer the second argument points257* to.258*/259CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle,260int *msgs_in_queue);261262/*263* Name: curl_multi_strerror()264*265* Desc: The curl_multi_strerror function may be used to turn a CURLMcode266* value into the equivalent human readable error string. This is267* useful for printing meaningful error messages.268*269* Returns: A pointer to a null-terminated error message.270*/271CURL_EXTERN const char *curl_multi_strerror(CURLMcode);272273/*274* Name: curl_multi_socket() and275* curl_multi_socket_all()276*277* Desc: An alternative version of curl_multi_perform() that allows the278* application to pass in one of the file descriptors that have been279* detected to have "action" on them and let libcurl perform.280* See manpage for details.281*/282#define CURL_POLL_NONE 0283#define CURL_POLL_IN 1284#define CURL_POLL_OUT 2285#define CURL_POLL_INOUT 3286#define CURL_POLL_REMOVE 4287288#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD289290#define CURL_CSELECT_IN 0x01291#define CURL_CSELECT_OUT 0x02292#define CURL_CSELECT_ERR 0x04293294typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */295curl_socket_t s, /* socket */296int what, /* see above */297void *userp, /* private callback298pointer */299void *socketp); /* private socket300pointer */301/*302* Name: curl_multi_timer_callback303*304* Desc: Called by libcurl whenever the library detects a change in the305* maximum number of milliseconds the app is allowed to wait before306* curl_multi_socket() or curl_multi_perform() must be called307* (to allow libcurl's timed events to take place).308*309* Returns: The callback should return zero.310*/311typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */312long timeout_ms, /* see above */313void *userp); /* private callback314pointer */315316CURL_EXTERN CURLMcode CURL_DEPRECATED(7.19.5, "Use curl_multi_socket_action()")317curl_multi_socket(CURLM *multi_handle, curl_socket_t s, int *running_handles);318319CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle,320curl_socket_t s,321int ev_bitmask,322int *running_handles);323324CURL_EXTERN CURLMcode CURL_DEPRECATED(7.19.5, "Use curl_multi_socket_action()")325curl_multi_socket_all(CURLM *multi_handle, int *running_handles);326327#ifndef CURL_ALLOW_OLD_MULTI_SOCKET328/* This macro below was added in 7.16.3 to push users who recompile to use329the new curl_multi_socket_action() instead of the old curl_multi_socket()330*/331#define curl_multi_socket(x,y,z) curl_multi_socket_action(x,y,0,z)332#endif333334/*335* Name: curl_multi_timeout()336*337* Desc: Returns the maximum number of milliseconds the app is allowed to338* wait before curl_multi_socket() or curl_multi_perform() must be339* called (to allow libcurl's timed events to take place).340*341* Returns: CURLM error code.342*/343CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle,344long *milliseconds);345346typedef enum {347/* This is the socket callback function pointer */348CURLOPT(CURLMOPT_SOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 1),349350/* This is the argument passed to the socket callback */351CURLOPT(CURLMOPT_SOCKETDATA, CURLOPTTYPE_OBJECTPOINT, 2),352353/* set to 1 to enable pipelining for this multi handle */354CURLOPT(CURLMOPT_PIPELINING, CURLOPTTYPE_LONG, 3),355356/* This is the timer callback function pointer */357CURLOPT(CURLMOPT_TIMERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 4),358359/* This is the argument passed to the timer callback */360CURLOPT(CURLMOPT_TIMERDATA, CURLOPTTYPE_OBJECTPOINT, 5),361362/* maximum number of entries in the connection cache */363CURLOPT(CURLMOPT_MAXCONNECTS, CURLOPTTYPE_LONG, 6),364365/* maximum number of (pipelining) connections to one host */366CURLOPT(CURLMOPT_MAX_HOST_CONNECTIONS, CURLOPTTYPE_LONG, 7),367368/* maximum number of requests in a pipeline */369CURLOPT(CURLMOPT_MAX_PIPELINE_LENGTH, CURLOPTTYPE_LONG, 8),370371/* a connection with a content-length longer than this372will not be considered for pipelining */373CURLOPT(CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 9),374375/* a connection with a chunk length longer than this376will not be considered for pipelining */377CURLOPT(CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 10),378379/* a list of site names(+port) that are blocked from pipelining */380CURLOPT(CURLMOPT_PIPELINING_SITE_BL, CURLOPTTYPE_OBJECTPOINT, 11),381382/* a list of server types that are blocked from pipelining */383CURLOPT(CURLMOPT_PIPELINING_SERVER_BL, CURLOPTTYPE_OBJECTPOINT, 12),384385/* maximum number of open connections in total */386CURLOPT(CURLMOPT_MAX_TOTAL_CONNECTIONS, CURLOPTTYPE_LONG, 13),387388/* This is the server push callback function pointer */389CURLOPT(CURLMOPT_PUSHFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 14),390391/* This is the argument passed to the server push callback */392CURLOPT(CURLMOPT_PUSHDATA, CURLOPTTYPE_OBJECTPOINT, 15),393394/* maximum number of concurrent streams to support on a connection */395CURLOPT(CURLMOPT_MAX_CONCURRENT_STREAMS, CURLOPTTYPE_LONG, 16),396397CURLMOPT_LASTENTRY /* the last unused */398} CURLMoption;399400401/*402* Name: curl_multi_setopt()403*404* Desc: Sets options for the multi handle.405*406* Returns: CURLM error code.407*/408CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle,409CURLMoption option, ...);410411412/*413* Name: curl_multi_assign()414*415* Desc: This function sets an association in the multi handle between the416* given socket and a private pointer of the application. This is417* (only) useful for curl_multi_socket uses.418*419* Returns: CURLM error code.420*/421CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle,422curl_socket_t sockfd, void *sockp);423424/*425* Name: curl_multi_get_handles()426*427* Desc: Returns an allocated array holding all handles currently added to428* the multi handle. Marks the final entry with a NULL pointer. If429* there is no easy handle added to the multi handle, this function430* returns an array with the first entry as a NULL pointer.431*432* Returns: NULL on failure, otherwise a CURL **array pointer433*/434CURL_EXTERN CURL **curl_multi_get_handles(CURLM *multi_handle);435436/*437* Name: curl_push_callback438*439* Desc: This callback gets called when a new stream is being pushed by the440* server. It approves or denies the new stream. It can also decide441* to completely fail the connection.442*443* Returns: CURL_PUSH_OK, CURL_PUSH_DENY or CURL_PUSH_ERROROUT444*/445#define CURL_PUSH_OK 0446#define CURL_PUSH_DENY 1447#define CURL_PUSH_ERROROUT 2 /* added in 7.72.0 */448449struct curl_pushheaders; /* forward declaration only */450451CURL_EXTERN char *curl_pushheader_bynum(struct curl_pushheaders *h,452size_t num);453CURL_EXTERN char *curl_pushheader_byname(struct curl_pushheaders *h,454const char *name);455456typedef int (*curl_push_callback)(CURL *parent,457CURL *easy,458size_t num_headers,459struct curl_pushheaders *headers,460void *userp);461462/*463* Name: curl_multi_waitfds()464*465* Desc: Ask curl for fds for polling. The app can use these to poll on.466* We want curl_multi_perform() called as soon as one of them are467* ready. Passing zero size allows to get just a number of fds.468*469* Returns: CURLMcode type, general multi error code.470*/471CURL_EXTERN CURLMcode curl_multi_waitfds(CURLM *multi,472struct curl_waitfd *ufds,473unsigned int size,474unsigned int *fd_count);475476#ifdef __cplusplus477} /* end of extern "C" */478#endif479480#endif481482483