summaryrefslogtreecommitdiff
path: root/lib/multi.c
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2019-04-05 16:38:36 +0200
committerDaniel Stenberg <daniel@haxx.se>2019-04-06 22:49:50 +0200
commit2f44e94efb3df8e50bb2ddbc4ec6b569a6424517 (patch)
tree14ddd0b5294633dd446fcff08218b2f53fc13cfd /lib/multi.c
parentaba1c515534197cab1588ab0f3a2343be1f0a8e5 (diff)
downloadcurl-2f44e94efb3df8e50bb2ddbc4ec6b569a6424517.tar.gz
pipelining: removed
As previously planned and documented in DEPRECATE.md, all pipelining code is removed. Closes #3651
Diffstat (limited to 'lib/multi.c')
-rw-r--r--lib/multi.c228
1 files changed, 58 insertions, 170 deletions
diff --git a/lib/multi.c b/lib/multi.c
index 22d79b5d2..ed30e2f41 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -41,7 +41,6 @@
#include "speedcheck.h"
#include "conncache.h"
#include "multihandle.h"
-#include "pipeline.h"
#include "sigpipe.h"
#include "vtls/vtls.h"
#include "connect.h"
@@ -136,12 +135,10 @@ static void mstate(struct Curl_easy *data, CURLMstate state
NULL, /* WAITPROXYCONNECT */
NULL, /* SENDPROTOCONNECT */
NULL, /* PROTOCONNECT */
- NULL, /* WAITDO */
Curl_connect_free, /* DO */
NULL, /* DOING */
NULL, /* DO_MORE */
NULL, /* DO_DONE */
- NULL, /* WAITPERFORM */
NULL, /* PERFORM */
NULL, /* TOOFAST */
NULL, /* DONE */
@@ -349,9 +346,6 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
Curl_llist_init(&multi->msglist, multi_freeamsg);
Curl_llist_init(&multi->pending, multi_freeamsg);
- multi->max_pipeline_length = 5;
- multi->pipelining = CURLPIPE_MULTIPLEX;
-
/* -1 means it not set by user, use the default value */
multi->maxconnects = -1;
return multi;
@@ -440,12 +434,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
data->psl = &multi->psl;
#endif
- /* This adds the new entry at the 'end' of the doubly-linked circular
- list of Curl_easy structs to try and maintain a FIFO queue so
- the pipelined requests are in order. */
-
- /* We add this new entry last in the list. */
-
+ /* We add the new entry last in the list. */
data->next = NULL; /* end of the line */
if(multi->easyp) {
struct Curl_easy *last = multi->easylp;
@@ -538,8 +527,6 @@ static CURLcode multi_done(struct Curl_easy *data,
/* Stop the resolver and free its own resources (but not dns_entry yet). */
Curl_resolver_kill(conn);
- Curl_getoff_all_pipelines(data, conn);
-
/* Cleanup possible redirect junk */
Curl_safefree(data->req.newurl);
Curl_safefree(data->req.location);
@@ -573,12 +560,12 @@ static CURLcode multi_done(struct Curl_easy *data,
process_pending_handles(data->multi); /* connection / multiplex */
- if(conn->send_pipe.size || conn->recv_pipe.size) {
- /* Stop if pipeline is not empty . */
- detach_connnection(data);
- DEBUGF(infof(data, "Connection still in use %zu/%zu, "
+ detach_connnection(data);
+ if(CONN_INUSE(conn)) {
+ /* Stop if still used. */
+ DEBUGF(infof(data, "Connection still in use %zu, "
"no more multi_done now!\n",
- conn->send_pipe.size, conn->recv_pipe.size));
+ conn->easyq.size));
return CURLE_OK;
}
@@ -652,7 +639,6 @@ static CURLcode multi_done(struct Curl_easy *data,
data->state.lastconnect = NULL;
}
- detach_connnection(data);
Curl_free_request_state(data);
return result;
}
@@ -698,9 +684,6 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
/* Set connection owner so that the DONE function closes it. We can
safely do this here since connection is killed. */
data->conn->data = easy;
- /* If the handle is in a pipeline and has started sending off its
- request but not received its response yet, we need to close
- connection. */
streamclose(data->conn, "Removed with partial response");
easy_owns_conn = TRUE;
}
@@ -723,9 +706,6 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
nothing really useful to do with it anyway! */
(void)multi_done(data, data->result, premature);
}
- else
- /* Clear connection pipelines, if multi_done above was not called */
- Curl_getoff_all_pipelines(data, data->conn);
}
if(data->connect_queue.ptr)
@@ -803,16 +783,19 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
return CURLM_OK;
}
-/* Return TRUE if the application asked for a certain set of pipelining */
-bool Curl_pipeline_wanted(const struct Curl_multi *multi, int bits)
+/* Return TRUE if the application asked for multiplexing */
+bool Curl_multiplex_wanted(const struct Curl_multi *multi)
{
- return (multi && (multi->pipelining & bits)) ? TRUE : FALSE;
+ return (multi && (multi->multiplexing));
}
/* This is the only function that should clear data->conn. This will
occasionally be called with the pointer already cleared. */
static void detach_connnection(struct Curl_easy *data)
{
+ struct connectdata *conn = data->conn;
+ if(conn)
+ Curl_llist_remove(&conn->easyq, &data->conn_queue, NULL);
data->conn = NULL;
}
@@ -821,7 +804,10 @@ void Curl_attach_connnection(struct Curl_easy *data,
struct connectdata *conn)
{
DEBUGASSERT(!data->conn);
+ DEBUGASSERT(conn);
data->conn = conn;
+ Curl_llist_insert_next(&conn->easyq, conn->easyq.tail, data,
+ &data->conn_queue);
}
static int waitconnect_getsock(struct connectdata *conn,
@@ -935,7 +921,6 @@ static int multi_getsock(struct Curl_easy *data,
to waiting for the same as the *PERFORM
states */
case CURLM_STATE_PERFORM:
- case CURLM_STATE_WAITPERFORM:
return Curl_single_getsock(data->conn, socks, numsocks);
}
@@ -1203,7 +1188,7 @@ CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
* do_complete is called when the DO actions are complete.
*
* We init chunking and trailer bits to their default values here immediately
- * before receiving any header data for the current request in the pipeline.
+ * before receiving any header data for the current request.
*/
static void do_complete(struct connectdata *conn)
{
@@ -1216,6 +1201,9 @@ static CURLcode multi_do(struct Curl_easy *data, bool *done)
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
+ DEBUGASSERT(conn);
+ DEBUGASSERT(conn->handler);
+
if(conn->handler->do_it) {
/* generic protocol-specific function pointer set in curl_connect() */
result = conn->handler->do_it(conn, done);
@@ -1266,7 +1254,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
bool done = FALSE;
CURLMcode rc;
CURLcode result = CURLE_OK;
- struct SingleRequest *k;
timediff_t timeout_ms;
timediff_t recv_timeout_ms;
timediff_t send_timeout_ms;
@@ -1293,7 +1280,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(multi_ischanged(multi, TRUE)) {
DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue!\n"));
- process_pending_handles(multi); /* pipelined/multiplexed */
+ process_pending_handles(multi); /* multiplexed */
}
if(data->conn && data->mstate > CURLM_STATE_CONNECT &&
@@ -1308,7 +1295,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* we need to wait for the connect state as only then is the start time
stored, but we must not check already completed handles */
timeout_ms = Curl_timeleft(data, &now,
- (data->mstate <= CURLM_STATE_WAITDO)?
+ (data->mstate <= CURLM_STATE_DO)?
TRUE:FALSE);
if(timeout_ms < 0) {
@@ -1322,7 +1309,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
" milliseconds",
Curl_timediff(now, data->progress.t_startsingle));
else {
- k = &data->req;
+ struct SingleRequest *k = &data->req;
if(k->size != -1) {
failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
" milliseconds with %" CURL_FORMAT_CURL_OFF_T " out of %"
@@ -1392,31 +1379,24 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
if(!result) {
- /* Add this handle to the send or pend pipeline */
- result = Curl_add_handle_to_pipeline(data, data->conn);
- if(result)
- stream_error = TRUE;
+ if(async)
+ /* We're now waiting for an asynchronous name lookup */
+ multistate(data, CURLM_STATE_WAITRESOLVE);
else {
- if(async)
- /* We're now waiting for an asynchronous name lookup */
- multistate(data, CURLM_STATE_WAITRESOLVE);
- else {
- /* after the connect has been sent off, go WAITCONNECT unless the
- protocol connect is already done and we can go directly to
- WAITDO or DO! */
- rc = CURLM_CALL_MULTI_PERFORM;
+ /* after the connect has been sent off, go WAITCONNECT unless the
+ protocol connect is already done and we can go directly to
+ WAITDO or DO! */
+ rc = CURLM_CALL_MULTI_PERFORM;
- if(protocol_connect)
- multistate(data, Curl_pipeline_wanted(multi, CURLPIPE_HTTP1)?
- CURLM_STATE_WAITDO:CURLM_STATE_DO);
- else {
+ if(protocol_connect)
+ multistate(data, CURLM_STATE_DO);
+ else {
#ifndef CURL_DISABLE_HTTP
- if(Curl_connect_ongoing(data->conn))
- multistate(data, CURLM_STATE_WAITPROXYCONNECT);
- else
+ if(Curl_connect_ongoing(data->conn))
+ multistate(data, CURLM_STATE_WAITPROXYCONNECT);
+ else
#endif
- multistate(data, CURLM_STATE_WAITCONNECT);
- }
+ multistate(data, CURLM_STATE_WAITCONNECT);
}
}
}
@@ -1429,6 +1409,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
struct connectdata *conn = data->conn;
const char *hostname;
+ DEBUGASSERT(conn);
if(conn->bits.httpproxy)
hostname = conn->http_proxy.host.name;
else if(conn->bits.conn_to_host)
@@ -1472,8 +1453,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* call again please so that we get the next socket setup */
rc = CURLM_CALL_MULTI_PERFORM;
if(protocol_connect)
- multistate(data, Curl_pipeline_wanted(multi, CURLPIPE_HTTP1)?
- CURLM_STATE_WAITDO:CURLM_STATE_DO);
+ multistate(data, CURLM_STATE_DO);
else {
#ifndef CURL_DISABLE_HTTP
if(Curl_connect_ongoing(data->conn))
@@ -1496,6 +1476,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
#ifndef CURL_DISABLE_HTTP
case CURLM_STATE_WAITPROXYCONNECT:
/* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
+ DEBUGASSERT(data->conn);
result = Curl_http_connect(data->conn, &protocol_connect);
if(data->conn->bits.proxy_connect_closed) {
@@ -1521,6 +1502,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
case CURLM_STATE_WAITCONNECT:
/* awaiting a completion of an asynch TCP connect */
+ DEBUGASSERT(data->conn);
result = Curl_is_connected(data->conn, FIRSTSOCKET, &connected);
if(connected && !result) {
#ifndef CURL_DISABLE_HTTP
@@ -1552,8 +1534,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
multistate(data, CURLM_STATE_PROTOCONNECT);
else if(!result) {
/* protocol connect has completed, go WAITDO or DO */
- multistate(data, Curl_pipeline_wanted(multi, CURLPIPE_HTTP1)?
- CURLM_STATE_WAITDO:CURLM_STATE_DO);
+ multistate(data, CURLM_STATE_DO);
rc = CURLM_CALL_MULTI_PERFORM;
}
else if(result) {
@@ -1569,8 +1550,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
result = Curl_protocol_connecting(data->conn, &protocol_connect);
if(!result && protocol_connect) {
/* after the connect has completed, go WAITDO or DO */
- multistate(data, Curl_pipeline_wanted(multi, CURLPIPE_HTTP1)?
- CURLM_STATE_WAITDO:CURLM_STATE_DO);
+ multistate(data, CURLM_STATE_DO);
rc = CURLM_CALL_MULTI_PERFORM;
}
else if(result) {
@@ -1581,15 +1561,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
break;
- case CURLM_STATE_WAITDO:
- /* Wait for our turn to DO when we're pipelining requests */
- if(Curl_pipeline_checkget_write(data, data->conn)) {
- /* Grabbed the channel */
- multistate(data, CURLM_STATE_DO);
- rc = CURLM_CALL_MULTI_PERFORM;
- }
- break;
-
case CURLM_STATE_DO:
if(data->set.connect_only) {
/* keep connection open for application to use the socket */
@@ -1696,6 +1667,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
case CURLM_STATE_DOING:
/* we continue DOING until the DO phase is complete */
+ DEBUGASSERT(data->conn);
result = Curl_protocol_doing(data->conn,
&dophase_done);
if(!result) {
@@ -1719,10 +1691,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/*
* When we are connected, DO MORE and then go DO_DONE
*/
+ DEBUGASSERT(data->conn);
result = multi_do_more(data->conn, &control);
- /* No need to remove this handle from the send pipeline here since that
- is done in multi_done() */
if(!result) {
if(control) {
/* if positive, advance to DO_DONE
@@ -1745,38 +1716,28 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
break;
case CURLM_STATE_DO_DONE:
- /* Move ourselves from the send to recv pipeline */
- Curl_move_handle_from_send_to_recv_pipe(data, data->conn);
-
- if(data->conn->bits.multiplex || data->conn->send_pipe.size)
+ DEBUGASSERT(data->conn);
+ if(data->conn->bits.multiplex)
/* Check if we can move pending requests to send pipe */
- process_pending_handles(multi); /* pipelined/multiplexed */
+ process_pending_handles(multi); /* multiplexed */
/* Only perform the transfer if there's a good socket to work with.
Having both BAD is a signal to skip immediately to DONE */
if((data->conn->sockfd != CURL_SOCKET_BAD) ||
(data->conn->writesockfd != CURL_SOCKET_BAD))
- multistate(data, CURLM_STATE_WAITPERFORM);
+ multistate(data, CURLM_STATE_PERFORM);
else {
if(data->state.wildcardmatch &&
((data->conn->handler->flags & PROTOPT_WILDCARD) == 0)) {
- data->wildcard.state = CURLWC_DONE;
+ data->wildcard.state = CURLWC_DONE;
}
multistate(data, CURLM_STATE_DONE);
}
rc = CURLM_CALL_MULTI_PERFORM;
break;
- case CURLM_STATE_WAITPERFORM:
- /* Wait for our turn to PERFORM */
- if(Curl_pipeline_checkget_read(data, data->conn)) {
- /* Grabbed the channel */
- multistate(data, CURLM_STATE_PERFORM);
- rc = CURLM_CALL_MULTI_PERFORM;
- }
- break;
-
case CURLM_STATE_TOOFAST: /* limit-rate exceeded in either direction */
+ DEBUGASSERT(data->conn);
/* if both rates are within spec, resume transfer */
if(Curl_pgrsUpdate(data->conn))
result = CURLE_ABORTED_BY_CALLBACK;
@@ -1850,18 +1811,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* read/write data if it is ready to do so */
result = Curl_readwrite(data->conn, data, &done, &comeback);
- k = &data->req;
-
- if(!(k->keepon & KEEP_RECV)) {
- /* We're done receiving */
- Curl_pipeline_leave_read(data->conn);
- }
-
- if(!(k->keepon & KEEP_SEND)) {
- /* We're done sending */
- Curl_pipeline_leave_write(data->conn);
- }
-
if(done || (result == CURLE_RECV_ERROR)) {
/* If CURLE_RECV_ERROR happens early enough, we assume it was a race
* condition and the server closed the re-used connection exactly when
@@ -1924,13 +1873,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* call this even if the readwrite function returned error */
Curl_posttransfer(data);
- /* we're no longer receiving */
- Curl_removeHandleFromPipeline(data, &data->conn->recv_pipe);
-
- /* expire the new receiving pipeline head */
- if(data->conn->recv_pipe.head)
- Curl_expire(data->conn->recv_pipe.head->ptr, 0, EXPIRE_RUN_NOW);
-
/* When we follow redirects or is set to retry the connection, we must
to go back to the CONNECT state */
if(data->req.newurl || retry) {
@@ -1988,12 +1930,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(data->conn) {
CURLcode res;
- /* Remove ourselves from the receive pipeline, if we are there. */
- Curl_removeHandleFromPipeline(data, &data->conn->recv_pipe);
-
- if(data->conn->bits.multiplex || data->conn->send_pipe.size)
+ if(data->conn->bits.multiplex)
/* Check if we can move pending requests to connection */
- process_pending_handles(multi); /* pipelined/multiplexing */
+ process_pending_handles(multi); /* multiplexing */
/* post-transfer command */
res = multi_done(data, result, FALSE);
@@ -2003,7 +1942,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
result = res;
/*
- * If there are other handles on the pipeline, multi_done won't set
+ * If there are other handles on the connection, multi_done won't set
* conn to NULL. In such a case, curl_multi_remove_handle() can
* access free'd data, if the connection is free'd and the handle
* removed before we perform the processing in CURLM_STATE_COMPLETED
@@ -2052,12 +1991,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
process_pending_handles(multi); /* connection */
if(data->conn) {
- /* if this has a connection, unsubscribe from the pipelines */
- Curl_pipeline_leave_write(data->conn);
- Curl_pipeline_leave_read(data->conn);
- Curl_removeHandleFromPipeline(data, &data->conn->send_pipe);
- Curl_removeHandleFromPipeline(data, &data->conn->recv_pipe);
-
if(stream_error) {
/* Don't attempt to send data over a connection that timed out */
bool dead_connection = result == CURLE_OPERATION_TIMEDOUT;
@@ -2218,12 +2151,6 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
Curl_hash_destroy(&multi->hostcache);
Curl_psl_destroy(&multi->psl);
-
- /* Free the blacklists by setting them to NULL */
- (void)Curl_pipeline_set_site_blacklist(NULL, &multi->pipelining_site_bl);
- (void)Curl_pipeline_set_server_blacklist(NULL,
- &multi->pipelining_server_bl);
-
free(multi);
return CURLM_OK;
@@ -2576,19 +2503,6 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
/* bad bad bad bad bad bad bad */
return CURLM_INTERNAL_ERROR;
- /* If the pipeline is enabled, take the handle which is in the head of
- the pipeline. If we should write into the socket, take the
- send_pipe head. If we should read from the socket, take the
- recv_pipe head. */
- if(data->conn) {
- if((ev_bitmask & CURL_POLL_OUT) &&
- data->conn->send_pipe.head)
- data = data->conn->send_pipe.head->ptr;
- else if((ev_bitmask & CURL_POLL_IN) &&
- data->conn->recv_pipe.head)
- data = data->conn->recv_pipe.head->ptr;
- }
-
if(data->conn && !(data->conn->handler->flags & PROTOPT_DIRLOCK))
/* set socket event bitmask if they're not locked */
data->conn->cselect_bits = ev_bitmask;
@@ -2695,7 +2609,7 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi,
multi->push_userp = va_arg(param, void *);
break;
case CURLMOPT_PIPELINING:
- multi->pipelining = va_arg(param, long) & CURLPIPE_MULTIPLEX;
+ multi->multiplexing = va_arg(param, long) & CURLPIPE_MULTIPLEX;
break;
case CURLMOPT_TIMERFUNCTION:
multi->timer_cb = va_arg(param, curl_multi_timer_callback);
@@ -2709,25 +2623,19 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi,
case CURLMOPT_MAX_HOST_CONNECTIONS:
multi->max_host_connections = va_arg(param, long);
break;
+ case CURLMOPT_MAX_TOTAL_CONNECTIONS:
+ multi->max_total_connections = va_arg(param, long);
+ break;
+ /* options formerly used for pipelining */
case CURLMOPT_MAX_PIPELINE_LENGTH:
- multi->max_pipeline_length = va_arg(param, long);
break;
case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE:
- multi->content_length_penalty_size = va_arg(param, long);
break;
case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE:
- multi->chunk_length_penalty_size = va_arg(param, long);
break;
case CURLMOPT_PIPELINING_SITE_BL:
- res = Curl_pipeline_set_site_blacklist(va_arg(param, char **),
- &multi->pipelining_site_bl);
break;
case CURLMOPT_PIPELINING_SERVER_BL:
- res = Curl_pipeline_set_server_blacklist(va_arg(param, char **),
- &multi->pipelining_server_bl);
- break;
- case CURLMOPT_MAX_TOTAL_CONNECTIONS:
- multi->max_total_connections = va_arg(param, long);
break;
default:
res = CURLM_UNKNOWN_OPTION;
@@ -3080,26 +2988,6 @@ size_t Curl_multi_max_total_connections(struct Curl_multi *multi)
return multi ? multi->max_total_connections : 0;
}
-curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi)
-{
- return multi ? multi->content_length_penalty_size : 0;
-}
-
-curl_off_t Curl_multi_chunk_length_penalty_size(struct Curl_multi *multi)
-{
- return multi ? multi->chunk_length_penalty_size : 0;
-}
-
-struct curl_llist *Curl_multi_pipelining_site_bl(struct Curl_multi *multi)
-{
- return &multi->pipelining_site_bl;
-}
-
-struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi)
-{
- return &multi->pipelining_server_bl;
-}
-
static void process_pending_handles(struct Curl_multi *multi)
{
struct curl_llist_element *e = multi->pending.head;