1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2016, 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 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 int i=0; 103 104 if((curl = curl_easy_init()) == NULL) { 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 fprintf(stderr, "perform url '%s' repeat %d failed, curlcode %d\n", 119 tdata->url, i, (int)code); 120 } 121 122 printf("CLEANUP\n"); 123 curl_easy_cleanup(curl); 124 125 return NULL; 126 } 127 128 /* test function */ 129 int test(char *URL) 130 { 131 int res; 132 CURLSHcode scode = CURLSHE_OK; 133 char *url; 134 struct Tdata tdata; 135 CURL *curl; 136 CURLSH *share; 137 int i; 138 struct userdata user; 139 140 user.text = (char *)"Pigs in space"; 141 user.counter = 0; 142 143 printf("GLOBAL_INIT\n"); 144 if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { 145 fprintf(stderr, "curl_global_init() failed\n"); 146 return TEST_ERR_MAJOR_BAD; 147 } 148 149 /* prepare share */ 150 printf("SHARE_INIT\n"); 151 if((share = curl_share_init()) == NULL) { 152 fprintf(stderr, "curl_share_init() failed\n"); 153 curl_global_cleanup(); 154 return TEST_ERR_MAJOR_BAD; 155 } 156 157 if(CURLSHE_OK == scode) { 158 printf("CURLSHOPT_LOCKFUNC\n"); 159 scode = curl_share_setopt(share, CURLSHOPT_LOCKFUNC, my_lock); 160 } 161 if(CURLSHE_OK == scode) { 162 printf("CURLSHOPT_UNLOCKFUNC\n"); 163 scode = curl_share_setopt(share, CURLSHOPT_UNLOCKFUNC, my_unlock); 164 } 165 if(CURLSHE_OK == scode) { 166 printf("CURLSHOPT_USERDATA\n"); 167 scode = curl_share_setopt(share, CURLSHOPT_USERDATA, &user); 168 } 169 if(CURLSHE_OK == scode) { 170 printf("CURL_LOCK_DATA_SSL_SESSION\n"); 171 scode = curl_share_setopt(share, CURLSHOPT_SHARE, 172 CURL_LOCK_DATA_SSL_SESSION); 173 } 174 175 if(CURLSHE_OK != scode) { 176 fprintf(stderr, "curl_share_setopt() failed\n"); 177 curl_share_cleanup(share); 178 curl_global_cleanup(); 179 return TEST_ERR_MAJOR_BAD; 180 } 181 182 183 res = 0; 184 185 /* start treads */ 186 for(i=1; i<=THREADS; i++) { 187 188 /* set thread data */ 189 tdata.url = URL; 190 tdata.share = share; 191 192 /* simulate thread, direct call of "thread" function */ 193 printf("*** run %d\n",i); 194 fire(&tdata); 195 } 196 197 198 /* fetch a another one */ 199 printf("*** run %d\n", i); 200 if((curl = curl_easy_init()) == NULL) { 201 fprintf(stderr, "curl_easy_init() failed\n"); 202 curl_share_cleanup(share); 203 curl_global_cleanup(); 204 return TEST_ERR_MAJOR_BAD; 205 } 206 207 url = URL; 208 test_setopt(curl, CURLOPT_URL, url); 209 printf("CURLOPT_SHARE\n"); 210 test_setopt(curl, CURLOPT_SHARE, share); 211 212 printf("PERFORM\n"); 213 curl_easy_perform(curl); 214 215 /* try to free share, expect to fail because share is in use*/ 216 printf("try SHARE_CLEANUP...\n"); 217 scode = curl_share_cleanup(share); 218 if(scode==CURLSHE_OK) { 219 fprintf(stderr, "curl_share_cleanup succeed but error expected\n"); 220 share = NULL; 221 } 222 else { 223 printf("SHARE_CLEANUP failed, correct\n"); 224 } 225 226 test_cleanup: 227 228 /* clean up last handle */ 229 printf("CLEANUP\n"); 230 curl_easy_cleanup(curl); 231 232 /* free share */ 233 printf("SHARE_CLEANUP\n"); 234 scode = curl_share_cleanup(share); 235 if(scode!=CURLSHE_OK) 236 fprintf(stderr, "curl_share_cleanup failed, code errno %d\n", 237 (int)scode); 238 239 printf("GLOBAL_CLEANUP\n"); 240 curl_global_cleanup(); 241 242 return res; 243 } 244 245