1 /*****************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
9 * A multi-threaded example that uses pthreads and fetches 4 remote files at
10 * once over HTTPS. The lock callbacks and stuff assume OpenSSL or GnuTLS
13 * OpenSSL docs for this:
14 * http://www.openssl.org/docs/crypto/threads.html
15 * gcrypt docs for this:
16 * http://gnupg.org/documentation/manuals/gcrypt/Multi_002dThreading.html
19 #define USE_OPENSSL /* or USE_GNUTLS accordingly */
23 #include <curl/curl.h>
27 /* we have this global to let the callback get easy access to it */
28 static pthread_mutex_t *lockarray;
31 #include <openssl/crypto.h>
32 static void lock_callback(int mode, int type, char *file, int line)
36 if (mode & CRYPTO_LOCK) {
37 pthread_mutex_lock(&(lockarray[type]));
40 pthread_mutex_unlock(&(lockarray[type]));
44 static unsigned long thread_id(void)
48 ret=(unsigned long)pthread_self();
52 static void init_locks(void)
56 lockarray=(pthread_mutex_t *)OPENSSL_malloc(CRYPTO_num_locks() *
57 sizeof(pthread_mutex_t));
58 for (i=0; i<CRYPTO_num_locks(); i++) {
59 pthread_mutex_init(&(lockarray[i]),NULL);
62 CRYPTO_set_id_callback((unsigned long (*)())thread_id);
63 CRYPTO_set_locking_callback((void (*)())lock_callback);
66 static void kill_locks(void)
70 CRYPTO_set_locking_callback(NULL);
71 for (i=0; i<CRYPTO_num_locks(); i++)
72 pthread_mutex_destroy(&(lockarray[i]));
74 OPENSSL_free(lockarray);
82 GCRY_THREAD_OPTION_PTHREAD_IMPL;
86 gcry_control(GCRYCTL_SET_THREAD_CBS);
92 /* List of URLs to fetch.*/
93 const char * const urls[]= {
94 "https://www.example.com/",
95 "https://www2.example.com/",
96 "https://www3.example.com/",
97 "https://www4.example.com/",
100 static void *pull_one_url(void *url)
104 curl = curl_easy_init();
105 curl_easy_setopt(curl, CURLOPT_URL, url);
106 /* this example doesn't verify the server's certificate, which means we
107 might be downloading stuff from an impostor */
108 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
109 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
110 curl_easy_perform(curl); /* ignores error */
111 curl_easy_cleanup(curl);
116 int main(int argc, char **argv)
121 (void)argc; /* we don't use any arguments in this example */
124 /* Must initialize libcurl before any threads are started */
125 curl_global_init(CURL_GLOBAL_ALL);
129 for(i=0; i< NUMT; i++) {
130 error = pthread_create(&tid[i],
131 NULL, /* default attributes please */
135 fprintf(stderr, "Couldn't run thread number %d, errno %d\n", i, error);
137 fprintf(stderr, "Thread %d, gets %s\n", i, urls[i]);
140 /* now wait for all threads to terminate */
141 for(i=0; i< NUMT; i++) {
142 error = pthread_join(tid[i], NULL);
143 fprintf(stderr, "Thread %d terminated\n", i);