1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker * _ _ ____ _
3*6236dae4SAndroid Build Coastguard Worker * Project ___| | | | _ \| |
4*6236dae4SAndroid Build Coastguard Worker * / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker * | (__| |_| | _ <| |___
6*6236dae4SAndroid Build Coastguard Worker * \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker *
8*6236dae4SAndroid Build Coastguard Worker * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker *
10*6236dae4SAndroid Build Coastguard Worker * This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker * you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker * are also available at https://curl.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker *
14*6236dae4SAndroid Build Coastguard Worker * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker * copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker * furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker *
18*6236dae4SAndroid Build Coastguard Worker * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker * KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker *
21*6236dae4SAndroid Build Coastguard Worker * SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker *
23*6236dae4SAndroid Build Coastguard Worker ***************************************************************************/
24*6236dae4SAndroid Build Coastguard Worker #include "test.h"
25*6236dae4SAndroid Build Coastguard Worker #include "testutil.h"
26*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
27*6236dae4SAndroid Build Coastguard Worker
28*6236dae4SAndroid Build Coastguard Worker #include <stdio.h>
29*6236dae4SAndroid Build Coastguard Worker
30*6236dae4SAndroid Build Coastguard Worker #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
31*6236dae4SAndroid Build Coastguard Worker #if defined(USE_THREADS_POSIX)
32*6236dae4SAndroid Build Coastguard Worker #include <pthread.h>
33*6236dae4SAndroid Build Coastguard Worker #endif
34*6236dae4SAndroid Build Coastguard Worker #include "curl_threads.h"
35*6236dae4SAndroid Build Coastguard Worker #endif
36*6236dae4SAndroid Build Coastguard Worker
37*6236dae4SAndroid Build Coastguard Worker #define CAINFO libtest_arg2
38*6236dae4SAndroid Build Coastguard Worker #define THREAD_SIZE 16
39*6236dae4SAndroid Build Coastguard Worker #define PER_THREAD_SIZE 8
40*6236dae4SAndroid Build Coastguard Worker
41*6236dae4SAndroid Build Coastguard Worker struct Ctx {
42*6236dae4SAndroid Build Coastguard Worker const char *URL;
43*6236dae4SAndroid Build Coastguard Worker CURLSH *share;
44*6236dae4SAndroid Build Coastguard Worker int result;
45*6236dae4SAndroid Build Coastguard Worker int thread_id;
46*6236dae4SAndroid Build Coastguard Worker struct curl_slist *contents;
47*6236dae4SAndroid Build Coastguard Worker };
48*6236dae4SAndroid Build Coastguard Worker
write_memory_callback(char * contents,size_t size,size_t nmemb,void * userp)49*6236dae4SAndroid Build Coastguard Worker static size_t write_memory_callback(char *contents, size_t size,
50*6236dae4SAndroid Build Coastguard Worker size_t nmemb, void *userp)
51*6236dae4SAndroid Build Coastguard Worker {
52*6236dae4SAndroid Build Coastguard Worker /* append the data to contents */
53*6236dae4SAndroid Build Coastguard Worker size_t realsize = size * nmemb;
54*6236dae4SAndroid Build Coastguard Worker struct Ctx *mem = (struct Ctx *)userp;
55*6236dae4SAndroid Build Coastguard Worker char *data = (char *)malloc(realsize + 1);
56*6236dae4SAndroid Build Coastguard Worker struct curl_slist *item_append = NULL;
57*6236dae4SAndroid Build Coastguard Worker if(!data) {
58*6236dae4SAndroid Build Coastguard Worker printf("not enough memory (malloc returned NULL)\n");
59*6236dae4SAndroid Build Coastguard Worker return 0;
60*6236dae4SAndroid Build Coastguard Worker }
61*6236dae4SAndroid Build Coastguard Worker memcpy(data, contents, realsize);
62*6236dae4SAndroid Build Coastguard Worker data[realsize] = '\0';
63*6236dae4SAndroid Build Coastguard Worker item_append = curl_slist_append(mem->contents, data);
64*6236dae4SAndroid Build Coastguard Worker free(data);
65*6236dae4SAndroid Build Coastguard Worker if(item_append) {
66*6236dae4SAndroid Build Coastguard Worker mem->contents = item_append;
67*6236dae4SAndroid Build Coastguard Worker }
68*6236dae4SAndroid Build Coastguard Worker else {
69*6236dae4SAndroid Build Coastguard Worker printf("not enough memory (curl_slist_append returned NULL)\n");
70*6236dae4SAndroid Build Coastguard Worker return 0;
71*6236dae4SAndroid Build Coastguard Worker }
72*6236dae4SAndroid Build Coastguard Worker return realsize;
73*6236dae4SAndroid Build Coastguard Worker }
74*6236dae4SAndroid Build Coastguard Worker
75*6236dae4SAndroid Build Coastguard Worker static
76*6236dae4SAndroid Build Coastguard Worker #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
77*6236dae4SAndroid Build Coastguard Worker #if defined(_WIN32_WCE) || defined(CURL_WINDOWS_UWP)
78*6236dae4SAndroid Build Coastguard Worker DWORD
79*6236dae4SAndroid Build Coastguard Worker #else
80*6236dae4SAndroid Build Coastguard Worker unsigned int
81*6236dae4SAndroid Build Coastguard Worker #endif
82*6236dae4SAndroid Build Coastguard Worker CURL_STDCALL
83*6236dae4SAndroid Build Coastguard Worker #else
84*6236dae4SAndroid Build Coastguard Worker unsigned int
85*6236dae4SAndroid Build Coastguard Worker #endif
test_thread(void * ptr)86*6236dae4SAndroid Build Coastguard Worker test_thread(void *ptr)
87*6236dae4SAndroid Build Coastguard Worker {
88*6236dae4SAndroid Build Coastguard Worker struct Ctx *ctx = (struct Ctx *)ptr;
89*6236dae4SAndroid Build Coastguard Worker CURLcode res = CURLE_OK;
90*6236dae4SAndroid Build Coastguard Worker
91*6236dae4SAndroid Build Coastguard Worker int i;
92*6236dae4SAndroid Build Coastguard Worker
93*6236dae4SAndroid Build Coastguard Worker /* Loop the transfer and cleanup the handle properly every lap. This will
94*6236dae4SAndroid Build Coastguard Worker still reuse ssl session since the pool is in the shared object! */
95*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < PER_THREAD_SIZE; i++) {
96*6236dae4SAndroid Build Coastguard Worker CURL *curl = curl_easy_init();
97*6236dae4SAndroid Build Coastguard Worker if(curl) {
98*6236dae4SAndroid Build Coastguard Worker curl_easy_setopt(curl, CURLOPT_URL, (char *)ctx->URL);
99*6236dae4SAndroid Build Coastguard Worker
100*6236dae4SAndroid Build Coastguard Worker /* use the share object */
101*6236dae4SAndroid Build Coastguard Worker curl_easy_setopt(curl, CURLOPT_SHARE, ctx->share);
102*6236dae4SAndroid Build Coastguard Worker curl_easy_setopt(curl, CURLOPT_CAINFO, CAINFO);
103*6236dae4SAndroid Build Coastguard Worker
104*6236dae4SAndroid Build Coastguard Worker curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_memory_callback);
105*6236dae4SAndroid Build Coastguard Worker curl_easy_setopt(curl, CURLOPT_WRITEDATA, ptr);
106*6236dae4SAndroid Build Coastguard Worker curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
107*6236dae4SAndroid Build Coastguard Worker
108*6236dae4SAndroid Build Coastguard Worker /* Perform the request, res will get the return code */
109*6236dae4SAndroid Build Coastguard Worker res = curl_easy_perform(curl);
110*6236dae4SAndroid Build Coastguard Worker
111*6236dae4SAndroid Build Coastguard Worker /* always cleanup */
112*6236dae4SAndroid Build Coastguard Worker curl_easy_cleanup(curl);
113*6236dae4SAndroid Build Coastguard Worker /* Check for errors */
114*6236dae4SAndroid Build Coastguard Worker if(res != CURLE_OK) {
115*6236dae4SAndroid Build Coastguard Worker fprintf(stderr, "curl_easy_perform() failed: %s\n",
116*6236dae4SAndroid Build Coastguard Worker curl_easy_strerror(res));
117*6236dae4SAndroid Build Coastguard Worker goto test_cleanup;
118*6236dae4SAndroid Build Coastguard Worker }
119*6236dae4SAndroid Build Coastguard Worker }
120*6236dae4SAndroid Build Coastguard Worker }
121*6236dae4SAndroid Build Coastguard Worker
122*6236dae4SAndroid Build Coastguard Worker test_cleanup:
123*6236dae4SAndroid Build Coastguard Worker ctx->result = (int)res;
124*6236dae4SAndroid Build Coastguard Worker return 0;
125*6236dae4SAndroid Build Coastguard Worker }
126*6236dae4SAndroid Build Coastguard Worker
127*6236dae4SAndroid Build Coastguard Worker #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
128*6236dae4SAndroid Build Coastguard Worker
test_lock(CURL * handle,curl_lock_data data,curl_lock_access laccess,void * useptr)129*6236dae4SAndroid Build Coastguard Worker static void test_lock(CURL *handle, curl_lock_data data,
130*6236dae4SAndroid Build Coastguard Worker curl_lock_access laccess, void *useptr)
131*6236dae4SAndroid Build Coastguard Worker {
132*6236dae4SAndroid Build Coastguard Worker curl_mutex_t *mutexes = (curl_mutex_t*) useptr;
133*6236dae4SAndroid Build Coastguard Worker (void)handle;
134*6236dae4SAndroid Build Coastguard Worker (void)laccess;
135*6236dae4SAndroid Build Coastguard Worker Curl_mutex_acquire(&mutexes[data]);
136*6236dae4SAndroid Build Coastguard Worker }
137*6236dae4SAndroid Build Coastguard Worker
test_unlock(CURL * handle,curl_lock_data data,void * useptr)138*6236dae4SAndroid Build Coastguard Worker static void test_unlock(CURL *handle, curl_lock_data data, void *useptr)
139*6236dae4SAndroid Build Coastguard Worker {
140*6236dae4SAndroid Build Coastguard Worker curl_mutex_t *mutexes = (curl_mutex_t*) useptr;
141*6236dae4SAndroid Build Coastguard Worker (void)handle;
142*6236dae4SAndroid Build Coastguard Worker Curl_mutex_release(&mutexes[data]);
143*6236dae4SAndroid Build Coastguard Worker }
144*6236dae4SAndroid Build Coastguard Worker
execute(CURLSH * share,struct Ctx * ctx)145*6236dae4SAndroid Build Coastguard Worker static void execute(CURLSH *share, struct Ctx *ctx)
146*6236dae4SAndroid Build Coastguard Worker {
147*6236dae4SAndroid Build Coastguard Worker int i;
148*6236dae4SAndroid Build Coastguard Worker curl_mutex_t mutexes[CURL_LOCK_DATA_LAST - 1];
149*6236dae4SAndroid Build Coastguard Worker curl_thread_t thread[THREAD_SIZE];
150*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < CURL_LOCK_DATA_LAST - 1; i++) {
151*6236dae4SAndroid Build Coastguard Worker Curl_mutex_init(&mutexes[i]);
152*6236dae4SAndroid Build Coastguard Worker }
153*6236dae4SAndroid Build Coastguard Worker curl_share_setopt(share, CURLSHOPT_LOCKFUNC, test_lock);
154*6236dae4SAndroid Build Coastguard Worker curl_share_setopt(share, CURLSHOPT_UNLOCKFUNC, test_unlock);
155*6236dae4SAndroid Build Coastguard Worker curl_share_setopt(share, CURLSHOPT_USERDATA, (void *)mutexes);
156*6236dae4SAndroid Build Coastguard Worker curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
157*6236dae4SAndroid Build Coastguard Worker
158*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < THREAD_SIZE; i++) {
159*6236dae4SAndroid Build Coastguard Worker thread[i] = Curl_thread_create(test_thread, (void *)&ctx[i]);
160*6236dae4SAndroid Build Coastguard Worker }
161*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < THREAD_SIZE; i++) {
162*6236dae4SAndroid Build Coastguard Worker if(thread[i]) {
163*6236dae4SAndroid Build Coastguard Worker Curl_thread_join(&thread[i]);
164*6236dae4SAndroid Build Coastguard Worker Curl_thread_destroy(thread[i]);
165*6236dae4SAndroid Build Coastguard Worker }
166*6236dae4SAndroid Build Coastguard Worker }
167*6236dae4SAndroid Build Coastguard Worker curl_share_setopt(share, CURLSHOPT_LOCKFUNC, NULL);
168*6236dae4SAndroid Build Coastguard Worker curl_share_setopt(share, CURLSHOPT_UNLOCKFUNC, NULL);
169*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < CURL_LOCK_DATA_LAST - 1; i++) {
170*6236dae4SAndroid Build Coastguard Worker Curl_mutex_destroy(&mutexes[i]);
171*6236dae4SAndroid Build Coastguard Worker }
172*6236dae4SAndroid Build Coastguard Worker }
173*6236dae4SAndroid Build Coastguard Worker
174*6236dae4SAndroid Build Coastguard Worker #else /* without pthread, run serially */
175*6236dae4SAndroid Build Coastguard Worker
execute(CURLSH * share,struct Ctx * ctx)176*6236dae4SAndroid Build Coastguard Worker static void execute(CURLSH *share, struct Ctx *ctx)
177*6236dae4SAndroid Build Coastguard Worker {
178*6236dae4SAndroid Build Coastguard Worker int i;
179*6236dae4SAndroid Build Coastguard Worker (void) share;
180*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < THREAD_SIZE; i++) {
181*6236dae4SAndroid Build Coastguard Worker test_thread((void *)&ctx[i]);
182*6236dae4SAndroid Build Coastguard Worker }
183*6236dae4SAndroid Build Coastguard Worker }
184*6236dae4SAndroid Build Coastguard Worker
185*6236dae4SAndroid Build Coastguard Worker #endif
186*6236dae4SAndroid Build Coastguard Worker
test(char * URL)187*6236dae4SAndroid Build Coastguard Worker CURLcode test(char *URL)
188*6236dae4SAndroid Build Coastguard Worker {
189*6236dae4SAndroid Build Coastguard Worker int res = 0;
190*6236dae4SAndroid Build Coastguard Worker int i;
191*6236dae4SAndroid Build Coastguard Worker CURLSH* share;
192*6236dae4SAndroid Build Coastguard Worker struct Ctx ctx[THREAD_SIZE];
193*6236dae4SAndroid Build Coastguard Worker
194*6236dae4SAndroid Build Coastguard Worker curl_global_init(CURL_GLOBAL_ALL);
195*6236dae4SAndroid Build Coastguard Worker
196*6236dae4SAndroid Build Coastguard Worker share = curl_share_init();
197*6236dae4SAndroid Build Coastguard Worker if(!share) {
198*6236dae4SAndroid Build Coastguard Worker fprintf(stderr, "curl_share_init() failed\n");
199*6236dae4SAndroid Build Coastguard Worker goto test_cleanup;
200*6236dae4SAndroid Build Coastguard Worker }
201*6236dae4SAndroid Build Coastguard Worker
202*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < THREAD_SIZE; i++) {
203*6236dae4SAndroid Build Coastguard Worker ctx[i].share = share;
204*6236dae4SAndroid Build Coastguard Worker ctx[i].URL = URL;
205*6236dae4SAndroid Build Coastguard Worker ctx[i].thread_id = i;
206*6236dae4SAndroid Build Coastguard Worker ctx[i].result = 0;
207*6236dae4SAndroid Build Coastguard Worker ctx[i].contents = NULL;
208*6236dae4SAndroid Build Coastguard Worker }
209*6236dae4SAndroid Build Coastguard Worker
210*6236dae4SAndroid Build Coastguard Worker execute(share, ctx);
211*6236dae4SAndroid Build Coastguard Worker
212*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < THREAD_SIZE; i++) {
213*6236dae4SAndroid Build Coastguard Worker if(ctx[i].result) {
214*6236dae4SAndroid Build Coastguard Worker res = ctx[i].result;
215*6236dae4SAndroid Build Coastguard Worker }
216*6236dae4SAndroid Build Coastguard Worker else {
217*6236dae4SAndroid Build Coastguard Worker struct curl_slist *item = ctx[i].contents;
218*6236dae4SAndroid Build Coastguard Worker while(item) {
219*6236dae4SAndroid Build Coastguard Worker printf("%s", item->data);
220*6236dae4SAndroid Build Coastguard Worker item = item->next;
221*6236dae4SAndroid Build Coastguard Worker }
222*6236dae4SAndroid Build Coastguard Worker }
223*6236dae4SAndroid Build Coastguard Worker curl_slist_free_all(ctx[i].contents);
224*6236dae4SAndroid Build Coastguard Worker }
225*6236dae4SAndroid Build Coastguard Worker
226*6236dae4SAndroid Build Coastguard Worker test_cleanup:
227*6236dae4SAndroid Build Coastguard Worker if(share)
228*6236dae4SAndroid Build Coastguard Worker curl_share_cleanup(share);
229*6236dae4SAndroid Build Coastguard Worker curl_global_cleanup();
230*6236dae4SAndroid Build Coastguard Worker return (CURLcode)res;
231*6236dae4SAndroid Build Coastguard Worker }
232