113498266Sopenharmony_ci/*************************************************************************** 213498266Sopenharmony_ci * _ _ ____ _ 313498266Sopenharmony_ci * Project ___| | | | _ \| | 413498266Sopenharmony_ci * / __| | | | |_) | | 513498266Sopenharmony_ci * | (__| |_| | _ <| |___ 613498266Sopenharmony_ci * \___|\___/|_| \_\_____| 713498266Sopenharmony_ci * 813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 913498266Sopenharmony_ci * 1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which 1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms 1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html. 1313498266Sopenharmony_ci * 1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell 1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is 1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file. 1713498266Sopenharmony_ci * 1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 1913498266Sopenharmony_ci * KIND, either express or implied. 2013498266Sopenharmony_ci * 2113498266Sopenharmony_ci * SPDX-License-Identifier: curl 2213498266Sopenharmony_ci * 2313498266Sopenharmony_ci ***************************************************************************/ 2413498266Sopenharmony_ci#include "test.h" 2513498266Sopenharmony_ci#include "memdebug.h" 2613498266Sopenharmony_ci 2713498266Sopenharmony_ci#define THREADS 2 2813498266Sopenharmony_ci 2913498266Sopenharmony_ci/* struct containing data of a thread */ 3013498266Sopenharmony_cistruct Tdata { 3113498266Sopenharmony_ci CURLSH *share; 3213498266Sopenharmony_ci char *url; 3313498266Sopenharmony_ci}; 3413498266Sopenharmony_ci 3513498266Sopenharmony_cistruct userdata { 3613498266Sopenharmony_ci const char *text; 3713498266Sopenharmony_ci int counter; 3813498266Sopenharmony_ci}; 3913498266Sopenharmony_ci 4013498266Sopenharmony_ci/* lock callback */ 4113498266Sopenharmony_cistatic void my_lock(CURL *handle, curl_lock_data data, 4213498266Sopenharmony_ci curl_lock_access laccess, void *useptr) 4313498266Sopenharmony_ci{ 4413498266Sopenharmony_ci const char *what; 4513498266Sopenharmony_ci struct userdata *user = (struct userdata *)useptr; 4613498266Sopenharmony_ci 4713498266Sopenharmony_ci (void)handle; 4813498266Sopenharmony_ci (void)laccess; 4913498266Sopenharmony_ci 5013498266Sopenharmony_ci switch(data) { 5113498266Sopenharmony_ci case CURL_LOCK_DATA_SHARE: 5213498266Sopenharmony_ci what = "share"; 5313498266Sopenharmony_ci break; 5413498266Sopenharmony_ci case CURL_LOCK_DATA_DNS: 5513498266Sopenharmony_ci what = "dns"; 5613498266Sopenharmony_ci break; 5713498266Sopenharmony_ci case CURL_LOCK_DATA_COOKIE: 5813498266Sopenharmony_ci what = "cookie"; 5913498266Sopenharmony_ci break; 6013498266Sopenharmony_ci case CURL_LOCK_DATA_SSL_SESSION: 6113498266Sopenharmony_ci what = "ssl_session"; 6213498266Sopenharmony_ci break; 6313498266Sopenharmony_ci default: 6413498266Sopenharmony_ci fprintf(stderr, "lock: no such data: %d\n", (int)data); 6513498266Sopenharmony_ci return; 6613498266Sopenharmony_ci } 6713498266Sopenharmony_ci printf("lock: %-6s [%s]: %d\n", what, user->text, user->counter); 6813498266Sopenharmony_ci user->counter++; 6913498266Sopenharmony_ci} 7013498266Sopenharmony_ci 7113498266Sopenharmony_ci/* unlock callback */ 7213498266Sopenharmony_cistatic void my_unlock(CURL *handle, curl_lock_data data, void *useptr) 7313498266Sopenharmony_ci{ 7413498266Sopenharmony_ci const char *what; 7513498266Sopenharmony_ci struct userdata *user = (struct userdata *)useptr; 7613498266Sopenharmony_ci (void)handle; 7713498266Sopenharmony_ci switch(data) { 7813498266Sopenharmony_ci case CURL_LOCK_DATA_SHARE: 7913498266Sopenharmony_ci what = "share"; 8013498266Sopenharmony_ci break; 8113498266Sopenharmony_ci case CURL_LOCK_DATA_DNS: 8213498266Sopenharmony_ci what = "dns"; 8313498266Sopenharmony_ci break; 8413498266Sopenharmony_ci case CURL_LOCK_DATA_COOKIE: 8513498266Sopenharmony_ci what = "cookie"; 8613498266Sopenharmony_ci break; 8713498266Sopenharmony_ci case CURL_LOCK_DATA_SSL_SESSION: 8813498266Sopenharmony_ci what = "ssl_session"; 8913498266Sopenharmony_ci break; 9013498266Sopenharmony_ci default: 9113498266Sopenharmony_ci fprintf(stderr, "unlock: no such data: %d\n", (int)data); 9213498266Sopenharmony_ci return; 9313498266Sopenharmony_ci } 9413498266Sopenharmony_ci printf("unlock: %-6s [%s]: %d\n", what, user->text, user->counter); 9513498266Sopenharmony_ci user->counter++; 9613498266Sopenharmony_ci} 9713498266Sopenharmony_ci 9813498266Sopenharmony_ci/* the dummy thread function */ 9913498266Sopenharmony_cistatic void *fire(void *ptr) 10013498266Sopenharmony_ci{ 10113498266Sopenharmony_ci CURLcode code; 10213498266Sopenharmony_ci struct Tdata *tdata = (struct Tdata*)ptr; 10313498266Sopenharmony_ci CURL *curl; 10413498266Sopenharmony_ci 10513498266Sopenharmony_ci curl = curl_easy_init(); 10613498266Sopenharmony_ci if(!curl) { 10713498266Sopenharmony_ci fprintf(stderr, "curl_easy_init() failed\n"); 10813498266Sopenharmony_ci return NULL; 10913498266Sopenharmony_ci } 11013498266Sopenharmony_ci 11113498266Sopenharmony_ci curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); 11213498266Sopenharmony_ci curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); 11313498266Sopenharmony_ci curl_easy_setopt(curl, CURLOPT_URL, tdata->url); 11413498266Sopenharmony_ci printf("CURLOPT_SHARE\n"); 11513498266Sopenharmony_ci curl_easy_setopt(curl, CURLOPT_SHARE, tdata->share); 11613498266Sopenharmony_ci 11713498266Sopenharmony_ci printf("PERFORM\n"); 11813498266Sopenharmony_ci code = curl_easy_perform(curl); 11913498266Sopenharmony_ci if(code != CURLE_OK) { 12013498266Sopenharmony_ci int i = 0; 12113498266Sopenharmony_ci fprintf(stderr, "perform url '%s' repeat %d failed, curlcode %d\n", 12213498266Sopenharmony_ci tdata->url, i, (int)code); 12313498266Sopenharmony_ci } 12413498266Sopenharmony_ci 12513498266Sopenharmony_ci printf("CLEANUP\n"); 12613498266Sopenharmony_ci curl_easy_cleanup(curl); 12713498266Sopenharmony_ci 12813498266Sopenharmony_ci return NULL; 12913498266Sopenharmony_ci} 13013498266Sopenharmony_ci 13113498266Sopenharmony_ci/* test function */ 13213498266Sopenharmony_ciint test(char *URL) 13313498266Sopenharmony_ci{ 13413498266Sopenharmony_ci CURLcode res = CURLE_OK; 13513498266Sopenharmony_ci CURLSHcode scode = CURLSHE_OK; 13613498266Sopenharmony_ci char *url; 13713498266Sopenharmony_ci struct Tdata tdata; 13813498266Sopenharmony_ci CURL *curl; 13913498266Sopenharmony_ci CURLSH *share; 14013498266Sopenharmony_ci int i; 14113498266Sopenharmony_ci struct userdata user; 14213498266Sopenharmony_ci 14313498266Sopenharmony_ci user.text = "Pigs in space"; 14413498266Sopenharmony_ci user.counter = 0; 14513498266Sopenharmony_ci 14613498266Sopenharmony_ci printf("GLOBAL_INIT\n"); 14713498266Sopenharmony_ci if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { 14813498266Sopenharmony_ci fprintf(stderr, "curl_global_init() failed\n"); 14913498266Sopenharmony_ci return TEST_ERR_MAJOR_BAD; 15013498266Sopenharmony_ci } 15113498266Sopenharmony_ci 15213498266Sopenharmony_ci /* prepare share */ 15313498266Sopenharmony_ci printf("SHARE_INIT\n"); 15413498266Sopenharmony_ci share = curl_share_init(); 15513498266Sopenharmony_ci if(!share) { 15613498266Sopenharmony_ci fprintf(stderr, "curl_share_init() failed\n"); 15713498266Sopenharmony_ci curl_global_cleanup(); 15813498266Sopenharmony_ci return TEST_ERR_MAJOR_BAD; 15913498266Sopenharmony_ci } 16013498266Sopenharmony_ci 16113498266Sopenharmony_ci if(CURLSHE_OK == scode) { 16213498266Sopenharmony_ci printf("CURLSHOPT_LOCKFUNC\n"); 16313498266Sopenharmony_ci scode = curl_share_setopt(share, CURLSHOPT_LOCKFUNC, my_lock); 16413498266Sopenharmony_ci } 16513498266Sopenharmony_ci if(CURLSHE_OK == scode) { 16613498266Sopenharmony_ci printf("CURLSHOPT_UNLOCKFUNC\n"); 16713498266Sopenharmony_ci scode = curl_share_setopt(share, CURLSHOPT_UNLOCKFUNC, my_unlock); 16813498266Sopenharmony_ci } 16913498266Sopenharmony_ci if(CURLSHE_OK == scode) { 17013498266Sopenharmony_ci printf("CURLSHOPT_USERDATA\n"); 17113498266Sopenharmony_ci scode = curl_share_setopt(share, CURLSHOPT_USERDATA, &user); 17213498266Sopenharmony_ci } 17313498266Sopenharmony_ci if(CURLSHE_OK == scode) { 17413498266Sopenharmony_ci printf("CURL_LOCK_DATA_SSL_SESSION\n"); 17513498266Sopenharmony_ci scode = curl_share_setopt(share, CURLSHOPT_SHARE, 17613498266Sopenharmony_ci CURL_LOCK_DATA_SSL_SESSION); 17713498266Sopenharmony_ci } 17813498266Sopenharmony_ci 17913498266Sopenharmony_ci if(CURLSHE_OK != scode) { 18013498266Sopenharmony_ci fprintf(stderr, "curl_share_setopt() failed\n"); 18113498266Sopenharmony_ci curl_share_cleanup(share); 18213498266Sopenharmony_ci curl_global_cleanup(); 18313498266Sopenharmony_ci return TEST_ERR_MAJOR_BAD; 18413498266Sopenharmony_ci } 18513498266Sopenharmony_ci 18613498266Sopenharmony_ci 18713498266Sopenharmony_ci /* start treads */ 18813498266Sopenharmony_ci for(i = 1; i <= THREADS; i++) { 18913498266Sopenharmony_ci 19013498266Sopenharmony_ci /* set thread data */ 19113498266Sopenharmony_ci tdata.url = URL; 19213498266Sopenharmony_ci tdata.share = share; 19313498266Sopenharmony_ci 19413498266Sopenharmony_ci /* simulate thread, direct call of "thread" function */ 19513498266Sopenharmony_ci printf("*** run %d\n",i); 19613498266Sopenharmony_ci fire(&tdata); 19713498266Sopenharmony_ci } 19813498266Sopenharmony_ci 19913498266Sopenharmony_ci 20013498266Sopenharmony_ci /* fetch a another one */ 20113498266Sopenharmony_ci printf("*** run %d\n", i); 20213498266Sopenharmony_ci curl = curl_easy_init(); 20313498266Sopenharmony_ci if(!curl) { 20413498266Sopenharmony_ci fprintf(stderr, "curl_easy_init() failed\n"); 20513498266Sopenharmony_ci curl_share_cleanup(share); 20613498266Sopenharmony_ci curl_global_cleanup(); 20713498266Sopenharmony_ci return TEST_ERR_MAJOR_BAD; 20813498266Sopenharmony_ci } 20913498266Sopenharmony_ci 21013498266Sopenharmony_ci url = URL; 21113498266Sopenharmony_ci test_setopt(curl, CURLOPT_URL, url); 21213498266Sopenharmony_ci printf("CURLOPT_SHARE\n"); 21313498266Sopenharmony_ci test_setopt(curl, CURLOPT_SHARE, share); 21413498266Sopenharmony_ci 21513498266Sopenharmony_ci printf("PERFORM\n"); 21613498266Sopenharmony_ci res = curl_easy_perform(curl); 21713498266Sopenharmony_ci 21813498266Sopenharmony_ci /* try to free share, expect to fail because share is in use */ 21913498266Sopenharmony_ci printf("try SHARE_CLEANUP...\n"); 22013498266Sopenharmony_ci scode = curl_share_cleanup(share); 22113498266Sopenharmony_ci if(scode == CURLSHE_OK) { 22213498266Sopenharmony_ci fprintf(stderr, "curl_share_cleanup succeed but error expected\n"); 22313498266Sopenharmony_ci share = NULL; 22413498266Sopenharmony_ci } 22513498266Sopenharmony_ci else { 22613498266Sopenharmony_ci printf("SHARE_CLEANUP failed, correct\n"); 22713498266Sopenharmony_ci } 22813498266Sopenharmony_ci 22913498266Sopenharmony_citest_cleanup: 23013498266Sopenharmony_ci 23113498266Sopenharmony_ci /* clean up last handle */ 23213498266Sopenharmony_ci printf("CLEANUP\n"); 23313498266Sopenharmony_ci curl_easy_cleanup(curl); 23413498266Sopenharmony_ci 23513498266Sopenharmony_ci /* free share */ 23613498266Sopenharmony_ci printf("SHARE_CLEANUP\n"); 23713498266Sopenharmony_ci scode = curl_share_cleanup(share); 23813498266Sopenharmony_ci if(scode != CURLSHE_OK) 23913498266Sopenharmony_ci fprintf(stderr, "curl_share_cleanup failed, code errno %d\n", 24013498266Sopenharmony_ci (int)scode); 24113498266Sopenharmony_ci 24213498266Sopenharmony_ci printf("GLOBAL_CLEANUP\n"); 24313498266Sopenharmony_ci curl_global_cleanup(); 24413498266Sopenharmony_ci 24513498266Sopenharmony_ci return res; 24613498266Sopenharmony_ci} 247