1 /*****************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * $Id: threaded-ssl.c,v 1.4 2008-05-22 21:20:09 danf Exp $
10 * A multi-threaded example that uses pthreads and fetches 4 remote files at
11 * once over HTTPS. The lock callbacks and stuff assume OpenSSL or GnuTLS
14 * OpenSSL docs for this:
15 * http://www.openssl.org/docs/crypto/threads.html
16 * gcrypt docs for this:
17 * http://gnupg.org/documentation/manuals/gcrypt/Multi_002dThreading.html
20 #define USE_OPENSSL /* or USE_GNUTLS accordingly */
24 #include <curl/curl.h>
28 /* we have this global to let the callback get easy access to it */
29 static pthread_mutex_t
*lockarray
;
32 #include <openssl/crypto.h>
33 static void lock_callback(int mode
, int type
, char *file
, int line
)
37 if (mode
& CRYPTO_LOCK
) {
38 pthread_mutex_lock(&(lockarray
[type
]));
41 pthread_mutex_unlock(&(lockarray
[type
]));
45 static unsigned long thread_id(void)
49 ret
=(unsigned long)pthread_self();
53 static void init_locks(void)
57 lockarray
=(pthread_mutex_t
*)OPENSSL_malloc(CRYPTO_num_locks() *
58 sizeof(pthread_mutex_t
));
59 for (i
=0; i
<CRYPTO_num_locks(); i
++) {
60 pthread_mutex_init(&(lockarray
[i
]),NULL
);
63 CRYPTO_set_id_callback((unsigned long (*)())thread_id
);
64 CRYPTO_set_locking_callback((void (*)())lock_callback
);
67 static void kill_locks(void)
71 CRYPTO_set_locking_callback(NULL
);
72 for (i
=0; i
<CRYPTO_num_locks(); i
++)
73 pthread_mutex_destroy(&(lockarray
[i
]));
75 OPENSSL_free(lockarray
);
83 GCRY_THREAD_OPTION_PTHREAD_IMPL
;
87 gcry_control(GCRYCTL_SET_THREAD_CBS
);
93 /* List of URLs to fetch.*/
94 const char * const urls
[]= {
95 "https://www.sf.net/",
96 "https://www.openssl.org/",
97 "https://www.sf.net/",
98 "https://www.openssl.org/",
101 static void *pull_one_url(void *url
)
105 curl
= curl_easy_init();
106 curl_easy_setopt(curl
, CURLOPT_URL
, url
);
107 /* this example doesn't verify the server's certificate, which means we
108 might be downloading stuff from an impostor */
109 curl_easy_setopt(curl
, CURLOPT_SSL_VERIFYPEER
, 0L);
110 curl_easy_setopt(curl
, CURLOPT_SSL_VERIFYHOST
, 0L);
111 curl_easy_perform(curl
); /* ignores error */
112 curl_easy_cleanup(curl
);
117 int main(int argc
, char **argv
)
122 (void)argc
; /* we don't use any arguments in this example */
125 /* Must initialize libcurl before any threads are started */
126 curl_global_init(CURL_GLOBAL_ALL
);
130 for(i
=0; i
< NUMT
; i
++) {
131 error
= pthread_create(&tid
[i
],
132 NULL
, /* default attributes please */
136 fprintf(stderr
, "Couldn't run thread number %d, errno %d\n", i
, error
);
138 fprintf(stderr
, "Thread %d, gets %s\n", i
, urls
[i
]);
141 /* now wait for all threads to terminate */
142 for(i
=0; i
< NUMT
; i
++) {
143 error
= pthread_join(tid
[i
], NULL
);
144 fprintf(stderr
, "Thread %d terminated\n", i
);