diff options
author | Benny Prijono <bennylp@teluu.com> | 2007-06-11 16:54:10 +0000 |
---|---|---|
committer | Benny Prijono <bennylp@teluu.com> | 2007-06-11 16:54:10 +0000 |
commit | 612be11df187ea3186c0c16c1c245b4f6c9b22b9 (patch) | |
tree | a97a877358f47d29a1390576a30dcbc09da00a54 | |
parent | 3f873c23f1ba23394203a2083e0f76f47266492b (diff) |
Ticket #331: Changed PJSIP DNS SRV resolver to use PJLIB-UTIL DNS SRV resolver
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1358 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r-- | pjsip/src/pjsip/sip_resolve.c | 722 |
1 files changed, 127 insertions, 595 deletions
diff --git a/pjsip/src/pjsip/sip_resolve.c b/pjsip/src/pjsip/sip_resolve.c index 98c3650d..367d3fc4 100644 --- a/pjsip/src/pjsip/sip_resolve.c +++ b/pjsip/src/pjsip/sip_resolve.c @@ -20,6 +20,7 @@ #include <pjsip/sip_transport.h> #include <pjsip/sip_errno.h> #include <pjlib-util/errno.h> +#include <pjlib-util/srv_resolver.h> #include <pj/array.h> #include <pj/assert.h> #include <pj/ctype.h> @@ -35,31 +36,18 @@ struct naptr_target { - pj_str_t target_name; /**< NAPTR target name. */ + pj_str_t res_type; /**< e.g. "_sip._udp" */ + pj_str_t name; /**< Domain name. */ pjsip_transport_type_e type; /**< Transport type. */ unsigned order; /**< Order */ unsigned pref; /**< Preference. */ }; -struct srv_target -{ - pjsip_transport_type_e type; - pj_str_t target_name; - char target_buf[PJ_MAX_HOSTNAME]; - unsigned port; - unsigned priority; - unsigned weight; - unsigned sum; - unsigned addr_cnt; - pj_in_addr addr[ADDR_MAX_COUNT]; -}; - struct query { - char objname[PJ_MAX_OBJ_NAME]; + char *objname; - pjsip_resolver_t *resolver; /**< Resolver SIP instance. */ - pj_dns_type dns_state; /**< DNS type being resolved. */ + pj_dns_type query_type; void *token; pjsip_resolver_callback *cb; pj_dns_async_query *object; @@ -68,30 +56,27 @@ struct query /* Original request: */ struct { pjsip_host_info target; + unsigned def_port; } req; /* NAPTR records: */ unsigned naptr_cnt; struct naptr_target naptr[8]; - - /* SRV records and their resolved IP addresses: */ - unsigned srv_cnt; - struct srv_target srv[PJSIP_MAX_RESOLVED_ADDRESSES]; - - /* Number of hosts in SRV records that the IP address has been resolved */ - unsigned host_resolved; }; struct pjsip_resolver_t { pj_dns_resolver *res; - unsigned job_id; }; -static void dns_callback(void *user_data, - pj_status_t status, - pj_dns_parsed_packet *response); + +static void srv_resolver_cb(void *user_data, + pj_status_t status, + const pj_dns_srv_record *rec); +static void dns_a_callback(void *user_data, + pj_status_t status, + pj_dns_parsed_packet *response); /* @@ -183,7 +168,6 @@ PJ_DEF(void) pjsip_resolve( pjsip_resolver_t *resolver, pj_status_t status = PJ_SUCCESS; int is_ip_addr; struct query *query; - pj_str_t srv_name; pjsip_transport_type_e type = target->type; /* Is it IP address or hostname?. */ @@ -279,9 +263,7 @@ PJ_DEF(void) pjsip_resolve( pjsip_resolver_t *resolver, /* Build the query state */ query = PJ_POOL_ZALLOC_T(pool, struct query); - pj_ansi_snprintf(query->objname, sizeof(query->objname), "rsvjob%X", - resolver->job_id++); - query->resolver = resolver; + query->objname = THIS_FILE; query->token = token; query->cb = cb; query->req.target = *target; @@ -298,60 +280,68 @@ PJ_DEF(void) pjsip_resolve( pjsip_resolver_t *resolver, query->naptr[0].order = 0; query->naptr[0].pref = 0; query->naptr[0].type = type; - query->naptr[0].target_name.ptr = (char*) - pj_pool_alloc(pool, target->addr.host.slen + 12); - - if (type == PJSIP_TRANSPORT_TLS) - pj_strcpy2(&query->naptr[0].target_name, "_sips._tcp."); - else if (type == PJSIP_TRANSPORT_TCP) - pj_strcpy2(&query->naptr[0].target_name, "_sip._tcp."); - else if (type == PJSIP_TRANSPORT_UDP) - pj_strcpy2(&query->naptr[0].target_name, "_sip._udp."); - else { - pj_assert(!"Unknown transport type"); - pj_strcpy2(&query->naptr[0].target_name, "_sip._udp."); - } - pj_strcat(&query->naptr[0].target_name, &target->addr.host); + pj_strdup(pool, &query->naptr[0].name, &target->addr.host); /* Start DNS SRV or A resolution, depending on whether port is specified */ if (target->addr.port == 0) { - query->dns_state = PJ_DNS_TYPE_SRV; - srv_name = query->naptr[0].target_name; + query->query_type = PJ_DNS_TYPE_SRV; + + query->req.def_port = 5060; + + if (type == PJSIP_TRANSPORT_TLS) { + query->naptr[0].res_type = pj_str("_sips._tcp."); + query->req.def_port = 5061; + } else if (type == PJSIP_TRANSPORT_TCP) + query->naptr[0].res_type = pj_str("_sip._tcp."); + else if (type == PJSIP_TRANSPORT_UDP) + query->naptr[0].res_type = pj_str("_sip._udp."); + else { + pj_assert(!"Unknown transport type"); + query->naptr[0].res_type = pj_str("_sip._udp."); + + } } else { /* Otherwise if port is specified, start with A (or AAAA) host * resolution */ - query->dns_state = PJ_DNS_TYPE_A; - - /* Since we don't perform SRV resolution, pretend that we'ee already - * done so by inserting a dummy SRV record. - */ - - query->srv_cnt = 1; - pj_bzero(&query->srv[0], sizeof(query->srv[0])); - query->srv[0].target_name = query->req.target.addr.host; - query->srv[0].type = type; - query->srv[0].port = query->req.target.addr.port; - query->srv[0].priority = 0; - query->srv[0].weight = 0; - - srv_name = query->srv[0].target_name; + query->query_type = PJ_DNS_TYPE_A; + query->naptr[0].res_type.slen = 0; + query->req.def_port = target->addr.port; } /* Start the asynchronous query */ PJ_LOG(5, (query->objname, - "Starting async DNS %s query: target=%.*s, transport=%s, " + "Starting async DNS %s query: target=%.*s%.*s, transport=%s, " "port=%d", - pj_dns_get_type_name(query->dns_state), - (int)srv_name.slen, srv_name.ptr, + pj_dns_get_type_name(query->query_type), + (int)query->naptr[0].res_type.slen, + query->naptr[0].res_type.ptr, + (int)query->naptr[0].name.slen, query->naptr[0].name.ptr, pjsip_transport_get_type_name(target->type), target->addr.port)); - status = pj_dns_resolver_start_query(resolver->res, &srv_name, - query->dns_state, 0, &dns_callback, - query, &query->object); + if (query->query_type == PJ_DNS_TYPE_SRV) { + + status = pj_dns_srv_resolve(&query->naptr[0].name, + &query->naptr[0].res_type, + query->req.def_port, pool, resolver->res, + PJ_TRUE, query, &srv_resolver_cb, NULL); + + } else if (query->query_type == PJ_DNS_TYPE_A) { + + status = pj_dns_resolver_start_query(resolver->res, + &query->naptr[0].name, + PJ_DNS_TYPE_A, 0, + &dns_a_callback, + query, &query->object); + + } else { + pj_assert(!"Unexpected"); + status = PJ_EBUG; + } + if (status != PJ_SUCCESS) goto on_error; @@ -376,562 +366,104 @@ on_error: } } -/* - * The rest of the code should only get compiled when resolver is enabled - */ #if PJSIP_HAS_RESOLVER -#define SWAP(type,ptr1,ptr2) if (ptr1 != ptr2) { \ - type tmp; \ - pj_memcpy(&tmp, ptr1, sizeof(type)); \ - pj_memcpy(ptr1, ptr2, sizeof(type)); \ - (ptr1)->target_name.ptr = (ptr1)->target_buf; \ - pj_memcpy(ptr2, &tmp, sizeof(type)); \ - (ptr2)->target_name.ptr = (ptr2)->target_buf; \ - } else {} - -/* Build server entries in the query based on received SRV response */ -static void build_server_entries(struct query *query, - pj_dns_parsed_packet *response) +/* + * This callback is called when target is resolved with DNS A query. + */ +static void dns_a_callback(void *user_data, + pj_status_t status, + pj_dns_parsed_packet *pkt) { + struct query *query = (struct query*) user_data; + pjsip_server_addresses srv; + pj_dns_a_record rec; unsigned i; - unsigned naptr_id; - - /* Find NAPTR target which corresponds to this SRV target */ - for (naptr_id=0; naptr_id < query->naptr_cnt; ++naptr_id) { - if (pj_stricmp(&query->naptr[naptr_id].target_name, - &response->ans[0].name)==0) - break; - } - if (naptr_id == query->naptr_cnt) { - PJ_LOG(4,(query->objname, - "Unable to find NAPTR record for SRV name %.*s!", - (int)response->ans[0].name.slen, - response->ans[0].name.ptr)); - return; - } + rec.addr_count = 0; - /* Save the Resource Records in DNS answer into SRV targets. */ - query->srv_cnt = 0; - for (i=0; i<response->hdr.anscount && - query->srv_cnt < PJSIP_MAX_RESOLVED_ADDRESSES; ++i) - { - pj_dns_parsed_rr *rr = &response->ans[i]; - struct srv_target *srv = &query->srv[query->srv_cnt]; - - if (rr->type != PJ_DNS_TYPE_SRV) { - PJ_LOG(4,(query->objname, - "Received non SRV answer for SRV query!")); - continue; - } - - if (rr->rdata.srv.target.slen > PJ_MAX_HOSTNAME) { - PJ_LOG(4,(query->objname, "Hostname is too long!")); - continue; - } - - /* Build the SRV entry for RR */ - pj_bzero(srv, sizeof(*srv)); - pj_memcpy(srv->target_buf, rr->rdata.srv.target.ptr, - rr->rdata.srv.target.slen); - srv->target_name.ptr = srv->target_buf; - srv->target_name.slen = rr->rdata.srv.target.slen; - srv->type = query->naptr[naptr_id].type; - srv->port = rr->rdata.srv.port; - srv->priority = rr->rdata.srv.prio; - srv->weight = rr->rdata.srv.weight; - - ++query->srv_cnt; + /* Parse the response */ + if (status == PJ_SUCCESS) { + status = pj_dns_parse_a_response(pkt, &rec); } - /* First pass: - * order the entries based on priority. - */ - for (i=0; i<query->srv_cnt-1; ++i) { - unsigned min = i, j; - for (j=i+1; j<query->srv_cnt; ++j) { - if (query->srv[j].priority < query->srv[min].priority) - min = j; - } - SWAP(struct srv_target, &query->srv[i], &query->srv[min]); - } - - /* Second pass: - * pick one host among hosts with the same priority, according - * to its weight. The idea is when one server fails, client should - * contact the next server with higher priority rather than contacting - * server with the same priority as the failed one. - * - * The algorithm for selecting server among servers with the same - * priority is described in RFC 2782. - */ - for (i=0; i<query->srv_cnt; ++i) { - unsigned j, count=1, sum; - - /* Calculate running sum for servers with the same priority */ - sum = query->srv[i].sum = query->srv[i].weight; - for (j=i+1; j<query->srv_cnt && - query->srv[j].priority == query->srv[i].priority; ++j) - { - sum += query->srv[j].weight; - query->srv[j].sum = sum; - ++count; - } - - if (count > 1) { - unsigned r; - - /* Elect one random number between zero and the total sum of - * weight (inclusive). - */ - r = pj_rand() % (sum + 1); - - /* Select the first server which running sum is greater than or - * equal to the random number. - */ - for (j=i; j<i+count; ++j) { - if (query->srv[j].sum >= r) - break; - } - - /* Must have selected one! */ - pj_assert(j != i+count); - - /* Put this entry in front (of entries with same priority) */ - SWAP(struct srv_target, &query->srv[i], &query->srv[j]); + if (status != PJ_SUCCESS) { + char errmsg[PJ_ERR_MSG_SIZE]; - /* Remove all other entries (of the same priority) */ - while (count > 1) { - pj_array_erase(query->srv, sizeof(struct srv_target), - query->srv_cnt, i+1); - --count; - --query->srv_cnt; - } - } - } + /* Log error */ + pj_strerror(status, errmsg, sizeof(errmsg)); + PJ_LOG(4,(query->objname, "DNS A record resolution failed: %s", + errmsg)); - /* Since we've been moving around SRV entries, update the pointers - * in target_name. - */ - for (i=0; i<query->srv_cnt; ++i) { - query->srv[i].target_name.ptr = query->srv[i].target_buf; + /* Call the callback */ + (*query->cb)(status, query->token, NULL); + return; } - /* Check for Additional Info section if A records are available, and - * fill in the IP address (so that we won't need to resolve the A - * record with another DNS query). - */ - for (i=0; i<response->hdr.arcount; ++i) { - pj_dns_parsed_rr *rr = &response->arr[i]; - unsigned j; - - if (rr->type != PJ_DNS_TYPE_A) - continue; - - /* Yippeaiyee!! There is an "A" record! - * Update the IP address of the corresponding SRV record. - */ - for (j=0; j<query->srv_cnt; ++j) { - if (pj_stricmp(&rr->name, &query->srv[j].target_name)==0) { - unsigned cnt = query->srv[j].addr_cnt; - query->srv[j].addr[cnt].s_addr = rr->rdata.a.ip_addr.s_addr; - ++query->srv[j].addr_cnt; - ++query->host_resolved; - break; - } - } - - /* Not valid message; SRV entry might have been deleted in - * server selection process. - */ - /* - if (j == query->srv_cnt) { - PJ_LOG(4,(query->objname, - "Received DNS SRV answer with A record, but " - "couldn't find matching name (name=%.*s)", - (int)rr->name.slen, - rr->name.ptr)); - } - */ + /* Build server addresses and call callback */ + srv.count = 0; + for (i=0; i<rec.addr_count; ++i) { + srv.entry[srv.count].type = query->naptr[0].type; + srv.entry[srv.count].priority = 0; + srv.entry[srv.count].weight = 0; + srv.entry[srv.count].addr_len = sizeof(pj_sockaddr_in); + pj_sockaddr_in_init(&srv.entry[srv.count].addr.ipv4, + 0, (pj_uint16_t)query->req.def_port); + srv.entry[srv.count].addr.ipv4.sin_addr.s_addr = + rec.addr[i].s_addr; + + ++srv.count; } - /* Rescan again the name specified in the SRV record to see if IP - * address is specified as the target name (unlikely, but well, who - * knows..). - */ - for (i=0; i<query->srv_cnt; ++i) { - pj_in_addr addr; - - if (query->srv[i].addr_cnt != 0) { - /* IP address already resolved */ - continue; - } - - if (pj_inet_aton(&query->srv[i].target_name, &addr) != 0) { - query->srv[i].addr[query->srv[i].addr_cnt++] = addr; - ++query->host_resolved; - } - } - - /* Print resolved entries to the log */ - PJ_LOG(5,(query->objname, - "SRV query for %.*s completed, " - "%d of %d total entries selected%c", - (int)query->naptr[naptr_id].target_name.slen, - query->naptr[naptr_id].target_name.ptr, - query->srv_cnt, - response->hdr.anscount, - (query->srv_cnt ? ':' : ' '))); - - for (i=0; i<query->srv_cnt; ++i) { - const char *addr; - - if (query->srv[i].addr_cnt != 0) - addr = pj_inet_ntoa(query->srv[i].addr[0]); - else - addr = "-"; - - PJ_LOG(5,(query->objname, - " %d: SRV %d %d %d %.*s (%s)", - i, query->srv[i].priority, - query->srv[i].weight, - query->srv[i].port, - (int)query->srv[i].target_name.slen, - query->srv[i].target_name.ptr, - addr)); - } + /* Call the callback */ + (*query->cb)(PJ_SUCCESS, query->token, &srv); } -/* Start DNS A record queries for all SRV records in the query structure */ -static pj_status_t resolve_hostnames(struct query *query) -{ - unsigned i; - pj_status_t err=PJ_SUCCESS, status; - - query->dns_state = PJ_DNS_TYPE_A; - for (i=0; i<query->srv_cnt; ++i) { - PJ_LOG(5, (query->objname, - "Starting async DNS A query for %.*s", - (int)query->srv[i].target_name.slen, - query->srv[i].target_name.ptr)); - - status = pj_dns_resolver_start_query(query->resolver->res, - &query->srv[i].target_name, - PJ_DNS_TYPE_A, 0, - &dns_callback, - query, NULL); - if (status != PJ_SUCCESS) { - query->host_resolved++; - err = status; - } - } - - return (query->host_resolved == query->srv_cnt) ? err : PJ_SUCCESS; -} - -/* - * This callback is called by PJLIB-UTIL DNS resolver when asynchronous - * query has completed (successfully or with error). - */ -static void dns_callback(void *user_data, - pj_status_t status, - pj_dns_parsed_packet *pkt) +/* Callback to be called by DNS SRV resolution */ +static void srv_resolver_cb(void *user_data, + pj_status_t status, + const pj_dns_srv_record *rec) { struct query *query = (struct query*) user_data; + pjsip_server_addresses srv; unsigned i; - /* Proceed to next stage */ - - if (query->dns_state == PJ_DNS_TYPE_SRV) { - - /* We are getting SRV response */ - - if (status == PJ_SUCCESS && pkt->hdr.anscount != 0) { - /* Got SRV response, build server entry. If A records are available - * in additional records section of the DNS response, save them too. - */ - build_server_entries(query, pkt); - - } else if (status != PJ_SUCCESS) { - char errmsg[PJ_ERR_MSG_SIZE]; - unsigned naptr_id; - - /* Update query last error */ - query->last_error = status; - - /* Find which NAPTR target has not got SRV records */ - for (naptr_id=0; naptr_id < query->naptr_cnt; ++naptr_id) { - for (i=0; i<query->srv_cnt; ++i) { - if (query->srv[i].type == query->naptr[naptr_id].type) - break; - } - if (i == query->srv_cnt) - break; - } - if (naptr_id == query->naptr_cnt) { - /* Strangely all NAPTR records seem to already have SRV - * records! This is quite unexpected, by anyway lets set - * the naptr_id to zero just in case. - */ - pj_assert(!"Strange"); - naptr_id = 0; - - } - - pj_strerror(status, errmsg, sizeof(errmsg)); - PJ_LOG(4,(query->objname, - "DNS SRV resolution failed for %.*s: %s", - (int)query->naptr[naptr_id].target_name.slen, - query->naptr[naptr_id].target_name.ptr, - errmsg)); - } - - /* If we can't build SRV record, assume the original target is - * an A record. - */ - if (query->srv_cnt == 0) { - /* Looks like we aren't getting any SRV responses. - * Resolve the original target as A record by creating a - * single "dummy" srv record and start the hostname resolution. - */ - unsigned naptr_id; - - /* Find which NAPTR target has not got SRV records */ - for (naptr_id=0; naptr_id < query->naptr_cnt; ++naptr_id) { - for (i=0; i<query->srv_cnt; ++i) { - if (query->srv[i].type == query->naptr[naptr_id].type) - break; - } - if (i == query->srv_cnt) - break; - } - if (naptr_id == query->naptr_cnt) { - /* Strangely all NAPTR records seem to already have SRV - * records! This is quite unexpected, by anyway lets set - * the naptr_id to zero just in case. - */ - pj_assert(!"Strange"); - naptr_id = 0; - - } - - PJ_LOG(4, (query->objname, - "DNS SRV resolution failed for %.*s, trying " - "resolving A record for %.*s", - (int)query->naptr[naptr_id].target_name.slen, - query->naptr[naptr_id].target_name.ptr, - (int)query->req.target.addr.host.slen, - query->req.target.addr.host.ptr)); - - /* Create a "dummy" srv record using the original target */ - i = query->srv_cnt++; - pj_bzero(&query->srv[i], sizeof(query->srv[i])); - query->srv[i].target_name = query->req.target.addr.host; - query->srv[i].type = query->naptr[naptr_id].type; - query->srv[i].priority = 0; - query->srv[i].weight = 0; - - query->srv[i].port = query->req.target.addr.port; - if (query->srv[i].port == 0) { - query->srv[i].port = (pj_uint16_t) - pjsip_transport_get_default_port_for_type(query->srv[i].type); - } - } - - - /* Resolve server hostnames (DNS A record) for hosts which don't have - * A record yet. - */ - if (query->host_resolved != query->srv_cnt) { - status = resolve_hostnames(query); - if (status != PJ_SUCCESS) - goto on_error; - - /* Must return now. Callback may have been called and query - * may have been destroyed. - */ - return; - } - - } else if (query->dns_state == PJ_DNS_TYPE_A) { - - /* Check that we really have answer */ - if (status==PJ_SUCCESS && pkt->hdr.anscount != 0) { - - unsigned srv_idx; - - /* Update IP address of the corresponding hostname */ - for (srv_idx=0; srv_idx<query->srv_cnt; ++srv_idx) { - if (pj_stricmp(&pkt->ans[0].name, - &query->srv[srv_idx].target_name)==0) - { - break; - } - } - - if (srv_idx == query->srv_cnt) { - PJ_LOG(4,(query->objname, - "Received answer to DNS A request with no matching " - "SRV record! The unknown name is %.*s", - (int)pkt->ans[0].name.slen, pkt->ans[0].name.ptr)); - } else { - int ans_idx = -1; - unsigned k, j; - pj_str_t cname = { NULL, 0 }; - - /* Find the first DNS A record in the answer while processing - * the CNAME info found in the response. - */ - for (k=0; k < pkt->hdr.anscount; ++k) { - - pj_dns_parsed_rr *rr = &pkt->ans[k]; - - if (rr->type == PJ_DNS_TYPE_A && - (cname.slen == 0 || pj_stricmp(&rr->name, &cname)==0)) - { - if (ans_idx == -1) - ans_idx = k; - - } else if (rr->type == PJ_DNS_TYPE_CNAME && - pj_stricmp(&query->srv[srv_idx].target_name, - &rr->name)==0) - { - cname = rr->rdata.cname.name; - } - } - - if (ans_idx == -1) { - /* There's no DNS A answer! */ - PJ_LOG(5,(query->objname, - "No DNS A record in response!")); - status = PJLIB_UTIL_EDNSNOANSWERREC; - goto on_error; - } - - query->srv[srv_idx].addr[query->srv[srv_idx].addr_cnt++].s_addr = - pkt->ans[ans_idx].rdata.a.ip_addr.s_addr; - - PJ_LOG(5,(query->objname, - "DNS A for %.*s: %s", - (int)query->srv[srv_idx].target_name.slen, - query->srv[srv_idx].target_name.ptr, - pj_inet_ntoa(pkt->ans[ans_idx].rdata.a.ip_addr))); - - /* Check for multiple IP addresses */ - for (j=ans_idx+1; j<pkt->hdr.anscount && - query->srv[srv_idx].addr_cnt < ADDR_MAX_COUNT; ++j) - { - query->srv[srv_idx].addr[query->srv[srv_idx].addr_cnt++].s_addr = - pkt->ans[j].rdata.a.ip_addr.s_addr; - - PJ_LOG(5,(query->objname, - "Additional DNS A for %.*s: %s", - (int)query->srv[srv_idx].target_name.slen, - query->srv[srv_idx].target_name.ptr, - pj_inet_ntoa(pkt->ans[j].rdata.a.ip_addr))); - } - } - - } else if (status != PJ_SUCCESS) { - char errmsg[PJ_ERR_MSG_SIZE]; - - /* Update last error */ - query->last_error = status; - - /* Log error */ - pj_strerror(status, errmsg, sizeof(errmsg)); - PJ_LOG(4,(query->objname, "DNS A record resolution failed: %s", - errmsg)); - } + if (status != PJ_SUCCESS) { + char errmsg[PJ_ERR_MSG_SIZE]; - ++query->host_resolved; + /* Log error */ + pj_strerror(status, errmsg, sizeof(errmsg)); + PJ_LOG(4,(query->objname, "DNS A record resolution failed: %s", + errmsg)); - } else { - pj_assert(!"Unexpected state!"); - query->last_error = status = PJ_EINVALIDOP; - goto on_error; + /* Call the callback */ + (*query->cb)(status, query->token, NULL); + return; } - /* Check if all hosts have been resolved */ - if (query->host_resolved == query->srv_cnt) { - /* Got all answers, build server addresses */ - pjsip_server_addresses svr_addr; - - svr_addr.count = 0; - for (i=0; i<query->srv_cnt; ++i) { - unsigned j; - - /* Do we have IP address for this server? */ - /* This log is redundant really. - if (query->srv[i].addr_cnt == 0) { - PJ_LOG(5,(query->objname, - " SRV target %.*s:%d does not have IP address!", - (int)query->srv[i].target_name.slen, - query->srv[i].target_name.ptr, - query->srv[i].port)); - continue; - } - */ - - for (j=0; j<query->srv[i].addr_cnt; ++j) { - unsigned idx = svr_addr.count; - pj_sockaddr_in *addr; - - svr_addr.entry[idx].type = query->srv[i].type; - svr_addr.entry[idx].priority = query->srv[i].priority; - svr_addr.entry[idx].weight = query->srv[i].weight; - svr_addr.entry[idx].addr_len = sizeof(pj_sockaddr_in); - - addr = (pj_sockaddr_in*)&svr_addr.entry[idx].addr; - pj_bzero(addr, sizeof(pj_sockaddr_in)); - addr->sin_family = PJ_AF_INET; - addr->sin_addr = query->srv[i].addr[j]; - addr->sin_port = pj_htons((pj_uint16_t)query->srv[i].port); - - ++svr_addr.count; - } - } - - PJ_LOG(5,(query->objname, - "Server resolution complete, %d server entry(s) found", - svr_addr.count)); - + /* Build server addresses and call callback */ + srv.count = 0; + for (i=0; i<rec->count; ++i) { + unsigned j; - if (svr_addr.count > 0) - status = PJ_SUCCESS; - else { - status = query->last_error; - if (status == PJ_SUCCESS) - status = PJLIB_UTIL_EDNSNOANSWERREC; + for (j=0; j<rec->entry[i].server.addr_count; ++j) { + srv.entry[srv.count].type = query->naptr[0].type; + srv.entry[srv.count].priority = rec->entry[i].priority; + srv.entry[srv.count].weight = rec->entry[i].weight; + srv.entry[srv.count].addr_len = sizeof(pj_sockaddr_in); + pj_sockaddr_in_init(&srv.entry[srv.count].addr.ipv4, + 0, (pj_uint16_t)rec->entry[i].port); + srv.entry[srv.count].addr.ipv4.sin_addr.s_addr = + rec->entry[i].server.addr[j].s_addr; + + ++srv.count; } - - /* Call the callback */ - (*query->cb)(status, query->token, &svr_addr); } - - return; - -on_error: - /* Check for failure */ - if (status != PJ_SUCCESS) { - char errmsg[PJ_ERR_MSG_SIZE]; - PJ_LOG(4,(query->objname, - "DNS %s record resolution error for '%.*s'." - " Err=%d (%s)", - pj_dns_get_type_name(query->dns_state), - (int)query->req.target.addr.host.slen, - query->req.target.addr.host.ptr, - status, - pj_strerror(status,errmsg,sizeof(errmsg)).ptr)); - (*query->cb)(status, query->token, NULL); - return; - } + /* Call the callback */ + (*query->cb)(PJ_SUCCESS, query->token, &srv); } #endif /* PJSIP_HAS_RESOLVER */ - - |