mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 15:48:49 -05:00
CURLMOPT_PIPELINE: bit 1 is for multiplexing
This commit is contained in:
parent
2ce2f03007
commit
02ec1ced9b
@ -5,7 +5,7 @@
|
||||
.\" * | (__| |_| | _ <| |___
|
||||
.\" * \___|\___/|_| \_\_____|
|
||||
.\" *
|
||||
.\" * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
.\" * Copyright (C) 1998 - 2015, 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
|
||||
@ -26,17 +26,28 @@ CURLMOPT_PIPELINING \- enable/disable HTTP pipelining
|
||||
.SH SYNOPSIS
|
||||
#include <curl/curl.h>
|
||||
|
||||
CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_PIPELINING, bool onoff);
|
||||
CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_PIPELINING, long bits);
|
||||
.SH DESCRIPTION
|
||||
Set the \fBonoff\fP parameter to 1 to make libcurl use HTTP pipelining for
|
||||
HTTP transfers done using this multi handle, as far as possible. This means
|
||||
that if you add a second request that can use an already existing connection,
|
||||
the second request will be \&"piped" on the same connection rather than being
|
||||
executed in parallel.
|
||||
Set the \fBbits\fP parameter to 1 to make libcurl use HTTP pipelining for
|
||||
HTTP/1.1 transfers done using this multi handle, as far as possible. This
|
||||
means that if you add a second request that can use an already existing
|
||||
connection, the second request will be \&"piped" on the same connection rather
|
||||
than being executed in parallel.
|
||||
|
||||
When using pipelining, there are also several other related options that are
|
||||
interesting to tweak and adjust to alter how libcurl spreads out requests on
|
||||
different connections or not etc.
|
||||
|
||||
Starting in 7.43.0, the \fBbits\fP parameter's bit 1 also has a meaning and
|
||||
libcurl is now offering symbol names for the bits:
|
||||
.IP CURLPIPE_NOTHING (0)
|
||||
Default, which means doing no attempts at pipelining or multiplexing.
|
||||
.IP CURLPIPE_HTTP1 (1)
|
||||
If this bit is set, libcurl will try to pipeline HTTP/1.1 requests on
|
||||
connections that are already established and in use to hosts.
|
||||
.IP CURLPIPE_MULTIPLEX (2)
|
||||
If this bit is set, libcurl will try to multiplex the new transfer over an
|
||||
existing connection if possible. This requires HTTP/2.
|
||||
.SH DEFAULT
|
||||
0 (off)
|
||||
.SH PROTOCOLS
|
||||
@ -44,7 +55,7 @@ HTTP(S)
|
||||
.SH EXAMPLE
|
||||
TODO
|
||||
.SH AVAILABILITY
|
||||
Added in 7.16.0
|
||||
Added in 7.16.0. Multiplex support bit added in 7.43.0.
|
||||
.SH RETURN VALUE
|
||||
Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
|
||||
.SH "SEE ALSO"
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2015, 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
|
||||
@ -74,6 +74,11 @@ typedef enum {
|
||||
curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */
|
||||
#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM
|
||||
|
||||
/* bitmask bits for CURLMOPT_PIPELINING */
|
||||
#define CURLPIPE_NOTHING 0L
|
||||
#define CURLPIPE_HTTP1 1L
|
||||
#define CURLPIPE_MULTIPLEX 2L
|
||||
|
||||
typedef enum {
|
||||
CURLMSG_NONE, /* first, not used */
|
||||
CURLMSG_DONE, /* This easy handle has completed. 'result' contains
|
||||
|
15
lib/multi.c
15
lib/multi.c
@ -613,9 +613,10 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
|
||||
return CURLM_OK;
|
||||
}
|
||||
|
||||
bool Curl_multi_pipeline_enabled(const struct Curl_multi *multi)
|
||||
/* Return TRUE if the application asked for a certain set of pipelining */
|
||||
bool Curl_pipeline_wanted(const struct Curl_multi *multi, int bits)
|
||||
{
|
||||
return (multi && multi->pipelining_enabled) ? TRUE : FALSE;
|
||||
return (multi && (multi->pipelining & bits)) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
void Curl_multi_handlePipeBreak(struct SessionHandle *data)
|
||||
@ -1082,7 +1083,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
rc = CURLM_CALL_MULTI_PERFORM;
|
||||
|
||||
if(protocol_connect)
|
||||
multistate(data, multi->pipelining_enabled?
|
||||
multistate(data, Curl_pipeline_wanted(multi, CURLPIPE_HTTP1)?
|
||||
CURLM_STATE_WAITDO:CURLM_STATE_DO);
|
||||
else {
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
@ -1139,7 +1140,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, multi->pipelining_enabled?
|
||||
multistate(data, Curl_pipeline_wanted(multi, CURLPIPE_HTTP1)?
|
||||
CURLM_STATE_WAITDO:CURLM_STATE_DO);
|
||||
else {
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
@ -1203,7 +1204,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, multi->pipelining_enabled?
|
||||
multistate(data, Curl_pipeline_wanted(multi, CURLPIPE_HTTP1)?
|
||||
CURLM_STATE_WAITDO:CURLM_STATE_DO);
|
||||
rc = CURLM_CALL_MULTI_PERFORM;
|
||||
}
|
||||
@ -1220,7 +1221,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
result = Curl_protocol_connecting(data->easy_conn, &protocol_connect);
|
||||
if(!result && protocol_connect) {
|
||||
/* after the connect has completed, go WAITDO or DO */
|
||||
multistate(data, multi->pipelining_enabled?
|
||||
multistate(data, Curl_pipeline_wanted(multi, CURLPIPE_HTTP1)?
|
||||
CURLM_STATE_WAITDO:CURLM_STATE_DO);
|
||||
rc = CURLM_CALL_MULTI_PERFORM;
|
||||
}
|
||||
@ -2340,7 +2341,7 @@ CURLMcode curl_multi_setopt(CURLM *multi_handle,
|
||||
multi->socket_userp = va_arg(param, void *);
|
||||
break;
|
||||
case CURLMOPT_PIPELINING:
|
||||
multi->pipelining_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE;
|
||||
multi->pipelining = va_arg(param, long);
|
||||
break;
|
||||
case CURLMOPT_TIMERFUNCTION:
|
||||
multi->timer_cb = va_arg(param, curl_multi_timer_callback);
|
||||
|
@ -62,6 +62,8 @@ typedef enum {
|
||||
#define GETSOCK_READABLE (0x00ff)
|
||||
#define GETSOCK_WRITABLE (0xff00)
|
||||
|
||||
#define CURLPIPE_ANY (CURLPIPE_HTTP1 | CURLPIPE_MULTIPLEX)
|
||||
|
||||
/* This is the struct known as CURLM on the outside */
|
||||
struct Curl_multi {
|
||||
/* First a simple identifier to easier detect if a user mix up
|
||||
@ -97,8 +99,8 @@ struct Curl_multi {
|
||||
same actual socket) */
|
||||
struct curl_hash sockhash;
|
||||
|
||||
/* Whether pipelining is enabled for this multi handle */
|
||||
bool pipelining_enabled;
|
||||
/* pipelining wanted bits (CURLPIPE*) */
|
||||
long pipelining;
|
||||
|
||||
/* Shared connection cache (bundles)*/
|
||||
struct conncache conn_cache;
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2015, 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
|
||||
@ -27,8 +27,7 @@
|
||||
*/
|
||||
void Curl_expire(struct SessionHandle *data, long milli);
|
||||
void Curl_expire_latest(struct SessionHandle *data, long milli);
|
||||
|
||||
bool Curl_multi_pipeline_enabled(const struct Curl_multi* multi);
|
||||
bool Curl_pipeline_wanted(const struct Curl_multi* multi, int bits);
|
||||
void Curl_multi_handlePipeBreak(struct SessionHandle *data);
|
||||
|
||||
/* Internal version of curl_multi_init() accepts size parameters for the
|
||||
|
@ -551,8 +551,7 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */
|
||||
ssize_t nread = 0;
|
||||
size_t bytesfromsocket = 0;
|
||||
char *buffertofill = NULL;
|
||||
bool pipelining = Curl_multi_pipeline_enabled(conn->data->multi) &&
|
||||
!conn->bits.multiplex;
|
||||
bool pipelining = Curl_pipeline_wanted(conn->data->multi, CURLPIPE_HTTP1);
|
||||
|
||||
/* Set 'num' to 0 or 1, depending on which socket that has been sent here.
|
||||
If it is the second socket, we set num to 1. Otherwise to 0. This lets
|
||||
|
@ -494,7 +494,7 @@ static CURLcode readwrite_data(struct SessionHandle *data,
|
||||
/* We've stopped dealing with input, get out of the do-while loop */
|
||||
|
||||
if(nread > 0) {
|
||||
if(Curl_multi_pipeline_enabled(conn->data->multi)) {
|
||||
if(Curl_pipeline_wanted(conn->data->multi, CURLPIPE_HTTP1)) {
|
||||
infof(data,
|
||||
"Rewinding stream by : %zd"
|
||||
" bytes on url %s (zero-length body)\n",
|
||||
@ -639,7 +639,7 @@ static CURLcode readwrite_data(struct SessionHandle *data,
|
||||
if(dataleft != 0) {
|
||||
infof(conn->data, "Leftovers after chunking: %zu bytes\n",
|
||||
dataleft);
|
||||
if(Curl_multi_pipeline_enabled(conn->data->multi)) {
|
||||
if(Curl_pipeline_wanted(conn->data->multi, CURLPIPE_HTTP1)) {
|
||||
/* only attempt the rewind if we truly are pipelining */
|
||||
infof(conn->data, "Rewinding %zu bytes\n",dataleft);
|
||||
read_rewind(conn, dataleft);
|
||||
@ -662,7 +662,7 @@ static CURLcode readwrite_data(struct SessionHandle *data,
|
||||
|
||||
excess = (size_t)(k->bytecount + nread - k->maxdownload);
|
||||
if(excess > 0 && !k->ignorebody) {
|
||||
if(Curl_multi_pipeline_enabled(conn->data->multi)) {
|
||||
if(Curl_pipeline_wanted(conn->data->multi, CURLPIPE_HTTP1)) {
|
||||
/* The 'excess' amount below can't be more than BUFSIZE which
|
||||
always will fit in a size_t */
|
||||
infof(data,
|
||||
|
15
lib/url.c
15
lib/url.c
@ -2782,7 +2782,7 @@ CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
|
||||
Curl_ssl_close(conn, FIRSTSOCKET);
|
||||
|
||||
/* Indicate to all handles on the pipe that we're dead */
|
||||
if(Curl_multi_pipeline_enabled(data->multi)) {
|
||||
if(Curl_pipeline_wanted(data->multi, CURLPIPE_ANY)) {
|
||||
signalPipeClose(conn->send_pipe, TRUE);
|
||||
signalPipeClose(conn->recv_pipe, TRUE);
|
||||
}
|
||||
@ -2815,7 +2815,7 @@ static bool IsPipeliningPossible(const struct SessionHandle *handle,
|
||||
{
|
||||
/* If a HTTP protocol and pipelining is enabled */
|
||||
if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
|
||||
Curl_multi_pipeline_enabled(handle->multi)) {
|
||||
Curl_pipeline_wanted(handle->multi, CURLPIPE_ANY)) {
|
||||
|
||||
if((handle->set.httpversion != CURL_HTTP_VERSION_1_0) &&
|
||||
(handle->set.httpreq == HTTPREQ_GET ||
|
||||
@ -2830,11 +2830,6 @@ static bool IsPipeliningPossible(const struct SessionHandle *handle,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool Curl_isPipeliningEnabled(const struct SessionHandle *handle)
|
||||
{
|
||||
return Curl_multi_pipeline_enabled(handle->multi);
|
||||
}
|
||||
|
||||
int Curl_removeHandleFromPipeline(struct SessionHandle *handle,
|
||||
struct curl_llist *pipeline)
|
||||
{
|
||||
@ -3786,9 +3781,9 @@ static struct connectdata *allocate_conn(struct SessionHandle *data)
|
||||
conn->response_header = NULL;
|
||||
#endif
|
||||
|
||||
if(Curl_multi_pipeline_enabled(data->multi) &&
|
||||
!conn->master_buffer) {
|
||||
/* Allocate master_buffer to be used for pipelining */
|
||||
if(Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1) &&
|
||||
!conn->master_buffer) {
|
||||
/* Allocate master_buffer to be used for HTTP/1 pipelining */
|
||||
conn->master_buffer = calloc(BUFSIZE, sizeof (char));
|
||||
if(!conn->master_buffer)
|
||||
goto error;
|
||||
|
Loading…
Reference in New Issue
Block a user