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