Ignore:
Timestamp:
Dec 28, 2016 3:40:07 AM (7 years ago)
Author:
nanang
Message:

Re #1900: More merged from trunk (r5512 mistakenly contains merged changes in third-party dir only).

Location:
pjproject/branches/projects/uwp
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/uwp

  • pjproject/branches/projects/uwp/pjlib-util/src/pjlib-util/srv_resolver.c

    r5170 r5513  
    3838}; 
    3939 
     40#pragma pack(1) 
    4041struct srv_target 
    4142{ 
    4243    struct common           common; 
     44    struct common           common_aaaa; 
    4345    pj_dns_srv_async_query *parent; 
    4446    pj_str_t                target_name; 
    4547    pj_dns_async_query     *q_a; 
     48    pj_dns_async_query     *q_aaaa; 
    4649    char                    target_buf[PJ_MAX_HOSTNAME]; 
    4750    pj_str_t                cname; 
    4851    char                    cname_buf[PJ_MAX_HOSTNAME]; 
    49     unsigned                port; 
     52    pj_uint16_t             port; 
    5053    unsigned                priority; 
    5154    unsigned                weight; 
    5255    unsigned                sum; 
    5356    unsigned                addr_cnt; 
    54     pj_in_addr              addr[ADDR_MAX_COUNT]; 
     57    pj_sockaddr             addr[ADDR_MAX_COUNT];/**< Address family and IP.*/ 
    5558}; 
     59#pragma pack() 
    5660 
    5761struct pj_dns_srv_async_query 
     
    136140    query_job->def_port = (pj_uint16_t)def_port; 
    137141 
     142    /* Normalize query job option PJ_DNS_SRV_RESOLVE_AAAA_ONLY */ 
     143    if (query_job->option & PJ_DNS_SRV_RESOLVE_AAAA_ONLY) 
     144        query_job->option |= PJ_DNS_SRV_RESOLVE_AAAA; 
     145 
    138146    /* Start the asynchronous query_job */ 
    139147 
     
    178186            srv->q_a = NULL; 
    179187            has_pending = PJ_TRUE; 
     188        } 
     189        if (srv->q_aaaa) { 
     190            /* Check if it is a dummy query. */ 
     191            if (srv->q_aaaa != (pj_dns_async_query*)0x1) { 
     192                pj_dns_resolver_cancel_query(srv->q_aaaa, PJ_FALSE); 
     193                has_pending = PJ_TRUE; 
     194            } 
     195            srv->q_aaaa = NULL; 
    180196        } 
    181197    } 
     
    315331    } 
    316332 
    317     /* Check for Additional Info section if A records are available, and 
    318      * fill in the IP address (so that we won't need to resolve the A  
     333    /* Check for Additional Info section if A/AAAA records are available, and 
     334     * fill in the IP address (so that we won't need to resolve the A/AAAA  
    319335     * record with another DNS query_job).  
    320336     */ 
     
    323339        unsigned j; 
    324340 
    325         if (rr->type != PJ_DNS_TYPE_A) 
     341        /* Skip non-A/AAAA record */ 
     342        if (rr->type != PJ_DNS_TYPE_A && rr->type != PJ_DNS_TYPE_AAAA) 
    326343            continue; 
    327344 
    328         /* Yippeaiyee!! There is an "A" record!  
     345        /* Also skip if: 
     346         * - it is A record and app only want AAAA record, or 
     347         * - it is AAAA record and app does not want AAAA record 
     348         */ 
     349        if ((rr->type == PJ_DNS_TYPE_A && 
     350            (query_job->option & PJ_DNS_SRV_RESOLVE_AAAA_ONLY)!=0) || 
     351            (rr->type == PJ_DNS_TYPE_AAAA && 
     352            (query_job->option & PJ_DNS_SRV_RESOLVE_AAAA)==0)) 
     353        { 
     354            continue; 
     355        }            
     356 
     357        /* Yippeaiyee!! There is an "A/AAAA" record!  
    329358         * Update the IP address of the corresponding SRV record. 
    330359         */ 
    331360        for (j=0; j<query_job->srv_cnt; ++j) { 
    332             if (pj_stricmp(&rr->name, &query_job->srv[j].target_name)==0 && 
    333                 query_job->srv[j].addr_cnt < ADDR_MAX_COUNT) 
    334             { 
     361            if (pj_stricmp(&rr->name, &query_job->srv[j].target_name)==0 
     362                && query_job->srv[j].addr_cnt < ADDR_MAX_COUNT) 
     363            { 
    335364                unsigned cnt = query_job->srv[j].addr_cnt; 
    336                 query_job->srv[j].addr[cnt].s_addr = rr->rdata.a.ip_addr.s_addr; 
     365                if (rr->type == PJ_DNS_TYPE_A) { 
     366                    pj_sockaddr_init(pj_AF_INET(), 
     367                                        &query_job->srv[j].addr[cnt], NULL, 
     368                                        query_job->srv[j].port); 
     369                    query_job->srv[j].addr[cnt].ipv4.sin_addr = 
     370                                                rr->rdata.a.ip_addr; 
     371                } else { 
     372                    pj_sockaddr_init(pj_AF_INET6(), 
     373                                        &query_job->srv[j].addr[cnt], NULL, 
     374                                        query_job->srv[j].port); 
     375                    query_job->srv[j].addr[cnt].ipv6.sin6_addr = 
     376                                                rr->rdata.aaaa.ip_addr; 
     377                } 
     378 
    337379                /* Only increment host_resolved once per SRV record */ 
    338380                if (query_job->srv[j].addr_cnt == 0) 
    339381                    ++query_job->host_resolved; 
     382 
    340383                ++query_job->srv[j].addr_cnt; 
    341384                break; 
     
    355398        } 
    356399        */ 
     400         
    357401    } 
    358402 
     
    363407    for (i=0; i<query_job->srv_cnt; ++i) { 
    364408        pj_in_addr addr; 
     409        pj_in6_addr addr6; 
    365410 
    366411        if (query_job->srv[i].addr_cnt != 0) { 
     
    369414        } 
    370415 
    371         if (pj_inet_aton(&query_job->srv[i].target_name, &addr) != 0) { 
    372             query_job->srv[i].addr[query_job->srv[i].addr_cnt++] = addr; 
     416        if ((query_job->option & PJ_DNS_SRV_RESOLVE_AAAA_ONLY)==0 && 
     417            pj_inet_pton(pj_AF_INET(), &query_job->srv[i].target_name, 
     418                         &addr) == PJ_SUCCESS) 
     419        { 
     420            unsigned cnt = query_job->srv[i].addr_cnt; 
     421            pj_sockaddr_init(pj_AF_INET(), &query_job->srv[i].addr[cnt], 
     422                             NULL, query_job->srv[i].port); 
     423            query_job->srv[i].addr[cnt].ipv4.sin_addr = addr; 
     424            ++query_job->srv[i].addr_cnt; 
     425            ++query_job->host_resolved; 
     426        } else if ((query_job->option & PJ_DNS_SRV_RESOLVE_AAAA)!=0 && 
     427                   pj_inet_pton(pj_AF_INET6(), &query_job->srv[i].target_name, 
     428                                &addr6) == PJ_SUCCESS) 
     429        { 
     430            unsigned cnt = query_job->srv[i].addr_cnt; 
     431            pj_sockaddr_init(pj_AF_INET6(), &query_job->srv[i].addr[cnt], 
     432                             NULL, query_job->srv[i].port); 
     433            query_job->srv[i].addr[cnt].ipv6.sin6_addr = addr6; 
     434            ++query_job->srv[i].addr_cnt; 
    373435            ++query_job->host_resolved; 
    374436        } 
     
    386448 
    387449    for (i=0; i<query_job->srv_cnt; ++i) { 
    388         const char *addr; 
    389  
    390         if (query_job->srv[i].addr_cnt != 0) 
    391             addr = pj_inet_ntoa(query_job->srv[i].addr[0]); 
    392         else 
    393             addr = "-"; 
     450        char addr[PJ_INET6_ADDRSTRLEN]; 
     451 
     452        if (query_job->srv[i].addr_cnt != 0) { 
     453            pj_sockaddr_print(&query_job->srv[i].addr[0], 
     454                         addr, sizeof(addr), 2); 
     455        } else 
     456            pj_ansi_strcpy(addr, "-"); 
    394457 
    395458        PJ_LOG(5,(query_job->objname,  
     
    405468 
    406469 
    407 /* Start DNS A record queries for all SRV records in the query_job structure */ 
     470/* Start DNS A and/or AAAA record queries for all SRV records in 
     471 * the query_job structure. 
     472 */ 
    408473static pj_status_t resolve_hostnames(pj_dns_srv_async_query *query_job) 
    409474{ 
     
    412477 
    413478    query_job->dns_state = PJ_DNS_TYPE_A; 
     479 
    414480    for (i=0; i<query_job->srv_cnt; ++i) { 
    415481        struct srv_target *srv = &query_job->srv[i]; 
     
    421487 
    422488        srv->common.type = PJ_DNS_TYPE_A; 
     489        srv->common_aaaa.type = PJ_DNS_TYPE_AAAA; 
    423490        srv->parent = query_job; 
     491        srv->q_a = NULL; 
     492        srv->q_aaaa = NULL; 
     493 
     494        status = PJ_SUCCESS; 
     495 
     496        /* Start DNA A record query */ 
     497        if ((query_job->option & PJ_DNS_SRV_RESOLVE_AAAA_ONLY) == 0) 
     498        { 
     499            if ((query_job->option & PJ_DNS_SRV_RESOLVE_AAAA) != 0) { 
     500                /* If there will be DNS AAAA query too, let's setup 
     501                 * a dummy one here, otherwise app callback may be called 
     502                 * immediately (before DNS AAAA query is sent) when 
     503                 * DNS A record is available in the cache. 
     504                 */ 
     505                srv->q_aaaa = (pj_dns_async_query*)0x1; 
     506            } 
     507            status = pj_dns_resolver_start_query(query_job->resolver, 
     508                                                 &srv->target_name, 
     509                                                 PJ_DNS_TYPE_A, 0, 
     510                                                 &dns_callback, 
     511                                                 &srv->common, &srv->q_a); 
     512        } 
     513 
     514        /* Start DNA AAAA record query */ 
     515        if (status == PJ_SUCCESS && 
     516            (query_job->option & PJ_DNS_SRV_RESOLVE_AAAA) != 0) 
     517        { 
     518            status = pj_dns_resolver_start_query(query_job->resolver, 
     519                                                 &srv->target_name, 
     520                                                 PJ_DNS_TYPE_AAAA, 0, 
     521                                                 &dns_callback, 
     522                                                 &srv->common_aaaa, &srv->q_aaaa); 
     523        } 
    424524 
    425525        /* See also #1809: dns_callback() will be invoked synchronously when response 
     
    428528         * returning false error, so don't use that variable for counting errors. 
    429529         */ 
    430         status = pj_dns_resolver_start_query(query_job->resolver, 
    431                                              &srv->target_name, 
    432                                              PJ_DNS_TYPE_A, 0, 
    433                                              &dns_callback, 
    434                                              srv, &srv->q_a); 
    435530        if (status != PJ_SUCCESS) { 
    436531            query_job->host_resolved++; 
     
    462557        srv = (struct srv_target*) common; 
    463558        query_job = srv->parent; 
     559    } else if (common->type == PJ_DNS_TYPE_AAAA) { 
     560        srv = (struct srv_target*)((pj_int8_t*)common-sizeof(struct common)); 
     561        query_job = srv->parent; 
    464562    } else { 
    465563        pj_assert(!"Unexpected user data!"); 
     
    472570        /* We are getting SRV response */ 
    473571 
     572        /* Clear the outstanding job */ 
    474573        query_job->q_srv = NULL; 
    475574 
     
    505604         */ 
    506605        if (query_job->srv_cnt == 0) { 
     606            unsigned new_option = 0; 
     607 
    507608            /* Looks like we aren't getting any SRV responses. 
    508609             * Resolve the original target as A record by creating a  
     
    511612            PJ_LOG(4, (query_job->objname,  
    512613                       "DNS SRV resolution failed for %.*s, trying " 
    513                        "resolving A record for %.*s", 
     614                       "resolving A/AAAA record for %.*s", 
    514615                       (int)query_job->full_name.slen,  
    515616                       query_job->full_name.ptr, 
     
    524625            query_job->srv[i].weight = 0; 
    525626            query_job->srv[i].port = query_job->def_port; 
    526         }  
     627 
     628            /* Update query_job resolution option based on fallback option */ 
     629            if (query_job->option & PJ_DNS_SRV_FALLBACK_AAAA) 
     630                new_option |= (PJ_DNS_SRV_RESOLVE_AAAA | 
     631                               PJ_DNS_SRV_RESOLVE_AAAA_ONLY); 
     632            if (query_job->option & PJ_DNS_SRV_FALLBACK_A) 
     633                new_option &= (~PJ_DNS_SRV_RESOLVE_AAAA_ONLY); 
     634             
     635            query_job->option = new_option; 
     636        } 
    527637         
    528638 
    529         /* Resolve server hostnames (DNS A record) for hosts which don't have 
    530          * A record yet. 
     639        /* Resolve server hostnames (DNS A/AAAA record) for hosts which 
     640         * don't have A/AAAA record yet. 
    531641         */ 
    532642        if (query_job->host_resolved != query_job->srv_cnt) { 
     
    542652 
    543653    } else if (query_job->dns_state == PJ_DNS_TYPE_A) { 
    544  
    545         /* Clear the outstanding job */ 
    546         srv->q_a = NULL; 
     654        pj_bool_t is_type_a, srv_completed; 
     655 
     656        /* Clear outstanding job */ 
     657        if (common->type == PJ_DNS_TYPE_A) { 
     658            srv_completed = (srv->q_aaaa == NULL); 
     659            srv->q_a = NULL; 
     660        } else if (common->type == PJ_DNS_TYPE_AAAA) { 
     661            srv_completed = (srv->q_a == NULL); 
     662            srv->q_aaaa = NULL; 
     663        } else { 
     664            pj_assert(!"Unexpected job type"); 
     665            query_job->last_error = status = PJ_EINVALIDOP; 
     666            goto on_error; 
     667        } 
     668 
     669        is_type_a = (common->type == PJ_DNS_TYPE_A); 
    547670 
    548671        /* Check that we really have answer */ 
    549672        if (status==PJ_SUCCESS && pkt->hdr.anscount != 0) { 
    550             pj_dns_a_record rec; 
     673            char addr[PJ_INET6_ADDRSTRLEN]; 
     674            pj_dns_addr_record rec; 
    551675 
    552676            /* Parse response */ 
    553             status = pj_dns_parse_a_response(pkt, &rec); 
     677            status = pj_dns_parse_addr_response(pkt, &rec); 
    554678            if (status != PJ_SUCCESS) 
    555679                goto on_error; 
     
    558682 
    559683            /* Update CNAME alias, if present. */ 
    560             if (rec.alias.slen) { 
     684            if (srv->cname.slen==0 && rec.alias.slen) { 
    561685                pj_assert(rec.alias.slen <= (int)sizeof(srv->cname_buf)); 
    562686                srv->cname.ptr = srv->cname_buf; 
    563687                pj_strcpy(&srv->cname, &rec.alias); 
    564             } else { 
    565                 srv->cname.slen = 0; 
     688            //} else { 
     689                //srv->cname.slen = 0; 
    566690            } 
    567691 
    568692            /* Update IP address of the corresponding hostname or CNAME */ 
    569             if (srv->addr_cnt < ADDR_MAX_COUNT) { 
    570                 srv->addr[srv->addr_cnt++].s_addr = rec.addr[0].s_addr; 
    571  
    572                 PJ_LOG(5,(query_job->objname,  
    573                           "DNS A for %.*s: %s", 
    574                           (int)srv->target_name.slen,  
    575                           srv->target_name.ptr, 
    576                           pj_inet_ntoa(rec.addr[0]))); 
    577             } 
    578  
    579             /* Check for multiple IP addresses */ 
    580             for (i=1; i<rec.addr_count && srv->addr_cnt < ADDR_MAX_COUNT; ++i) 
     693            for (i=0; i<rec.addr_count && srv->addr_cnt<ADDR_MAX_COUNT; ++i) 
    581694            { 
    582                 srv->addr[srv->addr_cnt++].s_addr = rec.addr[i].s_addr; 
    583  
    584                 PJ_LOG(5,(query_job->objname,  
    585                           "Additional DNS A for %.*s: %s", 
    586                           (int)srv->target_name.slen,  
    587                           srv->target_name.ptr, 
    588                           pj_inet_ntoa(rec.addr[i]))); 
     695                pj_bool_t added = PJ_FALSE; 
     696 
     697                if (is_type_a && rec.addr[i].af == pj_AF_INET()) { 
     698                    pj_sockaddr_init(pj_AF_INET(), &srv->addr[srv->addr_cnt], 
     699                                     NULL, srv->port); 
     700                    srv->addr[srv->addr_cnt].ipv4.sin_addr = 
     701                                     rec.addr[i].ip.v4; 
     702                    added = PJ_TRUE; 
     703                } else if (!is_type_a && rec.addr[i].af == pj_AF_INET6()) { 
     704                    pj_sockaddr_init(pj_AF_INET6(), &srv->addr[srv->addr_cnt], 
     705                                     NULL, srv->port); 
     706                    srv->addr[srv->addr_cnt].ipv6.sin6_addr = 
     707                                     rec.addr[i].ip.v6; 
     708                    added = PJ_TRUE; 
     709                } else { 
     710                    /* Mismatched address family, e.g: getting IPv6 address in 
     711                     * DNS A query resolution. 
     712                     */ 
     713                    PJ_LOG(4,(query_job->objname,  
     714                              "Bad address family in DNS %s query for %.*s", 
     715                              (is_type_a? "A" : "AAAA"), 
     716                              (int)srv->target_name.slen,  
     717                              srv->target_name.ptr)); 
     718                } 
     719 
     720                if (added) { 
     721                    PJ_LOG(5,(query_job->objname,  
     722                              "DNS %s for %.*s: %s", 
     723                              (is_type_a? "A" : "AAAA"), 
     724                              (int)srv->target_name.slen,  
     725                              srv->target_name.ptr, 
     726                              pj_sockaddr_print(&srv->addr[srv->addr_cnt], 
     727                                                addr, sizeof(addr), 2))); 
     728 
     729                    ++srv->addr_cnt; 
     730                } 
    589731            } 
    590732 
     
    597739            /* Log error */ 
    598740            pj_strerror(status, errmsg, sizeof(errmsg)); 
    599             PJ_LOG(4,(query_job->objname, "DNS A record resolution failed: %s",  
     741            PJ_LOG(4,(query_job->objname, 
     742                      "DNS %s record resolution failed: %s", 
     743                      (is_type_a? "A" : "AAAA"), 
    600744                      errmsg)); 
    601745        } 
    602746 
    603         ++query_job->host_resolved; 
     747        /* Increment host resolved count when both DNS A and AAAA record 
     748         * queries for this server are completed. 
     749         */ 
     750        if (srv_completed) 
     751            ++query_job->host_resolved; 
    604752 
    605753    } else { 
     
    618766            unsigned j; 
    619767            struct srv_target *srv2 = &query_job->srv[i]; 
     768            pj_dns_addr_record *s = &srv_rec.entry[srv_rec.count].server; 
    620769 
    621770            srv_rec.entry[srv_rec.count].priority = srv2->priority; 
     
    629778            pj_assert(srv2->addr_cnt <= PJ_DNS_MAX_IP_IN_A_REC); 
    630779 
    631             for (j=0; j<srv2->addr_cnt; ++j) { 
    632                 srv_rec.entry[srv_rec.count].server.addr[j].s_addr =  
    633                     srv2->addr[j].s_addr; 
    634                 ++srv_rec.entry[srv_rec.count].server.addr_count; 
     780            for (j=0; j<srv2->addr_cnt; ++j) {           
     781                s->addr[j].af = srv2->addr[j].addr.sa_family; 
     782                if (s->addr[j].af == pj_AF_INET()) 
     783                    s->addr[j].ip.v4 = srv2->addr[j].ipv4.sin_addr; 
     784                else 
     785                    s->addr[j].ip.v6 = srv2->addr[j].ipv6.sin6_addr; 
     786                ++s->addr_count; 
    635787            } 
    636788 
     
    675827                  status, 
    676828                  pj_strerror(status,errmsg,sizeof(errmsg)).ptr)); 
     829 
     830        /* Cancel any pending query */ 
     831        pj_dns_srv_cancel_query(query_job, PJ_FALSE); 
     832 
    677833        (*query_job->cb)(query_job->token, status, NULL); 
    678834        return; 
Note: See TracChangeset for help on using the changeset viewer.