Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib-util/src/pjlib-util/resolver.c

    r4649 r5826  
    2020#include <pjlib-util/resolver.h> 
    2121#include <pjlib-util/errno.h> 
     22#include <pj/compat/socket.h> 
    2223#include <pj/assert.h> 
    2324#include <pj/ctype.h> 
     
    8081struct nameserver 
    8182{ 
    82     pj_sockaddr_in  addr;               /**< Server address.                */ 
     83    pj_sockaddr     addr;               /**< Server address.                */ 
    8384 
    8485    enum ns_state   state;              /**< Nameserver state.              */ 
     
    169170    /* Internals */ 
    170171    pj_pool_t           *pool;          /**< Internal pool.                 */ 
    171     pj_mutex_t          *mutex;         /**< Mutex protection.              */ 
     172    pj_grp_lock_t       *grp_lock;      /**< Group lock protection.         */ 
    172173    pj_bool_t            own_timer;     /**< Do we own timer?               */ 
    173174    pj_timer_heap_t     *timer;         /**< Timer instance.                */ 
     
    180181    pj_ioqueue_key_t    *udp_key;       /**< UDP socket ioqueue key.        */ 
    181182    unsigned char        udp_rx_pkt[UDPSZ];/**< UDP receive buffer.         */ 
    182     unsigned char        udp_tx_pkt[UDPSZ];/**< UDP receive buffer.         */ 
    183     pj_ssize_t           udp_len;       /**< Length of received packet.     */ 
     183    unsigned char        udp_tx_pkt[UDPSZ];/**< UDP transmit buffer.        */ 
    184184    pj_ioqueue_op_key_t  udp_op_rx_key; /**< UDP read operation key.        */ 
    185185    pj_ioqueue_op_key_t  udp_op_tx_key; /**< UDP write operation key.       */ 
    186     pj_sockaddr_in       udp_src_addr;  /**< Source address of packet       */ 
     186    pj_sockaddr          udp_src_addr;  /**< Source address of packet       */ 
    187187    int                  udp_addr_len;  /**< Source address length.         */ 
     188 
     189#if PJ_HAS_IPV6 
     190    /* IPv6 socket */ 
     191    pj_sock_t            udp6_sock;     /**< UDP socket.                    */ 
     192    pj_ioqueue_key_t    *udp6_key;      /**< UDP socket ioqueue key.        */ 
     193    unsigned char        udp6_rx_pkt[UDPSZ];/**< UDP receive buffer.        */ 
     194    //unsigned char      udp6_tx_pkt[UDPSZ];/**< UDP transmit buffer.       */ 
     195    pj_ioqueue_op_key_t  udp6_op_rx_key;/**< UDP read operation key.        */ 
     196    pj_ioqueue_op_key_t  udp6_op_tx_key;/**< UDP write operation key.       */ 
     197    pj_sockaddr          udp6_src_addr; /**< Source address of packet       */ 
     198    int                  udp6_addr_len; /**< Source address length.         */ 
     199#endif 
    188200 
    189201    /* Settings */ 
     
    225237                                      unsigned servers[]); 
    226238 
     239/* Destructor */ 
     240static void dns_resolver_on_destroy(void *member); 
    227241 
    228242/* Close UDP socket */ 
     
    238252        resv->udp_sock = PJ_INVALID_SOCKET; 
    239253    } 
     254 
     255#if PJ_HAS_IPV6 
     256    if (resv->udp6_key != NULL) { 
     257        pj_ioqueue_unregister(resv->udp6_key); 
     258        resv->udp6_key = NULL; 
     259        resv->udp6_sock = PJ_INVALID_SOCKET; 
     260    } else if (resv->udp6_sock != PJ_INVALID_SOCKET) { 
     261        pj_sock_close(resv->udp6_sock); 
     262        resv->udp6_sock = PJ_INVALID_SOCKET; 
     263    } 
     264#endif 
    240265} 
    241266 
     
    245270{ 
    246271    pj_ioqueue_callback socket_cb; 
     272    pj_sockaddr bound_addr; 
     273    pj_ssize_t rx_pkt_size; 
    247274    pj_status_t status; 
    248275 
     
    260287    pj_bzero(&socket_cb, sizeof(socket_cb)); 
    261288    socket_cb.on_read_complete = &on_read_complete; 
    262     status = pj_ioqueue_register_sock(resv->pool, resv->ioqueue, 
    263                                       resv->udp_sock, resv, &socket_cb, 
    264                                       &resv->udp_key); 
     289    status = pj_ioqueue_register_sock2(resv->pool, resv->ioqueue, 
     290                                       resv->udp_sock, resv->grp_lock, 
     291                                       resv, &socket_cb, &resv->udp_key); 
    265292    if (status != PJ_SUCCESS) 
    266293        return status; 
     
    270297 
    271298    /* Start asynchronous read to the UDP socket */ 
    272     resv->udp_len = sizeof(resv->udp_rx_pkt); 
     299    rx_pkt_size = sizeof(resv->udp_rx_pkt); 
    273300    resv->udp_addr_len = sizeof(resv->udp_src_addr); 
    274301    status = pj_ioqueue_recvfrom(resv->udp_key, &resv->udp_op_rx_key, 
    275                                  resv->udp_rx_pkt, &resv->udp_len, 
     302                                 resv->udp_rx_pkt, &rx_pkt_size, 
    276303                                 PJ_IOQUEUE_ALWAYS_ASYNC, 
    277304                                 &resv->udp_src_addr, &resv->udp_addr_len); 
    278305    if (status != PJ_EPENDING) 
    279306        return status; 
     307 
     308 
     309#if PJ_HAS_IPV6 
     310    /* Also setup IPv6 socket */ 
     311 
     312    /* Create the UDP socket */ 
     313    status = pj_sock_socket(pj_AF_INET6(), pj_SOCK_DGRAM(), 0, 
     314                            &resv->udp6_sock); 
     315    if (status != PJ_SUCCESS) { 
     316        /* Skip IPv6 socket on system without IPv6 (see ticket #1953) */ 
     317        if (status == PJ_STATUS_FROM_OS(OSERR_EAFNOSUPPORT)) { 
     318            PJ_LOG(3,(resv->name.ptr, 
     319                      "System does not support IPv6, resolver will " 
     320                      "ignore any IPv6 nameservers")); 
     321            return PJ_SUCCESS; 
     322        } 
     323        return status; 
     324    } 
     325 
     326    /* Bind to any address/port */ 
     327    pj_sockaddr_init(pj_AF_INET6(), &bound_addr, NULL, 0); 
     328    status = pj_sock_bind(resv->udp6_sock, &bound_addr, 
     329                          pj_sockaddr_get_len(&bound_addr)); 
     330    if (status != PJ_SUCCESS) 
     331        return status; 
     332 
     333    /* Register to ioqueue */ 
     334    pj_bzero(&socket_cb, sizeof(socket_cb)); 
     335    socket_cb.on_read_complete = &on_read_complete; 
     336    status = pj_ioqueue_register_sock2(resv->pool, resv->ioqueue, 
     337                                       resv->udp6_sock, resv->grp_lock, 
     338                                       resv, &socket_cb, &resv->udp6_key); 
     339    if (status != PJ_SUCCESS) 
     340        return status; 
     341 
     342    pj_ioqueue_op_key_init(&resv->udp6_op_rx_key, 
     343                           sizeof(resv->udp6_op_rx_key)); 
     344    pj_ioqueue_op_key_init(&resv->udp6_op_tx_key, 
     345                           sizeof(resv->udp6_op_tx_key)); 
     346 
     347    /* Start asynchronous read to the UDP socket */ 
     348    rx_pkt_size = sizeof(resv->udp6_rx_pkt); 
     349    resv->udp6_addr_len = sizeof(resv->udp6_src_addr); 
     350    status = pj_ioqueue_recvfrom(resv->udp6_key, &resv->udp6_op_rx_key, 
     351                                 resv->udp6_rx_pkt, &rx_pkt_size, 
     352                                 PJ_IOQUEUE_ALWAYS_ASYNC, 
     353                                 &resv->udp6_src_addr, &resv->udp6_addr_len); 
     354    if (status != PJ_EPENDING) 
     355        return status; 
     356#else 
     357    PJ_UNUSED_ARG(bound_addr); 
     358#endif 
    280359 
    281360    return PJ_SUCCESS; 
     
    326405    pj_strdup2_with_null(pool, &resv->name, name); 
    327406     
    328     /* Create the mutex */ 
    329     status = pj_mutex_create_recursive(pool, name, &resv->mutex); 
     407    /* Create group lock */ 
     408    status = pj_grp_lock_create_w_handler(pool, NULL, resv, 
     409                                          &dns_resolver_on_destroy, 
     410                                          &resv->grp_lock);  
    330411    if (status != PJ_SUCCESS) 
    331412        goto on_error; 
     413 
     414    pj_grp_lock_add_ref(resv->grp_lock); 
    332415 
    333416    /* Timer, ioqueue, and settings */ 
     
    341424    /* Create the timer heap if one is not specified */ 
    342425    if (resv->timer == NULL) { 
     426        resv->own_timer = PJ_TRUE; 
    343427        status = pj_timer_heap_create(pool, TIMER_SIZE, &resv->timer); 
    344428        if (status != PJ_SUCCESS) 
     
    348432    /* Create the ioqueue if one is not specified */ 
    349433    if (resv->ioqueue == NULL) { 
     434        resv->own_ioqueue = PJ_TRUE; 
    350435        status = pj_ioqueue_create(pool, MAX_FD, &resv->ioqueue); 
    351436        if (status != PJ_SUCCESS) 
     
    373458    pj_dns_resolver_destroy(resv, PJ_FALSE); 
    374459    return status; 
     460} 
     461 
     462 
     463void dns_resolver_on_destroy(void *member) 
     464{ 
     465    pj_dns_resolver *resolver = (pj_dns_resolver*)member; 
     466    pj_pool_safe_release(&resolver->pool); 
    375467} 
    376468 
     
    432524    } 
    433525 
    434     if (resolver->mutex) { 
    435         pj_mutex_destroy(resolver->mutex); 
    436         resolver->mutex = NULL; 
    437     } 
    438  
    439     if (resolver->pool) { 
    440         pj_pool_t *pool = resolver->pool; 
    441         resolver->pool = NULL; 
    442         pj_pool_release(pool); 
    443     } 
     526    pj_grp_lock_dec_ref(resolver->grp_lock); 
     527 
    444528    return PJ_SUCCESS; 
    445529} 
     
    462546    PJ_ASSERT_RETURN(count < PJ_DNS_RESOLVER_MAX_NS, PJ_EINVAL); 
    463547 
    464     pj_mutex_lock(resolver->mutex); 
     548    pj_grp_lock_acquire(resolver->grp_lock); 
    465549 
    466550    if (count > PJ_DNS_RESOLVER_MAX_NS) 
     
    475559        struct nameserver *ns = &resolver->ns[i]; 
    476560 
    477         status = pj_sockaddr_in_init(&ns->addr, &servers[i],  
    478                                      (pj_uint16_t)(ports ? ports[i] : PORT)); 
     561        status = pj_sockaddr_init(pj_AF_INET(), &ns->addr, &servers[i],  
     562                                  (pj_uint16_t)(ports ? ports[i] : PORT)); 
     563        if (status != PJ_SUCCESS) 
     564            status = pj_sockaddr_init(pj_AF_INET6(), &ns->addr, &servers[i],  
     565                                      (pj_uint16_t)(ports ? ports[i] : PORT)); 
    479566        if (status != PJ_SUCCESS) { 
    480             pj_mutex_unlock(resolver->mutex); 
     567            pj_grp_lock_release(resolver->grp_lock); 
    481568            return PJLIB_UTIL_EDNSINNSADDR; 
    482569        } 
     
    489576    resolver->ns_count = count; 
    490577 
    491     pj_mutex_unlock(resolver->mutex); 
     578    pj_grp_lock_release(resolver->grp_lock); 
    492579    return PJ_SUCCESS; 
    493580} 
     
    503590    PJ_ASSERT_RETURN(resolver && st, PJ_EINVAL); 
    504591 
    505     pj_mutex_lock(resolver->mutex); 
     592    pj_grp_lock_acquire(resolver->grp_lock); 
    506593    pj_memcpy(&resolver->settings, st, sizeof(*st)); 
    507     pj_mutex_unlock(resolver->mutex); 
     594    pj_grp_lock_release(resolver->grp_lock); 
    508595    return PJ_SUCCESS; 
    509596} 
     
    518605    PJ_ASSERT_RETURN(resolver && st, PJ_EINVAL); 
    519606 
    520     pj_mutex_lock(resolver->mutex); 
     607    pj_grp_lock_acquire(resolver->grp_lock); 
    521608    pj_memcpy(st, &resolver->settings, sizeof(*st)); 
    522     pj_mutex_unlock(resolver->mutex); 
     609    pj_grp_lock_release(resolver->grp_lock); 
    523610    return PJ_SUCCESS; 
    524611} 
     
    533620    PJ_ASSERT_ON_FAIL(resolver, return); 
    534621 
    535     pj_mutex_lock(resolver->mutex); 
     622    pj_grp_lock_acquire(resolver->grp_lock); 
    536623    pj_timer_heap_poll(resolver->timer, NULL); 
    537     pj_mutex_unlock(resolver->mutex); 
     624    pj_grp_lock_release(resolver->grp_lock); 
    538625 
    539626    pj_ioqueue_poll(resolver->ioqueue, timeout); 
     
    580667{ 
    581668    unsigned pkt_size; 
    582     unsigned i, server_cnt; 
     669    unsigned i, server_cnt, send_cnt; 
    583670    unsigned servers[PJ_DNS_RESOLVER_MAX_NS]; 
    584671    pj_time_val now; 
     
    607694    delay.msec = resolver->settings.qretr_delay; 
    608695    pj_time_val_normalize(&delay); 
    609     status = pj_timer_heap_schedule(resolver->timer, &q->timer_entry, &delay); 
     696    status = pj_timer_heap_schedule_w_grp_lock(resolver->timer, 
     697                                               &q->timer_entry, 
     698                                               &delay, 1, 
     699                                               resolver->grp_lock); 
    610700    if (status != PJ_SUCCESS) { 
    611701        return status; 
     
    613703 
    614704    /* Check if the socket is available for sending */ 
    615     if (pj_ioqueue_is_pending(resolver->udp_key, &resolver->udp_op_tx_key)) { 
     705    if (pj_ioqueue_is_pending(resolver->udp_key, &resolver->udp_op_tx_key) 
     706#if PJ_HAS_IPV6 
     707        || (resolver->udp6_key && 
     708            pj_ioqueue_is_pending(resolver->udp6_key, 
     709                                  &resolver->udp6_op_tx_key)) 
     710#endif 
     711        ) 
     712    { 
    616713        ++q->transmit_cnt; 
    617714        PJ_LOG(4,(resolver->name.ptr, 
     
    638735 
    639736    /* Send the packet to name servers */ 
     737    send_cnt = 0; 
    640738    for (i=0; i<server_cnt; ++i) { 
     739        char addr[PJ_INET6_ADDRSTRLEN]; 
    641740        pj_ssize_t sent  = (pj_ssize_t) pkt_size; 
    642741        struct nameserver *ns = &resolver->ns[servers[i]]; 
    643742 
    644         status = pj_ioqueue_sendto(resolver->udp_key, 
    645                                    &resolver->udp_op_tx_key, 
    646                                    resolver->udp_tx_pkt, &sent, 0, 
    647                                    &resolver->ns[servers[i]].addr, 
    648                                    sizeof(pj_sockaddr_in)); 
     743        if (ns->addr.addr.sa_family == pj_AF_INET()) { 
     744            status = pj_ioqueue_sendto(resolver->udp_key, 
     745                                       &resolver->udp_op_tx_key, 
     746                                       resolver->udp_tx_pkt, &sent, 0, 
     747                                       &ns->addr, 
     748                                       pj_sockaddr_get_len(&ns->addr)); 
     749            if (status == PJ_SUCCESS || status == PJ_EPENDING) 
     750                send_cnt++; 
     751        } 
     752#if PJ_HAS_IPV6 
     753        else if (resolver->udp6_key) { 
     754            status = pj_ioqueue_sendto(resolver->udp6_key, 
     755                                       &resolver->udp6_op_tx_key, 
     756                                       resolver->udp_tx_pkt, &sent, 0, 
     757                                       &ns->addr, 
     758                                       pj_sockaddr_get_len(&ns->addr)); 
     759            if (status == PJ_SUCCESS || status == PJ_EPENDING) 
     760                send_cnt++; 
     761        } 
     762#endif 
     763        else { 
     764            continue; 
     765        } 
    649766 
    650767        PJ_PERROR(4,(resolver->name.ptr, status, 
     
    652769                  (q->transmit_cnt==0? "Transmitting":"Re-transmitting"), 
    653770                  (int)pkt_size, servers[i], 
    654                   pj_inet_ntoa(ns->addr.sin_addr),  
    655                   (int)pj_ntohs(ns->addr.sin_port), 
     771                  pj_sockaddr_print(&ns->addr, addr, sizeof(addr), 2), 
     772                  pj_sockaddr_get_port(&ns->addr), 
    656773                  pj_dns_get_type_name(q->key.qtype),  
    657774                  q->key.name)); 
     
    661778            ns->sent_time = now; 
    662779        } 
     780    } 
     781 
     782    if (send_cnt == 0) { 
     783        pj_timer_heap_cancel(resolver->timer, &q->timer_entry); 
     784        return PJLIB_UTIL_EDNSNOWORKINGNS; 
    663785    } 
    664786 
     
    747869    struct res_key key; 
    748870    struct cached_res *cache; 
    749     pj_dns_async_query *q; 
     871    pj_dns_async_query *q, *p_q = NULL; 
    750872    pj_uint32_t hval; 
    751873    pj_status_t status = PJ_SUCCESS; 
     
    761883    PJ_ASSERT_RETURN(type > 0 && type < 0xFFFF, PJ_EINVAL); 
    762884 
    763     if (p_query) 
    764         *p_query = NULL; 
    765  
    766885    /* Build resource key for looking up hash tables */ 
    767886    init_res_key(&key, type, name); 
    768887 
    769888    /* Start working with the resolver */ 
    770     pj_mutex_lock(resolver->mutex); 
     889    pj_grp_lock_acquire(resolver->grp_lock); 
    771890 
    772891    /* Get current time. */ 
     
    801920             */ 
    802921            cache->ref_cnt++; 
    803             pj_mutex_unlock(resolver->mutex); 
     922            pj_grp_lock_release(resolver->grp_lock); 
    804923 
    805924            /* This cached response is still valid. Just return this 
     
    811930 
    812931            /* Done. No host resolution is necessary */ 
    813             pj_mutex_lock(resolver->mutex); 
     932            pj_grp_lock_acquire(resolver->grp_lock); 
    814933 
    815934            /* Decrement the ref counter. Also check if it is time to free 
     
    823942            status = PJ_SUCCESS; 
    824943 
    825             goto on_return; 
     944            /* 
     945             * We cannot write to *p_query after calling cb because what 
     946             * p_query points to may have been freed by cb. 
     947             * Refer to ticket #1974. 
     948             */ 
     949            pj_grp_lock_release(resolver->grp_lock); 
     950            return status; 
    826951        } 
    827952 
     
    855980         * query completes. 
    856981         */ 
     982        p_q = nq; 
    857983        status = PJ_SUCCESS; 
    858984        goto on_return; 
     
    8821008                   0, q->hbufkey, q); 
    8831009 
     1010    p_q = q; 
     1011 
     1012on_return: 
    8841013    if (p_query) 
    885         *p_query = q; 
    886  
    887 on_return: 
    888     pj_mutex_unlock(resolver->mutex); 
     1014        *p_query = p_q; 
     1015 
     1016    pj_grp_lock_release(resolver->grp_lock); 
    8891017    return status; 
    8901018} 
     
    9011029    PJ_ASSERT_RETURN(query, PJ_EINVAL); 
    9021030 
    903     pj_mutex_lock(query->resolver->mutex); 
     1031    pj_grp_lock_acquire(query->resolver->grp_lock); 
     1032 
     1033    if (query->timer_entry.id == 1) { 
     1034        pj_timer_heap_cancel_if_active(query->resolver->timer, 
     1035                                       &query->timer_entry, 0); 
     1036    } 
    9041037 
    9051038    cb = query->cb; 
     
    9091042        (*cb)(query->user_data, PJ_ECANCELLED, NULL); 
    9101043 
    911     pj_mutex_unlock(query->resolver->mutex); 
     1044    pj_grp_lock_release(query->resolver->grp_lock); 
    9121045    return PJ_SUCCESS; 
    9131046} 
     
    10271160 
    10281161 
     1162/*  
     1163 * DNS response containing A and/or AAAA packet.  
     1164 */ 
     1165PJ_DEF(pj_status_t) pj_dns_parse_addr_response( 
     1166                                            const pj_dns_parsed_packet *pkt, 
     1167                                            pj_dns_addr_record *rec) 
     1168{ 
     1169    enum { MAX_SEARCH = 20 }; 
     1170    pj_str_t hostname, alias = {NULL, 0}, *resname; 
     1171    pj_size_t bufstart = 0; 
     1172    pj_size_t bufleft; 
     1173    unsigned i, ansidx, cnt=0; 
     1174 
     1175    PJ_ASSERT_RETURN(pkt && rec, PJ_EINVAL); 
     1176 
     1177    /* Init the record */ 
     1178    pj_bzero(rec, sizeof(*rec)); 
     1179 
     1180    bufleft = sizeof(rec->buf_); 
     1181 
     1182    /* Return error if there's error in the packet. */ 
     1183    if (PJ_DNS_GET_RCODE(pkt->hdr.flags)) 
     1184        return PJ_STATUS_FROM_DNS_RCODE(PJ_DNS_GET_RCODE(pkt->hdr.flags)); 
     1185 
     1186    /* Return error if there's no query section */ 
     1187    if (pkt->hdr.qdcount == 0) 
     1188        return PJLIB_UTIL_EDNSINANSWER; 
     1189 
     1190    /* Return error if there's no answer */ 
     1191    if (pkt->hdr.anscount == 0) 
     1192        return PJLIB_UTIL_EDNSNOANSWERREC; 
     1193 
     1194    /* Get the hostname from the query. */ 
     1195    hostname = pkt->q[0].name; 
     1196 
     1197    /* Copy hostname to the record */ 
     1198    if (hostname.slen > (int)bufleft) { 
     1199        return PJ_ENAMETOOLONG; 
     1200    } 
     1201 
     1202    pj_memcpy(&rec->buf_[bufstart], hostname.ptr, hostname.slen); 
     1203    rec->name.ptr = &rec->buf_[bufstart]; 
     1204    rec->name.slen = hostname.slen; 
     1205 
     1206    bufstart += hostname.slen; 
     1207    bufleft -= hostname.slen; 
     1208 
     1209    /* Find the first RR which name matches the hostname. */ 
     1210    for (ansidx=0; ansidx < pkt->hdr.anscount; ++ansidx) { 
     1211        if (pj_stricmp(&pkt->ans[ansidx].name, &hostname)==0) 
     1212            break; 
     1213    } 
     1214 
     1215    if (ansidx == pkt->hdr.anscount) 
     1216        return PJLIB_UTIL_EDNSNOANSWERREC; 
     1217 
     1218    resname = &hostname; 
     1219 
     1220    /* Keep following CNAME records. */ 
     1221    while (pkt->ans[ansidx].type == PJ_DNS_TYPE_CNAME && 
     1222           cnt++ < MAX_SEARCH) 
     1223    { 
     1224        resname = &pkt->ans[ansidx].rdata.cname.name; 
     1225 
     1226        if (!alias.slen) 
     1227            alias = *resname; 
     1228 
     1229        for (i=0; i < pkt->hdr.anscount; ++i) { 
     1230            if (pj_stricmp(resname, &pkt->ans[i].name)==0) 
     1231                break; 
     1232        } 
     1233 
     1234        if (i==pkt->hdr.anscount) 
     1235            return PJLIB_UTIL_EDNSNOANSWERREC; 
     1236 
     1237        ansidx = i; 
     1238    } 
     1239 
     1240    if (cnt >= MAX_SEARCH) 
     1241        return PJLIB_UTIL_EDNSINANSWER; 
     1242 
     1243    if (pkt->ans[ansidx].type != PJ_DNS_TYPE_A && 
     1244        pkt->ans[ansidx].type != PJ_DNS_TYPE_AAAA) 
     1245    { 
     1246        return PJLIB_UTIL_EDNSINANSWER; 
     1247    } 
     1248 
     1249    /* Copy alias to the record, if present. */ 
     1250    if (alias.slen) { 
     1251        if (alias.slen > (int)bufleft) 
     1252            return PJ_ENAMETOOLONG; 
     1253 
     1254        pj_memcpy(&rec->buf_[bufstart], alias.ptr, alias.slen); 
     1255        rec->alias.ptr = &rec->buf_[bufstart]; 
     1256        rec->alias.slen = alias.slen; 
     1257 
     1258        bufstart += alias.slen; 
     1259        bufleft -= alias.slen; 
     1260    } 
     1261 
     1262    /* Get the IP addresses. */ 
     1263    cnt = 0; 
     1264    for (i=0; i < pkt->hdr.anscount && cnt < PJ_DNS_MAX_IP_IN_A_REC ; ++i) { 
     1265        if ((pkt->ans[i].type == PJ_DNS_TYPE_A || 
     1266             pkt->ans[i].type == PJ_DNS_TYPE_AAAA) && 
     1267            pj_stricmp(&pkt->ans[i].name, resname)==0) 
     1268        { 
     1269            if (pkt->ans[i].type == PJ_DNS_TYPE_A) { 
     1270                rec->addr[cnt].af = pj_AF_INET(); 
     1271                rec->addr[cnt].ip.v4 = pkt->ans[i].rdata.a.ip_addr; 
     1272            } else { 
     1273                rec->addr[cnt].af = pj_AF_INET6(); 
     1274                rec->addr[cnt].ip.v6 = pkt->ans[i].rdata.aaaa.ip_addr; 
     1275            } 
     1276            ++cnt; 
     1277        } 
     1278    } 
     1279    rec->addr_count = cnt; 
     1280 
     1281    if (cnt == 0) 
     1282        return PJLIB_UTIL_EDNSNOANSWERREC; 
     1283 
     1284    return PJ_SUCCESS; 
     1285} 
     1286 
     1287 
    10291288/* Set nameserver state */ 
    10301289static void set_nameserver_state(pj_dns_resolver *resolver, 
     
    10351294    struct nameserver *ns = &resolver->ns[index]; 
    10361295    enum ns_state old_state = ns->state; 
     1296    char addr[PJ_INET6_ADDRSTRLEN]; 
    10371297 
    10381298    ns->state = state; 
     
    10481308 
    10491309    PJ_LOG(5, (resolver->name.ptr, "Nameserver %s:%d state changed %s --> %s", 
    1050                pj_inet_ntoa(ns->addr.sin_addr), 
    1051                (int)pj_ntohs(ns->addr.sin_port), 
     1310               pj_sockaddr_print(&ns->addr, addr, sizeof(addr), 2), 
     1311               pj_sockaddr_get_port(&ns->addr), 
    10521312               state_names[old_state], state_names[state])); 
    10531313} 
     
    11281388/* Update name server status */ 
    11291389static void report_nameserver_status(pj_dns_resolver *resolver, 
    1130                                      const pj_sockaddr_in *ns_addr, 
     1390                                     const pj_sockaddr *ns_addr, 
    11311391                                     const pj_dns_parsed_packet *pkt) 
    11321392{ 
     
    11481408    } 
    11491409 
    1150     if (!pkt || rcode == PJ_DNS_RCODE_SERVFAIL || 
     1410    /* Some nameserver is reported to respond with PJ_DNS_RCODE_SERVFAIL for 
     1411     * missing AAAA record, and the standard doesn't seem to specify that 
     1412     * SERVFAIL should prevent the server to be contacted again for other 
     1413     * queries. So let's not mark nameserver as bad for SERVFAIL response. 
     1414     */ 
     1415    if (!pkt || /* rcode == PJ_DNS_RCODE_SERVFAIL || */ 
    11511416                rcode == PJ_DNS_RCODE_REFUSED || 
    11521417                rcode == PJ_DNS_RCODE_NOTAUTH)  
     
    11651430        struct nameserver *ns = &resolver->ns[i]; 
    11661431 
    1167         if (ns->addr.sin_addr.s_addr == ns_addr->sin_addr.s_addr && 
    1168             ns->addr.sin_port == ns_addr->sin_port && 
    1169             ns->addr.sin_family == ns_addr->sin_family) 
    1170         { 
     1432        if (pj_sockaddr_cmp(&ns->addr, ns_addr) == 0) { 
    11711433            if (q_id == ns->q_id) { 
    11721434                /* Calculate response time */ 
     
    12331495        ttl = resolver->settings.cache_max_ttl; 
    12341496 
     1497    /* Get a cache response entry */ 
     1498    cache = (struct cached_res *) pj_hash_get(resolver->hrescache, key, 
     1499                                              sizeof(*key), &hval); 
     1500 
    12351501    /* If TTL is zero, clear the same entry in the hash table */ 
    12361502    if (ttl == 0) { 
    1237         cache = (struct cached_res *) pj_hash_get(resolver->hrescache, key,  
    1238                                                   sizeof(*key), &hval); 
    12391503        /* Remove the entry before releasing its pool (see ticket #1710) */ 
    12401504        pj_hash_set(NULL, resolver->hrescache, key, sizeof(*key), hval, NULL); 
     
    12461510    } 
    12471511 
    1248     /* Get a cache response entry */ 
    1249     cache = (struct cached_res *) pj_hash_get(resolver->hrescache, key,  
    1250                                               sizeof(*key), &hval); 
    12511512    if (cache == NULL) { 
    1252         cache = alloc_entry(resolver); 
    1253     } else if (cache->ref_cnt > 1) { 
    1254         /* When cache entry is being used by callback (to app), just decrement 
    1255          * ref_cnt so it will be freed after the callback returns and allocate 
    1256          * new entry. 
    1257          */ 
    1258         cache->ref_cnt--; 
    12591513        cache = alloc_entry(resolver); 
    12601514    } else { 
     
    12621516        pj_hash_set(NULL, resolver->hrescache, key, sizeof(*key), hval, NULL); 
    12631517 
    1264         /* Reset cache to avoid bloated cache pool */ 
    1265         reset_entry(&cache); 
     1518        if (cache->ref_cnt > 1) { 
     1519            /* When cache entry is being used by callback (to app), 
     1520             * just decrement ref_cnt so it will be freed after 
     1521             * the callback returns and allocate new entry. 
     1522             */ 
     1523            cache->ref_cnt--; 
     1524            cache = alloc_entry(resolver); 
     1525        } else { 
     1526            /* Reset cache to avoid bloated cache pool */ 
     1527            reset_entry(&cache); 
     1528        } 
    12661529    } 
    12671530 
     
    13081571    resolver = q->resolver; 
    13091572 
    1310     pj_mutex_lock(resolver->mutex); 
     1573    pj_grp_lock_acquire(resolver->grp_lock); 
    13111574 
    13121575    /* Recheck that this query is still pending, since there is a slight 
     
    13161579    if (pj_hash_get(resolver->hquerybyid, &q->id, sizeof(q->id), NULL)==NULL) { 
    13171580        /* Yeah, this query is done. */ 
    1318         pj_mutex_unlock(resolver->mutex); 
     1581        pj_grp_lock_release(resolver->grp_lock); 
    13191582        return; 
    13201583    } 
     
    13271590        status = transmit_query(resolver, q); 
    13281591        if (status == PJ_SUCCESS) { 
    1329             pj_mutex_unlock(resolver->mutex); 
     1592            pj_grp_lock_release(resolver->grp_lock); 
    13301593            return; 
    13311594        } else { 
     
    13461609 
    13471610    /* Workaround for deadlock problem in #1565 (similar to #1108) */ 
    1348     pj_mutex_unlock(resolver->mutex); 
     1611    pj_grp_lock_release(resolver->grp_lock); 
    13491612 
    13501613    /* Call application callback, if any. */ 
     
    13611624 
    13621625    /* Workaround for deadlock problem in #1565 (similar to #1108) */ 
    1363     pj_mutex_lock(resolver->mutex); 
     1626    pj_grp_lock_acquire(resolver->grp_lock); 
    13641627 
    13651628    /* Clear data */ 
     
    13781641    pj_list_push_back(&resolver->query_free_nodes, q); 
    13791642 
    1380     pj_mutex_unlock(resolver->mutex); 
     1643    pj_grp_lock_release(resolver->grp_lock); 
    13811644} 
    13821645 
     
    13911654    pj_dns_parsed_packet *dns_pkt; 
    13921655    pj_dns_async_query *q; 
     1656    char addr[PJ_INET6_ADDRSTRLEN]; 
     1657    pj_sockaddr *src_addr; 
     1658    int *src_addr_len; 
     1659    unsigned char *rx_pkt; 
     1660    pj_ssize_t rx_pkt_size; 
    13931661    pj_status_t status; 
    13941662    PJ_USE_EXCEPTION; 
     
    13961664 
    13971665    resolver = (pj_dns_resolver *) pj_ioqueue_get_user_data(key); 
    1398     pj_mutex_lock(resolver->mutex); 
     1666    pj_assert(resolver); 
     1667 
     1668#if PJ_HAS_IPV6 
     1669    if (key == resolver->udp6_key) { 
     1670        src_addr = &resolver->udp6_src_addr; 
     1671        src_addr_len = &resolver->udp6_addr_len; 
     1672        rx_pkt = resolver->udp6_rx_pkt; 
     1673        rx_pkt_size = sizeof(resolver->udp6_rx_pkt); 
     1674    } else  
     1675#endif 
     1676    { 
     1677        src_addr = &resolver->udp_src_addr; 
     1678        src_addr_len = &resolver->udp_addr_len; 
     1679        rx_pkt = resolver->udp_rx_pkt; 
     1680        rx_pkt_size = sizeof(resolver->udp_rx_pkt); 
     1681    } 
     1682 
     1683    pj_grp_lock_acquire(resolver->grp_lock); 
    13991684 
    14001685 
     
    14051690        status = (pj_status_t)-bytes_read; 
    14061691        pj_strerror(status, errmsg, sizeof(errmsg)); 
    1407         PJ_LOG(4,(resolver->name.ptr,  
    1408                   "DNS resolver read error from %s:%d: %s",  
    1409                   pj_inet_ntoa(resolver->udp_src_addr.sin_addr), 
    1410                   pj_ntohs(resolver->udp_src_addr.sin_port), 
    1411                   errmsg)); 
     1692        PJ_LOG(4,(resolver->name.ptr, "DNS resolver read error: %s", errmsg)); 
    14121693 
    14131694        goto read_next_packet; 
     
    14171698              "Received %d bytes DNS response from %s:%d", 
    14181699              (int)bytes_read,  
    1419               pj_inet_ntoa(resolver->udp_src_addr.sin_addr), 
    1420               pj_ntohs(resolver->udp_src_addr.sin_port))); 
     1700              pj_sockaddr_print(src_addr, addr, sizeof(addr), 2), 
     1701              pj_sockaddr_get_port(src_addr))); 
    14211702 
    14221703 
     
    14331714    dns_pkt = NULL; 
    14341715    PJ_TRY { 
    1435         status = pj_dns_parse_packet(pool, resolver->udp_rx_pkt,  
     1716        status = pj_dns_parse_packet(pool, rx_pkt,  
    14361717                                     (unsigned)bytes_read, &dns_pkt); 
    14371718    } 
     
    14421723 
    14431724    /* Update nameserver status */ 
    1444     report_nameserver_status(resolver, &resolver->udp_src_addr, dns_pkt); 
     1725    report_nameserver_status(resolver, src_addr, dns_pkt); 
    14451726 
    14461727    /* Handle parse error */ 
     
    14511732        PJ_LOG(3,(resolver->name.ptr,  
    14521733                  "Error parsing DNS response from %s:%d: %s",  
    1453                   pj_inet_ntoa(resolver->udp_src_addr.sin_addr),  
    1454                   pj_ntohs(resolver->udp_src_addr.sin_port),  
     1734                  pj_sockaddr_print(src_addr, addr, sizeof(addr), 2), 
     1735                  pj_sockaddr_get_port(src_addr), 
    14551736                  errmsg)); 
    14561737        goto read_next_packet; 
     
    14641745        PJ_LOG(5,(resolver->name.ptr,  
    14651746                  "DNS response from %s:%d id=%d discarded", 
    1466                   pj_inet_ntoa(resolver->udp_src_addr.sin_addr),  
    1467                   pj_ntohs(resolver->udp_src_addr.sin_port), 
     1747                  pj_sockaddr_print(src_addr, addr, sizeof(addr), 2), 
     1748                  pj_sockaddr_get_port(src_addr), 
    14681749                  (unsigned)dns_pkt->hdr.id)); 
    14691750        goto read_next_packet; 
     
    14831764 
    14841765    /* Workaround for deadlock problem in #1108 */ 
    1485     pj_mutex_unlock(resolver->mutex); 
     1766    pj_grp_lock_release(resolver->grp_lock); 
    14861767 
    14871768    /* Notify applications first, to allow application to modify the  
     
    15041785 
    15051786    /* Workaround for deadlock problem in #1108 */ 
    1506     pj_mutex_lock(resolver->mutex); 
     1787    pj_grp_lock_acquire(resolver->grp_lock); 
    15071788 
    15081789    /* Save/update response cache. */ 
     
    15281809        pj_pool_release(pool); 
    15291810    } 
    1530     bytes_read = sizeof(resolver->udp_rx_pkt); 
    1531     resolver->udp_addr_len = sizeof(resolver->udp_src_addr); 
    1532     status = pj_ioqueue_recvfrom(resolver->udp_key, op_key,  
    1533                                  resolver->udp_rx_pkt, 
    1534                                  &bytes_read, PJ_IOQUEUE_ALWAYS_ASYNC, 
    1535                                  &resolver->udp_src_addr,  
    1536                                  &resolver->udp_addr_len); 
    1537     if (status != PJ_EPENDING) { 
     1811 
     1812    status = pj_ioqueue_recvfrom(key, op_key, rx_pkt, &rx_pkt_size, 
     1813                                 PJ_IOQUEUE_ALWAYS_ASYNC, 
     1814                                 src_addr, src_addr_len); 
     1815 
     1816    if (status != PJ_EPENDING && status != PJ_ECANCELLED) { 
    15381817        char errmsg[PJ_ERR_MSG_SIZE]; 
    15391818 
     
    15451824    } 
    15461825 
    1547     pj_mutex_unlock(resolver->mutex); 
     1826    pj_grp_lock_release(resolver->grp_lock); 
    15481827} 
    15491828 
     
    15711850                     PJLIB_UTIL_EDNSNOANSWERREC); 
    15721851 
    1573     pj_mutex_lock(resolver->mutex); 
     1852    pj_grp_lock_acquire(resolver->grp_lock); 
    15741853 
    15751854    /* Build resource key for looking up hash tables */ 
     
    15931872    update_res_cache(resolver, &key, PJ_SUCCESS, set_ttl, pkt); 
    15941873 
    1595     pj_mutex_unlock(resolver->mutex); 
     1874    pj_grp_lock_release(resolver->grp_lock); 
    15961875 
    15971876    return PJ_SUCCESS; 
     
    16081887    PJ_ASSERT_RETURN(resolver, 0); 
    16091888 
    1610     pj_mutex_lock(resolver->mutex); 
     1889    pj_grp_lock_acquire(resolver->grp_lock); 
    16111890    count = pj_hash_count(resolver->hrescache); 
    1612     pj_mutex_unlock(resolver->mutex); 
     1891    pj_grp_lock_release(resolver->grp_lock); 
    16131892 
    16141893    return count; 
     
    16261905    pj_time_val now; 
    16271906 
    1628     pj_mutex_lock(resolver->mutex); 
     1907    pj_grp_lock_acquire(resolver->grp_lock); 
    16291908 
    16301909    pj_gettimeofday(&now); 
     
    16341913    PJ_LOG(3,(resolver->name.ptr, "  Name servers:")); 
    16351914    for (i=0; i<resolver->ns_count; ++i) { 
    1636         const char *state_names[] = { "probing", "active", "bad"}; 
     1915        char addr[PJ_INET6_ADDRSTRLEN]; 
    16371916        struct nameserver *ns = &resolver->ns[i]; 
    16381917 
    16391918        PJ_LOG(3,(resolver->name.ptr, 
    16401919                  "   NS %d: %s:%d (state=%s until %ds, rtt=%d ms)", 
    1641                   i, pj_inet_ntoa(ns->addr.sin_addr), 
    1642                   pj_ntohs(ns->addr.sin_port), 
     1920                  i, 
     1921                  pj_sockaddr_print(&ns->addr, addr, sizeof(addr), 2), 
     1922                  pj_sockaddr_get_port(&ns->addr), 
    16431923                  state_names[ns->state], 
    16441924                  ns->state_expiry.sec - now.sec, 
     
    16851965              pj_pool_get_used_size(resolver->pool))); 
    16861966 
    1687     pj_mutex_unlock(resolver->mutex); 
     1967    pj_grp_lock_release(resolver->grp_lock); 
    16881968#endif 
    16891969} 
Note: See TracChangeset for help on using the changeset viewer.