Ignore:
Timestamp:
Nov 18, 2007 2:53:47 PM (12 years ago)
Author:
bennylp
Message:

Ticket #415: implement IPv6 support in PJLIB

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib/src/pj/sock_bsd.c

    r1515 r1585  
    2424#include <pj/addr_resolv.h> 
    2525#include <pj/errno.h> 
     26#include <pj/unicode.h> 
    2627 
    2728/* 
     
    2930 * The values here are indexed based on pj_addr_family. 
    3031 */ 
     32const pj_uint16_t PJ_AF_UNSPEC  = AF_UNSPEC; 
    3133const pj_uint16_t PJ_AF_UNIX    = AF_UNIX; 
    3234const pj_uint16_t PJ_AF_INET    = AF_INET; 
     
    185187PJ_DEF(int) pj_inet_aton(const pj_str_t *cp, struct pj_in_addr *inp) 
    186188{ 
    187     char tempaddr[16]; 
     189    char tempaddr[PJ_INET_ADDRSTRLEN]; 
    188190 
    189191    /* Initialize output with PJ_INADDR_NONE. 
     
    198200     */ 
    199201    PJ_ASSERT_RETURN(cp && cp->slen && inp, 0); 
    200     if (cp->slen >= 16) { 
     202    if (cp->slen >= PJ_INET_ADDRSTRLEN) { 
    201203        return 0; 
    202204    } 
     
    210212    inp->s_addr = inet_addr(tempaddr); 
    211213    return inp->s_addr == PJ_INADDR_NONE ? 0 : 1; 
     214#endif 
     215} 
     216 
     217/* 
     218 * Convert text to IPv4/IPv6 address. 
     219 */ 
     220PJ_DEF(pj_status_t) pj_inet_pton(int af, const pj_str_t *src, void *dst) 
     221{ 
     222    char tempaddr[PJ_INET6_ADDRSTRLEN]; 
     223 
     224    PJ_ASSERT_RETURN(af==PJ_AF_INET || af==PJ_AF_INET6, PJ_EINVAL); 
     225    PJ_ASSERT_RETURN(src && src->slen && dst, PJ_EINVAL); 
     226 
     227    /* Initialize output with PJ_IN_ADDR_NONE for IPv4 (to be  
     228     * compatible with pj_inet_aton() 
     229     */ 
     230    if (af==PJ_AF_INET) { 
     231        ((pj_in_addr*)dst)->s_addr = PJ_INADDR_NONE; 
     232    } 
     233 
     234    /* Caution: 
     235     *  this function might be called with cp->slen >= 46 
     236     *  (i.e. when called with hostname to check if it's an IP addr). 
     237     */ 
     238    if (src->slen >= PJ_INET6_ADDRSTRLEN) { 
     239        return PJ_ENAMETOOLONG; 
     240    } 
     241 
     242    pj_memcpy(tempaddr, src->ptr, src->slen); 
     243    tempaddr[src->slen] = '\0'; 
     244 
     245#if defined(PJ_SOCK_HAS_INET_PTON) && PJ_SOCK_HAS_INET_PTON != 0 
     246    /* 
     247     * Implementation using inet_pton() 
     248     */ 
     249    if (inet_pton(af, tempaddr, dst) != 1) { 
     250        pj_status_t status = pj_get_netos_error(); 
     251        if (status == PJ_SUCCESS) 
     252            status = PJ_EUNKNOWN; 
     253 
     254        return status; 
     255    } 
     256 
     257    return PJ_SUCCESS; 
     258 
     259#elif defined(PJ_WIN32) || defined(PJ_WIN32_WINCE) 
     260    /* 
     261     * Implementation on Windows, using WSAStringToAddress(). 
     262     * Should also work on Unicode systems. 
     263     */ 
     264    { 
     265        PJ_DECL_UNICODE_TEMP_BUF(wtempaddr,PJ_INET6_ADDRSTRLEN) 
     266        pj_sockaddr sock_addr; 
     267        int addr_len = sizeof(sock_addr); 
     268        int rc; 
     269 
     270        sock_addr.addr.sa_family = (pj_uint16_t)af; 
     271        rc = WSAStringToAddress( 
     272                PJ_STRING_TO_NATIVE(tempaddr,wtempaddr,sizeof(wtempaddr)),  
     273                af, NULL, (LPSOCKADDR)&sock_addr, &addr_len); 
     274        if (rc != 0) { 
     275            pj_status_t status = pj_get_netos_error(); 
     276            if (status == PJ_SUCCESS) 
     277                status = PJ_EUNKNOWN; 
     278 
     279            return status; 
     280        } 
     281 
     282        if (sock_addr.addr.sa_family == PJ_AF_INET) { 
     283            pj_memcpy(dst, &sock_addr.ipv4.sin_addr, 4); 
     284            return PJ_SUCCESS; 
     285        } else if (sock_addr.addr.sa_family == PJ_AF_INET6) { 
     286            pj_memcpy(dst, &sock_addr.ipv6.sin6_addr, 16); 
     287            return PJ_SUCCESS; 
     288        } else { 
     289            pj_assert(!"Shouldn't happen"); 
     290            return PJ_EBUG; 
     291        } 
     292    } 
     293#elif !defined(PJ_HAS_IPV6) || PJ_HAS_IPV6==0 
     294    /* IPv6 support is disabled, just return error without raising assertion */ 
     295    return PJ_EIPV6NOTSUP; 
     296#else 
     297    pj_assert(!"Not supported"); 
     298    return PJ_EIPV6NOTSUP; 
     299#endif 
     300} 
     301 
     302/* 
     303 * Convert IPv4/IPv6 address to text. 
     304 */ 
     305PJ_DEF(pj_status_t) pj_inet_ntop(int af, const void *src, 
     306                                 char *dst, int size) 
     307 
     308{ 
     309    PJ_ASSERT_RETURN(src && dst && size, PJ_EINVAL); 
     310    PJ_ASSERT_RETURN(af==PJ_AF_INET || af==PJ_AF_INET6, PJ_EINVAL); 
     311 
     312#if defined(PJ_SOCK_HAS_INET_NTOP) && PJ_SOCK_HAS_INET_NTOP != 0 
     313    /* 
     314     * Implementation using inet_ntop() 
     315     */ 
     316    if (inet_ntop(af, src, dst, size) == NULL) { 
     317        pj_status_t status = pj_get_netos_error(); 
     318        if (status == PJ_SUCCESS) 
     319            status = PJ_EUNKNOWN; 
     320 
     321        return status; 
     322    } 
     323 
     324    return PJ_SUCCESS; 
     325 
     326#elif defined(PJ_WIN32) || defined(PJ_WIN32_WINCE) 
     327    /* 
     328     * Implementation on Windows, using WSAAddressToString(). 
     329     * Should also work on Unicode systems. 
     330     */ 
     331    { 
     332        PJ_DECL_UNICODE_TEMP_BUF(wtempaddr,PJ_INET6_ADDRSTRLEN) 
     333        pj_sockaddr sock_addr; 
     334        DWORD addr_len, addr_str_len; 
     335        int rc; 
     336 
     337        pj_bzero(&sock_addr, sizeof(sock_addr)); 
     338        sock_addr.addr.sa_family = (pj_uint16_t)af; 
     339        if (af == PJ_AF_INET) { 
     340            if (size < PJ_INET_ADDRSTRLEN) 
     341                return PJ_ETOOSMALL; 
     342            pj_memcpy(&sock_addr.ipv4.sin_addr, src, 4); 
     343            addr_len = sizeof(pj_sockaddr_in); 
     344            addr_str_len = PJ_INET_ADDRSTRLEN; 
     345        } else if (af == PJ_AF_INET6) { 
     346            if (size < PJ_INET6_ADDRSTRLEN) 
     347                return PJ_ETOOSMALL; 
     348            pj_memcpy(&sock_addr.ipv6.sin6_addr, src, 16); 
     349            addr_len = sizeof(pj_sockaddr_in6); 
     350            addr_str_len = PJ_INET6_ADDRSTRLEN; 
     351        } else { 
     352            pj_assert(!"Unsupported address family"); 
     353            return PJ_EINVAL; 
     354        } 
     355 
     356#if PJ_NATIVE_STRING_IS_UNICODE 
     357        rc = WSAAddressToString((LPSOCKADDR)&sock_addr, addr_len, 
     358                                NULL, wtempaddr, addr_str_len); 
     359        if (rc == 0) { 
     360            pj_unicode_to_ansi(wtempaddr, wcslen(wtempaddr), dst, size); 
     361        } 
     362#else 
     363        rc = WSAAddressToString((LPSOCKADDR)&sock_addr, addr_len, 
     364                                NULL, dst, &addr_str_len); 
     365#endif 
     366 
     367        if (rc != 0) { 
     368            pj_status_t status = pj_get_netos_error(); 
     369            if (status == PJ_SUCCESS) 
     370                status = PJ_EUNKNOWN; 
     371 
     372            return status; 
     373        } 
     374 
     375        return PJ_SUCCESS; 
     376    } 
     377 
     378#elif !defined(PJ_HAS_IPV6) || PJ_HAS_IPV6==0 
     379    /* IPv6 support is disabled, just return error without raising assertion */ 
     380    return PJ_EIPV6NOTSUP; 
     381#else 
     382    pj_assert(!"Not supported"); 
     383    return PJ_EIPV6NOTSUP; 
    212384#endif 
    213385} 
Note: See TracChangeset for help on using the changeset viewer.