- Timestamp:
- Dec 28, 2016 3:40:07 AM (8 years ago)
- Location:
- pjproject/branches/projects/uwp
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/branches/projects/uwp
- Property svn:mergeinfo changed
/pjproject/trunk (added) merged: 5209,5212-5234,5237-5253,5255,5257-5292,5294-5297,5299-5332,5334-5394,5396-5438,5440-5469,5471-5496,5498-5510
- Property svn:mergeinfo changed
-
pjproject/branches/projects/uwp/pjlib-util/src/pjlib-util/srv_resolver.c
r5170 r5513 38 38 }; 39 39 40 #pragma pack(1) 40 41 struct srv_target 41 42 { 42 43 struct common common; 44 struct common common_aaaa; 43 45 pj_dns_srv_async_query *parent; 44 46 pj_str_t target_name; 45 47 pj_dns_async_query *q_a; 48 pj_dns_async_query *q_aaaa; 46 49 char target_buf[PJ_MAX_HOSTNAME]; 47 50 pj_str_t cname; 48 51 char cname_buf[PJ_MAX_HOSTNAME]; 49 unsignedport;52 pj_uint16_t port; 50 53 unsigned priority; 51 54 unsigned weight; 52 55 unsigned sum; 53 56 unsigned addr_cnt; 54 pj_ in_addr addr[ADDR_MAX_COUNT];57 pj_sockaddr addr[ADDR_MAX_COUNT];/**< Address family and IP.*/ 55 58 }; 59 #pragma pack() 56 60 57 61 struct pj_dns_srv_async_query … … 136 140 query_job->def_port = (pj_uint16_t)def_port; 137 141 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 138 146 /* Start the asynchronous query_job */ 139 147 … … 178 186 srv->q_a = NULL; 179 187 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; 180 196 } 181 197 } … … 315 331 } 316 332 317 /* Check for Additional Info section if A records are available, and318 * 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 319 335 * record with another DNS query_job). 320 336 */ … … 323 339 unsigned j; 324 340 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) 326 343 continue; 327 344 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! 329 358 * Update the IP address of the corresponding SRV record. 330 359 */ 331 360 for (j=0; j<query_job->srv_cnt; ++j) { 332 if (pj_stricmp(&rr->name, &query_job->srv[j].target_name)==0 && 333 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 { 335 364 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 337 379 /* Only increment host_resolved once per SRV record */ 338 380 if (query_job->srv[j].addr_cnt == 0) 339 381 ++query_job->host_resolved; 382 340 383 ++query_job->srv[j].addr_cnt; 341 384 break; … … 355 398 } 356 399 */ 400 357 401 } 358 402 … … 363 407 for (i=0; i<query_job->srv_cnt; ++i) { 364 408 pj_in_addr addr; 409 pj_in6_addr addr6; 365 410 366 411 if (query_job->srv[i].addr_cnt != 0) { … … 369 414 } 370 415 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; 373 435 ++query_job->host_resolved; 374 436 } … … 386 448 387 449 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, "-"); 394 457 395 458 PJ_LOG(5,(query_job->objname, … … 405 468 406 469 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 */ 408 473 static pj_status_t resolve_hostnames(pj_dns_srv_async_query *query_job) 409 474 { … … 412 477 413 478 query_job->dns_state = PJ_DNS_TYPE_A; 479 414 480 for (i=0; i<query_job->srv_cnt; ++i) { 415 481 struct srv_target *srv = &query_job->srv[i]; … … 421 487 422 488 srv->common.type = PJ_DNS_TYPE_A; 489 srv->common_aaaa.type = PJ_DNS_TYPE_AAAA; 423 490 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 } 424 524 425 525 /* See also #1809: dns_callback() will be invoked synchronously when response … … 428 528 * returning false error, so don't use that variable for counting errors. 429 529 */ 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);435 530 if (status != PJ_SUCCESS) { 436 531 query_job->host_resolved++; … … 462 557 srv = (struct srv_target*) common; 463 558 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; 464 562 } else { 465 563 pj_assert(!"Unexpected user data!"); … … 472 570 /* We are getting SRV response */ 473 571 572 /* Clear the outstanding job */ 474 573 query_job->q_srv = NULL; 475 574 … … 505 604 */ 506 605 if (query_job->srv_cnt == 0) { 606 unsigned new_option = 0; 607 507 608 /* Looks like we aren't getting any SRV responses. 508 609 * Resolve the original target as A record by creating a … … 511 612 PJ_LOG(4, (query_job->objname, 512 613 "DNS SRV resolution failed for %.*s, trying " 513 "resolving A record for %.*s",614 "resolving A/AAAA record for %.*s", 514 615 (int)query_job->full_name.slen, 515 616 query_job->full_name.ptr, … … 524 625 query_job->srv[i].weight = 0; 525 626 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 } 527 637 528 638 529 /* Resolve server hostnames (DNS A record) for hosts which don't have530 * A record yet.639 /* Resolve server hostnames (DNS A/AAAA record) for hosts which 640 * don't have A/AAAA record yet. 531 641 */ 532 642 if (query_job->host_resolved != query_job->srv_cnt) { … … 542 652 543 653 } 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); 547 670 548 671 /* Check that we really have answer */ 549 672 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; 551 675 552 676 /* Parse response */ 553 status = pj_dns_parse_a _response(pkt, &rec);677 status = pj_dns_parse_addr_response(pkt, &rec); 554 678 if (status != PJ_SUCCESS) 555 679 goto on_error; … … 558 682 559 683 /* Update CNAME alias, if present. */ 560 if ( rec.alias.slen) {684 if (srv->cname.slen==0 && rec.alias.slen) { 561 685 pj_assert(rec.alias.slen <= (int)sizeof(srv->cname_buf)); 562 686 srv->cname.ptr = srv->cname_buf; 563 687 pj_strcpy(&srv->cname, &rec.alias); 564 } else {565 srv->cname.slen = 0;688 //} else { 689 //srv->cname.slen = 0; 566 690 } 567 691 568 692 /* 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) 581 694 { 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 } 589 731 } 590 732 … … 597 739 /* Log error */ 598 740 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"), 600 744 errmsg)); 601 745 } 602 746 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; 604 752 605 753 } else { … … 618 766 unsigned j; 619 767 struct srv_target *srv2 = &query_job->srv[i]; 768 pj_dns_addr_record *s = &srv_rec.entry[srv_rec.count].server; 620 769 621 770 srv_rec.entry[srv_rec.count].priority = srv2->priority; … … 629 778 pj_assert(srv2->addr_cnt <= PJ_DNS_MAX_IP_IN_A_REC); 630 779 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; 635 787 } 636 788 … … 675 827 status, 676 828 pj_strerror(status,errmsg,sizeof(errmsg)).ptr)); 829 830 /* Cancel any pending query */ 831 pj_dns_srv_cancel_query(query_job, PJ_FALSE); 832 677 833 (*query_job->cb)(query_job->token, status, NULL); 678 834 return;
Note: See TracChangeset
for help on using the changeset viewer.