| 1 | #ifndef __CURL_MULTI_H | 
| 2 | #define __CURL_MULTI_H | 
| 3 | /*************************************************************************** | 
| 4 |  *                                  _   _ ____  _ | 
| 5 |  *  Project                     ___| | | |  _ \| | | 
| 6 |  *                             / __| | | | |_) | | | 
| 7 |  *                            | (__| |_| |  _ <| |___ | 
| 8 |  *                             \___|\___/|_| \_\_____| | 
| 9 |  * | 
| 10 |  * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al. | 
| 11 |  * | 
| 12 |  * This software is licensed as described in the file COPYING, which | 
| 13 |  * you should have received as part of this distribution. The terms | 
| 14 |  * are also available at https://curl.haxx.se/docs/copyright.html. | 
| 15 |  * | 
| 16 |  * You may opt to use, copy, modify, merge, publish, distribute and/or sell | 
| 17 |  * copies of the Software, and permit persons to whom the Software is | 
| 18 |  * furnished to do so, under the terms of the COPYING file. | 
| 19 |  * | 
| 20 |  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | 
| 21 |  * KIND, either express or implied. | 
| 22 |  * | 
| 23 |  ***************************************************************************/ | 
| 24 | /* | 
| 25 |   This is an "external" header file. Don't give away any internals here! | 
| 26 |  | 
| 27 |   GOALS | 
| 28 |  | 
| 29 |   o Enable a "pull" interface. The application that uses libcurl decides where | 
| 30 |     and when to ask libcurl to get/send data. | 
| 31 |  | 
| 32 |   o Enable multiple simultaneous transfers in the same thread without making it | 
| 33 |     complicated for the application. | 
| 34 |  | 
| 35 |   o Enable the application to select() on its own file descriptors and curl's | 
| 36 |     file descriptors simultaneous easily. | 
| 37 |  | 
| 38 | */ | 
| 39 |  | 
| 40 | /* | 
| 41 |  * This header file should not really need to include "curl.h" since curl.h | 
| 42 |  * itself includes this file and we expect user applications to do #include | 
| 43 |  * <curl/curl.h> without the need for especially including multi.h. | 
| 44 |  * | 
| 45 |  * For some reason we added this include here at one point, and rather than to | 
| 46 |  * break existing (wrongly written) libcurl applications, we leave it as-is | 
| 47 |  * but with this warning attached. | 
| 48 |  */ | 
| 49 | #include "curl.h" | 
| 50 |  | 
| 51 | #ifdef  __cplusplus | 
| 52 | extern "C"  { | 
| 53 | #endif | 
| 54 |  | 
| 55 | #if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER) | 
| 56 | typedef struct Curl_multi CURLM; | 
| 57 | #else | 
| 58 | typedef void CURLM; | 
| 59 | #endif | 
| 60 |  | 
| 61 | typedef enum { | 
| 62 |   CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or | 
| 63 |                                     curl_multi_socket*() soon */ | 
| 64 |   CURLM_OK, | 
| 65 |   CURLM_BAD_HANDLE,      /* the passed-in handle is not a valid CURLM handle */ | 
| 66 |   CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */ | 
| 67 |   CURLM_OUT_OF_MEMORY,   /* if you ever get this, you're in deep sh*t */ | 
| 68 |   CURLM_INTERNAL_ERROR,  /* this is a libcurl bug */ | 
| 69 |   CURLM_BAD_SOCKET,      /* the passed in socket argument did not match */ | 
| 70 |   CURLM_UNKNOWN_OPTION,  /* curl_multi_setopt() with unsupported option */ | 
| 71 |   CURLM_ADDED_ALREADY,   /* an easy handle already added to a multi handle was | 
| 72 |                             attempted to get added - again */ | 
| 73 |   CURLM_RECURSIVE_API_CALL, /* an api function was called from inside a | 
| 74 |                                callback */ | 
| 75 |   CURLM_LAST | 
| 76 | } CURLMcode; | 
| 77 |  | 
| 78 | /* just to make code nicer when using curl_multi_socket() you can now check | 
| 79 |    for CURLM_CALL_MULTI_SOCKET too in the same style it works for | 
| 80 |    curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */ | 
| 81 | #define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM | 
| 82 |  | 
| 83 | /* bitmask bits for CURLMOPT_PIPELINING */ | 
| 84 | #define CURLPIPE_NOTHING   0L | 
| 85 | #define CURLPIPE_HTTP1     1L | 
| 86 | #define CURLPIPE_MULTIPLEX 2L | 
| 87 |  | 
| 88 | typedef enum { | 
| 89 |   CURLMSG_NONE, /* first, not used */ | 
| 90 |   CURLMSG_DONE, /* This easy handle has completed. 'result' contains | 
| 91 |                    the CURLcode of the transfer */ | 
| 92 |   CURLMSG_LAST /* last, not used */ | 
| 93 | } CURLMSG; | 
| 94 |  | 
| 95 | struct CURLMsg { | 
| 96 |   CURLMSG msg;       /* what this message means */ | 
| 97 |   CURL *easy_handle; /* the handle it concerns */ | 
| 98 |   union { | 
| 99 |     void *whatever;    /* message-specific data */ | 
| 100 |     CURLcode result;   /* return code for transfer */ | 
| 101 |   } data; | 
| 102 | }; | 
| 103 | typedef struct CURLMsg CURLMsg; | 
| 104 |  | 
| 105 | /* Based on poll(2) structure and values. | 
| 106 |  * We don't use pollfd and POLL* constants explicitly | 
| 107 |  * to cover platforms without poll(). */ | 
| 108 | #define CURL_WAIT_POLLIN    0x0001 | 
| 109 | #define CURL_WAIT_POLLPRI   0x0002 | 
| 110 | #define CURL_WAIT_POLLOUT   0x0004 | 
| 111 |  | 
| 112 | struct curl_waitfd { | 
| 113 |   curl_socket_t fd; | 
| 114 |   short events; | 
| 115 |   short revents; /* not supported yet */ | 
| 116 | }; | 
| 117 |  | 
| 118 | /* | 
| 119 |  * Name:    curl_multi_init() | 
| 120 |  * | 
| 121 |  * Desc:    inititalize multi-style curl usage | 
| 122 |  * | 
| 123 |  * Returns: a new CURLM handle to use in all 'curl_multi' functions. | 
| 124 |  */ | 
| 125 | CURL_EXTERN CURLM *curl_multi_init(void); | 
| 126 |  | 
| 127 | /* | 
| 128 |  * Name:    curl_multi_add_handle() | 
| 129 |  * | 
| 130 |  * Desc:    add a standard curl handle to the multi stack | 
| 131 |  * | 
| 132 |  * Returns: CURLMcode type, general multi error code. | 
| 133 |  */ | 
| 134 | CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle, | 
| 135 |                                             CURL *curl_handle); | 
| 136 |  | 
| 137 |  /* | 
| 138 |   * Name:    curl_multi_remove_handle() | 
| 139 |   * | 
| 140 |   * Desc:    removes a curl handle from the multi stack again | 
| 141 |   * | 
| 142 |   * Returns: CURLMcode type, general multi error code. | 
| 143 |   */ | 
| 144 | CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle, | 
| 145 |                                                CURL *curl_handle); | 
| 146 |  | 
| 147 |  /* | 
| 148 |   * Name:    curl_multi_fdset() | 
| 149 |   * | 
| 150 |   * Desc:    Ask curl for its fd_set sets. The app can use these to select() or | 
| 151 |   *          poll() on. We want curl_multi_perform() called as soon as one of | 
| 152 |   *          them are ready. | 
| 153 |   * | 
| 154 |   * Returns: CURLMcode type, general multi error code. | 
| 155 |   */ | 
| 156 | CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle, | 
| 157 |                                        fd_set *read_fd_set, | 
| 158 |                                        fd_set *write_fd_set, | 
| 159 |                                        fd_set *exc_fd_set, | 
| 160 |                                        int *max_fd); | 
| 161 |  | 
| 162 | /* | 
| 163 |  * Name:     curl_multi_wait() | 
| 164 |  * | 
| 165 |  * Desc:     Poll on all fds within a CURLM set as well as any | 
| 166 |  *           additional fds passed to the function. | 
| 167 |  * | 
| 168 |  * Returns:  CURLMcode type, general multi error code. | 
| 169 |  */ | 
| 170 | CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle, | 
| 171 |                                       struct curl_waitfd [], | 
| 172 |                                       unsigned int , | 
| 173 |                                       int timeout_ms, | 
| 174 |                                       int *ret); | 
| 175 |  | 
| 176 |  /* | 
| 177 |   * Name:    curl_multi_perform() | 
| 178 |   * | 
| 179 |   * Desc:    When the app thinks there's data available for curl it calls this | 
| 180 |   *          function to read/write whatever there is right now. This returns | 
| 181 |   *          as soon as the reads and writes are done. This function does not | 
| 182 |   *          require that there actually is data available for reading or that | 
| 183 |   *          data can be written, it can be called just in case. It returns | 
| 184 |   *          the number of handles that still transfer data in the second | 
| 185 |   *          argument's integer-pointer. | 
| 186 |   * | 
| 187 |   * Returns: CURLMcode type, general multi error code. *NOTE* that this only | 
| 188 |   *          returns errors etc regarding the whole multi stack. There might | 
| 189 |   *          still have occurred problems on individual transfers even when | 
| 190 |   *          this returns OK. | 
| 191 |   */ | 
| 192 | CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle, | 
| 193 |                                          int *running_handles); | 
| 194 |  | 
| 195 |  /* | 
| 196 |   * Name:    curl_multi_cleanup() | 
| 197 |   * | 
| 198 |   * Desc:    Cleans up and removes a whole multi stack. It does not free or | 
| 199 |   *          touch any individual easy handles in any way. We need to define | 
| 200 |   *          in what state those handles will be if this function is called | 
| 201 |   *          in the middle of a transfer. | 
| 202 |   * | 
| 203 |   * Returns: CURLMcode type, general multi error code. | 
| 204 |   */ | 
| 205 | CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle); | 
| 206 |  | 
| 207 | /* | 
| 208 |  * Name:    curl_multi_info_read() | 
| 209 |  * | 
| 210 |  * Desc:    Ask the multi handle if there's any messages/informationals from | 
| 211 |  *          the individual transfers. Messages include informationals such as | 
| 212 |  *          error code from the transfer or just the fact that a transfer is | 
| 213 |  *          completed. More details on these should be written down as well. | 
| 214 |  * | 
| 215 |  *          Repeated calls to this function will return a new struct each | 
| 216 |  *          time, until a special "end of msgs" struct is returned as a signal | 
| 217 |  *          that there is no more to get at this point. | 
| 218 |  * | 
| 219 |  *          The data the returned pointer points to will not survive calling | 
| 220 |  *          curl_multi_cleanup(). | 
| 221 |  * | 
| 222 |  *          The 'CURLMsg' struct is meant to be very simple and only contain | 
| 223 |  *          very basic information. If more involved information is wanted, | 
| 224 |  *          we will provide the particular "transfer handle" in that struct | 
| 225 |  *          and that should/could/would be used in subsequent | 
| 226 |  *          curl_easy_getinfo() calls (or similar). The point being that we | 
| 227 |  *          must never expose complex structs to applications, as then we'll | 
| 228 |  *          undoubtably get backwards compatibility problems in the future. | 
| 229 |  * | 
| 230 |  * Returns: A pointer to a filled-in struct, or NULL if it failed or ran out | 
| 231 |  *          of structs. It also writes the number of messages left in the | 
| 232 |  *          queue (after this read) in the integer the second argument points | 
| 233 |  *          to. | 
| 234 |  */ | 
| 235 | CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle, | 
| 236 |                                           int *msgs_in_queue); | 
| 237 |  | 
| 238 | /* | 
| 239 |  * Name:    curl_multi_strerror() | 
| 240 |  * | 
| 241 |  * Desc:    The curl_multi_strerror function may be used to turn a CURLMcode | 
| 242 |  *          value into the equivalent human readable error string.  This is | 
| 243 |  *          useful for printing meaningful error messages. | 
| 244 |  * | 
| 245 |  * Returns: A pointer to a zero-terminated error message. | 
| 246 |  */ | 
| 247 | CURL_EXTERN const char *curl_multi_strerror(CURLMcode); | 
| 248 |  | 
| 249 | /* | 
| 250 |  * Name:    curl_multi_socket() and | 
| 251 |  *          curl_multi_socket_all() | 
| 252 |  * | 
| 253 |  * Desc:    An alternative version of curl_multi_perform() that allows the | 
| 254 |  *          application to pass in one of the file descriptors that have been | 
| 255 |  *          detected to have "action" on them and let libcurl perform. | 
| 256 |  *          See man page for details. | 
| 257 |  */ | 
| 258 | #define CURL_POLL_NONE   0 | 
| 259 | #define CURL_POLL_IN     1 | 
| 260 | #define CURL_POLL_OUT    2 | 
| 261 | #define CURL_POLL_INOUT  3 | 
| 262 | #define CURL_POLL_REMOVE 4 | 
| 263 |  | 
| 264 | #define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD | 
| 265 |  | 
| 266 | #define CURL_CSELECT_IN   0x01 | 
| 267 | #define CURL_CSELECT_OUT  0x02 | 
| 268 | #define CURL_CSELECT_ERR  0x04 | 
| 269 |  | 
| 270 | typedef int (*curl_socket_callback)(CURL *easy,      /* easy handle */ | 
| 271 |                                     curl_socket_t s, /* socket */ | 
| 272 |                                     int what,        /* see above */ | 
| 273 |                                     void *userp,     /* private callback | 
| 274 |                                                         pointer */ | 
| 275 |                                     void *socketp);  /* private socket | 
| 276 |                                                         pointer */ | 
| 277 | /* | 
| 278 |  * Name:    curl_multi_timer_callback | 
| 279 |  * | 
| 280 |  * Desc:    Called by libcurl whenever the library detects a change in the | 
| 281 |  *          maximum number of milliseconds the app is allowed to wait before | 
| 282 |  *          curl_multi_socket() or curl_multi_perform() must be called | 
| 283 |  *          (to allow libcurl's timed events to take place). | 
| 284 |  * | 
| 285 |  * Returns: The callback should return zero. | 
| 286 |  */ | 
| 287 | typedef int (*curl_multi_timer_callback)(CURLM *multi,    /* multi handle */ | 
| 288 |                                          long timeout_ms, /* see above */ | 
| 289 |                                          void *userp);    /* private callback | 
| 290 |                                                              pointer */ | 
| 291 |  | 
| 292 | CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s, | 
| 293 |                                         int *running_handles); | 
| 294 |  | 
| 295 | CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle, | 
| 296 |                                                curl_socket_t s, | 
| 297 |                                                int ev_bitmask, | 
| 298 |                                                int *running_handles); | 
| 299 |  | 
| 300 | CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle, | 
| 301 |                                             int *running_handles); | 
| 302 |  | 
| 303 | #ifndef CURL_ALLOW_OLD_MULTI_SOCKET | 
| 304 | /* This macro below was added in 7.16.3 to push users who recompile to use | 
| 305 |    the new curl_multi_socket_action() instead of the old curl_multi_socket() | 
| 306 | */ | 
| 307 | #define curl_multi_socket(x,y,z) curl_multi_socket_action(x,y,0,z) | 
| 308 | #endif | 
| 309 |  | 
| 310 | /* | 
| 311 |  * Name:    curl_multi_timeout() | 
| 312 |  * | 
| 313 |  * Desc:    Returns the maximum number of milliseconds the app is allowed to | 
| 314 |  *          wait before curl_multi_socket() or curl_multi_perform() must be | 
| 315 |  *          called (to allow libcurl's timed events to take place). | 
| 316 |  * | 
| 317 |  * Returns: CURLM error code. | 
| 318 |  */ | 
| 319 | CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle, | 
| 320 |                                          long *milliseconds); | 
| 321 |  | 
| 322 | #undef CINIT /* re-using the same name as in curl.h */ | 
| 323 |  | 
| 324 | #ifdef CURL_ISOCPP | 
| 325 | #define CINIT(name,type,num) CURLMOPT_ ## name = CURLOPTTYPE_ ## type + num | 
| 326 | #else | 
| 327 | /* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ | 
| 328 | #define LONG          CURLOPTTYPE_LONG | 
| 329 | #define OBJECTPOINT   CURLOPTTYPE_OBJECTPOINT | 
| 330 | #define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT | 
| 331 | #define OFF_T         CURLOPTTYPE_OFF_T | 
| 332 | #define CINIT(name,type,number) CURLMOPT_/**/name = type + number | 
| 333 | #endif | 
| 334 |  | 
| 335 | typedef enum { | 
| 336 |   /* This is the socket callback function pointer */ | 
| 337 |   CINIT(SOCKETFUNCTION, FUNCTIONPOINT, 1), | 
| 338 |  | 
| 339 |   /* This is the argument passed to the socket callback */ | 
| 340 |   CINIT(SOCKETDATA, OBJECTPOINT, 2), | 
| 341 |  | 
| 342 |     /* set to 1 to enable pipelining for this multi handle */ | 
| 343 |   CINIT(PIPELINING, LONG, 3), | 
| 344 |  | 
| 345 |    /* This is the timer callback function pointer */ | 
| 346 |   CINIT(TIMERFUNCTION, FUNCTIONPOINT, 4), | 
| 347 |  | 
| 348 |   /* This is the argument passed to the timer callback */ | 
| 349 |   CINIT(TIMERDATA, OBJECTPOINT, 5), | 
| 350 |  | 
| 351 |   /* maximum number of entries in the connection cache */ | 
| 352 |   CINIT(MAXCONNECTS, LONG, 6), | 
| 353 |  | 
| 354 |   /* maximum number of (pipelining) connections to one host */ | 
| 355 |   CINIT(MAX_HOST_CONNECTIONS, LONG, 7), | 
| 356 |  | 
| 357 |   /* maximum number of requests in a pipeline */ | 
| 358 |   CINIT(MAX_PIPELINE_LENGTH, LONG, 8), | 
| 359 |  | 
| 360 |   /* a connection with a content-length longer than this | 
| 361 |      will not be considered for pipelining */ | 
| 362 |   CINIT(CONTENT_LENGTH_PENALTY_SIZE, OFF_T, 9), | 
| 363 |  | 
| 364 |   /* a connection with a chunk length longer than this | 
| 365 |      will not be considered for pipelining */ | 
| 366 |   CINIT(CHUNK_LENGTH_PENALTY_SIZE, OFF_T, 10), | 
| 367 |  | 
| 368 |   /* a list of site names(+port) that are blacklisted from | 
| 369 |      pipelining */ | 
| 370 |   CINIT(PIPELINING_SITE_BL, OBJECTPOINT, 11), | 
| 371 |  | 
| 372 |   /* a list of server types that are blacklisted from | 
| 373 |      pipelining */ | 
| 374 |   CINIT(PIPELINING_SERVER_BL, OBJECTPOINT, 12), | 
| 375 |  | 
| 376 |   /* maximum number of open connections in total */ | 
| 377 |   CINIT(MAX_TOTAL_CONNECTIONS, LONG, 13), | 
| 378 |  | 
| 379 |    /* This is the server push callback function pointer */ | 
| 380 |   CINIT(PUSHFUNCTION, FUNCTIONPOINT, 14), | 
| 381 |  | 
| 382 |   /* This is the argument passed to the server push callback */ | 
| 383 |   CINIT(PUSHDATA, OBJECTPOINT, 15), | 
| 384 |  | 
| 385 |   CURLMOPT_LASTENTRY /* the last unused */ | 
| 386 | } CURLMoption; | 
| 387 |  | 
| 388 |  | 
| 389 | /* | 
| 390 |  * Name:    curl_multi_setopt() | 
| 391 |  * | 
| 392 |  * Desc:    Sets options for the multi handle. | 
| 393 |  * | 
| 394 |  * Returns: CURLM error code. | 
| 395 |  */ | 
| 396 | CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle, | 
| 397 |                                         CURLMoption option, ...); | 
| 398 |  | 
| 399 |  | 
| 400 | /* | 
| 401 |  * Name:    curl_multi_assign() | 
| 402 |  * | 
| 403 |  * Desc:    This function sets an association in the multi handle between the | 
| 404 |  *          given socket and a private pointer of the application. This is | 
| 405 |  *          (only) useful for curl_multi_socket uses. | 
| 406 |  * | 
| 407 |  * Returns: CURLM error code. | 
| 408 |  */ | 
| 409 | CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle, | 
| 410 |                                         curl_socket_t sockfd, void *sockp); | 
| 411 |  | 
| 412 |  | 
| 413 | /* | 
| 414 |  * Name: curl_push_callback | 
| 415 |  * | 
| 416 |  * Desc: This callback gets called when a new stream is being pushed by the | 
| 417 |  *       server. It approves or denies the new stream. | 
| 418 |  * | 
| 419 |  * Returns: CURL_PUSH_OK or CURL_PUSH_DENY. | 
| 420 |  */ | 
| 421 | #define CURL_PUSH_OK   0 | 
| 422 | #define CURL_PUSH_DENY 1 | 
| 423 |  | 
| 424 | struct ;  /* forward declaration only */ | 
| 425 |  | 
| 426 | CURL_EXTERN char *(struct curl_pushheaders *h, | 
| 427 |                                         size_t num); | 
| 428 | CURL_EXTERN char *(struct curl_pushheaders *h, | 
| 429 |                                          const char *name); | 
| 430 |  | 
| 431 | typedef int (*curl_push_callback)(CURL *parent, | 
| 432 |                                   CURL *easy, | 
| 433 |                                   size_t , | 
| 434 |                                   struct curl_pushheaders *, | 
| 435 |                                   void *userp); | 
| 436 |  | 
| 437 | #ifdef __cplusplus | 
| 438 | } /* end of extern "C" */ | 
| 439 | #endif | 
| 440 |  | 
| 441 | #endif | 
| 442 |  |