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

📄 rvhost.c

📁 h.248协议源码
💻 C
字号:
/*****************************************************************************
Filename   : rvhost.c
Description: Host interface definition.
******************************************************************************
                Copyright (c) 1999 RADVision Inc.
******************************************************************************
NOTICE:
This document contains information that is proprietary to RADVision Inc.
No part of this publication may be reproduced in any form whatsoever 
without written prior approval by RADVision Inc.

RADVision Inc. reserves the right to revise this publication and make 
changes without obligation to notify any person of such revisions or 
changes.
******************************************************************************
$Revision:$
$Date:$
$Author: S. Cipolli$
******************************************************************************/

#include <string.h>
#include "rvplatform.h"
#include "rvutil.h"
#include "rvlog.h"
#include "rvinet.h"
#include "rvhost.h"

/* This function has the onerrous task of deep-copying a hostent */
static struct hostent* rvHostCopy_(char* dstBuf, struct hostent* src) {
    char** aliases;
    char** addrList;
    size_t i;
    size_t size;
    struct hostent* dst = NULL;
    
    if (src != NULL) {

        /* Carve hostent out of buffer */
        dst = (struct hostent*)dstBuf;
        dstBuf += sizeof(struct hostent);

        /* Copy address type and length */
        dst->h_addrtype = src->h_addrtype;
        dst->h_length = src->h_length;

        /* Copy the name */
        strcpy(dstBuf, src->h_name);
        dst->h_name = dstBuf;
        dstBuf += rvAlign64(strlen(dst->h_name) + 1);

        /* Determine the size of the alias list */
        size = 0;
        if(src->h_aliases != NULL)
            while(src->h_aliases[size] != NULL)
                size++;
        
        /* Copy aliases */
        aliases = (char**)dstBuf;
        dstBuf += sizeof(char*) * (size + 1);
        for (i = 0; i < size; ++i) {
            aliases[i] = strcpy(dstBuf, src->h_aliases[i]);
            dstBuf += (strlen(src->h_aliases[i]) + 1);
        }
        aliases[i] = NULL;
        dst->h_aliases = aliases;
        
#if defined(RV_DNS_PSOS)
        /* Copy address list */
        for (i = 0; src->h_addr_list[i] != NULL; ++i) {
            dst->h_addr_list[i] = memcpy(dstBuf, src->h_addr_list[i], src->h_length);
            dstBuf += src->h_length;
        }
        dst->h_addr_list[i] = NULL;
#else
        /* Determine the size of the address list */
        size = 0;
        if(src->h_addr_list != NULL)
            while(src->h_addr_list[size] != NULL)
                size++;

        /* Copy address list */
        dstBuf = (char*)rvAlign((ptrdiff_t)dstBuf);
        addrList = (char**)dstBuf;
        dstBuf += sizeof(char*) * (size + 1);
        for (i = 0; i < size; ++i) {
            addrList[i] = memcpy(dstBuf, src->h_addr_list[i], src->h_length);
            dstBuf += src->h_length;
        }
        addrList[i] = NULL;
        dst->h_addr_list = addrList;
#endif
    }
    return dst;
}

/* This function has the onerrous task of creating a hostent */
static struct hostent* rvHostConstruct_(char* dstBuf, char* addr, int len, int type) {
    static const char* name = "<unknown>";
    char** aliases;
    char** addrList;
    struct hostent* dst;
    
    /* Carve hostent out of buffer */
    dst = (struct hostent*)dstBuf;
    dstBuf += sizeof(struct hostent);

    /* Copy address type and length */
    dst->h_addrtype = type;
    dst->h_length = len;

    /* Copy the name */
    strcpy(dstBuf, name);
    dst->h_name = dstBuf;
    dstBuf += rvAlign64(strlen(name) + 1);

    /* Copy aliases */
    aliases = (char**)dstBuf;
    dstBuf += sizeof(char*);
    aliases[0] = NULL;
    dst->h_aliases = aliases;

    /* Copy address list */
#if defined(RV_DNS_PSOS)
    if (type == AF_INET)
        *(RvIpv4Addr*)dstBuf = *(RvIpv4Addr*)addr;
#if defined(RV_INET_IPV6)
    else
        *(RvIpv6Addr*)dstBuf = *(RvIpv6Addr*)addr;
#endif
    dst->h_addr_list[0] = dstBuf;
    dstBuf += len;
    dst->h_addr_list[1] = NULL;
#else
    addrList = (char**)dstBuf;
    dstBuf += sizeof(char*) * 2;
    if (type == AF_INET)
        *(RvIpv4Addr*)dstBuf = *(RvIpv4Addr*)addr;
#if defined(RV_INET_IPV6)
    else
        *(RvIpv6Addr*)dstBuf = *(RvIpv6Addr*)addr;
#endif
    addrList[0] = dstBuf;
    dstBuf += len;
    addrList[1] = NULL;
    dst->h_addr_list = addrList;
#endif

    return dst;
}

struct hostent* rvGetHostByName(const char* host, char* buf, size_t size) {
	struct hostent *h;
	char *resultbuf;
	size_t hostbufsize, resultbufsize;
#if defined(RV_DNS_VXWORKS)
	struct hostent *resulth;
#endif
#if defined(RV_DNS_POSIX)
	int err;
#endif
#if defined(RV_DNS_PSOS)
	int i;
	char *tmpbuf;
#endif
#if defined(RV_DNS_OSE)
	struct hostent *hsigbuf, *resulth;
#endif
#if defined(RV_DNS_NUCLEUS)
	NU_HOSTENT nuc_h;
	char **data;
#endif

	/* Make sure eveything is aligned right */
	h = (struct hostent *)rvAlign(buf); /* aligned hostent */
	hostbufsize = size - (size_t)((char *)h - buf); /* size of buffer with hostent */
	resultbuf = (char *)h + sizeof(struct hostent); /* start of remaining buffer */
	resultbufsize = size - (size_t)(resultbuf - buf); /* size of buffer without hostent */

#if defined(RV_DNS_POSIX)
    return gethostbyname_r(host, h, resultbuf, resultbufsize, &err);
#elif defined(RV_DNS_BSD) || defined(RV_DNS_WSOCK)  /* BSD (thread-local) */
    return rvHostCopy_((char *)h, gethostbyname(host)); 
#elif defined(RV_DNS_VXWORKS)   /* VxWorks non-standard interface */
    resulth = resolvGetHostByName((char *)host, (char *)h, hostbufsize);
	if(resulth != NULL) {
		/* Fix up items that VxWorks doesn't bother to fill in */
		*h->h_aliases = NULL;
		h->h_addrtype = AF_INET;
		h->h_length = 16;
	}
	return resulth;
#elif defined(RV_DNS_PSOS)      /* PSoS non-standard interface */
    /* The PSoS implementation of gethostbyname and hostent are non-standard 
       in the following ways:
       1. The interface to gethostbyname is different.
       2. The h_addr_list member of hostent is declared as an char* array of 
       fixed length rather than char**.
       3. The semantics for the h_addr_list is non-standard (a NULL pointer can 
       not be used to terminate the list).
       4. The buffer space needed by each address must be determined before the
       call to gethostbyname. We assume the addresses are IPv4 today.
    */
#define RV_HOST_MAXADDRS    10 /* should match pSOS value in rescfg.h */
    /* Make sure there is enough memory in the buffer */
    if (((sizeof(RvIpv4Addr) * RV_HOST_MAXADDRS) + sizeof(h->h_addr)) > resultbufsize)
        return NULL;

    /* Carve out N addresses from buffer, clear them, and initialize hostent pointers */
	tmpbuf = resultbuf + sizeof(h->h_addr);
    for (i = 0; i < RV_HOST_MAXADDRS; i++) {
        h->h_addr_list[i] = tmpbuf;
        tmpbuf += sizeof(RvIpv4Addr);
        memset(h->h_addr_list[i], 0, sizeof(RvIpv4Addr));
    }           

    /* Ask the resolver to fill in the addresses */
    gethostbyname((char *)host, h);

    /* Standard hostent requires end of list to be NULL, so find the end and fix it */
    for (i = 0; i < RV_HOST_MAXADDRS; i++) {
		if(*(h->h_addr_list[i]) == 0) {
			h->h_addr_list[i] = NULL;
			break;
		}
	}
	*resultbuf = NULL; /* We'll need a NULL terminated list even if MAXADDRS names are returned */
    
    return h;
#elif defined(RV_DNS_OSE)          /* OSE non-standard interface */
    hsigbuf = gethostbyname_r(host);     /* allocates a signal buffer */
    resulth = rvHostCopy_((char *)h, hsigbuf); /* copy into passed in buf */
    free_buf((union SIGNAL **)&h);  /* free the signal buffer */
    return resulth;
#elif defined(RV_DNS_NONE)
    return NULL;
#elif defined(RV_DNS_NUCLEUS)
    /* Nucleus never uses h_aliases and only allows one address (h_addr) */
    /* Also, name and address are not re-entrant, they point to internal */
    /* structures which can change out from underneath you. */

    /* Set up target result structure and data tables */
	data = (char **)resultbuf;
    *data = NULL;                  /* Empty alias table, has 1 null item */
    h->h_aliases = data;           /* set alias pointer to the table */
    data++;
    h->h_addr_list = data;         /* set address pointer to address table */
    data++;
    *data = NULL;                  /* end of address pointer table */
    data++;
    
    if(NU_Get_Host_By_Name((char *)host, &nuc_h) != NU_SUCCESS)
        return(NULL);
    if(resultbufsize < (strlen(nuc_h.h_name) + 1 + (sizeof(char *) * 4))) /* make sure we have enough space */
        return (NULL);
    *h->h_addr_list = memcpy((char *)data, nuc_h.h_addr, nuc_h.h_length); /* copy address and set ptr */
    data++;
    h->h_name = strcpy((char *)data, nuc_h.h_name);  /* copy name string and set h_hname */
    h->h_addrtype = nuc_h.h_addrtype;
    h->h_length = nuc_h.h_length;
    return h;
#else
#   error Unknown DNS implementation
#endif
}

RvHost* rvHostConstructLocal(RvHost* h) {
    char hostname[128];
    gethostname(hostname, sizeof(hostname));
    return rvHostConstruct(h, hostname);
}

RvHost* rvHostConstructIpv4(RvHost* h, RvIpv4Addr* ipv4) {
    RvIpv4Addr addr;
    

    rvLogEnter(&rvLog, "rvHostConstructIpv4");

    rvIpv4AddrConstruct(&addr, htonl(*(RvUint32*)ipv4));

    /* Create a dummy host entity */
    h->he = rvHostConstruct_(h->buf, (char*)&addr, sizeof(RvIpv4Addr), AF_INET);

    /* Determine the number of addresses */
    h->numAddrs = 1;

    rvLogLeave(&rvLog, "rvHostConstructIpv4");

    return h->he ? h : NULL;
}

RvHost* rvHostConstruct(RvHost* h, const char* dnsOrIp) {
    RvIpv4Addr ipv4;

    rvLogEnter(&rvLog, "rvHostConstruct");
#if defined(RV_INET_IPV6)
    {
        int errornum;
        struct hostent* ptr = getipnodebyname(dnsOrIp, AF_INET6, AI_DEFAULT, &errornum);

        if(ptr != NULL)
        {
            /* Copy hostent and free it so that we can manage the memory */
            h->he = rvHostCopy_(h->buf, ptr);
            freehostent(ptr);
        }
        else
        {
            /* Null the host structure pointer */
	    h->he = NULL;
        }
    }
#else
    /* See if it's an IPv4 address */
    rvIpv4AddrToUint32(&ipv4) = inet_addr(dnsOrIp);
    if (rvIpv4AddrToUint32(&ipv4) != ~0)
        /* Create a dummy host entity */
        h->he = rvHostConstruct_(h->buf, (char*)&ipv4, sizeof(RvIpv4Addr), AF_INET);
    else    /* It must be a DNS name */
        h->he = rvGetHostByName(dnsOrIp, h->buf, sizeof(h->buf));
#endif

    /* Determine the number of addresses */
    h->numAddrs = 0;
    if (h->he) {
        char** p;
        for (p = h->he->h_addr_list; *p != 0; ++p)
            ++(h->numAddrs);
    }

    rvLogLeave(&rvLog, "rvHostConstruct");

    return h->he ? h : NULL;
}

RvHost* rvHostCopy(RvHost* dst, RvHost* src) {
    rvLogEnter(&rvLog, "rvHostCopy");
    dst->numAddrs = src->numAddrs;
    dst->he = rvHostCopy_(dst->buf, src->he);
    rvLogLeave(&rvLog, "rvHostCopy");
    return dst;
}

RvBool rvHostEqual(RvHost* a, RvHost* b) {
    size_t i, j;

    if ((a->he->h_addrtype == b->he->h_addrtype) &&
        (a->numAddrs == b->numAddrs) &&
        (a->he->h_length == b->he->h_length)) { 

        for (i = 0; i < a->numAddrs; ++i) {
            for (j = 0; j < b->numAddrs; ++j) {
                if (memcmp(a->he->h_addr_list[i], 
                    b->he->h_addr_list[j], a->he->h_length) == 0)
                        break;
            }
            if (j == b->numAddrs)
                return rvFalse;
        }
        return rvTrue;
    }
    return rvFalse;
}

/* str must be large enough to hold converted address */
char* rvHostGetAddrAsString(RvHost* h, size_t n, OUT char* str) {
    struct in_addr *iaptr;
    char address[16];
    char *addrptr;
    rvLogEnter(&rvLog, "rvHostGetAddrAsString");

    /* If IPv4 ... */
    if (h->he->h_addrtype == AF_INET) {
        iaptr = (struct in_addr *)(h->he->h_addr_list[n]);
#if defined(RV_SOCKETS_NUCLEUS)
        addrptr = rvInetNtoa(iaptr->sck_ip_addr, address);
#else
        addrptr = rvInetNtoa(*iaptr, address);
#endif
        strcpy(str, addrptr);
#if defined(RV_INET_IPV6)
    } else if (h->he->h_addrtype == AF_INET6) {
        char addrStr[INET6_ADDRSTRLEN];
        strcpy(str, inet_ntop(AF_INET6, h->he->h_addr_list[n], 
          addrStr, INET6_ADDRSTRLEN));
#endif
    }
    
    rvLogLeave(&rvLog, "rvHostGetAddrAsString");

    return str;
}

RvIpv4Addr* rvHostGetIpv4Addr(RvHost* h, size_t n) {
    RvIpv4Addr* ipv4 = NULL;
    rvLogEnter(&rvLog, "rvHostGetIpv4Addr");
    if (n < h->numAddrs)
        ipv4 = (RvIpv4Addr*)h->he->h_addr_list[n];
    rvLogLeave(&rvLog, "rvHostGetIpv4Addr");
    return ipv4;
}

#if defined(RV_INET_IPV6)
RvIpv6Addr* rvHostGetIpv6Addr(RvHost* h, size_t n) {
    RvIpv6Addr* ipv6 = NULL;
    rvLogEnter(&rvLog, "rvHostGetIpv6Addr");
    if (n < h->numAddrs)
        ipv6 = (RvIpv6Addr*)h->he->h_addr_list[n];
    rvLogLeave(&rvLog, "rvHostGetIpv6Addr");
    return ipv6;
}
#endif


⌨️ 快捷键说明

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