diff --git a/configure.in b/configure.in index 83840a8f9ab95..95661a54f147c 100755 --- a/configure.in +++ b/configure.in @@ -698,6 +698,18 @@ AC_CHECK_HEADER([vorbis/vorbisenc.h],, AC_MSG_ERROR($missing_library)) AC_CHECK_HEADER([libmodplug/modplug.h],, AC_MSG_ERROR($missing_library)) AC_CHECK_HEADER([curl/curl.h],, AC_MSG_ERROR($missing_library)) AC_CHECK_HEADER([FLAC/stream_decoder.h],, AC_MSG_ERROR($missing_library)) + +# we need to check for the header because if it exists we set the openssl +# and gcrypt MT callback hooks. This is mostly so that libcurl operates +# in MT manner correctly. +AC_CHECK_HEADER([openssl/crypto.h], AC_DEFINE([HAVE_OPENSSL],[1],[Define if we have openssl]),) +AC_CHECK_HEADER([gcrypt.h], gcrypt_headers_available=yes,gcrypt_headers_available=no) +if test "$gcrypt_headers_available" = "yes"; then + # if we have the headers then we must have the lib + AC_CHECK_LIB([gcrypt],[gcry_control],, AC_MSG_ERROR($missing_library)) + AC_DEFINE([HAVE_GCRYPT],[1],[Define if we have gcrypt]) +fi + AC_CHECK_LIB([bz2], [main],, AC_MSG_ERROR($missing_library)) AC_CHECK_LIB([jpeg], [main],, AC_MSG_ERROR($missing_library)) # check for cximage AC_CHECK_LIB([tiff], [main],, AC_MSG_ERROR($missing_library)) diff --git a/xbmc/utils/CryptThreading.cpp b/xbmc/utils/CryptThreading.cpp new file mode 100644 index 0000000000000..5bc251ac51f42 --- /dev/null +++ b/xbmc/utils/CryptThreading.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#ifdef TARGET_WINDOWS +#error "The threading options for the cryptography libraries don't need to be and shouldn't be set on Windows. Do not include CryptThreading in your windows project." +#endif + +#include "CryptThreading.h" +#include "threads/Thread.h" +#include "utils/log.h" + +#if (defined HAVE_CONFIG_H) && (!defined WIN32) + #include "config.h" +#else +#define HAVE_OPENSSL +#endif + +#ifdef HAVE_OPENSSL +#include +#endif + +#ifdef HAVE_GCRYPT +#include +#include + +GCRY_THREAD_OPTION_PTHREAD_IMPL; +#endif + +/* ========================================================================= */ +/* openssl locking implementation for curl */ +static CCriticalSection* getlock(int index) +{ + return g_cryptThreadingInitializer.get_lock(index); +} + +static void lock_callback(int mode, int type, const char* file, int line) +{ + if (mode & 0x01 /* CRYPTO_LOCK from openssl/crypto.h */ ) + getlock(type)->lock(); + else + getlock(type)->unlock(); +} + +static unsigned long thread_id() +{ + return (unsigned long)CThread::GetCurrentThreadId(); +} +/* ========================================================================= */ + +CryptThreadingInitializer::CryptThreadingInitializer() +{ + bool attemptedToSetSSLMTHook = false; +#ifdef HAVE_OPENSSL + // set up OpenSSL + numlocks = CRYPTO_num_locks(); + CRYPTO_set_id_callback(thread_id); + CRYPTO_set_locking_callback(lock_callback); + attemptedToSetSSLMTHook = true; +#else + numlocks = 1; +#endif + + locks = new CCriticalSection*[numlocks]; + for (int i = 0; i < numlocks; i++) + locks[i] = NULL; + +#ifdef HAVE_GCRYPT + // set up gcrypt + gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); + attemptedToSetSSLMTHook = true; +#endif + + if (!attemptedToSetSSLMTHook) + CLog::Log(LOGWARNING, "Could not determine the libcurl security library to set the locking scheme. This may cause problem with multithreaded use of ssl or libraries that depend on it (libcurl)."); + +} + +CryptThreadingInitializer::~CryptThreadingInitializer() +{ + CSingleLock l(locksLock); +#ifdef HAVE_OPENSSL + CRYPTO_set_locking_callback(NULL); +#endif + + for (int i = 0; i < numlocks; i++) + delete locks[i]; // I always forget ... delete is NULL safe. + + delete [] locks; +} + +CCriticalSection* CryptThreadingInitializer::get_lock(int index) +{ + CSingleLock l(locksLock); + CCriticalSection* curlock = locks[index]; + if (curlock == NULL) + { + curlock = new CCriticalSection(); + locks[index] = curlock; + } + + return curlock; +} + + + + diff --git a/xbmc/utils/CryptThreading.h b/xbmc/utils/CryptThreading.h new file mode 100644 index 0000000000000..e33984b94b678 --- /dev/null +++ b/xbmc/utils/CryptThreading.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#pragma once + +#include "utils/GlobalsHandling.h" +#include "threads/CriticalSection.h" + +class CryptThreadingInitializer +{ + CCriticalSection** locks; + int numlocks; + CCriticalSection locksLock; + +public: + CryptThreadingInitializer(); + ~CryptThreadingInitializer(); + + CCriticalSection* get_lock(int index); +}; + +XBMC_GLOBAL_REF(CryptThreadingInitializer,g_cryptThreadingInitializer); +#define g_cryptThreadingInitializer XBMC_GLOBAL_USE(CryptThreadingInitializer) diff --git a/xbmc/utils/Makefile b/xbmc/utils/Makefile index c91572ec3298a..a420c5b16338e 100644 --- a/xbmc/utils/Makefile +++ b/xbmc/utils/Makefile @@ -7,6 +7,7 @@ SRCS=AlarmClock.cpp \ CharsetConverter.cpp \ CPUInfo.cpp \ Crc32.cpp \ + CryptThreading.cpp \ DownloadQueue.cpp \ DownloadQueueManager.cpp \ Fanart.cpp \