Changeset 1357


Ignore:
Timestamp:
Jun 11, 2007 4:51:18 PM (12 years ago)
Author:
bennylp
Message:

Ticket #330: Changed DNS SRV resolver to use the new DNS A response parser

Location:
pjproject/trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib-util/include/pjlib-util/srv_resolver.h

    r1102 r1357  
    7676 
    7777/** 
    78  * Maximum server address entries per one SRV record 
    79  */ 
    80 #ifndef PJ_DNS_SRV_MAX_ADDR 
    81 #   define PJ_DNS_SRV_MAX_ADDR      8 
    82 #endif 
    83  
    84  
    85 /** 
    86  * The server addresses returned by the resolver. 
     78 * This structure represents DNS SRV records as the result of DNS SRV 
     79 * resolution using #pj_dns_srv_resolve(). 
    8780 */ 
    8881typedef struct pj_dns_srv_record 
     
    9386    /** Address records. */ 
    9487    struct 
    95     { 
     88v    { 
    9689        /** Server priority (the lower the higher the priority). */ 
    9790        unsigned                priority; 
     
    10093        unsigned                weight; 
    10194 
    102         /** The server's address. */ 
    103         pj_sockaddr             addr; 
     95        /** Port number. */ 
     96        pj_uint16_t             port; 
    10497 
    105         /** Address length. */ 
    106         int                     addr_len; 
     98        /** The host address. */ 
     99        pj_dns_a_record         server; 
    107100 
    108101    } entry[PJ_DNS_SRV_MAX_ADDR]; 
     
    139132 * @param cb            Pointer to callback function to receive the 
    140133 *                      notification when the resolution process completes. 
     134 * @param p_query       Optional pointer to receive the query object, if one 
     135 *                      was started. If this pointer is specified, a NULL may 
     136 *                      be returned if response cache is available immediately. 
    141137 * 
    142138 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     
    149145                                        pj_bool_t fallback_a, 
    150146                                        void *token, 
    151                                         pj_dns_srv_resolver_cb *cb); 
     147                                        pj_dns_srv_resolver_cb *cb, 
     148                                        pj_dns_async_query **p_query); 
    152149 
    153150 
  • pjproject/trunk/pjlib-util/src/pjlib-util/srv_resolver.c

    r1346 r1357  
    2929#define THIS_FILE   "srv_resolver.c" 
    3030 
    31 #define ADDR_MAX_COUNT      8 
     31#define ADDR_MAX_COUNT      PJ_DNS_MAX_IP_IN_A_REC 
    3232 
    3333struct srv_target 
     
    5353    void                    *token; 
    5454    pj_dns_srv_resolver_cb  *cb; 
    55     pj_dns_async_query      *qobject; 
    5655    pj_status_t              last_error; 
    5756 
     
    8988                                        pj_bool_t fallback_a, 
    9089                                        void *token, 
    91                                         pj_dns_srv_resolver_cb *cb) 
     90                                        pj_dns_srv_resolver_cb *cb, 
     91                                        pj_dns_async_query **p_query) 
    9292{ 
    9393    int len; 
     
    128128 
    129129    PJ_LOG(5, (query_job->objname,  
    130                "Starting async DNS %s query_job: target=%.*s", 
     130               "Starting async DNS %s query_job: target=%.*s:%d", 
    131131               pj_dns_get_type_name(query_job->dns_state), 
    132                (int)target_name.slen, target_name.ptr)); 
     132               (int)target_name.slen, target_name.ptr, 
     133               def_port)); 
    133134 
    134135    status = pj_dns_resolver_start_query(resolver, &target_name,  
    135136                                         query_job->dns_state, 0,  
    136137                                         &dns_callback, 
    137                                          query_job, &query_job->qobject); 
     138                                         query_job, p_query); 
    138139    return status; 
    139140} 
     
    466467        /* Check that we really have answer */ 
    467468        if (status==PJ_SUCCESS && pkt->hdr.anscount != 0) { 
    468             int ans_idx = -1; 
    469  
    470             /* Find the first DNS A record in the answer while processing 
    471              * the CNAME info found in the response. 
    472              */ 
    473             for (i=0; i < pkt->hdr.anscount; ++i) { 
    474  
    475                 pj_dns_parsed_rr *rr = &pkt->ans[i]; 
    476  
    477                 if (rr->type == PJ_DNS_TYPE_A) { 
    478  
    479                     if (ans_idx == -1) 
    480                         ans_idx = i; 
    481  
    482                 } else if (rr->type == PJ_DNS_TYPE_CNAME) { 
    483                     /* Find which server entry to be updated with 
    484                      * the CNAME information. 
    485                      */ 
    486                     unsigned j; 
    487                     pj_str_t cname = rr->rdata.cname.name; 
    488  
    489                     for (j=0; j<query_job->srv_cnt; ++j)  
    490                     { 
    491                         struct srv_target *srv = &query_job->srv[j]; 
    492                         if (pj_stricmp(&rr->name, &srv->target_name)==0) 
    493                         { 
    494                             /* Update CNAME info for this server entry */ 
    495                             srv->cname.ptr = srv->cname_buf; 
    496                             pj_strncpy(&srv->cname, &cname,  
    497                                        sizeof(srv->cname_buf)); 
    498                             break; 
    499                         } 
    500                     } 
    501                 } 
    502             } 
    503  
    504             if (ans_idx == -1) { 
    505                 /* There's no DNS A answer! */ 
    506                 PJ_LOG(5,(query_job->objname,  
    507                           "No DNS A record in response!")); 
    508                 status = PJLIB_UTIL_EDNSNOANSWERREC; 
     469            unsigned srv_idx; 
     470            struct srv_target *srv = NULL; 
     471            pj_dns_a_record rec; 
     472 
     473            /* Parse response */ 
     474            status = pj_dns_parse_a_response(pkt, &rec); 
     475            if (status != PJ_SUCCESS) 
    509476                goto on_error; 
    510             } 
    511  
    512             /* Update IP address of the corresponding hostname or CNAME */ 
    513             for (i=0; i<query_job->srv_cnt; ++i) { 
    514                 pj_dns_parsed_rr *rr = &pkt->ans[ans_idx]; 
    515                 struct srv_target *srv = &query_job->srv[i]; 
    516  
    517                 if (pj_stricmp(&rr->name, &srv->target_name)==0 || 
    518                     pj_stricmp(&rr->name, &srv->cname)==0)  
    519                 { 
     477 
     478            pj_assert(rec.addr_count != 0); 
     479 
     480            /* Find which server entry to be updated. */ 
     481            for (srv_idx=0; srv_idx<query_job->srv_cnt; ++srv_idx) { 
     482                srv = &query_job->srv[srv_idx]; 
     483                if (pj_stricmp(&rec.name, &srv->target_name)==0) { 
    520484                    break; 
    521485                } 
    522486            } 
    523487 
    524             if (i == query_job->srv_cnt) { 
    525                 PJ_LOG(4,(query_job->objname,  
    526                           "Received answer to DNS A request with no matching " 
    527                           "SRV record! The unknown name is %.*s", 
    528                           (int)pkt->ans[ans_idx].name.slen,  
    529                           pkt->ans[ans_idx].name.ptr)); 
     488            if (srv_idx==query_job->srv_cnt) { 
     489                /* The DNS A response doesn't match any server names 
     490                 * we're querying! 
     491                 */ 
     492                status = PJLIB_UTIL_EDNSINANSWER; 
     493                goto on_error; 
     494            } 
     495 
     496            srv = &query_job->srv[srv_idx]; 
     497 
     498            /* Update CNAME alias, if present. */ 
     499            if (rec.alias.slen) { 
     500                pj_assert(rec.alias.slen <= sizeof(srv->cname_buf)); 
     501                srv->cname.ptr = srv->cname_buf; 
     502                pj_strcpy(&srv->cname, &rec.alias); 
    530503            } else { 
    531                 unsigned j; 
    532  
    533                 query_job->srv[i].addr[query_job->srv[i].addr_cnt++].s_addr = 
    534                     pkt->ans[ans_idx].rdata.a.ip_addr.s_addr; 
     504                srv->cname.slen = 0; 
     505            } 
     506 
     507            /* Update IP address of the corresponding hostname or CNAME */ 
     508            if (srv->addr_cnt < ADDR_MAX_COUNT) { 
     509                srv->addr[srv->addr_cnt++].s_addr = rec.addr[0].s_addr; 
    535510 
    536511                PJ_LOG(5,(query_job->objname,  
    537512                          "DNS A for %.*s: %s", 
    538                           (int)query_job->srv[i].target_name.slen,  
    539                           query_job->srv[i].target_name.ptr, 
    540                           pj_inet_ntoa(pkt->ans[ans_idx].rdata.a.ip_addr))); 
    541  
    542                 /* Check for multiple IP addresses */ 
    543                 for (j=ans_idx+1; j<pkt->hdr.anscount &&  
    544                             query_job->srv[i].addr_cnt < ADDR_MAX_COUNT; ++j) 
    545                 { 
    546                     query_job->srv[i].addr[query_job->srv[i].addr_cnt++].s_addr =  
    547                         pkt->ans[j].rdata.a.ip_addr.s_addr; 
    548  
    549                     PJ_LOG(5,(query_job->objname,  
    550                               "Additional DNS A for %.*s: %s", 
    551                               (int)query_job->srv[i].target_name.slen,  
    552                               query_job->srv[i].target_name.ptr, 
    553                               pj_inet_ntoa(pkt->ans[j].rdata.a.ip_addr))); 
    554                 } 
     513                          (int)srv->target_name.slen,  
     514                          srv->target_name.ptr, 
     515                          pj_inet_ntoa(rec.addr[0]))); 
     516            } 
     517 
     518            /* Check for multiple IP addresses */ 
     519            for (i=1; i<rec.addr_count && srv->addr_cnt < ADDR_MAX_COUNT; ++i) 
     520            { 
     521                srv->addr[srv->addr_cnt++].s_addr = rec.addr[i].s_addr; 
     522 
     523                PJ_LOG(5,(query_job->objname,  
     524                          "Additional DNS A for %.*s: %s", 
     525                          (int)srv->target_name.slen,  
     526                          srv->target_name.ptr, 
     527                          pj_inet_ntoa(rec.addr[i]))); 
    555528            } 
    556529 
     
    578551    if (query_job->host_resolved == query_job->srv_cnt) { 
    579552        /* Got all answers, build server addresses */ 
    580         pj_dns_srv_record svr_addr; 
    581  
    582         svr_addr.count = 0; 
     553        pj_dns_srv_record srv_rec; 
     554 
     555        srv_rec.count = 0; 
    583556        for (i=0; i<query_job->srv_cnt; ++i) { 
    584557            unsigned j; 
    585  
    586             /* Do we have IP address for this server? */ 
    587             /* This log is redundant really. 
    588             if (query_job->srv[i].addr_cnt == 0) { 
    589                 PJ_LOG(5,(query_job->objname,  
    590                           " SRV target %.*s:%d does not have IP address!", 
    591                           (int)query_job->srv[i].target_name.slen, 
    592                           query_job->srv[i].target_name.ptr, 
    593                           query_job->srv[i].port)); 
    594                 continue; 
    595             } 
    596             */ 
    597  
    598             for (j=0; j<query_job->srv[i].addr_cnt; ++j) { 
    599                 unsigned idx = svr_addr.count; 
    600                 pj_sockaddr_in *addr; 
    601  
    602                 svr_addr.entry[idx].priority = query_job->srv[i].priority; 
    603                 svr_addr.entry[idx].weight = query_job->srv[i].weight; 
    604                 svr_addr.entry[idx].addr_len = sizeof(pj_sockaddr_in); 
    605               
    606                 addr = (pj_sockaddr_in*)&svr_addr.entry[idx].addr; 
    607                 pj_bzero(addr, sizeof(pj_sockaddr_in)); 
    608                 addr->sin_family = PJ_AF_INET; 
    609                 addr->sin_addr = query_job->srv[i].addr[j]; 
    610                 addr->sin_port = pj_htons((pj_uint16_t)query_job->srv[i].port); 
    611  
    612                 ++svr_addr.count; 
     558            struct srv_target *srv = &query_job->srv[i]; 
     559 
     560            srv_rec.entry[srv_rec.count].priority = srv->priority; 
     561            srv_rec.entry[srv_rec.count].weight = srv->weight; 
     562            srv_rec.entry[srv_rec.count].port = (pj_uint16_t)srv->port ; 
     563 
     564            srv_rec.entry[srv_rec.count].server.name = srv->target_name; 
     565            srv_rec.entry[srv_rec.count].server.alias = srv->cname; 
     566            srv_rec.entry[srv_rec.count].server.addr_count = 0; 
     567 
     568            pj_assert(srv->addr_cnt <= PJ_DNS_MAX_IP_IN_A_REC); 
     569 
     570            for (j=0; j<srv->addr_cnt; ++j) { 
     571                srv_rec.entry[srv_rec.count].server.addr[j].s_addr =  
     572                    srv->addr[j].s_addr; 
     573                ++srv_rec.entry[srv_rec.count].server.addr_count; 
     574            } 
     575 
     576            if (srv->addr_cnt > 0) { 
     577                ++srv_rec.count; 
     578                if (srv_rec.count == PJ_DNS_SRV_MAX_ADDR) 
     579                    break; 
    613580            } 
    614581        } 
     
    616583        PJ_LOG(5,(query_job->objname,  
    617584                  "Server resolution complete, %d server entry(s) found", 
    618                   svr_addr.count)); 
    619  
    620  
    621         if (svr_addr.count > 0) 
     585                  srv_rec.count)); 
     586 
     587 
     588        if (srv_rec.count > 0) 
    622589            status = PJ_SUCCESS; 
    623590        else { 
     
    628595 
    629596        /* Call the callback */ 
    630         (*query_job->cb)(query_job->token, status, &svr_addr); 
     597        (*query_job->cb)(query_job->token, status, &srv_rec); 
    631598    } 
    632599 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c

    r1317 r1357  
    743743    } 
    744744 
    745     pj_memcpy(&pjsua_var.stun_srv, &rec->entry[0].addr,  
    746               rec->entry[0].addr_len); 
     745    pj_assert(rec->count != 0 && rec->entry[0].server.addr_count != 0); 
     746    pj_sockaddr_in_init(&pjsua_var.stun_srv.ipv4, NULL, 
     747                        rec->entry[0].port); 
     748    pjsua_var.stun_srv.ipv4.sin_addr.s_addr =  
     749        rec->entry[0].server.addr[0].s_addr; 
    747750 
    748751    PJ_LOG(3,(THIS_FILE, "_stun._udp.%.*s resolved, found %d entry(s):", 
     
    755758                  " %d: prio=%d, weight=%d  %s:%d",  
    756759                  i, rec->entry[i].priority, rec->entry[i].weight, 
    757                   pj_inet_ntoa(rec->entry[i].addr.ipv4.sin_addr), 
    758                   (int)pj_ntohs(rec->entry[i].addr.ipv4.sin_port))); 
     760                  pj_inet_ntoa(rec->entry[i].server.addr[0]), 
     761                  (int)rec->entry[i].port)); 
    759762    } 
    760763 
     
    794797                pj_dns_srv_resolve(&pjsua_var.ua_cfg.stun_domain, &res_type, 
    795798                                   3478, pjsua_var.pool, pjsua_var.resolver, 
    796                                    0, NULL, &stun_dns_srv_resolver_cb); 
     799                                   0, NULL, &stun_dns_srv_resolver_cb, NULL); 
    797800            if (status != PJ_SUCCESS) { 
    798801                pjsua_perror(THIS_FILE, "Error starting DNS SRV resolution",  
Note: See TracChangeset for help on using the changeset viewer.