Changeset 5349 for pjproject/trunk/pjlib-util/src/pjlib-util/resolver.c
- Timestamp:
- Jun 20, 2016 10:10:42 AM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjlib-util/src/pjlib-util/resolver.c
r5311 r5349 80 80 struct nameserver 81 81 { 82 pj_sockaddr _inaddr; /**< Server address. */82 pj_sockaddr addr; /**< Server address. */ 83 83 84 84 enum ns_state state; /**< Nameserver state. */ … … 180 180 pj_ioqueue_key_t *udp_key; /**< UDP socket ioqueue key. */ 181 181 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. */ 182 unsigned char udp_tx_pkt[UDPSZ];/**< UDP transmit buffer. */ 184 183 pj_ioqueue_op_key_t udp_op_rx_key; /**< UDP read operation key. */ 185 184 pj_ioqueue_op_key_t udp_op_tx_key; /**< UDP write operation key. */ 186 pj_sockaddr _inudp_src_addr; /**< Source address of packet */185 pj_sockaddr udp_src_addr; /**< Source address of packet */ 187 186 int udp_addr_len; /**< Source address length. */ 187 188 #if PJ_HAS_IPV6 189 /* IPv6 socket */ 190 pj_sock_t udp6_sock; /**< UDP socket. */ 191 pj_ioqueue_key_t *udp6_key; /**< UDP socket ioqueue key. */ 192 unsigned char udp6_rx_pkt[UDPSZ];/**< UDP receive buffer. */ 193 //unsigned char udp6_tx_pkt[UDPSZ];/**< UDP transmit buffer. */ 194 pj_ioqueue_op_key_t udp6_op_rx_key;/**< UDP read operation key. */ 195 pj_ioqueue_op_key_t udp6_op_tx_key;/**< UDP write operation key. */ 196 pj_sockaddr udp6_src_addr; /**< Source address of packet */ 197 int udp6_addr_len; /**< Source address length. */ 198 #endif 188 199 189 200 /* Settings */ … … 238 249 resv->udp_sock = PJ_INVALID_SOCKET; 239 250 } 251 252 #if PJ_HAS_IPV6 253 if (resv->udp6_key != NULL) { 254 pj_ioqueue_unregister(resv->udp6_key); 255 resv->udp6_key = NULL; 256 resv->udp6_sock = PJ_INVALID_SOCKET; 257 } else if (resv->udp6_sock != PJ_INVALID_SOCKET) { 258 pj_sock_close(resv->udp6_sock); 259 resv->udp6_sock = PJ_INVALID_SOCKET; 260 } 261 #endif 240 262 } 241 263 … … 245 267 { 246 268 pj_ioqueue_callback socket_cb; 269 pj_sockaddr bound_addr; 270 pj_ssize_t rx_pkt_size; 247 271 pj_status_t status; 248 272 … … 270 294 271 295 /* Start asynchronous read to the UDP socket */ 272 r esv->udp_len= sizeof(resv->udp_rx_pkt);296 rx_pkt_size = sizeof(resv->udp_rx_pkt); 273 297 resv->udp_addr_len = sizeof(resv->udp_src_addr); 274 298 status = pj_ioqueue_recvfrom(resv->udp_key, &resv->udp_op_rx_key, 275 resv->udp_rx_pkt, &r esv->udp_len,299 resv->udp_rx_pkt, &rx_pkt_size, 276 300 PJ_IOQUEUE_ALWAYS_ASYNC, 277 301 &resv->udp_src_addr, &resv->udp_addr_len); 278 302 if (status != PJ_EPENDING) 279 303 return status; 304 305 306 #if PJ_HAS_IPV6 307 /* Also setup IPv6 socket */ 308 309 /* Create the UDP socket */ 310 status = pj_sock_socket(pj_AF_INET6(), pj_SOCK_DGRAM(), 0, 311 &resv->udp6_sock); 312 if (status != PJ_SUCCESS) 313 return status; 314 315 /* Bind to any address/port */ 316 pj_sockaddr_init(pj_AF_INET6(), &bound_addr, NULL, 0); 317 status = pj_sock_bind(resv->udp6_sock, &bound_addr, 318 pj_sockaddr_get_len(&bound_addr)); 319 if (status != PJ_SUCCESS) 320 return status; 321 322 /* Register to ioqueue */ 323 pj_bzero(&socket_cb, sizeof(socket_cb)); 324 socket_cb.on_read_complete = &on_read_complete; 325 status = pj_ioqueue_register_sock(resv->pool, resv->ioqueue, 326 resv->udp6_sock, resv, &socket_cb, 327 &resv->udp6_key); 328 if (status != PJ_SUCCESS) 329 return status; 330 331 pj_ioqueue_op_key_init(&resv->udp6_op_rx_key, 332 sizeof(resv->udp6_op_rx_key)); 333 pj_ioqueue_op_key_init(&resv->udp6_op_tx_key, 334 sizeof(resv->udp6_op_tx_key)); 335 336 /* Start asynchronous read to the UDP socket */ 337 rx_pkt_size = sizeof(resv->udp6_rx_pkt); 338 resv->udp6_addr_len = sizeof(resv->udp6_src_addr); 339 status = pj_ioqueue_recvfrom(resv->udp6_key, &resv->udp6_op_rx_key, 340 resv->udp6_rx_pkt, &rx_pkt_size, 341 PJ_IOQUEUE_ALWAYS_ASYNC, 342 &resv->udp6_src_addr, &resv->udp6_addr_len); 343 if (status != PJ_EPENDING) 344 return status; 345 #else 346 PJ_UNUSED_ARG(bound_addr); 347 #endif 280 348 281 349 return PJ_SUCCESS; … … 475 543 struct nameserver *ns = &resolver->ns[i]; 476 544 477 status = pj_sockaddr_in_init(&ns->addr, &servers[i], 478 (pj_uint16_t)(ports ? ports[i] : PORT)); 545 status = pj_sockaddr_init(pj_AF_INET(), &ns->addr, &servers[i], 546 (pj_uint16_t)(ports ? ports[i] : PORT)); 547 if (status != PJ_SUCCESS) 548 status = pj_sockaddr_init(pj_AF_INET6(), &ns->addr, &servers[i], 549 (pj_uint16_t)(ports ? ports[i] : PORT)); 479 550 if (status != PJ_SUCCESS) { 480 551 pj_mutex_unlock(resolver->mutex); … … 613 684 614 685 /* Check if the socket is available for sending */ 615 if (pj_ioqueue_is_pending(resolver->udp_key, &resolver->udp_op_tx_key)) { 686 if (pj_ioqueue_is_pending(resolver->udp_key, &resolver->udp_op_tx_key) 687 #if PJ_HAS_IPV6 688 || pj_ioqueue_is_pending(resolver->udp6_key, 689 &resolver->udp6_op_tx_key) 690 #endif 691 ) 692 { 616 693 ++q->transmit_cnt; 617 694 PJ_LOG(4,(resolver->name.ptr, … … 643 720 struct nameserver *ns = &resolver->ns[servers[i]]; 644 721 645 status = pj_ioqueue_sendto(resolver->udp_key, 646 &resolver->udp_op_tx_key, 647 resolver->udp_tx_pkt, &sent, 0, 648 &resolver->ns[servers[i]].addr, 649 sizeof(pj_sockaddr_in)); 722 if (ns->addr.addr.sa_family == pj_AF_INET()) { 723 status = pj_ioqueue_sendto(resolver->udp_key, 724 &resolver->udp_op_tx_key, 725 resolver->udp_tx_pkt, &sent, 0, 726 &ns->addr, 727 pj_sockaddr_get_len(&ns->addr)); 728 } 729 #if PJ_HAS_IPV6 730 else { 731 status = pj_ioqueue_sendto(resolver->udp6_key, 732 &resolver->udp6_op_tx_key, 733 resolver->udp_tx_pkt, &sent, 0, 734 &ns->addr, 735 pj_sockaddr_get_len(&ns->addr)); 736 } 737 #endif 650 738 651 739 PJ_PERROR(4,(resolver->name.ptr, status, … … 653 741 (q->transmit_cnt==0? "Transmitting":"Re-transmitting"), 654 742 (int)pkt_size, servers[i], 655 pj_inet_ntop2(pj_AF_INET(), &ns->addr.sin_addr, addr, 656 sizeof(addr)), 657 (int)pj_ntohs(ns->addr.sin_port), 743 pj_sockaddr_print(&ns->addr, addr, sizeof(addr), 2), 744 pj_sockaddr_get_port(&ns->addr), 658 745 pj_dns_get_type_name(q->key.qtype), 659 746 q->key.name)); … … 1029 1116 1030 1117 1118 /* 1119 * DNS response containing A and/or AAAA packet. 1120 */ 1121 PJ_DEF(pj_status_t) pj_dns_parse_addr_response( 1122 const pj_dns_parsed_packet *pkt, 1123 pj_dns_addr_record *rec) 1124 { 1125 enum { MAX_SEARCH = 20 }; 1126 pj_str_t hostname, alias = {NULL, 0}, *resname; 1127 pj_size_t bufstart = 0; 1128 pj_size_t bufleft; 1129 unsigned i, ansidx, cnt=0; 1130 1131 PJ_ASSERT_RETURN(pkt && rec, PJ_EINVAL); 1132 1133 /* Init the record */ 1134 pj_bzero(rec, sizeof(*rec)); 1135 1136 bufleft = sizeof(rec->buf_); 1137 1138 /* Return error if there's error in the packet. */ 1139 if (PJ_DNS_GET_RCODE(pkt->hdr.flags)) 1140 return PJ_STATUS_FROM_DNS_RCODE(PJ_DNS_GET_RCODE(pkt->hdr.flags)); 1141 1142 /* Return error if there's no query section */ 1143 if (pkt->hdr.qdcount == 0) 1144 return PJLIB_UTIL_EDNSINANSWER; 1145 1146 /* Return error if there's no answer */ 1147 if (pkt->hdr.anscount == 0) 1148 return PJLIB_UTIL_EDNSNOANSWERREC; 1149 1150 /* Get the hostname from the query. */ 1151 hostname = pkt->q[0].name; 1152 1153 /* Copy hostname to the record */ 1154 if (hostname.slen > (int)bufleft) { 1155 return PJ_ENAMETOOLONG; 1156 } 1157 1158 pj_memcpy(&rec->buf_[bufstart], hostname.ptr, hostname.slen); 1159 rec->name.ptr = &rec->buf_[bufstart]; 1160 rec->name.slen = hostname.slen; 1161 1162 bufstart += hostname.slen; 1163 bufleft -= hostname.slen; 1164 1165 /* Find the first RR which name matches the hostname. */ 1166 for (ansidx=0; ansidx < pkt->hdr.anscount; ++ansidx) { 1167 if (pj_stricmp(&pkt->ans[ansidx].name, &hostname)==0) 1168 break; 1169 } 1170 1171 if (ansidx == pkt->hdr.anscount) 1172 return PJLIB_UTIL_EDNSNOANSWERREC; 1173 1174 resname = &hostname; 1175 1176 /* Keep following CNAME records. */ 1177 while (pkt->ans[ansidx].type == PJ_DNS_TYPE_CNAME && 1178 cnt++ < MAX_SEARCH) 1179 { 1180 resname = &pkt->ans[ansidx].rdata.cname.name; 1181 1182 if (!alias.slen) 1183 alias = *resname; 1184 1185 for (i=0; i < pkt->hdr.anscount; ++i) { 1186 if (pj_stricmp(resname, &pkt->ans[i].name)==0) 1187 break; 1188 } 1189 1190 if (i==pkt->hdr.anscount) 1191 return PJLIB_UTIL_EDNSNOANSWERREC; 1192 1193 ansidx = i; 1194 } 1195 1196 if (cnt >= MAX_SEARCH) 1197 return PJLIB_UTIL_EDNSINANSWER; 1198 1199 if (pkt->ans[ansidx].type != PJ_DNS_TYPE_A && 1200 pkt->ans[ansidx].type != PJ_DNS_TYPE_AAAA) 1201 { 1202 return PJLIB_UTIL_EDNSINANSWER; 1203 } 1204 1205 /* Copy alias to the record, if present. */ 1206 if (alias.slen) { 1207 if (alias.slen > (int)bufleft) 1208 return PJ_ENAMETOOLONG; 1209 1210 pj_memcpy(&rec->buf_[bufstart], alias.ptr, alias.slen); 1211 rec->alias.ptr = &rec->buf_[bufstart]; 1212 rec->alias.slen = alias.slen; 1213 1214 bufstart += alias.slen; 1215 bufleft -= alias.slen; 1216 } 1217 1218 /* Get the IP addresses. */ 1219 cnt = 0; 1220 for (i=0; i < pkt->hdr.anscount && cnt < PJ_DNS_MAX_IP_IN_A_REC ; ++i) { 1221 if ((pkt->ans[i].type == PJ_DNS_TYPE_A || 1222 pkt->ans[i].type == PJ_DNS_TYPE_AAAA) && 1223 pj_stricmp(&pkt->ans[i].name, resname)==0) 1224 { 1225 if (pkt->ans[i].type == PJ_DNS_TYPE_A) { 1226 rec->addr[cnt].af = pj_AF_INET(); 1227 rec->addr[cnt].ip.v4 = pkt->ans[i].rdata.a.ip_addr; 1228 } else { 1229 rec->addr[cnt].af = pj_AF_INET6(); 1230 rec->addr[cnt].ip.v6 = pkt->ans[i].rdata.aaaa.ip_addr; 1231 } 1232 ++cnt; 1233 } 1234 } 1235 rec->addr_count = cnt; 1236 1237 if (cnt == 0) 1238 return PJLIB_UTIL_EDNSNOANSWERREC; 1239 1240 return PJ_SUCCESS; 1241 } 1242 1243 1031 1244 /* Set nameserver state */ 1032 1245 static void set_nameserver_state(pj_dns_resolver *resolver, … … 1037 1250 struct nameserver *ns = &resolver->ns[index]; 1038 1251 enum ns_state old_state = ns->state; 1039 char addr[PJ_INET _ADDRSTRLEN];1252 char addr[PJ_INET6_ADDRSTRLEN]; 1040 1253 1041 1254 ns->state = state; … … 1051 1264 1052 1265 PJ_LOG(5, (resolver->name.ptr, "Nameserver %s:%d state changed %s --> %s", 1053 pj_inet_ntop2(pj_AF_INET(), &ns->addr.sin_addr, addr, 1054 sizeof(addr)), 1055 (int)pj_ntohs(ns->addr.sin_port), 1266 pj_sockaddr_print(&ns->addr, addr, sizeof(addr), 2), 1267 pj_sockaddr_get_port(&ns->addr), 1056 1268 state_names[old_state], state_names[state])); 1057 1269 } … … 1132 1344 /* Update name server status */ 1133 1345 static void report_nameserver_status(pj_dns_resolver *resolver, 1134 const pj_sockaddr _in*ns_addr,1346 const pj_sockaddr *ns_addr, 1135 1347 const pj_dns_parsed_packet *pkt) 1136 1348 { … … 1169 1381 struct nameserver *ns = &resolver->ns[i]; 1170 1382 1171 if (ns->addr.sin_addr.s_addr == ns_addr->sin_addr.s_addr && 1172 ns->addr.sin_port == ns_addr->sin_port && 1173 ns->addr.sin_family == ns_addr->sin_family) 1174 { 1383 if (pj_sockaddr_cmp(&ns->addr, ns_addr) == 0) { 1175 1384 if (q_id == ns->q_id) { 1176 1385 /* Calculate response time */ … … 1395 1604 pj_dns_parsed_packet *dns_pkt; 1396 1605 pj_dns_async_query *q; 1397 char addr[PJ_INET_ADDRSTRLEN]; 1606 char addr[PJ_INET6_ADDRSTRLEN]; 1607 pj_sockaddr *src_addr; 1608 int *src_addr_len; 1609 unsigned char *rx_pkt; 1610 pj_ssize_t rx_pkt_size; 1398 1611 pj_status_t status; 1399 1612 PJ_USE_EXCEPTION; … … 1401 1614 1402 1615 resolver = (pj_dns_resolver *) pj_ioqueue_get_user_data(key); 1616 pj_assert(resolver); 1617 1618 #if PJ_HAS_IPV6 1619 if (key == resolver->udp6_key) { 1620 src_addr = &resolver->udp6_src_addr; 1621 src_addr_len = &resolver->udp6_addr_len; 1622 rx_pkt = resolver->udp6_rx_pkt; 1623 rx_pkt_size = sizeof(resolver->udp6_rx_pkt); 1624 } else 1625 #endif 1626 { 1627 src_addr = &resolver->udp_src_addr; 1628 src_addr_len = &resolver->udp_addr_len; 1629 rx_pkt = resolver->udp_rx_pkt; 1630 rx_pkt_size = sizeof(resolver->udp_rx_pkt); 1631 } 1632 1403 1633 pj_mutex_lock(resolver->mutex); 1404 1634 … … 1412 1642 PJ_LOG(4,(resolver->name.ptr, 1413 1643 "DNS resolver read error from %s:%d: %s", 1414 pj_inet_ntop2(pj_AF_INET(), &resolver->udp_src_addr.sin_addr, 1415 addr, sizeof(addr)), 1416 pj_ntohs(resolver->udp_src_addr.sin_port), 1644 pj_sockaddr_print(src_addr, addr, sizeof(addr), 2), 1645 pj_sockaddr_get_port(src_addr), 1417 1646 errmsg)); 1418 1647 … … 1423 1652 "Received %d bytes DNS response from %s:%d", 1424 1653 (int)bytes_read, 1425 pj_inet_ntop2(pj_AF_INET(), &resolver->udp_src_addr.sin_addr, 1426 addr, sizeof(addr)), 1427 pj_ntohs(resolver->udp_src_addr.sin_port))); 1654 pj_sockaddr_print(src_addr, addr, sizeof(addr), 2), 1655 pj_sockaddr_get_port(src_addr))); 1428 1656 1429 1657 … … 1440 1668 dns_pkt = NULL; 1441 1669 PJ_TRY { 1442 status = pj_dns_parse_packet(pool, r esolver->udp_rx_pkt,1670 status = pj_dns_parse_packet(pool, rx_pkt, 1443 1671 (unsigned)bytes_read, &dns_pkt); 1444 1672 } … … 1449 1677 1450 1678 /* Update nameserver status */ 1451 report_nameserver_status(resolver, &resolver->udp_src_addr, dns_pkt);1679 report_nameserver_status(resolver, src_addr, dns_pkt); 1452 1680 1453 1681 /* Handle parse error */ … … 1458 1686 PJ_LOG(3,(resolver->name.ptr, 1459 1687 "Error parsing DNS response from %s:%d: %s", 1460 pj_inet_ntop2(pj_AF_INET(), &resolver->udp_src_addr.sin_addr, 1461 addr, sizeof(addr)), 1462 pj_ntohs(resolver->udp_src_addr.sin_port), 1688 pj_sockaddr_print(src_addr, addr, sizeof(addr), 2), 1689 pj_sockaddr_get_port(src_addr), 1463 1690 errmsg)); 1464 1691 goto read_next_packet; … … 1472 1699 PJ_LOG(5,(resolver->name.ptr, 1473 1700 "DNS response from %s:%d id=%d discarded", 1474 pj_inet_ntop2(pj_AF_INET(), &resolver->udp_src_addr.sin_addr, 1475 addr, sizeof(addr)), 1476 pj_ntohs(resolver->udp_src_addr.sin_port), 1701 pj_sockaddr_print(src_addr, addr, sizeof(addr), 2), 1702 pj_sockaddr_get_port(src_addr), 1477 1703 (unsigned)dns_pkt->hdr.id)); 1478 1704 goto read_next_packet; … … 1537 1763 pj_pool_release(pool); 1538 1764 } 1539 bytes_read = sizeof(resolver->udp_rx_pkt); 1540 resolver->udp_addr_len = sizeof(resolver->udp_src_addr); 1541 status = pj_ioqueue_recvfrom(resolver->udp_key, op_key, 1542 resolver->udp_rx_pkt, 1543 &bytes_read, PJ_IOQUEUE_ALWAYS_ASYNC, 1544 &resolver->udp_src_addr, 1545 &resolver->udp_addr_len); 1765 1766 status = pj_ioqueue_recvfrom(key, op_key, rx_pkt, &rx_pkt_size, 1767 PJ_IOQUEUE_ALWAYS_ASYNC, 1768 src_addr, src_addr_len); 1769 1546 1770 if (status != PJ_EPENDING) { 1547 1771 char errmsg[PJ_ERR_MSG_SIZE]; … … 1643 1867 PJ_LOG(3,(resolver->name.ptr, " Name servers:")); 1644 1868 for (i=0; i<resolver->ns_count; ++i) { 1645 char addr[PJ_INET _ADDRSTRLEN];1869 char addr[PJ_INET6_ADDRSTRLEN]; 1646 1870 struct nameserver *ns = &resolver->ns[i]; 1647 1871 1648 1872 PJ_LOG(3,(resolver->name.ptr, 1649 1873 " NS %d: %s:%d (state=%s until %ds, rtt=%d ms)", 1650 i, pj_inet_ntop2(pj_AF_INET(), &ns->addr.sin_addr, addr,1651 sizeof(addr)),1652 pj_ ntohs(ns->addr.sin_port),1874 i, 1875 pj_sockaddr_print(&ns->addr, addr, sizeof(addr), 2), 1876 pj_sockaddr_get_port(&ns->addr), 1653 1877 state_names[ns->state], 1654 1878 ns->state_expiry.sec - now.sec,
Note: See TracChangeset
for help on using the changeset viewer.