lib506.c (10435B)
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 "first.h" 25 26 #include "testutil.h" 27 #include "memdebug.h" 28 29 #define JAR libtest_arg2 30 #define THREADS 2 31 32 /* struct containing data of a thread */ 33 struct t506_Tdata { 34 CURLSH *share; 35 char *url; 36 }; 37 38 struct t506_userdata { 39 const char *text; 40 int counter; 41 }; 42 43 static int locks[3]; 44 45 /* lock callback */ 46 static void t506_test_lock(CURL *handle, curl_lock_data data, 47 curl_lock_access laccess, void *useptr) 48 { 49 const char *what; 50 struct t506_userdata *user = (struct t506_userdata *)useptr; 51 int locknum; 52 53 (void)handle; 54 (void)laccess; 55 56 switch(data) { 57 case CURL_LOCK_DATA_SHARE: 58 what = "share"; 59 locknum = 0; 60 break; 61 case CURL_LOCK_DATA_DNS: 62 what = "dns"; 63 locknum = 1; 64 break; 65 case CURL_LOCK_DATA_COOKIE: 66 what = "cookie"; 67 locknum = 2; 68 break; 69 default: 70 curl_mfprintf(stderr, "lock: no such data: %d\n", (int)data); 71 return; 72 } 73 74 /* detect locking of locked locks */ 75 if(locks[locknum]) { 76 curl_mprintf("lock: double locked %s\n", what); 77 return; 78 } 79 locks[locknum]++; 80 81 curl_mprintf("lock: %-6s [%s]: %d\n", what, user->text, user->counter); 82 user->counter++; 83 } 84 85 /* unlock callback */ 86 static void t506_test_unlock(CURL *handle, curl_lock_data data, void *useptr) 87 { 88 const char *what; 89 struct t506_userdata *user = (struct t506_userdata *)useptr; 90 int locknum; 91 (void)handle; 92 switch(data) { 93 case CURL_LOCK_DATA_SHARE: 94 what = "share"; 95 locknum = 0; 96 break; 97 case CURL_LOCK_DATA_DNS: 98 what = "dns"; 99 locknum = 1; 100 break; 101 case CURL_LOCK_DATA_COOKIE: 102 what = "cookie"; 103 locknum = 2; 104 break; 105 default: 106 curl_mfprintf(stderr, "unlock: no such data: %d\n", (int)data); 107 return; 108 } 109 110 /* detect unlocking of unlocked locks */ 111 if(!locks[locknum]) { 112 curl_mprintf("unlock: double unlocked %s\n", what); 113 return; 114 } 115 locks[locknum]--; 116 117 curl_mprintf("unlock: %-6s [%s]: %d\n", what, user->text, user->counter); 118 user->counter++; 119 } 120 121 /* build host entry */ 122 static struct curl_slist *sethost(struct curl_slist *headers) 123 { 124 (void)headers; 125 return curl_slist_append(NULL, "Host: www.host.foo.com"); 126 } 127 128 /* the dummy thread function */ 129 static void *t506_test_fire(void *ptr) 130 { 131 CURLcode code; 132 struct curl_slist *headers; 133 struct t506_Tdata *tdata = (struct t506_Tdata*)ptr; 134 CURL *curl; 135 136 curl = curl_easy_init(); 137 if(!curl) { 138 curl_mfprintf(stderr, "curl_easy_init() failed\n"); 139 return NULL; 140 } 141 142 headers = sethost(NULL); 143 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); 144 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); 145 curl_easy_setopt(curl, CURLOPT_URL, tdata->url); 146 curl_easy_setopt(curl, CURLOPT_COOKIEFILE, ""); 147 curl_mprintf("CURLOPT_SHARE\n"); 148 curl_easy_setopt(curl, CURLOPT_SHARE, tdata->share); 149 150 curl_mprintf("PERFORM\n"); 151 code = curl_easy_perform(curl); 152 if(code) { 153 int i = 0; 154 curl_mfprintf(stderr, "perform url '%s' repeat %d failed, curlcode %d\n", 155 tdata->url, i, (int)code); 156 } 157 158 curl_mprintf("CLEANUP\n"); 159 curl_easy_cleanup(curl); 160 curl_slist_free_all(headers); 161 162 return NULL; 163 } 164 165 /* test function */ 166 static CURLcode test_lib506(char *URL) 167 { 168 CURLcode res; 169 CURLSHcode scode = CURLSHE_OK; 170 CURLcode code = CURLE_OK; 171 char *url = NULL; 172 struct t506_Tdata tdata; 173 CURL *curl; 174 CURLSH *share; 175 struct curl_slist *headers = NULL; 176 struct curl_slist *cookies = NULL; 177 struct curl_slist *next_cookie = NULL; 178 int i; 179 struct t506_userdata user; 180 181 user.text = "Pigs in space"; 182 user.counter = 0; 183 184 curl_mprintf("GLOBAL_INIT\n"); 185 if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { 186 curl_mfprintf(stderr, "curl_global_init() failed\n"); 187 return TEST_ERR_MAJOR_BAD; 188 } 189 190 /* prepare share */ 191 curl_mprintf("SHARE_INIT\n"); 192 share = curl_share_init(); 193 if(!share) { 194 curl_mfprintf(stderr, "curl_share_init() failed\n"); 195 curl_global_cleanup(); 196 return TEST_ERR_MAJOR_BAD; 197 } 198 199 if(CURLSHE_OK == scode) { 200 curl_mprintf("CURLSHOPT_LOCKFUNC\n"); 201 scode = curl_share_setopt(share, CURLSHOPT_LOCKFUNC, t506_test_lock); 202 } 203 if(CURLSHE_OK == scode) { 204 curl_mprintf("CURLSHOPT_UNLOCKFUNC\n"); 205 scode = curl_share_setopt(share, CURLSHOPT_UNLOCKFUNC, t506_test_unlock); 206 } 207 if(CURLSHE_OK == scode) { 208 curl_mprintf("CURLSHOPT_USERDATA\n"); 209 scode = curl_share_setopt(share, CURLSHOPT_USERDATA, &user); 210 } 211 if(CURLSHE_OK == scode) { 212 curl_mprintf("CURL_LOCK_DATA_COOKIE\n"); 213 scode = curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE); 214 } 215 if(CURLSHE_OK == scode) { 216 curl_mprintf("CURL_LOCK_DATA_DNS\n"); 217 scode = curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); 218 } 219 220 if(CURLSHE_OK != scode) { 221 curl_mfprintf(stderr, "curl_share_setopt() failed\n"); 222 curl_share_cleanup(share); 223 curl_global_cleanup(); 224 return TEST_ERR_MAJOR_BAD; 225 } 226 227 /* initial cookie manipulation */ 228 curl = curl_easy_init(); 229 if(!curl) { 230 curl_mfprintf(stderr, "curl_easy_init() failed\n"); 231 curl_share_cleanup(share); 232 curl_global_cleanup(); 233 return TEST_ERR_MAJOR_BAD; 234 } 235 curl_mprintf("CURLOPT_SHARE\n"); 236 test_setopt(curl, CURLOPT_SHARE, share); 237 curl_mprintf("CURLOPT_COOKIELIST injected_and_clobbered\n"); 238 test_setopt(curl, CURLOPT_COOKIELIST, 239 "Set-Cookie: injected_and_clobbered=yes; " 240 "domain=host.foo.com; expires=Sat Feb 2 11:56:27 GMT 2030"); 241 curl_mprintf("CURLOPT_COOKIELIST ALL\n"); 242 test_setopt(curl, CURLOPT_COOKIELIST, "ALL"); 243 curl_mprintf("CURLOPT_COOKIELIST session\n"); 244 test_setopt(curl, CURLOPT_COOKIELIST, "Set-Cookie: session=elephants"); 245 curl_mprintf("CURLOPT_COOKIELIST injected\n"); 246 test_setopt(curl, CURLOPT_COOKIELIST, 247 "Set-Cookie: injected=yes; domain=host.foo.com; " 248 "expires=Sat Feb 2 11:56:27 GMT 2030"); 249 curl_mprintf("CURLOPT_COOKIELIST SESS\n"); 250 test_setopt(curl, CURLOPT_COOKIELIST, "SESS"); 251 curl_mprintf("CLEANUP\n"); 252 curl_easy_cleanup(curl); 253 254 255 /* start treads */ 256 for(i = 1; i <= THREADS; i++) { 257 258 /* set thread data */ 259 tdata.url = tutil_suburl(URL, i); /* must be curl_free()d */ 260 tdata.share = share; 261 262 /* simulate thread, direct call of "thread" function */ 263 curl_mprintf("*** run %d\n",i); 264 t506_test_fire(&tdata); 265 266 curl_free(tdata.url); 267 } 268 269 270 /* fetch another one and save cookies */ 271 curl_mprintf("*** run %d\n", i); 272 curl = curl_easy_init(); 273 if(!curl) { 274 curl_mfprintf(stderr, "curl_easy_init() failed\n"); 275 curl_share_cleanup(share); 276 curl_global_cleanup(); 277 return TEST_ERR_MAJOR_BAD; 278 } 279 280 url = tutil_suburl(URL, i); 281 headers = sethost(NULL); 282 test_setopt(curl, CURLOPT_HTTPHEADER, headers); 283 test_setopt(curl, CURLOPT_URL, url); 284 curl_mprintf("CURLOPT_SHARE\n"); 285 test_setopt(curl, CURLOPT_SHARE, share); 286 curl_mprintf("CURLOPT_COOKIEJAR\n"); 287 test_setopt(curl, CURLOPT_COOKIEJAR, JAR); 288 curl_mprintf("CURLOPT_COOKIELIST FLUSH\n"); 289 test_setopt(curl, CURLOPT_COOKIELIST, "FLUSH"); 290 291 curl_mprintf("PERFORM\n"); 292 curl_easy_perform(curl); 293 294 curl_mprintf("CLEANUP\n"); 295 curl_easy_cleanup(curl); 296 curl_free(url); 297 curl_slist_free_all(headers); 298 299 /* load cookies */ 300 curl = curl_easy_init(); 301 if(!curl) { 302 curl_mfprintf(stderr, "curl_easy_init() failed\n"); 303 curl_share_cleanup(share); 304 curl_global_cleanup(); 305 return TEST_ERR_MAJOR_BAD; 306 } 307 url = tutil_suburl(URL, i); 308 headers = sethost(NULL); 309 test_setopt(curl, CURLOPT_HTTPHEADER, headers); 310 test_setopt(curl, CURLOPT_URL, url); 311 curl_mprintf("CURLOPT_SHARE\n"); 312 test_setopt(curl, CURLOPT_SHARE, share); 313 curl_mprintf("CURLOPT_COOKIELIST ALL\n"); 314 test_setopt(curl, CURLOPT_COOKIELIST, "ALL"); 315 curl_mprintf("CURLOPT_COOKIEJAR\n"); 316 test_setopt(curl, CURLOPT_COOKIEFILE, JAR); 317 curl_mprintf("CURLOPT_COOKIELIST RELOAD\n"); 318 test_setopt(curl, CURLOPT_COOKIELIST, "RELOAD"); 319 320 res = CURLE_OK; 321 322 code = curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies); 323 if(code != CURLE_OK) { 324 curl_mfprintf(stderr, "curl_easy_getinfo() failed\n"); 325 res = TEST_ERR_MAJOR_BAD; 326 goto test_cleanup; 327 } 328 curl_mprintf("loaded cookies:\n"); 329 if(!cookies) { 330 curl_mfprintf(stderr, " reloading cookies from '%s' failed\n", JAR); 331 res = TEST_ERR_MAJOR_BAD; 332 goto test_cleanup; 333 } 334 curl_mprintf("-----------------\n"); 335 next_cookie = cookies; 336 while(next_cookie) { 337 curl_mprintf(" %s\n", next_cookie->data); 338 next_cookie = next_cookie->next; 339 } 340 curl_mprintf("-----------------\n"); 341 curl_slist_free_all(cookies); 342 343 /* try to free share, expect to fail because share is in use */ 344 curl_mprintf("try SHARE_CLEANUP...\n"); 345 scode = curl_share_cleanup(share); 346 if(scode == CURLSHE_OK) { 347 curl_mfprintf(stderr, "curl_share_cleanup succeed but error expected\n"); 348 share = NULL; 349 } 350 else { 351 curl_mprintf("SHARE_CLEANUP failed, correct\n"); 352 } 353 354 test_cleanup: 355 356 /* clean up last handle */ 357 curl_mprintf("CLEANUP\n"); 358 curl_easy_cleanup(curl); 359 curl_slist_free_all(headers); 360 curl_free(url); 361 362 /* free share */ 363 curl_mprintf("SHARE_CLEANUP\n"); 364 scode = curl_share_cleanup(share); 365 if(scode != CURLSHE_OK) 366 curl_mfprintf(stderr, "curl_share_cleanup failed, code errno %d\n", 367 (int)scode); 368 369 curl_mprintf("GLOBAL_CLEANUP\n"); 370 curl_global_cleanup(); 371 372 return res; 373 }