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
|
.\" * This software is licensed as described in the file COPYING, which
|
||||||
.\" * you should have received as part of this distribution. The terms
|
.\" * you should have received as part of this distribution. The terms
|
||||||
@ -26,17 +26,28 @@ CURLMOPT_PIPELINING \- enable/disable HTTP pipelining
|
|||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
#include <curl/curl.h>
|
#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
|
.SH DESCRIPTION
|
||||||
Set the \fBonoff\fP parameter to 1 to make libcurl use HTTP pipelining for
|
Set the \fBbits\fP parameter to 1 to make libcurl use HTTP pipelining for
|
||||||
HTTP transfers done using this multi handle, as far as possible. This means
|
HTTP/1.1 transfers done using this multi handle, as far as possible. This
|
||||||
that if you add a second request that can use an already existing connection,
|
means that if you add a second request that can use an already existing
|
||||||
the second request will be \&"piped" on the same connection rather than being
|
connection, the second request will be \&"piped" on the same connection rather
|
||||||
executed in parallel.
|
than being executed in parallel.
|
||||||
|
|
||||||
When using pipelining, there are also several other related options that are
|
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
|
interesting to tweak and adjust to alter how libcurl spreads out requests on
|
||||||
different connections or not etc.
|
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
|
.SH DEFAULT
|
||||||
0 (off)
|
0 (off)
|
||||||
.SH PROTOCOLS
|
.SH PROTOCOLS
|
||||||
@ -44,7 +55,7 @@ HTTP(S)
|
|||||||
.SH EXAMPLE
|
.SH EXAMPLE
|
||||||
TODO
|
TODO
|
||||||
.SH AVAILABILITY
|
.SH AVAILABILITY
|
||||||
Added in 7.16.0
|
Added in 7.16.0. Multiplex support bit added in 7.43.0.
|
||||||
.SH RETURN VALUE
|
.SH RETURN VALUE
|
||||||
Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
|
Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
|
||||||
.SH "SEE ALSO"
|
.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
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* 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 */
|
curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */
|
||||||
#define CURLM_CALL_MULTI_SOCKET 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 {
|
typedef enum {
|
||||||
CURLMSG_NONE, /* first, not used */
|
CURLMSG_NONE, /* first, not used */
|
||||||
CURLMSG_DONE, /* This easy handle has completed. 'result' contains
|
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;
|
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)
|
void Curl_multi_handlePipeBreak(struct SessionHandle *data)
|
||||||
@ -1082,7 +1083,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
rc = CURLM_CALL_MULTI_PERFORM;
|
rc = CURLM_CALL_MULTI_PERFORM;
|
||||||
|
|
||||||
if(protocol_connect)
|
if(protocol_connect)
|
||||||
multistate(data, multi->pipelining_enabled?
|
multistate(data, Curl_pipeline_wanted(multi, CURLPIPE_HTTP1)?
|
||||||
CURLM_STATE_WAITDO:CURLM_STATE_DO);
|
CURLM_STATE_WAITDO:CURLM_STATE_DO);
|
||||||
else {
|
else {
|
||||||
#ifndef CURL_DISABLE_HTTP
|
#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 */
|
/* call again please so that we get the next socket setup */
|
||||||
rc = CURLM_CALL_MULTI_PERFORM;
|
rc = CURLM_CALL_MULTI_PERFORM;
|
||||||
if(protocol_connect)
|
if(protocol_connect)
|
||||||
multistate(data, multi->pipelining_enabled?
|
multistate(data, Curl_pipeline_wanted(multi, CURLPIPE_HTTP1)?
|
||||||
CURLM_STATE_WAITDO:CURLM_STATE_DO);
|
CURLM_STATE_WAITDO:CURLM_STATE_DO);
|
||||||
else {
|
else {
|
||||||
#ifndef CURL_DISABLE_HTTP
|
#ifndef CURL_DISABLE_HTTP
|
||||||
@ -1203,7 +1204,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
multistate(data, CURLM_STATE_PROTOCONNECT);
|
multistate(data, CURLM_STATE_PROTOCONNECT);
|
||||||
else if(!result) {
|
else if(!result) {
|
||||||
/* protocol connect has completed, go WAITDO or DO */
|
/* 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);
|
CURLM_STATE_WAITDO:CURLM_STATE_DO);
|
||||||
rc = CURLM_CALL_MULTI_PERFORM;
|
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);
|
result = Curl_protocol_connecting(data->easy_conn, &protocol_connect);
|
||||||
if(!result && protocol_connect) {
|
if(!result && protocol_connect) {
|
||||||
/* after the connect has completed, go WAITDO or DO */
|
/* 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);
|
CURLM_STATE_WAITDO:CURLM_STATE_DO);
|
||||||
rc = CURLM_CALL_MULTI_PERFORM;
|
rc = CURLM_CALL_MULTI_PERFORM;
|
||||||
}
|
}
|
||||||
@ -2340,7 +2341,7 @@ CURLMcode curl_multi_setopt(CURLM *multi_handle,
|
|||||||
multi->socket_userp = va_arg(param, void *);
|
multi->socket_userp = va_arg(param, void *);
|
||||||
break;
|
break;
|
||||||
case CURLMOPT_PIPELINING:
|
case CURLMOPT_PIPELINING:
|
||||||
multi->pipelining_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE;
|
multi->pipelining = va_arg(param, long);
|
||||||
break;
|
break;
|
||||||
case CURLMOPT_TIMERFUNCTION:
|
case CURLMOPT_TIMERFUNCTION:
|
||||||
multi->timer_cb = va_arg(param, curl_multi_timer_callback);
|
multi->timer_cb = va_arg(param, curl_multi_timer_callback);
|
||||||
|
@ -62,6 +62,8 @@ typedef enum {
|
|||||||
#define GETSOCK_READABLE (0x00ff)
|
#define GETSOCK_READABLE (0x00ff)
|
||||||
#define GETSOCK_WRITABLE (0xff00)
|
#define GETSOCK_WRITABLE (0xff00)
|
||||||
|
|
||||||
|
#define CURLPIPE_ANY (CURLPIPE_HTTP1 | CURLPIPE_MULTIPLEX)
|
||||||
|
|
||||||
/* This is the struct known as CURLM on the outside */
|
/* This is the struct known as CURLM on the outside */
|
||||||
struct Curl_multi {
|
struct Curl_multi {
|
||||||
/* First a simple identifier to easier detect if a user mix up
|
/* First a simple identifier to easier detect if a user mix up
|
||||||
@ -97,8 +99,8 @@ struct Curl_multi {
|
|||||||
same actual socket) */
|
same actual socket) */
|
||||||
struct curl_hash sockhash;
|
struct curl_hash sockhash;
|
||||||
|
|
||||||
/* Whether pipelining is enabled for this multi handle */
|
/* pipelining wanted bits (CURLPIPE*) */
|
||||||
bool pipelining_enabled;
|
long pipelining;
|
||||||
|
|
||||||
/* Shared connection cache (bundles)*/
|
/* Shared connection cache (bundles)*/
|
||||||
struct conncache conn_cache;
|
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
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* 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(struct SessionHandle *data, long milli);
|
||||||
void Curl_expire_latest(struct SessionHandle *data, long milli);
|
void Curl_expire_latest(struct SessionHandle *data, long milli);
|
||||||
|
bool Curl_pipeline_wanted(const struct Curl_multi* multi, int bits);
|
||||||
bool Curl_multi_pipeline_enabled(const struct Curl_multi* multi);
|
|
||||||
void Curl_multi_handlePipeBreak(struct SessionHandle *data);
|
void Curl_multi_handlePipeBreak(struct SessionHandle *data);
|
||||||
|
|
||||||
/* Internal version of curl_multi_init() accepts size parameters for the
|
/* 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;
|
ssize_t nread = 0;
|
||||||
size_t bytesfromsocket = 0;
|
size_t bytesfromsocket = 0;
|
||||||
char *buffertofill = NULL;
|
char *buffertofill = NULL;
|
||||||
bool pipelining = Curl_multi_pipeline_enabled(conn->data->multi) &&
|
bool pipelining = Curl_pipeline_wanted(conn->data->multi, CURLPIPE_HTTP1);
|
||||||
!conn->bits.multiplex;
|
|
||||||
|
|
||||||
/* Set 'num' to 0 or 1, depending on which socket that has been sent here.
|
/* 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
|
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 */
|
/* We've stopped dealing with input, get out of the do-while loop */
|
||||||
|
|
||||||
if(nread > 0) {
|
if(nread > 0) {
|
||||||
if(Curl_multi_pipeline_enabled(conn->data->multi)) {
|
if(Curl_pipeline_wanted(conn->data->multi, CURLPIPE_HTTP1)) {
|
||||||
infof(data,
|
infof(data,
|
||||||
"Rewinding stream by : %zd"
|
"Rewinding stream by : %zd"
|
||||||
" bytes on url %s (zero-length body)\n",
|
" bytes on url %s (zero-length body)\n",
|
||||||
@ -639,7 +639,7 @@ static CURLcode readwrite_data(struct SessionHandle *data,
|
|||||||
if(dataleft != 0) {
|
if(dataleft != 0) {
|
||||||
infof(conn->data, "Leftovers after chunking: %zu bytes\n",
|
infof(conn->data, "Leftovers after chunking: %zu bytes\n",
|
||||||
dataleft);
|
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 */
|
/* only attempt the rewind if we truly are pipelining */
|
||||||
infof(conn->data, "Rewinding %zu bytes\n",dataleft);
|
infof(conn->data, "Rewinding %zu bytes\n",dataleft);
|
||||||
read_rewind(conn, dataleft);
|
read_rewind(conn, dataleft);
|
||||||
@ -662,7 +662,7 @@ static CURLcode readwrite_data(struct SessionHandle *data,
|
|||||||
|
|
||||||
excess = (size_t)(k->bytecount + nread - k->maxdownload);
|
excess = (size_t)(k->bytecount + nread - k->maxdownload);
|
||||||
if(excess > 0 && !k->ignorebody) {
|
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
|
/* The 'excess' amount below can't be more than BUFSIZE which
|
||||||
always will fit in a size_t */
|
always will fit in a size_t */
|
||||||
infof(data,
|
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);
|
Curl_ssl_close(conn, FIRSTSOCKET);
|
||||||
|
|
||||||
/* Indicate to all handles on the pipe that we're dead */
|
/* 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->send_pipe, TRUE);
|
||||||
signalPipeClose(conn->recv_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 a HTTP protocol and pipelining is enabled */
|
||||||
if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
|
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) &&
|
if((handle->set.httpversion != CURL_HTTP_VERSION_1_0) &&
|
||||||
(handle->set.httpreq == HTTPREQ_GET ||
|
(handle->set.httpreq == HTTPREQ_GET ||
|
||||||
@ -2830,11 +2830,6 @@ static bool IsPipeliningPossible(const struct SessionHandle *handle,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Curl_isPipeliningEnabled(const struct SessionHandle *handle)
|
|
||||||
{
|
|
||||||
return Curl_multi_pipeline_enabled(handle->multi);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Curl_removeHandleFromPipeline(struct SessionHandle *handle,
|
int Curl_removeHandleFromPipeline(struct SessionHandle *handle,
|
||||||
struct curl_llist *pipeline)
|
struct curl_llist *pipeline)
|
||||||
{
|
{
|
||||||
@ -3786,9 +3781,9 @@ static struct connectdata *allocate_conn(struct SessionHandle *data)
|
|||||||
conn->response_header = NULL;
|
conn->response_header = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(Curl_multi_pipeline_enabled(data->multi) &&
|
if(Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1) &&
|
||||||
!conn->master_buffer) {
|
!conn->master_buffer) {
|
||||||
/* Allocate master_buffer to be used for pipelining */
|
/* Allocate master_buffer to be used for HTTP/1 pipelining */
|
||||||
conn->master_buffer = calloc(BUFSIZE, sizeof (char));
|
conn->master_buffer = calloc(BUFSIZE, sizeof (char));
|
||||||
if(!conn->master_buffer)
|
if(!conn->master_buffer)
|
||||||
goto error;
|
goto error;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user