[Asterisk-code-review] astobj2: Eliminate usage of legacy container allocation macros. (asterisk[16])
George Joseph
asteriskteam at digium.com
Wed Oct 24 08:30:57 CDT 2018
George Joseph has submitted this change and it was merged. ( https://gerrit.asterisk.org/10504 )
Change subject: astobj2: Eliminate usage of legacy container allocation macros.
......................................................................
astobj2: Eliminate usage of legacy container allocation macros.
These macros have been documented as legacy for a long time but are
still used in new code because they exist. Remove all references to:
* ao2_container_alloc_options
* ao2_t_container_alloc_options
* ao2_t_container_alloc
These macro's are still available for use but only in modules. Only
ao2_container_alloc remains due to it's use in over 100 places.
Change-Id: I1a26258b5bf3deb081aaeed11a0baa175c933c7a
---
M channels/chan_sip.c
M include/asterisk/astobj2.h
M main/bridge.c
M main/bucket.c
M main/ccss.c
M main/channel.c
M main/codec.c
M main/features_config.c
M main/format.c
M main/format_cache.c
M main/media_cache.c
M main/pbx.c
M main/pickup.c
M main/sorcery.c
M res/res_musiconhold.c
M res/res_pjsip_notify.c
M res/res_pjsip_outbound_publish.c
M res/res_sorcery_memory_cache.c
M res/res_srtp.c
M tests/test_astobj2.c
20 files changed, 86 insertions(+), 54 deletions(-)
Approvals:
Richard Mudgett: Looks good to me, but someone else must approve
George Joseph: Looks good to me, approved; Approved for Submit
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index c8a2dea..c54789a 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -35360,12 +35360,18 @@
/* the fact that ao2_containers can't resize automatically is a major worry! */
/* if the number of objects gets above MAX_XXX_BUCKETS, things will slow down */
- peers = ao2_t_container_alloc(HASH_PEER_SIZE, peer_hash_cb, peer_cmp_cb, "allocate peers");
- peers_by_ip = ao2_t_container_alloc(HASH_PEER_SIZE, peer_iphash_cb, NULL, "allocate peers_by_ip");
- dialogs = ao2_t_container_alloc(HASH_DIALOG_SIZE, dialog_hash_cb, dialog_cmp_cb, "allocate dialogs");
- dialogs_needdestroy = ao2_t_container_alloc(1, NULL, NULL, "allocate dialogs_needdestroy");
- dialogs_rtpcheck = ao2_t_container_alloc(HASH_DIALOG_SIZE, dialog_hash_cb, dialog_cmp_cb, "allocate dialogs for rtpchecks");
- threadt = ao2_t_container_alloc(HASH_DIALOG_SIZE, threadt_hash_cb, threadt_cmp_cb, "allocate threadt table");
+ peers = ao2_t_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, HASH_PEER_SIZE,
+ peer_hash_cb, NULL, peer_cmp_cb, "allocate peers");
+ peers_by_ip = ao2_t_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, HASH_PEER_SIZE,
+ peer_iphash_cb, NULL, NULL, "allocate peers_by_ip");
+ dialogs = ao2_t_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, HASH_DIALOG_SIZE,
+ dialog_hash_cb, NULL, dialog_cmp_cb, "allocate dialogs");
+ dialogs_needdestroy = ao2_t_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, 1,
+ NULL, NULL, NULL, "allocate dialogs_needdestroy");
+ dialogs_rtpcheck = ao2_t_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, HASH_DIALOG_SIZE,
+ dialog_hash_cb, NULL, dialog_cmp_cb, "allocate dialogs for rtpchecks");
+ threadt = ao2_t_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, HASH_DIALOG_SIZE,
+ threadt_hash_cb, NULL, threadt_cmp_cb, "allocate threadt table");
if (!peers || !peers_by_ip || !dialogs || !dialogs_needdestroy || !dialogs_rtpcheck
|| !threadt) {
ast_log(LOG_ERROR, "Unable to create primary SIP container(s)\n");
@@ -35379,7 +35385,8 @@
}
ast_format_cap_append_by_type(sip_tech.capabilities, AST_MEDIA_TYPE_AUDIO);
- registry_list = ao2_t_container_alloc(HASH_REGISTRY_SIZE, registry_hash_cb, registry_cmp_cb, "allocate registry_list");
+ registry_list = ao2_t_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, HASH_REGISTRY_SIZE,
+ registry_hash_cb, NULL, registry_cmp_cb, "allocate registry_list");
subscription_mwi_list = ao2_t_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX,
AO2_CONTAINER_ALLOC_OPT_INSERT_BEGIN, NULL, NULL, "allocate subscription_mwi_list");
diff --git a/include/asterisk/astobj2.h b/include/asterisk/astobj2.h
index 8e3a105..2910304 100644
--- a/include/asterisk/astobj2.h
+++ b/include/asterisk/astobj2.h
@@ -1298,6 +1298,7 @@
struct ao2_container;
/*!
+ * \deprecated
* \brief Allocate and initialize a hash container with the desired number of buckets.
*
* \details
@@ -1315,16 +1316,20 @@
* \note Destructor is set implicitly.
* \note This is legacy container creation that is mapped to the new method.
*/
+#define ao2_container_alloc(n_buckets, hash_fn, cmp_fn) \
+ ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, (n_buckets), (hash_fn), NULL, (cmp_fn))
+#ifndef AST_IN_CORE
+/* These macros are removed from Asterisk 17. They are still available to modules
+ * but should only be used by third party modules that have not been updated. */
#define ao2_t_container_alloc_options(options, n_buckets, hash_fn, cmp_fn, tag) \
ao2_t_container_alloc_hash((options), 0, (n_buckets), (hash_fn), NULL, (cmp_fn), (tag))
#define ao2_container_alloc_options(options, n_buckets, hash_fn, cmp_fn) \
ao2_container_alloc_hash((options), 0, (n_buckets), (hash_fn), NULL, (cmp_fn))
#define ao2_t_container_alloc(n_buckets, hash_fn, cmp_fn, tag) \
- ao2_t_container_alloc_options(AO2_ALLOC_OPT_LOCK_MUTEX, (n_buckets), (hash_fn), (cmp_fn), (tag))
-#define ao2_container_alloc(n_buckets, hash_fn, cmp_fn) \
- ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_MUTEX, (n_buckets), (hash_fn), (cmp_fn))
+ ao2_t_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, (n_buckets), (hash_fn), NULL, (cmp_fn), (tag))
+#endif
/*!
* \brief Allocate and initialize a hash container with the desired number of buckets.
diff --git a/main/bridge.c b/main/bridge.c
index 2b347fd..db49180 100644
--- a/main/bridge.c
+++ b/main/bridge.c
@@ -4068,8 +4068,8 @@
struct ao2_container *channels;
struct ast_bridge_channel *iter;
- channels = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK,
- 13, channel_hash, channel_cmp);
+ channels = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,
+ 13, channel_hash, NULL, channel_cmp);
if (!channels) {
return NULL;
}
diff --git a/main/bucket.c b/main/bucket.c
index 07cd016..8f6eafa 100644
--- a/main/bucket.c
+++ b/main/bucket.c
@@ -649,8 +649,8 @@
return NULL;
}
- file->metadata = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, METADATA_BUCKETS,
- ast_bucket_metadata_hash_fn, ast_bucket_metadata_cmp_fn);
+ file->metadata = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, METADATA_BUCKETS,
+ ast_bucket_metadata_hash_fn, NULL, ast_bucket_metadata_cmp_fn);
if (!file->metadata) {
return NULL;
}
@@ -954,8 +954,8 @@
{
ast_register_cleanup(&bucket_cleanup);
- schemes = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, SCHEME_BUCKETS,
- ast_bucket_scheme_hash_fn, ast_bucket_scheme_cmp_fn);
+ schemes = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_RWLOCK, 0, SCHEME_BUCKETS,
+ ast_bucket_scheme_hash_fn, NULL, ast_bucket_scheme_cmp_fn);
if (!schemes) {
ast_log(LOG_ERROR, "Failed to create container for Bucket schemes\n");
return -1;
diff --git a/main/ccss.c b/main/ccss.c
index 9cf16e3..5758574 100644
--- a/main/ccss.c
+++ b/main/ccss.c
@@ -4649,14 +4649,19 @@
{
int res;
- if (!(cc_core_instances = ao2_t_container_alloc(CC_CORE_INSTANCES_BUCKETS,
- cc_core_instance_hash_fn, cc_core_instance_cmp_fn,
- "Create core instance container"))) {
+ cc_core_instances = ao2_t_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0,
+ CC_CORE_INSTANCES_BUCKETS,
+ cc_core_instance_hash_fn, NULL, cc_core_instance_cmp_fn,
+ "Create core instance container");
+ if (!cc_core_instances) {
return AST_MODULE_LOAD_FAILURE;
}
- if (!(generic_monitors = ao2_t_container_alloc(CC_CORE_INSTANCES_BUCKETS,
- generic_monitor_instance_list_hash_fn, generic_monitor_instance_list_cmp_fn,
- "Create generic monitor container"))) {
+
+ generic_monitors = ao2_t_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0,
+ CC_CORE_INSTANCES_BUCKETS,
+ generic_monitor_instance_list_hash_fn, NULL, generic_monitor_instance_list_cmp_fn,
+ "Create generic monitor container");
+ if (!generic_monitors) {
return AST_MODULE_LOAD_FAILURE;
}
if (!(cc_core_taskprocessor = ast_taskprocessor_get("CCSS_core", TPS_REF_DEFAULT))) {
diff --git a/main/channel.c b/main/channel.c
index 2bacfa4..a72439c 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -7536,8 +7536,8 @@
return NULL;
}
- namedgroups = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 19,
- namedgroup_hash_cb, namedgroup_cmp_cb);
+ namedgroups = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, 19,
+ namedgroup_hash_cb, NULL, namedgroup_cmp_cb);
if (!namedgroups) {
return NULL;
}
diff --git a/main/codec.c b/main/codec.c
index d6de072..32350f1 100644
--- a/main/codec.c
+++ b/main/codec.c
@@ -248,8 +248,8 @@
int ast_codec_init(void)
{
- codecs = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, CODEC_BUCKETS,
- ast_codec_hash_fn, codec_cmp);
+ codecs = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_RWLOCK, 0, CODEC_BUCKETS,
+ ast_codec_hash_fn, NULL, codec_cmp);
if (!codecs) {
return -1;
}
diff --git a/main/features_config.c b/main/features_config.c
index f116e89..c74d849 100644
--- a/main/features_config.c
+++ b/main/features_config.c
@@ -759,8 +759,8 @@
return NULL;
}
- cfg->featuregroups = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 11, featuregroup_hash,
- featuregroup_cmp);
+ cfg->featuregroups = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, 11,
+ featuregroup_hash, NULL, featuregroup_cmp);
if (!cfg->featuregroups) {
return NULL;
}
diff --git a/main/format.c b/main/format.c
index 5ba9ffe..f0da43c 100644
--- a/main/format.c
+++ b/main/format.c
@@ -76,8 +76,8 @@
int ast_format_init(void)
{
- interfaces = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, FORMAT_INTERFACE_BUCKETS,
- format_interface_hash_fn, format_interface_cmp_fn);
+ interfaces = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_RWLOCK, 0,
+ FORMAT_INTERFACE_BUCKETS, format_interface_hash_fn, NULL, format_interface_cmp_fn);
if (!interfaces) {
return -1;
}
diff --git a/main/format_cache.c b/main/format_cache.c
index db0d9b9..95ad5ea 100644
--- a/main/format_cache.c
+++ b/main/format_cache.c
@@ -363,8 +363,8 @@
int ast_format_cache_init(void)
{
- formats = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, CACHE_BUCKETS,
- format_hash_cb, format_cmp_cb);
+ formats = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_RWLOCK, 0, CACHE_BUCKETS,
+ format_hash_cb, NULL, format_cmp_cb);
if (!formats) {
return -1;
}
diff --git a/main/media_cache.c b/main/media_cache.c
index e0a6dbb..97a80d5 100644
--- a/main/media_cache.c
+++ b/main/media_cache.c
@@ -697,8 +697,8 @@
{
ast_register_cleanup(media_cache_shutdown);
- media_cache = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_MUTEX, AO2_BUCKETS,
- ast_sorcery_object_id_hash, ast_sorcery_object_id_compare);
+ media_cache = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, AO2_BUCKETS,
+ ast_sorcery_object_id_hash, NULL, ast_sorcery_object_id_compare);
if (!media_cache) {
return -1;
}
diff --git a/main/pbx.c b/main/pbx.c
index 727018b..f961295 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -3054,7 +3054,7 @@
static struct ao2_container *alloc_device_state_info(void)
{
- return ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL);
+ return ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, NULL, NULL);
}
static int ast_extension_state3(struct ast_str *hint_app, struct ao2_container *device_state_info)
@@ -8916,8 +8916,8 @@
ao2_container_register("hintdevices", hintdevices, print_hintdevices_key);
}
/* This is protected by the context_and_merge lock */
- autohints = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, HASH_EXTENHINT_SIZE,
- autohint_hash_cb, autohint_cmp);
+ autohints = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, HASH_EXTENHINT_SIZE,
+ autohint_hash_cb, NULL, autohint_cmp);
if (autohints) {
ao2_container_register("autohints", autohints, print_autohint_key);
}
diff --git a/main/pickup.c b/main/pickup.c
index f0936dd..484f98b 100644
--- a/main/pickup.c
+++ b/main/pickup.c
@@ -135,7 +135,7 @@
struct ao2_container *candidates;/*!< Candidate channels found to pickup. */
struct ast_channel *target;/*!< Potential pickup target */
- candidates = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL);
+ candidates = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, NULL, NULL);
if (!candidates) {
return NULL;
}
diff --git a/main/sorcery.c b/main/sorcery.c
index 9028707..beaad21 100644
--- a/main/sorcery.c
+++ b/main/sorcery.c
@@ -621,8 +621,8 @@
goto failure_cleanup;
}
- sorcery->types = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, TYPE_BUCKETS,
- ast_sorcery_object_type_hash_fn, ast_sorcery_object_type_cmp_fn);
+ sorcery->types = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_RWLOCK, 0, TYPE_BUCKETS,
+ ast_sorcery_object_type_hash_fn, NULL, ast_sorcery_object_type_cmp_fn);
if (!sorcery->types) {
goto failure_cleanup;
}
@@ -1792,7 +1792,8 @@
/* If returning multiple objects create a container to store them in */
if ((flags & AST_RETRIEVE_FLAG_MULTIPLE)) {
- if (!(object = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL))) {
+ object = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, NULL, NULL);
+ if (!object) {
return NULL;
}
}
@@ -1836,7 +1837,12 @@
struct ao2_container *objects;
int i;
- if (!object_type || !(objects = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL))) {
+ if (!object_type) {
+ return NULL;
+ }
+
+ objects = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, NULL, NULL);
+ if (!objects) {
return NULL;
}
@@ -1866,7 +1872,12 @@
struct ao2_container *objects;
int i;
- if (!object_type || !(objects = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL))) {
+ if (!object_type) {
+ return NULL;
+ }
+
+ objects = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, NULL, NULL);
+ if (!objects) {
return NULL;
}
diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c
index 5c739ab..d14e209 100644
--- a/res/res_musiconhold.c
+++ b/res/res_musiconhold.c
@@ -2005,7 +2005,9 @@
{
int res;
- if (!(mohclasses = ao2_t_container_alloc(53, moh_class_hash, moh_class_cmp, "Moh class container"))) {
+ mohclasses = ao2_t_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, 53,
+ moh_class_hash, NULL, moh_class_cmp, "Moh class container");
+ if (!mohclasses) {
return AST_MODULE_LOAD_DECLINE;
}
diff --git a/res/res_pjsip_notify.c b/res/res_pjsip_notify.c
index 98a75c9..35144fe 100644
--- a/res/res_pjsip_notify.c
+++ b/res/res_pjsip_notify.c
@@ -226,9 +226,9 @@
return NULL;
}
- if (!(cfg->notify_options = ao2_container_alloc_options(
- AO2_ALLOC_OPT_LOCK_NOLOCK, 20, notify_option_hash,
- notify_option_cmp))) {
+ cfg->notify_options = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,
+ 20, notify_option_hash, NULL, notify_option_cmp);
+ if (!cfg->notify_options) {
ao2_cleanup(cfg);
return NULL;
}
diff --git a/res/res_pjsip_outbound_publish.c b/res/res_pjsip_outbound_publish.c
index 4894e55..e4e9fd4 100644
--- a/res/res_pjsip_outbound_publish.c
+++ b/res/res_pjsip_outbound_publish.c
@@ -1555,9 +1555,9 @@
* object if created/updated, or keep the old object if an error occurs.
*/
if (!new_states) {
- new_states = ao2_container_alloc_options(
- AO2_ALLOC_OPT_LOCK_NOLOCK, DEFAULT_STATE_BUCKETS,
- outbound_publish_state_hash, outbound_publish_state_cmp);
+ new_states = ao2_container_alloc_hash(
+ AO2_ALLOC_OPT_LOCK_NOLOCK, 0, DEFAULT_STATE_BUCKETS,
+ outbound_publish_state_hash, NULL, outbound_publish_state_cmp);
if (!new_states) {
ast_log(LOG_ERROR, "Unable to allocate new states container\n");
diff --git a/res/res_sorcery_memory_cache.c b/res/res_sorcery_memory_cache.c
index 30e6ef0..9a1ade0 100644
--- a/res/res_sorcery_memory_cache.c
+++ b/res/res_sorcery_memory_cache.c
@@ -1556,9 +1556,9 @@
}
}
- cache->objects = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK,
+ cache->objects = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_RWLOCK, 0,
cache->maximum_objects ? cache->maximum_objects : CACHE_CONTAINER_BUCKET_SIZE,
- sorcery_memory_cached_object_hash, sorcery_memory_cached_object_cmp);
+ sorcery_memory_cached_object_hash, NULL, sorcery_memory_cached_object_cmp);
if (!cache->objects) {
ast_log(LOG_ERROR, "Could not create a container to hold cached objects for memory cache\n");
return NULL;
diff --git a/res/res_srtp.c b/res/res_srtp.c
index bebcbe6..06d5188 100644
--- a/res/res_srtp.c
+++ b/res/res_srtp.c
@@ -194,7 +194,9 @@
return NULL;
}
- if (!(srtp->policies = ao2_t_container_alloc(5, policy_hash_fn, policy_cmp_fn, "SRTP policy container"))) {
+ srtp->policies = ao2_t_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, 5,
+ policy_hash_fn, NULL, policy_cmp_fn, "SRTP policy container");
+ if (!srtp->policies) {
ast_free(srtp);
return NULL;
}
diff --git a/tests/test_astobj2.c b/tests/test_astobj2.c
index 3158a66..4abe28a 100644
--- a/tests/test_astobj2.c
+++ b/tests/test_astobj2.c
@@ -456,7 +456,7 @@
test_sort_cb, test_cmp_cb, "test");
break;
}
- c2 = ao2_t_container_alloc(1, NULL, NULL, "test");
+ c2 = ao2_t_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL, NULL, "test");
if (!c1 || !c2) {
ast_test_status_update(test, "ao2_container_alloc failed.\n");
--
To view, visit https://gerrit.asterisk.org/10504
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings
Gerrit-Project: asterisk
Gerrit-Branch: 16
Gerrit-MessageType: merged
Gerrit-Change-Id: I1a26258b5bf3deb081aaeed11a0baa175c933c7a
Gerrit-Change-Number: 10504
Gerrit-PatchSet: 3
Gerrit-Owner: Corey Farrell <git at cfware.com>
Gerrit-Reviewer: George Joseph <gjoseph at digium.com>
Gerrit-Reviewer: Jenkins2 (1000185)
Gerrit-Reviewer: Richard Mudgett <rmudgett at digium.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20181024/c083b805/attachment-0001.html>
More information about the asterisk-code-review
mailing list