00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "libavutil/avutil.h"
00022 #include "network.h"
00023 #include "libavcodec/internal.h"
00024
00025 #define THREADS (HAVE_PTHREADS || (defined(WIN32) && !defined(__MINGW32CE__)))
00026
00027 #if THREADS
00028 #if HAVE_PTHREADS
00029 #include <pthread.h>
00030 #else
00031 #include "libavcodec/w32pthreads.h"
00032 #endif
00033 #endif
00034
00035 #if CONFIG_OPENSSL
00036 #include <openssl/ssl.h>
00037 static int openssl_init;
00038 #if THREADS
00039 #include <openssl/crypto.h>
00040 #include "libavutil/avutil.h"
00041 pthread_mutex_t *openssl_mutexes;
00042 static void openssl_lock(int mode, int type, const char *file, int line)
00043 {
00044 if (mode & CRYPTO_LOCK)
00045 pthread_mutex_lock(&openssl_mutexes[type]);
00046 else
00047 pthread_mutex_unlock(&openssl_mutexes[type]);
00048 }
00049 #if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000
00050 static unsigned long openssl_thread_id(void)
00051 {
00052 return (intptr_t) pthread_self();
00053 }
00054 #endif
00055 #endif
00056 #endif
00057 #if CONFIG_GNUTLS
00058 #include <gnutls/gnutls.h>
00059 #if THREADS && GNUTLS_VERSION_NUMBER <= 0x020b00
00060 #include <gcrypt.h>
00061 #include <errno.h>
00062 #undef malloc
00063 #undef free
00064 GCRY_THREAD_OPTION_PTHREAD_IMPL;
00065 #endif
00066 #endif
00067
00068 void ff_tls_init(void)
00069 {
00070 avpriv_lock_avformat();
00071 #if CONFIG_OPENSSL
00072 if (!openssl_init) {
00073 SSL_library_init();
00074 SSL_load_error_strings();
00075 #if THREADS
00076 if (!CRYPTO_get_locking_callback()) {
00077 int i;
00078 openssl_mutexes = av_malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
00079 for (i = 0; i < CRYPTO_num_locks(); i++)
00080 pthread_mutex_init(&openssl_mutexes[i], NULL);
00081 CRYPTO_set_locking_callback(openssl_lock);
00082 #if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000
00083 CRYPTO_set_id_callback(openssl_thread_id);
00084 #endif
00085 }
00086 #endif
00087 }
00088 openssl_init++;
00089 #endif
00090 #if CONFIG_GNUTLS
00091 #if THREADS && GNUTLS_VERSION_NUMBER < 0x020b00
00092 if (gcry_control(GCRYCTL_ANY_INITIALIZATION_P) == 0)
00093 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
00094 #endif
00095 gnutls_global_init();
00096 #endif
00097 avpriv_unlock_avformat();
00098 }
00099
00100 void ff_tls_deinit(void)
00101 {
00102 avpriv_lock_avformat();
00103 #if CONFIG_OPENSSL
00104 openssl_init--;
00105 if (!openssl_init) {
00106 #if THREADS
00107 if (CRYPTO_get_locking_callback() == openssl_lock) {
00108 int i;
00109 CRYPTO_set_locking_callback(NULL);
00110 for (i = 0; i < CRYPTO_num_locks(); i++)
00111 pthread_mutex_destroy(&openssl_mutexes[i]);
00112 av_free(openssl_mutexes);
00113 }
00114 #endif
00115 }
00116 #endif
00117 #if CONFIG_GNUTLS
00118 gnutls_global_deinit();
00119 #endif
00120 avpriv_unlock_avformat();
00121 }
00122
00123 int ff_network_inited_globally;
00124
00125 int ff_network_init(void)
00126 {
00127 if (!ff_network_inited_globally)
00128 av_log(NULL, AV_LOG_WARNING, "Using network protocols without global "
00129 "network initialization. Please use "
00130 "avformat_network_init(), this will "
00131 "become mandatory later.\n");
00132 #if HAVE_WINSOCK2_H
00133 WSADATA wsaData;
00134 if (WSAStartup(MAKEWORD(1,1), &wsaData))
00135 return 0;
00136 #endif
00137 return 1;
00138 }
00139
00140 int ff_network_wait_fd(int fd, int write)
00141 {
00142 int ev = write ? POLLOUT : POLLIN;
00143 struct pollfd p = { .fd = fd, .events = ev, .revents = 0 };
00144 int ret;
00145 ret = poll(&p, 1, 100);
00146 return ret < 0 ? ff_neterrno() : p.revents & (ev | POLLERR | POLLHUP) ? 0 : AVERROR(EAGAIN);
00147 }
00148
00149 void ff_network_close(void)
00150 {
00151 #if HAVE_WINSOCK2_H
00152 WSACleanup();
00153 #endif
00154 }
00155
00156 #if HAVE_WINSOCK2_H
00157 int ff_neterrno(void)
00158 {
00159 int err = WSAGetLastError();
00160 switch (err) {
00161 case WSAEWOULDBLOCK:
00162 return AVERROR(EAGAIN);
00163 case WSAEINTR:
00164 return AVERROR(EINTR);
00165 }
00166 return -err;
00167 }
00168 #endif
00169
00170 int ff_is_multicast_address(struct sockaddr *addr)
00171 {
00172 if (addr->sa_family == AF_INET) {
00173 return IN_MULTICAST(ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr));
00174 }
00175 #if HAVE_STRUCT_SOCKADDR_IN6
00176 if (addr->sa_family == AF_INET6) {
00177 return IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)addr)->sin6_addr);
00178 }
00179 #endif
00180
00181 return 0;
00182 }
00183