1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2011, 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 http://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 <stdlib.h> 24#include <ctype.h> 25#include <errno.h> 26 27#include <curl/mprintf.h> 28 29#include "memdebug.h" 30 31static const char *HOSTHEADER = "Host: www.host.foo.com"; 32static const char *JAR = "log/jar506"; 33#define THREADS 2 34 35/* struct containing data of a thread */ 36struct Tdata { 37 CURLSH *share; 38 char *url; 39}; 40 41struct userdata { 42 char *text; 43 int counter; 44}; 45 46/* lock callback */ 47static void my_lock(CURL *handle, curl_lock_data data, curl_lock_access laccess, 48 void *useptr ) 49{ 50 const char *what; 51 struct userdata *user = (struct userdata *)useptr; 52 53 (void)handle; 54 (void)laccess; 55 56 switch ( data ) { 57 case CURL_LOCK_DATA_SHARE: 58 what = "share"; 59 break; 60 case CURL_LOCK_DATA_DNS: 61 what = "dns"; 62 break; 63 case CURL_LOCK_DATA_COOKIE: 64 what = "cookie"; 65 break; 66 default: 67 fprintf(stderr, "lock: no such data: %d\n", (int)data); 68 return; 69 } 70 printf("lock: %-6s [%s]: %d\n", what, user->text, user->counter); 71 user->counter++; 72} 73 74/* unlock callback */ 75static void my_unlock(CURL *handle, curl_lock_data data, void *useptr ) 76{ 77 const char *what; 78 struct userdata *user = (struct userdata *)useptr; 79 (void)handle; 80 switch ( data ) { 81 case CURL_LOCK_DATA_SHARE: 82 what = "share"; 83 break; 84 case CURL_LOCK_DATA_DNS: 85 what = "dns"; 86 break; 87 case CURL_LOCK_DATA_COOKIE: 88 what = "cookie"; 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 99/* build host entry */ 100static struct curl_slist *sethost(struct curl_slist *headers) 101{ 102 (void)headers; 103 return curl_slist_append(NULL, HOSTHEADER ); 104} 105 106 107/* the dummy thread function */ 108static void *fire(void *ptr) 109{ 110 CURLcode code; 111 struct curl_slist *headers; 112 struct Tdata *tdata = (struct Tdata*)ptr; 113 CURL *curl; 114 int i=0; 115 116 if ((curl = curl_easy_init()) == NULL) { 117 fprintf(stderr, "curl_easy_init() failed\n"); 118 return NULL; 119 } 120 121 headers = sethost(NULL); 122 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); 123 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); 124 curl_easy_setopt(curl, CURLOPT_URL, tdata->url); 125 printf( "CURLOPT_SHARE\n" ); 126 curl_easy_setopt(curl, CURLOPT_SHARE, tdata->share); 127 128 printf( "PERFORM\n" ); 129 code = curl_easy_perform(curl); 130 if( code != CURLE_OK ) { 131 fprintf(stderr, "perform url '%s' repeat %d failed, curlcode %d\n", 132 tdata->url, i, (int)code); 133 } 134 135 printf( "CLEANUP\n" ); 136 curl_easy_cleanup(curl); 137 curl_slist_free_all(headers); 138 139 return NULL; 140} 141 142 143/* build request url */ 144static char *suburl(const char *base, int i) 145{ 146 return curl_maprintf("%s%.4d", base, i); 147} 148 149 150/* test function */ 151int test(char *URL) 152{ 153 int res; 154 CURLSHcode scode = CURLSHE_OK; 155 char *url; 156 struct Tdata tdata; 157 CURL *curl; 158 CURLSH *share; 159 struct curl_slist *headers; 160 int i; 161 struct userdata user; 162 163 user.text = (char *)"Pigs in space"; 164 user.counter = 0; 165 166 printf( "GLOBAL_INIT\n" ); 167 if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { 168 fprintf(stderr, "curl_global_init() failed\n"); 169 return TEST_ERR_MAJOR_BAD; 170 } 171 172 /* prepare share */ 173 printf( "SHARE_INIT\n" ); 174 if ((share = curl_share_init()) == NULL) { 175 fprintf(stderr, "curl_share_init() failed\n"); 176 curl_global_cleanup(); 177 return TEST_ERR_MAJOR_BAD; 178 } 179 180 if ( CURLSHE_OK == scode ) { 181 printf( "CURLSHOPT_LOCKFUNC\n" ); 182 scode = curl_share_setopt( share, CURLSHOPT_LOCKFUNC, my_lock); 183 } 184 if ( CURLSHE_OK == scode ) { 185 printf( "CURLSHOPT_UNLOCKFUNC\n" ); 186 scode = curl_share_setopt( share, CURLSHOPT_UNLOCKFUNC, my_unlock); 187 } 188 if ( CURLSHE_OK == scode ) { 189 printf( "CURLSHOPT_USERDATA\n" ); 190 scode = curl_share_setopt( share, CURLSHOPT_USERDATA, &user); 191 } 192 if ( CURLSHE_OK == scode ) { 193 printf( "CURL_LOCK_DATA_COOKIE\n" ); 194 scode = curl_share_setopt( share, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE); 195 } 196 if ( CURLSHE_OK == scode ) { 197 printf( "CURL_LOCK_DATA_DNS\n" ); 198 scode = curl_share_setopt( share, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); 199 } 200 201 if ( CURLSHE_OK != scode ) { 202 fprintf(stderr, "curl_share_setopt() failed\n"); 203 curl_share_cleanup(share); 204 curl_global_cleanup(); 205 return TEST_ERR_MAJOR_BAD; 206 } 207 208 209 res = 0; 210 211 /* start treads */ 212 for (i=1; i<=THREADS; i++ ) { 213 214 /* set thread data */ 215 tdata.url = suburl( URL, i ); /* must be curl_free()d */ 216 tdata.share = share; 217 218 /* simulate thread, direct call of "thread" function */ 219 printf( "*** run %d\n",i ); 220 fire( &tdata ); 221 222 curl_free( tdata.url ); 223 224 } 225 226 227 /* fetch a another one and save cookies */ 228 printf( "*** run %d\n", i ); 229 if ((curl = curl_easy_init()) == NULL) { 230 fprintf(stderr, "curl_easy_init() failed\n"); 231 curl_share_cleanup(share); 232 curl_global_cleanup(); 233 return TEST_ERR_MAJOR_BAD; 234 } 235 236 url = suburl( URL, i ); 237 headers = sethost( NULL ); 238 test_setopt( curl, CURLOPT_HTTPHEADER, headers ); 239 test_setopt( curl, CURLOPT_URL, url ); 240 printf( "CURLOPT_SHARE\n" ); 241 test_setopt( curl, CURLOPT_SHARE, share ); 242 printf( "CURLOPT_COOKIEJAR\n" ); 243 test_setopt( curl, CURLOPT_COOKIEJAR, JAR ); 244 245 printf( "PERFORM\n" ); 246 curl_easy_perform( curl ); 247 248 /* try to free share, expect to fail because share is in use*/ 249 printf( "try SHARE_CLEANUP...\n" ); 250 scode = curl_share_cleanup( share ); 251 if ( scode==CURLSHE_OK ) 252 { 253 fprintf(stderr, "curl_share_cleanup succeed but error expected\n"); 254 share = NULL; 255 } else { 256 printf( "SHARE_CLEANUP failed, correct\n" ); 257 } 258 259test_cleanup: 260 261 /* clean up last handle */ 262 printf( "CLEANUP\n" ); 263 curl_easy_cleanup( curl ); 264 curl_slist_free_all( headers ); 265 266 curl_free(url); 267 268 /* free share */ 269 printf( "SHARE_CLEANUP\n" ); 270 scode = curl_share_cleanup( share ); 271 if ( scode!=CURLSHE_OK ) 272 fprintf(stderr, "curl_share_cleanup failed, code errno %d\n", 273 (int)scode); 274 275 printf( "GLOBAL_CLEANUP\n" ); 276 curl_global_cleanup(); 277 278 return res; 279} 280 281