]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
CURLMOPT_PIPELINE: bit 1 is for multiplexing
authorDaniel Stenberg <daniel@haxx.se>
Fri, 8 May 2015 08:43:36 +0000 (10:43 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 18 May 2015 06:57:18 +0000 (08:57 +0200)
docs/libcurl/opts/CURLMOPT_PIPELINING.3
include/curl/multi.h
lib/multi.c
lib/multihandle.h
lib/multiif.h
lib/sendf.c
lib/transfer.c
lib/url.c

index c1df1d560352c638d407348772d35d6047bf45f3..c795c48ecc24646707a8a1607ed3c5c3574f4238 100644 (file)
@@ -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"
index 3c4acb0f6eafdedaa81bcd24af8f0b5353b5f304..0d859f8fd98c509a0450998bdec60f6e7ff35299 100644 (file)
@@ -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
index 5595bbd1f82d3b9755a758278096938eaea723a1..5573151a8b5ce0f22bcf75cf8ecbe7005c10c2e8 100644 (file)
@@ -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);
index 640e3fb4b945c352af23df26cb57f6b06a1d0f8b..13b32d8fe4aa24e7079b0e85c86a71da53456120 100644 (file)
@@ -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;
index d8acfcabe7ce79b490193c8ab9a9cb78c5b482d7..152cb8be21819d7a50cdac4efee93b3d5b946ff6 100644 (file)
@@ -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
index 71b2d6030cb564a67f4e90cf00e265f517680827..5f39d1f2d4268f02ca06227aa5dbb0191ed706a3 100644 (file)
@@ -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
index 8ac91664c52e1f285cedd873c0f2d6dd440bf71d..59e6acb4d6084de0c1f41a0de5c9af7713398b50 100644 (file)
@@ -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,
index bdda991c80de0e91474e69aba4566bce21ae91ed..805459c82bdfff1c7c86cfc3838f2fc2ebb9b1a4 100644 (file)
--- a/lib/url.c
+++ b/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;