Initial commit of visual studio 9 git build superproject.
[git-build-vc9.git] / curl / docs / examples / threaded-ssl.c
blob95552ea41d29ae86a9c6eb84cf5e59d08402227a
1 /*****************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
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
12 * (libgcrypt) so far.
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 */
22 #include <stdio.h>
23 #include <pthread.h>
24 #include <curl/curl.h>
26 #define NUMT 4
28 /* we have this global to let the callback get easy access to it */
29 static pthread_mutex_t *lockarray;
31 #ifdef USE_OPENSSL
32 #include <openssl/crypto.h>
33 static void lock_callback(int mode, int type, char *file, int line)
35 (void)file;
36 (void)line;
37 if (mode & CRYPTO_LOCK) {
38 pthread_mutex_lock(&(lockarray[type]));
40 else {
41 pthread_mutex_unlock(&(lockarray[type]));
45 static unsigned long thread_id(void)
47 unsigned long ret;
49 ret=(unsigned long)pthread_self();
50 return(ret);
53 static void init_locks(void)
55 int i;
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)
69 int i;
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);
77 #endif
79 #ifdef USE_GNUTLS
80 #include <gcrypt.h>
81 #include <errno.h>
83 GCRY_THREAD_OPTION_PTHREAD_IMPL;
85 void init_locks(void)
87 gcry_control(GCRYCTL_SET_THREAD_CBS);
90 #define kill_locks()
91 #endif
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)
103 CURL *curl;
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);
114 return NULL;
117 int main(int argc, char **argv)
119 pthread_t tid[NUMT];
120 int i;
121 int error;
122 (void)argc; /* we don't use any arguments in this example */
123 (void)argv;
125 /* Must initialize libcurl before any threads are started */
126 curl_global_init(CURL_GLOBAL_ALL);
128 init_locks();
130 for(i=0; i< NUMT; i++) {
131 error = pthread_create(&tid[i],
132 NULL, /* default attributes please */
133 pull_one_url,
134 (void *)urls[i]);
135 if(0 != error)
136 fprintf(stderr, "Couldn't run thread number %d, errno %d\n", i, error);
137 else
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);
147 kill_locks();
149 return 0;