Libav
network.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007 The Libav Project
3  *
4  * This file is part of Libav.
5  *
6  * Libav 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  * Libav 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 Libav; 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 "tls.h"
24 #include "url.h"
25 #include "libavcodec/internal.h"
26 #include "libavutil/mem.h"
27 
28 void ff_tls_init(void)
29 {
30 #if CONFIG_TLS_OPENSSL_PROTOCOL
32 #endif
33 #if CONFIG_TLS_GNUTLS_PROTOCOL
35 #endif
36 }
37 
38 void ff_tls_deinit(void)
39 {
40 #if CONFIG_TLS_OPENSSL_PROTOCOL
42 #endif
43 #if CONFIG_TLS_GNUTLS_PROTOCOL
45 #endif
46 }
47 
49 
50 int ff_network_init(void)
51 {
52 #if HAVE_WINSOCK2_H
53  WSADATA wsaData;
54 #endif
55 
57  av_log(NULL, AV_LOG_WARNING, "Using network protocols without global "
58  "network initialization. Please use "
59  "avformat_network_init(), this will "
60  "become mandatory later.\n");
61 #if HAVE_WINSOCK2_H
62  if (WSAStartup(MAKEWORD(1,1), &wsaData))
63  return 0;
64 #endif
65  return 1;
66 }
67 
68 int ff_network_wait_fd(int fd, int write)
69 {
70  int ev = write ? POLLOUT : POLLIN;
71  struct pollfd p = { .fd = fd, .events = ev, .revents = 0 };
72  int ret;
73  ret = poll(&p, 1, 100);
74  return ret < 0 ? ff_neterrno() : p.revents & (ev | POLLERR | POLLHUP) ? 0 : AVERROR(EAGAIN);
75 }
76 
77 void ff_network_close(void)
78 {
79 #if HAVE_WINSOCK2_H
80  WSACleanup();
81 #endif
82 }
83 
84 #if HAVE_WINSOCK2_H
85 int ff_neterrno(void)
86 {
87  int err = WSAGetLastError();
88  switch (err) {
89  case WSAEWOULDBLOCK:
90  return AVERROR(EAGAIN);
91  case WSAEINTR:
92  return AVERROR(EINTR);
93  case WSAEPROTONOSUPPORT:
94  return AVERROR(EPROTONOSUPPORT);
95  case WSAETIMEDOUT:
96  return AVERROR(ETIMEDOUT);
97  case WSAECONNREFUSED:
98  return AVERROR(ECONNREFUSED);
99  case WSAEINPROGRESS:
100  return AVERROR(EINPROGRESS);
101  }
102  return -err;
103 }
104 #endif
105 
106 int ff_is_multicast_address(struct sockaddr *addr)
107 {
108  if (addr->sa_family == AF_INET) {
109  return IN_MULTICAST(ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr));
110  }
111 #if HAVE_STRUCT_SOCKADDR_IN6
112  if (addr->sa_family == AF_INET6) {
113  return IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)addr)->sin6_addr);
114  }
115 #endif
116 
117  return 0;
118 }
119 
120 static int ff_poll_interrupt(struct pollfd *p, nfds_t nfds, int timeout,
121  AVIOInterruptCB *cb)
122 {
123  int runs = timeout / POLLING_TIME;
124  int ret = 0;
125 
126  do {
127  if (ff_check_interrupt(cb))
128  return AVERROR_EXIT;
129  ret = poll(p, nfds, POLLING_TIME);
130  if (ret != 0)
131  break;
132  } while (timeout < 0 || runs-- > 0);
133 
134  if (!ret)
135  return AVERROR(ETIMEDOUT);
136  if (ret < 0)
137  return AVERROR(errno);
138  return ret;
139 }
140 
141 int ff_socket(int af, int type, int proto)
142 {
143  int fd;
144 
145 #ifdef SOCK_CLOEXEC
146  fd = socket(af, type | SOCK_CLOEXEC, proto);
147  if (fd == -1 && errno == EINVAL)
148 #endif
149  {
150  fd = socket(af, type, proto);
151 #if HAVE_FCNTL
152  if (fd != -1)
153  fcntl(fd, F_SETFD, FD_CLOEXEC);
154 #endif
155  }
156 #ifdef SO_NOSIGPIPE
157  if (fd != -1)
158  setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &(int){1}, sizeof(int));
159 #endif
160  return fd;
161 }
162 
163 int ff_listen_bind(int fd, const struct sockaddr *addr,
164  socklen_t addrlen, int timeout, URLContext *h)
165 {
166  int ret;
167  int reuse = 1;
168  struct pollfd lp = { fd, POLLIN, 0 };
169  setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
170  ret = bind(fd, addr, addrlen);
171  if (ret)
172  return ff_neterrno();
173 
174  ret = listen(fd, 1);
175  if (ret)
176  return ff_neterrno();
177 
178  ret = ff_poll_interrupt(&lp, 1, timeout, &h->interrupt_callback);
179  if (ret < 0)
180  return ret;
181 
182  ret = accept(fd, NULL, NULL);
183  if (ret < 0)
184  return ff_neterrno();
185 
186  closesocket(fd);
187 
188  ff_socket_nonblock(ret, 1);
189  return ret;
190 }
191 
192 int ff_listen_connect(int fd, const struct sockaddr *addr,
193  socklen_t addrlen, int timeout, URLContext *h,
194  int will_try_next)
195 {
196  struct pollfd p = {fd, POLLOUT, 0};
197  int ret;
198  socklen_t optlen;
199 
200  ff_socket_nonblock(fd, 1);
201 
202  while ((ret = connect(fd, addr, addrlen))) {
203  ret = ff_neterrno();
204  switch (ret) {
205  case AVERROR(EINTR):
207  return AVERROR_EXIT;
208  continue;
209  case AVERROR(EINPROGRESS):
210  case AVERROR(EAGAIN):
211  ret = ff_poll_interrupt(&p, 1, timeout, &h->interrupt_callback);
212  if (ret < 0)
213  return ret;
214  optlen = sizeof(ret);
215  if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen))
216  ret = AVUNERROR(ff_neterrno());
217  if (ret != 0) {
218  char errbuf[100];
219  ret = AVERROR(ret);
220  av_strerror(ret, errbuf, sizeof(errbuf));
221  if (will_try_next)
223  "Connection to %s failed (%s), trying next address\n",
224  h->filename, errbuf);
225  else
226  av_log(h, AV_LOG_ERROR, "Connection to %s failed: %s\n",
227  h->filename, errbuf);
228  }
229  default:
230  return ret;
231  }
232  }
233  return ret;
234 }
235 
236 static int match_host_pattern(const char *pattern, const char *hostname)
237 {
238  int len_p, len_h;
239  if (!strcmp(pattern, "*"))
240  return 1;
241  // Skip a possible *. at the start of the pattern
242  if (pattern[0] == '*')
243  pattern++;
244  if (pattern[0] == '.')
245  pattern++;
246  len_p = strlen(pattern);
247  len_h = strlen(hostname);
248  if (len_p > len_h)
249  return 0;
250  // Simply check if the end of hostname is equal to 'pattern'
251  if (!strcmp(pattern, &hostname[len_h - len_p])) {
252  if (len_h == len_p)
253  return 1; // Exact match
254  if (hostname[len_h - len_p - 1] == '.')
255  return 1; // The matched substring is a domain and not just a substring of a domain
256  }
257  return 0;
258 }
259 
260 int ff_http_match_no_proxy(const char *no_proxy, const char *hostname)
261 {
262  char *buf, *start;
263  int ret = 0;
264  if (!no_proxy)
265  return 0;
266  if (!hostname)
267  return 0;
268  buf = av_strdup(no_proxy);
269  if (!buf)
270  return 0;
271  start = buf;
272  while (start) {
273  char *sep, *next = NULL;
274  start += strspn(start, " ,");
275  sep = start + strcspn(start, " ,");
276  if (*sep) {
277  next = sep + 1;
278  *sep = '\0';
279  }
280  if (match_host_pattern(start, hostname)) {
281  ret = 1;
282  break;
283  }
284  start = next;
285  }
286  av_free(buf);
287  return ret;
288 }
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:130
memory handling functions
static int match_host_pattern(const char *pattern, const char *hostname)
Definition: network.c:236
AVIOInterruptCB interrupt_callback
Definition: url.h:51
av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (%s)\, len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt), use_generic ? ac->func_descr_generic :ac->func_descr)
void ff_network_close(void)
Definition: network.c:77
static int ff_poll_interrupt(struct pollfd *p, nfds_t nfds, int timeout, AVIOInterruptCB *cb)
Definition: network.c:120
int ff_socket(int af, int type, int proto)
Definition: network.c:141
int ff_network_inited_globally
Definition: network.c:48
#define IN6_IS_ADDR_MULTICAST(a)
Definition: network.h:213
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:163
int ff_network_init(void)
Definition: network.c:50
void ff_gnutls_init(void)
Definition: tls_gnutls.c:52
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:192
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:124
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:190
#define AVERROR(e)
Definition: error.h:43
int ff_is_multicast_address(struct sockaddr *addr)
Definition: network.c:106
#define ff_neterrno()
Definition: network.h:63
int ff_http_match_no_proxy(const char *no_proxy, const char *hostname)
Definition: network.c:260
void ff_openssl_init(void)
Definition: tls_openssl.c:69
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:52
NULL
Definition: eval.c:55
int ff_check_interrupt(AVIOInterruptCB *cb)
Check if the user has requested to interrupt a blocking function associated with cb.
Definition: avio.c:374
char * av_strdup(const char *s)
Duplicate the string s.
Definition: mem.c:219
Definition: url.h:38
#define IN_MULTICAST(a)
Definition: network.h:210
#define POLLING_TIME
Definition: network.h:218
void ff_gnutls_deinit(void)
Definition: tls_gnutls.c:63
int av_strerror(int errnum, char *errbuf, size_t errbuf_size)
Put a description of the AVERROR code errnum in errbuf.
Definition: error.c:23
common internal api header.
char * filename
specified URL
Definition: url.h:46
#define AVUNERROR(e)
Definition: error.h:44
void ff_tls_init(void)
Definition: network.c:28
void ff_tls_deinit(void)
Definition: network.c:38
int ff_network_wait_fd(int fd, int write)
Definition: network.c:68
void ff_openssl_deinit(void)
Definition: tls_openssl.c:92
unbuffered private I/O API