Ignore:
Timestamp:
Dec 1, 2007 8:52:57 AM (16 years ago)
Author:
bennylp
Message:

More ticket #415: more IPv6 and some reorganization of the source codes

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib/src/pj/addr_resolv_symbian.cpp

    r1599 r1601  
    2828  
    2929 
     30 
    3031// PJLIB API: resolve hostname 
    3132PJ_DEF(pj_status_t) pj_gethostbyname(const pj_str_t *name, pj_hostent *he) 
    3233{ 
    33     PJ_ASSERT_RETURN(name && he, PJ_EINVAL); 
     34    static pj_addrinfo ai; 
     35    static char *aliases[2]; 
     36    static char *addrlist[2]; 
     37    unsigned count = 1; 
     38    pj_status_t status; 
     39     
     40    status = pj_getaddrinfo(PJ_AF_INET, name, &count, &ai); 
     41    if (status != PJ_SUCCESS) 
     42        return status; 
     43     
     44    aliases[0] = ai.ai_canonname; 
     45    aliases[1] = NULL; 
     46     
     47    addrlist[0] = (char*) &ai.ai_addr.ipv4.sin_addr; 
     48    addrlist[1] = NULL; 
     49     
     50    pj_bzero(he, sizeof(*he)); 
     51    he->h_name = aliases[0]; 
     52    he->h_aliases = aliases; 
     53    he->h_addrtype = PJ_AF_INET; 
     54    he->h_length = 4; 
     55    he->h_addr_list = addrlist; 
     56     
     57    return PJ_SUCCESS; 
     58} 
    3459 
    35     RHostResolver &resv = PjSymbianOS::Instance()->GetResolver(); 
     60 
     61// Resolve for specific address family 
     62static pj_status_t getaddrinfo_by_af(int af, const pj_str_t *name, 
     63                                     unsigned *count, pj_addrinfo ai[])  
     64{ 
     65    unsigned i; 
     66    pj_status_t status; 
     67     
     68    PJ_ASSERT_RETURN(name && count && ai, PJ_EINVAL); 
     69 
     70    // Get resolver for the specified address family 
     71    RHostResolver &resv = PjSymbianOS::Instance()->GetResolver(af); 
    3672 
    3773    // Convert name to Unicode 
     
    4783    User::WaitForRequest(reqStatus); 
    4884     
    49     if (reqStatus != KErrNone) 
    50         return PJ_RETURN_OS_ERROR(reqStatus.Int()); 
     85    // Iterate each result 
     86    i = 0; 
     87    while (reqStatus == KErrNone && i < *count) { 
     88         
     89        // Get the resolved TInetAddr 
     90        TInetAddr inetAddr(nameEntry().iAddr); 
     91        int addrlen; 
    5192 
    52     // Get the resolved TInetAddr 
    53     // This doesn't work, see Martin email on 28/3/2007: 
    54     // const TNameRecord &rec = (const TNameRecord&) nameEntry; 
    55     // TInetAddr inetAddr(rec.iAddr); 
    56     TInetAddr inetAddr(nameEntry().iAddr); 
     93        // Ignore if this is not the same address family 
     94        if (inetAddr.Family() != af) { 
     95            resv.Next(nameEntry, reqStatus); 
     96            User::WaitForRequest(reqStatus); 
     97            continue; 
     98        } 
     99         
     100        // Convert the official address to ANSI. 
     101        pj_unicode_to_ansi((const wchar_t*)nameEntry().iName.Ptr(),  
     102                           nameEntry().iName.Length(), 
     103                           ai[i].ai_canonname, sizeof(ai[i].ai_canonname)); 
    57104 
    58     // 
    59     // This where we keep static variables. 
    60     // These should be kept in TLS probably, to allow multiple threads 
    61     // to call pj_gethostbyname() without interfering each other. 
    62     // But again, we don't support threads in Symbian! 
    63     // 
    64     static char resolved_name[PJ_MAX_HOSTNAME]; 
    65     static char *no_aliases[1]; 
    66     static pj_in_addr *addr_list[2]; 
    67     static pj_sockaddr_in resolved_addr; 
     105        // Convert IP address 
     106        addrlen = sizeof(ai[i].ai_addr); 
     107        status = PjSymbianOS::Addr2pj(inetAddr, ai[i].ai_addr, &addrlen); 
     108        if (status != PJ_SUCCESS) 
     109            return status; 
     110         
     111        // Next 
     112        ++i; 
     113        resv.Next(nameEntry, reqStatus); 
     114        User::WaitForRequest(reqStatus); 
     115    } 
    68116 
    69     // Convert the official address to ANSI. 
    70     pj_unicode_to_ansi((const wchar_t*)nameEntry().iName.Ptr(), nameEntry().iName.Length(), 
    71                        resolved_name, sizeof(resolved_name)); 
    72  
    73     // Convert IP address 
    74      
    75     PjSymbianOS::Addr2pj(inetAddr, resolved_addr); 
    76     addr_list[0] = &resolved_addr.sin_addr; 
    77  
    78     // Return hostent 
    79     he->h_name = resolved_name; 
    80     he->h_aliases = no_aliases; 
    81     he->h_addrtype = pj_AF_INET(); 
    82     he->h_length = 4; 
    83     he->h_addr_list = (char**) addr_list; 
    84  
     117    *count = i; 
    85118    return PJ_SUCCESS; 
    86119} 
    87120 
    88  
    89 /* Get the default IP interface */ 
    90 PJ_DEF(pj_status_t) pj_getdefaultipinterface(pj_in_addr *addr) 
     121/* Resolve IPv4/IPv6 address */ 
     122PJ_DEF(pj_status_t) pj_getaddrinfo(int af, const pj_str_t *nodename, 
     123                                   unsigned *count, pj_addrinfo ai[])  
    91124{ 
    92     pj_sock_t fd; 
    93     pj_str_t cp; 
    94     pj_sockaddr_in a; 
    95     int len; 
     125    unsigned start; 
    96126    pj_status_t status; 
    97  
    98     status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &fd); 
    99     if (status != PJ_SUCCESS) { 
    100         return status; 
     127     
     128    PJ_ASSERT_RETURN(af==PJ_AF_INET || af==PJ_AF_INET6 || af==PJ_AF_UNSPEC, 
     129                     PJ_EAFNOTSUP); 
     130    PJ_ASSERT_RETURN(nodename && count && *count && ai, PJ_EINVAL); 
     131     
     132    start = 0; 
     133     
     134    if (af==PJ_AF_INET6 || af==PJ_AF_UNSPEC) { 
     135        unsigned max = *count; 
     136        status = getaddrinfo_by_af(PJ_AF_INET6, nodename,  
     137                                   &max, &ai[start]); 
     138        if (status == PJ_SUCCESS) { 
     139            (*count) -= max; 
     140            start += max; 
     141        } 
    101142    } 
    102  
    103     cp = pj_str("1.1.1.1"); 
    104     pj_sockaddr_in_init(&a, &cp, 53); 
    105  
    106     status = pj_sock_connect(fd, &a, sizeof(a)); 
    107     if (status != PJ_SUCCESS) { 
    108         pj_sock_close(fd); 
    109         return status; 
     143     
     144    if (af==PJ_AF_INET || af==PJ_AF_UNSPEC) { 
     145        unsigned max = *count; 
     146        status = getaddrinfo_by_af(PJ_AF_INET, nodename,  
     147                                   &max, &ai[start]); 
     148        if (status == PJ_SUCCESS) { 
     149            (*count) -= max; 
     150            start += max; 
     151        } 
    110152    } 
    111  
    112     len = sizeof(a); 
    113     status = pj_sock_getsockname(fd, &a, &len); 
    114     if (status != PJ_SUCCESS) { 
    115         pj_sock_close(fd); 
    116         return status; 
     153     
     154    *count = start; 
     155     
     156    if (*count) { 
     157        return PJ_SUCCESS; 
     158    } else { 
     159        return status!=PJ_SUCCESS ? status : PJ_ENOTFOUND; 
    117160    } 
    118  
    119     pj_sock_close(fd); 
    120  
    121     *addr = a.sin_addr; 
    122  
    123     /* Success */ 
    124     return PJ_SUCCESS; 
    125161} 
    126162 
    127  
    128 /* Resolve the IP address of local machine */ 
    129 PJ_DEF(pj_status_t) pj_gethostip(pj_in_addr *addr) 
    130 { 
    131     const pj_str_t *hostname = pj_gethostname(); 
    132     struct pj_hostent he; 
    133     pj_status_t status; 
    134  
    135  
    136     /* Try with resolving local hostname first */ 
    137     status = pj_gethostbyname(hostname, &he); 
    138     if (status == PJ_SUCCESS) { 
    139         *addr = *(pj_in_addr*)he.h_addr; 
    140     } 
    141  
    142  
    143     /* If we end up with 127.x.x.x, resolve the IP by getting the default 
    144      * interface to connect to some public host. 
    145      */ 
    146     if (status != PJ_SUCCESS || (pj_ntohl(addr->s_addr) >> 24)==127 || 
    147         addr->s_addr == 0)  
    148     { 
    149         status = pj_getdefaultipinterface(addr); 
    150     } 
    151  
    152     /* As the last resort, get the first available interface */ 
    153     if (status != PJ_SUCCESS) { 
    154         pj_in_addr addrs[2]; 
    155         unsigned count = PJ_ARRAY_SIZE(addrs); 
    156  
    157         status = pj_enum_ip_interface(&count, addrs); 
    158         if (status == PJ_SUCCESS) { 
    159             if (count != 0) { 
    160                 *addr = addrs[0]; 
    161             } else { 
    162                 /* Just return 127.0.0.1 */ 
    163                 addr->s_addr = pj_htonl(0x7f000001); 
    164             } 
    165         } 
    166     } 
    167  
    168     return status; 
    169 } 
    170  
    171  
Note: See TracChangeset for help on using the changeset viewer.