1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) Daniel Stenberg, <daniel@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.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 * SPDX-License-Identifier: curl 22 * 23 ***************************************************************************/ 24#include "test.h" 25#include "memdebug.h" 26 27#define THREADS 2 28 29/* struct containing data of a thread */ 30struct Tdata { 31 CURLSH *share; 32 char *url; 33}; 34 35struct userdata { 36 const char *text; 37 int counter; 38}; 39 40/* lock callback */ 41static void my_lock(CURL *handle, curl_lock_data data, 42 curl_lock_access laccess, void *useptr) 43{ 44 const char *what; 45 struct userdata *user = (struct userdata *)useptr; 46 47 (void)handle; 48 (void)laccess; 49 50 switch(data) { 51 case CURL_LOCK_DATA_SHARE: 52 what = "share"; 53 break; 54 case CURL_LOCK_DATA_DNS: 55 what = "dns"; 56 break; 57 case CURL_LOCK_DATA_COOKIE: 58 what = "cookie"; 59 break; 60 case CURL_LOCK_DATA_SSL_SESSION: 61 what = "ssl_session"; 62 break; 63 default: 64 fprintf(stderr, "lock: no such data: %d\n", (int)data); 65 return; 66 } 67 printf("lock: %-6s [%s]: %d\n", what, user->text, user->counter); 68 user->counter++; 69} 70 71/* unlock callback */ 72static void my_unlock(CURL *handle, curl_lock_data data, void *useptr) 73{ 74 const char *what; 75 struct userdata *user = (struct userdata *)useptr; 76 (void)handle; 77 switch(data) { 78 case CURL_LOCK_DATA_SHARE: 79 what = "share"; 80 break; 81 case CURL_LOCK_DATA_DNS: 82 what = "dns"; 83 break; 84 case CURL_LOCK_DATA_COOKIE: 85 what = "cookie"; 86 break; 87 case CURL_LOCK_DATA_SSL_SESSION: 88 what = "ssl_session"; 89 break; 90 default: 91 fprintf(stderr, "unlock: no such data: %d\n", (int)data); 92 return; 93 } 94 printf("unlock: %-6s [%s]: %d\n", what, user->text, user->counter); 95 user->counter++; 96} 97 98/* the dummy thread function */ 99static void *fire(void *ptr) 100{ 101 CURLcode code; 102 struct Tdata *tdata = (struct Tdata*)ptr; 103 CURL *curl; 104 105 curl = curl_easy_init(); 106 if(!curl) { 107 fprintf(stderr, "curl_easy_init() failed\n"); 108 return NULL; 109 } 110 111 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); 112 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); 113 curl_easy_setopt(curl, CURLOPT_URL, tdata->url); 114 printf("CURLOPT_SHARE\n"); 115 curl_easy_setopt(curl, CURLOPT_SHARE, tdata->share); 116 117 printf("PERFORM\n"); 118 code = curl_easy_perform(curl); 119 if(code != CURLE_OK) { 120 int i = 0; 121 fprintf(stderr, "perform url '%s' repeat %d failed, curlcode %d\n", 122 tdata->url, i, (int)code); 123 } 124 125 printf("CLEANUP\n"); 126 curl_easy_cleanup(curl); 127 128 return NULL; 129} 130 131/* test function */ 132int test(char *URL) 133{ 134 CURLcode res = CURLE_OK; 135 CURLSHcode scode = CURLSHE_OK; 136 char *url; 137 struct Tdata tdata; 138 CURL *curl; 139 CURLSH *share; 140 int i; 141 struct userdata user; 142 143 user.text = "Pigs in space"; 144 user.counter = 0; 145 146 printf("GLOBAL_INIT\n"); 147 if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { 148 fprintf(stderr, "curl_global_init() failed\n"); 149 return TEST_ERR_MAJOR_BAD; 150 } 151 152 /* prepare share */ 153 printf("SHARE_INIT\n"); 154 share = curl_share_init(); 155 if(!share) { 156 fprintf(stderr, "curl_share_init() failed\n"); 157 curl_global_cleanup(); 158 return TEST_ERR_MAJOR_BAD; 159 } 160 161 if(CURLSHE_OK == scode) { 162 printf("CURLSHOPT_LOCKFUNC\n"); 163 scode = curl_share_setopt(share, CURLSHOPT_LOCKFUNC, my_lock); 164 } 165 if(CURLSHE_OK == scode) { 166 printf("CURLSHOPT_UNLOCKFUNC\n"); 167 scode = curl_share_setopt(share, CURLSHOPT_UNLOCKFUNC, my_unlock); 168 } 169 if(CURLSHE_OK == scode) { 170 printf("CURLSHOPT_USERDATA\n"); 171 scode = curl_share_setopt(share, CURLSHOPT_USERDATA, &user); 172 } 173 if(CURLSHE_OK == scode) { 174 printf("CURL_LOCK_DATA_SSL_SESSION\n"); 175 scode = curl_share_setopt(share, CURLSHOPT_SHARE, 176 CURL_LOCK_DATA_SSL_SESSION); 177 } 178 179 if(CURLSHE_OK != scode) { 180 fprintf(stderr, "curl_share_setopt() failed\n"); 181 curl_share_cleanup(share); 182 curl_global_cleanup(); 183 return TEST_ERR_MAJOR_BAD; 184 } 185 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 res = 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 229test_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