Subversion Repositories Kolibri OS

Rev

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