aboutsummaryrefslogtreecommitdiff
path: root/src/utils/CryptThreading.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/utils/CryptThreading.cpp')
-rw-r--r--src/utils/CryptThreading.cpp123
1 files changed, 123 insertions, 0 deletions
diff --git a/src/utils/CryptThreading.cpp b/src/utils/CryptThreading.cpp
new file mode 100644
index 0000000000..49a24e557f
--- /dev/null
+++ b/src/utils/CryptThreading.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2005-2013 Team XBMC
+ * http://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, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#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 TARGET_WINDOWS)
+ #include "config.h"
+#else
+#define HAVE_OPENSSL
+#endif
+
+#ifdef HAVE_OPENSSL
+#include <openssl/crypto.h>
+#endif
+
+#ifdef HAVE_GCRYPT
+#include <gcrypt.h>
+#include <errno.h>
+
+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;
+}
+
+
+
+