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