yading@11: /* yading@11: * Copyright (c) 2007 The Libav Project yading@11: * yading@11: * This file is part of Libav. yading@11: * yading@11: * Libav is free software; you can redistribute it and/or yading@11: * modify it under the terms of the GNU Lesser General Public yading@11: * License as published by the Free Software Foundation; either yading@11: * version 2.1 of the License, or (at your option) any later version. yading@11: * yading@11: * Libav is distributed in the hope that it will be useful, yading@11: * but WITHOUT ANY WARRANTY; without even the implied warranty of yading@11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU yading@11: * Lesser General Public License for more details. yading@11: * yading@11: * You should have received a copy of the GNU Lesser General Public yading@11: * License along with Libav; if not, write to the Free Software yading@11: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA yading@11: */ yading@11: yading@11: #include "libavutil/avutil.h" yading@11: #include "network.h" yading@11: #include "libavcodec/internal.h" yading@11: #include "libavutil/mem.h" yading@11: #include "url.h" yading@11: #include "libavutil/time.h" yading@11: yading@11: #if HAVE_THREADS yading@11: #if HAVE_PTHREADS yading@11: #include yading@11: #elif HAVE_OS2THREADS yading@11: #include "libavcodec/os2threads.h" yading@11: #else yading@11: #include "libavcodec/w32pthreads.h" yading@11: #endif yading@11: #endif yading@11: yading@11: #if CONFIG_OPENSSL yading@11: #include yading@11: static int openssl_init; yading@11: #if HAVE_THREADS yading@11: #include yading@11: #include "libavutil/avutil.h" yading@11: pthread_mutex_t *openssl_mutexes; yading@11: static void openssl_lock(int mode, int type, const char *file, int line) yading@11: { yading@11: if (mode & CRYPTO_LOCK) yading@11: pthread_mutex_lock(&openssl_mutexes[type]); yading@11: else yading@11: pthread_mutex_unlock(&openssl_mutexes[type]); yading@11: } yading@11: #if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000 yading@11: static unsigned long openssl_thread_id(void) yading@11: { yading@11: return (intptr_t) pthread_self(); yading@11: } yading@11: #endif yading@11: #endif yading@11: #endif yading@11: #if CONFIG_GNUTLS yading@11: #include yading@11: #if HAVE_THREADS && GNUTLS_VERSION_NUMBER <= 0x020b00 yading@11: #include yading@11: #include yading@11: GCRY_THREAD_OPTION_PTHREAD_IMPL; yading@11: #endif yading@11: #endif yading@11: yading@11: void ff_tls_init(void) yading@11: { yading@11: avpriv_lock_avformat(); yading@11: #if CONFIG_OPENSSL yading@11: if (!openssl_init) { yading@11: SSL_library_init(); yading@11: SSL_load_error_strings(); yading@11: #if HAVE_THREADS yading@11: if (!CRYPTO_get_locking_callback()) { yading@11: int i; yading@11: openssl_mutexes = av_malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks()); yading@11: for (i = 0; i < CRYPTO_num_locks(); i++) yading@11: pthread_mutex_init(&openssl_mutexes[i], NULL); yading@11: CRYPTO_set_locking_callback(openssl_lock); yading@11: #if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000 yading@11: CRYPTO_set_id_callback(openssl_thread_id); yading@11: #endif yading@11: } yading@11: #endif yading@11: } yading@11: openssl_init++; yading@11: #endif yading@11: #if CONFIG_GNUTLS yading@11: #if HAVE_THREADS && GNUTLS_VERSION_NUMBER < 0x020b00 yading@11: if (gcry_control(GCRYCTL_ANY_INITIALIZATION_P) == 0) yading@11: gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); yading@11: #endif yading@11: gnutls_global_init(); yading@11: #endif yading@11: avpriv_unlock_avformat(); yading@11: } yading@11: yading@11: void ff_tls_deinit(void) yading@11: { yading@11: avpriv_lock_avformat(); yading@11: #if CONFIG_OPENSSL yading@11: openssl_init--; yading@11: if (!openssl_init) { yading@11: #if HAVE_THREADS yading@11: if (CRYPTO_get_locking_callback() == openssl_lock) { yading@11: int i; yading@11: CRYPTO_set_locking_callback(NULL); yading@11: for (i = 0; i < CRYPTO_num_locks(); i++) yading@11: pthread_mutex_destroy(&openssl_mutexes[i]); yading@11: av_free(openssl_mutexes); yading@11: } yading@11: #endif yading@11: } yading@11: #endif yading@11: #if CONFIG_GNUTLS yading@11: gnutls_global_deinit(); yading@11: #endif yading@11: avpriv_unlock_avformat(); yading@11: } yading@11: yading@11: int ff_network_inited_globally; yading@11: yading@11: int ff_network_init(void) yading@11: { yading@11: #if HAVE_WINSOCK2_H yading@11: WSADATA wsaData; yading@11: #endif yading@11: yading@11: if (!ff_network_inited_globally) yading@11: av_log(NULL, AV_LOG_WARNING, "Using network protocols without global " yading@11: "network initialization. Please use " yading@11: "avformat_network_init(), this will " yading@11: "become mandatory later.\n"); yading@11: #if HAVE_WINSOCK2_H yading@11: if (WSAStartup(MAKEWORD(1,1), &wsaData)) yading@11: return 0; yading@11: #endif yading@11: return 1; yading@11: } yading@11: yading@11: int ff_network_wait_fd(int fd, int write) yading@11: { yading@11: int ev = write ? POLLOUT : POLLIN; yading@11: struct pollfd p = { .fd = fd, .events = ev, .revents = 0 }; yading@11: int ret; yading@11: ret = poll(&p, 1, 100); yading@11: return ret < 0 ? ff_neterrno() : p.revents & (ev | POLLERR | POLLHUP) ? 0 : AVERROR(EAGAIN); yading@11: } yading@11: yading@11: int ff_network_wait_fd_timeout(int fd, int write, int64_t timeout, AVIOInterruptCB *int_cb) yading@11: { yading@11: int ret; yading@11: int64_t wait_start = 0; yading@11: yading@11: while (1) { yading@11: ret = ff_network_wait_fd(fd, write); yading@11: if (ret != AVERROR(EAGAIN)) yading@11: return ret; yading@11: if (ff_check_interrupt(int_cb)) yading@11: return AVERROR_EXIT; yading@11: if (timeout) { yading@11: if (!wait_start) yading@11: wait_start = av_gettime(); yading@11: else if (av_gettime() - wait_start > timeout) yading@11: return AVERROR(ETIMEDOUT); yading@11: } yading@11: } yading@11: } yading@11: yading@11: void ff_network_close(void) yading@11: { yading@11: #if HAVE_WINSOCK2_H yading@11: WSACleanup(); yading@11: #endif yading@11: } yading@11: yading@11: #if HAVE_WINSOCK2_H yading@11: int ff_neterrno(void) yading@11: { yading@11: int err = WSAGetLastError(); yading@11: switch (err) { yading@11: case WSAEWOULDBLOCK: yading@11: return AVERROR(EAGAIN); yading@11: case WSAEINTR: yading@11: return AVERROR(EINTR); yading@11: case WSAEPROTONOSUPPORT: yading@11: return AVERROR(EPROTONOSUPPORT); yading@11: case WSAETIMEDOUT: yading@11: return AVERROR(ETIMEDOUT); yading@11: case WSAECONNREFUSED: yading@11: return AVERROR(ECONNREFUSED); yading@11: case WSAEINPROGRESS: yading@11: return AVERROR(EINPROGRESS); yading@11: } yading@11: return -err; yading@11: } yading@11: #endif yading@11: yading@11: int ff_is_multicast_address(struct sockaddr *addr) yading@11: { yading@11: if (addr->sa_family == AF_INET) { yading@11: return IN_MULTICAST(ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr)); yading@11: } yading@11: #if HAVE_STRUCT_SOCKADDR_IN6 yading@11: if (addr->sa_family == AF_INET6) { yading@11: return IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)addr)->sin6_addr); yading@11: } yading@11: #endif yading@11: yading@11: return 0; yading@11: }