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