mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-30 18:21:52 +00:00
Compare commits
2 Commits
5bda42aa04
...
0e3c16fa18
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0e3c16fa18 | ||
|
|
754ca979f7 |
@@ -1 +1 @@
|
||||
ChangeLogs/ChangeLog-21.12.0-rc1.html
|
||||
ChangeLogs/ChangeLog-21.12.0-rc2.html
|
||||
@@ -1 +1 @@
|
||||
ChangeLogs/ChangeLog-21.12.0-rc1.md
|
||||
ChangeLogs/ChangeLog-21.12.0-rc2.md
|
||||
61
ChangeLogs/ChangeLog-21.12.0-rc2.html
Normal file
61
ChangeLogs/ChangeLog-21.12.0-rc2.html
Normal file
@@ -0,0 +1,61 @@
|
||||
<html><head><title>ChangeLog for asterisk-21.12.0-rc2</title></head><body>
|
||||
<h2>Change Log for Release asterisk-21.12.0-rc2</h2>
|
||||
<h3>Links:</h3>
|
||||
<ul>
|
||||
<li><a href="https://downloads.asterisk.org/pub/telephony/asterisk/releases/ChangeLog-21.12.0-rc2.html">Full ChangeLog</a> </li>
|
||||
<li><a href="https://github.com/asterisk/asterisk/compare/21.12.0-rc1...21.12.0-rc2">GitHub Diff</a> </li>
|
||||
<li><a href="https://downloads.asterisk.org/pub/telephony/asterisk/asterisk-21.12.0-rc2.tar.gz">Tarball</a> </li>
|
||||
<li><a href="https://downloads.asterisk.org/pub/telephony/asterisk">Downloads</a> </li>
|
||||
</ul>
|
||||
<h3>Summary:</h3>
|
||||
<ul>
|
||||
<li>Commits: 1</li>
|
||||
<li>Commit Authors: 1</li>
|
||||
<li>Issues Resolved: 1</li>
|
||||
<li>Security Advisories Resolved: 0</li>
|
||||
</ul>
|
||||
<h3>User Notes:</h3>
|
||||
<h3>Upgrade Notes:</h3>
|
||||
<h3>Developer Notes:</h3>
|
||||
<h3>Commit Authors:</h3>
|
||||
<ul>
|
||||
<li>George Joseph: (1)</li>
|
||||
</ul>
|
||||
<h2>Issue and Commit Detail:</h2>
|
||||
<h3>Closed Issues:</h3>
|
||||
<ul>
|
||||
<li>1578: [bug]: Deadlock with externalMedia custom channel id and cpp map channel backend</li>
|
||||
</ul>
|
||||
<h3>Commits By Author:</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4>George Joseph (1):</h4>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Commit List:</h3>
|
||||
<ul>
|
||||
<li>channelstorage: Allow storage driver read locking to be skipped.</li>
|
||||
</ul>
|
||||
<h3>Commit Details:</h3>
|
||||
<h4>channelstorage: Allow storage driver read locking to be skipped.</h4>
|
||||
<p>Author: George Joseph
|
||||
Date: 2025-11-06</p>
|
||||
<p>After PR #1498 added read locking to channelstorage_cpp_map_name_id, if ARI
|
||||
channels/externalMedia was called with a custom channel id AND the
|
||||
cpp_map_name_id channel storage backend is in use, a deadlock can occur when
|
||||
hanging up the channel. It's actually triggered in
|
||||
channel.c:__ast_channel_alloc_ap() when it gets a write lock on the
|
||||
channelstorage driver then subsequently does a lookup for channel uniqueid
|
||||
which now does a read lock. This is an invalid operation and causes the lock
|
||||
state to get "bad". When the channels try to hang up, a write lock is
|
||||
attempted again which hangs and causes the deadlock.</p>
|
||||
<p>Now instead of the cpp_map_name_id channelstorage driver "get" APIs
|
||||
automatically performing a read lock, they take a "lock" parameter which
|
||||
allows a caller who already has a write lock to indicate that the "get" API
|
||||
must not attempt its own lock. This prevents the state from getting mesed up.</p>
|
||||
<p>The ao2_legacy driver uses the ao2 container's recursive mutex so doesn't
|
||||
have this issue but since it also implements the common channelstorage API,
|
||||
it needed its "get" implementations updated to take the lock parameter. They
|
||||
just don't use it.</p>
|
||||
<p>Resolves: #1578</p>
|
||||
</body></html>
|
||||
72
ChangeLogs/ChangeLog-21.12.0-rc2.md
Normal file
72
ChangeLogs/ChangeLog-21.12.0-rc2.md
Normal file
@@ -0,0 +1,72 @@
|
||||
|
||||
## Change Log for Release asterisk-21.12.0-rc2
|
||||
|
||||
### Links:
|
||||
|
||||
- [Full ChangeLog](https://downloads.asterisk.org/pub/telephony/asterisk/releases/ChangeLog-21.12.0-rc2.html)
|
||||
- [GitHub Diff](https://github.com/asterisk/asterisk/compare/21.12.0-rc1...21.12.0-rc2)
|
||||
- [Tarball](https://downloads.asterisk.org/pub/telephony/asterisk/asterisk-21.12.0-rc2.tar.gz)
|
||||
- [Downloads](https://downloads.asterisk.org/pub/telephony/asterisk)
|
||||
|
||||
### Summary:
|
||||
|
||||
- Commits: 1
|
||||
- Commit Authors: 1
|
||||
- Issues Resolved: 1
|
||||
- Security Advisories Resolved: 0
|
||||
|
||||
### User Notes:
|
||||
|
||||
|
||||
### Upgrade Notes:
|
||||
|
||||
|
||||
### Developer Notes:
|
||||
|
||||
|
||||
### Commit Authors:
|
||||
|
||||
- George Joseph: (1)
|
||||
|
||||
## Issue and Commit Detail:
|
||||
|
||||
### Closed Issues:
|
||||
|
||||
- 1578: [bug]: Deadlock with externalMedia custom channel id and cpp map channel backend
|
||||
|
||||
### Commits By Author:
|
||||
|
||||
- #### George Joseph (1):
|
||||
|
||||
### Commit List:
|
||||
|
||||
- channelstorage: Allow storage driver read locking to be skipped.
|
||||
|
||||
### Commit Details:
|
||||
|
||||
#### channelstorage: Allow storage driver read locking to be skipped.
|
||||
Author: George Joseph
|
||||
Date: 2025-11-06
|
||||
|
||||
After PR #1498 added read locking to channelstorage_cpp_map_name_id, if ARI
|
||||
channels/externalMedia was called with a custom channel id AND the
|
||||
cpp_map_name_id channel storage backend is in use, a deadlock can occur when
|
||||
hanging up the channel. It's actually triggered in
|
||||
channel.c:__ast_channel_alloc_ap() when it gets a write lock on the
|
||||
channelstorage driver then subsequently does a lookup for channel uniqueid
|
||||
which now does a read lock. This is an invalid operation and causes the lock
|
||||
state to get "bad". When the channels try to hang up, a write lock is
|
||||
attempted again which hangs and causes the deadlock.
|
||||
|
||||
Now instead of the cpp_map_name_id channelstorage driver "get" APIs
|
||||
automatically performing a read lock, they take a "lock" parameter which
|
||||
allows a caller who already has a write lock to indicate that the "get" API
|
||||
must not attempt its own lock. This prevents the state from getting mesed up.
|
||||
|
||||
The ao2_legacy driver uses the ao2 container's recursive mutex so doesn't
|
||||
have this issue but since it also implements the common channelstorage API,
|
||||
it needed its "get" implementations updated to take the lock parameter. They
|
||||
just don't use it.
|
||||
|
||||
Resolves: #1578
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<html><head><title>Readme for asterisk-21.12.0-rc1</title></head><body>
|
||||
<html><head><title>Readme for asterisk-21.12.0-rc2</title></head><body>
|
||||
<h1>The Asterisk(R) Open Source PBX</h1>
|
||||
<pre><code>By Mark Spencer <markster@digium.com> and the Asterisk.org developer community.
|
||||
Copyright (C) 2001-2025 Sangoma Technologies Corporation and other copyright holders.
|
||||
@@ -37,7 +37,7 @@ hardware.</p>
|
||||
<p>If you are updating from a previous version of Asterisk, make sure you
|
||||
read the Change Logs.</p>
|
||||
<!-- CHANGELOGS (the URL will change based on the location of this README) -->
|
||||
<p><a href="ChangeLogs/ChangeLog-21.12.0-rc1.html">Change Logs</a></p>
|
||||
<p><a href="ChangeLogs/ChangeLog-21.12.0-rc2.html">Change Logs</a></p>
|
||||
<!-- END-CHANGELOGS -->
|
||||
|
||||
<h3>NEW INSTALLATIONS</h3>
|
||||
|
||||
@@ -55,7 +55,7 @@ If you are updating from a previous version of Asterisk, make sure you
|
||||
read the Change Logs.
|
||||
|
||||
<!-- CHANGELOGS (the URL will change based on the location of this README) -->
|
||||
[Change Logs](ChangeLogs/ChangeLog-21.12.0-rc1.html)
|
||||
[Change Logs](ChangeLogs/ChangeLog-21.12.0-rc2.html)
|
||||
<!-- END-CHANGELOGS -->
|
||||
|
||||
### NEW INSTALLATIONS
|
||||
|
||||
@@ -498,7 +498,7 @@ void ast_softhangup_all(void)
|
||||
/*! \brief returns number of active/allocated channels */
|
||||
int ast_active_channels(void)
|
||||
{
|
||||
return current_channel_storage_instance ? CHANNELSTORAGE_API(current_channel_storage_instance, active_channels) : 0;
|
||||
return current_channel_storage_instance ? CHANNELSTORAGE_API(current_channel_storage_instance, active_channels, 1) : 0;
|
||||
}
|
||||
|
||||
int ast_undestroyed_channels(void)
|
||||
@@ -707,7 +707,7 @@ static const struct ast_channel_tech null_tech = {
|
||||
static void ast_channel_destructor(void *obj);
|
||||
static void ast_dummy_channel_destructor(void *obj);
|
||||
|
||||
static int do_ids_conflict(const struct ast_assigned_ids *assignedids)
|
||||
static int do_ids_conflict(const struct ast_assigned_ids *assignedids, int rdlock)
|
||||
{
|
||||
struct ast_channel *conflict;
|
||||
|
||||
@@ -717,7 +717,7 @@ static int do_ids_conflict(const struct ast_assigned_ids *assignedids)
|
||||
|
||||
if (!ast_strlen_zero(assignedids->uniqueid)) {
|
||||
conflict = CHANNELSTORAGE_API(current_channel_storage_instance,
|
||||
get_by_uniqueid, assignedids->uniqueid);
|
||||
get_by_uniqueid, assignedids->uniqueid, rdlock);
|
||||
if (conflict) {
|
||||
ast_log(LOG_ERROR, "Channel Unique ID '%s' already in use by channel %s(%p)\n",
|
||||
assignedids->uniqueid, ast_channel_name(conflict), conflict);
|
||||
@@ -728,7 +728,7 @@ static int do_ids_conflict(const struct ast_assigned_ids *assignedids)
|
||||
|
||||
if (!ast_strlen_zero(assignedids->uniqueid2)) {
|
||||
conflict = CHANNELSTORAGE_API(current_channel_storage_instance,
|
||||
get_by_uniqueid, assignedids->uniqueid2);
|
||||
get_by_uniqueid, assignedids->uniqueid2, rdlock);
|
||||
if (conflict) {
|
||||
ast_log(LOG_ERROR, "Channel Unique ID2 '%s' already in use by channel %s(%p)\n",
|
||||
assignedids->uniqueid2, ast_channel_name(conflict), conflict);
|
||||
@@ -933,7 +933,7 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
|
||||
|
||||
CHANNELSTORAGE_API(current_channel_storage_instance, wrlock);
|
||||
|
||||
if (do_ids_conflict(assignedids)) {
|
||||
if (do_ids_conflict(assignedids, 0)) {
|
||||
ast_channel_internal_errno_set(AST_CHANNEL_ERROR_ID_EXISTS);
|
||||
ast_channel_unlock(tmp);
|
||||
CHANNELSTORAGE_API(current_channel_storage_instance, unlock);
|
||||
@@ -1324,7 +1324,7 @@ struct ast_channel *ast_channel_callback(
|
||||
ast_log(LOG_ERROR, "callback function must be provided\n");
|
||||
return NULL;
|
||||
}
|
||||
return CHANNELSTORAGE_API(current_channel_storage_instance, callback, cb_fn, arg, data, ao2_flags);
|
||||
return CHANNELSTORAGE_API(current_channel_storage_instance, callback, cb_fn, arg, data, ao2_flags, 1);
|
||||
}
|
||||
|
||||
struct ast_channel_iterator *ast_channel_iterator_destroy(struct ast_channel_iterator *i)
|
||||
@@ -1388,7 +1388,7 @@ struct ast_channel *ast_channel_get_by_name_prefix(const char *name, size_t name
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return CHANNELSTORAGE_API(current_channel_storage_instance, get_by_name_prefix_or_uniqueid, name, name_len);
|
||||
return CHANNELSTORAGE_API(current_channel_storage_instance, get_by_name_prefix_or_uniqueid, name, name_len, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1405,7 +1405,7 @@ struct ast_channel *ast_channel_get_by_name(const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return CHANNELSTORAGE_API(current_channel_storage_instance, get_by_name_prefix_or_uniqueid, name, 0);
|
||||
return CHANNELSTORAGE_API(current_channel_storage_instance, get_by_name_prefix_or_uniqueid, name, 0, 1);
|
||||
}
|
||||
|
||||
struct ast_channel *ast_channel_get_by_exten(const char *exten, const char *context)
|
||||
@@ -1417,7 +1417,7 @@ struct ast_channel *ast_channel_get_by_exten(const char *exten, const char *cont
|
||||
ast_log(LOG_ERROR, "exten and context must be provided\n");
|
||||
return NULL;
|
||||
}
|
||||
return CHANNELSTORAGE_API(current_channel_storage_instance, get_by_exten, exten, context);
|
||||
return CHANNELSTORAGE_API(current_channel_storage_instance, get_by_exten, exten, context, 1);
|
||||
}
|
||||
|
||||
struct ast_channel *ast_channel_get_by_uniqueid(const char *uniqueid)
|
||||
@@ -1429,7 +1429,7 @@ struct ast_channel *ast_channel_get_by_uniqueid(const char *uniqueid)
|
||||
ast_log(LOG_ERROR, "uniqueid must be provided\n");
|
||||
return NULL;
|
||||
}
|
||||
return CHANNELSTORAGE_API(current_channel_storage_instance, get_by_uniqueid, uniqueid);
|
||||
return CHANNELSTORAGE_API(current_channel_storage_instance, get_by_uniqueid, uniqueid, 1);
|
||||
}
|
||||
|
||||
int ast_is_deferrable_frame(const struct ast_frame *frame)
|
||||
|
||||
@@ -85,12 +85,12 @@ int channelstorage_exten_cb(void *obj, void *arg, void *data, int flags)
|
||||
}
|
||||
|
||||
struct ast_channel *channelstorage_by_exten(struct ast_channelstorage_instance *driver,
|
||||
const char *exten, const char *context)
|
||||
const char *exten, const char *context, int rdlock)
|
||||
{
|
||||
char *l_exten = (char *) exten;
|
||||
char *l_context = (char *) context;
|
||||
|
||||
return CHANNELSTORAGE_API(driver, callback, channelstorage_exten_cb, l_context, l_exten, 0);
|
||||
return CHANNELSTORAGE_API(driver, callback, channelstorage_exten_cb, l_context, l_exten, 0, rdlock);
|
||||
}
|
||||
|
||||
int channelstorage_name_cb(void *obj, void *arg, void *data, int flags)
|
||||
@@ -114,23 +114,23 @@ int channelstorage_name_cb(void *obj, void *arg, void *data, int flags)
|
||||
}
|
||||
|
||||
struct ast_channel *channelstorage_by_name_or_uniqueid(struct ast_channelstorage_instance *driver,
|
||||
const char *name)
|
||||
const char *name, int rdlock)
|
||||
{
|
||||
return CHANNELSTORAGE_API(driver, get_by_name_prefix_or_uniqueid, name, 0);
|
||||
return CHANNELSTORAGE_API(driver, get_by_name_prefix_or_uniqueid, name, 0, rdlock);
|
||||
}
|
||||
|
||||
struct ast_channel *channelstorage_by_name_prefix_or_uniqueid(struct ast_channelstorage_instance *driver,
|
||||
const char *name, size_t name_len)
|
||||
const char *name, size_t name_len, int rdlock)
|
||||
{
|
||||
struct ast_channel *chan = NULL;
|
||||
|
||||
chan = CHANNELSTORAGE_API(driver, get_by_name_prefix, name, name_len);
|
||||
chan = CHANNELSTORAGE_API(driver, get_by_name_prefix, name, name_len, rdlock);
|
||||
if (chan) {
|
||||
return chan;
|
||||
}
|
||||
|
||||
if (name_len == 0) {
|
||||
chan = CHANNELSTORAGE_API(driver, get_by_uniqueid, name);
|
||||
chan = CHANNELSTORAGE_API(driver, get_by_uniqueid, name, rdlock);
|
||||
}
|
||||
|
||||
return chan;
|
||||
@@ -150,9 +150,9 @@ int channelstorage_uniqueid_cb(void *obj, void *arg, void *data, int flags)
|
||||
}
|
||||
|
||||
struct ast_channel *channelstorage_by_uniqueid(struct ast_channelstorage_instance *driver,
|
||||
const char *uniqueid)
|
||||
const char *uniqueid, int rdlock)
|
||||
{
|
||||
return CHANNELSTORAGE_API(driver, callback, channelstorage_uniqueid_cb, (char *)uniqueid, NULL, 0);
|
||||
return CHANNELSTORAGE_API(driver, callback, channelstorage_uniqueid_cb, (char *)uniqueid, NULL, 0, rdlock);
|
||||
}
|
||||
|
||||
#ifdef TEST_FRAMEWORK
|
||||
@@ -214,14 +214,14 @@ static void *test_storage_thread(void *data)
|
||||
}
|
||||
end = ast_tvnow();
|
||||
elapsed = ast_tvdiff_us(end, start);
|
||||
i = CHANNELSTORAGE_API(storage_instance, active_channels);
|
||||
i = CHANNELSTORAGE_API(storage_instance, active_channels, 1);
|
||||
ast_test_status_update(test, "%*s: %8ld\n", collen, "create channels", elapsed);
|
||||
ast_test_validate_cleanup(test, i == CHANNEL_COUNT, res, done);
|
||||
|
||||
start = ast_tvnow();
|
||||
for (i = 0; i < CHANNEL_COUNT; i++) {
|
||||
sprintf(search1, "testchannel-%ld-%04d-something", rand, i);
|
||||
mock_channel = CHANNELSTORAGE_API(storage_instance, get_by_name_prefix_or_uniqueid, search1, 0);
|
||||
mock_channel = CHANNELSTORAGE_API(storage_instance, get_by_name_prefix_or_uniqueid, search1, 0, 1);
|
||||
ast_test_validate_cleanup(test, mock_channel, res, done);
|
||||
ast_test_validate_cleanup(test, mock_channel == test_channels[i], res, done);
|
||||
ast_test_validate_cleanup(test,
|
||||
@@ -235,7 +235,7 @@ static void *test_storage_thread(void *data)
|
||||
start = ast_tvnow();
|
||||
for (i = 0; i < CHANNEL_COUNT; i++) {
|
||||
sprintf(search1, "TestUniqueid-%ld-%04d-something", rand, i);
|
||||
mock_channel = CHANNELSTORAGE_API(storage_instance, get_by_uniqueid, search1);
|
||||
mock_channel = CHANNELSTORAGE_API(storage_instance, get_by_uniqueid, search1, 1);
|
||||
ast_test_validate_cleanup(test, mock_channel, res, done);
|
||||
ast_channel_unref(mock_channel);
|
||||
}
|
||||
@@ -246,7 +246,7 @@ static void *test_storage_thread(void *data)
|
||||
start = ast_tvnow();
|
||||
for (i = 0; i < CHANNEL_COUNT; i++) {
|
||||
sprintf(search1, "TestUniqueid-%ld-%04d-something", rand, i);
|
||||
mock_channel = CHANNELSTORAGE_API(storage_instance, get_by_name_prefix_or_uniqueid, search1, 0);
|
||||
mock_channel = CHANNELSTORAGE_API(storage_instance, get_by_name_prefix_or_uniqueid, search1, 0, 1);
|
||||
ast_test_validate_cleanup(test, mock_channel, res, done);
|
||||
ast_channel_unref(mock_channel);
|
||||
}
|
||||
@@ -257,7 +257,7 @@ static void *test_storage_thread(void *data)
|
||||
start = ast_tvnow();
|
||||
for (i = 0; i < CHANNEL_COUNT; i++) {
|
||||
sprintf(search1, "TestChannel-%ld-%04d", rand, i);
|
||||
mock_channel = CHANNELSTORAGE_API(storage_instance, get_by_name_prefix_or_uniqueid, search1, strlen(search1));
|
||||
mock_channel = CHANNELSTORAGE_API(storage_instance, get_by_name_prefix_or_uniqueid, search1, strlen(search1), 1);
|
||||
ast_test_validate_cleanup(test, mock_channel, res, done);
|
||||
ast_channel_unref(mock_channel);
|
||||
}
|
||||
@@ -269,7 +269,7 @@ static void *test_storage_thread(void *data)
|
||||
for (i = 0; i < CHANNEL_COUNT; i++) {
|
||||
sprintf(search1, "TestContext-%ld-%04d", rand, i % 100);
|
||||
sprintf(search2, "TestExten-%ld-%04d", rand, i % 10);
|
||||
mock_channel = CHANNELSTORAGE_API(storage_instance, get_by_exten, search2, search1);
|
||||
mock_channel = CHANNELSTORAGE_API(storage_instance, get_by_exten, search2, search1, 1);
|
||||
ast_test_validate_cleanup(test, mock_channel, res, done);
|
||||
ast_channel_unref(mock_channel);
|
||||
}
|
||||
@@ -290,7 +290,7 @@ static void *test_storage_thread(void *data)
|
||||
ast_test_status_update(test, "%*s: %8ld\n", collen, "iter all chan", elapsed);
|
||||
ast_test_validate_cleanup_custom(test, i == CHANNEL_COUNT, res, done,
|
||||
"Expected %d channels, got %d, in container: %d\n", CHANNEL_COUNT, i,
|
||||
CHANNELSTORAGE_API(storage_instance, active_channels));
|
||||
CHANNELSTORAGE_API(storage_instance, active_channels, 1));
|
||||
|
||||
i = 0;
|
||||
start = ast_tvnow();
|
||||
@@ -310,7 +310,7 @@ static void *test_storage_thread(void *data)
|
||||
ast_test_status_update(test, "%*s: %8ld\n", collen, "iter 10 partial name", elapsed);
|
||||
ast_test_validate_cleanup_custom(test, i == 10, res, done,
|
||||
"Expected %d channels, got %d, in container: %d\n", 10, i,
|
||||
CHANNELSTORAGE_API(storage_instance, active_channels));
|
||||
CHANNELSTORAGE_API(storage_instance, active_channels, 1));
|
||||
|
||||
i = 0;
|
||||
start = ast_tvnow();
|
||||
@@ -349,7 +349,7 @@ done:
|
||||
elapsed = ast_tvdiff_us(end, start);
|
||||
ast_test_status_update(test, "%*s: %8ld\n", collen, "del all channels", elapsed);
|
||||
ast_test_validate_cleanup(test, i == CHANNEL_COUNT, res, done);
|
||||
rc = CHANNELSTORAGE_API(storage_instance, active_channels);
|
||||
rc = CHANNELSTORAGE_API(storage_instance, active_channels, 1);
|
||||
ast_test_validate_cleanup_custom(test, rc == 0, res, final,
|
||||
"There are still %d channels in the container\n", rc);
|
||||
|
||||
|
||||
@@ -51,13 +51,13 @@ struct ast_channelstorage_instance {
|
||||
void (*rdlock)(struct ast_channelstorage_instance *driver);
|
||||
void (*wrlock)(struct ast_channelstorage_instance *driver);
|
||||
void (*unlock)(struct ast_channelstorage_instance *driver);
|
||||
int (*active_channels)(struct ast_channelstorage_instance *driver);
|
||||
int (*active_channels)(struct ast_channelstorage_instance *driver, int rdlock);
|
||||
struct ast_channel *(*callback)(struct ast_channelstorage_instance *driver, ao2_callback_data_fn *cb_fn,
|
||||
void *arg, void *data, int ao2_flags);
|
||||
struct ast_channel *(*get_by_name_prefix)(struct ast_channelstorage_instance *driver, const char *name, size_t len);
|
||||
struct ast_channel *(*get_by_name_prefix_or_uniqueid)(struct ast_channelstorage_instance *driver, const char *name, size_t len);
|
||||
struct ast_channel *(*get_by_exten)(struct ast_channelstorage_instance *driver, const char *exten, const char *context);
|
||||
struct ast_channel *(*get_by_uniqueid)(struct ast_channelstorage_instance *driver, const char *uniqueid);
|
||||
void *arg, void *data, int ao2_flags, int rdlock);
|
||||
struct ast_channel *(*get_by_name_prefix)(struct ast_channelstorage_instance *driver, const char *name, size_t len, int rdlock);
|
||||
struct ast_channel *(*get_by_name_prefix_or_uniqueid)(struct ast_channelstorage_instance *driver, const char *name, size_t len, int rdlock);
|
||||
struct ast_channel *(*get_by_exten)(struct ast_channelstorage_instance *driver, const char *exten, const char *context, int rdlock);
|
||||
struct ast_channel *(*get_by_uniqueid)(struct ast_channelstorage_instance *driver, const char *uniqueid, int rdlock);
|
||||
struct ast_channel_iterator *(*iterator_all_new)(struct ast_channelstorage_instance *driver);
|
||||
struct ast_channel_iterator *(*iterator_by_exten_new)
|
||||
(struct ast_channelstorage_instance *driver, const char *exten, const char *context);
|
||||
@@ -81,15 +81,15 @@ void ast_channelstorage_close(struct ast_channelstorage_instance *storage_instan
|
||||
|
||||
int channelstorage_exten_cb(void *obj, void *arg, void *data, int flags);
|
||||
struct ast_channel *channelstorage_by_exten(struct ast_channelstorage_instance *driver,
|
||||
const char *exten, const char *context);
|
||||
const char *exten, const char *context, int rdlock);
|
||||
int channelstorage_name_cb(void *obj, void *arg, void *data, int flags);
|
||||
struct ast_channel *channelstorage_by_name_or_uniqueid(struct ast_channelstorage_instance *driver,
|
||||
const char *name);
|
||||
const char *name, int rdlock);
|
||||
struct ast_channel *channelstorage_by_name_prefix_or_uniqueid(struct ast_channelstorage_instance *driver,
|
||||
const char *name, size_t name_len);
|
||||
const char *name, size_t name_len, int rdlock);
|
||||
int channelstorage_uniqueid_cb(void *obj, void *arg, void *data, int flags);
|
||||
struct ast_channel *channelstorage_by_uniqueid(struct ast_channelstorage_instance *driver,
|
||||
const char *uniqueid);
|
||||
const char *uniqueid, int rdlock);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
|
||||
@@ -58,13 +58,13 @@ static int delete_channel(struct ast_channelstorage_instance *driver,
|
||||
}
|
||||
|
||||
/*! \brief returns number of active/allocated channels */
|
||||
static int active_channels(struct ast_channelstorage_instance *driver)
|
||||
static int active_channels(struct ast_channelstorage_instance *driver, int rdlock)
|
||||
{
|
||||
return getdb(driver) ? ao2_container_count(getdb(driver)) : 0;
|
||||
}
|
||||
|
||||
static struct ast_channel *callback(struct ast_channelstorage_instance *driver,
|
||||
ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags)
|
||||
ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags, int rdlock)
|
||||
{
|
||||
return ao2_callback_data(getdb(driver), ao2_flags, cb_fn, arg, data);
|
||||
}
|
||||
@@ -161,7 +161,7 @@ static struct ast_channel_iterator *iterator_by_exten_new(struct ast_channelstor
|
||||
}
|
||||
|
||||
i->active_iterator = (void *) callback(driver, by_exten_cb,
|
||||
l_context, l_exten, OBJ_MULTIPLE);
|
||||
l_context, l_exten, OBJ_MULTIPLE, 1);
|
||||
if (!i->active_iterator) {
|
||||
ast_free(i);
|
||||
return NULL;
|
||||
@@ -182,7 +182,7 @@ static struct ast_channel_iterator *iterator_by_name_new(struct ast_channelstora
|
||||
|
||||
i->active_iterator = (void *) callback(driver, by_name_cb,
|
||||
l_name, &name_len,
|
||||
OBJ_MULTIPLE | (name_len == 0 /* match the whole word, so optimize */ ? OBJ_KEY : 0));
|
||||
OBJ_MULTIPLE | (name_len == 0 /* match the whole word, so optimize */ ? OBJ_KEY : 0), 1);
|
||||
if (!i->active_iterator) {
|
||||
ast_free(i);
|
||||
return NULL;
|
||||
@@ -212,17 +212,17 @@ static struct ast_channel *iterator_next(struct ast_channelstorage_instance *dri
|
||||
}
|
||||
|
||||
static struct ast_channel *get_by_uniqueid(struct ast_channelstorage_instance *driver,
|
||||
const char *uniqueid)
|
||||
const char *uniqueid, int lock)
|
||||
{
|
||||
char *l_name = (char *) uniqueid;
|
||||
size_t name_len = strlen(uniqueid);
|
||||
|
||||
struct ast_channel *chan = callback(driver, by_uniqueid_cb, l_name, &name_len, 0);
|
||||
struct ast_channel *chan = callback(driver, by_uniqueid_cb, l_name, &name_len, 0, lock);
|
||||
return chan;
|
||||
}
|
||||
|
||||
static struct ast_channel *get_by_name_prefix(struct ast_channelstorage_instance *driver,
|
||||
const char *name, size_t name_len)
|
||||
const char *name, size_t name_len, int lock)
|
||||
{
|
||||
struct ast_channel *chan;
|
||||
char *l_name = (char *) name;
|
||||
@@ -233,23 +233,23 @@ static struct ast_channel *get_by_name_prefix(struct ast_channelstorage_instance
|
||||
}
|
||||
|
||||
chan = callback(driver, by_name_cb, l_name, &name_len,
|
||||
(name_len == 0) /* optimize if it is a complete name match */ ? OBJ_KEY : 0);
|
||||
(name_len == 0) /* optimize if it is a complete name match */ ? OBJ_KEY : 0, lock);
|
||||
if (chan) {
|
||||
return chan;
|
||||
}
|
||||
|
||||
/* Now try a search for uniqueid. */
|
||||
chan = callback(driver, by_uniqueid_cb, l_name, &name_len, 0);
|
||||
chan = callback(driver, by_uniqueid_cb, l_name, &name_len, 0, lock);
|
||||
return chan;
|
||||
}
|
||||
|
||||
static struct ast_channel *get_by_exten(struct ast_channelstorage_instance *driver,
|
||||
const char *exten, const char *context)
|
||||
const char *exten, const char *context, int rdlock)
|
||||
{
|
||||
char *l_exten = (char *) exten;
|
||||
char *l_context = (char *) context;
|
||||
|
||||
return callback(driver, by_exten_cb, l_context, l_exten, 0);
|
||||
return callback(driver, by_exten_cb, l_context, l_exten, 0, rdlock);
|
||||
}
|
||||
|
||||
static int hash_cb(const void *obj, const int flags)
|
||||
|
||||
@@ -139,7 +139,7 @@ static int delete_channel(struct ast_channelstorage_instance *driver,
|
||||
}
|
||||
|
||||
/*! \brief returns number of active/allocated channels */
|
||||
static int active_channels(struct ast_channelstorage_instance *driver)
|
||||
static int active_channels(struct ast_channelstorage_instance *driver, int lock)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
@@ -147,15 +147,19 @@ static int active_channels(struct ast_channelstorage_instance *driver)
|
||||
return 0;
|
||||
}
|
||||
|
||||
rdlock(driver);
|
||||
if (lock) {
|
||||
rdlock(driver);
|
||||
}
|
||||
count = getdb(driver).size();
|
||||
unlock(driver);
|
||||
if (lock) {
|
||||
unlock(driver);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct ast_channel *callback(struct ast_channelstorage_instance *driver,
|
||||
ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags)
|
||||
ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags, int lock)
|
||||
{
|
||||
struct ast_channel *chan = NULL;
|
||||
ChannelMap::const_iterator it;
|
||||
@@ -164,18 +168,21 @@ static struct ast_channel *callback(struct ast_channelstorage_instance *driver,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rdlock(driver);
|
||||
if (lock) {
|
||||
rdlock(driver);
|
||||
}
|
||||
for (it = getdb(driver).begin(); it != getdb(driver).end(); it++) {
|
||||
chan = it->second;
|
||||
if (cb_fn(chan, arg, data, ao2_flags) == (CMP_MATCH | CMP_STOP)) {
|
||||
ao2_bump(chan);
|
||||
unlock(driver);
|
||||
return chan;
|
||||
break;
|
||||
}
|
||||
}
|
||||
unlock(driver);
|
||||
if (lock) {
|
||||
unlock(driver);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return chan;
|
||||
}
|
||||
|
||||
enum cpp_map_iterator_type {
|
||||
@@ -460,7 +467,7 @@ static struct ast_channel_iterator *iterator_by_exten_new(struct ast_channelstor
|
||||
}
|
||||
|
||||
static struct ast_channel *get_by_uniqueid(struct ast_channelstorage_instance *driver,
|
||||
const char *uniqueid)
|
||||
const char *uniqueid, int lock)
|
||||
{
|
||||
struct ast_channel *chan = NULL;
|
||||
char *search = uniqueid ? ast_str_to_lower(ast_strdupa(uniqueid)) : NULL;
|
||||
@@ -469,18 +476,22 @@ static struct ast_channel *get_by_uniqueid(struct ast_channelstorage_instance *d
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rdlock(driver);
|
||||
if (lock) {
|
||||
rdlock(driver);
|
||||
}
|
||||
auto rtn = map_by_id(driver).find(search);
|
||||
if (rtn != map_by_id(driver).end()) {
|
||||
chan = ao2_bump((struct ast_channel *)rtn->second);
|
||||
}
|
||||
unlock(driver);
|
||||
if (lock) {
|
||||
unlock(driver);
|
||||
}
|
||||
|
||||
return chan;
|
||||
}
|
||||
|
||||
static struct ast_channel *get_by_name_exact(struct ast_channelstorage_instance *driver,
|
||||
const char *name)
|
||||
const char *name, int lock)
|
||||
{
|
||||
struct ast_channel *chan = NULL;
|
||||
char *search = name ? ast_str_to_lower(ast_strdupa(name)) : NULL;
|
||||
@@ -489,35 +500,43 @@ static struct ast_channel *get_by_name_exact(struct ast_channelstorage_instance
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rdlock(driver);
|
||||
if (lock) {
|
||||
rdlock(driver);
|
||||
}
|
||||
auto rtn = getdb(driver).find(search);
|
||||
if (rtn != getdb(driver).end()) {
|
||||
chan = ao2_bump((struct ast_channel *)rtn->second);
|
||||
}
|
||||
unlock(driver);
|
||||
if (lock) {
|
||||
unlock(driver);
|
||||
}
|
||||
|
||||
return chan;
|
||||
}
|
||||
|
||||
static struct ast_channel *get_by_name_prefix(struct ast_channelstorage_instance *driver,
|
||||
const char *name, size_t name_len)
|
||||
const char *name, size_t name_len, int lock)
|
||||
{
|
||||
struct ast_channel *chan = NULL;
|
||||
char *l_name = NULL;
|
||||
|
||||
if (name_len == 0) {
|
||||
chan = get_by_name_exact(driver, name);
|
||||
chan = get_by_name_exact(driver, name, lock);
|
||||
return chan;
|
||||
}
|
||||
|
||||
l_name = ast_str_to_lower(ast_strdupa(name));
|
||||
|
||||
rdlock(driver);
|
||||
if (lock) {
|
||||
rdlock(driver);
|
||||
}
|
||||
auto rtn = getdb(driver).lower_bound(l_name);
|
||||
if (rtn != getdb(driver).end()) {
|
||||
chan = ao2_bump((struct ast_channel *)rtn->second);
|
||||
}
|
||||
unlock(driver);
|
||||
if (lock) {
|
||||
unlock(driver);
|
||||
}
|
||||
|
||||
return chan;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user