.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * 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
.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
.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"
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
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
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)
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
/* 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
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;
}
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;
}
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);
#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
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;
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
*/
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
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
/* 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",
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);
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,
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);
}
{
/* 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 ||
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)
{
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;