FFmpeg  2.6.9
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
network.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007 The FFmpeg Project
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include <fcntl.h>
22 #include "network.h"
23 #include "url.h"
24 #include "libavcodec/internal.h"
25 #include "libavutil/avutil.h"
26 #include "libavutil/mem.h"
27 #include "libavutil/time.h"
28 
29 #if HAVE_THREADS
30 #if HAVE_PTHREADS
31 #include <pthread.h>
32 #elif HAVE_OS2THREADS
33 #include "compat/os2threads.h"
34 #else
35 #include "compat/w32pthreads.h"
36 #endif
37 #endif
38 
39 #if CONFIG_OPENSSL
40 #include <openssl/ssl.h>
41 static int openssl_init;
42 #if HAVE_THREADS
43 #include <openssl/crypto.h>
44 pthread_mutex_t *openssl_mutexes;
45 static void openssl_lock(int mode, int type, const char *file, int line)
46 {
47  if (mode & CRYPTO_LOCK)
48  pthread_mutex_lock(&openssl_mutexes[type]);
49  else
50  pthread_mutex_unlock(&openssl_mutexes[type]);
51 }
52 #if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000
53 static unsigned long openssl_thread_id(void)
54 {
55  return (intptr_t) pthread_self();
56 }
57 #endif
58 #endif
59 #endif
60 #if CONFIG_GNUTLS
61 #include <gnutls/gnutls.h>
62 #if HAVE_THREADS && GNUTLS_VERSION_NUMBER <= 0x020b00
63 #include <gcrypt.h>
64 #include <errno.h>
65 GCRY_THREAD_OPTION_PTHREAD_IMPL;
66 #endif
67 #endif
68 
69 int ff_tls_init(void)
70 {
72 #if CONFIG_OPENSSL
73  if (!openssl_init) {
74  SSL_library_init();
75  SSL_load_error_strings();
76 #if HAVE_THREADS
77  if (!CRYPTO_get_locking_callback()) {
78  int i;
79  openssl_mutexes = av_malloc_array(sizeof(pthread_mutex_t), CRYPTO_num_locks());
80  if (!openssl_mutexes) {
82  return AVERROR(ENOMEM);
83  }
84  for (i = 0; i < CRYPTO_num_locks(); i++)
85  pthread_mutex_init(&openssl_mutexes[i], NULL);
86  CRYPTO_set_locking_callback(openssl_lock);
87 #if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000
88  CRYPTO_set_id_callback(openssl_thread_id);
89 #endif
90  }
91 #endif
92  }
93  openssl_init++;
94 #endif
95 #if CONFIG_GNUTLS
96 #if HAVE_THREADS && GNUTLS_VERSION_NUMBER < 0x020b00
97  if (gcry_control(GCRYCTL_ANY_INITIALIZATION_P) == 0)
98  gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
99 #endif
100  gnutls_global_init();
101 #endif
103 
104  return 0;
105 }
106 
107 void ff_tls_deinit(void)
108 {
110 #if CONFIG_OPENSSL
111  openssl_init--;
112  if (!openssl_init) {
113 #if HAVE_THREADS
114  if (CRYPTO_get_locking_callback() == openssl_lock) {
115  int i;
116  CRYPTO_set_locking_callback(NULL);
117  for (i = 0; i < CRYPTO_num_locks(); i++)
118  pthread_mutex_destroy(&openssl_mutexes[i]);
119  av_free(openssl_mutexes);
120  }
121 #endif
122  }
123 #endif
124 #if CONFIG_GNUTLS
125  gnutls_global_deinit();
126 #endif
128 }
129 
131 
133 {
134 #if HAVE_WINSOCK2_H
135  WSADATA wsaData;
136 #endif
137 
138  if (!ff_network_inited_globally)
139  av_log(NULL, AV_LOG_WARNING, "Using network protocols without global "
140  "network initialization. Please use "
141  "avformat_network_init(), this will "
142  "become mandatory later.\n");
143 #if HAVE_WINSOCK2_H
144  if (WSAStartup(MAKEWORD(1,1), &wsaData))
145  return 0;
146 #endif
147  return 1;
148 }
149 
150 int ff_network_wait_fd(int fd, int write)
151 {
152  int ev = write ? POLLOUT : POLLIN;
153  struct pollfd p = { .fd = fd, .events = ev, .revents = 0 };
154  int ret;
155  ret = poll(&p, 1, 100);
156  return ret < 0 ? ff_neterrno() : p.revents & (ev | POLLERR | POLLHUP) ? 0 : AVERROR(EAGAIN);
157 }
158 
159 int ff_network_wait_fd_timeout(int fd, int write, int64_t timeout, AVIOInterruptCB *int_cb)
160 {
161  int ret;
162  int64_t wait_start = 0;
163 
164  while (1) {
165  if (ff_check_interrupt(int_cb))
166  return AVERROR_EXIT;
167  ret = ff_network_wait_fd(fd, write);
168  if (ret != AVERROR(EAGAIN))
169  return ret;
170  if (timeout > 0) {
171  if (!wait_start)
172  wait_start = av_gettime_relative();
173  else if (av_gettime_relative() - wait_start > timeout)
174  return AVERROR(ETIMEDOUT);
175  }
176  }
177 }
178 
180 {
181 #if HAVE_WINSOCK2_H
182  WSACleanup();
183 #endif
184 }
185 
186 #if HAVE_WINSOCK2_H
187 int ff_neterrno(void)
188 {
189  int err = WSAGetLastError();
190  switch (err) {
191  case WSAEWOULDBLOCK:
192  return AVERROR(EAGAIN);
193  case WSAEINTR:
194  return AVERROR(EINTR);
195  case WSAEPROTONOSUPPORT:
196  return AVERROR(EPROTONOSUPPORT);
197  case WSAETIMEDOUT:
198  return AVERROR(ETIMEDOUT);
199  case WSAECONNREFUSED:
200  return AVERROR(ECONNREFUSED);
201  case WSAEINPROGRESS:
202  return AVERROR(EINPROGRESS);
203  }
204  return -err;
205 }
206 #endif
207 
208 int ff_is_multicast_address(struct sockaddr *addr)
209 {
210  if (addr->sa_family == AF_INET) {
211  return IN_MULTICAST(ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr));
212  }
213 #if HAVE_STRUCT_SOCKADDR_IN6
214  if (addr->sa_family == AF_INET6) {
215  return IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)addr)->sin6_addr);
216  }
217 #endif
218 
219  return 0;
220 }
221 
222 static int ff_poll_interrupt(struct pollfd *p, nfds_t nfds, int timeout,
224 {
225  int runs = timeout / POLLING_TIME;
226  int ret = 0;
227 
228  do {
229  if (ff_check_interrupt(cb))
230  return AVERROR_EXIT;
231  ret = poll(p, nfds, POLLING_TIME);
232  if (ret != 0)
233  break;
234  } while (timeout <= 0 || runs-- > 0);
235 
236  if (!ret)
237  return AVERROR(ETIMEDOUT);
238  if (ret < 0)
239  return AVERROR(errno);
240  return ret;
241 }
242 
243 int ff_socket(int af, int type, int proto)
244 {
245  int fd;
246 
247 #ifdef SOCK_CLOEXEC
248  fd = socket(af, type | SOCK_CLOEXEC, proto);
249  if (fd == -1 && errno == EINVAL)
250 #endif
251  {
252  fd = socket(af, type, proto);
253 #if HAVE_FCNTL
254  if (fd != -1) {
255  if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
256  av_log(NULL, AV_LOG_DEBUG, "Failed to set close on exec\n");
257  }
258 #endif
259  }
260  return fd;
261 }
262 
263 int ff_listen_bind(int fd, const struct sockaddr *addr,
264  socklen_t addrlen, int timeout, URLContext *h)
265 {
266  int ret;
267  int reuse = 1;
268  struct pollfd lp = { fd, POLLIN, 0 };
269  if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))) {
270  av_log(NULL, AV_LOG_WARNING, "setsockopt(SO_REUSEADDR) failed\n");
271  }
272  ret = bind(fd, addr, addrlen);
273  if (ret)
274  return ff_neterrno();
275 
276  ret = listen(fd, 1);
277  if (ret)
278  return ff_neterrno();
279 
280  ret = ff_poll_interrupt(&lp, 1, timeout, &h->interrupt_callback);
281  if (ret < 0)
282  return ret;
283 
284  ret = accept(fd, NULL, NULL);
285  if (ret < 0)
286  return ff_neterrno();
287 
288  closesocket(fd);
289 
290  if (ff_socket_nonblock(ret, 1) < 0)
291  av_log(NULL, AV_LOG_DEBUG, "ff_socket_nonblock failed\n");
292 
293  return ret;
294 }
295 
296 int ff_listen_connect(int fd, const struct sockaddr *addr,
297  socklen_t addrlen, int timeout, URLContext *h,
298  int will_try_next)
299 {
300  struct pollfd p = {fd, POLLOUT, 0};
301  int ret;
302  socklen_t optlen;
303 
304  if (ff_socket_nonblock(fd, 1) < 0)
305  av_log(NULL, AV_LOG_DEBUG, "ff_socket_nonblock failed\n");
306 
307  while ((ret = connect(fd, addr, addrlen))) {
308  ret = ff_neterrno();
309  switch (ret) {
310  case AVERROR(EINTR):
312  return AVERROR_EXIT;
313  continue;
314  case AVERROR(EINPROGRESS):
315  case AVERROR(EAGAIN):
316  ret = ff_poll_interrupt(&p, 1, timeout, &h->interrupt_callback);
317  if (ret < 0)
318  return ret;
319  optlen = sizeof(ret);
320  if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen))
321  ret = AVUNERROR(ff_neterrno());
322  if (ret != 0) {
323  char errbuf[100];
324  ret = AVERROR(ret);
325  av_strerror(ret, errbuf, sizeof(errbuf));
326  if (will_try_next)
328  "Connection to %s failed (%s), trying next address\n",
329  h->filename, errbuf);
330  else
331  av_log(h, AV_LOG_ERROR, "Connection to %s failed: %s\n",
332  h->filename, errbuf);
333  }
334  default:
335  return ret;
336  }
337  }
338  return ret;
339 }
340 
341 static int match_host_pattern(const char *pattern, const char *hostname)
342 {
343  int len_p, len_h;
344  if (!strcmp(pattern, "*"))
345  return 1;
346  // Skip a possible *. at the start of the pattern
347  if (pattern[0] == '*')
348  pattern++;
349  if (pattern[0] == '.')
350  pattern++;
351  len_p = strlen(pattern);
352  len_h = strlen(hostname);
353  if (len_p > len_h)
354  return 0;
355  // Simply check if the end of hostname is equal to 'pattern'
356  if (!strcmp(pattern, &hostname[len_h - len_p])) {
357  if (len_h == len_p)
358  return 1; // Exact match
359  if (hostname[len_h - len_p - 1] == '.')
360  return 1; // The matched substring is a domain and not just a substring of a domain
361  }
362  return 0;
363 }
364 
365 int ff_http_match_no_proxy(const char *no_proxy, const char *hostname)
366 {
367  char *buf, *start;
368  int ret = 0;
369  if (!no_proxy)
370  return 0;
371  if (!hostname)
372  return 0;
373  buf = av_strdup(no_proxy);
374  if (!buf)
375  return 0;
376  start = buf;
377  while (start) {
378  char *sep, *next = NULL;
379  start += strspn(start, " ,");
380  sep = start + strcspn(start, " ,");
381  if (*sep) {
382  next = sep + 1;
383  *sep = '\0';
384  }
385  if (match_host_pattern(start, hostname)) {
386  ret = 1;
387  break;
388  }
389  start = next;
390  }
391  av_free(buf);
392  return ret;
393 }
#define NULL
Definition: coverity.c:32
static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
Definition: os2threads.h:92
int avpriv_unlock_avformat(void)
Definition: utils.c:3643
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:181
memory handling functions
static int match_host_pattern(const char *pattern, const char *hostname)
Definition: network.c:341
AVIOInterruptCB interrupt_callback
Definition: url.h:48
os2threads to pthreads wrapper
external API header
void ff_network_close(void)
Definition: network.c:179
int ff_tls_init(void)
Definition: network.c:69
static int ff_poll_interrupt(struct pollfd *p, nfds_t nfds, int timeout, AVIOInterruptCB *cb)
Definition: network.c:222
int ff_socket(int af, int type, int proto)
Definition: network.c:243
int ff_network_inited_globally
Definition: network.c:130
#define IN6_IS_ADDR_MULTICAST(a)
Definition: network.h:234
static double cb(void *priv, double x, double y)
Definition: vf_geq.c:96
int ff_listen_bind(int fd, const struct sockaddr *addr, socklen_t addrlen, int timeout, URLContext *h)
Bind to a file descriptor and poll for a connection.
Definition: network.c:263
HMTX pthread_mutex_t
Definition: os2threads.h:40
int ff_network_init(void)
Definition: network.c:132
mode
Definition: f_perms.c:27
int ff_listen_connect(int fd, const struct sockaddr *addr, socklen_t addrlen, int timeout, URLContext *h, int will_try_next)
Connect to a file descriptor and poll for result.
Definition: network.c:296
#define av_log(a,...)
Callback for checking whether to abort blocking functions.
Definition: avio.h:51
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:175
const AVIOInterruptCB int_cb
Definition: ffmpeg.c:423
#define closesocket
Definition: ffserver.c:28
#define AVERROR(e)
Definition: error.h:43
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:196
Definition: graph2dot.c:48
int avpriv_lock_avformat(void)
Definition: utils.c:3634
int ff_is_multicast_address(struct sockaddr *addr)
Definition: network.c:208
int ff_network_wait_fd_timeout(int fd, int write, int64_t timeout, AVIOInterruptCB *int_cb)
This works similarly to ff_network_wait_fd, but waits up to 'timeout' microseconds Uses ff_network_wa...
Definition: network.c:159
ret
Definition: avfilter.c:974
#define ff_neterrno()
Definition: network.h:64
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
Definition: os2threads.h:85
int ff_http_match_no_proxy(const char *no_proxy, const char *hostname)
Definition: network.c:365
int ff_socket_nonblock(int socket, int enable)
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
Definition: error.h:56
int ff_check_interrupt(AVIOInterruptCB *cb)
Check if the user has requested to interrup a blocking function associated with cb.
Definition: avio.c:470
char * av_strdup(const char *s)
Duplicate the string s.
Definition: mem.c:265
void * buf
Definition: avisynth_c.h:595
Definition: url.h:39
GLint GLenum type
Definition: opengl_enc.c:105
#define IN_MULTICAST(a)
Definition: network.h:231
#define POLLING_TIME
Definition: network.h:239
int64_t av_gettime_relative(void)
Get the current time in microseconds since some unspecified starting point.
Definition: time.c:56
int av_strerror(int errnum, char *errbuf, size_t errbuf_size)
Put a description of the AVERROR code errnum in errbuf.
Definition: error.c:68
common internal api header.
char * filename
specified URL
Definition: url.h:43
#define AVUNERROR(e)
Definition: error.h:44
#define av_free(p)
static av_always_inline int pthread_mutex_unlock(pthread_mutex_t *mutex)
Definition: os2threads.h:106
w32threads to pthreads wrapper
void ff_tls_deinit(void)
Definition: network.c:107
int ff_network_wait_fd(int fd, int write)
Definition: network.c:150
void INT64 start
Definition: avisynth_c.h:595
unbuffered private I/O API
static av_always_inline int pthread_mutex_lock(pthread_mutex_t *mutex)
Definition: os2threads.h:99
#define av_malloc_array(a, b)
#define MAKEWORD(a, b)
Definition: windows2linux.h:56