Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * various OS-feature replacement utilities
  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 _DEFAULT_SOURCE
  25. #define _SVID_SOURCE
  26.  
  27. #include "config.h"
  28. #include "avformat.h"
  29. #include "os_support.h"
  30.  
  31. #if CONFIG_NETWORK
  32. #include <fcntl.h>
  33. #if !HAVE_POLL_H
  34. #if HAVE_SYS_TIME_H
  35. #include <sys/time.h>
  36. #endif /* HAVE_SYS_TIME_H */
  37. #if HAVE_WINSOCK2_H
  38. #include <winsock2.h>
  39. #elif HAVE_SYS_SELECT_H
  40. #include <sys/select.h>
  41. #endif /* HAVE_WINSOCK2_H */
  42. #endif /* !HAVE_POLL_H */
  43.  
  44. #include "network.h"
  45.  
  46. #if !HAVE_INET_ATON
  47. #include <stdlib.h>
  48.  
  49. int ff_inet_aton(const char *str, struct in_addr *add)
  50. {
  51.     unsigned int add1 = 0, add2 = 0, add3 = 0, add4 = 0;
  52.  
  53.     if (sscanf(str, "%d.%d.%d.%d", &add1, &add2, &add3, &add4) != 4)
  54.         return 0;
  55.  
  56.     if (!add1 || (add1 | add2 | add3 | add4) > 255)
  57.         return 0;
  58.  
  59.     add->s_addr = htonl((add1 << 24) + (add2 << 16) + (add3 << 8) + add4);
  60.  
  61.     return 1;
  62. }
  63. #else
  64. int ff_inet_aton(const char *str, struct in_addr *add)
  65. {
  66.     return inet_aton(str, add);
  67. }
  68. #endif /* !HAVE_INET_ATON */
  69.  
  70. #if !HAVE_GETADDRINFO
  71. int ff_getaddrinfo(const char *node, const char *service,
  72.                    const struct addrinfo *hints, struct addrinfo **res)
  73. {
  74.     struct hostent *h = NULL;
  75.     struct addrinfo *ai;
  76.     struct sockaddr_in *sin;
  77.  
  78. #if HAVE_WINSOCK2_H
  79.     int (WSAAPI *win_getaddrinfo)(const char *node, const char *service,
  80.                                   const struct addrinfo *hints,
  81.                                   struct addrinfo **res);
  82.     HMODULE ws2mod = GetModuleHandle("ws2_32.dll");
  83.     win_getaddrinfo = GetProcAddress(ws2mod, "getaddrinfo");
  84.     if (win_getaddrinfo)
  85.         return win_getaddrinfo(node, service, hints, res);
  86. #endif /* HAVE_WINSOCK2_H */
  87.  
  88.     *res = NULL;
  89.     sin  = av_mallocz(sizeof(struct sockaddr_in));
  90.     if (!sin)
  91.         return EAI_FAIL;
  92.     sin->sin_family = AF_INET;
  93.  
  94.     if (node) {
  95.         if (!ff_inet_aton(node, &sin->sin_addr)) {
  96.             if (hints && (hints->ai_flags & AI_NUMERICHOST)) {
  97.                 av_free(sin);
  98.                 return EAI_FAIL;
  99.             }
  100.             h = gethostbyname(node);
  101.             if (!h) {
  102.                 av_free(sin);
  103.                 return EAI_FAIL;
  104.             }
  105.             memcpy(&sin->sin_addr, h->h_addr_list[0], sizeof(struct in_addr));
  106.         }
  107.     } else {
  108.         if (hints && (hints->ai_flags & AI_PASSIVE))
  109.             sin->sin_addr.s_addr = INADDR_ANY;
  110.         else
  111.             sin->sin_addr.s_addr = INADDR_LOOPBACK;
  112.     }
  113.  
  114.     /* Note: getaddrinfo allows service to be a string, which
  115.      * should be looked up using getservbyname. */
  116.     if (service)
  117.         sin->sin_port = htons(atoi(service));
  118.  
  119.     ai = av_mallocz(sizeof(struct addrinfo));
  120.     if (!ai) {
  121.         av_free(sin);
  122.         return EAI_FAIL;
  123.     }
  124.  
  125.     *res            = ai;
  126.     ai->ai_family   = AF_INET;
  127.     ai->ai_socktype = hints ? hints->ai_socktype : 0;
  128.     switch (ai->ai_socktype) {
  129.     case SOCK_STREAM:
  130.         ai->ai_protocol = IPPROTO_TCP;
  131.         break;
  132.     case SOCK_DGRAM:
  133.         ai->ai_protocol = IPPROTO_UDP;
  134.         break;
  135.     default:
  136.         ai->ai_protocol = 0;
  137.         break;
  138.     }
  139.  
  140.     ai->ai_addr    = (struct sockaddr *)sin;
  141.     ai->ai_addrlen = sizeof(struct sockaddr_in);
  142.     if (hints && (hints->ai_flags & AI_CANONNAME))
  143.         ai->ai_canonname = h ? av_strdup(h->h_name) : NULL;
  144.  
  145.     ai->ai_next = NULL;
  146.     return 0;
  147. }
  148.  
  149. void ff_freeaddrinfo(struct addrinfo *res)
  150. {
  151. #if HAVE_WINSOCK2_H
  152.     void (WSAAPI *win_freeaddrinfo)(struct addrinfo *res);
  153.     HMODULE ws2mod = GetModuleHandle("ws2_32.dll");
  154.     win_freeaddrinfo = (void (WSAAPI *)(struct addrinfo *res))
  155.                        GetProcAddress(ws2mod, "freeaddrinfo");
  156.     if (win_freeaddrinfo) {
  157.         win_freeaddrinfo(res);
  158.         return;
  159.     }
  160. #endif /* HAVE_WINSOCK2_H */
  161.  
  162.     av_freep(&res->ai_canonname);
  163.     av_freep(&res->ai_addr);
  164.     av_freep(&res);
  165. }
  166.  
  167. int ff_getnameinfo(const struct sockaddr *sa, int salen,
  168.                    char *host, int hostlen,
  169.                    char *serv, int servlen, int flags)
  170. {
  171.     const struct sockaddr_in *sin = (const struct sockaddr_in *)sa;
  172.  
  173. #if HAVE_WINSOCK2_H
  174.     int (WSAAPI *win_getnameinfo)(const struct sockaddr *sa, socklen_t salen,
  175.                                   char *host, DWORD hostlen,
  176.                                   char *serv, DWORD servlen, int flags);
  177.     HMODULE ws2mod = GetModuleHandle("ws2_32.dll");
  178.     win_getnameinfo = GetProcAddress(ws2mod, "getnameinfo");
  179.     if (win_getnameinfo)
  180.         return win_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
  181. #endif /* HAVE_WINSOCK2_H */
  182.  
  183.     if (sa->sa_family != AF_INET)
  184.         return EAI_FAMILY;
  185.     if (!host && !serv)
  186.         return EAI_NONAME;
  187.  
  188.     if (host && hostlen > 0) {
  189.         struct hostent *ent = NULL;
  190.         uint32_t a;
  191.         if (!(flags & NI_NUMERICHOST))
  192.             ent = gethostbyaddr((const char *)&sin->sin_addr,
  193.                                 sizeof(sin->sin_addr), AF_INET);
  194.  
  195.         if (ent) {
  196.             snprintf(host, hostlen, "%s", ent->h_name);
  197.         } else if (flags & NI_NAMERQD) {
  198.             return EAI_NONAME;
  199.         } else {
  200.             a = ntohl(sin->sin_addr.s_addr);
  201.             snprintf(host, hostlen, "%d.%d.%d.%d",
  202.                      ((a >> 24) & 0xff), ((a >> 16) & 0xff),
  203.                      ((a >>  8) & 0xff),  (a        & 0xff));
  204.         }
  205.     }
  206.  
  207.     if (serv && servlen > 0) {
  208.         struct servent *ent = NULL;
  209. #if HAVE_GETSERVBYPORT
  210.         if (!(flags & NI_NUMERICSERV))
  211.             ent = getservbyport(sin->sin_port, flags & NI_DGRAM ? "udp" : "tcp");
  212. #endif /* HAVE_GETSERVBYPORT */
  213.  
  214.         if (ent)
  215.             snprintf(serv, servlen, "%s", ent->s_name);
  216.         else
  217.             snprintf(serv, servlen, "%d", ntohs(sin->sin_port));
  218.     }
  219.  
  220.     return 0;
  221. }
  222. #endif /* !HAVE_GETADDRINFO */
  223.  
  224. #if !HAVE_GETADDRINFO || HAVE_WINSOCK2_H
  225. const char *ff_gai_strerror(int ecode)
  226. {
  227.     switch (ecode) {
  228.     case EAI_AGAIN:
  229.         return "Temporary failure in name resolution";
  230.     case EAI_BADFLAGS:
  231.         return "Invalid flags for ai_flags";
  232.     case EAI_FAIL:
  233.         return "A non-recoverable error occurred";
  234.     case EAI_FAMILY:
  235.         return "The address family was not recognized or the address "
  236.                "length was invalid for the specified family";
  237.     case EAI_MEMORY:
  238.         return "Memory allocation failure";
  239. #if EAI_NODATA != EAI_NONAME
  240.     case EAI_NODATA:
  241.         return "No address associated with hostname";
  242. #endif /* EAI_NODATA != EAI_NONAME */
  243.     case EAI_NONAME:
  244.         return "The name does not resolve for the supplied parameters";
  245.     case EAI_SERVICE:
  246.         return "servname not supported for ai_socktype";
  247.     case EAI_SOCKTYPE:
  248.         return "ai_socktype not supported";
  249.     }
  250.  
  251.     return "Unknown error";
  252. }
  253. #endif /* !HAVE_GETADDRINFO || HAVE_WINSOCK2_H */
  254.  
  255. int ff_socket_nonblock(int socket, int enable)
  256. {
  257. #if HAVE_WINSOCK2_H
  258.     u_long param = enable;
  259.     return ioctlsocket(socket, FIONBIO, &param);
  260. #else
  261.     if (enable)
  262.         return fcntl(socket, F_SETFL, fcntl(socket, F_GETFL) | O_NONBLOCK);
  263.     else
  264.         return fcntl(socket, F_SETFL, fcntl(socket, F_GETFL) & ~O_NONBLOCK);
  265. #endif /* HAVE_WINSOCK2_H */
  266. }
  267.  
  268. #if !HAVE_POLL_H
  269. int ff_poll(struct pollfd *fds, nfds_t numfds, int timeout)
  270. {
  271.     fd_set read_set;
  272.     fd_set write_set;
  273.     fd_set exception_set;
  274.     nfds_t i;
  275.     int n;
  276.     int rc;
  277.  
  278. #if HAVE_WINSOCK2_H
  279.     if (numfds >= FD_SETSIZE) {
  280.         errno = EINVAL;
  281.         return -1;
  282.     }
  283. #endif /* HAVE_WINSOCK2_H */
  284.  
  285.     FD_ZERO(&read_set);
  286.     FD_ZERO(&write_set);
  287.     FD_ZERO(&exception_set);
  288.  
  289.     n = 0;
  290.     for (i = 0; i < numfds; i++) {
  291.         if (fds[i].fd < 0)
  292.             continue;
  293. #if !HAVE_WINSOCK2_H
  294.         if (fds[i].fd >= FD_SETSIZE) {
  295.             errno = EINVAL;
  296.             return -1;
  297.         }
  298. #endif /* !HAVE_WINSOCK2_H */
  299.  
  300.         if (fds[i].events & POLLIN)
  301.             FD_SET(fds[i].fd, &read_set);
  302.         if (fds[i].events & POLLOUT)
  303.             FD_SET(fds[i].fd, &write_set);
  304.         if (fds[i].events & POLLERR)
  305.             FD_SET(fds[i].fd, &exception_set);
  306.  
  307.         if (fds[i].fd >= n)
  308.             n = fds[i].fd + 1;
  309.     }
  310.  
  311.     if (n == 0)
  312.         /* Hey!? Nothing to poll, in fact!!! */
  313.         return 0;
  314.  
  315.     if (timeout < 0) {
  316.         rc = select(n, &read_set, &write_set, &exception_set, NULL);
  317.     } else {
  318.         struct timeval tv;
  319.         tv.tv_sec  = timeout / 1000;
  320.         tv.tv_usec = 1000 * (timeout % 1000);
  321.         rc         = select(n, &read_set, &write_set, &exception_set, &tv);
  322.     }
  323.  
  324.     if (rc < 0)
  325.         return rc;
  326.  
  327.     for (i = 0; i < numfds; i++) {
  328.         fds[i].revents = 0;
  329.  
  330.         if (FD_ISSET(fds[i].fd, &read_set))
  331.             fds[i].revents |= POLLIN;
  332.         if (FD_ISSET(fds[i].fd, &write_set))
  333.             fds[i].revents |= POLLOUT;
  334.         if (FD_ISSET(fds[i].fd, &exception_set))
  335.             fds[i].revents |= POLLERR;
  336.     }
  337.  
  338.     return rc;
  339. }
  340. #endif /* !HAVE_POLL_H */
  341.  
  342. #endif /* CONFIG_NETWORK */
  343.