to allow code to act differently on the situation.
Also added some more info message for the connection re-use function to
make it clearer when connections are not re-used.
return CURLE_OUT_OF_MEMORY;
(*cb_ptr)->num_connections = 0;
- (*cb_ptr)->server_supports_pipelining = FALSE;
+ (*cb_ptr)->multiuse = BUNDLE_UNKNOWN;
(*cb_ptr)->conn_list = Curl_llist_alloc((curl_llist_dtor) conn_llist_dtor);
if(!(*cb_ptr)->conn_list) {
return result;
key = hashkey(conn);
- if(!key) {
- bundle_destroy(new_bundle);
+ if(!key)
return CURLE_OUT_OF_MEMORY;
- }
rc = conncache_add_bundle(data->state.conn_cache, key, new_bundle);
free(key);
struct timeval last_cleanup;
};
+#define BUNDLE_NO_MULTIUSE -1
+#define BUNDLE_UNKNOWN 0 /* initial value */
+#define BUNDLE_PIPELINING 1
+#define BUNDLE_MULTIPLEX 2
+
struct connectbundle {
- bool server_supports_pipelining; /* TRUE if server supports pipelining,
- set after first response */
+ int multiuse; /* supports multi-use */
size_t num_connections; /* Number of connections in the bundle */
struct curl_llist *conn_list; /* The connectdata members of the bundle */
};
/* HTTP/2 cannot blacklist multiplexing since it is a core
functionality of the protocol */
- conn->bundle->server_supports_pipelining = TRUE;
+ conn->bundle->multiuse = BUNDLE_MULTIPLEX;
}
else if(conn->httpversion >= 11 &&
!conn->bits.close) {
cb_ptr = conn->bundle;
if(cb_ptr) {
if(!Curl_pipeline_site_blacklisted(data, conn))
- cb_ptr->server_supports_pipelining = TRUE;
+ cb_ptr->multiuse = BUNDLE_PIPELINING;
}
}
char *server_name = Curl_copy_header_value(k->p);
/* Turn off pipelining if the server version is blacklisted */
- if(conn->bundle && conn->bundle->server_supports_pipelining) {
+ if(conn->bundle && (conn->bundle->multiuse == BUNDLE_PIPELINING)) {
if(Curl_pipeline_server_blacklisted(data, server_name))
- conn->bundle->server_supports_pipelining = FALSE;
+ conn->bundle->multiuse = BUNDLE_NO_MULTIUSE;
}
free(server_name);
}
#include "curl_base64.h"
#include "rawstr.h"
#include "multiif.h"
-#include "bundles.h"
+#include "conncache.h"
/* The last #include files should be: */
#include "curl_memory.h"
conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
conn->httpversion = 20;
- conn->bundle->server_supports_pipelining = TRUE;
+ conn->bundle->multiuse = BUNDLE_MULTIPLEX;
return CURLE_OK;
}
return multi ? multi->max_total_connections : 0;
}
-size_t Curl_multi_max_pipeline_length(struct Curl_multi *multi)
-{
- return multi ? multi->max_pipeline_length : 0;
-}
-
curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi)
{
return multi ? multi->content_length_penalty_size : 0;
/* Return the value of the CURLMOPT_MAX_HOST_CONNECTIONS option */
size_t Curl_multi_max_host_connections(struct Curl_multi *multi);
-/* Return the value of the CURLMOPT_MAX_PIPELINE_LENGTH option */
-size_t Curl_multi_max_pipeline_length(struct Curl_multi *multi);
-
/* Return the value of the CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE option */
curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi);
}
}
+
+static size_t max_pipeline_length(struct Curl_multi *multi)
+{
+ return multi ? multi->max_pipeline_length : 0;
+}
+
+
/*
* Given one filled in connection struct (named needle), this function should
* detect if there already is one that has all the significant details
particular host */
bundle = Curl_conncache_find_bundle(needle, data->state.conn_cache);
if(bundle) {
- size_t max_pipe_len = Curl_multi_max_pipeline_length(data->multi);
+ size_t max_pipe_len = max_pipeline_length(data->multi);
size_t best_pipe_len = max_pipe_len;
struct curl_llist_element *curr;
needle->host.name, (void *)bundle);
/* We can't pipe if we don't know anything about the server */
- if(canPipeline && !bundle->server_supports_pipelining) {
+ if(canPipeline && (bundle->multiuse <= BUNDLE_UNKNOWN)) {
infof(data, "Server doesn't support multi-use (yet)\n");
canPipeline = FALSE;
}
pipeLen = check->send_pipe->size + check->recv_pipe->size;
if(canPipeline) {
- /* Make sure the pipe has only GET requests */
- struct SessionHandle* sh = gethandleathead(check->send_pipe);
- struct SessionHandle* rh = gethandleathead(check->recv_pipe);
- if(sh) {
- if(!IsPipeliningPossible(sh, check))
- continue;
- }
- else if(rh) {
- if(!IsPipeliningPossible(rh, check))
- continue;
+
+ if(!check->bits.multiplex) {
+ /* If not multiplexing, make sure the pipe has only GET requests */
+ struct SessionHandle* sh = gethandleathead(check->send_pipe);
+ struct SessionHandle* rh = gethandleathead(check->recv_pipe);
+ if(sh) {
+ if(!IsPipeliningPossible(sh, check))
+ continue;
+ }
+ else if(rh) {
+ if(!IsPipeliningPossible(rh, check))
+ continue;
+ }
}
}
else {
}
/* We can't use the connection if the pipe is full */
- if(pipeLen >= max_pipe_len)
+ if(pipeLen >= max_pipe_len) {
+ infof(data, "Pipe is full, skip (%d)\n", pipeLen);
continue;
+ }
/* We can't use the connection if the pipe is penalized */
if(Curl_pipeline_penalized(data, check))
conn_candidate->data = data;
(void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
}
- else
+ else {
+ infof(data, "No more connections allowed to host: %d\n",
+ max_host_connections);
no_connections_available = TRUE;
+ }
}
if(max_total_connections > 0 &&
conn_candidate->data = data;
(void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
}
- else
+ else {
+ infof(data, "No connections available in cache\n");
no_connections_available = TRUE;
+ }
}