Changeset 1358 for pjproject/trunk
- Timestamp:
- Jun 11, 2007 4:54:10 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip/src/pjsip/sip_resolve.c
r1326 r1358 21 21 #include <pjsip/sip_errno.h> 22 22 #include <pjlib-util/errno.h> 23 #include <pjlib-util/srv_resolver.h> 23 24 #include <pj/array.h> 24 25 #include <pj/assert.h> … … 36 37 struct naptr_target 37 38 { 38 pj_str_t target_name; /**< NAPTR target name. */ 39 pj_str_t res_type; /**< e.g. "_sip._udp" */ 40 pj_str_t name; /**< Domain name. */ 39 41 pjsip_transport_type_e type; /**< Transport type. */ 40 42 unsigned order; /**< Order */ … … 42 44 }; 43 45 44 struct srv_target45 {46 pjsip_transport_type_e type;47 pj_str_t target_name;48 char target_buf[PJ_MAX_HOSTNAME];49 unsigned port;50 unsigned priority;51 unsigned weight;52 unsigned sum;53 unsigned addr_cnt;54 pj_in_addr addr[ADDR_MAX_COUNT];55 };56 57 46 struct query 58 47 { 59 char objname[PJ_MAX_OBJ_NAME]; 60 61 pjsip_resolver_t *resolver; /**< Resolver SIP instance. */ 62 pj_dns_type dns_state; /**< DNS type being resolved. */ 48 char *objname; 49 50 pj_dns_type query_type; 63 51 void *token; 64 52 pjsip_resolver_callback *cb; … … 69 57 struct { 70 58 pjsip_host_info target; 59 unsigned def_port; 71 60 } req; 72 61 … … 74 63 unsigned naptr_cnt; 75 64 struct naptr_target naptr[8]; 76 77 /* SRV records and their resolved IP addresses: */78 unsigned srv_cnt;79 struct srv_target srv[PJSIP_MAX_RESOLVED_ADDRESSES];80 81 /* Number of hosts in SRV records that the IP address has been resolved */82 unsigned host_resolved;83 65 }; 84 66 … … 87 69 { 88 70 pj_dns_resolver *res; 89 unsigned job_id;90 71 }; 91 72 92 static void dns_callback(void *user_data, 93 pj_status_t status, 94 pj_dns_parsed_packet *response); 73 74 static void srv_resolver_cb(void *user_data, 75 pj_status_t status, 76 const pj_dns_srv_record *rec); 77 static void dns_a_callback(void *user_data, 78 pj_status_t status, 79 pj_dns_parsed_packet *response); 95 80 96 81 … … 184 169 int is_ip_addr; 185 170 struct query *query; 186 pj_str_t srv_name;187 171 pjsip_transport_type_e type = target->type; 188 172 … … 280 264 /* Build the query state */ 281 265 query = PJ_POOL_ZALLOC_T(pool, struct query); 282 pj_ansi_snprintf(query->objname, sizeof(query->objname), "rsvjob%X", 283 resolver->job_id++); 284 query->resolver = resolver; 266 query->objname = THIS_FILE; 285 267 query->token = token; 286 268 query->cb = cb; … … 299 281 query->naptr[0].pref = 0; 300 282 query->naptr[0].type = type; 301 query->naptr[0].target_name.ptr = (char*) 302 pj_pool_alloc(pool, target->addr.host.slen + 12); 303 304 if (type == PJSIP_TRANSPORT_TLS) 305 pj_strcpy2(&query->naptr[0].target_name, "_sips._tcp."); 306 else if (type == PJSIP_TRANSPORT_TCP) 307 pj_strcpy2(&query->naptr[0].target_name, "_sip._tcp."); 308 else if (type == PJSIP_TRANSPORT_UDP) 309 pj_strcpy2(&query->naptr[0].target_name, "_sip._udp."); 310 else { 311 pj_assert(!"Unknown transport type"); 312 pj_strcpy2(&query->naptr[0].target_name, "_sip._udp."); 313 } 314 pj_strcat(&query->naptr[0].target_name, &target->addr.host); 283 pj_strdup(pool, &query->naptr[0].name, &target->addr.host); 315 284 316 285 317 286 /* Start DNS SRV or A resolution, depending on whether port is specified */ 318 287 if (target->addr.port == 0) { 319 query->dns_state = PJ_DNS_TYPE_SRV; 320 srv_name = query->naptr[0].target_name; 288 query->query_type = PJ_DNS_TYPE_SRV; 289 290 query->req.def_port = 5060; 291 292 if (type == PJSIP_TRANSPORT_TLS) { 293 query->naptr[0].res_type = pj_str("_sips._tcp."); 294 query->req.def_port = 5061; 295 } else if (type == PJSIP_TRANSPORT_TCP) 296 query->naptr[0].res_type = pj_str("_sip._tcp."); 297 else if (type == PJSIP_TRANSPORT_UDP) 298 query->naptr[0].res_type = pj_str("_sip._udp."); 299 else { 300 pj_assert(!"Unknown transport type"); 301 query->naptr[0].res_type = pj_str("_sip._udp."); 302 303 } 321 304 322 305 } else { … … 324 307 * resolution 325 308 */ 326 query->dns_state = PJ_DNS_TYPE_A; 327 328 /* Since we don't perform SRV resolution, pretend that we'ee already 329 * done so by inserting a dummy SRV record. 330 */ 331 332 query->srv_cnt = 1; 333 pj_bzero(&query->srv[0], sizeof(query->srv[0])); 334 query->srv[0].target_name = query->req.target.addr.host; 335 query->srv[0].type = type; 336 query->srv[0].port = query->req.target.addr.port; 337 query->srv[0].priority = 0; 338 query->srv[0].weight = 0; 339 340 srv_name = query->srv[0].target_name; 309 query->query_type = PJ_DNS_TYPE_A; 310 query->naptr[0].res_type.slen = 0; 311 query->req.def_port = target->addr.port; 341 312 } 342 313 343 314 /* Start the asynchronous query */ 344 315 PJ_LOG(5, (query->objname, 345 "Starting async DNS %s query: target=%.*s , transport=%s, "316 "Starting async DNS %s query: target=%.*s%.*s, transport=%s, " 346 317 "port=%d", 347 pj_dns_get_type_name(query->dns_state), 348 (int)srv_name.slen, srv_name.ptr, 318 pj_dns_get_type_name(query->query_type), 319 (int)query->naptr[0].res_type.slen, 320 query->naptr[0].res_type.ptr, 321 (int)query->naptr[0].name.slen, query->naptr[0].name.ptr, 349 322 pjsip_transport_get_type_name(target->type), 350 323 target->addr.port)); 351 324 352 status = pj_dns_resolver_start_query(resolver->res, &srv_name, 353 query->dns_state, 0, &dns_callback, 354 query, &query->object); 325 if (query->query_type == PJ_DNS_TYPE_SRV) { 326 327 status = pj_dns_srv_resolve(&query->naptr[0].name, 328 &query->naptr[0].res_type, 329 query->req.def_port, pool, resolver->res, 330 PJ_TRUE, query, &srv_resolver_cb, NULL); 331 332 } else if (query->query_type == PJ_DNS_TYPE_A) { 333 334 status = pj_dns_resolver_start_query(resolver->res, 335 &query->naptr[0].name, 336 PJ_DNS_TYPE_A, 0, 337 &dns_a_callback, 338 query, &query->object); 339 340 } else { 341 pj_assert(!"Unexpected"); 342 status = PJ_EBUG; 343 } 344 355 345 if (status != PJ_SUCCESS) 356 346 goto on_error; … … 377 367 } 378 368 379 /*380 * The rest of the code should only get compiled when resolver is enabled381 */382 369 #if PJSIP_HAS_RESOLVER 383 370 384 #define SWAP(type,ptr1,ptr2) if (ptr1 != ptr2) { \ 385 type tmp; \ 386 pj_memcpy(&tmp, ptr1, sizeof(type)); \ 387 pj_memcpy(ptr1, ptr2, sizeof(type)); \ 388 (ptr1)->target_name.ptr = (ptr1)->target_buf; \ 389 pj_memcpy(ptr2, &tmp, sizeof(type)); \ 390 (ptr2)->target_name.ptr = (ptr2)->target_buf; \ 391 } else {} 392 393 /* Build server entries in the query based on received SRV response */ 394 static void build_server_entries(struct query *query, 395 pj_dns_parsed_packet *response) 396 { 371 /* 372 * This callback is called when target is resolved with DNS A query. 373 */ 374 static void dns_a_callback(void *user_data, 375 pj_status_t status, 376 pj_dns_parsed_packet *pkt) 377 { 378 struct query *query = (struct query*) user_data; 379 pjsip_server_addresses srv; 380 pj_dns_a_record rec; 397 381 unsigned i; 398 unsigned naptr_id; 399 400 /* Find NAPTR target which corresponds to this SRV target */ 401 for (naptr_id=0; naptr_id < query->naptr_cnt; ++naptr_id) { 402 if (pj_stricmp(&query->naptr[naptr_id].target_name, 403 &response->ans[0].name)==0) 404 break; 405 } 406 if (naptr_id == query->naptr_cnt) { 407 PJ_LOG(4,(query->objname, 408 "Unable to find NAPTR record for SRV name %.*s!", 409 (int)response->ans[0].name.slen, 410 response->ans[0].name.ptr)); 411 return; 412 } 413 414 415 /* Save the Resource Records in DNS answer into SRV targets. */ 416 query->srv_cnt = 0; 417 for (i=0; i<response->hdr.anscount && 418 query->srv_cnt < PJSIP_MAX_RESOLVED_ADDRESSES; ++i) 419 { 420 pj_dns_parsed_rr *rr = &response->ans[i]; 421 struct srv_target *srv = &query->srv[query->srv_cnt]; 422 423 if (rr->type != PJ_DNS_TYPE_SRV) { 424 PJ_LOG(4,(query->objname, 425 "Received non SRV answer for SRV query!")); 426 continue; 427 } 428 429 if (rr->rdata.srv.target.slen > PJ_MAX_HOSTNAME) { 430 PJ_LOG(4,(query->objname, "Hostname is too long!")); 431 continue; 432 } 433 434 /* Build the SRV entry for RR */ 435 pj_bzero(srv, sizeof(*srv)); 436 pj_memcpy(srv->target_buf, rr->rdata.srv.target.ptr, 437 rr->rdata.srv.target.slen); 438 srv->target_name.ptr = srv->target_buf; 439 srv->target_name.slen = rr->rdata.srv.target.slen; 440 srv->type = query->naptr[naptr_id].type; 441 srv->port = rr->rdata.srv.port; 442 srv->priority = rr->rdata.srv.prio; 443 srv->weight = rr->rdata.srv.weight; 444 445 ++query->srv_cnt; 446 } 447 448 /* First pass: 449 * order the entries based on priority. 450 */ 451 for (i=0; i<query->srv_cnt-1; ++i) { 452 unsigned min = i, j; 453 for (j=i+1; j<query->srv_cnt; ++j) { 454 if (query->srv[j].priority < query->srv[min].priority) 455 min = j; 456 } 457 SWAP(struct srv_target, &query->srv[i], &query->srv[min]); 458 } 459 460 /* Second pass: 461 * pick one host among hosts with the same priority, according 462 * to its weight. The idea is when one server fails, client should 463 * contact the next server with higher priority rather than contacting 464 * server with the same priority as the failed one. 465 * 466 * The algorithm for selecting server among servers with the same 467 * priority is described in RFC 2782. 468 */ 469 for (i=0; i<query->srv_cnt; ++i) { 470 unsigned j, count=1, sum; 471 472 /* Calculate running sum for servers with the same priority */ 473 sum = query->srv[i].sum = query->srv[i].weight; 474 for (j=i+1; j<query->srv_cnt && 475 query->srv[j].priority == query->srv[i].priority; ++j) 476 { 477 sum += query->srv[j].weight; 478 query->srv[j].sum = sum; 479 ++count; 480 } 481 482 if (count > 1) { 483 unsigned r; 484 485 /* Elect one random number between zero and the total sum of 486 * weight (inclusive). 487 */ 488 r = pj_rand() % (sum + 1); 489 490 /* Select the first server which running sum is greater than or 491 * equal to the random number. 492 */ 493 for (j=i; j<i+count; ++j) { 494 if (query->srv[j].sum >= r) 495 break; 496 } 497 498 /* Must have selected one! */ 499 pj_assert(j != i+count); 500 501 /* Put this entry in front (of entries with same priority) */ 502 SWAP(struct srv_target, &query->srv[i], &query->srv[j]); 503 504 /* Remove all other entries (of the same priority) */ 505 while (count > 1) { 506 pj_array_erase(query->srv, sizeof(struct srv_target), 507 query->srv_cnt, i+1); 508 --count; 509 --query->srv_cnt; 510 } 511 } 512 } 513 514 /* Since we've been moving around SRV entries, update the pointers 515 * in target_name. 516 */ 517 for (i=0; i<query->srv_cnt; ++i) { 518 query->srv[i].target_name.ptr = query->srv[i].target_buf; 519 } 520 521 /* Check for Additional Info section if A records are available, and 522 * fill in the IP address (so that we won't need to resolve the A 523 * record with another DNS query). 524 */ 525 for (i=0; i<response->hdr.arcount; ++i) { 526 pj_dns_parsed_rr *rr = &response->arr[i]; 527 unsigned j; 528 529 if (rr->type != PJ_DNS_TYPE_A) 530 continue; 531 532 /* Yippeaiyee!! There is an "A" record! 533 * Update the IP address of the corresponding SRV record. 534 */ 535 for (j=0; j<query->srv_cnt; ++j) { 536 if (pj_stricmp(&rr->name, &query->srv[j].target_name)==0) { 537 unsigned cnt = query->srv[j].addr_cnt; 538 query->srv[j].addr[cnt].s_addr = rr->rdata.a.ip_addr.s_addr; 539 ++query->srv[j].addr_cnt; 540 ++query->host_resolved; 541 break; 542 } 543 } 544 545 /* Not valid message; SRV entry might have been deleted in 546 * server selection process. 547 */ 548 /* 549 if (j == query->srv_cnt) { 550 PJ_LOG(4,(query->objname, 551 "Received DNS SRV answer with A record, but " 552 "couldn't find matching name (name=%.*s)", 553 (int)rr->name.slen, 554 rr->name.ptr)); 555 } 556 */ 557 } 558 559 /* Rescan again the name specified in the SRV record to see if IP 560 * address is specified as the target name (unlikely, but well, who 561 * knows..). 562 */ 563 for (i=0; i<query->srv_cnt; ++i) { 564 pj_in_addr addr; 565 566 if (query->srv[i].addr_cnt != 0) { 567 /* IP address already resolved */ 568 continue; 569 } 570 571 if (pj_inet_aton(&query->srv[i].target_name, &addr) != 0) { 572 query->srv[i].addr[query->srv[i].addr_cnt++] = addr; 573 ++query->host_resolved; 574 } 575 } 576 577 /* Print resolved entries to the log */ 578 PJ_LOG(5,(query->objname, 579 "SRV query for %.*s completed, " 580 "%d of %d total entries selected%c", 581 (int)query->naptr[naptr_id].target_name.slen, 582 query->naptr[naptr_id].target_name.ptr, 583 query->srv_cnt, 584 response->hdr.anscount, 585 (query->srv_cnt ? ':' : ' '))); 586 587 for (i=0; i<query->srv_cnt; ++i) { 588 const char *addr; 589 590 if (query->srv[i].addr_cnt != 0) 591 addr = pj_inet_ntoa(query->srv[i].addr[0]); 592 else 593 addr = "-"; 594 595 PJ_LOG(5,(query->objname, 596 " %d: SRV %d %d %d %.*s (%s)", 597 i, query->srv[i].priority, 598 query->srv[i].weight, 599 query->srv[i].port, 600 (int)query->srv[i].target_name.slen, 601 query->srv[i].target_name.ptr, 602 addr)); 603 } 604 } 605 606 607 /* Start DNS A record queries for all SRV records in the query structure */ 608 static pj_status_t resolve_hostnames(struct query *query) 609 { 610 unsigned i; 611 pj_status_t err=PJ_SUCCESS, status; 612 613 query->dns_state = PJ_DNS_TYPE_A; 614 for (i=0; i<query->srv_cnt; ++i) { 615 PJ_LOG(5, (query->objname, 616 "Starting async DNS A query for %.*s", 617 (int)query->srv[i].target_name.slen, 618 query->srv[i].target_name.ptr)); 619 620 status = pj_dns_resolver_start_query(query->resolver->res, 621 &query->srv[i].target_name, 622 PJ_DNS_TYPE_A, 0, 623 &dns_callback, 624 query, NULL); 625 if (status != PJ_SUCCESS) { 626 query->host_resolved++; 627 err = status; 628 } 629 } 630 631 return (query->host_resolved == query->srv_cnt) ? err : PJ_SUCCESS; 632 } 633 634 /* 635 * This callback is called by PJLIB-UTIL DNS resolver when asynchronous 636 * query has completed (successfully or with error). 637 */ 638 static void dns_callback(void *user_data, 639 pj_status_t status, 640 pj_dns_parsed_packet *pkt) 641 { 642 struct query *query = (struct query*) user_data; 643 unsigned i; 644 645 /* Proceed to next stage */ 646 647 if (query->dns_state == PJ_DNS_TYPE_SRV) { 648 649 /* We are getting SRV response */ 650 651 if (status == PJ_SUCCESS && pkt->hdr.anscount != 0) { 652 /* Got SRV response, build server entry. If A records are available 653 * in additional records section of the DNS response, save them too. 654 */ 655 build_server_entries(query, pkt); 656 657 } else if (status != PJ_SUCCESS) { 658 char errmsg[PJ_ERR_MSG_SIZE]; 659 unsigned naptr_id; 660 661 /* Update query last error */ 662 query->last_error = status; 663 664 /* Find which NAPTR target has not got SRV records */ 665 for (naptr_id=0; naptr_id < query->naptr_cnt; ++naptr_id) { 666 for (i=0; i<query->srv_cnt; ++i) { 667 if (query->srv[i].type == query->naptr[naptr_id].type) 668 break; 669 } 670 if (i == query->srv_cnt) 671 break; 672 } 673 if (naptr_id == query->naptr_cnt) { 674 /* Strangely all NAPTR records seem to already have SRV 675 * records! This is quite unexpected, by anyway lets set 676 * the naptr_id to zero just in case. 677 */ 678 pj_assert(!"Strange"); 679 naptr_id = 0; 680 681 } 682 683 pj_strerror(status, errmsg, sizeof(errmsg)); 684 PJ_LOG(4,(query->objname, 685 "DNS SRV resolution failed for %.*s: %s", 686 (int)query->naptr[naptr_id].target_name.slen, 687 query->naptr[naptr_id].target_name.ptr, 688 errmsg)); 689 } 690 691 /* If we can't build SRV record, assume the original target is 692 * an A record. 693 */ 694 if (query->srv_cnt == 0) { 695 /* Looks like we aren't getting any SRV responses. 696 * Resolve the original target as A record by creating a 697 * single "dummy" srv record and start the hostname resolution. 698 */ 699 unsigned naptr_id; 700 701 /* Find which NAPTR target has not got SRV records */ 702 for (naptr_id=0; naptr_id < query->naptr_cnt; ++naptr_id) { 703 for (i=0; i<query->srv_cnt; ++i) { 704 if (query->srv[i].type == query->naptr[naptr_id].type) 705 break; 706 } 707 if (i == query->srv_cnt) 708 break; 709 } 710 if (naptr_id == query->naptr_cnt) { 711 /* Strangely all NAPTR records seem to already have SRV 712 * records! This is quite unexpected, by anyway lets set 713 * the naptr_id to zero just in case. 714 */ 715 pj_assert(!"Strange"); 716 naptr_id = 0; 717 718 } 719 720 PJ_LOG(4, (query->objname, 721 "DNS SRV resolution failed for %.*s, trying " 722 "resolving A record for %.*s", 723 (int)query->naptr[naptr_id].target_name.slen, 724 query->naptr[naptr_id].target_name.ptr, 725 (int)query->req.target.addr.host.slen, 726 query->req.target.addr.host.ptr)); 727 728 /* Create a "dummy" srv record using the original target */ 729 i = query->srv_cnt++; 730 pj_bzero(&query->srv[i], sizeof(query->srv[i])); 731 query->srv[i].target_name = query->req.target.addr.host; 732 query->srv[i].type = query->naptr[naptr_id].type; 733 query->srv[i].priority = 0; 734 query->srv[i].weight = 0; 735 736 query->srv[i].port = query->req.target.addr.port; 737 if (query->srv[i].port == 0) { 738 query->srv[i].port = (pj_uint16_t) 739 pjsip_transport_get_default_port_for_type(query->srv[i].type); 740 } 741 } 742 743 744 /* Resolve server hostnames (DNS A record) for hosts which don't have 745 * A record yet. 746 */ 747 if (query->host_resolved != query->srv_cnt) { 748 status = resolve_hostnames(query); 749 if (status != PJ_SUCCESS) 750 goto on_error; 751 752 /* Must return now. Callback may have been called and query 753 * may have been destroyed. 754 */ 755 return; 756 } 757 758 } else if (query->dns_state == PJ_DNS_TYPE_A) { 759 760 /* Check that we really have answer */ 761 if (status==PJ_SUCCESS && pkt->hdr.anscount != 0) { 762 763 unsigned srv_idx; 764 765 /* Update IP address of the corresponding hostname */ 766 for (srv_idx=0; srv_idx<query->srv_cnt; ++srv_idx) { 767 if (pj_stricmp(&pkt->ans[0].name, 768 &query->srv[srv_idx].target_name)==0) 769 { 770 break; 771 } 772 } 773 774 if (srv_idx == query->srv_cnt) { 775 PJ_LOG(4,(query->objname, 776 "Received answer to DNS A request with no matching " 777 "SRV record! The unknown name is %.*s", 778 (int)pkt->ans[0].name.slen, pkt->ans[0].name.ptr)); 779 } else { 780 int ans_idx = -1; 781 unsigned k, j; 782 pj_str_t cname = { NULL, 0 }; 783 784 /* Find the first DNS A record in the answer while processing 785 * the CNAME info found in the response. 786 */ 787 for (k=0; k < pkt->hdr.anscount; ++k) { 788 789 pj_dns_parsed_rr *rr = &pkt->ans[k]; 790 791 if (rr->type == PJ_DNS_TYPE_A && 792 (cname.slen == 0 || pj_stricmp(&rr->name, &cname)==0)) 793 { 794 if (ans_idx == -1) 795 ans_idx = k; 796 797 } else if (rr->type == PJ_DNS_TYPE_CNAME && 798 pj_stricmp(&query->srv[srv_idx].target_name, 799 &rr->name)==0) 800 { 801 cname = rr->rdata.cname.name; 802 } 803 } 804 805 if (ans_idx == -1) { 806 /* There's no DNS A answer! */ 807 PJ_LOG(5,(query->objname, 808 "No DNS A record in response!")); 809 status = PJLIB_UTIL_EDNSNOANSWERREC; 810 goto on_error; 811 } 812 813 query->srv[srv_idx].addr[query->srv[srv_idx].addr_cnt++].s_addr = 814 pkt->ans[ans_idx].rdata.a.ip_addr.s_addr; 815 816 PJ_LOG(5,(query->objname, 817 "DNS A for %.*s: %s", 818 (int)query->srv[srv_idx].target_name.slen, 819 query->srv[srv_idx].target_name.ptr, 820 pj_inet_ntoa(pkt->ans[ans_idx].rdata.a.ip_addr))); 821 822 /* Check for multiple IP addresses */ 823 for (j=ans_idx+1; j<pkt->hdr.anscount && 824 query->srv[srv_idx].addr_cnt < ADDR_MAX_COUNT; ++j) 825 { 826 query->srv[srv_idx].addr[query->srv[srv_idx].addr_cnt++].s_addr = 827 pkt->ans[j].rdata.a.ip_addr.s_addr; 828 829 PJ_LOG(5,(query->objname, 830 "Additional DNS A for %.*s: %s", 831 (int)query->srv[srv_idx].target_name.slen, 832 query->srv[srv_idx].target_name.ptr, 833 pj_inet_ntoa(pkt->ans[j].rdata.a.ip_addr))); 834 } 835 } 836 837 } else if (status != PJ_SUCCESS) { 838 char errmsg[PJ_ERR_MSG_SIZE]; 839 840 /* Update last error */ 841 query->last_error = status; 842 843 /* Log error */ 844 pj_strerror(status, errmsg, sizeof(errmsg)); 845 PJ_LOG(4,(query->objname, "DNS A record resolution failed: %s", 846 errmsg)); 847 } 848 849 ++query->host_resolved; 850 851 } else { 852 pj_assert(!"Unexpected state!"); 853 query->last_error = status = PJ_EINVALIDOP; 854 goto on_error; 855 } 856 857 /* Check if all hosts have been resolved */ 858 if (query->host_resolved == query->srv_cnt) { 859 /* Got all answers, build server addresses */ 860 pjsip_server_addresses svr_addr; 861 862 svr_addr.count = 0; 863 for (i=0; i<query->srv_cnt; ++i) { 864 unsigned j; 865 866 /* Do we have IP address for this server? */ 867 /* This log is redundant really. 868 if (query->srv[i].addr_cnt == 0) { 869 PJ_LOG(5,(query->objname, 870 " SRV target %.*s:%d does not have IP address!", 871 (int)query->srv[i].target_name.slen, 872 query->srv[i].target_name.ptr, 873 query->srv[i].port)); 874 continue; 875 } 876 */ 877 878 for (j=0; j<query->srv[i].addr_cnt; ++j) { 879 unsigned idx = svr_addr.count; 880 pj_sockaddr_in *addr; 881 882 svr_addr.entry[idx].type = query->srv[i].type; 883 svr_addr.entry[idx].priority = query->srv[i].priority; 884 svr_addr.entry[idx].weight = query->srv[i].weight; 885 svr_addr.entry[idx].addr_len = sizeof(pj_sockaddr_in); 886 887 addr = (pj_sockaddr_in*)&svr_addr.entry[idx].addr; 888 pj_bzero(addr, sizeof(pj_sockaddr_in)); 889 addr->sin_family = PJ_AF_INET; 890 addr->sin_addr = query->srv[i].addr[j]; 891 addr->sin_port = pj_htons((pj_uint16_t)query->srv[i].port); 892 893 ++svr_addr.count; 894 } 895 } 896 897 PJ_LOG(5,(query->objname, 898 "Server resolution complete, %d server entry(s) found", 899 svr_addr.count)); 900 901 902 if (svr_addr.count > 0) 903 status = PJ_SUCCESS; 904 else { 905 status = query->last_error; 906 if (status == PJ_SUCCESS) 907 status = PJLIB_UTIL_EDNSNOANSWERREC; 908 } 909 910 /* Call the callback */ 911 (*query->cb)(status, query->token, &svr_addr); 912 } 913 914 915 return; 916 917 on_error: 918 /* Check for failure */ 382 383 rec.addr_count = 0; 384 385 /* Parse the response */ 386 if (status == PJ_SUCCESS) { 387 status = pj_dns_parse_a_response(pkt, &rec); 388 } 389 919 390 if (status != PJ_SUCCESS) { 920 391 char errmsg[PJ_ERR_MSG_SIZE]; 921 PJ_LOG(4,(query->objname, 922 "DNS %s record resolution error for '%.*s'." 923 " Err=%d (%s)", 924 pj_dns_get_type_name(query->dns_state), 925 (int)query->req.target.addr.host.slen, 926 query->req.target.addr.host.ptr, 927 status, 928 pj_strerror(status,errmsg,sizeof(errmsg)).ptr)); 392 393 /* Log error */ 394 pj_strerror(status, errmsg, sizeof(errmsg)); 395 PJ_LOG(4,(query->objname, "DNS A record resolution failed: %s", 396 errmsg)); 397 398 /* Call the callback */ 929 399 (*query->cb)(status, query->token, NULL); 930 400 return; 931 401 } 402 403 /* Build server addresses and call callback */ 404 srv.count = 0; 405 for (i=0; i<rec.addr_count; ++i) { 406 srv.entry[srv.count].type = query->naptr[0].type; 407 srv.entry[srv.count].priority = 0; 408 srv.entry[srv.count].weight = 0; 409 srv.entry[srv.count].addr_len = sizeof(pj_sockaddr_in); 410 pj_sockaddr_in_init(&srv.entry[srv.count].addr.ipv4, 411 0, (pj_uint16_t)query->req.def_port); 412 srv.entry[srv.count].addr.ipv4.sin_addr.s_addr = 413 rec.addr[i].s_addr; 414 415 ++srv.count; 416 } 417 418 /* Call the callback */ 419 (*query->cb)(PJ_SUCCESS, query->token, &srv); 420 } 421 422 423 /* Callback to be called by DNS SRV resolution */ 424 static void srv_resolver_cb(void *user_data, 425 pj_status_t status, 426 const pj_dns_srv_record *rec) 427 { 428 struct query *query = (struct query*) user_data; 429 pjsip_server_addresses srv; 430 unsigned i; 431 432 if (status != PJ_SUCCESS) { 433 char errmsg[PJ_ERR_MSG_SIZE]; 434 435 /* Log error */ 436 pj_strerror(status, errmsg, sizeof(errmsg)); 437 PJ_LOG(4,(query->objname, "DNS A record resolution failed: %s", 438 errmsg)); 439 440 /* Call the callback */ 441 (*query->cb)(status, query->token, NULL); 442 return; 443 } 444 445 /* Build server addresses and call callback */ 446 srv.count = 0; 447 for (i=0; i<rec->count; ++i) { 448 unsigned j; 449 450 for (j=0; j<rec->entry[i].server.addr_count; ++j) { 451 srv.entry[srv.count].type = query->naptr[0].type; 452 srv.entry[srv.count].priority = rec->entry[i].priority; 453 srv.entry[srv.count].weight = rec->entry[i].weight; 454 srv.entry[srv.count].addr_len = sizeof(pj_sockaddr_in); 455 pj_sockaddr_in_init(&srv.entry[srv.count].addr.ipv4, 456 0, (pj_uint16_t)rec->entry[i].port); 457 srv.entry[srv.count].addr.ipv4.sin_addr.s_addr = 458 rec->entry[i].server.addr[j].s_addr; 459 460 ++srv.count; 461 } 462 } 463 464 /* Call the callback */ 465 (*query->cb)(PJ_SUCCESS, query->token, &srv); 932 466 } 933 467 934 468 #endif /* PJSIP_HAS_RESOLVER */ 935 469 936 937
Note: See TracChangeset
for help on using the changeset viewer.