1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * various OS-feature replacement utilities 3cabdff1aSopenharmony_ci * Copyright (c) 2000, 2001, 2002 Fabrice Bellard 4cabdff1aSopenharmony_ci * copyright (c) 2002 Francois Revol 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * This file is part of FFmpeg. 7cabdff1aSopenharmony_ci * 8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 12cabdff1aSopenharmony_ci * 13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16cabdff1aSopenharmony_ci * Lesser General Public License for more details. 17cabdff1aSopenharmony_ci * 18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21cabdff1aSopenharmony_ci */ 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ci/* needed by inet_aton() */ 24cabdff1aSopenharmony_ci#define _DEFAULT_SOURCE 25cabdff1aSopenharmony_ci#define _SVID_SOURCE 26cabdff1aSopenharmony_ci 27cabdff1aSopenharmony_ci#include "config.h" 28cabdff1aSopenharmony_ci#include "avformat.h" 29cabdff1aSopenharmony_ci#include "os_support.h" 30cabdff1aSopenharmony_ci 31cabdff1aSopenharmony_ci#if CONFIG_NETWORK 32cabdff1aSopenharmony_ci#include <fcntl.h> 33cabdff1aSopenharmony_ci#if !HAVE_POLL_H 34cabdff1aSopenharmony_ci#if HAVE_SYS_TIME_H 35cabdff1aSopenharmony_ci#include <sys/time.h> 36cabdff1aSopenharmony_ci#endif /* HAVE_SYS_TIME_H */ 37cabdff1aSopenharmony_ci#if HAVE_WINSOCK2_H 38cabdff1aSopenharmony_ci#include <winsock2.h> 39cabdff1aSopenharmony_ci#elif HAVE_SYS_SELECT_H 40cabdff1aSopenharmony_ci#include <sys/select.h> 41cabdff1aSopenharmony_ci#endif /* HAVE_WINSOCK2_H */ 42cabdff1aSopenharmony_ci#endif /* !HAVE_POLL_H */ 43cabdff1aSopenharmony_ci 44cabdff1aSopenharmony_ci#include "network.h" 45cabdff1aSopenharmony_ci 46cabdff1aSopenharmony_ci#if !HAVE_GETADDRINFO 47cabdff1aSopenharmony_ci#if !HAVE_INET_ATON 48cabdff1aSopenharmony_ci#include <stdlib.h> 49cabdff1aSopenharmony_ci 50cabdff1aSopenharmony_cistatic int inet_aton(const char *str, struct in_addr *add) 51cabdff1aSopenharmony_ci{ 52cabdff1aSopenharmony_ci unsigned int add1 = 0, add2 = 0, add3 = 0, add4 = 0; 53cabdff1aSopenharmony_ci 54cabdff1aSopenharmony_ci if (sscanf(str, "%d.%d.%d.%d", &add1, &add2, &add3, &add4) != 4) 55cabdff1aSopenharmony_ci return 0; 56cabdff1aSopenharmony_ci 57cabdff1aSopenharmony_ci if (!add1 || (add1 | add2 | add3 | add4) > 255) 58cabdff1aSopenharmony_ci return 0; 59cabdff1aSopenharmony_ci 60cabdff1aSopenharmony_ci add->s_addr = htonl((add1 << 24) + (add2 << 16) + (add3 << 8) + add4); 61cabdff1aSopenharmony_ci 62cabdff1aSopenharmony_ci return 1; 63cabdff1aSopenharmony_ci} 64cabdff1aSopenharmony_ci#endif /* !HAVE_INET_ATON */ 65cabdff1aSopenharmony_ci 66cabdff1aSopenharmony_ciint ff_getaddrinfo(const char *node, const char *service, 67cabdff1aSopenharmony_ci const struct addrinfo *hints, struct addrinfo **res) 68cabdff1aSopenharmony_ci{ 69cabdff1aSopenharmony_ci struct hostent *h = NULL; 70cabdff1aSopenharmony_ci struct addrinfo *ai; 71cabdff1aSopenharmony_ci struct sockaddr_in *sin; 72cabdff1aSopenharmony_ci 73cabdff1aSopenharmony_ci *res = NULL; 74cabdff1aSopenharmony_ci sin = av_mallocz(sizeof(struct sockaddr_in)); 75cabdff1aSopenharmony_ci if (!sin) 76cabdff1aSopenharmony_ci return EAI_FAIL; 77cabdff1aSopenharmony_ci sin->sin_family = AF_INET; 78cabdff1aSopenharmony_ci 79cabdff1aSopenharmony_ci if (node) { 80cabdff1aSopenharmony_ci if (!inet_aton(node, &sin->sin_addr)) { 81cabdff1aSopenharmony_ci if (hints && (hints->ai_flags & AI_NUMERICHOST)) { 82cabdff1aSopenharmony_ci av_free(sin); 83cabdff1aSopenharmony_ci return EAI_FAIL; 84cabdff1aSopenharmony_ci } 85cabdff1aSopenharmony_ci h = gethostbyname(node); 86cabdff1aSopenharmony_ci if (!h) { 87cabdff1aSopenharmony_ci av_free(sin); 88cabdff1aSopenharmony_ci return EAI_FAIL; 89cabdff1aSopenharmony_ci } 90cabdff1aSopenharmony_ci memcpy(&sin->sin_addr, h->h_addr_list[0], sizeof(struct in_addr)); 91cabdff1aSopenharmony_ci } 92cabdff1aSopenharmony_ci } else { 93cabdff1aSopenharmony_ci if (hints && (hints->ai_flags & AI_PASSIVE)) 94cabdff1aSopenharmony_ci sin->sin_addr.s_addr = INADDR_ANY; 95cabdff1aSopenharmony_ci else 96cabdff1aSopenharmony_ci sin->sin_addr.s_addr = INADDR_LOOPBACK; 97cabdff1aSopenharmony_ci } 98cabdff1aSopenharmony_ci 99cabdff1aSopenharmony_ci /* Note: getaddrinfo allows service to be a string, which 100cabdff1aSopenharmony_ci * should be looked up using getservbyname. */ 101cabdff1aSopenharmony_ci if (service) 102cabdff1aSopenharmony_ci sin->sin_port = htons(atoi(service)); 103cabdff1aSopenharmony_ci 104cabdff1aSopenharmony_ci ai = av_mallocz(sizeof(struct addrinfo)); 105cabdff1aSopenharmony_ci if (!ai) { 106cabdff1aSopenharmony_ci av_free(sin); 107cabdff1aSopenharmony_ci return EAI_FAIL; 108cabdff1aSopenharmony_ci } 109cabdff1aSopenharmony_ci 110cabdff1aSopenharmony_ci *res = ai; 111cabdff1aSopenharmony_ci ai->ai_family = AF_INET; 112cabdff1aSopenharmony_ci ai->ai_socktype = hints ? hints->ai_socktype : 0; 113cabdff1aSopenharmony_ci switch (ai->ai_socktype) { 114cabdff1aSopenharmony_ci case SOCK_STREAM: 115cabdff1aSopenharmony_ci ai->ai_protocol = IPPROTO_TCP; 116cabdff1aSopenharmony_ci break; 117cabdff1aSopenharmony_ci case SOCK_DGRAM: 118cabdff1aSopenharmony_ci ai->ai_protocol = IPPROTO_UDP; 119cabdff1aSopenharmony_ci break; 120cabdff1aSopenharmony_ci default: 121cabdff1aSopenharmony_ci ai->ai_protocol = 0; 122cabdff1aSopenharmony_ci break; 123cabdff1aSopenharmony_ci } 124cabdff1aSopenharmony_ci 125cabdff1aSopenharmony_ci ai->ai_addr = (struct sockaddr *)sin; 126cabdff1aSopenharmony_ci ai->ai_addrlen = sizeof(struct sockaddr_in); 127cabdff1aSopenharmony_ci if (hints && (hints->ai_flags & AI_CANONNAME)) 128cabdff1aSopenharmony_ci ai->ai_canonname = h ? av_strdup(h->h_name) : NULL; 129cabdff1aSopenharmony_ci 130cabdff1aSopenharmony_ci ai->ai_next = NULL; 131cabdff1aSopenharmony_ci return 0; 132cabdff1aSopenharmony_ci} 133cabdff1aSopenharmony_ci 134cabdff1aSopenharmony_civoid ff_freeaddrinfo(struct addrinfo *res) 135cabdff1aSopenharmony_ci{ 136cabdff1aSopenharmony_ci av_freep(&res->ai_canonname); 137cabdff1aSopenharmony_ci av_freep(&res->ai_addr); 138cabdff1aSopenharmony_ci av_freep(&res); 139cabdff1aSopenharmony_ci} 140cabdff1aSopenharmony_ci 141cabdff1aSopenharmony_ciint ff_getnameinfo(const struct sockaddr *sa, int salen, 142cabdff1aSopenharmony_ci char *host, int hostlen, 143cabdff1aSopenharmony_ci char *serv, int servlen, int flags) 144cabdff1aSopenharmony_ci{ 145cabdff1aSopenharmony_ci const struct sockaddr_in *sin = (const struct sockaddr_in *)sa; 146cabdff1aSopenharmony_ci 147cabdff1aSopenharmony_ci if (sa->sa_family != AF_INET) 148cabdff1aSopenharmony_ci return EAI_FAMILY; 149cabdff1aSopenharmony_ci if (!host && !serv) 150cabdff1aSopenharmony_ci return EAI_NONAME; 151cabdff1aSopenharmony_ci 152cabdff1aSopenharmony_ci if (host && hostlen > 0) { 153cabdff1aSopenharmony_ci struct hostent *ent = NULL; 154cabdff1aSopenharmony_ci uint32_t a; 155cabdff1aSopenharmony_ci if (!(flags & NI_NUMERICHOST)) 156cabdff1aSopenharmony_ci ent = gethostbyaddr((const char *)&sin->sin_addr, 157cabdff1aSopenharmony_ci sizeof(sin->sin_addr), AF_INET); 158cabdff1aSopenharmony_ci 159cabdff1aSopenharmony_ci if (ent) { 160cabdff1aSopenharmony_ci snprintf(host, hostlen, "%s", ent->h_name); 161cabdff1aSopenharmony_ci } else if (flags & NI_NAMERQD) { 162cabdff1aSopenharmony_ci return EAI_NONAME; 163cabdff1aSopenharmony_ci } else { 164cabdff1aSopenharmony_ci a = ntohl(sin->sin_addr.s_addr); 165cabdff1aSopenharmony_ci snprintf(host, hostlen, "%d.%d.%d.%d", 166cabdff1aSopenharmony_ci ((a >> 24) & 0xff), ((a >> 16) & 0xff), 167cabdff1aSopenharmony_ci ((a >> 8) & 0xff), (a & 0xff)); 168cabdff1aSopenharmony_ci } 169cabdff1aSopenharmony_ci } 170cabdff1aSopenharmony_ci 171cabdff1aSopenharmony_ci if (serv && servlen > 0) { 172cabdff1aSopenharmony_ci if (!(flags & NI_NUMERICSERV)) 173cabdff1aSopenharmony_ci return EAI_FAIL; 174cabdff1aSopenharmony_ci snprintf(serv, servlen, "%d", ntohs(sin->sin_port)); 175cabdff1aSopenharmony_ci } 176cabdff1aSopenharmony_ci 177cabdff1aSopenharmony_ci return 0; 178cabdff1aSopenharmony_ci} 179cabdff1aSopenharmony_ci#endif /* !HAVE_GETADDRINFO */ 180cabdff1aSopenharmony_ci 181cabdff1aSopenharmony_ci#if !HAVE_GETADDRINFO || HAVE_WINSOCK2_H 182cabdff1aSopenharmony_ciconst char *ff_gai_strerror(int ecode) 183cabdff1aSopenharmony_ci{ 184cabdff1aSopenharmony_ci switch (ecode) { 185cabdff1aSopenharmony_ci case EAI_AGAIN: 186cabdff1aSopenharmony_ci return "Temporary failure in name resolution"; 187cabdff1aSopenharmony_ci case EAI_BADFLAGS: 188cabdff1aSopenharmony_ci return "Invalid flags for ai_flags"; 189cabdff1aSopenharmony_ci case EAI_FAIL: 190cabdff1aSopenharmony_ci return "A non-recoverable error occurred"; 191cabdff1aSopenharmony_ci case EAI_FAMILY: 192cabdff1aSopenharmony_ci return "The address family was not recognized or the address " 193cabdff1aSopenharmony_ci "length was invalid for the specified family"; 194cabdff1aSopenharmony_ci case EAI_MEMORY: 195cabdff1aSopenharmony_ci return "Memory allocation failure"; 196cabdff1aSopenharmony_ci#if EAI_NODATA != EAI_NONAME 197cabdff1aSopenharmony_ci case EAI_NODATA: 198cabdff1aSopenharmony_ci return "No address associated with hostname"; 199cabdff1aSopenharmony_ci#endif /* EAI_NODATA != EAI_NONAME */ 200cabdff1aSopenharmony_ci case EAI_NONAME: 201cabdff1aSopenharmony_ci return "The name does not resolve for the supplied parameters"; 202cabdff1aSopenharmony_ci case EAI_SERVICE: 203cabdff1aSopenharmony_ci return "servname not supported for ai_socktype"; 204cabdff1aSopenharmony_ci case EAI_SOCKTYPE: 205cabdff1aSopenharmony_ci return "ai_socktype not supported"; 206cabdff1aSopenharmony_ci } 207cabdff1aSopenharmony_ci 208cabdff1aSopenharmony_ci return "Unknown error"; 209cabdff1aSopenharmony_ci} 210cabdff1aSopenharmony_ci#endif /* !HAVE_GETADDRINFO || HAVE_WINSOCK2_H */ 211cabdff1aSopenharmony_ci 212cabdff1aSopenharmony_ciint ff_socket_nonblock(int socket, int enable) 213cabdff1aSopenharmony_ci{ 214cabdff1aSopenharmony_ci#if HAVE_WINSOCK2_H 215cabdff1aSopenharmony_ci u_long param = enable; 216cabdff1aSopenharmony_ci return ioctlsocket(socket, FIONBIO, ¶m); 217cabdff1aSopenharmony_ci#else 218cabdff1aSopenharmony_ci if (enable) 219cabdff1aSopenharmony_ci return fcntl(socket, F_SETFL, fcntl(socket, F_GETFL) | O_NONBLOCK); 220cabdff1aSopenharmony_ci else 221cabdff1aSopenharmony_ci return fcntl(socket, F_SETFL, fcntl(socket, F_GETFL) & ~O_NONBLOCK); 222cabdff1aSopenharmony_ci#endif /* HAVE_WINSOCK2_H */ 223cabdff1aSopenharmony_ci} 224cabdff1aSopenharmony_ci 225cabdff1aSopenharmony_ci#if !HAVE_POLL_H 226cabdff1aSopenharmony_ciint ff_poll(struct pollfd *fds, nfds_t numfds, int timeout) 227cabdff1aSopenharmony_ci{ 228cabdff1aSopenharmony_ci fd_set read_set; 229cabdff1aSopenharmony_ci fd_set write_set; 230cabdff1aSopenharmony_ci fd_set exception_set; 231cabdff1aSopenharmony_ci nfds_t i; 232cabdff1aSopenharmony_ci int n; 233cabdff1aSopenharmony_ci int rc; 234cabdff1aSopenharmony_ci 235cabdff1aSopenharmony_ci#if HAVE_WINSOCK2_H 236cabdff1aSopenharmony_ci if (numfds >= FD_SETSIZE) { 237cabdff1aSopenharmony_ci errno = EINVAL; 238cabdff1aSopenharmony_ci return -1; 239cabdff1aSopenharmony_ci } 240cabdff1aSopenharmony_ci#endif /* HAVE_WINSOCK2_H */ 241cabdff1aSopenharmony_ci 242cabdff1aSopenharmony_ci FD_ZERO(&read_set); 243cabdff1aSopenharmony_ci FD_ZERO(&write_set); 244cabdff1aSopenharmony_ci FD_ZERO(&exception_set); 245cabdff1aSopenharmony_ci 246cabdff1aSopenharmony_ci n = 0; 247cabdff1aSopenharmony_ci for (i = 0; i < numfds; i++) { 248cabdff1aSopenharmony_ci if (fds[i].fd < 0) 249cabdff1aSopenharmony_ci continue; 250cabdff1aSopenharmony_ci#if !HAVE_WINSOCK2_H 251cabdff1aSopenharmony_ci if (fds[i].fd >= FD_SETSIZE) { 252cabdff1aSopenharmony_ci errno = EINVAL; 253cabdff1aSopenharmony_ci return -1; 254cabdff1aSopenharmony_ci } 255cabdff1aSopenharmony_ci#endif /* !HAVE_WINSOCK2_H */ 256cabdff1aSopenharmony_ci 257cabdff1aSopenharmony_ci if (fds[i].events & POLLIN) 258cabdff1aSopenharmony_ci FD_SET(fds[i].fd, &read_set); 259cabdff1aSopenharmony_ci if (fds[i].events & POLLOUT) 260cabdff1aSopenharmony_ci FD_SET(fds[i].fd, &write_set); 261cabdff1aSopenharmony_ci if (fds[i].events & POLLERR) 262cabdff1aSopenharmony_ci FD_SET(fds[i].fd, &exception_set); 263cabdff1aSopenharmony_ci 264cabdff1aSopenharmony_ci if (fds[i].fd >= n) 265cabdff1aSopenharmony_ci n = fds[i].fd + 1; 266cabdff1aSopenharmony_ci } 267cabdff1aSopenharmony_ci 268cabdff1aSopenharmony_ci if (n == 0) 269cabdff1aSopenharmony_ci /* Hey!? Nothing to poll, in fact!!! */ 270cabdff1aSopenharmony_ci return 0; 271cabdff1aSopenharmony_ci 272cabdff1aSopenharmony_ci if (timeout < 0) { 273cabdff1aSopenharmony_ci rc = select(n, &read_set, &write_set, &exception_set, NULL); 274cabdff1aSopenharmony_ci } else { 275cabdff1aSopenharmony_ci struct timeval tv; 276cabdff1aSopenharmony_ci tv.tv_sec = timeout / 1000; 277cabdff1aSopenharmony_ci tv.tv_usec = 1000 * (timeout % 1000); 278cabdff1aSopenharmony_ci rc = select(n, &read_set, &write_set, &exception_set, &tv); 279cabdff1aSopenharmony_ci } 280cabdff1aSopenharmony_ci 281cabdff1aSopenharmony_ci if (rc < 0) 282cabdff1aSopenharmony_ci return rc; 283cabdff1aSopenharmony_ci 284cabdff1aSopenharmony_ci for (i = 0; i < numfds; i++) { 285cabdff1aSopenharmony_ci fds[i].revents = 0; 286cabdff1aSopenharmony_ci 287cabdff1aSopenharmony_ci if (FD_ISSET(fds[i].fd, &read_set)) 288cabdff1aSopenharmony_ci fds[i].revents |= POLLIN; 289cabdff1aSopenharmony_ci if (FD_ISSET(fds[i].fd, &write_set)) 290cabdff1aSopenharmony_ci fds[i].revents |= POLLOUT; 291cabdff1aSopenharmony_ci if (FD_ISSET(fds[i].fd, &exception_set)) 292cabdff1aSopenharmony_ci fds[i].revents |= POLLERR; 293cabdff1aSopenharmony_ci } 294cabdff1aSopenharmony_ci 295cabdff1aSopenharmony_ci return rc; 296cabdff1aSopenharmony_ci} 297cabdff1aSopenharmony_ci#endif /* !HAVE_POLL_H */ 298cabdff1aSopenharmony_ci 299cabdff1aSopenharmony_ci#endif /* CONFIG_NETWORK */ 300