[04/10] avformat: Add ff_tls_init()/deinit() that initialize OpenSSL

Message ID 1320154365-10834-4-git-send-email-martin@martin.st
State Committed
Headers show

Commit Message

Martin Storsjö Nov. 1, 2011, 1:32 p.m.
If the application hasn't set up mutex callbacks, we set up
our own using pthreads (or w32pthreads).
---
 libavformat/network.c |   79 +++++++++++++++++++++++++++++++++++++++++++++++++
 libavformat/network.h |    3 ++
 2 files changed, 82 insertions(+), 0 deletions(-)

Comments

Martin Storsjö Nov. 3, 2011, 12:32 p.m. | #1
On Tue, 1 Nov 2011, Martin Storsjö wrote:

> +void ff_tls_init(void)
> +{
> +    avpriv_lock_avformat();
> +#if CONFIG_OPENSSL
> +    openssl_init++;
> +    if (openssl_init > 1)
> +        return;

I realized that this doesn't unlock the mutex - changed it locally to:

if (!init) {
    // do all init
}
init++;

Which should be slightly clearer and have less risk for forgetting to 
unlock mutexes, while indenting the whole function one step further.

// Martin
Anton Khirnov Nov. 3, 2011, 1:06 p.m. | #2
On Tue,  1 Nov 2011 15:32:39 +0200, Martin Storsjö <martin@martin.st> wrote:
> If the application hasn't set up mutex callbacks, we set up
> our own using pthreads (or w32pthreads).
> ---
>  libavformat/network.c |   79 +++++++++++++++++++++++++++++++++++++++++++++++++
>  libavformat/network.h |    3 ++
>  2 files changed, 82 insertions(+), 0 deletions(-)
> 
> diff --git a/libavformat/network.c b/libavformat/network.c
> index c42cf23..291dc8c 100644
> --- a/libavformat/network.c
> +++ b/libavformat/network.c
> @@ -19,6 +19,85 @@
>   */
>  
>  #include "network.h"
> +#include "libavcodec/internal.h"
> +
> +#define THREADS (HAVE_PTHREADS || (defined(WIN32) && !defined(__MINGW32CE__)))
> +
> +#if THREADS
> +#if HAVE_PTHREADS
> +#include <pthread.h>
> +#else
> +#include "libavcodec/w32pthreads.h"
> +#endif
> +#endif
> +
> +#if CONFIG_OPENSSL
> +#include <openssl/ssl.h>
> +static int openssl_init;
> +#if THREADS
> +#include <openssl/crypto.h>
> +#include "libavutil/avutil.h"
> +pthread_mutex_t *openssl_mutexes;
> +static void openssl_lock(int mode, int type, const char *file, int line)
> +{
> +    if (mode & CRYPTO_LOCK)
> +        pthread_mutex_lock(&openssl_mutexes[type]);
> +    else
> +        pthread_mutex_unlock(&openssl_mutexes[type]);
> +}
> +#ifndef WIN32
> +static unsigned long openssl_thread_id(void)
> +{
> +    return (intptr_t) pthread_self();
> +}
> +#endif
> +#endif
> +#endif
> +
> +void ff_tls_init(void)
> +{
> +    avpriv_lock_avformat();
> +#if CONFIG_OPENSSL
> +    openssl_init++;
> +    if (openssl_init > 1)
> +        return;
> +    SSL_library_init();
> +    SSL_load_error_strings();
> +#if THREADS
> +    if (!CRYPTO_get_locking_callback()) {
> +        int i;
> +        openssl_mutexes = av_malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
> +        for (i = 0; i < CRYPTO_num_locks(); i++)
> +            pthread_mutex_init(&openssl_mutexes[i], NULL);
> +        CRYPTO_set_locking_callback(openssl_lock);
> +#ifndef WIN32
> +        CRYPTO_set_id_callback(openssl_thread_id);

This function seems to be deprecated since 1.0.0, replaced by
CRYPTO_THREADID_set_callback().
Martin Storsjö Nov. 3, 2011, 1:45 p.m. | #3
On Thu, 3 Nov 2011, Anton Khirnov wrote:

>
> On Tue,  1 Nov 2011 15:32:39 +0200, Martin Storsjö <martin@martin.st> wrote:
>> If the application hasn't set up mutex callbacks, we set up
>> our own using pthreads (or w32pthreads).
>> ---
>>  libavformat/network.c |   79 +++++++++++++++++++++++++++++++++++++++++++++++++
>>  libavformat/network.h |    3 ++
>>  2 files changed, 82 insertions(+), 0 deletions(-)
>>
>> diff --git a/libavformat/network.c b/libavformat/network.c
>> index c42cf23..291dc8c 100644
>> --- a/libavformat/network.c
>> +++ b/libavformat/network.c
>> @@ -19,6 +19,85 @@
>>   */
>>
>>  #include "network.h"
>> +#include "libavcodec/internal.h"
>> +
>> +#define THREADS (HAVE_PTHREADS || (defined(WIN32) && !defined(__MINGW32CE__)))
>> +
>> +#if THREADS
>> +#if HAVE_PTHREADS
>> +#include <pthread.h>
>> +#else
>> +#include "libavcodec/w32pthreads.h"
>> +#endif
>> +#endif
>> +
>> +#if CONFIG_OPENSSL
>> +#include <openssl/ssl.h>
>> +static int openssl_init;
>> +#if THREADS
>> +#include <openssl/crypto.h>
>> +#include "libavutil/avutil.h"
>> +pthread_mutex_t *openssl_mutexes;
>> +static void openssl_lock(int mode, int type, const char *file, int line)
>> +{
>> +    if (mode & CRYPTO_LOCK)
>> +        pthread_mutex_lock(&openssl_mutexes[type]);
>> +    else
>> +        pthread_mutex_unlock(&openssl_mutexes[type]);
>> +}
>> +#ifndef WIN32
>> +static unsigned long openssl_thread_id(void)
>> +{
>> +    return (intptr_t) pthread_self();
>> +}
>> +#endif
>> +#endif
>> +#endif
>> +
>> +void ff_tls_init(void)
>> +{
>> +    avpriv_lock_avformat();
>> +#if CONFIG_OPENSSL
>> +    openssl_init++;
>> +    if (openssl_init > 1)
>> +        return;
>> +    SSL_library_init();
>> +    SSL_load_error_strings();
>> +#if THREADS
>> +    if (!CRYPTO_get_locking_callback()) {
>> +        int i;
>> +        openssl_mutexes = av_malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
>> +        for (i = 0; i < CRYPTO_num_locks(); i++)
>> +            pthread_mutex_init(&openssl_mutexes[i], NULL);
>> +        CRYPTO_set_locking_callback(openssl_lock);
>> +#ifndef WIN32
>> +        CRYPTO_set_id_callback(openssl_thread_id);
>
> This function seems to be deprecated since 1.0.0, replaced by
> CRYPTO_THREADID_set_callback().

OS X Snow Leopard, which I'm using, only has OpenSSL 0.9.8l. As far as I 
know, the 0.9.8 series is still in quite wide use - debian stable only has 
0.9.8, and Ubuntu got 1.0.0 only in 11.10.

// Martin
Anton Khirnov Nov. 5, 2011, 6:57 a.m. | #4
On Thu, 3 Nov 2011 15:45:38 +0200 (EET), Martin Storsjö <martin@martin.st> wrote:
> On Thu, 3 Nov 2011, Anton Khirnov wrote:
> 
> >
> > On Tue,  1 Nov 2011 15:32:39 +0200, Martin Storsjö <martin@martin.st> wrote:
> >> If the application hasn't set up mutex callbacks, we set up
> >> our own using pthreads (or w32pthreads).
> >> ---
> >>  libavformat/network.c |   79 +++++++++++++++++++++++++++++++++++++++++++++++++
> >>  libavformat/network.h |    3 ++
> >>  2 files changed, 82 insertions(+), 0 deletions(-)
> >>
> >> diff --git a/libavformat/network.c b/libavformat/network.c
> >> index c42cf23..291dc8c 100644
> >> --- a/libavformat/network.c
> >> +++ b/libavformat/network.c
> >> @@ -19,6 +19,85 @@
> >>   */
> >>
> >>  #include "network.h"
> >> +#include "libavcodec/internal.h"
> >> +
> >> +#define THREADS (HAVE_PTHREADS || (defined(WIN32) && !defined(__MINGW32CE__)))
> >> +
> >> +#if THREADS
> >> +#if HAVE_PTHREADS
> >> +#include <pthread.h>
> >> +#else
> >> +#include "libavcodec/w32pthreads.h"
> >> +#endif
> >> +#endif
> >> +
> >> +#if CONFIG_OPENSSL
> >> +#include <openssl/ssl.h>
> >> +static int openssl_init;
> >> +#if THREADS
> >> +#include <openssl/crypto.h>
> >> +#include "libavutil/avutil.h"
> >> +pthread_mutex_t *openssl_mutexes;
> >> +static void openssl_lock(int mode, int type, const char *file, int line)
> >> +{
> >> +    if (mode & CRYPTO_LOCK)
> >> +        pthread_mutex_lock(&openssl_mutexes[type]);
> >> +    else
> >> +        pthread_mutex_unlock(&openssl_mutexes[type]);
> >> +}
> >> +#ifndef WIN32
> >> +static unsigned long openssl_thread_id(void)
> >> +{
> >> +    return (intptr_t) pthread_self();
> >> +}
> >> +#endif
> >> +#endif
> >> +#endif
> >> +
> >> +void ff_tls_init(void)
> >> +{
> >> +    avpriv_lock_avformat();
> >> +#if CONFIG_OPENSSL
> >> +    openssl_init++;
> >> +    if (openssl_init > 1)
> >> +        return;
> >> +    SSL_library_init();
> >> +    SSL_load_error_strings();
> >> +#if THREADS
> >> +    if (!CRYPTO_get_locking_callback()) {
> >> +        int i;
> >> +        openssl_mutexes = av_malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
> >> +        for (i = 0; i < CRYPTO_num_locks(); i++)
> >> +            pthread_mutex_init(&openssl_mutexes[i], NULL);
> >> +        CRYPTO_set_locking_callback(openssl_lock);
> >> +#ifndef WIN32
> >> +        CRYPTO_set_id_callback(openssl_thread_id);
> >
> > This function seems to be deprecated since 1.0.0, replaced by
> > CRYPTO_THREADID_set_callback().
> 
> OS X Snow Leopard, which I'm using, only has OpenSSL 0.9.8l. As far as I 
> know, the 0.9.8 series is still in quite wide use - debian stable only has 
> 0.9.8, and Ubuntu got 1.0.0 only in 11.10.
> 

Ok then. But we should keep it in mind for the future.

Patch

diff --git a/libavformat/network.c b/libavformat/network.c
index c42cf23..291dc8c 100644
--- a/libavformat/network.c
+++ b/libavformat/network.c
@@ -19,6 +19,85 @@ 
  */
 
 #include "network.h"
+#include "libavcodec/internal.h"
+
+#define THREADS (HAVE_PTHREADS || (defined(WIN32) && !defined(__MINGW32CE__)))
+
+#if THREADS
+#if HAVE_PTHREADS
+#include <pthread.h>
+#else
+#include "libavcodec/w32pthreads.h"
+#endif
+#endif
+
+#if CONFIG_OPENSSL
+#include <openssl/ssl.h>
+static int openssl_init;
+#if THREADS
+#include <openssl/crypto.h>
+#include "libavutil/avutil.h"
+pthread_mutex_t *openssl_mutexes;
+static void openssl_lock(int mode, int type, const char *file, int line)
+{
+    if (mode & CRYPTO_LOCK)
+        pthread_mutex_lock(&openssl_mutexes[type]);
+    else
+        pthread_mutex_unlock(&openssl_mutexes[type]);
+}
+#ifndef WIN32
+static unsigned long openssl_thread_id(void)
+{
+    return (intptr_t) pthread_self();
+}
+#endif
+#endif
+#endif
+
+void ff_tls_init(void)
+{
+    avpriv_lock_avformat();
+#if CONFIG_OPENSSL
+    openssl_init++;
+    if (openssl_init > 1)
+        return;
+    SSL_library_init();
+    SSL_load_error_strings();
+#if THREADS
+    if (!CRYPTO_get_locking_callback()) {
+        int i;
+        openssl_mutexes = av_malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
+        for (i = 0; i < CRYPTO_num_locks(); i++)
+            pthread_mutex_init(&openssl_mutexes[i], NULL);
+        CRYPTO_set_locking_callback(openssl_lock);
+#ifndef WIN32
+        CRYPTO_set_id_callback(openssl_thread_id);
+#endif
+    }
+#endif
+#endif
+    avpriv_unlock_avformat();
+}
+
+void ff_tls_deinit(void)
+{
+    avpriv_lock_avformat();
+#if CONFIG_OPENSSL
+    openssl_init--;
+    if (!openssl_init) {
+#if THREADS
+        if (CRYPTO_get_locking_callback() == openssl_lock) {
+            int i;
+            CRYPTO_set_locking_callback(NULL);
+            for (i = 0; i < CRYPTO_num_locks(); i++)
+                pthread_mutex_destroy(&openssl_mutexes[i]);
+            av_free(openssl_mutexes);
+        }
+#endif
+    }
+#endif
+    avpriv_unlock_avformat();
+}
 
 int ff_network_init(void)
 {
diff --git a/libavformat/network.h b/libavformat/network.h
index 00daed8..df79f45 100644
--- a/libavformat/network.h
+++ b/libavformat/network.h
@@ -59,6 +59,9 @@  int ff_socket_nonblock(int socket, int enable);
 int ff_network_init(void);
 void ff_network_close(void);
 
+void ff_tls_init(void);
+void ff_tls_deinit(void);
+
 int ff_network_wait_fd(int fd, int write);
 
 int ff_inet_aton (const char * str, struct in_addr * add);