Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
/*
|
|
|
|
|
* Asterisk -- An open source telephony toolkit.
|
|
|
|
|
*
|
|
|
|
|
* Copyright (C) 2009, Digium, Inc.
|
|
|
|
|
*
|
|
|
|
|
* Mark Michelson <mmichelson@digium.com>
|
|
|
|
|
*
|
|
|
|
|
* See http://www.asterisk.org for more information about
|
|
|
|
|
* the Asterisk project. Please do not directly contact
|
|
|
|
|
* any of the maintainers of this project for assistance;
|
|
|
|
|
* the project provides a web site, mailing lists and IRC
|
|
|
|
|
* channels for your use.
|
|
|
|
|
*
|
|
|
|
|
* This program is free software, distributed under the terms of
|
|
|
|
|
* the GNU General Public License Version 2. See the LICENSE file
|
|
|
|
|
* at the top of the source tree.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* \file
|
|
|
|
|
* \brief "smart" channels that update automatically if a channel is masqueraded
|
|
|
|
|
*
|
|
|
|
|
* \author Mark Michelson <mmichelson@digium.com>
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "asterisk.h"
|
|
|
|
|
#include "asterisk/linkedlists.h"
|
|
|
|
|
|
|
|
|
|
#ifndef _ASTERISK_AUTOCHAN_H
|
|
|
|
|
#define _ASTERISK_AUTOCHAN_H
|
|
|
|
|
|
|
|
|
|
struct ast_autochan {
|
|
|
|
|
struct ast_channel *chan;
|
|
|
|
|
AST_LIST_ENTRY(ast_autochan) list;
|
2017-03-15 13:24:33 -05:00
|
|
|
ast_mutex_t lock;
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
};
|
|
|
|
|
|
2017-12-22 09:23:22 -05:00
|
|
|
/*!
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
* \par Just what the $!@# is an autochan?
|
|
|
|
|
*
|
|
|
|
|
* An ast_autochan is a structure which contains an ast_channel. The pointer
|
|
|
|
|
* inside an autochan has the ability to update itself if the channel it points
|
|
|
|
|
* to is masqueraded into a different channel.
|
|
|
|
|
*
|
|
|
|
|
* This has a great benefit for any application or service which creates a thread
|
|
|
|
|
* outside of the channel's main operating thread which keeps a pointer to said
|
|
|
|
|
* channel. when a masquerade occurs on the channel, the autochan's chan pointer
|
|
|
|
|
* will automatically update to point to the new channel.
|
|
|
|
|
*
|
|
|
|
|
* Some rules for autochans
|
|
|
|
|
*
|
|
|
|
|
* 1. If you are going to use an autochan, then be sure to always refer to the
|
|
|
|
|
* channel using the chan pointer inside the autochan if possible, since this is
|
|
|
|
|
* the pointer that will be updated during a masquerade.
|
|
|
|
|
*
|
|
|
|
|
* 2. If you are going to save off a pointer to the autochan's chan, then be sure
|
|
|
|
|
* to save off the pointer using ast_channel_ref and to unref the channel when you
|
|
|
|
|
* are finished with the pointer. If you do not do this and a masquerade occurs on
|
|
|
|
|
* the channel, then it is possible that your saved pointer will become invalid.
|
2016-03-11 23:03:08 +01:00
|
|
|
*
|
|
|
|
|
* 3. If you want to lock the autochan->chan channel, be sure to use
|
|
|
|
|
* ast_autochan_channel_lock and ast_autochan_channel_unlock. An attempt to lock
|
|
|
|
|
* the autochan->chan directly may result in it being changed after you've
|
|
|
|
|
* retrieved the value of chan, but before you've had a chance to lock it.
|
2017-03-15 13:24:33 -05:00
|
|
|
* While chan is locked, the autochan structure is guaranteed to keep the
|
2016-03-11 23:03:08 +01:00
|
|
|
* same channel.
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
*/
|
|
|
|
|
|
2017-03-15 13:24:33 -05:00
|
|
|
/*!
|
|
|
|
|
* \brief Lock the autochan's channel lock.
|
|
|
|
|
*
|
|
|
|
|
* \note We must do deadlock avoidance because the channel lock is
|
|
|
|
|
* superior to the autochan lock in locking order.
|
|
|
|
|
*/
|
2016-03-11 23:03:08 +01:00
|
|
|
#define ast_autochan_channel_lock(autochan) \
|
|
|
|
|
do { \
|
2017-03-15 13:24:33 -05:00
|
|
|
ast_mutex_lock(&(autochan)->lock); \
|
|
|
|
|
while (ast_channel_trylock((autochan)->chan)) { \
|
|
|
|
|
DEADLOCK_AVOIDANCE(&(autochan)->lock); \
|
2016-03-11 23:03:08 +01:00
|
|
|
} \
|
2017-03-15 13:24:33 -05:00
|
|
|
ast_mutex_unlock(&(autochan)->lock); \
|
|
|
|
|
} while (0)
|
2016-03-11 23:03:08 +01:00
|
|
|
|
|
|
|
|
#define ast_autochan_channel_unlock(autochan) \
|
|
|
|
|
ast_channel_unlock(autochan->chan)
|
|
|
|
|
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
/*!
|
|
|
|
|
* \brief set up a new ast_autochan structure
|
|
|
|
|
*
|
|
|
|
|
* \details
|
|
|
|
|
* Allocates and initializes an ast_autochan, sets the
|
|
|
|
|
* autochan's chan pointer to point to the chan parameter, and
|
|
|
|
|
* adds the autochan to the global list of autochans. The newly-
|
|
|
|
|
* created autochan is returned to the caller. This function will
|
|
|
|
|
* cause the refcount of chan to increase by 1.
|
|
|
|
|
*
|
|
|
|
|
* \param chan The channel our new autochan will point to
|
|
|
|
|
*
|
|
|
|
|
* \note autochans must be freed using ast_autochan_destroy
|
|
|
|
|
*
|
|
|
|
|
* \retval NULL Failure
|
|
|
|
|
* \retval non-NULL success
|
|
|
|
|
*/
|
|
|
|
|
struct ast_autochan *ast_autochan_setup(struct ast_channel *chan);
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* \brief destroy an ast_autochan structure
|
|
|
|
|
*
|
|
|
|
|
* \details
|
|
|
|
|
* Removes the passed-in autochan from the list of autochans and
|
|
|
|
|
* unrefs the channel that is pointed to. Also frees the autochan
|
|
|
|
|
* struct itself. This function will unref the channel reference
|
|
|
|
|
* which was made in ast_autochan_setup
|
|
|
|
|
*
|
|
|
|
|
* \param autochan The autochan that you wish to destroy
|
|
|
|
|
*/
|
|
|
|
|
void ast_autochan_destroy(struct ast_autochan *autochan);
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* \brief Switch what channel autochans point to
|
|
|
|
|
*
|
|
|
|
|
* \details
|
|
|
|
|
* Traverses the list of autochans. All autochans which point to
|
|
|
|
|
* old_chan will be updated to point to new_chan instead. Currently
|
Fix a deadlock that occurred due to a conflict of masquerades.
For the explanation, here is a copy-paste of the review board explanation:
Initially, it was discovered that performing an attended transfer of a
multiparty bridge with a PJSIP channel would cause a deadlock. A PBX thread
started a masquerade and reached the point where it was calling the fixup()
callback on the "original" channel. For chan_pjsip, this involves pushing a
synchronous task to the session's serializer. The problem was that a task ahead
of the fixup task was also attempting to perform a channel masquerade. However,
since masquerades are designed in a way to only allow for one to occur at a
time, the task ahead of the fixup could not continue until the masquerade
already in progress had completed. And of course, the masquerade in progress
could not complete until the task ahead of the fixup task had completed.
Deadlock.
The initial fix was to change the fixup task to be asynchronous. While this
prevented the deadlock from occurring, it had the frightful side effect of
potentially allowing for tasks in the session's serializer to operate on a
zombie channel.
Taking a step back from this particular deadlock, it became clear that the
problem was not really this one particular issue but that masquerades
themselves needed to be addressed. A PJSIP attended transfer operation calls
ast_channel_move(), which attempts to both set up and execute a masquerade. The
problem was that after it had set up the masquerade, the PBX thread had swooped
in and tried to actually perform the masquerade. Looking at changes that had
been made to Asterisk 12, it became clear that there never is any time now that
anyone ever wants to set up a masquerade and allow for the channel thread to
actually perform the masquerade. Everyone always is calling ast_channel_move(),
performs the masquerade itself before returning.
In this patch, I have removed all blocks of code from channel.c that will
attempt to perform a masquerade if ast_channel_masq() returns true. Now, there
is no distinction between setting up a masquerade and performing the
masquerade. It is one operation. The only remaining checks for
ast_channel_masq() and ast_channel_masqr() are in ast_hangup() since we do not
want to interrupt a masquerade by hanging up the channel. Instead, now
ast_hangup() will wait for a masquerade to complete before moving forward with
its operation.
The ast_channel_move() function has been modified to basically in-line the
logic that used to be in ast_channel_masquerade(). ast_channel_masquerade() has
been killed off for real. ast_channel_move() now has a lock associated with it
that is used to prevent any simultaneous moves from occurring at once. This
means there is no need to make sure that ast_channel_masq() or
ast_channel_masqr() are already set on a channel when ast_channel_move() is
called. It also means the channel container lock is not pulling double duty by
both keeping the container locked and preventing multiple masquerades from
occurring simultaneously.
The ast_do_masquerade() function has been renamed to do_channel_masquerade()
and is now internal to channel.c. The function now takes explicit arguments of
which channels are involved in the masquerade instead of a single channel.
While it probably is possible to do some further refactoring of this method, I
feel that I would be treading dangerously. Instead, all I did was change some
comments that no longer are true after this changeset.
The other more minor change introduced in this patch is to res_pjsip.c to make
ast_sip_push_task_synchronous() run the task in-place if we are already a SIP
servant thread. This is related to this patch because even when we isolate the
channel masquerade to only running in the SIP servant thread, we would still
deadlock when the fixup() callback is reached since we would essentially be
waiting forever for ourselves to finish before actually running the fixup. This
makes it so the fixup is run without having to push a task into a serializer at
all.
(closes issue ASTERISK-22936)
Reported by Jonathan Rose
Review: https://reviewboard.asterisk.org/r/3069
........
Merged revisions 404356 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@404368 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2013-12-19 17:45:21 +00:00
|
|
|
* this is only called during an ast_channel_move() operation in
|
|
|
|
|
* channel.c.
|
|
|
|
|
*
|
Convert the ast_channel data structure over to the astobj2 framework.
There is a lot that could be said about this, but the patch is a big
improvement for performance, stability, code maintainability,
and ease of future code development.
The channel list is no longer an unsorted linked list. The main container
for channels is an astobj2 hash table. All of the code related to searching
for channels or iterating active channels has been rewritten. Let n be
the number of active channels. Iterating the channel list has gone from
O(n^2) to O(n). Searching for a channel by name went from O(n) to O(1).
Searching for a channel by extension is still O(n), but uses a new method
for doing so, which is more efficient.
The ast_channel object is now a reference counted object. The benefits
here are plentiful. Some benefits directly related to issues in the
previous code include:
1) When threads other than the channel thread owning a channel wanted
access to a channel, it had to hold the lock on it to ensure that it didn't
go away. This is no longer a requirement. Holding a reference is
sufficient.
2) There are places that now require less dealing with channel locks.
3) There are places where channel locks are held for much shorter periods
of time.
4) There are places where dealing with more than one channel at a time becomes
_MUCH_ easier. ChanSpy is a great example of this. Writing code in the
future that deals with multiple channels will be much easier.
Some additional information regarding channel locking and reference count
handling can be found in channel.h, where a new section has been added that
discusses some of the rules associated with it.
Mark Michelson also assisted with the development of this patch. He did the
conversion of ChanSpy and introduced a new API, ast_autochan, which makes it
much easier to deal with holding on to a channel pointer for an extended period
of time and having it get automatically updated if the channel gets masqueraded.
Mark was also a huge help in the code review process.
Thanks to David Vossel for his assistance with this branch, as well. David
did the conversion of the DAHDIScan application by making it become a wrapper
for ChanSpy internally.
The changes come from the svn/asterisk/team/russell/ast_channel_ao2 branch.
Review: http://reviewboard.digium.com/r/203/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-04-24 14:04:26 +00:00
|
|
|
* \pre Both channels must be locked before calling this function.
|
|
|
|
|
*
|
|
|
|
|
* \param old_chan The channel that autochans may currently point to
|
|
|
|
|
* \param new_chan The channel that we want to point those autochans to now
|
|
|
|
|
*/
|
|
|
|
|
void ast_autochan_new_channel(struct ast_channel *old_chan, struct ast_channel *new_chan);
|
|
|
|
|
|
|
|
|
|
#endif /* _ASTERISK_AUTOCHAN_H */
|