- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjlib-util/src/pjlib-util/resolver.c
r5826 r4649 20 20 #include <pjlib-util/resolver.h> 21 21 #include <pjlib-util/errno.h> 22 #include <pj/compat/socket.h>23 22 #include <pj/assert.h> 24 23 #include <pj/ctype.h> … … 81 80 struct nameserver 82 81 { 83 pj_sockaddr 82 pj_sockaddr_in addr; /**< Server address. */ 84 83 85 84 enum ns_state state; /**< Nameserver state. */ … … 170 169 /* Internals */ 171 170 pj_pool_t *pool; /**< Internal pool. */ 172 pj_ grp_lock_t *grp_lock; /**< Group lock protection.*/171 pj_mutex_t *mutex; /**< Mutex protection. */ 173 172 pj_bool_t own_timer; /**< Do we own timer? */ 174 173 pj_timer_heap_t *timer; /**< Timer instance. */ … … 181 180 pj_ioqueue_key_t *udp_key; /**< UDP socket ioqueue key. */ 182 181 unsigned char udp_rx_pkt[UDPSZ];/**< UDP receive buffer. */ 183 unsigned char udp_tx_pkt[UDPSZ];/**< UDP transmit buffer. */ 182 unsigned char udp_tx_pkt[UDPSZ];/**< UDP receive buffer. */ 183 pj_ssize_t udp_len; /**< Length of received packet. */ 184 184 pj_ioqueue_op_key_t udp_op_rx_key; /**< UDP read operation key. */ 185 185 pj_ioqueue_op_key_t udp_op_tx_key; /**< UDP write operation key. */ 186 pj_sockaddr 186 pj_sockaddr_in udp_src_addr; /**< Source address of packet */ 187 187 int udp_addr_len; /**< Source address length. */ 188 189 #if PJ_HAS_IPV6190 /* 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 #endif200 188 201 189 /* Settings */ … … 237 225 unsigned servers[]); 238 226 239 /* Destructor */240 static void dns_resolver_on_destroy(void *member);241 227 242 228 /* Close UDP socket */ … … 252 238 resv->udp_sock = PJ_INVALID_SOCKET; 253 239 } 254 255 #if PJ_HAS_IPV6256 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 #endif265 240 } 266 241 … … 270 245 { 271 246 pj_ioqueue_callback socket_cb; 272 pj_sockaddr bound_addr;273 pj_ssize_t rx_pkt_size;274 247 pj_status_t status; 275 248 … … 287 260 pj_bzero(&socket_cb, sizeof(socket_cb)); 288 261 socket_cb.on_read_complete = &on_read_complete; 289 status = pj_ioqueue_register_sock 2(resv->pool, resv->ioqueue,290 resv->udp_sock, resv->grp_lock,291 resv, &socket_cb,&resv->udp_key);262 status = pj_ioqueue_register_sock(resv->pool, resv->ioqueue, 263 resv->udp_sock, resv, &socket_cb, 264 &resv->udp_key); 292 265 if (status != PJ_SUCCESS) 293 266 return status; … … 297 270 298 271 /* Start asynchronous read to the UDP socket */ 299 r x_pkt_size= sizeof(resv->udp_rx_pkt);272 resv->udp_len = sizeof(resv->udp_rx_pkt); 300 273 resv->udp_addr_len = sizeof(resv->udp_src_addr); 301 274 status = pj_ioqueue_recvfrom(resv->udp_key, &resv->udp_op_rx_key, 302 resv->udp_rx_pkt, &r x_pkt_size,275 resv->udp_rx_pkt, &resv->udp_len, 303 276 PJ_IOQUEUE_ALWAYS_ASYNC, 304 277 &resv->udp_src_addr, &resv->udp_addr_len); 305 278 if (status != PJ_EPENDING) 306 279 return status; 307 308 309 #if PJ_HAS_IPV6310 /* 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 #else357 PJ_UNUSED_ARG(bound_addr);358 #endif359 280 360 281 return PJ_SUCCESS; … … 405 326 pj_strdup2_with_null(pool, &resv->name, name); 406 327 407 /* Create group lock */ 408 status = pj_grp_lock_create_w_handler(pool, NULL, resv, 409 &dns_resolver_on_destroy, 410 &resv->grp_lock); 328 /* Create the mutex */ 329 status = pj_mutex_create_recursive(pool, name, &resv->mutex); 411 330 if (status != PJ_SUCCESS) 412 331 goto on_error; 413 414 pj_grp_lock_add_ref(resv->grp_lock);415 332 416 333 /* Timer, ioqueue, and settings */ … … 424 341 /* Create the timer heap if one is not specified */ 425 342 if (resv->timer == NULL) { 426 resv->own_timer = PJ_TRUE;427 343 status = pj_timer_heap_create(pool, TIMER_SIZE, &resv->timer); 428 344 if (status != PJ_SUCCESS) … … 432 348 /* Create the ioqueue if one is not specified */ 433 349 if (resv->ioqueue == NULL) { 434 resv->own_ioqueue = PJ_TRUE;435 350 status = pj_ioqueue_create(pool, MAX_FD, &resv->ioqueue); 436 351 if (status != PJ_SUCCESS) … … 458 373 pj_dns_resolver_destroy(resv, PJ_FALSE); 459 374 return status; 460 }461 462 463 void dns_resolver_on_destroy(void *member)464 {465 pj_dns_resolver *resolver = (pj_dns_resolver*)member;466 pj_pool_safe_release(&resolver->pool);467 375 } 468 376 … … 524 432 } 525 433 526 pj_grp_lock_dec_ref(resolver->grp_lock); 527 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 } 528 444 return PJ_SUCCESS; 529 445 } … … 546 462 PJ_ASSERT_RETURN(count < PJ_DNS_RESOLVER_MAX_NS, PJ_EINVAL); 547 463 548 pj_ grp_lock_acquire(resolver->grp_lock);464 pj_mutex_lock(resolver->mutex); 549 465 550 466 if (count > PJ_DNS_RESOLVER_MAX_NS) … … 559 475 struct nameserver *ns = &resolver->ns[i]; 560 476 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)); 477 status = pj_sockaddr_in_init(&ns->addr, &servers[i], 478 (pj_uint16_t)(ports ? ports[i] : PORT)); 566 479 if (status != PJ_SUCCESS) { 567 pj_ grp_lock_release(resolver->grp_lock);480 pj_mutex_unlock(resolver->mutex); 568 481 return PJLIB_UTIL_EDNSINNSADDR; 569 482 } … … 576 489 resolver->ns_count = count; 577 490 578 pj_ grp_lock_release(resolver->grp_lock);491 pj_mutex_unlock(resolver->mutex); 579 492 return PJ_SUCCESS; 580 493 } … … 590 503 PJ_ASSERT_RETURN(resolver && st, PJ_EINVAL); 591 504 592 pj_ grp_lock_acquire(resolver->grp_lock);505 pj_mutex_lock(resolver->mutex); 593 506 pj_memcpy(&resolver->settings, st, sizeof(*st)); 594 pj_ grp_lock_release(resolver->grp_lock);507 pj_mutex_unlock(resolver->mutex); 595 508 return PJ_SUCCESS; 596 509 } … … 605 518 PJ_ASSERT_RETURN(resolver && st, PJ_EINVAL); 606 519 607 pj_ grp_lock_acquire(resolver->grp_lock);520 pj_mutex_lock(resolver->mutex); 608 521 pj_memcpy(st, &resolver->settings, sizeof(*st)); 609 pj_ grp_lock_release(resolver->grp_lock);522 pj_mutex_unlock(resolver->mutex); 610 523 return PJ_SUCCESS; 611 524 } … … 620 533 PJ_ASSERT_ON_FAIL(resolver, return); 621 534 622 pj_ grp_lock_acquire(resolver->grp_lock);535 pj_mutex_lock(resolver->mutex); 623 536 pj_timer_heap_poll(resolver->timer, NULL); 624 pj_ grp_lock_release(resolver->grp_lock);537 pj_mutex_unlock(resolver->mutex); 625 538 626 539 pj_ioqueue_poll(resolver->ioqueue, timeout); … … 667 580 { 668 581 unsigned pkt_size; 669 unsigned i, server_cnt , send_cnt;582 unsigned i, server_cnt; 670 583 unsigned servers[PJ_DNS_RESOLVER_MAX_NS]; 671 584 pj_time_val now; … … 694 607 delay.msec = resolver->settings.qretr_delay; 695 608 pj_time_val_normalize(&delay); 696 status = pj_timer_heap_schedule_w_grp_lock(resolver->timer, 697 &q->timer_entry, 698 &delay, 1, 699 resolver->grp_lock); 609 status = pj_timer_heap_schedule(resolver->timer, &q->timer_entry, &delay); 700 610 if (status != PJ_SUCCESS) { 701 611 return status; … … 703 613 704 614 /* Check if the socket is available for sending */ 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 { 615 if (pj_ioqueue_is_pending(resolver->udp_key, &resolver->udp_op_tx_key)) { 713 616 ++q->transmit_cnt; 714 617 PJ_LOG(4,(resolver->name.ptr, … … 735 638 736 639 /* Send the packet to name servers */ 737 send_cnt = 0;738 640 for (i=0; i<server_cnt; ++i) { 739 char addr[PJ_INET6_ADDRSTRLEN];740 641 pj_ssize_t sent = (pj_ssize_t) pkt_size; 741 642 struct nameserver *ns = &resolver->ns[servers[i]]; 742 643 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 } 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)); 766 649 767 650 PJ_PERROR(4,(resolver->name.ptr, status, … … 769 652 (q->transmit_cnt==0? "Transmitting":"Re-transmitting"), 770 653 (int)pkt_size, servers[i], 771 pj_ sockaddr_print(&ns->addr, addr, sizeof(addr), 2),772 pj_sockaddr_get_port(&ns->addr),654 pj_inet_ntoa(ns->addr.sin_addr), 655 (int)pj_ntohs(ns->addr.sin_port), 773 656 pj_dns_get_type_name(q->key.qtype), 774 657 q->key.name)); … … 778 661 ns->sent_time = now; 779 662 } 780 }781 782 if (send_cnt == 0) {783 pj_timer_heap_cancel(resolver->timer, &q->timer_entry);784 return PJLIB_UTIL_EDNSNOWORKINGNS;785 663 } 786 664 … … 869 747 struct res_key key; 870 748 struct cached_res *cache; 871 pj_dns_async_query *q , *p_q = NULL;749 pj_dns_async_query *q; 872 750 pj_uint32_t hval; 873 751 pj_status_t status = PJ_SUCCESS; … … 883 761 PJ_ASSERT_RETURN(type > 0 && type < 0xFFFF, PJ_EINVAL); 884 762 763 if (p_query) 764 *p_query = NULL; 765 885 766 /* Build resource key for looking up hash tables */ 886 767 init_res_key(&key, type, name); 887 768 888 769 /* Start working with the resolver */ 889 pj_ grp_lock_acquire(resolver->grp_lock);770 pj_mutex_lock(resolver->mutex); 890 771 891 772 /* Get current time. */ … … 920 801 */ 921 802 cache->ref_cnt++; 922 pj_ grp_lock_release(resolver->grp_lock);803 pj_mutex_unlock(resolver->mutex); 923 804 924 805 /* This cached response is still valid. Just return this … … 930 811 931 812 /* Done. No host resolution is necessary */ 932 pj_ grp_lock_acquire(resolver->grp_lock);813 pj_mutex_lock(resolver->mutex); 933 814 934 815 /* Decrement the ref counter. Also check if it is time to free … … 942 823 status = PJ_SUCCESS; 943 824 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; 825 goto on_return; 951 826 } 952 827 … … 980 855 * query completes. 981 856 */ 982 p_q = nq;983 857 status = PJ_SUCCESS; 984 858 goto on_return; … … 1008 882 0, q->hbufkey, q); 1009 883 1010 p_q = q; 884 if (p_query) 885 *p_query = q; 1011 886 1012 887 on_return: 1013 if (p_query) 1014 *p_query = p_q; 1015 1016 pj_grp_lock_release(resolver->grp_lock); 888 pj_mutex_unlock(resolver->mutex); 1017 889 return status; 1018 890 } … … 1029 901 PJ_ASSERT_RETURN(query, PJ_EINVAL); 1030 902 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 } 903 pj_mutex_lock(query->resolver->mutex); 1037 904 1038 905 cb = query->cb; … … 1042 909 (*cb)(query->user_data, PJ_ECANCELLED, NULL); 1043 910 1044 pj_ grp_lock_release(query->resolver->grp_lock);911 pj_mutex_unlock(query->resolver->mutex); 1045 912 return PJ_SUCCESS; 1046 913 } … … 1160 1027 1161 1028 1162 /*1163 * DNS response containing A and/or AAAA packet.1164 */1165 PJ_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 1288 1029 /* Set nameserver state */ 1289 1030 static void set_nameserver_state(pj_dns_resolver *resolver, … … 1294 1035 struct nameserver *ns = &resolver->ns[index]; 1295 1036 enum ns_state old_state = ns->state; 1296 char addr[PJ_INET6_ADDRSTRLEN];1297 1037 1298 1038 ns->state = state; … … 1308 1048 1309 1049 PJ_LOG(5, (resolver->name.ptr, "Nameserver %s:%d state changed %s --> %s", 1310 pj_ sockaddr_print(&ns->addr, addr, sizeof(addr), 2),1311 pj_sockaddr_get_port(&ns->addr),1050 pj_inet_ntoa(ns->addr.sin_addr), 1051 (int)pj_ntohs(ns->addr.sin_port), 1312 1052 state_names[old_state], state_names[state])); 1313 1053 } … … 1388 1128 /* Update name server status */ 1389 1129 static void report_nameserver_status(pj_dns_resolver *resolver, 1390 const pj_sockaddr *ns_addr,1130 const pj_sockaddr_in *ns_addr, 1391 1131 const pj_dns_parsed_packet *pkt) 1392 1132 { … … 1408 1148 } 1409 1149 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 || */ 1150 if (!pkt || rcode == PJ_DNS_RCODE_SERVFAIL || 1416 1151 rcode == PJ_DNS_RCODE_REFUSED || 1417 1152 rcode == PJ_DNS_RCODE_NOTAUTH) … … 1430 1165 struct nameserver *ns = &resolver->ns[i]; 1431 1166 1432 if (pj_sockaddr_cmp(&ns->addr, ns_addr) == 0) { 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 { 1433 1171 if (q_id == ns->q_id) { 1434 1172 /* Calculate response time */ … … 1495 1233 ttl = resolver->settings.cache_max_ttl; 1496 1234 1497 /* Get a cache response entry */1498 cache = (struct cached_res *) pj_hash_get(resolver->hrescache, key,1499 sizeof(*key), &hval);1500 1501 1235 /* If TTL is zero, clear the same entry in the hash table */ 1502 1236 if (ttl == 0) { 1237 cache = (struct cached_res *) pj_hash_get(resolver->hrescache, key, 1238 sizeof(*key), &hval); 1503 1239 /* Remove the entry before releasing its pool (see ticket #1710) */ 1504 1240 pj_hash_set(NULL, resolver->hrescache, key, sizeof(*key), hval, NULL); … … 1510 1246 } 1511 1247 1248 /* Get a cache response entry */ 1249 cache = (struct cached_res *) pj_hash_get(resolver->hrescache, key, 1250 sizeof(*key), &hval); 1512 1251 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--; 1513 1259 cache = alloc_entry(resolver); 1514 1260 } else { … … 1516 1262 pj_hash_set(NULL, resolver->hrescache, key, sizeof(*key), hval, NULL); 1517 1263 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 } 1264 /* Reset cache to avoid bloated cache pool */ 1265 reset_entry(&cache); 1529 1266 } 1530 1267 … … 1571 1308 resolver = q->resolver; 1572 1309 1573 pj_ grp_lock_acquire(resolver->grp_lock);1310 pj_mutex_lock(resolver->mutex); 1574 1311 1575 1312 /* Recheck that this query is still pending, since there is a slight … … 1579 1316 if (pj_hash_get(resolver->hquerybyid, &q->id, sizeof(q->id), NULL)==NULL) { 1580 1317 /* Yeah, this query is done. */ 1581 pj_ grp_lock_release(resolver->grp_lock);1318 pj_mutex_unlock(resolver->mutex); 1582 1319 return; 1583 1320 } … … 1590 1327 status = transmit_query(resolver, q); 1591 1328 if (status == PJ_SUCCESS) { 1592 pj_ grp_lock_release(resolver->grp_lock);1329 pj_mutex_unlock(resolver->mutex); 1593 1330 return; 1594 1331 } else { … … 1609 1346 1610 1347 /* Workaround for deadlock problem in #1565 (similar to #1108) */ 1611 pj_ grp_lock_release(resolver->grp_lock);1348 pj_mutex_unlock(resolver->mutex); 1612 1349 1613 1350 /* Call application callback, if any. */ … … 1624 1361 1625 1362 /* Workaround for deadlock problem in #1565 (similar to #1108) */ 1626 pj_ grp_lock_acquire(resolver->grp_lock);1363 pj_mutex_lock(resolver->mutex); 1627 1364 1628 1365 /* Clear data */ … … 1641 1378 pj_list_push_back(&resolver->query_free_nodes, q); 1642 1379 1643 pj_ grp_lock_release(resolver->grp_lock);1380 pj_mutex_unlock(resolver->mutex); 1644 1381 } 1645 1382 … … 1654 1391 pj_dns_parsed_packet *dns_pkt; 1655 1392 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;1661 1393 pj_status_t status; 1662 1394 PJ_USE_EXCEPTION; … … 1664 1396 1665 1397 resolver = (pj_dns_resolver *) pj_ioqueue_get_user_data(key); 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); 1398 pj_mutex_lock(resolver->mutex); 1684 1399 1685 1400 … … 1690 1405 status = (pj_status_t)-bytes_read; 1691 1406 pj_strerror(status, errmsg, sizeof(errmsg)); 1692 PJ_LOG(4,(resolver->name.ptr, "DNS resolver read error: %s", 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)); 1693 1412 1694 1413 goto read_next_packet; … … 1698 1417 "Received %d bytes DNS response from %s:%d", 1699 1418 (int)bytes_read, 1700 pj_ sockaddr_print(src_addr, addr, sizeof(addr), 2),1701 pj_ sockaddr_get_port(src_addr)));1419 pj_inet_ntoa(resolver->udp_src_addr.sin_addr), 1420 pj_ntohs(resolver->udp_src_addr.sin_port))); 1702 1421 1703 1422 … … 1714 1433 dns_pkt = NULL; 1715 1434 PJ_TRY { 1716 status = pj_dns_parse_packet(pool, r x_pkt,1435 status = pj_dns_parse_packet(pool, resolver->udp_rx_pkt, 1717 1436 (unsigned)bytes_read, &dns_pkt); 1718 1437 } … … 1723 1442 1724 1443 /* Update nameserver status */ 1725 report_nameserver_status(resolver, src_addr, dns_pkt);1444 report_nameserver_status(resolver, &resolver->udp_src_addr, dns_pkt); 1726 1445 1727 1446 /* Handle parse error */ … … 1732 1451 PJ_LOG(3,(resolver->name.ptr, 1733 1452 "Error parsing DNS response from %s:%d: %s", 1734 pj_ sockaddr_print(src_addr, addr, sizeof(addr), 2),1735 pj_ sockaddr_get_port(src_addr),1453 pj_inet_ntoa(resolver->udp_src_addr.sin_addr), 1454 pj_ntohs(resolver->udp_src_addr.sin_port), 1736 1455 errmsg)); 1737 1456 goto read_next_packet; … … 1745 1464 PJ_LOG(5,(resolver->name.ptr, 1746 1465 "DNS response from %s:%d id=%d discarded", 1747 pj_ sockaddr_print(src_addr, addr, sizeof(addr), 2),1748 pj_ sockaddr_get_port(src_addr),1466 pj_inet_ntoa(resolver->udp_src_addr.sin_addr), 1467 pj_ntohs(resolver->udp_src_addr.sin_port), 1749 1468 (unsigned)dns_pkt->hdr.id)); 1750 1469 goto read_next_packet; … … 1764 1483 1765 1484 /* Workaround for deadlock problem in #1108 */ 1766 pj_ grp_lock_release(resolver->grp_lock);1485 pj_mutex_unlock(resolver->mutex); 1767 1486 1768 1487 /* Notify applications first, to allow application to modify the … … 1785 1504 1786 1505 /* Workaround for deadlock problem in #1108 */ 1787 pj_ grp_lock_acquire(resolver->grp_lock);1506 pj_mutex_lock(resolver->mutex); 1788 1507 1789 1508 /* Save/update response cache. */ … … 1809 1528 pj_pool_release(pool); 1810 1529 } 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) { 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) { 1817 1538 char errmsg[PJ_ERR_MSG_SIZE]; 1818 1539 … … 1824 1545 } 1825 1546 1826 pj_ grp_lock_release(resolver->grp_lock);1547 pj_mutex_unlock(resolver->mutex); 1827 1548 } 1828 1549 … … 1850 1571 PJLIB_UTIL_EDNSNOANSWERREC); 1851 1572 1852 pj_ grp_lock_acquire(resolver->grp_lock);1573 pj_mutex_lock(resolver->mutex); 1853 1574 1854 1575 /* Build resource key for looking up hash tables */ … … 1872 1593 update_res_cache(resolver, &key, PJ_SUCCESS, set_ttl, pkt); 1873 1594 1874 pj_ grp_lock_release(resolver->grp_lock);1595 pj_mutex_unlock(resolver->mutex); 1875 1596 1876 1597 return PJ_SUCCESS; … … 1887 1608 PJ_ASSERT_RETURN(resolver, 0); 1888 1609 1889 pj_ grp_lock_acquire(resolver->grp_lock);1610 pj_mutex_lock(resolver->mutex); 1890 1611 count = pj_hash_count(resolver->hrescache); 1891 pj_ grp_lock_release(resolver->grp_lock);1612 pj_mutex_unlock(resolver->mutex); 1892 1613 1893 1614 return count; … … 1905 1626 pj_time_val now; 1906 1627 1907 pj_ grp_lock_acquire(resolver->grp_lock);1628 pj_mutex_lock(resolver->mutex); 1908 1629 1909 1630 pj_gettimeofday(&now); … … 1913 1634 PJ_LOG(3,(resolver->name.ptr, " Name servers:")); 1914 1635 for (i=0; i<resolver->ns_count; ++i) { 1915 c har addr[PJ_INET6_ADDRSTRLEN];1636 const char *state_names[] = { "probing", "active", "bad"}; 1916 1637 struct nameserver *ns = &resolver->ns[i]; 1917 1638 1918 1639 PJ_LOG(3,(resolver->name.ptr, 1919 1640 " NS %d: %s:%d (state=%s until %ds, rtt=%d ms)", 1920 i, 1921 pj_sockaddr_print(&ns->addr, addr, sizeof(addr), 2), 1922 pj_sockaddr_get_port(&ns->addr), 1641 i, pj_inet_ntoa(ns->addr.sin_addr), 1642 pj_ntohs(ns->addr.sin_port), 1923 1643 state_names[ns->state], 1924 1644 ns->state_expiry.sec - now.sec, … … 1965 1685 pj_pool_get_used_size(resolver->pool))); 1966 1686 1967 pj_ grp_lock_release(resolver->grp_lock);1687 pj_mutex_unlock(resolver->mutex); 1968 1688 #endif 1969 1689 }
Note: See TracChangeset
for help on using the changeset viewer.