yading@11
|
1 /*
|
yading@11
|
2 * Copyright (c) 2007 The Libav Project
|
yading@11
|
3 *
|
yading@11
|
4 * This file is part of Libav.
|
yading@11
|
5 *
|
yading@11
|
6 * Libav is free software; you can redistribute it and/or
|
yading@11
|
7 * modify it under the terms of the GNU Lesser General Public
|
yading@11
|
8 * License as published by the Free Software Foundation; either
|
yading@11
|
9 * version 2.1 of the License, or (at your option) any later version.
|
yading@11
|
10 *
|
yading@11
|
11 * Libav is distributed in the hope that it will be useful,
|
yading@11
|
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
yading@11
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
yading@11
|
14 * Lesser General Public License for more details.
|
yading@11
|
15 *
|
yading@11
|
16 * You should have received a copy of the GNU Lesser General Public
|
yading@11
|
17 * License along with Libav; if not, write to the Free Software
|
yading@11
|
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
yading@11
|
19 */
|
yading@11
|
20
|
yading@11
|
21 #include "libavutil/avutil.h"
|
yading@11
|
22 #include "network.h"
|
yading@11
|
23 #include "libavcodec/internal.h"
|
yading@11
|
24 #include "libavutil/mem.h"
|
yading@11
|
25 #include "url.h"
|
yading@11
|
26 #include "libavutil/time.h"
|
yading@11
|
27
|
yading@11
|
28 #if HAVE_THREADS
|
yading@11
|
29 #if HAVE_PTHREADS
|
yading@11
|
30 #include <pthread.h>
|
yading@11
|
31 #elif HAVE_OS2THREADS
|
yading@11
|
32 #include "libavcodec/os2threads.h"
|
yading@11
|
33 #else
|
yading@11
|
34 #include "libavcodec/w32pthreads.h"
|
yading@11
|
35 #endif
|
yading@11
|
36 #endif
|
yading@11
|
37
|
yading@11
|
38 #if CONFIG_OPENSSL
|
yading@11
|
39 #include <openssl/ssl.h>
|
yading@11
|
40 static int openssl_init;
|
yading@11
|
41 #if HAVE_THREADS
|
yading@11
|
42 #include <openssl/crypto.h>
|
yading@11
|
43 #include "libavutil/avutil.h"
|
yading@11
|
44 pthread_mutex_t *openssl_mutexes;
|
yading@11
|
45 static void openssl_lock(int mode, int type, const char *file, int line)
|
yading@11
|
46 {
|
yading@11
|
47 if (mode & CRYPTO_LOCK)
|
yading@11
|
48 pthread_mutex_lock(&openssl_mutexes[type]);
|
yading@11
|
49 else
|
yading@11
|
50 pthread_mutex_unlock(&openssl_mutexes[type]);
|
yading@11
|
51 }
|
yading@11
|
52 #if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000
|
yading@11
|
53 static unsigned long openssl_thread_id(void)
|
yading@11
|
54 {
|
yading@11
|
55 return (intptr_t) pthread_self();
|
yading@11
|
56 }
|
yading@11
|
57 #endif
|
yading@11
|
58 #endif
|
yading@11
|
59 #endif
|
yading@11
|
60 #if CONFIG_GNUTLS
|
yading@11
|
61 #include <gnutls/gnutls.h>
|
yading@11
|
62 #if HAVE_THREADS && GNUTLS_VERSION_NUMBER <= 0x020b00
|
yading@11
|
63 #include <gcrypt.h>
|
yading@11
|
64 #include <errno.h>
|
yading@11
|
65 GCRY_THREAD_OPTION_PTHREAD_IMPL;
|
yading@11
|
66 #endif
|
yading@11
|
67 #endif
|
yading@11
|
68
|
yading@11
|
69 void ff_tls_init(void)
|
yading@11
|
70 {
|
yading@11
|
71 avpriv_lock_avformat();
|
yading@11
|
72 #if CONFIG_OPENSSL
|
yading@11
|
73 if (!openssl_init) {
|
yading@11
|
74 SSL_library_init();
|
yading@11
|
75 SSL_load_error_strings();
|
yading@11
|
76 #if HAVE_THREADS
|
yading@11
|
77 if (!CRYPTO_get_locking_callback()) {
|
yading@11
|
78 int i;
|
yading@11
|
79 openssl_mutexes = av_malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
|
yading@11
|
80 for (i = 0; i < CRYPTO_num_locks(); i++)
|
yading@11
|
81 pthread_mutex_init(&openssl_mutexes[i], NULL);
|
yading@11
|
82 CRYPTO_set_locking_callback(openssl_lock);
|
yading@11
|
83 #if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000
|
yading@11
|
84 CRYPTO_set_id_callback(openssl_thread_id);
|
yading@11
|
85 #endif
|
yading@11
|
86 }
|
yading@11
|
87 #endif
|
yading@11
|
88 }
|
yading@11
|
89 openssl_init++;
|
yading@11
|
90 #endif
|
yading@11
|
91 #if CONFIG_GNUTLS
|
yading@11
|
92 #if HAVE_THREADS && GNUTLS_VERSION_NUMBER < 0x020b00
|
yading@11
|
93 if (gcry_control(GCRYCTL_ANY_INITIALIZATION_P) == 0)
|
yading@11
|
94 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
|
yading@11
|
95 #endif
|
yading@11
|
96 gnutls_global_init();
|
yading@11
|
97 #endif
|
yading@11
|
98 avpriv_unlock_avformat();
|
yading@11
|
99 }
|
yading@11
|
100
|
yading@11
|
101 void ff_tls_deinit(void)
|
yading@11
|
102 {
|
yading@11
|
103 avpriv_lock_avformat();
|
yading@11
|
104 #if CONFIG_OPENSSL
|
yading@11
|
105 openssl_init--;
|
yading@11
|
106 if (!openssl_init) {
|
yading@11
|
107 #if HAVE_THREADS
|
yading@11
|
108 if (CRYPTO_get_locking_callback() == openssl_lock) {
|
yading@11
|
109 int i;
|
yading@11
|
110 CRYPTO_set_locking_callback(NULL);
|
yading@11
|
111 for (i = 0; i < CRYPTO_num_locks(); i++)
|
yading@11
|
112 pthread_mutex_destroy(&openssl_mutexes[i]);
|
yading@11
|
113 av_free(openssl_mutexes);
|
yading@11
|
114 }
|
yading@11
|
115 #endif
|
yading@11
|
116 }
|
yading@11
|
117 #endif
|
yading@11
|
118 #if CONFIG_GNUTLS
|
yading@11
|
119 gnutls_global_deinit();
|
yading@11
|
120 #endif
|
yading@11
|
121 avpriv_unlock_avformat();
|
yading@11
|
122 }
|
yading@11
|
123
|
yading@11
|
124 int ff_network_inited_globally;
|
yading@11
|
125
|
yading@11
|
126 int ff_network_init(void)
|
yading@11
|
127 {
|
yading@11
|
128 #if HAVE_WINSOCK2_H
|
yading@11
|
129 WSADATA wsaData;
|
yading@11
|
130 #endif
|
yading@11
|
131
|
yading@11
|
132 if (!ff_network_inited_globally)
|
yading@11
|
133 av_log(NULL, AV_LOG_WARNING, "Using network protocols without global "
|
yading@11
|
134 "network initialization. Please use "
|
yading@11
|
135 "avformat_network_init(), this will "
|
yading@11
|
136 "become mandatory later.\n");
|
yading@11
|
137 #if HAVE_WINSOCK2_H
|
yading@11
|
138 if (WSAStartup(MAKEWORD(1,1), &wsaData))
|
yading@11
|
139 return 0;
|
yading@11
|
140 #endif
|
yading@11
|
141 return 1;
|
yading@11
|
142 }
|
yading@11
|
143
|
yading@11
|
144 int ff_network_wait_fd(int fd, int write)
|
yading@11
|
145 {
|
yading@11
|
146 int ev = write ? POLLOUT : POLLIN;
|
yading@11
|
147 struct pollfd p = { .fd = fd, .events = ev, .revents = 0 };
|
yading@11
|
148 int ret;
|
yading@11
|
149 ret = poll(&p, 1, 100);
|
yading@11
|
150 return ret < 0 ? ff_neterrno() : p.revents & (ev | POLLERR | POLLHUP) ? 0 : AVERROR(EAGAIN);
|
yading@11
|
151 }
|
yading@11
|
152
|
yading@11
|
153 int ff_network_wait_fd_timeout(int fd, int write, int64_t timeout, AVIOInterruptCB *int_cb)
|
yading@11
|
154 {
|
yading@11
|
155 int ret;
|
yading@11
|
156 int64_t wait_start = 0;
|
yading@11
|
157
|
yading@11
|
158 while (1) {
|
yading@11
|
159 ret = ff_network_wait_fd(fd, write);
|
yading@11
|
160 if (ret != AVERROR(EAGAIN))
|
yading@11
|
161 return ret;
|
yading@11
|
162 if (ff_check_interrupt(int_cb))
|
yading@11
|
163 return AVERROR_EXIT;
|
yading@11
|
164 if (timeout) {
|
yading@11
|
165 if (!wait_start)
|
yading@11
|
166 wait_start = av_gettime();
|
yading@11
|
167 else if (av_gettime() - wait_start > timeout)
|
yading@11
|
168 return AVERROR(ETIMEDOUT);
|
yading@11
|
169 }
|
yading@11
|
170 }
|
yading@11
|
171 }
|
yading@11
|
172
|
yading@11
|
173 void ff_network_close(void)
|
yading@11
|
174 {
|
yading@11
|
175 #if HAVE_WINSOCK2_H
|
yading@11
|
176 WSACleanup();
|
yading@11
|
177 #endif
|
yading@11
|
178 }
|
yading@11
|
179
|
yading@11
|
180 #if HAVE_WINSOCK2_H
|
yading@11
|
181 int ff_neterrno(void)
|
yading@11
|
182 {
|
yading@11
|
183 int err = WSAGetLastError();
|
yading@11
|
184 switch (err) {
|
yading@11
|
185 case WSAEWOULDBLOCK:
|
yading@11
|
186 return AVERROR(EAGAIN);
|
yading@11
|
187 case WSAEINTR:
|
yading@11
|
188 return AVERROR(EINTR);
|
yading@11
|
189 case WSAEPROTONOSUPPORT:
|
yading@11
|
190 return AVERROR(EPROTONOSUPPORT);
|
yading@11
|
191 case WSAETIMEDOUT:
|
yading@11
|
192 return AVERROR(ETIMEDOUT);
|
yading@11
|
193 case WSAECONNREFUSED:
|
yading@11
|
194 return AVERROR(ECONNREFUSED);
|
yading@11
|
195 case WSAEINPROGRESS:
|
yading@11
|
196 return AVERROR(EINPROGRESS);
|
yading@11
|
197 }
|
yading@11
|
198 return -err;
|
yading@11
|
199 }
|
yading@11
|
200 #endif
|
yading@11
|
201
|
yading@11
|
202 int ff_is_multicast_address(struct sockaddr *addr)
|
yading@11
|
203 {
|
yading@11
|
204 if (addr->sa_family == AF_INET) {
|
yading@11
|
205 return IN_MULTICAST(ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr));
|
yading@11
|
206 }
|
yading@11
|
207 #if HAVE_STRUCT_SOCKADDR_IN6
|
yading@11
|
208 if (addr->sa_family == AF_INET6) {
|
yading@11
|
209 return IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)addr)->sin6_addr);
|
yading@11
|
210 }
|
yading@11
|
211 #endif
|
yading@11
|
212
|
yading@11
|
213 return 0;
|
yading@11
|
214 }
|