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

📄 getaddrinfo.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************** * getaddrinfo.c: getaddrinfo/getnameinfo replacement functions ***************************************************************************** * Copyright (C) 2005 the VideoLAN team * Copyright (C) 2002-2007 Rémi Denis-Courmont * $Id$ * * 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. *****************************************************************************/#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.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 <vlc_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#ifndef HAVE_GAI_STRERRORstatic const struct{    int        code;    const char msg[41];} 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_OVERFLOW,   "Buffer overflow" },    { EAI_SYSTEM,     "System error" },    { 0,              "" },};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){    for (unsigned i = 0; *gai_errlist[i].msg; i++)        if (errnum == gai_errlist[i].code)            return gai_errlist[i].msg;    return gai_unknownerr;}#else /* ifndef HAVE_GAI_STRERROR */const char *vlc_gai_strerror (int errnum){    return gai_strerror (errnum);}#endif#ifndef HAVE_GETNAMEINFO#define _NI_MASK (NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|NI_NAMEREQD|\                  NI_DGRAM)/* * getnameinfo() non-thread-safe IPv4-only implementation, * Address-family-independent 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(). */#ifdef WIN32static int WSAAPIstub_getnameinfo (const struct sockaddr *sa, socklen_t salen,             char *host, DWORD hostlen, char *serv, DWORD servlen, int flags)#elsestatic intstub_getnameinfo (const struct sockaddr *sa, socklen_t salen,             char *host, int hostlen, char *serv, int servlen, int flags)#endif{    if (((size_t)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)        {            /* host name resolution */            if (!(flags & NI_NUMERICHOST))            {                if (flags & NI_NAMEREQD)                    return EAI_NONAME;            }            /* inet_ntoa() is not thread-safe, do not use it */            uint32_t ipv4 = ntohl (addr->sin_addr.s_addr);            if (snprintf (host, hostlen, "%u.%u.%u.%u", ipv4 >> 24,                          (ipv4 >> 16) & 0xff, (ipv4 >> 8) & 0xff,                          ipv4 & 0xff) >= (int)hostlen)                return EAI_OVERFLOW;        }        if (serv != NULL)        {            if (snprintf (serv, servlen, "%u",                          (unsigned int)ntohs (addr->sin_port)) >= (int)servlen)                return EAI_OVERFLOW;        }    }    return 0;}#undef getnameinfo#define getnameifo stub_getnameinfo#endif /* if !HAVE_GETNAMEINFO */#ifndef HAVE_GETADDRINFO#define _AI_MASK (AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST)/* * 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;}/* * This functions must be used to free the memory allocated by getaddrinfo(). */#ifdef WIN32static void WSAAPI stub_freeaddrinfo (struct addrinfo *res)#elsestatic void stub_freeaddrinfo (struct addrinfo *res)#endif{    if (res == NULL)        return;    free (res->ai_canonname);    free (res->ai_addr);    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-independent 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. */#ifdef WIN32static int WSAAPIstub_getaddrinfo (const char *node, const char *service,             const struct addrinfo *hints, struct addrinfo **res)#elsestatic intstub_getaddrinfo (const char *node, const char *service,             const struct addrinfo *hints, struct addrinfo **res)#endif{    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:                protocol = IPPROTO_TCP;                break;            case SOCK_DGRAM:                protocol = IPPROTO_UDP;                break;#ifndef SOCK_RAW            case SOCK_RAW:#endif            case 0:                break;            default:                return EAI_SOCKTYPE;        }        if (hints->ai_protocol && protocol         && (protocol != hints->ai_protocol))            return EAI_SERVICE;    }    *res = NULL;    /* default values */    if (node == NULL)    {        if (flags & AI_PASSIVE)            ip = htonl (INADDR_ANY);        else            ip = htonl (INADDR_LOOPBACK);    }    else    if ((ip = inet_addr (node)) == INADDR_NONE)    {        struct hostent *entry = NULL;        /* hostname resolution */        if (!(flags & AI_NUMERICHOST))            entry = gethostbyname (node);        if (entry == NULL)            return gai_error_from_herrno ();        if ((entry->h_length != 4) || (entry->h_addrtype != AF_INET))            return EAI_FAMILY;

⌨️ 快捷键说明

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