threaded-ssl.c
Go to the documentation of this file.
1 /***************************************************************************
2  * _ _ ____ _
3  * Project ___| | | | _ \| |
4  * / __| | | | |_) | |
5  * | (__| |_| | _ <| |___
6  * \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2017, 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 https://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 /* <DESC>
23  * Show the required mutex callback setups for GnuTLS and OpenSSL when using
24  * libcurl multi-threaded.
25  * </DESC>
26  */
27 /* A multi-threaded example that uses pthreads and fetches 4 remote files at
28  * once over HTTPS. The lock callbacks and stuff assume OpenSSL <1.1 or GnuTLS
29  * (libgcrypt) so far.
30  *
31  * OpenSSL docs for this:
32  * https://www.openssl.org/docs/crypto/threads.html
33  * gcrypt docs for this:
34  * https://gnupg.org/documentation/manuals/gcrypt/Multi_002dThreading.html
35  */
36 
37 #define USE_OPENSSL /* or USE_GNUTLS accordingly */
38 
39 #include <stdio.h>
40 #include <pthread.h>
41 #include <curl/curl.h>
42 
43 #define NUMT 4
44 
45 /* we have this global to let the callback get easy access to it */
46 static pthread_mutex_t *lockarray;
47 
48 #ifdef USE_OPENSSL
49 #include <openssl/crypto.h>
50 static void lock_callback(int mode, int type, char *file, int line)
51 {
52  (void)file;
53  (void)line;
54  if(mode & CRYPTO_LOCK) {
55  pthread_mutex_lock(&(lockarray[type]));
56  }
57  else {
58  pthread_mutex_unlock(&(lockarray[type]));
59  }
60 }
61 
62 static unsigned long thread_id(void)
63 {
64  unsigned long ret;
65 
66  ret = (unsigned long)pthread_self();
67  return ret;
68 }
69 
70 static void init_locks(void)
71 {
72  int i;
73 
74  lockarray = (pthread_mutex_t *)OPENSSL_malloc(CRYPTO_num_locks() *
75  sizeof(pthread_mutex_t));
76  for(i = 0; i<CRYPTO_num_locks(); i++) {
77  pthread_mutex_init(&(lockarray[i]), NULL);
78  }
79 
80  CRYPTO_set_id_callback((unsigned long (*)())thread_id);
81  CRYPTO_set_locking_callback((void (*)())lock_callback);
82 }
83 
84 static void kill_locks(void)
85 {
86  int i;
87 
88  CRYPTO_set_locking_callback(NULL);
89  for(i = 0; i<CRYPTO_num_locks(); i++)
90  pthread_mutex_destroy(&(lockarray[i]));
91 
92  OPENSSL_free(lockarray);
93 }
94 #endif
95 
96 #ifdef USE_GNUTLS
97 #include <gcrypt.h>
98 #include <errno.h>
99 
100 GCRY_THREAD_OPTION_PTHREAD_IMPL;
101 
102 void init_locks(void)
103 {
104  gcry_control(GCRYCTL_SET_THREAD_CBS);
105 }
106 
107 #define kill_locks()
108 #endif
109 
110 /* List of URLs to fetch.*/
111 const char * const urls[]= {
112  "https://www.example.com/",
113  "https://www2.example.com/",
114  "https://www3.example.com/",
115  "https://www4.example.com/",
116 };
117 
118 static void *pull_one_url(void *url)
119 {
120  CURL *curl;
121 
122  curl = curl_easy_init();
123  curl_easy_setopt(curl, CURLOPT_URL, url);
124  /* this example doesn't verify the server's certificate, which means we
125  might be downloading stuff from an impostor */
126  curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
127  curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
128  curl_easy_perform(curl); /* ignores error */
129  curl_easy_cleanup(curl);
130 
131  return NULL;
132 }
133 
134 int main(int argc, char **argv)
135 {
136  pthread_t tid[NUMT];
137  int i;
138  int error;
139  (void)argc; /* we don't use any arguments in this example */
140  (void)argv;
141 
142  /* Must initialize libcurl before any threads are started */
144 
145  init_locks();
146 
147  for(i = 0; i< NUMT; i++) {
148  error = pthread_create(&tid[i],
149  NULL, /* default attributes please */
150  pull_one_url,
151  (void *)urls[i]);
152  if(0 != error)
153  fprintf(stderr, "Couldn't run thread number %d, errno %d\n", i, error);
154  else
155  fprintf(stderr, "Thread %d, gets %s\n", i, urls[i]);
156  }
157 
158  /* now wait for all threads to terminate */
159  for(i = 0; i< NUMT; i++) {
160  error = pthread_join(tid[i], NULL);
161  fprintf(stderr, "Thread %d terminated\n", i);
162  }
163 
164  kill_locks();
165 
166  return 0;
167 }
static pthread_mutex_t * lockarray
Definition: threaded-ssl.c:46
#define curl_easy_setopt(handle, option, value)
Definition: typecheck-gcc.h:41
int main(int argc, char **argv)
Definition: threaded-ssl.c:134
unsigned int i
Definition: unit1303.c:79
const char *const urls[]
Definition: threaded-ssl.c:111
CURL_EXTERN CURL * curl_easy_init(void)
Definition: easy.c:343
CURL_EXTERN void curl_easy_cleanup(CURL *curl)
static void init_locks(void)
Definition: threaded-ssl.c:70
static void kill_locks(void)
Definition: threaded-ssl.c:84
CURL_EXTERN CURLcode curl_global_init(long flags)
curl_global_init() globally initializes curl given a bitwise set of the different features of what to...
Definition: easy.c:271
void CURL
Definition: curl.h:102
#define NUMT
Definition: threaded-ssl.c:43
static void * pull_one_url(void *url)
Definition: threaded-ssl.c:118
#define fprintf
Definition: curl_printf.h:41
#define CURL_GLOBAL_ALL
Definition: curl.h:2519
static unsigned long thread_id(void)
Definition: threaded-ssl.c:62
static CURL * curl
Definition: sessioninfo.c:35
CURL_EXTERN CURLcode curl_easy_perform(CURL *curl)
static void lock_callback(int mode, int type, char *file, int line)
Definition: threaded-ssl.c:50


rc_tagdetect_client
Author(s): Monika Florek-Jasinska , Raphael Schaller
autogenerated on Sat Feb 13 2021 03:42:16