Lines Matching defs:multi
78 /* On a debug build, we want to fail hard on multi handles that
89 static CURLMcode singlesocket(struct Curl_multi *multi,
92 struct Curl_multi *multi,
94 static CURLMcode multi_timeout(struct Curl_multi *multi,
96 static void process_pending_handles(struct Curl_multi *multi);
190 DEBUGASSERT(data->multi->num_alive > 0);
191 data->multi->num_alive--;
368 * the list kept in the multi handle.
370 static void multi_addmsg(struct Curl_multi *multi, struct Curl_message *msg)
372 Curl_llist_insert_next(&multi->msglist, multi->msglist.tail, msg,
380 struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
382 if(!multi)
385 multi->magic = CURL_MULTI_HANDLE;
387 Curl_init_dnscache(&multi->hostcache, dnssize);
389 sh_init(&multi->sockhash, hashsize);
391 if(Curl_conncache_init(&multi->conn_cache, chashsize))
394 Curl_llist_init(&multi->msglist, NULL);
395 Curl_llist_init(&multi->pending, NULL);
396 Curl_llist_init(&multi->msgsent, NULL);
398 multi->multiplexing = TRUE;
399 multi->max_concurrent_streams = 100;
402 multi->wsa_event = WSACreateEvent();
403 if(multi->wsa_event == WSA_INVALID_EVENT)
407 if(wakeup_create(multi->wakeup_pair) < 0) {
408 multi->wakeup_pair[0] = CURL_SOCKET_BAD;
409 multi->wakeup_pair[1] = CURL_SOCKET_BAD;
411 else if(curlx_nonblock(multi->wakeup_pair[0], TRUE) < 0 ||
412 curlx_nonblock(multi->wakeup_pair[1], TRUE) < 0) {
413 wakeup_close(multi->wakeup_pair[0]);
414 wakeup_close(multi->wakeup_pair[1]);
415 multi->wakeup_pair[0] = CURL_SOCKET_BAD;
416 multi->wakeup_pair[1] = CURL_SOCKET_BAD;
421 return multi;
425 sockhash_destroy(&multi->sockhash);
426 Curl_hash_destroy(&multi->hostcache);
427 Curl_conncache_destroy(&multi->conn_cache);
428 free(multi);
440 static void multi_warn_debug(struct Curl_multi *multi, struct Curl_easy *data)
442 if(!multi->warned) {
446 multi->warned = true;
461 static void link_easy(struct Curl_multi *multi,
466 if(multi->easyp) {
467 struct Curl_easy *last = multi->easylp;
470 multi->easylp = data; /* the new last node */
475 multi->easylp = multi->easyp = data; /* both first and last */
480 static void unlink_easy(struct Curl_multi *multi,
487 multi->easyp = data->next; /* point to first node */
493 multi->easylp = data->prev; /* point to last node */
499 CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
504 if(!GOOD_MULTI_HANDLE(multi))
512 adding to more than one multi stack */
513 if(data->multi)
516 if(multi->in_callback)
519 if(multi->dead) {
523 if(multi->num_alive)
525 multi->dead = FALSE;
533 * modification of easy nor multi handle allowed before this except for
534 * potential multi's connection cache growing which won't be undone in this
540 /* make the Curl_easy refer back to this multi handle - before Curl_expire()
542 data->multi = multi;
562 memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
564 rc = Curl_update_timer(multi);
571 /* for multi interface connections, we share DNS cache automatically if the
575 data->dns.hostcache = &multi->hostcache;
579 /* Point to the shared or multi handle connection cache */
583 data->state.conn_cache = &multi->conn_cache;
591 data->psl = &multi->psl;
594 link_easy(multi, data);
597 multi->num_easy++;
600 multi->num_alive++;
617 multi_warn_debug(multi, data);
625 * Curl_hash_print(&multi->sockhash, debug_print_sock_hash);
697 process_pending_handles(data->multi); /* connection / multiplex */
806 CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
815 if(!GOOD_MULTI_HANDLE(multi))
823 if(!data->multi)
826 /* Prevent users from trying to remove an easy handle from the wrong multi */
827 if(data->multi != multi)
830 if(multi->in_callback)
840 multi->num_alive--;
860 /* The timer must be shut down before data->multi is set to NULL, else the
869 Curl_llist_remove(&multi->pending, &data->connect_queue, NULL);
871 Curl_llist_remove(&multi->msgsent, &data->connect_queue, NULL);
874 unlink_easy(multi, data);
877 /* stop using the multi handle's DNS cache, *after* the possible
891 (void)singlesocket(multi, easy); /* to let the application know what sockets
898 /* This removes a handle that was part the multi interface that used
902 anymore once removed from the multi handle
923 if(data->psl == &multi->psl)
928 since we're not part of that multi handle anymore */
931 data->multi = NULL; /* clear the association to this multi handle */
935 for(e = multi->msglist.head; e; e = e->next) {
939 Curl_llist_remove(&multi->msglist, e, NULL);
947 multi->num_easy--; /* one less to care about now */
949 process_pending_handles(multi);
951 rc = Curl_update_timer(multi);
958 bool Curl_multiplex_wanted(const struct Curl_multi *multi)
960 return (multi && (multi->multiplexing));
1149 failf(data, "multi_getsock: unexpected multi state %d", data->mstate);
1155 CURLMcode curl_multi_fdset(struct Curl_multi *multi,
1168 if(!GOOD_MULTI_HANDLE(multi))
1171 if(multi->in_callback)
1175 for(data = multi->easyp; data; data = data->next) {
1214 static CURLMcode multi_wait(struct Curl_multi *multi,
1234 DEBUGASSERT(multi->wsa_event != WSA_INVALID_EVENT);
1240 if(!GOOD_MULTI_HANDLE(multi))
1243 if(multi->in_callback)
1249 /* Count up how many fds we have from the multi handle */
1251 for(data = multi->easyp; data; data = data->next) {
1259 (void)multi_timeout(multi, &timeout_internal);
1270 if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
1293 for(data = multi->easyp; data; data = data->next) {
1317 if(WSAEventSelect(ps.sockets[i], multi->wsa_event, mask) != 0) {
1339 if(WSAEventSelect(extra_fds[i].fd, multi->wsa_event, mask) != 0) {
1358 if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
1359 ufds[nfds].fd = multi->wakeup_pair[0];
1388 WSAWaitForMultipleEvents(1, &multi->wsa_event, FALSE, timeout_ms, FALSE);
1413 WSAEventSelect(s, multi->wsa_event, 0);
1433 for(data = multi->easyp; data; data = data->next) {
1443 WSAEventSelect(ps.sockets[i], multi->wsa_event, 0);
1448 WSAResetEvent(multi->wsa_event);
1451 if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
1460 nread = wakeup_read(multi->wakeup_pair[0], buf, sizeof(buf));
1488 if(!curl_multi_timeout(multi, &sleep_ms) && sleep_ms) {
1491 /* when there are no easy handles in the multi, this holds a -1
1502 CURLMcode curl_multi_wait(struct Curl_multi *multi,
1508 return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, FALSE,
1512 CURLMcode curl_multi_poll(struct Curl_multi *multi,
1518 return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, TRUE,
1522 CURLMcode curl_multi_wakeup(struct Curl_multi *multi)
1529 if(!GOOD_MULTI_HANDLE(multi))
1534 if(WSASetEvent(multi->wsa_event))
1540 if(multi->wakeup_pair[1] != CURL_SOCKET_BAD) {
1553 if(wakeup_write(multi->wakeup_pair[1], buf, sizeof(buf)) < 0) {
1582 static bool multi_ischanged(struct Curl_multi *multi, bool clear)
1584 bool retval = multi->recheckstate;
1586 multi->recheckstate = FALSE;
1592 * this multi handle that has changed state (multiplexing become possible, the
1594 * multi handle should move CONNECT_PEND handles back to CONNECT to have them
1597 void Curl_multi_connchanged(struct Curl_multi *multi)
1599 multi->recheckstate = TRUE;
1602 CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
1608 if(multi->in_callback)
1611 rc = curl_multi_add_handle(multi, data);
1642 * multi_do_more() is called during the DO_MORE multi state. It is basically a
1717 * over from the multi interface until the connection phase is done on
1737 * We are DOING this is being called over and over from the multi interface
1806 * POST/PUT with multi-pass authentication when a sending was denied and a
1903 static void set_in_callback(struct Curl_multi *multi, bool value)
1905 multi->in_callback = value;
1908 static CURLMcode multi_runsingle(struct Curl_multi *multi,
1927 if(multi->dead) {
1928 /* a multi-level callback returned error before, meaning every individual
1936 multi_warn_debug(multi, data);
1944 if(multi_ischanged(multi, TRUE)) {
1945 DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue"));
1946 process_pending_handles(multi); /* multiplexed */
2009 Curl_llist_insert_next(&multi->pending, multi->pending.tail, data,
2012 unlink_easy(multi, data);
2019 process_pending_handles(data->multi);
2081 rc = singlesocket(multi, data);
2384 process_pending_handles(multi); /* multiplexed */
2611 process_pending_handles(multi); /* multiplexing */
2653 !multi_ischanged(multi, false)) {
2676 process_pending_handles(multi); /* connection */
2731 multi_addmsg(multi, msg);
2737 Curl_llist_insert_next(&multi->msgsent, multi->msgsent.tail, data,
2740 unlink_easy(multi, data);
2743 } while((rc == CURLM_CALL_MULTI_PERFORM) || multi_ischanged(multi, FALSE));
2750 CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles)
2757 if(!GOOD_MULTI_HANDLE(multi))
2760 if(multi->in_callback)
2763 data = multi->easyp;
2780 result = multi_runsingle(multi, &now, data);
2799 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
2802 (void)add_next_timeout(now, multi, t->payload);
2806 *running_handles = multi->num_alive;
2809 returncode = Curl_update_timer(multi);
2815 multi handle */
2816 static void unlink_all_msgsent_handles(struct Curl_multi *multi)
2818 struct Curl_llist_element *e = multi->msgsent.head;
2822 data->multi = NULL;
2826 CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
2831 if(GOOD_MULTI_HANDLE(multi)) {
2832 if(multi->in_callback)
2835 multi->magic = 0; /* not good anymore */
2837 unlink_all_msgsent_handles(multi);
2838 process_pending_handles(multi);
2840 data = multi->easyp;
2855 data->multi = NULL; /* clear the association */
2858 if(data->psl == &multi->psl)
2866 Curl_conncache_close_all_connections(&multi->conn_cache);
2868 sockhash_destroy(&multi->sockhash);
2869 Curl_conncache_destroy(&multi->conn_cache);
2870 Curl_hash_destroy(&multi->hostcache);
2871 Curl_psl_destroy(&multi->psl);
2874 WSACloseEvent(multi->wsa_event);
2877 wakeup_close(multi->wakeup_pair[0]);
2878 wakeup_close(multi->wakeup_pair[1]);
2883 Curl_free_multi_ssl_backend_data(multi->ssl_backend_data);
2886 free(multi);
2896 * This function is the primary way for a multi/multi_socket application to
2903 CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue)
2909 if(GOOD_MULTI_HANDLE(multi) &&
2910 !multi->in_callback &&
2911 Curl_llist_count(&multi->msglist)) {
2916 e = multi->msglist.head;
2921 Curl_llist_remove(&multi->msglist, e, NULL);
2923 *msgs_in_queue = curlx_uztosi(Curl_llist_count(&multi->msglist));
2935 static CURLMcode singlesocket(struct Curl_multi *multi,
2961 entry = sh_getentry(&multi->sockhash, s);
2974 entry = sh_addentry(&multi->sockhash, s);
3014 if(multi->socket_cb) {
3015 set_in_callback(multi, TRUE);
3016 rc = multi->socket_cb(data, s, comboaction, multi->socket_userp,
3019 set_in_callback(multi, FALSE);
3021 multi->dead = TRUE;
3030 * Need to remove the easy handle from the multi->sockhash->transfers and
3031 * remove multi->sockhash entry when this was the last transfer */
3046 entry = sh_getentry(&multi->sockhash, s);
3058 if(multi->socket_cb) {
3059 set_in_callback(multi, TRUE);
3060 rc = multi->socket_cb(data, s, CURL_POLL_REMOVE,
3061 multi->socket_userp, entry->socketp);
3062 set_in_callback(multi, FALSE);
3064 multi->dead = TRUE;
3068 sh_delentry(entry, &multi->sockhash, s);
3087 if(singlesocket(data->multi, data))
3107 struct Curl_multi *multi = data->multi;
3108 if(multi) {
3110 a multi handle, and only then this is necessary */
3111 struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
3115 if(multi->socket_cb) {
3116 set_in_callback(multi, TRUE);
3117 rc = multi->socket_cb(data, s, CURL_POLL_REMOVE,
3118 multi->socket_userp, entry->socketp);
3119 set_in_callback(multi, FALSE);
3123 sh_delentry(entry, &multi->sockhash, s);
3125 /* This just marks the multi handle as "dead" without returning an
3128 multi->dead = TRUE;
3147 struct Curl_multi *multi,
3184 multi->timetree = Curl_splayinsert(*tv, multi->timetree,
3190 static CURLMcode multi_socket(struct Curl_multi *multi,
3206 result = curl_multi_perform(multi, running_handles);
3211 data = multi->easyp;
3213 result = singlesocket(multi, data);
3222 struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
3266 memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
3287 result = multi_runsingle(multi, &now, data);
3292 result = singlesocket(multi, data);
3301 multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
3304 (void)add_next_timeout(now, multi, t->payload);
3311 *running_handles = multi->num_alive;
3316 CURLMcode curl_multi_setopt(struct Curl_multi *multi,
3323 if(!GOOD_MULTI_HANDLE(multi))
3326 if(multi->in_callback)
3333 multi->socket_cb = va_arg(param, curl_socket_callback);
3336 multi->socket_userp = va_arg(param, void *);
3339 multi->push_cb = va_arg(param, curl_push_callback);
3342 multi->push_userp = va_arg(param, void *);
3345 multi->multiplexing = va_arg(param, long) & CURLPIPE_MULTIPLEX ? 1 : 0;
3348 multi->timer_cb = va_arg(param, curl_multi_timer_callback);
3351 multi->timer_userp = va_arg(param, void *);
3356 multi->maxconnects = (unsigned int)uarg;
3359 multi->max_host_connections = va_arg(param, long);
3362 multi->max_total_connections = va_arg(param, long);
3380 multi->max_concurrent_streams = (unsigned int)streams;
3391 /* we define curl_multi_socket() in the public multi.h header */
3394 CURLMcode curl_multi_socket(struct Curl_multi *multi, curl_socket_t s,
3398 if(multi->in_callback)
3400 result = multi_socket(multi, FALSE, s, 0, running_handles);
3402 result = Curl_update_timer(multi);
3406 CURLMcode curl_multi_socket_action(struct Curl_multi *multi, curl_socket_t s,
3410 if(multi->in_callback)
3412 result = multi_socket(multi, FALSE, s, ev_bitmask, running_handles);
3414 result = Curl_update_timer(multi);
3418 CURLMcode curl_multi_socket_all(struct Curl_multi *multi, int *running_handles)
3421 if(multi->in_callback)
3423 result = multi_socket(multi, TRUE, CURL_SOCKET_BAD, 0, running_handles);
3425 result = Curl_update_timer(multi);
3429 static CURLMcode multi_timeout(struct Curl_multi *multi,
3434 if(multi->dead) {
3439 if(multi->timetree) {
3444 multi->timetree = Curl_splay(tv_zero, multi->timetree);
3446 if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
3448 timediff_t diff = Curl_timediff_ceil(multi->timetree->key, now);
3463 CURLMcode curl_multi_timeout(struct Curl_multi *multi,
3467 if(!GOOD_MULTI_HANDLE(multi))
3470 if(multi->in_callback)
3473 return multi_timeout(multi, timeout_ms);
3480 CURLMcode Curl_update_timer(struct Curl_multi *multi)
3485 if(!multi->timer_cb || multi->dead)
3487 if(multi_timeout(multi, &timeout_ms)) {
3492 if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
3493 multi->timer_lastcall = none;
3496 set_in_callback(multi, TRUE);
3497 rc = multi->timer_cb(multi, -1, multi->timer_userp);
3498 set_in_callback(multi, FALSE);
3500 multi->dead = TRUE;
3508 /* When multi_timeout() is done, multi->timetree points to the node with the
3512 if(Curl_splaycomparekeys(multi->timetree->key, multi->timer_lastcall) == 0)
3515 multi->timer_lastcall = multi->timetree->key;
3517 set_in_callback(multi, TRUE);
3518 rc = multi->timer_cb(multi, timeout_ms, multi->timer_userp);
3519 set_in_callback(multi, FALSE);
3521 multi->dead = TRUE;
3603 struct Curl_multi *multi = data->multi;
3607 /* this is only interesting while there is still an associated multi struct
3609 if(!multi)
3645 rc = Curl_splayremove(multi->timetree, &data->state.timenode,
3646 &multi->timetree);
3655 multi->timetree = Curl_splayinsert(*nowp, multi->timetree,
3678 struct Curl_multi *multi = data->multi;
3681 /* this is only interesting while there is still an associated multi struct
3683 if(!multi)
3692 rc = Curl_splayremove(multi->timetree, &data->state.timenode,
3693 &multi->timetree);
3713 CURLMcode curl_multi_assign(struct Curl_multi *multi, curl_socket_t s,
3718 there = sh_getentry(&multi->sockhash, s);
3728 size_t Curl_multi_max_host_connections(struct Curl_multi *multi)
3730 return multi ? multi->max_host_connections : 0;
3733 size_t Curl_multi_max_total_connections(struct Curl_multi *multi)
3735 return multi ? multi->max_total_connections : 0;
3747 DEBUGASSERT(data->multi);
3753 process_pending_handles(data->multi);
3758 static void process_pending_handles(struct Curl_multi *multi)
3760 struct Curl_llist_element *e = multi->pending.head;
3767 link_easy(multi, data);
3772 Curl_llist_remove(&multi->pending, e, NULL);
3788 else if(data->multi)
3789 data->multi->in_callback = value;
3795 return ((easy->multi && easy->multi->in_callback) ||
3799 unsigned int Curl_multi_max_concurrent_streams(struct Curl_multi *multi)
3801 DEBUGASSERT(multi);
3802 return multi->max_concurrent_streams;
3805 struct Curl_easy **curl_multi_get_handles(struct Curl_multi *multi)
3808 (multi->num_easy + 1));
3811 struct Curl_easy *e = multi->easyp;
3813 DEBUGASSERT(i < multi->num_easy);