1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel (at) haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.haxx.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 ***************************************************************************/ 22 #include "test.h" 23 #include "memdebug.h" 24 25 #define THREADS 2 26 27 /* struct containing data of a thread */ 28 struct Tdata { 29 CURLSH *share; 30 char *url; 31 }; 32 33 struct userdata { 34 const char *text; 35 int counter; 36 }; 37 38 /* lock callback */ 39 static void my_lock(CURL *handle, curl_lock_data data, 40 curl_lock_access laccess, void *useptr) 41 { 42 const char *what; 43 struct userdata *user = (struct userdata *)useptr; 44 45 (void)handle; 46 (void)laccess; 47 48 switch(data) { 49 case CURL_LOCK_DATA_SHARE: 50 what = "share"; 51 break; 52 case CURL_LOCK_DATA_DNS: 53 what = "dns"; 54 break; 55 case CURL_LOCK_DATA_COOKIE: 56 what = "cookie"; 57 break; 58 case CURL_LOCK_DATA_SSL_SESSION: 59 what = "ssl_session"; 60 break; 61 default: 62 fprintf(stderr, "lock: no such data: %d\n", (int)data); 63 return; 64 } 65 printf("lock: %-6s [%s]: %d\n", what, user->text, user->counter); 66 user->counter++; 67 } 68 69 /* unlock callback */ 70 static void my_unlock(CURL *handle, curl_lock_data data, void *useptr) 71 { 72 const char *what; 73 struct userdata *user = (struct userdata *)useptr; 74 (void)handle; 75 switch(data) { 76 case CURL_LOCK_DATA_SHARE: 77 what = "share"; 78 break; 79 case CURL_LOCK_DATA_DNS: 80 what = "dns"; 81 break; 82 case CURL_LOCK_DATA_COOKIE: 83 what = "cookie"; 84 break; 85 case CURL_LOCK_DATA_SSL_SESSION: 86 what = "ssl_session"; 87 break; 88 default: 89 fprintf(stderr, "unlock: no such data: %d\n", (int)data); 90 return; 91 } 92 printf("unlock: %-6s [%s]: %d\n", what, user->text, user->counter); 93 user->counter++; 94 } 95 96 /* the dummy thread function */ 97 static void *fire(void *ptr) 98 { 99 CURLcode code; 100 struct Tdata *tdata = (struct Tdata*)ptr; 101 CURL *curl; 102 103 curl = curl_easy_init(); 104 if(!curl) { 105 fprintf(stderr, "curl_easy_init() failed\n"); 106 return NULL; 107 } 108 109 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); 110 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); 111 curl_easy_setopt(curl, CURLOPT_URL, tdata->url); 112 printf("CURLOPT_SHARE\n"); 113 curl_easy_setopt(curl, CURLOPT_SHARE, tdata->share); 114 115 printf("PERFORM\n"); 116 code = curl_easy_perform(curl); 117 if(code != CURLE_OK) { 118 int i = 0; 119 fprintf(stderr, "perform url '%s' repeat %d failed, curlcode %d\n", 120 tdata->url, i, (int)code); 121 } 122 123 printf("CLEANUP\n"); 124 curl_easy_cleanup(curl); 125 126 return NULL; 127 } 128 129 /* test function */ 130 int test(char *URL) 131 { 132 int res; 133 CURLSHcode scode = CURLSHE_OK; 134 char *url; 135 struct Tdata tdata; 136 CURL *curl; 137 CURLSH *share; 138 int i; 139 struct userdata user; 140 141 user.text = "Pigs in space"; 142 user.counter = 0; 143 144 printf("GLOBAL_INIT\n"); 145 if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { 146 fprintf(stderr, "curl_global_init() failed\n"); 147 return TEST_ERR_MAJOR_BAD; 148 } 149 150 /* prepare share */ 151 printf("SHARE_INIT\n"); 152 share = curl_share_init(); 153 if(!share) { 154 fprintf(stderr, "curl_share_init() failed\n"); 155 curl_global_cleanup(); 156 return TEST_ERR_MAJOR_BAD; 157 } 158 159 if(CURLSHE_OK == scode) { 160 printf("CURLSHOPT_LOCKFUNC\n"); 161 scode = curl_share_setopt(share, CURLSHOPT_LOCKFUNC, my_lock); 162 } 163 if(CURLSHE_OK == scode) { 164 printf("CURLSHOPT_UNLOCKFUNC\n"); 165 scode = curl_share_setopt(share, CURLSHOPT_UNLOCKFUNC, my_unlock); 166 } 167 if(CURLSHE_OK == scode) { 168 printf("CURLSHOPT_USERDATA\n"); 169 scode = curl_share_setopt(share, CURLSHOPT_USERDATA, &user); 170 } 171 if(CURLSHE_OK == scode) { 172 printf("CURL_LOCK_DATA_SSL_SESSION\n"); 173 scode = curl_share_setopt(share, CURLSHOPT_SHARE, 174 CURL_LOCK_DATA_SSL_SESSION); 175 } 176 177 if(CURLSHE_OK != scode) { 178 fprintf(stderr, "curl_share_setopt() failed\n"); 179 curl_share_cleanup(share); 180 curl_global_cleanup(); 181 return TEST_ERR_MAJOR_BAD; 182 } 183 184 185 res = 0; 186 187 /* start treads */ 188 for(i = 1; i <= THREADS; i++) { 189 190 /* set thread data */ 191 tdata.url = URL; 192 tdata.share = share; 193 194 /* simulate thread, direct call of "thread" function */ 195 printf("*** run %d\n",i); 196 fire(&tdata); 197 } 198 199 200 /* fetch a another one */ 201 printf("*** run %d\n", i); 202 curl = curl_easy_init(); 203 if(!curl) { 204 fprintf(stderr, "curl_easy_init() failed\n"); 205 curl_share_cleanup(share); 206 curl_global_cleanup(); 207 return TEST_ERR_MAJOR_BAD; 208 } 209 210 url = URL; 211 test_setopt(curl, CURLOPT_URL, url); 212 printf("CURLOPT_SHARE\n"); 213 test_setopt(curl, CURLOPT_SHARE, share); 214 215 printf("PERFORM\n"); 216 curl_easy_perform(curl); 217 218 /* try to free share, expect to fail because share is in use*/ 219 printf("try SHARE_CLEANUP...\n"); 220 scode = curl_share_cleanup(share); 221 if(scode == CURLSHE_OK) { 222 fprintf(stderr, "curl_share_cleanup succeed but error expected\n"); 223 share = NULL; 224 } 225 else { 226 printf("SHARE_CLEANUP failed, correct\n"); 227 } 228 229 test_cleanup: 230 231 /* clean up last handle */ 232 printf("CLEANUP\n"); 233 curl_easy_cleanup(curl); 234 235 /* free share */ 236 printf("SHARE_CLEANUP\n"); 237 scode = curl_share_cleanup(share); 238 if(scode != CURLSHE_OK) 239 fprintf(stderr, "curl_share_cleanup failed, code errno %d\n", 240 (int)scode); 241 242 printf("GLOBAL_CLEANUP\n"); 243 curl_global_cleanup(); 244 245 return res; 246 } 247