diff options
author | taesubkim <taesub.kim@samsung.com> | 2016-04-25 10:21:23 +0900 |
---|---|---|
committer | taesubkim <taesub.kim@samsung.com> | 2016-04-25 10:27:58 +0900 |
commit | 0a710b32648c435f792f5993fdefa2d96f802580 (patch) | |
tree | 8370266f83e70616acf75c514a5707407887e4b7 /lib/conncache.c | |
parent | 7b6dca47a42828c0ae87eab0d8b68f97d1495b67 (diff) | |
download | curl-0a710b32648c435f792f5993fdefa2d96f802580.tar.gz curl-0a710b32648c435f792f5993fdefa2d96f802580.tar.bz2 curl-0a710b32648c435f792f5993fdefa2d96f802580.zip |
Imported Upstream version 7.48.0upstream/7.48.0
Change-Id: Ibca5368d95ef0b73c945bb0df8b7ef9fc3e3bd82
Signed-off-by: Taesub Kim <taesub.kim@samsung.com>
Diffstat (limited to 'lib/conncache.c')
-rw-r--r-- | lib/conncache.c | 163 |
1 files changed, 120 insertions, 43 deletions
diff --git a/lib/conncache.c b/lib/conncache.c index fcfb15015..6e03caf3c 100644 --- a/lib/conncache.c +++ b/lib/conncache.c @@ -6,11 +6,11 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2012, Linus Nielsen Feltzing, <linus@haxx.se> - * Copyright (C) 2012 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 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 - * are also available at http://curl.haxx.se/docs/copyright.html. + * are also available at https://curl.haxx.se/docs/copyright.html. * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is @@ -31,66 +31,134 @@ #include "multiif.h" #include "sendf.h" #include "rawstr.h" -#include "bundles.h" #include "conncache.h" +#include "curl_printf.h" #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" -static void free_bundle_hash_entry(void *freethis) +static void conn_llist_dtor(void *user, void *element) { - struct connectbundle *b = (struct connectbundle *) freethis; + struct connectdata *data = element; + (void)user; - Curl_bundle_destroy(b); + data->bundle = NULL; } -struct conncache *Curl_conncache_init(int size) +static CURLcode bundle_create(struct SessionHandle *data, + struct connectbundle **cb_ptr) { - struct conncache *connc; - - connc = calloc(1, sizeof(struct conncache)); - if(!connc) - return NULL; + (void)data; + DEBUGASSERT(*cb_ptr == NULL); + *cb_ptr = malloc(sizeof(struct connectbundle)); + if(!*cb_ptr) + return CURLE_OUT_OF_MEMORY; + + (*cb_ptr)->num_connections = 0; + (*cb_ptr)->multiuse = BUNDLE_UNKNOWN; + + (*cb_ptr)->conn_list = Curl_llist_alloc((curl_llist_dtor) conn_llist_dtor); + if(!(*cb_ptr)->conn_list) { + Curl_safefree(*cb_ptr); + return CURLE_OUT_OF_MEMORY; + } + return CURLE_OK; +} - connc->hash = Curl_hash_alloc(size, Curl_hash_str, - Curl_str_key_compare, free_bundle_hash_entry); +static void bundle_destroy(struct connectbundle *cb_ptr) +{ + if(!cb_ptr) + return; - if(!connc->hash) { - free(connc); - return NULL; + if(cb_ptr->conn_list) { + Curl_llist_destroy(cb_ptr->conn_list, NULL); + cb_ptr->conn_list = NULL; } + free(cb_ptr); +} + +/* Add a connection to a bundle */ +static CURLcode bundle_add_conn(struct connectbundle *cb_ptr, + struct connectdata *conn) +{ + if(!Curl_llist_insert_next(cb_ptr->conn_list, cb_ptr->conn_list->tail, conn)) + return CURLE_OUT_OF_MEMORY; - return connc; + conn->bundle = cb_ptr; + + cb_ptr->num_connections++; + return CURLE_OK; } -void Curl_conncache_destroy(struct conncache *connc) +/* Remove a connection from a bundle */ +static int bundle_remove_conn(struct connectbundle *cb_ptr, + struct connectdata *conn) { - if(connc) { - Curl_hash_destroy(connc->hash); - connc->hash = NULL; - free(connc); + struct curl_llist_element *curr; + + curr = cb_ptr->conn_list->head; + while(curr) { + if(curr->ptr == conn) { + Curl_llist_remove(cb_ptr->conn_list, curr, NULL); + cb_ptr->num_connections--; + conn->bundle = NULL; + return 1; /* we removed a handle */ + } + curr = curr->next; } + return 0; } -struct connectbundle *Curl_conncache_find_bundle(struct conncache *connc, - char *hostname) +static void free_bundle_hash_entry(void *freethis) { - struct connectbundle *bundle = NULL; + struct connectbundle *b = (struct connectbundle *) freethis; + + bundle_destroy(b); +} +int Curl_conncache_init(struct conncache *connc, int size) +{ + return Curl_hash_init(&connc->hash, size, Curl_hash_str, + Curl_str_key_compare, free_bundle_hash_entry); +} + +void Curl_conncache_destroy(struct conncache *connc) +{ if(connc) - bundle = Curl_hash_pick(connc->hash, hostname, strlen(hostname)+1); + Curl_hash_destroy(&connc->hash); +} + +/* returns an allocated key to find a bundle for this connection */ +static char *hashkey(struct connectdata *conn) +{ + return aprintf("%s:%d", + conn->bits.proxy?conn->proxy.name:conn->host.name, + conn->localport); +} + +/* Look up the bundle with all the connections to the same host this + connectdata struct is setup to use. */ +struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn, + struct conncache *connc) +{ + struct connectbundle *bundle = NULL; + if(connc) { + char *key = hashkey(conn); + if(key) { + bundle = Curl_hash_pick(&connc->hash, key, strlen(key)); + free(key); + } + } return bundle; } static bool conncache_add_bundle(struct conncache *connc, - char *hostname, + char *key, struct connectbundle *bundle) { - void *p; - - p = Curl_hash_add(connc->hash, hostname, strlen(hostname)+1, bundle); + void *p = Curl_hash_add(&connc->hash, key, strlen(key), bundle); return p?TRUE:FALSE; } @@ -104,14 +172,14 @@ static void conncache_remove_bundle(struct conncache *connc, if(!connc) return; - Curl_hash_start_iterate(connc->hash, &iter); + Curl_hash_start_iterate(&connc->hash, &iter); he = Curl_hash_next_element(&iter); while(he) { if(he->ptr == bundle) { /* The bundle is destroyed by the hash destructor function, free_bundle_hash_entry() */ - Curl_hash_delete(connc->hash, he->key, he->key_len); + Curl_hash_delete(&connc->hash, he->key, he->key_len); return; } @@ -127,22 +195,31 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc, struct connectbundle *new_bundle = NULL; struct SessionHandle *data = conn->data; - bundle = Curl_conncache_find_bundle(data->state.conn_cache, - conn->host.name); + bundle = Curl_conncache_find_bundle(conn, data->state.conn_cache); if(!bundle) { - result = Curl_bundle_create(data, &new_bundle); + char *key; + int rc; + + result = bundle_create(data, &new_bundle); if(result) return result; - if(!conncache_add_bundle(data->state.conn_cache, - conn->host.name, new_bundle)) { - Curl_bundle_destroy(new_bundle); + key = hashkey(conn); + if(!key) { + bundle_destroy(new_bundle); + return CURLE_OUT_OF_MEMORY; + } + + rc = conncache_add_bundle(data->state.conn_cache, key, new_bundle); + free(key); + if(!rc) { + bundle_destroy(new_bundle); return CURLE_OUT_OF_MEMORY; } bundle = new_bundle; } - result = Curl_bundle_add_conn(bundle, conn); + result = bundle_add_conn(bundle, conn); if(result) { if(new_bundle) conncache_remove_bundle(data->state.conn_cache, new_bundle); @@ -167,7 +244,7 @@ void Curl_conncache_remove_conn(struct conncache *connc, /* The bundle pointer can be NULL, since this function can be called due to a failed connection attempt, before being added to a bundle */ if(bundle) { - Curl_bundle_remove_conn(bundle, conn); + bundle_remove_conn(bundle, conn); if(bundle->num_connections == 0) { conncache_remove_bundle(connc, bundle); } @@ -199,7 +276,7 @@ void Curl_conncache_foreach(struct conncache *connc, if(!connc) return; - Curl_hash_start_iterate(connc->hash, &iter); + Curl_hash_start_iterate(&connc->hash, &iter); he = Curl_hash_next_element(&iter); while(he) { @@ -230,7 +307,7 @@ Curl_conncache_find_first_connection(struct conncache *connc) struct curl_hash_element *he; struct connectbundle *bundle; - Curl_hash_start_iterate(connc->hash, &iter); + Curl_hash_start_iterate(&connc->hash, &iter); he = Curl_hash_next_element(&iter); while(he) { |