From: Michael Jerris Date: Fri, 10 Jul 2009 00:39:58 +0000 (+0000) Subject: Tue Jul 7 15:29:27 CDT 2009 Pekka Pessi X-Git-Tag: v1.0.4~212 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e8ee4c18fffd28c4ef6447f2218bb293950903a3;p=thirdparty%2Ffreeswitch.git Tue Jul 7 15:29:27 CDT 2009 Pekka Pessi * nta.c: if NAPTRs has protocols with same preference, select one preferred locally git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@14177 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- diff --git a/libs/sofia-sip/.update b/libs/sofia-sip/.update index aeba066b26..a746706851 100644 --- a/libs/sofia-sip/.update +++ b/libs/sofia-sip/.update @@ -1 +1 @@ -Thu Jul 9 11:14:29 CDT 2009 +Thu Jul 9 19:38:10 CDT 2009 diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/nta.c b/libs/sofia-sip/libsofia-sip-ua/nta/nta.c index 961b9c1031..f6e4a87bf2 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nta/nta.c +++ b/libs/sofia-sip/libsofia-sip-ua/nta/nta.c @@ -9747,6 +9747,8 @@ static void outgoing_graylist(nta_outgoing_t *orq, struct sipdns_query *sq); static int outgoing_query_naptr(nta_outgoing_t *orq, char const *domain); static void outgoing_answer_naptr(sres_context_t *orq, sres_query_t *q, sres_record_t *answers[]); +struct sipdns_tport const *outgoing_naptr_tport(nta_outgoing_t *orq, + sres_record_t *answers[]); static int outgoing_make_srv_query(nta_outgoing_t *orq); static int outgoing_make_a_aaaa_query(nta_outgoing_t *orq); @@ -10229,10 +10231,9 @@ void outgoing_answer_naptr(sres_context_t *orq, sres_query_t *q, sres_record_t *answers[]) { - int i, j, order = -1; + int i, order = -1; size_t rlen; su_home_t *home = msg_home(orq->orq_request); - nta_agent_t *agent = orq->orq_agent; struct sipdns_resolver *sr = orq->orq_resolver; tp_name_t tpn[1]; struct sipdns_query *sq, *selected = NULL, **tail = &selected, **at; @@ -10246,28 +10247,19 @@ void outgoing_answer_naptr(sres_context_t *orq, /* The NAPTR results are sorted first by Order then by Preference */ sres_sort_answers(orq->orq_agent->sa_resolver, answers); + if (sr->sr_tport == NULL) + sr->sr_tport = outgoing_naptr_tport(orq, answers); + for (i = 0; answers && answers[i]; i++) { sres_naptr_record_t const *na = answers[i]->sr_naptr; - struct sipdns_tport const *tport = NULL; uint16_t type; + int valid_tport; if (na->na_record->r_status) continue; if (na->na_record->r_type != sres_type_naptr) continue; - /* RFC 2915 p 4: - * Order - * A 16-bit unsigned integer specifying the order in which the - * NAPTR records MUST be processed to ensure the correct ordering - * of rules. Low numbers are processed before high numbers, and - * once a NAPTR is found whose rule "matches" the target, the - * client MUST NOT consider any NAPTRs with a higher value for - * order (except as noted below for the Flags field). - */ - if (order >= 0 && order != na->na_order) - break; - /* Check if NAPTR matches our target */ if (!su_casenmatch(na->na_services, "SIP+", 4) && !su_casenmatch(na->na_services, "SIPS+", 5)) @@ -10277,36 +10269,29 @@ void outgoing_answer_naptr(sres_context_t *orq, /* Use NAPTR results, don't try extra SRV/A/AAAA records */ sr->sr_use_srv = 0, sr->sr_use_a_aaaa = 0; - if (sr->sr_tport) { - if (su_casematch(na->na_services, sr->sr_tport->service)) - tport = sr->sr_tport; - } - /* Check if we have a transport mathing with service */ - else for (j = 0; sr->sr_tports[j]; j++) { - /* - * Syntax of services is actually more complicated - * but comparing the values in the transport list - * match with those values that make any sense - */ - if (!su_casematch(na->na_services, sr->sr_tports[j]->service)) - continue; - - tpn->tpn_proto = sr->sr_tports[j]->name; - - if (tport_primary_by_name(agent->sa_tports, tpn)) { - tport = sr->sr_tport = sr->sr_tports[j]; - break; - } - } + valid_tport = sr->sr_tport && + su_casematch(na->na_services, sr->sr_tport->service); SU_DEBUG_5(("nta: %s IN NAPTR %u %u \"%s\" \"%s\" \"%s\" %s%s\n", na->na_record->r_name, na->na_order, na->na_prefer, na->na_flags, na->na_services, na->na_regexp, na->na_replace, - tport ? "" : " (not used)")); + order >= 0 && order != na->na_order ? " (out of order)" : + valid_tport ? "" : " (tport not used)")); - if (!tport) + /* RFC 2915 p 4: + * Order + * A 16-bit unsigned integer specifying the order in which the + * NAPTR records MUST be processed to ensure the correct ordering + * of rules. Low numbers are processed before high numbers, and + * once a NAPTR is found whose rule "matches" the target, the + * client MUST NOT consider any NAPTRs with a higher value for + * order (except as noted below for the Flags field). + */ + if (order >= 0 && order != na->na_order) + continue; + if (!valid_tport) continue; /* OK, we found matching NAPTR */ @@ -10336,7 +10321,7 @@ void outgoing_answer_naptr(sres_context_t *orq, sq->sq_weight = 1; sq->sq_type = type; sq->sq_domain = memcpy(sq + 1, na->na_replace, rlen); - sq->sq_proto = tport->name; + sq->sq_proto = sr->sr_tport->name; } sres_free_answers(orq->orq_agent->sa_resolver, answers); @@ -10366,6 +10351,49 @@ void outgoing_answer_naptr(sres_context_t *orq, outgoing_resolve_next(orq); } +/* Find first supported protocol in order and preference */ +struct sipdns_tport const * +outgoing_naptr_tport(nta_outgoing_t *orq, sres_record_t *answers[]) +{ + int i, j, order, pref; + int orders[SIPDNS_TRANSPORTS], prefs[SIPDNS_TRANSPORTS]; + struct sipdns_tport const *tport; + + struct sipdns_resolver *sr = orq->orq_resolver; + + for (j = 0; sr->sr_tports[j]; j++) { + tport = sr->sr_tports[j]; + + orders[j] = 65536, prefs[j] = 65536; + + /* Find transport order */ + for (i = 0; answers && answers[i]; i++) { + sres_naptr_record_t const *na = answers[i]->sr_naptr; + if (na->na_record->r_status) + continue; + if (na->na_record->r_type != sres_type_naptr) + continue; + /* Check if NAPTR matches transport */ + if (!su_casematch(na->na_services, tport->service)) + continue; + orders[j] = na->na_order; + prefs[j] = na->na_prefer; + break; + } + } + + tport = sr->sr_tports[0], order = orders[0], pref = prefs[0]; + + for (j = 1; sr->sr_tports[j]; j++) { + if (orders[j] <= order && prefs[j] < pref) { + tport = sr->sr_tports[j], order = orders[j], pref = prefs[j]; + } + } + + return tport; +} + + /* Query SRV records */ static int outgoing_query_srv(nta_outgoing_t *orq,