summaryrefslogtreecommitdiffstats
path: root/main/asterisk
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2012-01-31 09:07:54 +0200
committerTimo Teräs <timo.teras@iki.fi>2012-01-31 09:08:37 +0200
commit1ca00eb19499a0b605d9dc766565fc7a4e7067ce (patch)
tree69135067587d4c7ee67d9f698a9de364323a8d44 /main/asterisk
parent4d59ce7e0a9d75ecab8839b6c5edb79298e3efd5 (diff)
downloadaports-1ca00eb19499a0b605d9dc766565fc7a4e7067ce.tar.bz2
aports-1ca00eb19499a0b605d9dc766565fc7a4e7067ce.tar.xz
main/asterisk: update ASTERISK-19106 patch
It's now the patch that actually got committed.
Diffstat (limited to 'main/asterisk')
-rw-r--r--main/asterisk/APKBUILD4
-rw-r--r--main/asterisk/ASTERISK-19106.patch287
2 files changed, 173 insertions, 118 deletions
diff --git a/main/asterisk/APKBUILD b/main/asterisk/APKBUILD
index b7e7486e5..309c26e5b 100644
--- a/main/asterisk/APKBUILD
+++ b/main/asterisk/APKBUILD
@@ -2,7 +2,7 @@
# Maintainer: Timo Teras <timo.teras@iki.fi>
pkgname=asterisk
pkgver=10.1.0
-pkgrel=0
+pkgrel=1
pkgdesc="Asterisk: A Module Open Source PBX System"
url="http://www.asterisk.org/"
arch="all"
@@ -167,7 +167,7 @@ b794636266cc573f0dda730fba634567 900-tryinclude.patch
da5a3c500192dee4275aae5235d25f97 ASTERISK-18976.patch
1ddadef41aa7120e168738b6f3ed8917 ASTERISK-18977.patch
bc6713f5434e07b79d3afdd155461d72 ASTERISK-18995.patch
-8190437436de46b3a5a607f56f5af539 ASTERISK-19106.patch
+2581cf79297ebf4ce4a7145f07512c7e ASTERISK-19106.patch
a22bb1d513d026564cb40ec213b1ae7f ASTERISK-19109.patch
74cd25a5638a94ef51e9f4ede2fd28f2 asterisk.initd
ed31d7ba37bcf8b0346dcf8593c395f0 asterisk.confd
diff --git a/main/asterisk/ASTERISK-19106.patch b/main/asterisk/ASTERISK-19106.patch
index 93e9d2d89..d66c4744d 100644
--- a/main/asterisk/ASTERISK-19106.patch
+++ b/main/asterisk/ASTERISK-19106.patch
@@ -1,20 +1,62 @@
-Index: channels/chan_sip.c
-===================================================================
---- a/channels/chan_sip.c (revision 352352)
-+++ b/channels/chan_sip.c (working copy)
-@@ -2883,6 +2883,11 @@
+commit f987e47193c1ce64466663134e5e311742d022d2
+Author: twilson <twilson@f38db490-d61c-443f-a65b-d21fe96a405b>
+Date: Mon Jan 30 23:58:51 2012 +0000
+
+ Re-link peers by IP when dnsmgr changes the IP
+
+ Asterisk's dnsmgr currently takes a pointer to an ast_sockaddr and updates it
+ anytime an address resolves to something different. There are a couple of
+ issues with this. First, the ast_sockaddr is usually the address of an
+ ast_sockaddr inside a refcounted struct and we never bump the refcount of those
+ structs when using dnsmgr. This makes it possible that a refresh could happen
+ after the destructor for that object is called (despite ast_dnsmgr_release
+ being called in that destructor). Second, the module using dnsmgr cannot be
+ aware of an address changing without polling for it in the code. If an action
+ needs to be taken on address update (like re-linking a SIP peer in the
+ peers_by_ip table), then polling for this change negates many of the benefits
+ of having dnsmgr in the first place.
+
+ This patch adds a function to the dnsmgr API that calls an update callback
+ instead of blindly updating the address itself. It also moves calls to
+ ast_dnsmgr_release outside of the destructor functions and into cleanup
+ functions that are called when we no longer need the objects and increments the
+ refcount of the objects using dnsmgr since those objects are stored on the
+ ast_dnsmgr_entry struct. A helper function for returning the proper default SIP
+ port (non-tls vs tls) is also added and used.
+
+ This patch also incorporates changes from a patch posted by Timo Teräs to
+ ASTERISK-19106 for related dnsmgr issues.
+
+ (closes issue ASTERISK-19106)
+
+ Review: https://reviewboard.asterisk.org/r/1691/
+ ........
+
+ Merged revisions 353371 from http://svn.asterisk.org/svn/asterisk/branches/1.8
+ ........
+
+ Merged revisions 353397 from http://svn.asterisk.org/svn/asterisk/branches/10
+
+
+ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@353418 f38db490-d61c-443f-a65b-d21fe96a405b
+
+diff --git a/channels/chan_sip.c b/channels/chan_sip.c
+index e1dfaea..698894f 100644
+--- a/channels/chan_sip.c
++++ b/channels/chan_sip.c
+@@ -2897,6 +2897,11 @@ static int match_and_cleanup_peer_sched(void *peerobj, void *arg, int flags)
if (which == SIP_PEERS_ALL || peer->the_mark) {
peer_sched_cleanup(peer);
+ if (peer->dnsmgr) {
+ ast_dnsmgr_release(peer->dnsmgr);
-+ ao2_t_ref(peer, -1, "Release peer from dnsmgr");
+ peer->dnsmgr = NULL;
++ sip_unref_peer(peer, "Release peer from dnsmgr");
+ }
return CMP_MATCH;
}
return 0;
-@@ -4661,8 +4666,6 @@
+@@ -4681,8 +4686,6 @@ static void sip_destroy_peer(struct sip_peer *peer)
ao2_t_ref(peer->auth, -1, "Removing peer authentication");
peer->auth = NULL;
}
@@ -23,7 +65,7 @@ Index: channels/chan_sip.c
if (peer->socket.tcptls_session) {
ao2_ref(peer->socket.tcptls_session, -1);
-@@ -5401,6 +5404,12 @@
+@@ -5423,6 +5426,12 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
return 0;
}
@@ -36,7 +78,7 @@ Index: channels/chan_sip.c
/*! \brief create address structure from device name
* Or, if peer not found, find it in the global DNS
* returns TRUE (-1) on failure, FALSE on success */
-@@ -5503,9 +5512,7 @@
+@@ -5525,9 +5534,7 @@ static int create_addr(struct sip_pvt *dialog, const char *opeer, struct ast_soc
}
if (!ast_sockaddr_port(&dialog->sa)) {
@@ -47,7 +89,7 @@ Index: channels/chan_sip.c
}
ast_sockaddr_copy(&dialog->recv, &dialog->sa);
return 0;
-@@ -5725,7 +5732,6 @@
+@@ -5747,7 +5754,6 @@ static void sip_registry_destroy(struct sip_registry *reg)
ast_string_field_free_memory(reg);
ast_atomic_fetchadd_int(&regobjs, -1);
@@ -55,7 +97,7 @@ Index: channels/chan_sip.c
ast_free(reg);
}
-@@ -5739,7 +5745,6 @@
+@@ -5761,7 +5767,6 @@ static void sip_subscribe_mwi_destroy(struct sip_subscription_mwi *mwi)
AST_SCHED_DEL(sched, mwi->resub);
ast_string_field_free_memory(mwi);
@@ -63,13 +105,14 @@ Index: channels/chan_sip.c
ast_free(mwi);
}
-@@ -12565,6 +12570,67 @@
+@@ -12721,6 +12726,72 @@ static int sip_subscribe_mwi_do(const void *data)
return 0;
}
+static void on_dns_update_registry(struct ast_sockaddr *old, struct ast_sockaddr *new, void *data)
+{
+ struct sip_registry *reg = data;
++ const char *old_str;
+
+ /* This shouldn't happen, but just in case */
+ if (ast_sockaddr_isnull(new)) {
@@ -80,14 +123,17 @@ Index: channels/chan_sip.c
+ if (!ast_sockaddr_port(new)) {
+ ast_sockaddr_set_port(new, reg->portno);
+ }
-+
-+ ast_debug(1, "Changing registry %s from %s to %s\n", S_OR(reg->peername, reg->hostname), ast_sockaddr_stringify(old), ast_sockaddr_stringify(new));
++
++ old_str = ast_strdupa(ast_sockaddr_stringify(old));
++
++ ast_debug(1, "Changing registry %s from %s to %s\n", S_OR(reg->peername, reg->hostname), old_str, ast_sockaddr_stringify(new));
+ ast_sockaddr_copy(&reg->us, new);
+}
+
+static void on_dns_update_peer(struct ast_sockaddr *old, struct ast_sockaddr *new, void *data)
+{
+ struct sip_peer *peer = data;
++ const char *old_str;
+
+ /* This shouldn't happen, but just in case */
+ if (ast_sockaddr_isnull(new)) {
@@ -95,7 +141,6 @@ Index: channels/chan_sip.c
+ return;
+ }
+
-+ ao2_ref(peer, +1);
+ if (!ast_sockaddr_isnull(&peer->addr)) {
+ ao2_unlink(peers_by_ip, peer);
+ }
@@ -104,19 +149,20 @@ Index: channels/chan_sip.c
+ ast_sockaddr_set_port(new, default_sip_port(peer->socket.type));
+ }
+
-+ ast_debug(1, "Changing peer %s address from %s to %s\n", peer->name, ast_sockaddr_stringify(old), ast_sockaddr_stringify(new));
++ old_str = ast_strdupa(ast_sockaddr_stringify(old));
++ ast_debug(1, "Changing peer %s address from %s to %s\n", peer->name, old_str, ast_sockaddr_stringify(new));
+
+ ao2_lock(peer);
+ ast_sockaddr_copy(&peer->addr, new);
+ ao2_unlock(peer);
+
+ ao2_link(peers_by_ip, peer);
-+ ao2_ref(peer, -1);
+}
+
+static void on_dns_update_mwi(struct ast_sockaddr *old, struct ast_sockaddr *new, void *data)
+{
+ struct sip_subscription_mwi *mwi = data;
++ const char *old_str;
+
+ /* This shouldn't happen, but just in case */
+ if (ast_sockaddr_isnull(new)) {
@@ -124,27 +170,28 @@ Index: channels/chan_sip.c
+ return;
+ }
+
-+ ast_debug(1, "Changing mwi %s from %s to %s\n", mwi->hostname, ast_sockaddr_stringify(old), ast_sockaddr_stringify(new));
++ old_str = ast_strdupa(ast_sockaddr_stringify(old));
++ ast_debug(1, "Changing mwi %s from %s to %s\n", mwi->hostname, old_str, ast_sockaddr_stringify(new));
+ ast_sockaddr_copy(&mwi->us, new);
+}
+
/*! \brief Actually setup an MWI subscription or resubscribe */
static int __sip_subscribe_mwi_do(struct sip_subscription_mwi *mwi)
{
-@@ -12574,7 +12640,11 @@
+@@ -12730,7 +12801,11 @@ static int __sip_subscribe_mwi_do(struct sip_subscription_mwi *mwi)
snprintf(transport, sizeof(transport), "_%s._%s", get_srv_service(mwi->transport), get_srv_protocol(mwi->transport));
mwi->us.ss.ss_family = get_address_family_filter(&bindaddr); /* Filter address family */
- ast_dnsmgr_lookup(mwi->hostname, &mwi->us, &mwi->dnsmgr, sip_cfg.srvlookup ? transport : NULL);
-+ ASTOBJ_REF(mwi); /* Add aref for storing the mwi on the dnsmgr for updates */
-+ ast_dnsmgr_lookup(mwi->hostname, &mwi->us, &mwi->dnsmgr, sip_cfg.srvlookup ? transport : NULL, on_dns_update_mwi, mwi);
++ ASTOBJ_REF(mwi); /* Add a ref for storing the mwi on the dnsmgr for updates */
++ ast_dnsmgr_lookup_cb(mwi->hostname, &mwi->us, &mwi->dnsmgr, sip_cfg.srvlookup ? transport : NULL, on_dns_update_mwi, mwi);
+ if (!mwi->dnsmgr) {
+ ASTOBJ_UNREF(mwi, sip_subscribe_mwi_destroy); /* dnsmgr disabled, remove reference */
+ }
}
/* If we already have a subscription up simply send a resubscription */
-@@ -13255,17 +13325,8 @@
+@@ -13411,17 +13486,8 @@ static int sip_reg_timeout(const void *data)
}
if (r->dnsmgr) {
@@ -162,46 +209,43 @@ Index: channels/chan_sip.c
}
/* If the initial tranmission failed, we may not have an existing dialog,
-@@ -13348,10 +13409,16 @@
- peer = sip_find_peer(r->hostname, NULL, TRUE, FINDPEERS, FALSE, 0);
- snprintf(transport, sizeof(transport), "_%s._%s",get_srv_service(r->transport), get_srv_protocol(r->transport)); /* have to use static sip_get_transport function */
- r->us.ss.ss_family = get_address_family_filter(&bindaddr); /* Filter address family */
-- ast_dnsmgr_lookup(peer ? peer->tohost : r->hostname, &r->us, &r->dnsmgr, sip_cfg.srvlookup ? transport : NULL);
-+ registry_addref(r, "add reg ref for dnsmgr");
-+ ast_dnsmgr_lookup(peer ? peer->tohost : r->hostname, &r->us, &r->dnsmgr, sip_cfg.srvlookup ? transport : NULL, on_dns_update_registry, r);
+@@ -13510,7 +13576,12 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char *
+ * or peer NULL. Since we're only concerned with its existence, we're not going to
+ * bother getting a ref to the proxy*/
+ if (!obproxy_get(r->call, peer)) {
+- ast_dnsmgr_lookup(peer ? peer->tohost : r->hostname, &r->us, &r->dnsmgr, sip_cfg.srvlookup ? transport : NULL);
++ registry_addref(r, "add reg ref for dnsmgr");
++ ast_dnsmgr_lookup_cb(peer ? peer->tohost : r->hostname, &r->us, &r->dnsmgr, sip_cfg.srvlookup ? transport : NULL, on_dns_update_registry, r);
++ if (!r->dnsmgr) {
++ /*dnsmgr refresh disabled, no reference added! */
++ registry_unref(r, "remove reg ref, dnsmgr disabled");
++ }
+ }
if (peer) {
peer = sip_unref_peer(peer, "removing peer ref for dnsmgr_lookup");
- }
-+ if (!r->dnsmgr) {
-+ /* dnsmgr refresh disabled, no reference added! */
-+ registry_unref(r, "remove reg ref, dnsmgr disabled");
-+ }
-+
- }
-
- if (r->call) { /* We have a registration */
-@@ -13380,18 +13447,21 @@
+@@ -13543,18 +13614,21 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char *
}
/* Use port number specified if no SRV record was found */
- if (!ast_sockaddr_port(&r->us) && r->portno) {
- ast_sockaddr_set_port(&r->us, r->portno);
- }
-+ if (!ast_sockaddr_isnull(&r->us)) {
-+ if (!ast_sockaddr_port(&r->us) && r->portno) {
-+ ast_sockaddr_set_port(&r->us, r->portno);
-+ }
-+ /* It is possible that DNS was unavailable at the time the peer was created.
-+ * Here, if we've update the address in the registry via manually calling
-+ * ast_dnsmgr_lookup() above, then we call the same function that dnsmgr would
-+ * call if it was updating a peer's address */
-
+-
- /* It is possible that DNS is unavailable at the time the peer is created. Here, if
- * we've updated the address in the registry, we copy it to the peer so that
- * create_addr() can copy it to the dialog via create_addr_from_peer */
- if ((peer = sip_find_peer(r->hostname, NULL, TRUE, FINDPEERS, FALSE, 0))) {
- if (ast_sockaddr_isnull(&peer->addr) && !(ast_sockaddr_isnull(&r->us))) {
- ast_sockaddr_copy(&peer->addr, &r->us);
++ if (!ast_sockaddr_isnull(&r->us)) {
++ if (!ast_sockaddr_port(&r->us) && r->portno) {
++ ast_sockaddr_set_port(&r->us, r->portno);
++ }
++
++ /* It is possible that DNS was unavailable at the time the peer was created.
++ * Here, if we've updated the address in the registry via manually calling
++ * ast_dnsmgr_lookup_cb() above, then we call the same function that dnsmgr would
++ * call if it was updating a peer's address */
+ if ((peer = sip_find_peer(S_OR(r->peername, r->hostname), NULL, TRUE, FINDPEERS, FALSE, 0))) {
+ if (ast_sockaddr_cmp(&peer->addr, &r->us)) {
+ on_dns_update_peer(&peer->addr, &r->us, peer);
@@ -212,7 +256,7 @@ Index: channels/chan_sip.c
}
/* Find address to hostname */
-@@ -14243,9 +14313,7 @@
+@@ -14392,9 +14466,7 @@ static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, st
peer->portinuri = ast_sockaddr_port(&testsa) ? TRUE : FALSE;
if (!ast_sockaddr_port(&testsa)) {
@@ -223,93 +267,68 @@ Index: channels/chan_sip.c
}
ast_sockaddr_copy(&peer->addr, &testsa);
-@@ -28327,11 +28395,16 @@
+@@ -28679,11 +28751,17 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
snprintf(transport, sizeof(transport), "_%s._%s", get_srv_service(peer->socket.type), get_srv_protocol(peer->socket.type));
peer->addr.ss.ss_family = get_address_family_filter(&bindaddr); /* Filter address family */
- if (ast_dnsmgr_lookup(_srvlookup, &peer->addr, &peer->dnsmgr, sip_cfg.srvlookup && !peer->portinuri ? transport : NULL)) {
-+ ao2_t_ref(peer, +1, "Store peer on dnsmgr"); /* Ref for storing peer (and peer->addr) on the dnsmgr for the callback */
-+ if (ast_dnsmgr_lookup(_srvlookup, &peer->addr, &peer->dnsmgr, sip_cfg.srvlookup && !peer->portinuri ? transport : NULL, on_dns_update_peer, peer)) {
++ if (ast_dnsmgr_lookup_cb(_srvlookup, &peer->addr, &peer->dnsmgr, sip_cfg.srvlookup && !peer->portinuri ? transport : NULL,
++ on_dns_update_peer, sip_ref_peer(peer, "Store peer on dnsmgr"))) {
ast_log(LOG_ERROR, "srvlookup failed for host: %s, on peer %s, removing peer\n", _srvlookup, peer->name);
++ sip_unref_peer(peer, "dnsmgr lookup failed, getting rid of peer dnsmgr ref");
sip_unref_peer(peer, "getting rid of a peer pointer");
return NULL;
}
+ if (!peer->dnsmgr) {
+ /* dnsmgr refresh disabeld, release reference */
-+ ao2_t_ref(peer, -1, "dnsmgr disabled, unref peer");
++ sip_unref_peer(peer, "dnsmgr disabled, unref peer");
+ }
ast_string_field_set(peer, tohost, srvlookup);
-@@ -28549,6 +28622,11 @@
+@@ -28817,7 +28895,7 @@ static void cleanup_all_regs(void)
+ /* First, destroy all outstanding registry calls */
+ /* This is needed, since otherwise active registry entries will not be destroyed */
+ ASTOBJ_CONTAINER_TRAVERSE(&regl, 1, do { /* regl is locked */
+- ASTOBJ_RDLOCK(iterator); /* now regl is locked, and the object is also locked */
++ ASTOBJ_WRLOCK(iterator); /* now regl is locked, and the object is also locked */
+ if (iterator->call) {
+ ast_debug(3, "Destroying active SIP dialog for registry %s@%s\n", iterator->username, iterator->hostname);
+ /* This will also remove references to the registry */
+@@ -28830,6 +28908,11 @@ static void cleanup_all_regs(void)
if (iterator->timeout > -1) {
AST_SCHED_DEL_UNREF(sched, iterator->timeout, registry_unref(iterator, "reg ptr unref from reload config"));
}
+ if (iterator->dnsmgr) {
+ ast_dnsmgr_release(iterator->dnsmgr);
-+ registry_unref(iterator, "reg ptr unref from dnsmgr");
+ iterator->dnsmgr = NULL;
++ registry_unref(iterator, "reg ptr unref from dnsmgr");
+ }
ASTOBJ_UNLOCK(iterator);
} while(0));
-
-@@ -31105,8 +31183,29 @@
- ast_free(default_tls_cfg.capath);
- }
-
-+ ASTOBJ_CONTAINER_TRAVERSE(&regl, 1, do { /* regl is locked */
-+ ASTOBJ_RDLOCK(iterator); /* now regl is locked, and the object is also locked */
-+ if (iterator->dnsmgr) {
-+ ast_dnsmgr_release(iterator->dnsmgr);
-+ registry_unref(iterator, "reg ptr unref from dnsmgr");
-+ iterator->dnsmgr = NULL;
-+ }
-+ ASTOBJ_UNLOCK(iterator);
-+ } while(0));
-+
+ }
+@@ -31496,6 +31579,16 @@ static int unload_module(void)
+ cleanup_all_regs();
ASTOBJ_CONTAINER_DESTROYALL(&regl, sip_registry_destroy);
ASTOBJ_CONTAINER_DESTROY(&regl);
+
+ ASTOBJ_CONTAINER_TRAVERSE(&submwil, 1, do {
-+ ASTOBJ_RDLOCK(iterator);
++ ASTOBJ_WRLOCK(iterator);
+ if (iterator->dnsmgr) {
+ ast_dnsmgr_release(iterator->dnsmgr);
-+ ASTOBJ_UNREF(iterator, sip_subscribe_mwi_destroy);
+ iterator->dnsmgr = NULL;
++ ASTOBJ_UNREF(iterator, sip_subscribe_mwi_destroy);
+ }
+ ASTOBJ_UNLOCK(iterator);
+ } while(0));
-+
ASTOBJ_CONTAINER_DESTROYALL(&submwil, sip_subscribe_mwi_destroy);
ASTOBJ_CONTAINER_DESTROY(&submwil);
-Index: channels/chan_iax2.c
-===================================================================
---- a/channels/chan_iax2.c (revision 352352)
-+++ b/channels/chan_iax2.c (working copy)
-@@ -8587,7 +8587,7 @@
- return -1;
-
- reg->addr.ss.ss_family = AF_INET;
-- if (ast_dnsmgr_lookup(hostname, &reg->addr, &reg->dnsmgr, srvlookup ? "_iax._udp" : NULL) < 0) {
-+ if (ast_dnsmgr_lookup(hostname, &reg->addr, &reg->dnsmgr, srvlookup ? "_iax._udp" : NULL, NULL, NULL) < 0) {
- ast_free(reg);
- return -1;
- }
-@@ -12595,7 +12595,7 @@
- /* Non-dynamic. Make sure we become that way if we're not */
- AST_SCHED_DEL(sched, peer->expire);
- ast_clear_flag64(peer, IAX_DYNAMIC);
-- if (ast_dnsmgr_lookup(v->value, &peer->addr, &peer->dnsmgr, srvlookup ? "_iax._udp" : NULL))
-+ if (ast_dnsmgr_lookup(v->value, &peer->addr, &peer->dnsmgr, srvlookup ? "_iax._udp" : NULL, NULL, NULL))
- return peer_unref(peer);
- if (!ast_sockaddr_port(&peer->addr)) {
- ast_sockaddr_set_port(&peer->addr, IAX_DEFAULT_PORTNO);
-Index: include/asterisk/dnsmgr.h
-===================================================================
---- a/include/asterisk/dnsmgr.h (revision 352352)
-+++ b/include/asterisk/dnsmgr.h (working copy)
-@@ -37,6 +37,8 @@
+diff --git a/include/asterisk/dnsmgr.h b/include/asterisk/dnsmgr.h
+index b62c2a1..07d6268 100644
+--- a/include/asterisk/dnsmgr.h
++++ b/include/asterisk/dnsmgr.h
+@@ -37,6 +37,8 @@ extern "C" {
*/
struct ast_dnsmgr_entry;
@@ -318,20 +337,43 @@ Index: include/asterisk/dnsmgr.h
/*!
* \brief Allocate a new DNS manager entry
*
-@@ -102,7 +104,7 @@
- * \retval non-zero failure
- * \version 1.6.1 result changed from struct in_addr to struct aockaddr_in to store port number
- */
--int ast_dnsmgr_lookup(const char *name, struct ast_sockaddr *result, struct ast_dnsmgr_entry **dnsmgr, const char *service);
-+int ast_dnsmgr_lookup(const char *name, struct ast_sockaddr *result, struct ast_dnsmgr_entry **dnsmgr, const char *service, dns_update_func func, void *data);
+@@ -105,6 +107,31 @@ void ast_dnsmgr_release(struct ast_dnsmgr_entry *entry);
+ int ast_dnsmgr_lookup(const char *name, struct ast_sockaddr *result, struct ast_dnsmgr_entry **dnsmgr, const char *service);
/*!
++ * \brief Allocate and initialize a DNS manager entry, with update callback
++ *
++ * \param name the hostname
++ * \param result The addr which is intended to be updated in the update callback when DNS manager calls it on refresh.
++ * The address family is used as an input parameter to filter the returned addresses.
++ * If it is 0, both IPv4 and IPv6 addresses can be returned.
++ * \param dnsmgr Where to store the allocate DNS manager entry
++ * \param service
++ * \param func The update callback function
++ * The update callback will be called when DNS manager detects that an IP address has been changed.
++ * Instead of updating the addr itself, DNS manager will call this callback function with the old
++ * and new addresses. It is the responsibility of the callback to perform any updates
++ * \param data A pointer to data that will be passed through to the callback function
++ *
++ * \note
++ * This function allocates a new DNS manager entry object, and fills it with
++ * the provided hostname and IP address. This function _does_ force an initial
++ * lookup, so it may block for some period of time.
++ *
++ * \retval 0 success
++ * \retval non-zero failure
++ */
++int ast_dnsmgr_lookup_cb(const char *name, struct ast_sockaddr *result, struct ast_dnsmgr_entry **dnsmgr, const char *service, dns_update_func func, void *data);
++
++/*!
* \brief Force a refresh of a dnsmgr entry
-Index: main/dnsmgr.c
-===================================================================
---- a/main/dnsmgr.c (revision 352352)
-+++ b/main/dnsmgr.c (working copy)
-@@ -58,6 +58,10 @@
+ *
+ * \retval non-zero if the result is different than the previous result
+diff --git a/main/dnsmgr.c b/main/dnsmgr.c
+index d11cd99..7cdcd0c 100644
+--- a/main/dnsmgr.c
++++ b/main/dnsmgr.c
+@@ -58,6 +58,10 @@ struct ast_dnsmgr_entry {
unsigned int family;
/*! Set to 1 if the entry changes */
unsigned int changed:1;
@@ -342,17 +384,17 @@ Index: main/dnsmgr.c
ast_mutex_t lock;
AST_RWLIST_ENTRY(ast_dnsmgr_entry) list;
/*! just 1 here, but we use calloc to allocate the correct size */
-@@ -129,7 +133,7 @@
+@@ -130,7 +134,7 @@ void ast_dnsmgr_release(struct ast_dnsmgr_entry *entry)
ast_free(entry);
}
-int ast_dnsmgr_lookup(const char *name, struct ast_sockaddr *result, struct ast_dnsmgr_entry **dnsmgr, const char *service)
-+int ast_dnsmgr_lookup(const char *name, struct ast_sockaddr *result, struct ast_dnsmgr_entry **dnsmgr, const char *service, dns_update_func func, void *data)
++static int internal_dnsmgr_lookup(const char *name, struct ast_sockaddr *result, struct ast_dnsmgr_entry **dnsmgr, const char *service, dns_update_func func, void *data)
{
unsigned int family;
-@@ -164,6 +168,8 @@
-
+@@ -165,9 +169,21 @@ int ast_dnsmgr_lookup(const char *name, struct ast_sockaddr *result, struct ast_
+
ast_verb(3, "adding dns manager for '%s'\n", name);
*dnsmgr = ast_dnsmgr_get_family(name, result, service, family);
+ (*dnsmgr)->update_func = func;
@@ -360,7 +402,20 @@ Index: main/dnsmgr.c
return !*dnsmgr;
}
-@@ -186,16 +192,19 @@
++int ast_dnsmgr_lookup(const char *name, struct ast_sockaddr *result, struct ast_dnsmgr_entry **dnsmgr, const char *service)
++{
++ return internal_dnsmgr_lookup(name, result, dnsmgr, service, NULL, NULL);
++}
++
++int ast_dnsmgr_lookup_cb(const char *name, struct ast_sockaddr *result, struct ast_dnsmgr_entry **dnsmgr, const char *service, dns_update_func func, void *data)
++{
++ return internal_dnsmgr_lookup(name, result, dnsmgr, service, func, data);
++}
++
+ /*
+ * Refresh a dnsmgr entry
+ */
+@@ -187,16 +203,19 @@ static int dnsmgr_refresh(struct ast_dnsmgr_entry *entry, int verbose)
if (!ast_sockaddr_port(&tmp)) {
ast_sockaddr_set_port(&tmp, ast_sockaddr_port(entry->result));
}