Use getaddrinfo(), if available, in resolve_host(). Patch by Martin
[ffmpeg.git] / libavformat / os_support.c
1 /*
2  * Various utilities for ffmpeg system
3  * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
4  * copyright (c) 2002 Francois Revol
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22
23 /* needed by inet_aton() */
24 #define _SVID_SOURCE
25
26 #include "config.h"
27 #include "avformat.h"
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <sys/time.h>
31 #include "os_support.h"
32
33 #if CONFIG_NETWORK
34 #if !HAVE_POLL_H
35 #if HAVE_WINSOCK2_H
36 #include <winsock2.h>
37 #elif HAVE_SYS_SELECT_H
38 #include <sys/select.h>
39 #endif
40 #endif
41
42 #include "network.h"
43
44 #if !HAVE_INET_ATON
45 #include <stdlib.h>
46 #include <strings.h>
47
48 int inet_aton (const char * str, struct in_addr * add)
49 {
50     unsigned int add1 = 0, add2 = 0, add3 = 0, add4 = 0;
51
52     if (sscanf(str, "%d.%d.%d.%d", &add1, &add2, &add3, &add4) != 4)
53         return 0;
54
55     if (!add1 || (add1|add2|add3|add4) > 255) return 0;
56
57     add->s_addr = htonl((add1 << 24) + (add2 << 16) + (add3 << 8) + add4);
58
59     return 1;
60 }
61 #endif /* !HAVE_INET_ATON */
62
63 /* resolve host with also IP address parsing */
64 int resolve_host(struct in_addr *sin_addr, const char *hostname)
65 {
66
67     if (!inet_aton(hostname, sin_addr)) {
68 #if HAVE_GETADDRINFO
69         struct addrinfo *ai, *cur;
70         struct addrinfo hints;
71         memset(&hints, 0, sizeof(hints));
72         hints.ai_family = AF_INET;
73         if (getaddrinfo(hostname, NULL, &hints, &ai))
74             return -1;
75         /* getaddrinfo returns a linked list of addrinfo structs.
76          * Even if we set ai_family = AF_INET above, make sure
77          * that the returned one actually is of the correct type. */
78         for (cur = ai; cur; cur = cur->ai_next) {
79             if (cur->ai_family == AF_INET) {
80                 *sin_addr = ((struct sockaddr_in *)cur->ai_addr)->sin_addr;
81                 freeaddrinfo(ai);
82                 return 0;
83             }
84         }
85         freeaddrinfo(ai);
86         return -1;
87 #else
88         struct hostent *hp;
89         hp = gethostbyname(hostname);
90         if (!hp)
91             return -1;
92         memcpy(sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
93 #endif
94     }
95     return 0;
96 }
97
98 int ff_socket_nonblock(int socket, int enable)
99 {
100 #if HAVE_WINSOCK2_H
101    return ioctlsocket(socket, FIONBIO, &enable);
102 #else
103    if (enable)
104       return fcntl(socket, F_SETFL, fcntl(socket, F_GETFL) | O_NONBLOCK);
105    else
106       return fcntl(socket, F_SETFL, fcntl(socket, F_GETFL) & ~O_NONBLOCK);
107 #endif
108 }
109 #endif /* CONFIG_NETWORK */
110
111 #if CONFIG_FFSERVER
112 #if !HAVE_POLL_H
113 int poll(struct pollfd *fds, nfds_t numfds, int timeout)
114 {
115     fd_set read_set;
116     fd_set write_set;
117     fd_set exception_set;
118     nfds_t i;
119     int n;
120     int rc;
121
122 #if HAVE_WINSOCK2_H
123     if (numfds >= FD_SETSIZE) {
124         errno = EINVAL;
125         return -1;
126     }
127 #endif
128
129     FD_ZERO(&read_set);
130     FD_ZERO(&write_set);
131     FD_ZERO(&exception_set);
132
133     n = -1;
134     for(i = 0; i < numfds; i++) {
135         if (fds[i].fd < 0)
136             continue;
137 #if !HAVE_WINSOCK2_H
138         if (fds[i].fd >= FD_SETSIZE) {
139             errno = EINVAL;
140             return -1;
141         }
142 #endif
143
144         if (fds[i].events & POLLIN)  FD_SET(fds[i].fd, &read_set);
145         if (fds[i].events & POLLOUT) FD_SET(fds[i].fd, &write_set);
146         if (fds[i].events & POLLERR) FD_SET(fds[i].fd, &exception_set);
147
148         if (fds[i].fd > n)
149             n = fds[i].fd;
150     };
151
152     if (n == -1)
153         /* Hey!? Nothing to poll, in fact!!! */
154         return 0;
155
156     if (timeout < 0)
157         rc = select(n+1, &read_set, &write_set, &exception_set, NULL);
158     else {
159         struct timeval    tv;
160
161         tv.tv_sec = timeout / 1000;
162         tv.tv_usec = 1000 * (timeout % 1000);
163         rc = select(n+1, &read_set, &write_set, &exception_set, &tv);
164     };
165
166     if (rc < 0)
167         return rc;
168
169     for(i = 0; i < (nfds_t) n; i++) {
170         fds[i].revents = 0;
171
172         if (FD_ISSET(fds[i].fd, &read_set))      fds[i].revents |= POLLIN;
173         if (FD_ISSET(fds[i].fd, &write_set))     fds[i].revents |= POLLOUT;
174         if (FD_ISSET(fds[i].fd, &exception_set)) fds[i].revents |= POLLERR;
175     };
176
177     return rc;
178 }
179 #endif /* HAVE_POLL_H */
180 #endif /* CONFIG_FFSERVER */
181