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 HAVE_WINSOCK2_H
00128 WSADATA wsaData;
00129 #endif
00130
00131 if (!ff_network_inited_globally)
00132 av_log(NULL, AV_LOG_WARNING, "Using network protocols without global "
00133 "network initialization. Please use "
00134 "avformat_network_init(), this will "
00135 "become mandatory later.\n");
00136 #if HAVE_WINSOCK2_H
00137 if (WSAStartup(MAKEWORD(1,1), &wsaData))
00138 return 0;
00139 #endif
00140 return 1;
00141 }
00142
00143 int ff_network_wait_fd(int fd, int write)
00144 {
00145 int ev = write ? POLLOUT : POLLIN;
00146 struct pollfd p = { .fd = fd, .events = ev, .revents = 0 };
00147 int ret;
00148 ret = poll(&p, 1, 100);
00149 return ret < 0 ? ff_neterrno() : p.revents & (ev | POLLERR | POLLHUP) ? 0 : AVERROR(EAGAIN);
00150 }
00151
00152 void ff_network_close(void)
00153 {
00154 #if HAVE_WINSOCK2_H
00155 WSACleanup();
00156 #endif
00157 }
00158
00159 #if HAVE_WINSOCK2_H
00160 int ff_neterrno(void)
00161 {
00162 int err = WSAGetLastError();
00163 switch (err) {
00164 case WSAEWOULDBLOCK:
00165 return AVERROR(EAGAIN);
00166 case WSAEINTR:
00167 return AVERROR(EINTR);
00168 }
00169 return -err;
00170 }
00171 #endif
00172
00173 int ff_is_multicast_address(struct sockaddr *addr)
00174 {
00175 if (addr->sa_family == AF_INET) {
00176 return IN_MULTICAST(ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr));
00177 }
00178 #if HAVE_STRUCT_SOCKADDR_IN6
00179 if (addr->sa_family == AF_INET6) {
00180 return IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)addr)->sin6_addr);
00181 }
00182 #endif
00183
00184 return 0;
00185 }
00186