Return to threaded-ssl.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / docs / examples |
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: }