⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 getaddrinfo.c

📁 uclinux 下的vlc播放器源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************** * getaddrinfo.c: getaddrinfo/getnameinfo replacement functions ***************************************************************************** * Copyright (C) 2005 the VideoLAN team * Copyright (C) 2002-2004 Rémi Denis-Courmont * $Id: getaddrinfo.c 16460 2006-08-31 22:01:13Z hartman $ * * Author: Rémi Denis-Courmont <rem # videolan.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/#include <vlc/vlc.h>#include <stddef.h> /* size_t */#include <string.h> /* strlen(), memcpy(), memset(), strchr() */#include <stdlib.h> /* malloc(), free(), strtoul() */#include <errno.h>#ifdef HAVE_SYS_TYPES_H#   include <sys/types.h>#endif#ifdef HAVE_ARPA_INET_H#   include <arpa/inet.h>#endif#ifdef HAVE_NETINET_IN_H#   include <netinet/in.h>#endif#ifdef HAVE_UNISTD_H#   include <unistd.h>#endif#include "network.h"#ifndef NO_ADDRESS#   define NO_ADDRESS  NO_DATA#endif#ifndef INADDR_NONE#   define INADDR_NONE 0xFFFFFFFF#endif#ifndef AF_UNSPEC#   define AF_UNSPEC   0#endif#define _NI_MASK (NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|NI_NAMEREQD|\                  NI_DGRAM)#define _AI_MASK (AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST)#ifndef HAVE_GAI_STRERRORstatic struct{    int code;    const char *msg;} const __gai_errlist[] ={    { 0,              "Error 0" },    { EAI_BADFLAGS,   "Invalid flag used" },    { EAI_NONAME,     "Host or service not found" },    { EAI_AGAIN,      "Temporary name service failure" },    { EAI_FAIL,       "Non-recoverable name service failure" },    { EAI_NODATA,     "No data for host name" },    { EAI_FAMILY,     "Unsupported address family" },    { EAI_SOCKTYPE,   "Unsupported socket type" },    { EAI_SERVICE,    "Incompatible service for socket type" },    { EAI_ADDRFAMILY, "Unavailable address family for host name" },    { EAI_MEMORY,     "Memory allocation failure" },    { EAI_SYSTEM,     "System error" },    { 0,              NULL }};static const char *__gai_unknownerr = "Unrecognized error number";/**************************************************************************** * Converts an EAI_* error code into human readable english text. ****************************************************************************/const char *vlc_gai_strerror( int errnum ){    int i;    for (i = 0; __gai_errlist[i].msg != NULL; i++)        if (errnum == __gai_errlist[i].code)            return __gai_errlist[i].msg;    return __gai_unknownerr;}# undef _EAI_POSITIVE_MAX#else /* ifndef HAVE_GAI_STRERROR */const char *vlc_gai_strerror( int errnum ){    return gai_strerror( errnum );}#endif#if !(defined (HAVE_GETNAMEINFO) && defined (HAVE_GETADDRINFO))/* * Converts the current herrno error value into an EAI_* error code. * That error code is normally returned by getnameinfo() or getaddrinfo(). */static intgai_error_from_herrno( void ){    switch(h_errno)    {        case HOST_NOT_FOUND:            return EAI_NONAME;        case NO_ADDRESS:# if (NO_ADDRESS != NO_DATA)        case NO_DATA:# endif            return EAI_NODATA;        case NO_RECOVERY:            return EAI_FAIL;        case TRY_AGAIN:            return EAI_AGAIN;    }    return EAI_SYSTEM;}#endif /* if !(HAVE_GETNAMEINFO && HAVE_GETADDRINFO) */#ifndef HAVE_GETNAMEINFO/* * getnameinfo() non-thread-safe IPv4-only implementation, * Address-family-independant address to hostname translation * (reverse DNS lookup in case of IPv4). * * This is meant for use on old IP-enabled systems that are not IPv6-aware, * and probably do not have getnameinfo(), but have the old gethostbyaddr() * function. * * GNU C library 2.0.x is known to lack this function, even though it defines * getaddrinfo(). */static int__getnameinfo( const struct sockaddr *sa, socklen_t salen,               char *host, int hostlen, char *serv, int servlen, int flags ){    if (((unsigned)salen < sizeof (struct sockaddr_in))     || (sa->sa_family != AF_INET))        return EAI_FAMILY;    else if (flags & (~_NI_MASK))        return EAI_BADFLAGS;    else    {        const struct sockaddr_in *addr;        addr = (const struct sockaddr_in *)sa;        if (host != NULL)        {            int solved = 0;            /* host name resolution */            if (!(flags & NI_NUMERICHOST))            {                struct hostent *hent;                hent = gethostbyaddr ((const void*)&addr->sin_addr,                                      4, AF_INET);                if (hent != NULL)                {                    strlcpy (host, hent->h_name, hostlen);                    /*                     * only keep first part of hostname                     * if user don't want fully qualified                     * domain name                     */                    if (flags & NI_NOFQDN)                    {                        char *ptr;                        ptr = strchr (host, '.');                        if (ptr != NULL)                            *ptr = 0;                    }                    solved = 1;                }                else if (flags & NI_NAMEREQD)                    return gai_error_from_herrno ();            }            if (!solved)                /* inet_ntoa() can't fail */                strlcpy (host, inet_ntoa (addr->sin_addr), hostlen);        }        if (serv != NULL)        {            struct servent *sent = NULL;#ifndef SYS_BEOS /* No getservbyport() */            int solved = 0;            /* service name resolution */            if (!(flags & NI_NUMERICSERV))            {                sent = getservbyport(addr->sin_port,                                     (flags & NI_DGRAM)                                     ? "udp" : "tcp");                if (sent != NULL)                {                    strlcpy (serv, sent->s_name, servlen);                    solved = 1;                }            }            if (sent == NULL)#endif            {                snprintf (serv, servlen, "%u",                          (unsigned int)ntohs (addr->sin_port));                serv[servlen - 1] = '\0';            }        }    }    return 0;}#endif /* if !HAVE_GETNAMEINFO */#ifndef HAVE_GETADDRINFO/* * This functions must be used to free the memory allocated by getaddrinfo(). */static void__freeaddrinfo (struct addrinfo *res){    if (res != NULL)    {        if (res->ai_canonname != NULL)            free (res->ai_canonname);        if (res->ai_addr != NULL)            free (res->ai_addr);        if (res->ai_next != NULL)            free (res->ai_next);        free (res);    }}/* * Internal function that builds an addrinfo struct. */static struct addrinfo *makeaddrinfo (int af, int type, int proto,              const struct sockaddr *addr, size_t addrlen,              const char *canonname){    struct addrinfo *res;    res = (struct addrinfo *)malloc (sizeof (struct addrinfo));    if (res != NULL)    {        res->ai_flags = 0;        res->ai_family = af;        res->ai_socktype = type;        res->ai_protocol = proto;        res->ai_addrlen = addrlen;        res->ai_addr = malloc (addrlen);        res->ai_canonname = NULL;        res->ai_next = NULL;        if (res->ai_addr != NULL)        {            memcpy (res->ai_addr, addr, addrlen);            if (canonname != NULL)            {                res->ai_canonname = strdup (canonname);                if (res->ai_canonname != NULL)                    return res; /* success ! */            }            else                return res;        }    }    /* failsafe */    vlc_freeaddrinfo (res);    return NULL;}static struct addrinfo *makeipv4info (int type, int proto, u_long ip, u_short port, const char *name){    struct sockaddr_in addr;    memset (&addr, 0, sizeof (addr));    addr.sin_family = AF_INET;# ifdef HAVE_SA_LEN    addr.sin_len = sizeof (addr);# endif    addr.sin_port = port;    addr.sin_addr.s_addr = ip;    return makeaddrinfo (AF_INET, type, proto,                         (struct sockaddr*)&addr, sizeof (addr), name);}/* * getaddrinfo() non-thread-safe IPv4-only implementation * Address-family-independant hostname to address resolution. * * This is meant for IPv6-unaware systems that do probably not provide * getaddrinfo(), but still have old function gethostbyname(). * * Only UDP and TCP over IPv4 are supported here. */static int__getaddrinfo (const char *node, const char *service,               const struct addrinfo *hints, struct addrinfo **res){    struct addrinfo *info;    u_long ip;    u_short port;    int protocol = 0, flags = 0;    const char *name = NULL;#ifdef WIN32    /*     * Maybe you knew already that Winsock does not handle TCP/RST packets     * properly, so that when a TCP connection fails, it will wait until it     * times out even if the remote host did return a TCP/RST. However, it     * still sees the TCP/RST as the error code is 10061 instead of 10060.     * Basically, we have the stupid brainfucked behavior with DNS queries...     * When the recursive DNS server returns an error, Winsock waits about     * 2 seconds before it returns to the callers, even though it should know     * that is pointless. I'd like to know how come this hasn't been fixed     * for the past decade, or maybe not.     *     * Anyway, this is causing a severe delay when the SAP listener tries     * to resolve more than ten IPv6 numeric addresses. Modern systems will     * eventually realize that it is an IPv6 address, and won't try to resolve     * it as a IPv4 address via the Domain Name Service. Old systems     * (including Windows XP without the IPv6 stack) will not. It is normally     * not an issue as the DNS server usually returns an error very quickly.     * But it IS a severe issue on Windows, given the bug explained above.     * So here comes one more bug-to-bug Windows compatibility fix.     */    if ((node != NULL) && (strchr (node, ':') != NULL))       return EAI_NONAME;#endif    if (hints != NULL)    {        flags = hints->ai_flags;        if (flags & ~_AI_MASK)            return EAI_BADFLAGS;        /* only accept AF_INET and AF_UNSPEC */        if (hints->ai_family && (hints->ai_family != AF_INET))            return EAI_FAMILY;        /* protocol sanity check */        switch (hints->ai_socktype)        {            case SOCK_STREAM:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -