Annotation of embedaddon/curl/docs/examples/threaded-ssl.c, revision 1.1
1.1 ! misho 1: /***************************************************************************
! 2: * _ _ ____ _
! 3: * Project ___| | | | _ \| |
! 4: * / __| | | | |_) | |
! 5: * | (__| |_| | _ <| |___
! 6: * \___|\___/|_| \_\_____|
! 7: *
! 8: * Copyright (C) 1998 - 2019, 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/man1.0.2/man3/CRYPTO_num_locks.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: (void)argc; /* we don't use any arguments in this example */
! 139: (void)argv;
! 140:
! 141: /* Must initialize libcurl before any threads are started */
! 142: curl_global_init(CURL_GLOBAL_ALL);
! 143:
! 144: init_locks();
! 145:
! 146: for(i = 0; i< NUMT; i++) {
! 147: int error = pthread_create(&tid[i],
! 148: NULL, /* default attributes please */
! 149: pull_one_url,
! 150: (void *)urls[i]);
! 151: if(0 != error)
! 152: fprintf(stderr, "Couldn't run thread number %d, errno %d\n", i, error);
! 153: else
! 154: fprintf(stderr, "Thread %d, gets %s\n", i, urls[i]);
! 155: }
! 156:
! 157: /* now wait for all threads to terminate */
! 158: for(i = 0; i< NUMT; i++) {
! 159: pthread_join(tid[i], NULL);
! 160: fprintf(stderr, "Thread %d terminated\n", i);
! 161: }
! 162:
! 163: kill_locks();
! 164:
! 165: return 0;
! 166: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>