Channel Management. More...
#include "asterisk.h"
#include "asterisk/_private.h"
#include <sys/time.h>
#include <signal.h>
#include <math.h>
#include "asterisk/paths.h"
#include "asterisk/pbx.h"
#include "asterisk/frame.h"
#include "asterisk/mod_format.h"
#include "asterisk/sched.h"
#include "asterisk/channel.h"
#include "asterisk/musiconhold.h"
#include "asterisk/say.h"
#include "asterisk/file.h"
#include "asterisk/cli.h"
#include "asterisk/translate.h"
#include "asterisk/manager.h"
#include "asterisk/cel.h"
#include "asterisk/chanvars.h"
#include "asterisk/linkedlists.h"
#include "asterisk/indications.h"
#include "asterisk/monitor.h"
#include "asterisk/causes.h"
#include "asterisk/callerid.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/app.h"
#include "asterisk/transcap.h"
#include "asterisk/devicestate.h"
#include "asterisk/threadstorage.h"
#include "asterisk/slinfactory.h"
#include "asterisk/audiohook.h"
#include "asterisk/framehook.h"
#include "asterisk/timing.h"
#include "asterisk/autochan.h"
#include "asterisk/stringfields.h"
#include "asterisk/global_datastores.h"
#include "asterisk/data.h"
#include "asterisk/features.h"
#include "asterisk/test.h"
Go to the source code of this file.
Data Structures | |
struct | ast_channel_iterator |
struct | ast_epoll_data |
struct | ast_party_id_ies |
struct | ast_party_name_ies |
struct | ast_party_number_ies |
struct | ast_party_subaddress_ies |
struct | ast_silence_generator |
struct | backends |
the list of registered channel types More... | |
struct | causes_map |
map AST_CAUSE's to readable string representations More... | |
struct | chanlist |
List of channel drivers. More... | |
struct | plc_ds |
struct | tonepair_def |
struct | tonepair_state |
struct | xfer_masquerade_ds |
Defines | |
#define | AST_DEFAULT_EMULATE_DTMF_DURATION 100 |
#define | AST_MIN_DTMF_DURATION 80 |
#define | AST_MIN_DTMF_GAP 45 |
#define | DATA_EXPORT_CHANNEL(MEMBER) |
#define | FORMAT "%-10.10s %-40.40s %-12.12s %-12.12s %-12.12s\n" |
#define | NUM_CHANNEL_BUCKETS 1567 |
#define | STATE2STR_BUFSIZE 32 |
Enumerations | |
enum | { AST_CONNECTED_LINE_NUMBER, AST_CONNECTED_LINE_NAME, AST_CONNECTED_LINE_NUMBER_PLAN, AST_CONNECTED_LINE_ID_PRESENTATION, AST_CONNECTED_LINE_SOURCE, AST_CONNECTED_LINE_SUBADDRESS, AST_CONNECTED_LINE_SUBADDRESS_TYPE, AST_CONNECTED_LINE_SUBADDRESS_ODD_EVEN, AST_CONNECTED_LINE_SUBADDRESS_VALID, AST_CONNECTED_LINE_TAG, AST_CONNECTED_LINE_VERSION, AST_CONNECTED_LINE_NAME_VALID, AST_CONNECTED_LINE_NAME_CHAR_SET, AST_CONNECTED_LINE_NAME_PRESENTATION, AST_CONNECTED_LINE_NUMBER_VALID, AST_CONNECTED_LINE_NUMBER_PRESENTATION } |
Element identifiers for connected line indication frame data. More... | |
enum | { AST_REDIRECTING_FROM_NUMBER, AST_REDIRECTING_FROM_NAME, AST_REDIRECTING_FROM_NUMBER_PLAN, AST_REDIRECTING_FROM_ID_PRESENTATION, AST_REDIRECTING_TO_NUMBER, AST_REDIRECTING_TO_NAME, AST_REDIRECTING_TO_NUMBER_PLAN, AST_REDIRECTING_TO_ID_PRESENTATION, AST_REDIRECTING_REASON, AST_REDIRECTING_COUNT, AST_REDIRECTING_FROM_SUBADDRESS, AST_REDIRECTING_FROM_SUBADDRESS_TYPE, AST_REDIRECTING_FROM_SUBADDRESS_ODD_EVEN, AST_REDIRECTING_FROM_SUBADDRESS_VALID, AST_REDIRECTING_TO_SUBADDRESS, AST_REDIRECTING_TO_SUBADDRESS_TYPE, AST_REDIRECTING_TO_SUBADDRESS_ODD_EVEN, AST_REDIRECTING_TO_SUBADDRESS_VALID, AST_REDIRECTING_FROM_TAG, AST_REDIRECTING_TO_TAG, AST_REDIRECTING_VERSION, AST_REDIRECTING_FROM_NAME_VALID, AST_REDIRECTING_FROM_NAME_CHAR_SET, AST_REDIRECTING_FROM_NAME_PRESENTATION, AST_REDIRECTING_FROM_NUMBER_VALID, AST_REDIRECTING_FROM_NUMBER_PRESENTATION, AST_REDIRECTING_TO_NAME_VALID, AST_REDIRECTING_TO_NAME_CHAR_SET, AST_REDIRECTING_TO_NAME_PRESENTATION, AST_REDIRECTING_TO_NUMBER_VALID, AST_REDIRECTING_TO_NUMBER_PRESENTATION } |
Element identifiers for redirecting indication frame data. More... | |
Functions | |
int | __ast_answer (struct ast_channel *chan, unsigned int delay, int cdr_answer) |
Answer a channel, with a selectable delay before returning. | |
static void | __ast_change_name_nolink (struct ast_channel *chan, const char *newname) |
this function simply changes the name of the channel and issues a manager_event with out unlinking and linking the channel from the ao2_container. This should only be used when the channel has already been unlinked from the ao2_container. | |
struct ast_channel * | __ast_channel_alloc (int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const char *linkedid, const int amaflag, const char *file, int line, const char *function, const char *name_fmt,...) |
Create a channel structure. | |
static struct ast_channel *attribute_malloc | __ast_channel_alloc_ap (int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const char *linkedid, const int amaflag, const char *file, int line, const char *function, const char *name_fmt, va_list ap1, va_list ap2) |
Create a new channel structure. | |
static int | __ast_channel_masquerade (struct ast_channel *original, struct ast_channel *clonechan, struct ast_datastore *xfer_ds) |
struct ast_channel * | __ast_dummy_channel_alloc (const char *file, int line, const char *function) |
static int | __ast_queue_frame (struct ast_channel *chan, struct ast_frame *fin, int head, struct ast_frame *after) |
static struct ast_frame * | __ast_read (struct ast_channel *chan, int dropaudio) |
struct ast_channel * | __ast_request_and_dial (const char *type, format_t format, const struct ast_channel *requestor, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, struct outgoing_helper *oh) |
Request a channel of a given type, with data as optional information used by the low level module and attempt to place a call on it. | |
static void | __init_state2str_threadbuf (void) |
static void | adjust_frame_for_plc (struct ast_channel *chan, struct ast_frame *frame, struct ast_datastore *datastore) |
static void | apply_plc (struct ast_channel *chan, struct ast_frame *frame) |
int | ast_activate_generator (struct ast_channel *chan, struct ast_generator *gen, void *params) |
int | ast_active_channels (void) |
returns number of active/allocated channels | |
int | ast_answer (struct ast_channel *chan) |
Answer a channel. | |
void | ast_begin_shutdown (int hangup) |
format_t | ast_best_codec (format_t fmts) |
Pick the best audio codec. | |
struct ast_channel * | ast_bridged_channel (struct ast_channel *chan) |
Find bridged channel. | |
int | ast_call (struct ast_channel *chan, char *addr, int timeout) |
Make a call. | |
struct ast_channel * | ast_call_forward (struct ast_channel *caller, struct ast_channel *orig, int *timeout, format_t format, struct outgoing_helper *oh, int *outstate) |
Forwards a call to a new channel specified by the original channel's call_forward str. If possible, the new forwarded channel is created and returned while the original one is terminated. | |
void | ast_cancel_shutdown (void) |
Cancel a shutdown in progress. | |
const char * | ast_cause2str (int cause) |
Gives the string form of a given hangup cause. | |
void | ast_change_name (struct ast_channel *chan, const char *newname) |
Change channel name. | |
struct ast_channel * | ast_channel_alloc (int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const char *linkedid, const int amaflag, const char *name_fmt,...) |
enum ast_bridge_result | ast_channel_bridge (struct ast_channel *c0, struct ast_channel *c1, struct ast_bridge_config *config, struct ast_frame **fo, struct ast_channel **rc) |
Bridge two channels together. | |
struct ast_channel * | ast_channel_callback (ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags) |
Call a function with every active channel. | |
int | ast_channel_cc_params_init (struct ast_channel *chan, const struct ast_cc_config_params *base_params) |
Set up datastore with CCSS parameters for a channel. | |
static void | ast_channel_change_linkedid (struct ast_channel *chan, const char *linkedid) |
void | ast_channel_clear_softhangup (struct ast_channel *chan, int flag) |
Clear a set of softhangup flags from a channel. | |
static int | ast_channel_cmp_cb (void *obj, void *arg, int flags) |
int | ast_channel_cmpwhentohangup (struct ast_channel *chan, time_t offset) |
Compare a offset with the settings of when to hang a channel up. | |
int | ast_channel_cmpwhentohangup_tv (struct ast_channel *chan, struct timeval offset) |
Compare a offset with when to hangup channel. | |
int | ast_channel_connected_line_macro (struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *connected_info, int is_caller, int is_frame) |
Run a connected line interception macro and update a channel's connected line information. | |
int | ast_channel_data_add_structure (struct ast_data *tree, struct ast_channel *chan, int add_bridged) |
Insert into an astdata tree, the channel structure. | |
int | ast_channel_data_cmp_structure (const struct ast_data_search *tree, struct ast_channel *chan, const char *structure_name) |
Compare to channel structures using the data api. | |
int | ast_channel_datastore_add (struct ast_channel *chan, struct ast_datastore *datastore) |
Add a datastore to a channel. | |
struct ast_datastore * | ast_channel_datastore_alloc (const struct ast_datastore_info *info, const char *uid) |
Create a channel data store object. | |
struct ast_datastore * | ast_channel_datastore_find (struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid) |
Find a datastore on a channel. | |
int | ast_channel_datastore_free (struct ast_datastore *datastore) |
Free a channel data store object. | |
int | ast_channel_datastore_inherit (struct ast_channel *from, struct ast_channel *to) |
Inherit datastores from a parent to a child. | |
int | ast_channel_datastore_remove (struct ast_channel *chan, struct ast_datastore *datastore) |
Remove a datastore from a channel. | |
int | ast_channel_defer_dtmf (struct ast_channel *chan) |
Set defer DTMF flag on channel. | |
static void | ast_channel_destructor (void *obj) |
Free a channel structure. | |
int | ast_channel_early_bridge (struct ast_channel *c0, struct ast_channel *c1) |
Bridge two channels together (early). | |
struct ast_channel * | ast_channel_get_by_exten (const char *exten, const char *context) |
Find a channel by extension and context. | |
struct ast_channel * | ast_channel_get_by_name (const char *name) |
Find a channel by name. | |
struct ast_channel * | ast_channel_get_by_name_prefix (const char *name, size_t name_len) |
Find a channel by a name prefix. | |
int | ast_channel_get_cc_agent_type (struct ast_channel *chan, char *agent_type, size_t size) |
Find the appropriate CC agent type to use given a channel. | |
struct ast_cc_config_params * | ast_channel_get_cc_config_params (struct ast_channel *chan) |
Get the CCSS parameters from a channel. | |
int | ast_channel_get_device_name (struct ast_channel *chan, char *device_name, size_t name_buffer_length) |
Get a device name given its channel structure. | |
static struct ast_channel * | ast_channel_get_full (const char *name, size_t name_len, const char *exten, const char *context) |
static int | ast_channel_hash_cb (const void *obj, const int flags) |
void | ast_channel_inherit_variables (const struct ast_channel *parent, struct ast_channel *child) |
Inherits channel variable from parent to child channel. | |
struct ast_channel_iterator * | ast_channel_iterator_all_new (void) |
Create a new channel iterator. | |
struct ast_channel_iterator * | ast_channel_iterator_by_exten_new (const char *exten, const char *context) |
Create a new channel iterator based on extension. | |
struct ast_channel_iterator * | ast_channel_iterator_by_name_new (const char *name, size_t name_len) |
Create a new channel iterator based on name. | |
struct ast_channel_iterator * | ast_channel_iterator_destroy (struct ast_channel_iterator *i) |
Destroy a channel iterator. | |
struct ast_channel * | ast_channel_iterator_next (struct ast_channel_iterator *i) |
Get the next channel for a channel iterator. | |
int | ast_channel_make_compatible (struct ast_channel *chan, struct ast_channel *peer) |
Makes two channel formats compatible. | |
static int | ast_channel_make_compatible_helper (struct ast_channel *from, struct ast_channel *to) |
Set up translation from one channel to another. | |
int | ast_channel_masquerade (struct ast_channel *original, struct ast_channel *clone) |
Weird function made for call transfers. | |
int | ast_channel_queryoption (struct ast_channel *chan, int option, void *data, int *datalen, int block) |
Checks the value of an option. | |
void | ast_channel_queue_connected_line_update (struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update) |
Queue a connected line update frame on a channel. | |
void | ast_channel_queue_redirecting_update (struct ast_channel *chan, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update) |
Queue a redirecting update frame on a channel. | |
const char * | ast_channel_reason2str (int reason) |
return an english explanation of the code returned thru __ast_request_and_dial's 'outstate' argument | |
int | ast_channel_redirecting_macro (struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *redirecting_info, int is_caller, int is_frame) |
Run a redirecting interception macro and update a channel's redirecting information. | |
int | ast_channel_register (const struct ast_channel_tech *tech) |
Register a new telephony channel in Asterisk. | |
struct ast_channel * | ast_channel_release (struct ast_channel *chan) |
Unlink and release reference to a channel. | |
int | ast_channel_sendhtml (struct ast_channel *chan, int subclass, const char *data, int datalen) |
Sends HTML on given channel Send HTML or URL on link. | |
int | ast_channel_sendurl (struct ast_channel *chan, const char *url) |
Sends a URL on a given link Send URL on link. | |
void | ast_channel_set_caller (struct ast_channel *chan, const struct ast_party_caller *caller, const struct ast_set_party_caller *update) |
Set the caller id information in the Asterisk channel. | |
void | ast_channel_set_caller_event (struct ast_channel *chan, const struct ast_party_caller *caller, const struct ast_set_party_caller *update) |
Set the caller id information in the Asterisk channel and generate an AMI event if the caller id name or number changed. | |
void | ast_channel_set_connected_line (struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update) |
Set the connected line information in the Asterisk channel. | |
void | ast_channel_set_fd (struct ast_channel *chan, int which, int fd) |
void | ast_channel_set_linkgroup (struct ast_channel *chan, struct ast_channel *peer) |
Propagate the oldest linkedid between associated channels. | |
void | ast_channel_set_redirecting (struct ast_channel *chan, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update) |
Set the redirecting id information in the Asterisk channel. | |
int | ast_channel_setoption (struct ast_channel *chan, int option, void *data, int datalen, int block) |
Sets an option on a channel. | |
void | ast_channel_setwhentohangup (struct ast_channel *chan, time_t offset) |
Set when to hang a channel up. | |
void | ast_channel_setwhentohangup_tv (struct ast_channel *chan, struct timeval offset) |
Set when to hangup channel. | |
static int | ast_channel_softhangup_cb (void *obj, void *arg, int flags) |
struct ast_silence_generator * | ast_channel_start_silence_generator (struct ast_channel *chan) |
Starts a silence generator on the given channel. | |
void | ast_channel_stop_silence_generator (struct ast_channel *chan, struct ast_silence_generator *state) |
Stops a previously-started silence generator on the given channel. | |
int | ast_channel_supports_html (struct ast_channel *chan) |
Checks for HTML support on a channel. | |
int | ast_channel_transfer_masquerade (struct ast_channel *target_chan, const struct ast_party_connected_line *target_id, int target_held, struct ast_channel *transferee_chan, const struct ast_party_connected_line *transferee_id, int transferee_held) |
Setup a masquerade to transfer a call. | |
void | ast_channel_undefer_dtmf (struct ast_channel *chan) |
Unset defer DTMF flag on channel. | |
void | ast_channel_unregister (const struct ast_channel_tech *tech) |
Unregister channel driver. | |
void | ast_channel_update_connected_line (struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update) |
Indicate that the connected line information has changed. | |
void | ast_channel_update_redirecting (struct ast_channel *chan, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update) |
Indicate that the redirecting id has changed. | |
void | ast_channels_init (void) |
struct ast_variable * | ast_channeltype_list (void) |
return an ast_variable list of channeltypes | |
int | ast_check_hangup (struct ast_channel *chan) |
Checks to see if a channel is needing hang up. | |
int | ast_check_hangup_locked (struct ast_channel *chan) |
int | ast_connected_line_build_data (unsigned char *data, size_t datalen, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update) |
Build the connected line information data frame. | |
void | ast_connected_line_copy_from_caller (struct ast_party_connected_line *dest, const struct ast_party_caller *src) |
Copy the caller information to the connected line information. | |
void | ast_connected_line_copy_to_caller (struct ast_party_caller *dest, const struct ast_party_connected_line *src) |
Copy the connected line information to the caller information. | |
int | ast_connected_line_parse_data (const unsigned char *data, size_t datalen, struct ast_party_connected_line *connected) |
Parse connected line indication frame data. | |
AST_DATA_STRUCTURE (ast_channel, DATA_EXPORT_CHANNEL) | |
void | ast_deactivate_generator (struct ast_channel *chan) |
int | ast_do_masquerade (struct ast_channel *original) |
Masquerade a channel. | |
static void | ast_dummy_channel_destructor (void *obj) |
Free a dummy channel structure. | |
static enum ast_bridge_result | ast_generic_bridge (struct ast_channel *c0, struct ast_channel *c1, struct ast_bridge_config *config, struct ast_frame **fo, struct ast_channel **rc) |
struct ast_channel_tech * | ast_get_channel_tech (const char *name) |
Get handle to channel driver based on name. | |
ast_group_t | ast_get_group (const char *s) |
int | ast_hangup (struct ast_channel *chan) |
Hangup a channel. | |
int | ast_indicate (struct ast_channel *chan, int condition) |
Indicates condition of channel. | |
int | ast_indicate_data (struct ast_channel *chan, int _condition, const void *data, size_t datalen) |
Indicates condition of channel, with payload. | |
void | ast_install_music_functions (int(*start_ptr)(struct ast_channel *, const char *, const char *), void(*stop_ptr)(struct ast_channel *), void(*cleanup_ptr)(struct ast_channel *)) |
int | ast_internal_timing_enabled (struct ast_channel *chan) |
Check if the channel can run in internal timing mode. | |
int | ast_is_deferrable_frame (const struct ast_frame *frame) |
Should we keep this frame for later? | |
void | ast_moh_cleanup (struct ast_channel *chan) |
int | ast_moh_start (struct ast_channel *chan, const char *mclass, const char *interpclass) |
Turn on music on hold on a given channel. | |
void | ast_moh_stop (struct ast_channel *chan) |
Turn off music on hold on a given channel. | |
void | ast_party_caller_copy (struct ast_party_caller *dest, const struct ast_party_caller *src) |
Copy the source caller information to the destination caller. | |
void | ast_party_caller_free (struct ast_party_caller *doomed) |
Destroy the caller party contents. | |
void | ast_party_caller_init (struct ast_party_caller *init) |
Initialize the given caller structure. | |
void | ast_party_caller_set (struct ast_party_caller *dest, const struct ast_party_caller *src, const struct ast_set_party_caller *update) |
Set the caller information based on another caller source. | |
void | ast_party_caller_set_init (struct ast_party_caller *init, const struct ast_party_caller *guide) |
Initialize the given caller structure using the given guide for a set update operation. | |
void | ast_party_connected_line_collect_caller (struct ast_party_connected_line *connected, struct ast_party_caller *caller) |
Collect the caller party information into a connected line structure. | |
void | ast_party_connected_line_copy (struct ast_party_connected_line *dest, const struct ast_party_connected_line *src) |
Copy the source connected line information to the destination connected line. | |
void | ast_party_connected_line_free (struct ast_party_connected_line *doomed) |
Destroy the connected line information contents. | |
void | ast_party_connected_line_init (struct ast_party_connected_line *init) |
Initialize the given connected line structure. | |
void | ast_party_connected_line_set (struct ast_party_connected_line *dest, const struct ast_party_connected_line *src, const struct ast_set_party_connected_line *update) |
Set the connected line information based on another connected line source. | |
void | ast_party_connected_line_set_init (struct ast_party_connected_line *init, const struct ast_party_connected_line *guide) |
Initialize the given connected line structure using the given guide for a set update operation. | |
void | ast_party_dialed_copy (struct ast_party_dialed *dest, const struct ast_party_dialed *src) |
Copy the source dialed party information to the destination dialed party. | |
void | ast_party_dialed_free (struct ast_party_dialed *doomed) |
Destroy the dialed party contents. | |
void | ast_party_dialed_init (struct ast_party_dialed *init) |
Initialize the given dialed structure. | |
void | ast_party_dialed_set (struct ast_party_dialed *dest, const struct ast_party_dialed *src) |
Set the dialed information based on another dialed source. | |
void | ast_party_dialed_set_init (struct ast_party_dialed *init, const struct ast_party_dialed *guide) |
Initialize the given dialed structure using the given guide for a set update operation. | |
void | ast_party_id_copy (struct ast_party_id *dest, const struct ast_party_id *src) |
Copy the source party id information to the destination party id. | |
void | ast_party_id_free (struct ast_party_id *doomed) |
Destroy the party id contents. | |
void | ast_party_id_init (struct ast_party_id *init) |
Initialize the given party id structure. | |
int | ast_party_id_presentation (const struct ast_party_id *id) |
Determine the overall presentation value for the given party. | |
void | ast_party_id_set (struct ast_party_id *dest, const struct ast_party_id *src, const struct ast_set_party_id *update) |
Set the source party id information into the destination party id. | |
void | ast_party_id_set_init (struct ast_party_id *init, const struct ast_party_id *guide) |
Initialize the given party id structure using the given guide for a set update operation. | |
void | ast_party_name_copy (struct ast_party_name *dest, const struct ast_party_name *src) |
Copy the source party name information to the destination party name. | |
void | ast_party_name_free (struct ast_party_name *doomed) |
Destroy the party name contents. | |
void | ast_party_name_init (struct ast_party_name *init) |
Initialize the given name structure. | |
void | ast_party_name_set (struct ast_party_name *dest, const struct ast_party_name *src) |
Set the source party name information into the destination party name. | |
void | ast_party_name_set_init (struct ast_party_name *init, const struct ast_party_name *guide) |
Initialize the given party name structure using the given guide for a set update operation. | |
void | ast_party_number_copy (struct ast_party_number *dest, const struct ast_party_number *src) |
Copy the source party number information to the destination party number. | |
void | ast_party_number_free (struct ast_party_number *doomed) |
Destroy the party number contents. | |
void | ast_party_number_init (struct ast_party_number *init) |
Initialize the given number structure. | |
void | ast_party_number_set (struct ast_party_number *dest, const struct ast_party_number *src) |
Set the source party number information into the destination party number. | |
void | ast_party_number_set_init (struct ast_party_number *init, const struct ast_party_number *guide) |
Initialize the given party number structure using the given guide for a set update operation. | |
void | ast_party_redirecting_copy (struct ast_party_redirecting *dest, const struct ast_party_redirecting *src) |
Copy the source redirecting information to the destination redirecting. | |
void | ast_party_redirecting_free (struct ast_party_redirecting *doomed) |
Destroy the redirecting information contents. | |
void | ast_party_redirecting_init (struct ast_party_redirecting *init) |
Initialize the given redirecting structure. | |
void | ast_party_redirecting_set (struct ast_party_redirecting *dest, const struct ast_party_redirecting *src, const struct ast_set_party_redirecting *update) |
Set the redirecting information based on another redirecting source. | |
void | ast_party_redirecting_set_init (struct ast_party_redirecting *init, const struct ast_party_redirecting *guide) |
Initialize the given redirecting id structure using the given guide for a set update operation. | |
void | ast_party_subaddress_copy (struct ast_party_subaddress *dest, const struct ast_party_subaddress *src) |
Copy the source party subaddress information to the destination party subaddress. | |
void | ast_party_subaddress_free (struct ast_party_subaddress *doomed) |
Destroy the party subaddress contents. | |
void | ast_party_subaddress_init (struct ast_party_subaddress *init) |
Initialize the given subaddress structure. | |
void | ast_party_subaddress_set (struct ast_party_subaddress *dest, const struct ast_party_subaddress *src) |
Set the source party subaddress information into the destination party subaddress. | |
void | ast_party_subaddress_set_init (struct ast_party_subaddress *init, const struct ast_party_subaddress *guide) |
Initialize the given party subaddress structure using the given guide for a set update operation. | |
int | ast_plc_reload (void) |
Reload genericplc configuration value from codecs.conf. | |
void | ast_poll_channel_add (struct ast_channel *chan0, struct ast_channel *chan1) |
void | ast_poll_channel_del (struct ast_channel *chan0, struct ast_channel *chan1) |
char * | ast_print_group (char *buf, int buflen, ast_group_t group) |
Print call group and pickup group ---. | |
int | ast_prod (struct ast_channel *chan) |
Send empty audio to prime a channel driver. | |
int | ast_queue_control (struct ast_channel *chan, enum ast_control_frame_type control) |
Queue a control frame. | |
int | ast_queue_control_data (struct ast_channel *chan, enum ast_control_frame_type control, const void *data, size_t datalen) |
Queue a control frame with payload. | |
int | ast_queue_frame (struct ast_channel *chan, struct ast_frame *fin) |
Queue one or more frames to a channel's frame queue. | |
int | ast_queue_frame_head (struct ast_channel *chan, struct ast_frame *fin) |
Queue one or more frames to the head of a channel's frame queue. | |
int | ast_queue_hangup (struct ast_channel *chan) |
Queue a hangup frame for channel. | |
int | ast_queue_hangup_with_cause (struct ast_channel *chan, int cause) |
Queue a hangup frame for channel. | |
int | ast_raw_answer (struct ast_channel *chan, int cdr_answer) |
Answer a channel. | |
struct ast_frame * | ast_read (struct ast_channel *chan) |
Reads a frame. | |
static void | ast_read_generator_actions (struct ast_channel *chan, struct ast_frame *f) |
struct ast_frame * | ast_read_noaudio (struct ast_channel *chan) |
Reads a frame, returning AST_FRAME_NULL frame if audio. | |
int | ast_readstring (struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders) |
Reads multiple digits. | |
int | ast_readstring_full (struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders, int audiofd, int ctrlfd) |
int | ast_recvchar (struct ast_channel *chan, int timeout) |
Receives a text character from a channel. | |
char * | ast_recvtext (struct ast_channel *chan, int timeout) |
Receives a text string from a channel Read a string of text from a channel. | |
int | ast_redirecting_build_data (unsigned char *data, size_t datalen, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update) |
Build the redirecting id data frame. | |
int | ast_redirecting_parse_data (const unsigned char *data, size_t datalen, struct ast_party_redirecting *redirecting) |
Parse redirecting indication frame data. | |
struct ast_channel * | ast_request (const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause) |
Requests a channel. | |
struct ast_channel * | ast_request_and_dial (const char *type, format_t format, const struct ast_channel *requestor, void *data, int timeout, int *outstate, const char *cidnum, const char *cidname) |
Request a channel of a given type, with data as optional information used by the low level module and attempt to place a call on it. | |
int | ast_safe_sleep (struct ast_channel *chan, int ms) |
Wait, look for hangups. | |
int | ast_safe_sleep_conditional (struct ast_channel *chan, int timeout_ms, int(*cond)(void *), void *data) |
Wait, look for hangups and condition arg. | |
int | ast_say_character_str (struct ast_channel *chan, const char *str, const char *ints, const char *lang) |
int | ast_say_digit_str (struct ast_channel *chan, const char *str, const char *ints, const char *lang) |
says digits of a string | |
int | ast_say_digits (struct ast_channel *chan, int num, const char *ints, const char *lang) |
says digits | |
int | ast_say_digits_full (struct ast_channel *chan, int num, const char *ints, const char *lang, int audiofd, int ctrlfd) |
int | ast_say_enumeration (struct ast_channel *chan, int num, const char *ints, const char *language, const char *options) |
says an enumeration | |
int | ast_say_number (struct ast_channel *chan, int num, const char *ints, const char *language, const char *options) |
says a number | |
int | ast_say_phonetic_str (struct ast_channel *chan, const char *str, const char *ints, const char *lang) |
int | ast_senddigit (struct ast_channel *chan, char digit, unsigned int duration) |
Send a DTMF digit to a channel. | |
int | ast_senddigit_begin (struct ast_channel *chan, char digit) |
Send a DTMF digit to a channel. | |
int | ast_senddigit_end (struct ast_channel *chan, char digit, unsigned int duration) |
Send a DTMF digit to a channel. | |
int | ast_sendtext (struct ast_channel *chan, const char *text) |
Sends text to a channel. | |
void | ast_set_callerid (struct ast_channel *chan, const char *cid_num, const char *cid_name, const char *cid_ani) |
Set caller ID number, name and ANI and generate AMI event. | |
void | ast_set_hangupsource (struct ast_channel *chan, const char *source, int force) |
Set the source of the hangup in this channel and it's bridge. | |
static void | ast_set_owners_and_peers (struct ast_channel *chan1, struct ast_channel *chan2) |
int | ast_set_read_format (struct ast_channel *chan, format_t fmt) |
Sets read format on channel chan Set read format for channel to whichever component of "format" is best. | |
void | ast_set_variables (struct ast_channel *chan, struct ast_variable *vars) |
adds a list of channel variables to a channel | |
int | ast_set_write_format (struct ast_channel *chan, format_t fmt) |
Sets write format on channel chan Set write format for channel to whichever component of "format" is best. | |
int | ast_setstate (struct ast_channel *chan, enum ast_channel_state state) |
Change the state of a channel. | |
int | ast_settimeout (struct ast_channel *c, unsigned int rate, int(*func)(const void *data), void *data) |
Enable or disable timer ticks for a channel. | |
int | ast_settimeout_full (struct ast_channel *c, unsigned int rate, int(*func)(const void *data), void *data, unsigned int is_ao2_obj) |
int | ast_shutting_down (void) |
Returns non-zero if Asterisk is being shut down. | |
int | ast_softhangup (struct ast_channel *chan, int cause) |
Softly hangup a channel, lock. | |
int | ast_softhangup_nolock (struct ast_channel *chan, int cause) |
Softly hangup a channel, don't lock. | |
const char * | ast_state2str (enum ast_channel_state state) |
Gives the string form of a given channel state. | |
int | ast_str2cause (const char *name) |
Convert a symbolic hangup cause to number. | |
int | ast_tonepair (struct ast_channel *chan, int freq1, int freq2, int duration, int vol) |
int | ast_tonepair_start (struct ast_channel *chan, int freq1, int freq2, int duration, int vol) |
void | ast_tonepair_stop (struct ast_channel *chan) |
int | ast_transfer (struct ast_channel *chan, char *dest) |
Transfer a call to dest, if the channel supports transfer. | |
char * | ast_transfercapability2str (int transfercapability) |
Gives the string form of a given transfer capability. | |
int | ast_undestroyed_channels (void) |
void | ast_uninstall_music_functions (void) |
int | ast_waitfor (struct ast_channel *c, int ms) |
Wait for input on a channel. | |
struct ast_channel * | ast_waitfor_n (struct ast_channel **c, int n, int *ms) |
Waits for input on a group of channels Wait for input on an array of channels for a given # of milliseconds. | |
int | ast_waitfor_n_fd (int *fds, int n, int *ms, int *exception) |
Wait for x amount of time on a file descriptor to have input. | |
struct ast_channel * | ast_waitfor_nandfds (struct ast_channel **c, int n, int *fds, int nfds, int *exception, int *outfd, int *ms) |
Wait for x amount of time on a file descriptor to have input. | |
int | ast_waitfordigit (struct ast_channel *c, int ms) |
Waits for a digit. | |
int | ast_waitfordigit_full (struct ast_channel *c, int timeout_ms, int audiofd, int cmdfd) |
Wait for a digit Same as ast_waitfordigit() with audio fd for outputting read audio and ctrlfd to monitor for reading. | |
int | ast_write (struct ast_channel *chan, struct ast_frame *fr) |
Write a frame to a channel This function writes the given frame to the indicated channel. | |
int | ast_write_video (struct ast_channel *chan, struct ast_frame *fr) |
Write video frame to a channel This function writes the given frame to the indicated channel. | |
static void | bridge_play_sounds (struct ast_channel *c0, struct ast_channel *c1) |
static void | bridge_playfile (struct ast_channel *chan, struct ast_channel *peer, const char *sound, int remain) |
static int | calc_monitor_jump (int samples, int sample_rate, int seek_rate) |
calculates the number of samples to jump forward with in a monitor stream. | |
static void | call_forward_inherit (struct ast_channel *new_chan, struct ast_channel *parent, struct ast_channel *orig) |
static void * | channel_cc_params_copy (void *data) |
static void | channel_cc_params_destroy (void *data) |
static void | channel_data_add_flags (struct ast_data *tree, struct ast_channel *chan) |
static struct ast_channel_iterator * | channel_iterator_search (const char *name, size_t name_len, const char *exten, const char *context) |
const char * | channelreloadreason2txt (enum channelreloadreason reason) |
Convert enum channelreloadreason to text string for manager event. | |
static void | channels_shutdown (void) |
static void | clone_variables (struct ast_channel *original, struct ast_channel *clonechan) |
Clone channel variables from 'clone' channel into 'original' channel. | |
static char * | complete_channeltypes (struct ast_cli_args *a) |
static int | data_channels_provider_handler (const struct ast_data_search *search, struct ast_data *root) |
static int | data_channeltypes_provider_handler (const struct ast_data_search *search, struct ast_data *data_root) |
static void | deactivate_generator_nolock (struct ast_channel *chan) |
static int | deactivate_silence_generator (struct ast_channel *chan) |
static void | destroy_hooks (struct ast_channel *chan) |
static void | free_translation (struct ast_channel *clonechan) |
static int | generator_force (const void *data) |
static void | handle_cause (int cause, int *outstate) |
static char * | handle_cli_core_show_channeltype (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Show details about a channel driver - CLI command. | |
static char * | handle_cli_core_show_channeltypes (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Show channel types - CLI command. | |
static int attribute_const | is_visible_indication (enum ast_control_frame_type condition) |
static struct ast_frame * | kill_exception (struct ast_channel *chan) |
static int | kill_fixup (struct ast_channel *oldchan, struct ast_channel *newchan) |
static int | kill_hangup (struct ast_channel *chan) |
static struct ast_frame * | kill_read (struct ast_channel *chan) |
static int | kill_write (struct ast_channel *chan, struct ast_frame *frame) |
static void | manager_bridge_event (int onoff, int type, struct ast_channel *c0, struct ast_channel *c1) |
Send manager event for bridge link and unlink events. | |
static void | masquerade_colp_transfer (struct ast_channel *transferee, struct xfer_masquerade_ds *colp) |
static const char * | oldest_linkedid (const char *a, const char *b) |
static void | party_connected_line_copy_transfer (struct ast_party_connected_line *dest, const struct ast_party_connected_line *src) |
static int | party_id_build_data (unsigned char *data, size_t datalen, const struct ast_party_id *id, const char *label, const struct ast_party_id_ies *ies, const struct ast_set_party_id *update) |
static int | party_name_build_data (unsigned char *data, size_t datalen, const struct ast_party_name *name, const char *label, const struct ast_party_name_ies *ies) |
static int | party_number_build_data (unsigned char *data, size_t datalen, const struct ast_party_number *number, const char *label, const struct ast_party_number_ies *ies) |
static int | party_subaddress_build_data (unsigned char *data, size_t datalen, const struct ast_party_subaddress *subaddress, const char *label, const struct ast_party_subaddress_ies *ies) |
static void | plc_ds_destroy (void *data) |
static void | queue_dtmf_readq (struct ast_channel *chan, struct ast_frame *f) |
static void | report_new_callerid (struct ast_channel *chan) |
static void | send_dtmf_event (struct ast_channel *chan, const char *direction, const char digit, const char *begin, const char *end) |
static int | set_format (struct ast_channel *chan, format_t fmt, format_t *rawformat, format_t *format, struct ast_trans_pvt **trans, const int direction) |
static int | set_security_requirements (const struct ast_channel *requestor, struct ast_channel *out) |
static int | should_skip_dtmf (struct ast_channel *chan) |
Determine whether or not we should ignore DTMF in the readq. | |
static void * | silence_generator_alloc (struct ast_channel *chan, void *data) |
static int | silence_generator_generate (struct ast_channel *chan, void *data, int len, int samples) |
static void | silence_generator_release (struct ast_channel *chan, void *data) |
static void * | tonepair_alloc (struct ast_channel *chan, void *params) |
static int | tonepair_generator (struct ast_channel *chan, void *data, int len, int samples) |
static void | tonepair_release (struct ast_channel *chan, void *params) |
static void | update_bridge_vars (struct ast_channel *c0, struct ast_channel *c1) |
static void | xfer_ds_destroy (void *data) |
Variables | |
struct ast_channel_tech | ast_kill_tech |
Kill the channel channel driver technology descriptor. | |
static void(* | ast_moh_cleanup_ptr )(struct ast_channel *) = NULL |
static int(* | ast_moh_start_ptr )(struct ast_channel *, const char *, const char *) = NULL |
static void(* | ast_moh_stop_ptr )(struct ast_channel *) = NULL |
static struct causes_map | causes [] |
static struct ast_datastore_info | cc_channel_datastore_info |
static int | chancount |
static struct ast_data_entry | channel_providers [] |
static struct ao2_container * | channels |
All active channels on the system. | |
static struct ast_data_handler | channels_provider |
static struct ast_data_handler | channeltypes_provider |
static struct ast_cli_entry | cli_channel [] |
unsigned long | global_fin |
unsigned long | global_fout |
static struct ast_channel_tech | null_tech |
static struct ast_datastore_info | plc_ds_info |
static int | shutting_down |
Prevent new channel allocation if shutting down. | |
static struct ast_generator | silence_generator |
static struct ast_threadstorage | state2str_threadbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_state2str_threadbuf , .custom_init = NULL , } |
static struct ast_generator | tonepair |
static int | uniqueint |
static struct ast_datastore_info | xfer_ds_info |
Channel Management.
Definition in file channel.c.
#define AST_DEFAULT_EMULATE_DTMF_DURATION 100 |
Default amount of time to use when emulating a digit as a begin and end 100ms
Definition at line 111 of file channel.c.
Referenced by __ast_read(), and ast_senddigit().
#define AST_MIN_DTMF_DURATION 80 |
Minimum allowed digit length - 80ms
Definition at line 114 of file channel.c.
Referenced by __ast_read().
#define AST_MIN_DTMF_GAP 45 |
Minimum amount of time between the end of the last digit and the beginning of a new one - 45ms
Definition at line 118 of file channel.c.
Referenced by __ast_read(), and should_skip_dtmf().
#define FORMAT "%-10.10s %-40.40s %-12.12s %-12.12s %-12.12s\n" |
#define NUM_CHANNEL_BUCKETS 1567 |
Definition at line 148 of file channel.c.
Referenced by ast_channels_init().
#define STATE2STR_BUFSIZE 32 |
Definition at line 107 of file channel.c.
Referenced by ast_state2str().
anonymous enum |
Element identifiers for connected line indication frame data.
Definition at line 8806 of file channel.c.
08806 { 08807 AST_CONNECTED_LINE_NUMBER, 08808 AST_CONNECTED_LINE_NAME, 08809 AST_CONNECTED_LINE_NUMBER_PLAN, 08810 AST_CONNECTED_LINE_ID_PRESENTATION,/* Combined number and name presentation. */ 08811 AST_CONNECTED_LINE_SOURCE, 08812 AST_CONNECTED_LINE_SUBADDRESS, 08813 AST_CONNECTED_LINE_SUBADDRESS_TYPE, 08814 AST_CONNECTED_LINE_SUBADDRESS_ODD_EVEN, 08815 AST_CONNECTED_LINE_SUBADDRESS_VALID, 08816 AST_CONNECTED_LINE_TAG, 08817 AST_CONNECTED_LINE_VERSION, 08818 AST_CONNECTED_LINE_NAME_VALID, 08819 AST_CONNECTED_LINE_NAME_CHAR_SET, 08820 AST_CONNECTED_LINE_NAME_PRESENTATION, 08821 AST_CONNECTED_LINE_NUMBER_VALID, 08822 AST_CONNECTED_LINE_NUMBER_PRESENTATION, 08823 };
anonymous enum |
Element identifiers for redirecting indication frame data.
Definition at line 9127 of file channel.c.
09127 { 09128 AST_REDIRECTING_FROM_NUMBER, 09129 AST_REDIRECTING_FROM_NAME, 09130 AST_REDIRECTING_FROM_NUMBER_PLAN, 09131 AST_REDIRECTING_FROM_ID_PRESENTATION, 09132 AST_REDIRECTING_TO_NUMBER, 09133 AST_REDIRECTING_TO_NAME, 09134 AST_REDIRECTING_TO_NUMBER_PLAN, 09135 AST_REDIRECTING_TO_ID_PRESENTATION, 09136 AST_REDIRECTING_REASON, 09137 AST_REDIRECTING_COUNT, 09138 AST_REDIRECTING_FROM_SUBADDRESS, 09139 AST_REDIRECTING_FROM_SUBADDRESS_TYPE, 09140 AST_REDIRECTING_FROM_SUBADDRESS_ODD_EVEN, 09141 AST_REDIRECTING_FROM_SUBADDRESS_VALID, 09142 AST_REDIRECTING_TO_SUBADDRESS, 09143 AST_REDIRECTING_TO_SUBADDRESS_TYPE, 09144 AST_REDIRECTING_TO_SUBADDRESS_ODD_EVEN, 09145 AST_REDIRECTING_TO_SUBADDRESS_VALID, 09146 AST_REDIRECTING_FROM_TAG, 09147 AST_REDIRECTING_TO_TAG, 09148 AST_REDIRECTING_VERSION, 09149 AST_REDIRECTING_FROM_NAME_VALID, 09150 AST_REDIRECTING_FROM_NAME_CHAR_SET, 09151 AST_REDIRECTING_FROM_NAME_PRESENTATION, 09152 AST_REDIRECTING_FROM_NUMBER_VALID, 09153 AST_REDIRECTING_FROM_NUMBER_PRESENTATION, 09154 AST_REDIRECTING_TO_NAME_VALID, 09155 AST_REDIRECTING_TO_NAME_CHAR_SET, 09156 AST_REDIRECTING_TO_NAME_PRESENTATION, 09157 AST_REDIRECTING_TO_NUMBER_VALID, 09158 AST_REDIRECTING_TO_NUMBER_PRESENTATION, 09159 };
int __ast_answer | ( | struct ast_channel * | chan, | |
unsigned int | delay, | |||
int | cdr_answer | |||
) |
Answer a channel, with a selectable delay before returning.
chan | channel to answer | |
delay | maximum amount of time to wait for incoming media | |
cdr_answer | flag to control whether any associated CDR should be marked as 'answered' |
This function answers a channel and handles all necessary call setup functions.
0 | on success | |
non-zero | on failure |
Definition at line 2982 of file channel.c.
References ast_channel::_state, ast_channel_lock, ast_channel_unlock, AST_CONTROL_HANGUP, ast_debug, AST_FRAME_CNG, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_HTML, AST_FRAME_IAX, AST_FRAME_IMAGE, AST_FRAME_MODEM, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree, ast_frisolate(), AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_HEAD_NOLOCK, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_HEAD, ast_log(), ast_queue_frame_head(), ast_raw_answer(), ast_read(), ast_remaining_ms(), AST_STATE_RING, AST_STATE_RINGING, ast_tvnow(), ast_waitfor(), errno, frames, ast_frame::frametype, ast_frame_subclass::integer, LOG_WARNING, MAX, and ast_frame::subclass.
Referenced by ast_answer(), pbx_builtin_answer(), and pbx_builtin_incomplete().
02983 { 02984 int res = 0; 02985 enum ast_channel_state old_state; 02986 02987 old_state = chan->_state; 02988 if ((res = ast_raw_answer(chan, cdr_answer))) { 02989 return res; 02990 } 02991 02992 switch (old_state) { 02993 case AST_STATE_RINGING: 02994 case AST_STATE_RING: 02995 /* wait for media to start flowing, but don't wait any longer 02996 * than 'delay' or 500 milliseconds, whichever is longer 02997 */ 02998 do { 02999 AST_LIST_HEAD_NOLOCK(, ast_frame) frames; 03000 struct ast_frame *cur, *new; 03001 int timeout_ms = MAX(delay, 500); 03002 unsigned int done = 0; 03003 struct timeval start; 03004 03005 AST_LIST_HEAD_INIT_NOLOCK(&frames); 03006 03007 start = ast_tvnow(); 03008 for (;;) { 03009 int ms = ast_remaining_ms(start, timeout_ms); 03010 ms = ast_waitfor(chan, ms); 03011 if (ms < 0) { 03012 ast_log(LOG_WARNING, "Error condition occurred when polling channel %s for a voice frame: %s\n", chan->name, strerror(errno)); 03013 res = -1; 03014 break; 03015 } 03016 if (ms == 0) { 03017 ast_debug(2, "Didn't receive a media frame from %s within %u ms of answering. Continuing anyway\n", chan->name, MAX(delay, 500)); 03018 break; 03019 } 03020 cur = ast_read(chan); 03021 if (!cur || ((cur->frametype == AST_FRAME_CONTROL) && 03022 (cur->subclass.integer == AST_CONTROL_HANGUP))) { 03023 if (cur) { 03024 ast_frfree(cur); 03025 } 03026 res = -1; 03027 ast_debug(2, "Hangup of channel %s detected in answer routine\n", chan->name); 03028 break; 03029 } 03030 03031 if ((new = ast_frisolate(cur)) != cur) { 03032 ast_frfree(cur); 03033 } 03034 03035 AST_LIST_INSERT_HEAD(&frames, new, frame_list); 03036 03037 /* if a specific delay period was requested, continue 03038 * until that delay has passed. don't stop just because 03039 * incoming media has arrived. 03040 */ 03041 if (delay) { 03042 continue; 03043 } 03044 03045 switch (new->frametype) { 03046 /* all of these frametypes qualify as 'media' */ 03047 case AST_FRAME_VOICE: 03048 case AST_FRAME_VIDEO: 03049 case AST_FRAME_TEXT: 03050 case AST_FRAME_DTMF_BEGIN: 03051 case AST_FRAME_DTMF_END: 03052 case AST_FRAME_IMAGE: 03053 case AST_FRAME_HTML: 03054 case AST_FRAME_MODEM: 03055 done = 1; 03056 break; 03057 case AST_FRAME_CONTROL: 03058 case AST_FRAME_IAX: 03059 case AST_FRAME_NULL: 03060 case AST_FRAME_CNG: 03061 break; 03062 } 03063 03064 if (done) { 03065 break; 03066 } 03067 } 03068 03069 if (res == 0) { 03070 ast_channel_lock(chan); 03071 while ((cur = AST_LIST_REMOVE_HEAD(&frames, frame_list))) { 03072 ast_queue_frame_head(chan, cur); 03073 ast_frfree(cur); 03074 } 03075 ast_channel_unlock(chan); 03076 } 03077 } while (0); 03078 break; 03079 default: 03080 break; 03081 } 03082 03083 return res; 03084 }
static void __ast_change_name_nolink | ( | struct ast_channel * | chan, | |
const char * | newname | |||
) | [static] |
this function simply changes the name of the channel and issues a manager_event with out unlinking and linking the channel from the ao2_container. This should only be used when the channel has already been unlinked from the ao2_container.
Definition at line 6223 of file channel.c.
References ast_manager_event, ast_string_field_set, EVENT_FLAG_CALL, and name.
Referenced by ast_change_name(), and ast_do_masquerade().
06224 { 06225 ast_manager_event(chan, EVENT_FLAG_CALL, "Rename", "Channel: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", chan->name, newname, chan->uniqueid); 06226 ast_string_field_set(chan, name, newname); 06227 }
struct ast_channel* __ast_channel_alloc | ( | int | needqueue, | |
int | state, | |||
const char * | cid_num, | |||
const char * | cid_name, | |||
const char * | acctcode, | |||
const char * | exten, | |||
const char * | context, | |||
const char * | linkedid, | |||
const int | amaflag, | |||
const char * | file, | |||
int | line, | |||
const char * | function, | |||
const char * | name_fmt, | |||
... | ||||
) | [read] |
Create a channel structure.
NULL | failure | |
non-NULL | successfully allocated channel |
Definition at line 1366 of file channel.c.
References __ast_channel_alloc_ap().
01372 { 01373 va_list ap1, ap2; 01374 struct ast_channel *result; 01375 01376 va_start(ap1, name_fmt); 01377 va_start(ap2, name_fmt); 01378 result = __ast_channel_alloc_ap(needqueue, state, cid_num, cid_name, acctcode, exten, context, 01379 linkedid, amaflag, file, line, function, name_fmt, ap1, ap2); 01380 va_end(ap1); 01381 va_end(ap2); 01382 01383 return result; 01384 }
static struct ast_channel* attribute_malloc __ast_channel_alloc_ap | ( | int | needqueue, | |
int | state, | |||
const char * | cid_num, | |||
const char * | cid_name, | |||
const char * | acctcode, | |||
const char * | exten, | |||
const char * | context, | |||
const char * | linkedid, | |||
const int | amaflag, | |||
const char * | file, | |||
int | line, | |||
const char * | function, | |||
const char * | name_fmt, | |||
va_list | ap1, | |||
va_list | ap2 | |||
) | [static, read] |
Create a new channel structure.
Definition at line 1130 of file channel.c.
References __ao2_alloc_debug(), ast_channel::_state, accountcode, ast_channel::alertpipe, ast_channel::amaflags, ao2_alloc, ao2_link, ARRAY_LEN, AST_ALERT_FD, ast_atomic_fetchadd_int(), ast_cdr_alloc(), ast_cdr_init(), ast_cdr_start(), AST_CEL_CHANNEL_START, ast_cel_report_event(), ast_channel_destructor(), ast_channel_set_fd(), ast_channel_unref, ast_config_AST_SYSTEM_NAME, ast_copy_string(), ast_default_accountcode, ast_default_amaflags, ast_get_channel_tech(), AST_LIST_HEAD_INIT_NOLOCK, ast_log(), ast_manager_event, ast_party_caller_init(), ast_party_connected_line_init(), ast_party_dialed_init(), ast_party_redirecting_init(), ast_state2str(), ast_strdup, ast_strdupa, ast_string_field_build, ast_string_field_build_va, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_timer_fd(), ast_timer_get_name(), ast_timer_open(), AST_TIMING_FD, ast_channel::caller, ast_channel::cdr, channels, ast_channel::connected, ast_channel::context, defaultlanguage, ast_channel::dialed, errno, EVENT_FLAG_CALL, ast_channel::exten, ast_channel::fds, ast_channel::fin, chanlist::flags, ast_channel::fout, ast_party_caller::id, language, LOG_WARNING, name, ast_party_id::name, null_tech, ast_party_id::number, ast_channel::priority, ast_channel::redirecting, S_OR, ast_channel::sched, sched_context_create(), ast_party_number::str, ast_party_name::str, ast_channel::streamid, ast_channel::tech, chanlist::tech, ast_channel::timer, ast_channel::timingfd, ast_party_number::valid, ast_party_name::valid, and ast_channel::varshead.
Referenced by __ast_channel_alloc(), and ast_channel_alloc().
01134 { 01135 struct ast_channel *tmp; 01136 int x; 01137 int flags; 01138 struct varshead *headp; 01139 char *tech = "", *tech2 = NULL; 01140 01141 /* If shutting down, don't allocate any new channels */ 01142 if (shutting_down) { 01143 ast_log(LOG_WARNING, "Channel allocation failed: Refusing due to active shutdown\n"); 01144 return NULL; 01145 } 01146 01147 #if defined(REF_DEBUG) 01148 tmp = __ao2_alloc_debug(sizeof(*tmp), ast_channel_destructor, "", file, line, 01149 function, 1); 01150 #elif defined(__AST_DEBUG_MALLOC) 01151 tmp = __ao2_alloc_debug(sizeof(*tmp), ast_channel_destructor, "", file, line, 01152 function, 0); 01153 #else 01154 tmp = ao2_alloc(sizeof(*tmp), ast_channel_destructor); 01155 #endif 01156 if (!tmp) { 01157 /* Channel structure allocation failure. */ 01158 return NULL; 01159 } 01160 01161 /* 01162 * Init file descriptors to unopened state so 01163 * the destructor can know not to close them. 01164 */ 01165 tmp->timingfd = -1; 01166 for (x = 0; x < ARRAY_LEN(tmp->alertpipe); ++x) { 01167 tmp->alertpipe[x] = -1; 01168 } 01169 for (x = 0; x < ARRAY_LEN(tmp->fds); ++x) { 01170 tmp->fds[x] = -1; 01171 } 01172 #ifdef HAVE_EPOLL 01173 tmp->epfd = epoll_create(25); 01174 #endif 01175 01176 if (!(tmp->sched = sched_context_create())) { 01177 ast_log(LOG_WARNING, "Channel allocation failed: Unable to create schedule context\n"); 01178 return ast_channel_unref(tmp); 01179 } 01180 01181 ast_party_dialed_init(&tmp->dialed); 01182 ast_party_caller_init(&tmp->caller); 01183 ast_party_connected_line_init(&tmp->connected); 01184 ast_party_redirecting_init(&tmp->redirecting); 01185 01186 if (cid_name) { 01187 tmp->caller.id.name.valid = 1; 01188 tmp->caller.id.name.str = ast_strdup(cid_name); 01189 if (!tmp->caller.id.name.str) { 01190 return ast_channel_unref(tmp); 01191 } 01192 } 01193 if (cid_num) { 01194 tmp->caller.id.number.valid = 1; 01195 tmp->caller.id.number.str = ast_strdup(cid_num); 01196 if (!tmp->caller.id.number.str) { 01197 return ast_channel_unref(tmp); 01198 } 01199 } 01200 01201 if ((tmp->timer = ast_timer_open())) { 01202 if (strcmp(ast_timer_get_name(tmp->timer), "timerfd")) { 01203 needqueue = 0; 01204 } 01205 tmp->timingfd = ast_timer_fd(tmp->timer); 01206 } 01207 01208 if (needqueue) { 01209 if (pipe(tmp->alertpipe)) { 01210 ast_log(LOG_WARNING, "Channel allocation failed: Can't create alert pipe! Try increasing max file descriptors with ulimit -n\n"); 01211 return ast_channel_unref(tmp); 01212 } else { 01213 flags = fcntl(tmp->alertpipe[0], F_GETFL); 01214 if (fcntl(tmp->alertpipe[0], F_SETFL, flags | O_NONBLOCK) < 0) { 01215 ast_log(LOG_WARNING, "Channel allocation failed: Unable to set alertpipe nonblocking! (%d: %s)\n", errno, strerror(errno)); 01216 return ast_channel_unref(tmp); 01217 } 01218 flags = fcntl(tmp->alertpipe[1], F_GETFL); 01219 if (fcntl(tmp->alertpipe[1], F_SETFL, flags | O_NONBLOCK) < 0) { 01220 ast_log(LOG_WARNING, "Channel allocation failed: Unable to set alertpipe nonblocking! (%d: %s)\n", errno, strerror(errno)); 01221 return ast_channel_unref(tmp); 01222 } 01223 } 01224 } 01225 01226 /* 01227 * This is the last place the channel constructor can fail. 01228 * 01229 * The destructor takes advantage of this fact to ensure that the 01230 * AST_CEL_CHANNEL_END is not posted if we have not posted the 01231 * AST_CEL_CHANNEL_START yet. 01232 */ 01233 if ((ast_string_field_init(tmp, 128))) { 01234 return ast_channel_unref(tmp); 01235 } 01236 01237 /* Always watch the alertpipe */ 01238 ast_channel_set_fd(tmp, AST_ALERT_FD, tmp->alertpipe[0]); 01239 /* And timing pipe */ 01240 ast_channel_set_fd(tmp, AST_TIMING_FD, tmp->timingfd); 01241 01242 /* Initial state */ 01243 tmp->_state = state; 01244 01245 tmp->streamid = -1; 01246 01247 tmp->fin = global_fin; 01248 tmp->fout = global_fout; 01249 01250 if (ast_strlen_zero(ast_config_AST_SYSTEM_NAME)) { 01251 ast_string_field_build(tmp, uniqueid, "%li.%d", (long) time(NULL), 01252 ast_atomic_fetchadd_int(&uniqueint, 1)); 01253 } else { 01254 ast_string_field_build(tmp, uniqueid, "%s-%li.%d", ast_config_AST_SYSTEM_NAME, 01255 (long) time(NULL), ast_atomic_fetchadd_int(&uniqueint, 1)); 01256 } 01257 01258 if (!ast_strlen_zero(linkedid)) { 01259 ast_string_field_set(tmp, linkedid, linkedid); 01260 } else { 01261 ast_string_field_set(tmp, linkedid, tmp->uniqueid); 01262 } 01263 01264 if (!ast_strlen_zero(name_fmt)) { 01265 char *slash, *slash2; 01266 /* Almost every channel is calling this function, and setting the name via the ast_string_field_build() call. 01267 * And they all use slightly different formats for their name string. 01268 * This means, to set the name here, we have to accept variable args, and call the string_field_build from here. 01269 * This means, that the stringfields must have a routine that takes the va_lists directly, and 01270 * uses them to build the string, instead of forming the va_lists internally from the vararg ... list. 01271 * This new function was written so this can be accomplished. 01272 */ 01273 ast_string_field_build_va(tmp, name, name_fmt, ap1, ap2); 01274 tech = ast_strdupa(tmp->name); 01275 if ((slash = strchr(tech, '/'))) { 01276 if ((slash2 = strchr(slash + 1, '/'))) { 01277 tech2 = slash + 1; 01278 *slash2 = '\0'; 01279 } 01280 *slash = '\0'; 01281 } 01282 } else { 01283 /* 01284 * Start the string with '-' so it becomes an empty string 01285 * in the destructor. 01286 */ 01287 ast_string_field_set(tmp, name, "-**Unknown**"); 01288 } 01289 01290 /* Reminder for the future: under what conditions do we NOT want to track cdrs on channels? */ 01291 01292 /* These 4 variables need to be set up for the cdr_init() to work right */ 01293 if (amaflag) 01294 tmp->amaflags = amaflag; 01295 else 01296 tmp->amaflags = ast_default_amaflags; 01297 01298 if (!ast_strlen_zero(acctcode)) 01299 ast_string_field_set(tmp, accountcode, acctcode); 01300 else 01301 ast_string_field_set(tmp, accountcode, ast_default_accountcode); 01302 01303 if (!ast_strlen_zero(context)) 01304 ast_copy_string(tmp->context, context, sizeof(tmp->context)); 01305 else 01306 strcpy(tmp->context, "default"); 01307 01308 if (!ast_strlen_zero(exten)) 01309 ast_copy_string(tmp->exten, exten, sizeof(tmp->exten)); 01310 else 01311 strcpy(tmp->exten, "s"); 01312 01313 tmp->priority = 1; 01314 01315 tmp->cdr = ast_cdr_alloc(); 01316 ast_cdr_init(tmp->cdr, tmp); 01317 ast_cdr_start(tmp->cdr); 01318 01319 ast_atomic_fetchadd_int(&chancount, +1); 01320 ast_cel_report_event(tmp, AST_CEL_CHANNEL_START, NULL, NULL, NULL); 01321 01322 headp = &tmp->varshead; 01323 AST_LIST_HEAD_INIT_NOLOCK(headp); 01324 01325 AST_LIST_HEAD_INIT_NOLOCK(&tmp->datastores); 01326 01327 AST_LIST_HEAD_INIT_NOLOCK(&tmp->autochans); 01328 01329 ast_string_field_set(tmp, language, defaultlanguage); 01330 01331 tmp->tech = &null_tech; 01332 01333 ao2_link(channels, tmp); 01334 01335 /* 01336 * And now, since the channel structure is built, and has its name, let's 01337 * call the manager event generator with this Newchannel event. This is the 01338 * proper and correct place to make this call, but you sure do have to pass 01339 * a lot of data into this func to do it here! 01340 */ 01341 if (ast_get_channel_tech(tech) || (tech2 && ast_get_channel_tech(tech2))) { 01342 ast_manager_event(tmp, EVENT_FLAG_CALL, "Newchannel", 01343 "Channel: %s\r\n" 01344 "ChannelState: %d\r\n" 01345 "ChannelStateDesc: %s\r\n" 01346 "CallerIDNum: %s\r\n" 01347 "CallerIDName: %s\r\n" 01348 "AccountCode: %s\r\n" 01349 "Exten: %s\r\n" 01350 "Context: %s\r\n" 01351 "Uniqueid: %s\r\n", 01352 tmp->name, 01353 state, 01354 ast_state2str(state), 01355 S_OR(cid_num, ""), 01356 S_OR(cid_name, ""), 01357 tmp->accountcode, 01358 S_OR(exten, ""), 01359 S_OR(context, ""), 01360 tmp->uniqueid); 01361 } 01362 01363 return tmp; 01364 }
static int __ast_channel_masquerade | ( | struct ast_channel * | original, | |
struct ast_channel * | clonechan, | |||
struct ast_datastore * | xfer_ds | |||
) | [static] |
Definition at line 5987 of file channel.c.
References ast_channel::_bridge, ast_bridged_channel(), ast_channel_datastore_add(), ast_channel_lock_both, ast_channel_trylock, ast_channel_unlock, ast_debug, AST_FLAG_ZOMBIE, ast_log(), ast_null_frame, ast_queue_frame(), ast_test_flag, ast_channel_tech::get_base_channel, LOG_WARNING, ast_channel::masq, ast_channel::masqr, and ast_channel::tech.
Referenced by ast_channel_masquerade(), and ast_channel_transfer_masquerade().
05988 { 05989 int res = -1; 05990 struct ast_channel *final_orig, *final_clone, *base; 05991 05992 for (;;) { 05993 final_orig = original; 05994 final_clone = clonechan; 05995 05996 ast_channel_lock_both(original, clonechan); 05997 05998 if (ast_test_flag(original, AST_FLAG_ZOMBIE) 05999 || ast_test_flag(clonechan, AST_FLAG_ZOMBIE)) { 06000 /* Zombies! Run! */ 06001 ast_log(LOG_WARNING, 06002 "Can't setup masquerade. One or both channels is dead. (%s <-- %s)\n", 06003 original->name, clonechan->name); 06004 ast_channel_unlock(clonechan); 06005 ast_channel_unlock(original); 06006 return -1; 06007 } 06008 06009 /* 06010 * Each of these channels may be sitting behind a channel proxy 06011 * (i.e. chan_agent) and if so, we don't really want to 06012 * masquerade it, but its proxy 06013 */ 06014 if (original->_bridge 06015 && (original->_bridge != ast_bridged_channel(original)) 06016 && (original->_bridge->_bridge != original)) { 06017 final_orig = original->_bridge; 06018 } 06019 if (clonechan->_bridge 06020 && (clonechan->_bridge != ast_bridged_channel(clonechan)) 06021 && (clonechan->_bridge->_bridge != clonechan)) { 06022 final_clone = clonechan->_bridge; 06023 } 06024 if (final_clone->tech->get_base_channel 06025 && (base = final_clone->tech->get_base_channel(final_clone))) { 06026 final_clone = base; 06027 } 06028 06029 if ((final_orig != original) || (final_clone != clonechan)) { 06030 /* 06031 * Lots and lots of deadlock avoidance. The main one we're 06032 * competing with is ast_write(), which locks channels 06033 * recursively, when working with a proxy channel. 06034 */ 06035 if (ast_channel_trylock(final_orig)) { 06036 ast_channel_unlock(clonechan); 06037 ast_channel_unlock(original); 06038 06039 /* Try again */ 06040 continue; 06041 } 06042 if (ast_channel_trylock(final_clone)) { 06043 ast_channel_unlock(final_orig); 06044 ast_channel_unlock(clonechan); 06045 ast_channel_unlock(original); 06046 06047 /* Try again */ 06048 continue; 06049 } 06050 ast_channel_unlock(clonechan); 06051 ast_channel_unlock(original); 06052 original = final_orig; 06053 clonechan = final_clone; 06054 06055 if (ast_test_flag(original, AST_FLAG_ZOMBIE) 06056 || ast_test_flag(clonechan, AST_FLAG_ZOMBIE)) { 06057 /* Zombies! Run! */ 06058 ast_log(LOG_WARNING, 06059 "Can't setup masquerade. One or both channels is dead. (%s <-- %s)\n", 06060 original->name, clonechan->name); 06061 ast_channel_unlock(clonechan); 06062 ast_channel_unlock(original); 06063 return -1; 06064 } 06065 } 06066 break; 06067 } 06068 06069 if (original == clonechan) { 06070 ast_log(LOG_WARNING, "Can't masquerade channel '%s' into itself!\n", original->name); 06071 ast_channel_unlock(clonechan); 06072 ast_channel_unlock(original); 06073 return -1; 06074 } 06075 06076 ast_debug(1, "Planning to masquerade channel %s into the structure of %s\n", 06077 clonechan->name, original->name); 06078 06079 if (!original->masqr && !original->masq && !clonechan->masq && !clonechan->masqr) { 06080 original->masq = clonechan; 06081 clonechan->masqr = original; 06082 if (xfer_ds) { 06083 ast_channel_datastore_add(original, xfer_ds); 06084 } 06085 ast_queue_frame(original, &ast_null_frame); 06086 ast_queue_frame(clonechan, &ast_null_frame); 06087 ast_debug(1, "Done planning to masquerade channel %s into the structure of %s\n", clonechan->name, original->name); 06088 res = 0; 06089 } else if (original->masq) { 06090 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 06091 original->masq->name, original->name); 06092 } else if (original->masqr) { 06093 /* not yet as a previously planned masq hasn't yet happened */ 06094 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 06095 original->name, original->masqr->name); 06096 } else if (clonechan->masq) { 06097 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 06098 clonechan->masq->name, clonechan->name); 06099 } else { /* (clonechan->masqr) */ 06100 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 06101 clonechan->name, clonechan->masqr->name); 06102 } 06103 06104 ast_channel_unlock(clonechan); 06105 ast_channel_unlock(original); 06106 06107 return res; 06108 }
struct ast_channel* __ast_dummy_channel_alloc | ( | const char * | file, | |
int | line, | |||
const char * | function | |||
) | [read] |
Definition at line 1389 of file channel.c.
References __ao2_alloc_debug(), ast_channel::alertpipe, ao2_alloc, ARRAY_LEN, ast_channel_unref, ast_dummy_channel_destructor(), AST_LIST_HEAD_INIT_NOLOCK, ast_string_field_init, ast_channel::fds, ast_channel::timingfd, and ast_channel::varshead.
01393 { 01394 struct ast_channel *tmp; 01395 struct varshead *headp; 01396 int x; 01397 01398 #if defined(REF_DEBUG) 01399 tmp = __ao2_alloc_debug(sizeof(*tmp), ast_dummy_channel_destructor, "dummy channel", 01400 file, line, function, 1); 01401 #elif defined(__AST_DEBUG_MALLOC) 01402 tmp = __ao2_alloc_debug(sizeof(*tmp), ast_dummy_channel_destructor, "dummy channel", 01403 file, line, function, 0); 01404 #else 01405 tmp = ao2_alloc(sizeof(*tmp), ast_dummy_channel_destructor); 01406 #endif 01407 if (!tmp) { 01408 /* Dummy channel structure allocation failure. */ 01409 return NULL; 01410 } 01411 01412 if ((ast_string_field_init(tmp, 128))) { 01413 return ast_channel_unref(tmp); 01414 } 01415 01416 /* 01417 * Init file descriptors to unopened state just in case 01418 * autoservice is called on the channel or something tries to 01419 * read a frame from it. 01420 */ 01421 tmp->timingfd = -1; 01422 for (x = 0; x < ARRAY_LEN(tmp->alertpipe); ++x) { 01423 tmp->alertpipe[x] = -1; 01424 } 01425 for (x = 0; x < ARRAY_LEN(tmp->fds); ++x) { 01426 tmp->fds[x] = -1; 01427 } 01428 #ifdef HAVE_EPOLL 01429 tmp->epfd = -1; 01430 #endif 01431 01432 headp = &tmp->varshead; 01433 AST_LIST_HEAD_INIT_NOLOCK(headp); 01434 01435 return tmp; 01436 }
static int __ast_queue_frame | ( | struct ast_channel * | chan, | |
struct ast_frame * | fin, | |||
int | head, | |||
struct ast_frame * | after | |||
) | [static] |
Definition at line 1438 of file channel.c.
References ast_channel::alertpipe, ast_channel_lock, ast_channel_unlock, AST_CONTROL_END_OF_Q, AST_CONTROL_HANGUP, AST_FLAG_BLOCKING, AST_FRAME_CONTROL, AST_FRAME_NULL, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup(), ast_frfree, AST_LIST_APPEND_LIST, AST_LIST_FIRST, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_HEAD_NOLOCK, AST_LIST_INSERT_LIST_AFTER, AST_LIST_INSERT_TAIL, AST_LIST_LAST, AST_LIST_NEXT, AST_LIST_REMOVE, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), ast_test_flag, ast_timer_enable_continuous(), ast_channel::blocker, errno, f, frames, ast_frame::frametype, ast_frame_subclass::integer, LOG_WARNING, ast_frame::subclass, ast_channel::timer, and ast_channel::timingfd.
Referenced by __ast_read(), ast_queue_frame(), and ast_queue_frame_head().
01439 { 01440 struct ast_frame *f; 01441 struct ast_frame *cur; 01442 unsigned int new_frames = 0; 01443 unsigned int new_voice_frames = 0; 01444 unsigned int queued_frames = 0; 01445 unsigned int queued_voice_frames = 0; 01446 AST_LIST_HEAD_NOLOCK(, ast_frame) frames; 01447 01448 ast_channel_lock(chan); 01449 01450 /* 01451 * Check the last frame on the queue if we are queuing the new 01452 * frames after it. 01453 */ 01454 cur = AST_LIST_LAST(&chan->readq); 01455 if (cur && cur->frametype == AST_FRAME_CONTROL && !head && (!after || after == cur)) { 01456 switch (cur->subclass.integer) { 01457 case AST_CONTROL_END_OF_Q: 01458 if (fin->frametype == AST_FRAME_CONTROL 01459 && fin->subclass.integer == AST_CONTROL_HANGUP) { 01460 /* 01461 * Destroy the end-of-Q marker frame so we can queue the hangup 01462 * frame in its place. 01463 */ 01464 AST_LIST_REMOVE(&chan->readq, cur, frame_list); 01465 ast_frfree(cur); 01466 01467 /* 01468 * This has degenerated to a normal queue append anyway. Since 01469 * we just destroyed the last frame in the queue we must make 01470 * sure that "after" is NULL or bad things will happen. 01471 */ 01472 after = NULL; 01473 break; 01474 } 01475 /* Fall through */ 01476 case AST_CONTROL_HANGUP: 01477 /* Don't queue anything. */ 01478 ast_channel_unlock(chan); 01479 return 0; 01480 default: 01481 break; 01482 } 01483 } 01484 01485 /* Build copies of all the new frames and count them */ 01486 AST_LIST_HEAD_INIT_NOLOCK(&frames); 01487 for (cur = fin; cur; cur = AST_LIST_NEXT(cur, frame_list)) { 01488 if (!(f = ast_frdup(cur))) { 01489 if (AST_LIST_FIRST(&frames)) { 01490 ast_frfree(AST_LIST_FIRST(&frames)); 01491 } 01492 ast_channel_unlock(chan); 01493 return -1; 01494 } 01495 01496 AST_LIST_INSERT_TAIL(&frames, f, frame_list); 01497 new_frames++; 01498 if (f->frametype == AST_FRAME_VOICE) { 01499 new_voice_frames++; 01500 } 01501 } 01502 01503 /* Count how many frames exist on the queue */ 01504 AST_LIST_TRAVERSE(&chan->readq, cur, frame_list) { 01505 queued_frames++; 01506 if (cur->frametype == AST_FRAME_VOICE) { 01507 queued_voice_frames++; 01508 } 01509 } 01510 01511 if ((queued_frames + new_frames > 128 || queued_voice_frames + new_voice_frames > 96)) { 01512 int count = 0; 01513 ast_log(LOG_WARNING, "Exceptionally long %squeue length queuing to %s\n", queued_frames + new_frames > 128 ? "" : "voice ", chan->name); 01514 AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->readq, cur, frame_list) { 01515 /* Save the most recent frame */ 01516 if (!AST_LIST_NEXT(cur, frame_list)) { 01517 break; 01518 } else if (cur->frametype == AST_FRAME_VOICE || cur->frametype == AST_FRAME_VIDEO || cur->frametype == AST_FRAME_NULL) { 01519 if (++count > 64) { 01520 break; 01521 } 01522 AST_LIST_REMOVE_CURRENT(frame_list); 01523 ast_frfree(cur); 01524 } 01525 } 01526 AST_LIST_TRAVERSE_SAFE_END; 01527 } 01528 01529 if (after) { 01530 AST_LIST_INSERT_LIST_AFTER(&chan->readq, &frames, after, frame_list); 01531 } else { 01532 if (head) { 01533 AST_LIST_APPEND_LIST(&frames, &chan->readq, frame_list); 01534 AST_LIST_HEAD_INIT_NOLOCK(&chan->readq); 01535 } 01536 AST_LIST_APPEND_LIST(&chan->readq, &frames, frame_list); 01537 } 01538 01539 if (chan->alertpipe[1] > -1) { 01540 int blah[new_frames]; 01541 01542 memset(blah, 1, sizeof(blah)); 01543 if (write(chan->alertpipe[1], &blah, sizeof(blah)) != (sizeof(blah))) { 01544 ast_log(LOG_WARNING, "Unable to write to alert pipe on %s (qlen = %u): %s!\n", 01545 chan->name, queued_frames, strerror(errno)); 01546 } 01547 } else if (chan->timingfd > -1) { 01548 ast_timer_enable_continuous(chan->timer); 01549 } else if (ast_test_flag(chan, AST_FLAG_BLOCKING)) { 01550 pthread_kill(chan->blocker, SIGURG); 01551 } 01552 01553 ast_channel_unlock(chan); 01554 01555 return 0; 01556 }
static struct ast_frame* __ast_read | ( | struct ast_channel * | chan, | |
int | dropaudio | |||
) | [static, read] |
Definition at line 3836 of file channel.c.
References __ast_queue_frame(), ast_channel::_softhangup, ast_channel::_state, ast_control_read_action_payload::action, ast_channel::alertpipe, ao2_ref, ast_audiohook_detach_list(), AST_AUDIOHOOK_DIRECTION_READ, ast_audiohook_write_list(), ast_audiohook_write_list_empty(), ast_bridged_channel(), AST_CEL_ANSWER, ast_cel_report_event(), ast_channel_connected_line_macro(), ast_channel_lock, ast_channel_unlock, ast_check_hangup(), ast_clear_flag, ast_connected_line_parse_data(), AST_CONTROL_ANSWER, AST_CONTROL_CONNECTED_LINE, AST_CONTROL_END_OF_Q, AST_CONTROL_HANGUP, AST_CONTROL_READ_ACTION, ast_deactivate_generator(), ast_debug, AST_DEFAULT_EMULATE_DTMF_DURATION, ast_do_masquerade(), AST_FLAG_DEFER_DTMF, AST_FLAG_EMULATE_DTMF, AST_FLAG_END_DTMF_ONLY, AST_FLAG_EXCEPTION, AST_FLAG_IN_DTMF, AST_FLAG_OUTGOING, AST_FLAG_TIMINGDATA_IS_AO2_OBJ, AST_FLAG_ZOMBIE, ast_format_rate(), AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_frame_dump(), AST_FRAME_NULL, AST_FRAME_READ_ACTION_CONNECTED_LINE_MACRO, AST_FRAME_VOICE, ast_framehook_list_read_event(), ast_frfree, AST_GENERATOR_FD, ast_getformatname(), ast_getformatname_multiple(), ast_indicate_data(), AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_LAST, AST_LIST_NEXT, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), AST_MIN_DTMF_DURATION, AST_MIN_DTMF_GAP, AST_MONITOR_RUNNING, ast_null_frame, ast_party_connected_line_copy(), ast_party_connected_line_free(), ast_party_connected_line_init(), ast_queue_control(), ast_queue_frame(), ast_queue_frame_head(), ast_read_generator_actions(), ast_seekstream(), ast_set_flag, ast_setstate(), AST_SOFTHANGUP_DEV, AST_STATE_UP, ast_test_flag, ast_timer_ack(), ast_timer_disable_continuous(), ast_timer_get_event(), ast_timer_set_rate(), AST_TIMING_EVENT_CONTINUOUS, AST_TIMING_EVENT_EXPIRED, AST_TIMING_FD, ast_translate(), ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), ast_writestream(), ast_channel::audiohooks, ast_channel::blocker, calc_monitor_jump(), ast_frame_subclass::codec, ast_channel::connected, ast_frame::data, DEBUGCHAN_FLAG, ast_generator::digit, ast_channel::dtmf_tv, ast_channel::dtmff, ast_channel::emulate_dtmf_digit, ast_channel::emulate_dtmf_duration, errno, ast_channel_tech::exception, ast_channel::fdno, ast_channel::fds, ast_channel::fin, chanlist::flags, ast_filestream::fmt, ast_format::format, FRAMECOUNT_INC, ast_channel::framehooks, ast_frame::frametype, ast_generator::generate, ast_channel::generator, ast_channel::generatordata, ast_channel::hangupcause, ast_channel::insmpl, ast_frame_subclass::integer, ast_frame::len, LOG_DTMF, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_channel::masq, ast_channel::monitor, ast_channel::music_state, ast_channel::nativeformats, ast_channel::outsmpl, ast_control_read_action_payload::payload, ast_control_read_action_payload::payload_size, ast_frame::ptr, queue_dtmf_readq(), ast_channel_tech::read, ast_channel_monitor::read_stream, ast_channel::readtrans, ast_frame::samples, SEEK_FORCECUR, send_dtmf_event(), should_skip_dtmf(), ast_channel_monitor::state, ast_frame::subclass, ast_channel::tech, ast_channel::timer, ast_channel::timingdata, ast_channel::timingfd, ast_channel::timingfunc, and ast_frame::uint32.
Referenced by ast_read(), and ast_read_noaudio().
03837 { 03838 struct ast_frame *f = NULL; /* the return value */ 03839 int blah; 03840 int prestate; 03841 int cause = 0; 03842 03843 /* this function is very long so make sure there is only one return 03844 * point at the end (there are only two exceptions to this). 03845 */ 03846 03847 if (chan->masq) { 03848 ast_do_masquerade(chan); 03849 return &ast_null_frame; 03850 } 03851 03852 /* if here, no masq has happened, lock the channel and proceed */ 03853 ast_channel_lock(chan); 03854 03855 /* Stop if we're a zombie or need a soft hangup */ 03856 if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) { 03857 if (chan->generator) 03858 ast_deactivate_generator(chan); 03859 03860 /* 03861 * It is possible for chan->_softhangup to be set and there 03862 * still be control frames that need to be read. Instead of 03863 * just going to 'done' in the case of ast_check_hangup(), we 03864 * need to queue the end-of-Q frame so that it can mark the end 03865 * of the read queue. If there are frames to be read, 03866 * ast_queue_control() will be called repeatedly, but will only 03867 * queue the first end-of-Q frame. 03868 */ 03869 if (chan->_softhangup) { 03870 ast_queue_control(chan, AST_CONTROL_END_OF_Q); 03871 } else { 03872 goto done; 03873 } 03874 } else { 03875 #ifdef AST_DEVMODE 03876 /* 03877 * The ast_waitfor() code records which of the channel's file 03878 * descriptors reported that data is available. In theory, 03879 * ast_read() should only be called after ast_waitfor() reports 03880 * that a channel has data available for reading. However, 03881 * there still may be some edge cases throughout the code where 03882 * ast_read() is called improperly. This can potentially cause 03883 * problems, so if this is a developer build, make a lot of 03884 * noise if this happens so that it can be addressed. 03885 * 03886 * One of the potential problems is blocking on a dead channel. 03887 */ 03888 if (chan->fdno == -1) { 03889 ast_log(LOG_ERROR, 03890 "ast_read() on chan '%s' called with no recorded file descriptor.\n", 03891 chan->name); 03892 } 03893 #endif 03894 } 03895 03896 prestate = chan->_state; 03897 if (chan->timingfd > -1 && chan->fdno == AST_TIMING_FD) { 03898 enum ast_timer_event res; 03899 03900 ast_clear_flag(chan, AST_FLAG_EXCEPTION); 03901 03902 res = ast_timer_get_event(chan->timer); 03903 03904 switch (res) { 03905 case AST_TIMING_EVENT_EXPIRED: 03906 if (ast_timer_ack(chan->timer, 1) < 0) { 03907 ast_log(LOG_ERROR, "Failed to acknoweldge timer in ast_read\n"); 03908 goto done; 03909 } 03910 03911 if (chan->timingfunc) { 03912 /* save a copy of func/data before unlocking the channel */ 03913 int (*func)(const void *) = chan->timingfunc; 03914 void *data = chan->timingdata; 03915 int got_ref = 0; 03916 if (data && ast_test_flag(chan, AST_FLAG_TIMINGDATA_IS_AO2_OBJ)) { 03917 ao2_ref(data, 1); 03918 got_ref = 1; 03919 } 03920 chan->fdno = -1; 03921 ast_channel_unlock(chan); 03922 func(data); 03923 if (got_ref) { 03924 ao2_ref(data, -1); 03925 } 03926 } else { 03927 ast_timer_set_rate(chan->timer, 0); 03928 chan->fdno = -1; 03929 ast_channel_unlock(chan); 03930 } 03931 03932 /* cannot 'goto done' because the channel is already unlocked */ 03933 return &ast_null_frame; 03934 03935 case AST_TIMING_EVENT_CONTINUOUS: 03936 if (AST_LIST_EMPTY(&chan->readq) || 03937 !AST_LIST_NEXT(AST_LIST_FIRST(&chan->readq), frame_list)) { 03938 ast_timer_disable_continuous(chan->timer); 03939 } 03940 break; 03941 } 03942 03943 } else if (chan->fds[AST_GENERATOR_FD] > -1 && chan->fdno == AST_GENERATOR_FD) { 03944 /* if the AST_GENERATOR_FD is set, call the generator with args 03945 * set to -1 so it can do whatever it needs to. 03946 */ 03947 void *tmp = chan->generatordata; 03948 chan->generatordata = NULL; /* reset to let ast_write get through */ 03949 chan->generator->generate(chan, tmp, -1, -1); 03950 chan->generatordata = tmp; 03951 f = &ast_null_frame; 03952 chan->fdno = -1; 03953 goto done; 03954 } 03955 03956 /* Read and ignore anything on the alertpipe, but read only 03957 one sizeof(blah) per frame that we send from it */ 03958 if (chan->alertpipe[0] > -1) { 03959 int flags = fcntl(chan->alertpipe[0], F_GETFL); 03960 /* For some odd reason, the alertpipe occasionally loses nonblocking status, 03961 * which immediately causes a deadlock scenario. Detect and prevent this. */ 03962 if ((flags & O_NONBLOCK) == 0) { 03963 ast_log(LOG_ERROR, "Alertpipe on channel %s lost O_NONBLOCK?!!\n", chan->name); 03964 if (fcntl(chan->alertpipe[0], F_SETFL, flags | O_NONBLOCK) < 0) { 03965 ast_log(LOG_WARNING, "Unable to set alertpipe nonblocking! (%d: %s)\n", errno, strerror(errno)); 03966 f = &ast_null_frame; 03967 goto done; 03968 } 03969 } 03970 if (read(chan->alertpipe[0], &blah, sizeof(blah)) < 0) { 03971 if (errno != EINTR && errno != EAGAIN) 03972 ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno)); 03973 } 03974 } 03975 03976 03977 /* Check for pending read queue */ 03978 if (!AST_LIST_EMPTY(&chan->readq)) { 03979 int skip_dtmf = should_skip_dtmf(chan); 03980 03981 AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->readq, f, frame_list) { 03982 /* We have to be picky about which frame we pull off of the readq because 03983 * there are cases where we want to leave DTMF frames on the queue until 03984 * some later time. */ 03985 03986 if ( (f->frametype == AST_FRAME_DTMF_BEGIN || f->frametype == AST_FRAME_DTMF_END) && skip_dtmf) { 03987 continue; 03988 } 03989 03990 AST_LIST_REMOVE_CURRENT(frame_list); 03991 break; 03992 } 03993 AST_LIST_TRAVERSE_SAFE_END; 03994 03995 if (!f) { 03996 /* There were no acceptable frames on the readq. */ 03997 f = &ast_null_frame; 03998 if (chan->alertpipe[0] > -1) { 03999 int poke = 0; 04000 /* Restore the state of the alertpipe since we aren't ready for any 04001 * of the frames in the readq. */ 04002 if (write(chan->alertpipe[1], &poke, sizeof(poke)) != sizeof(poke)) { 04003 ast_log(LOG_ERROR, "Failed to write to alertpipe: %s\n", strerror(errno)); 04004 } 04005 } 04006 } 04007 04008 /* Interpret hangup and end-of-Q frames to return NULL */ 04009 /* XXX why not the same for frames from the channel ? */ 04010 if (f->frametype == AST_FRAME_CONTROL) { 04011 switch (f->subclass.integer) { 04012 case AST_CONTROL_HANGUP: 04013 chan->_softhangup |= AST_SOFTHANGUP_DEV; 04014 cause = f->data.uint32; 04015 /* Fall through */ 04016 case AST_CONTROL_END_OF_Q: 04017 ast_frfree(f); 04018 f = NULL; 04019 break; 04020 default: 04021 break; 04022 } 04023 } 04024 } else { 04025 chan->blocker = pthread_self(); 04026 if (ast_test_flag(chan, AST_FLAG_EXCEPTION)) { 04027 if (chan->tech->exception) 04028 f = chan->tech->exception(chan); 04029 else { 04030 ast_log(LOG_WARNING, "Exception flag set on '%s', but no exception handler\n", chan->name); 04031 f = &ast_null_frame; 04032 } 04033 /* Clear the exception flag */ 04034 ast_clear_flag(chan, AST_FLAG_EXCEPTION); 04035 } else if (chan->tech && chan->tech->read) 04036 f = chan->tech->read(chan); 04037 else 04038 ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name); 04039 } 04040 04041 /* 04042 * Reset the recorded file descriptor that triggered this read so that we can 04043 * easily detect when ast_read() is called without properly using ast_waitfor(). 04044 */ 04045 chan->fdno = -1; 04046 04047 /* Perform the framehook read event here. After the frame enters the framehook list 04048 * there is no telling what will happen, <insert mad scientist laugh here>!!! */ 04049 f = ast_framehook_list_read_event(chan->framehooks, f); 04050 04051 if (f) { 04052 struct ast_frame *readq_tail = AST_LIST_LAST(&chan->readq); 04053 struct ast_control_read_action_payload *read_action_payload; 04054 struct ast_party_connected_line connected; 04055 04056 /* if the channel driver returned more than one frame, stuff the excess 04057 into the readq for the next ast_read call 04058 */ 04059 if (AST_LIST_NEXT(f, frame_list)) { 04060 ast_queue_frame(chan, AST_LIST_NEXT(f, frame_list)); 04061 ast_frfree(AST_LIST_NEXT(f, frame_list)); 04062 AST_LIST_NEXT(f, frame_list) = NULL; 04063 } 04064 04065 switch (f->frametype) { 04066 case AST_FRAME_CONTROL: 04067 if (f->subclass.integer == AST_CONTROL_ANSWER) { 04068 if (!ast_test_flag(chan, AST_FLAG_OUTGOING)) { 04069 ast_debug(1, "Ignoring answer on an inbound call!\n"); 04070 ast_frfree(f); 04071 f = &ast_null_frame; 04072 } else if (prestate == AST_STATE_UP && ast_bridged_channel(chan)) { 04073 ast_debug(1, "Dropping duplicate answer!\n"); 04074 ast_frfree(f); 04075 f = &ast_null_frame; 04076 } else { 04077 /* Answer the CDR */ 04078 ast_setstate(chan, AST_STATE_UP); 04079 /* removed a call to ast_cdr_answer(chan->cdr) from here. */ 04080 ast_cel_report_event(chan, AST_CEL_ANSWER, NULL, NULL, NULL); 04081 } 04082 } else if (f->subclass.integer == AST_CONTROL_READ_ACTION) { 04083 read_action_payload = f->data.ptr; 04084 switch (read_action_payload->action) { 04085 case AST_FRAME_READ_ACTION_CONNECTED_LINE_MACRO: 04086 ast_party_connected_line_init(&connected); 04087 ast_party_connected_line_copy(&connected, &chan->connected); 04088 if (ast_connected_line_parse_data(read_action_payload->payload, 04089 read_action_payload->payload_size, &connected)) { 04090 ast_party_connected_line_free(&connected); 04091 break; 04092 } 04093 ast_channel_unlock(chan); 04094 if (ast_channel_connected_line_macro(NULL, chan, &connected, 1, 0)) { 04095 ast_indicate_data(chan, AST_CONTROL_CONNECTED_LINE, 04096 read_action_payload->payload, 04097 read_action_payload->payload_size); 04098 } 04099 ast_party_connected_line_free(&connected); 04100 ast_channel_lock(chan); 04101 break; 04102 } 04103 ast_frfree(f); 04104 f = &ast_null_frame; 04105 } 04106 break; 04107 case AST_FRAME_DTMF_END: 04108 send_dtmf_event(chan, "Received", f->subclass.integer, "No", "Yes"); 04109 ast_log(LOG_DTMF, "DTMF end '%c' received on %s, duration %ld ms\n", f->subclass.integer, chan->name, f->len); 04110 /* Queue it up if DTMF is deferred, or if DTMF emulation is forced. */ 04111 if (ast_test_flag(chan, AST_FLAG_DEFER_DTMF) || ast_test_flag(chan, AST_FLAG_EMULATE_DTMF)) { 04112 queue_dtmf_readq(chan, f); 04113 ast_frfree(f); 04114 f = &ast_null_frame; 04115 } else if (!ast_test_flag(chan, AST_FLAG_IN_DTMF | AST_FLAG_END_DTMF_ONLY)) { 04116 if (!ast_tvzero(chan->dtmf_tv) && 04117 ast_tvdiff_ms(ast_tvnow(), chan->dtmf_tv) < AST_MIN_DTMF_GAP) { 04118 /* If it hasn't been long enough, defer this digit */ 04119 queue_dtmf_readq(chan, f); 04120 ast_frfree(f); 04121 f = &ast_null_frame; 04122 } else { 04123 /* There was no begin, turn this into a begin and send the end later */ 04124 f->frametype = AST_FRAME_DTMF_BEGIN; 04125 ast_set_flag(chan, AST_FLAG_EMULATE_DTMF); 04126 chan->emulate_dtmf_digit = f->subclass.integer; 04127 chan->dtmf_tv = ast_tvnow(); 04128 if (f->len) { 04129 if (f->len > AST_MIN_DTMF_DURATION) 04130 chan->emulate_dtmf_duration = f->len; 04131 else 04132 chan->emulate_dtmf_duration = AST_MIN_DTMF_DURATION; 04133 } else 04134 chan->emulate_dtmf_duration = AST_DEFAULT_EMULATE_DTMF_DURATION; 04135 ast_log(LOG_DTMF, "DTMF begin emulation of '%c' with duration %u queued on %s\n", f->subclass.integer, chan->emulate_dtmf_duration, chan->name); 04136 } 04137 if (chan->audiohooks) { 04138 struct ast_frame *old_frame = f; 04139 /*! 04140 * \todo XXX It is possible to write a digit to the audiohook twice 04141 * if the digit was originally read while the channel was in autoservice. */ 04142 f = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_READ, f); 04143 if (old_frame != f) 04144 ast_frfree(old_frame); 04145 } 04146 } else { 04147 struct timeval now = ast_tvnow(); 04148 if (ast_test_flag(chan, AST_FLAG_IN_DTMF)) { 04149 ast_log(LOG_DTMF, "DTMF end accepted with begin '%c' on %s\n", f->subclass.integer, chan->name); 04150 ast_clear_flag(chan, AST_FLAG_IN_DTMF); 04151 if (!f->len) 04152 f->len = ast_tvdiff_ms(now, chan->dtmf_tv); 04153 04154 /* detect tones that were received on 04155 * the wire with durations shorter than 04156 * AST_MIN_DTMF_DURATION and set f->len 04157 * to the actual duration of the DTMF 04158 * frames on the wire. This will cause 04159 * dtmf emulation to be triggered later 04160 * on. 04161 */ 04162 if (ast_tvdiff_ms(now, chan->dtmf_tv) < AST_MIN_DTMF_DURATION) { 04163 f->len = ast_tvdiff_ms(now, chan->dtmf_tv); 04164 ast_log(LOG_DTMF, "DTMF end '%c' detected to have actual duration %ld on the wire, emulation will be triggered on %s\n", f->subclass.integer, f->len, chan->name); 04165 } 04166 } else if (!f->len) { 04167 ast_log(LOG_DTMF, "DTMF end accepted without begin '%c' on %s\n", f->subclass.integer, chan->name); 04168 f->len = AST_MIN_DTMF_DURATION; 04169 } 04170 if (f->len < AST_MIN_DTMF_DURATION && !ast_test_flag(chan, AST_FLAG_END_DTMF_ONLY)) { 04171 ast_log(LOG_DTMF, "DTMF end '%c' has duration %ld but want minimum %d, emulating on %s\n", f->subclass.integer, f->len, AST_MIN_DTMF_DURATION, chan->name); 04172 ast_set_flag(chan, AST_FLAG_EMULATE_DTMF); 04173 chan->emulate_dtmf_digit = f->subclass.integer; 04174 chan->emulate_dtmf_duration = AST_MIN_DTMF_DURATION - f->len; 04175 ast_frfree(f); 04176 f = &ast_null_frame; 04177 } else { 04178 ast_log(LOG_DTMF, "DTMF end passthrough '%c' on %s\n", f->subclass.integer, chan->name); 04179 if (f->len < AST_MIN_DTMF_DURATION) { 04180 f->len = AST_MIN_DTMF_DURATION; 04181 } 04182 chan->dtmf_tv = now; 04183 } 04184 if (chan->audiohooks) { 04185 struct ast_frame *old_frame = f; 04186 f = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_READ, f); 04187 if (old_frame != f) 04188 ast_frfree(old_frame); 04189 } 04190 } 04191 break; 04192 case AST_FRAME_DTMF_BEGIN: 04193 send_dtmf_event(chan, "Received", f->subclass.integer, "Yes", "No"); 04194 ast_log(LOG_DTMF, "DTMF begin '%c' received on %s\n", f->subclass.integer, chan->name); 04195 if ( ast_test_flag(chan, AST_FLAG_DEFER_DTMF | AST_FLAG_END_DTMF_ONLY | AST_FLAG_EMULATE_DTMF) || 04196 (!ast_tvzero(chan->dtmf_tv) && 04197 ast_tvdiff_ms(ast_tvnow(), chan->dtmf_tv) < AST_MIN_DTMF_GAP) ) { 04198 ast_log(LOG_DTMF, "DTMF begin ignored '%c' on %s\n", f->subclass.integer, chan->name); 04199 ast_frfree(f); 04200 f = &ast_null_frame; 04201 } else { 04202 ast_set_flag(chan, AST_FLAG_IN_DTMF); 04203 chan->dtmf_tv = ast_tvnow(); 04204 ast_log(LOG_DTMF, "DTMF begin passthrough '%c' on %s\n", f->subclass.integer, chan->name); 04205 } 04206 break; 04207 case AST_FRAME_NULL: 04208 /* The EMULATE_DTMF flag must be cleared here as opposed to when the duration 04209 * is reached , because we want to make sure we pass at least one 04210 * voice frame through before starting the next digit, to ensure a gap 04211 * between DTMF digits. */ 04212 if (ast_test_flag(chan, AST_FLAG_EMULATE_DTMF)) { 04213 struct timeval now = ast_tvnow(); 04214 if (!chan->emulate_dtmf_duration) { 04215 ast_clear_flag(chan, AST_FLAG_EMULATE_DTMF); 04216 chan->emulate_dtmf_digit = 0; 04217 } else if (ast_tvdiff_ms(now, chan->dtmf_tv) >= chan->emulate_dtmf_duration) { 04218 chan->emulate_dtmf_duration = 0; 04219 ast_frfree(f); 04220 f = &chan->dtmff; 04221 f->frametype = AST_FRAME_DTMF_END; 04222 f->subclass.integer = chan->emulate_dtmf_digit; 04223 f->len = ast_tvdiff_ms(now, chan->dtmf_tv); 04224 chan->dtmf_tv = now; 04225 ast_clear_flag(chan, AST_FLAG_EMULATE_DTMF); 04226 chan->emulate_dtmf_digit = 0; 04227 ast_log(LOG_DTMF, "DTMF end emulation of '%c' queued on %s\n", f->subclass.integer, chan->name); 04228 if (chan->audiohooks) { 04229 struct ast_frame *old_frame = f; 04230 f = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_READ, f); 04231 if (old_frame != f) { 04232 ast_frfree(old_frame); 04233 } 04234 } 04235 } 04236 } 04237 break; 04238 case AST_FRAME_VOICE: 04239 /* The EMULATE_DTMF flag must be cleared here as opposed to when the duration 04240 * is reached , because we want to make sure we pass at least one 04241 * voice frame through before starting the next digit, to ensure a gap 04242 * between DTMF digits. */ 04243 if (ast_test_flag(chan, AST_FLAG_EMULATE_DTMF) && !chan->emulate_dtmf_duration) { 04244 ast_clear_flag(chan, AST_FLAG_EMULATE_DTMF); 04245 chan->emulate_dtmf_digit = 0; 04246 } 04247 04248 if (dropaudio || ast_test_flag(chan, AST_FLAG_IN_DTMF)) { 04249 if (dropaudio) 04250 ast_read_generator_actions(chan, f); 04251 ast_frfree(f); 04252 f = &ast_null_frame; 04253 } 04254 04255 if (ast_test_flag(chan, AST_FLAG_EMULATE_DTMF) && !ast_test_flag(chan, AST_FLAG_IN_DTMF)) { 04256 struct timeval now = ast_tvnow(); 04257 if (ast_tvdiff_ms(now, chan->dtmf_tv) >= chan->emulate_dtmf_duration) { 04258 chan->emulate_dtmf_duration = 0; 04259 ast_frfree(f); 04260 f = &chan->dtmff; 04261 f->frametype = AST_FRAME_DTMF_END; 04262 f->subclass.integer = chan->emulate_dtmf_digit; 04263 f->len = ast_tvdiff_ms(now, chan->dtmf_tv); 04264 chan->dtmf_tv = now; 04265 if (chan->audiohooks) { 04266 struct ast_frame *old_frame = f; 04267 f = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_READ, f); 04268 if (old_frame != f) 04269 ast_frfree(old_frame); 04270 } 04271 ast_log(LOG_DTMF, "DTMF end emulation of '%c' queued on %s\n", f->subclass.integer, chan->name); 04272 } else { 04273 /* Drop voice frames while we're still in the middle of the digit */ 04274 ast_frfree(f); 04275 f = &ast_null_frame; 04276 } 04277 } else if ((f->frametype == AST_FRAME_VOICE) && !(f->subclass.codec & chan->nativeformats)) { 04278 /* This frame is not one of the current native formats -- drop it on the floor */ 04279 char to[200]; 04280 ast_log(LOG_NOTICE, "Dropping incompatible voice frame on %s of format %s since our native format has changed to %s\n", 04281 chan->name, ast_getformatname(f->subclass.codec), ast_getformatname_multiple(to, sizeof(to), chan->nativeformats)); 04282 ast_frfree(f); 04283 f = &ast_null_frame; 04284 } else if ((f->frametype == AST_FRAME_VOICE)) { 04285 /* Send frame to audiohooks if present */ 04286 if (chan->audiohooks) { 04287 struct ast_frame *old_frame = f; 04288 f = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_READ, f); 04289 if (old_frame != f) 04290 ast_frfree(old_frame); 04291 } 04292 if (chan->monitor && chan->monitor->read_stream ) { 04293 /* XXX what does this do ? */ 04294 #ifndef MONITOR_CONSTANT_DELAY 04295 int jump = chan->outsmpl - chan->insmpl - 4 * f->samples; 04296 if (jump >= 0) { 04297 jump = calc_monitor_jump((chan->outsmpl - chan->insmpl), ast_format_rate(f->subclass.codec), ast_format_rate(chan->monitor->read_stream->fmt->format)); 04298 if (ast_seekstream(chan->monitor->read_stream, jump, SEEK_FORCECUR) == -1) 04299 ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n"); 04300 chan->insmpl += (chan->outsmpl - chan->insmpl) + f->samples; 04301 } else 04302 chan->insmpl+= f->samples; 04303 #else 04304 int jump = calc_monitor_jump((chan->outsmpl - chan->insmpl), ast_format_rate(f->subclass.codec), ast_format_rate(chan->monitor->read_stream->fmt->format)); 04305 if (jump - MONITOR_DELAY >= 0) { 04306 if (ast_seekstream(chan->monitor->read_stream, jump - f->samples, SEEK_FORCECUR) == -1) 04307 ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n"); 04308 chan->insmpl += chan->outsmpl - chan->insmpl; 04309 } else 04310 chan->insmpl += f->samples; 04311 #endif 04312 if (chan->monitor->state == AST_MONITOR_RUNNING) { 04313 if (ast_writestream(chan->monitor->read_stream, f) < 0) 04314 ast_log(LOG_WARNING, "Failed to write data to channel monitor read stream\n"); 04315 } 04316 } 04317 04318 if (chan->readtrans && (f = ast_translate(chan->readtrans, f, 1)) == NULL) { 04319 f = &ast_null_frame; 04320 } 04321 04322 /* it is possible for the translation process on chan->readtrans to have 04323 produced multiple frames from the single input frame we passed it; if 04324 this happens, queue the additional frames *before* the frames we may 04325 have queued earlier. if the readq was empty, put them at the head of 04326 the queue, and if it was not, put them just after the frame that was 04327 at the end of the queue. 04328 */ 04329 if (AST_LIST_NEXT(f, frame_list)) { 04330 if (!readq_tail) { 04331 ast_queue_frame_head(chan, AST_LIST_NEXT(f, frame_list)); 04332 } else { 04333 __ast_queue_frame(chan, AST_LIST_NEXT(f, frame_list), 0, readq_tail); 04334 } 04335 ast_frfree(AST_LIST_NEXT(f, frame_list)); 04336 AST_LIST_NEXT(f, frame_list) = NULL; 04337 } 04338 04339 /* Run generator sitting on the line if timing device not available 04340 * and synchronous generation of outgoing frames is necessary */ 04341 ast_read_generator_actions(chan, f); 04342 } 04343 break; 04344 default: 04345 /* Just pass it on! */ 04346 break; 04347 } 04348 } else { 04349 /* Make sure we always return NULL in the future */ 04350 if (!chan->_softhangup) { 04351 chan->_softhangup |= AST_SOFTHANGUP_DEV; 04352 } 04353 if (cause) 04354 chan->hangupcause = cause; 04355 if (chan->generator) 04356 ast_deactivate_generator(chan); 04357 /* We no longer End the CDR here */ 04358 } 04359 04360 /* High bit prints debugging */ 04361 if (chan->fin & DEBUGCHAN_FLAG) 04362 ast_frame_dump(chan->name, f, "<<"); 04363 chan->fin = FRAMECOUNT_INC(chan->fin); 04364 04365 done: 04366 if (chan->music_state && chan->generator && chan->generator->digit && f && f->frametype == AST_FRAME_DTMF_END) 04367 chan->generator->digit(chan, f->subclass.integer); 04368 04369 if (chan->audiohooks && ast_audiohook_write_list_empty(chan->audiohooks)) { 04370 /* The list gets recreated if audiohooks are added again later */ 04371 ast_audiohook_detach_list(chan->audiohooks); 04372 chan->audiohooks = NULL; 04373 } 04374 ast_channel_unlock(chan); 04375 return f; 04376 }
struct ast_channel* __ast_request_and_dial | ( | const char * | type, | |
format_t | format, | |||
const struct ast_channel * | requestor, | |||
void * | data, | |||
int | timeout, | |||
int * | reason, | |||
const char * | cid_num, | |||
const char * | cid_name, | |||
struct outgoing_helper * | oh | |||
) | [read] |
Request a channel of a given type, with data as optional information used by the low level module and attempt to place a call on it.
type | type of channel to request | |
format | requested channel format | |
requestor | channel requesting data | |
data | data to pass to the channel requester | |
timeout | maximum amount of time to wait for an answer | |
reason | why unsuccessful (if unsuccessful) | |
cid_num | Caller-ID Number | |
cid_name | Caller-ID Name (ascii) | |
oh | Outgoing helper |
Definition at line 5456 of file channel.c.
References ast_channel::_state, outgoing_helper::account, ast_call(), ast_call_forward(), AST_CAUSE_NO_ANSWER, ast_cdr_alloc(), ast_cdr_answer(), ast_cdr_busy(), ast_cdr_disposition(), ast_cdr_end(), ast_cdr_failed(), AST_CDR_FLAG_ORIGINATED, ast_cdr_init(), ast_cdr_setaccount(), ast_cdr_setapp(), ast_cdr_start(), ast_cdr_update(), ast_channel_datastore_inherit(), ast_channel_inherit_variables(), ast_channel_lock, ast_channel_lock_both, ast_channel_set_connected_line(), ast_channel_unlock, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CC, AST_CONTROL_CONGESTION, AST_CONTROL_CONNECTED_LINE, AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_REDIRECTING, AST_CONTROL_RINGING, AST_CONTROL_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, ast_copy_string(), AST_FRAME_CONTROL, ast_frfree, ast_hangup(), ast_log(), ast_party_connected_line_set_init(), AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, ast_read(), ast_remaining_ms(), ast_request(), ast_set_callerid(), ast_set_flag, ast_set_variables(), AST_STATE_UP, ast_strlen_zero(), ast_tvnow(), ast_waitfor(), ast_channel::cdr, outgoing_helper::cid_name, outgoing_helper::cid_num, ast_channel::connected, ast_channel::context, outgoing_helper::context, ast_channel::exten, outgoing_helper::exten, ast_frame::frametype, handle_cause(), ast_channel::hangupcause, ast_party_connected_line::id, ast_frame_subclass::integer, LOG_NOTICE, ast_party_id::name, ast_party_id::number, outgoing_helper::parent_channel, ast_party_name::presentation, ast_party_number::presentation, ast_channel::priority, outgoing_helper::priority, ast_party_name::str, ast_party_number::str, ast_frame::subclass, ast_party_name::valid, ast_party_number::valid, and outgoing_helper::vars.
Referenced by ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), ast_request_and_dial(), and parkandannounce_exec().
05457 { 05458 int dummy_outstate; 05459 int cause = 0; 05460 struct ast_channel *chan; 05461 int res = 0; 05462 int last_subclass = 0; 05463 struct ast_party_connected_line connected; 05464 05465 if (outstate) 05466 *outstate = 0; 05467 else 05468 outstate = &dummy_outstate; /* make outstate always a valid pointer */ 05469 05470 chan = ast_request(type, format, requestor, data, &cause); 05471 if (!chan) { 05472 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data); 05473 handle_cause(cause, outstate); 05474 return NULL; 05475 } 05476 05477 if (oh) { 05478 if (oh->vars) { 05479 ast_set_variables(chan, oh->vars); 05480 } 05481 if (!ast_strlen_zero(oh->cid_num) && !ast_strlen_zero(oh->cid_name)) { 05482 /* 05483 * Use the oh values instead of the function parameters for the 05484 * outgoing CallerID. 05485 */ 05486 cid_num = oh->cid_num; 05487 cid_name = oh->cid_name; 05488 } 05489 if (oh->parent_channel) { 05490 /* Safely inherit variables and datastores from the parent channel. */ 05491 ast_channel_lock_both(oh->parent_channel, chan); 05492 ast_channel_inherit_variables(oh->parent_channel, chan); 05493 ast_channel_datastore_inherit(oh->parent_channel, chan); 05494 ast_channel_unlock(oh->parent_channel); 05495 ast_channel_unlock(chan); 05496 } 05497 if (oh->account) { 05498 ast_channel_lock(chan); 05499 ast_cdr_setaccount(chan, oh->account); 05500 ast_channel_unlock(chan); 05501 } 05502 } 05503 05504 /* 05505 * I seems strange to set the CallerID on an outgoing call leg 05506 * to whom we are calling, but this function's callers are doing 05507 * various Originate methods. This call leg goes to the local 05508 * user. Once the local user answers, the dialplan needs to be 05509 * able to access the CallerID from the CALLERID function as if 05510 * the local user had placed this call. 05511 */ 05512 ast_set_callerid(chan, cid_num, cid_name, cid_num); 05513 05514 ast_set_flag(chan->cdr, AST_CDR_FLAG_ORIGINATED); 05515 ast_party_connected_line_set_init(&connected, &chan->connected); 05516 if (cid_num) { 05517 connected.id.number.valid = 1; 05518 connected.id.number.str = (char *) cid_num; 05519 connected.id.number.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED; 05520 } 05521 if (cid_name) { 05522 connected.id.name.valid = 1; 05523 connected.id.name.str = (char *) cid_name; 05524 connected.id.name.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED; 05525 } 05526 ast_channel_set_connected_line(chan, &connected, NULL); 05527 05528 if (ast_call(chan, data, 0)) { /* ast_call failed... */ 05529 ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data); 05530 } else { 05531 struct timeval start = ast_tvnow(); 05532 res = 1; /* mark success in case chan->_state is already AST_STATE_UP */ 05533 while (timeout && chan->_state != AST_STATE_UP) { 05534 struct ast_frame *f; 05535 int ms = ast_remaining_ms(start, timeout); 05536 05537 res = ast_waitfor(chan, ms); 05538 if (res == 0) { /* timeout, treat it like ringing */ 05539 *outstate = AST_CONTROL_RINGING; 05540 break; 05541 } 05542 if (res < 0) /* error or done */ 05543 break; 05544 if (!ast_strlen_zero(chan->call_forward)) { 05545 if (!(chan = ast_call_forward(NULL, chan, NULL, format, oh, outstate))) { 05546 return NULL; 05547 } 05548 continue; 05549 } 05550 05551 f = ast_read(chan); 05552 if (!f) { 05553 *outstate = AST_CONTROL_HANGUP; 05554 res = 0; 05555 break; 05556 } 05557 if (f->frametype == AST_FRAME_CONTROL) { 05558 switch (f->subclass.integer) { 05559 case AST_CONTROL_RINGING: /* record but keep going */ 05560 *outstate = f->subclass.integer; 05561 break; 05562 05563 case AST_CONTROL_BUSY: 05564 ast_cdr_busy(chan->cdr); 05565 *outstate = f->subclass.integer; 05566 timeout = 0; 05567 break; 05568 05569 case AST_CONTROL_INCOMPLETE: 05570 ast_cdr_failed(chan->cdr); 05571 *outstate = AST_CONTROL_CONGESTION; 05572 timeout = 0; 05573 break; 05574 05575 case AST_CONTROL_CONGESTION: 05576 ast_cdr_failed(chan->cdr); 05577 *outstate = f->subclass.integer; 05578 timeout = 0; 05579 break; 05580 05581 case AST_CONTROL_ANSWER: 05582 ast_cdr_answer(chan->cdr); 05583 *outstate = f->subclass.integer; 05584 timeout = 0; /* trick to force exit from the while() */ 05585 break; 05586 05587 /* Ignore these */ 05588 case AST_CONTROL_PROGRESS: 05589 case AST_CONTROL_PROCEEDING: 05590 case AST_CONTROL_HOLD: 05591 case AST_CONTROL_UNHOLD: 05592 case AST_CONTROL_VIDUPDATE: 05593 case AST_CONTROL_SRCUPDATE: 05594 case AST_CONTROL_SRCCHANGE: 05595 case AST_CONTROL_CONNECTED_LINE: 05596 case AST_CONTROL_REDIRECTING: 05597 case AST_CONTROL_CC: 05598 case -1: /* Ignore -- just stopping indications */ 05599 break; 05600 05601 default: 05602 ast_log(LOG_NOTICE, "Don't know what to do with control frame %d\n", f->subclass.integer); 05603 } 05604 last_subclass = f->subclass.integer; 05605 } 05606 ast_frfree(f); 05607 } 05608 } 05609 05610 /* Final fixups */ 05611 if (oh) { 05612 if (!ast_strlen_zero(oh->context)) 05613 ast_copy_string(chan->context, oh->context, sizeof(chan->context)); 05614 if (!ast_strlen_zero(oh->exten)) 05615 ast_copy_string(chan->exten, oh->exten, sizeof(chan->exten)); 05616 if (oh->priority) 05617 chan->priority = oh->priority; 05618 } 05619 if (chan->_state == AST_STATE_UP) 05620 *outstate = AST_CONTROL_ANSWER; 05621 05622 if (res <= 0) { 05623 ast_channel_lock(chan); 05624 if (AST_CONTROL_RINGING == last_subclass) { 05625 chan->hangupcause = AST_CAUSE_NO_ANSWER; 05626 } 05627 if (!chan->cdr && (chan->cdr = ast_cdr_alloc())) { 05628 ast_cdr_init(chan->cdr, chan); 05629 } 05630 if (chan->cdr) { 05631 char tmp[256]; 05632 05633 snprintf(tmp, sizeof(tmp), "%s/%s", type, (char *)data); 05634 ast_cdr_setapp(chan->cdr, "Dial", tmp); 05635 ast_cdr_update(chan); 05636 ast_cdr_start(chan->cdr); 05637 ast_cdr_end(chan->cdr); 05638 /* If the cause wasn't handled properly */ 05639 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) { 05640 ast_cdr_failed(chan->cdr); 05641 } 05642 } 05643 ast_channel_unlock(chan); 05644 ast_hangup(chan); 05645 chan = NULL; 05646 } 05647 return chan; 05648 }
static void __init_state2str_threadbuf | ( | void | ) | [static] |
static void adjust_frame_for_plc | ( | struct ast_channel * | chan, | |
struct ast_frame * | frame, | |||
struct ast_datastore * | datastore | |||
) | [static] |
Definition at line 4837 of file channel.c.
References ast_calloc, ast_channel_datastore_remove(), ast_datastore_free(), ast_free, AST_FRIENDLY_OFFSET, ast_frame::data, ast_datastore::data, ast_frame::datalen, plc_ds::num_samples, ast_frame::offset, plc_fillin(), plc_rx(), plc_ds::plc_state, ast_frame::ptr, ast_frame::samples, and plc_ds::samples_buf.
Referenced by apply_plc().
04838 { 04839 int num_new_samples = frame->samples; 04840 struct plc_ds *plc = datastore->data; 04841 04842 /* As a general note, let me explain the somewhat odd calculations used when taking 04843 * the frame offset into account here. According to documentation in frame.h, the frame's 04844 * offset field indicates the number of bytes that the audio is offset. The plc->samples_buf 04845 * is not an array of bytes, but rather an array of 16-bit integers since it holds SLIN 04846 * samples. So I had two choices to make here with the offset. 04847 * 04848 * 1. Make the offset AST_FRIENDLY_OFFSET bytes. The main downside for this is that 04849 * I can't just add AST_FRIENDLY_OFFSET to the plc->samples_buf and have the pointer 04850 * arithmetic come out right. I would have to do some odd casting or division for this to 04851 * work as I wanted. 04852 * 2. Make the offset AST_FRIENDLY_OFFSET * 2 bytes. This allows the pointer arithmetic 04853 * to work out better with the plc->samples_buf. The downside here is that the buffer's 04854 * allocation contains an extra 64 bytes of unused space. 04855 * 04856 * I decided to go with option 2. This is why in the calloc statement and the statement that 04857 * sets the frame's offset, AST_FRIENDLY_OFFSET is multiplied by 2. 04858 */ 04859 04860 /* If this audio frame has no samples to fill in, ignore it */ 04861 if (!num_new_samples) { 04862 return; 04863 } 04864 04865 /* First, we need to be sure that our buffer is large enough to accomodate 04866 * the samples we need to fill in. This will likely only occur on the first 04867 * frame we write. 04868 */ 04869 if (plc->num_samples < num_new_samples) { 04870 ast_free(plc->samples_buf); 04871 plc->samples_buf = ast_calloc(1, (num_new_samples * sizeof(*plc->samples_buf)) + (AST_FRIENDLY_OFFSET * 2)); 04872 if (!plc->samples_buf) { 04873 ast_channel_datastore_remove(chan, datastore); 04874 ast_datastore_free(datastore); 04875 return; 04876 } 04877 plc->num_samples = num_new_samples; 04878 } 04879 04880 if (frame->datalen == 0) { 04881 plc_fillin(&plc->plc_state, plc->samples_buf + AST_FRIENDLY_OFFSET, frame->samples); 04882 frame->data.ptr = plc->samples_buf + AST_FRIENDLY_OFFSET; 04883 frame->datalen = num_new_samples * 2; 04884 frame->offset = AST_FRIENDLY_OFFSET * 2; 04885 } else { 04886 plc_rx(&plc->plc_state, frame->data.ptr, frame->samples); 04887 } 04888 }
static void apply_plc | ( | struct ast_channel * | chan, | |
struct ast_frame * | frame | |||
) | [static] |
Definition at line 4890 of file channel.c.
References adjust_frame_for_plc(), ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_datastore_alloc, ast_datastore_free(), and ast_datastore::data.
Referenced by ast_write().
04891 { 04892 struct ast_datastore *datastore; 04893 struct plc_ds *plc; 04894 04895 datastore = ast_channel_datastore_find(chan, &plc_ds_info, NULL); 04896 if (datastore) { 04897 plc = datastore->data; 04898 adjust_frame_for_plc(chan, frame, datastore); 04899 return; 04900 } 04901 04902 datastore = ast_datastore_alloc(&plc_ds_info, NULL); 04903 if (!datastore) { 04904 return; 04905 } 04906 plc = ast_calloc(1, sizeof(*plc)); 04907 if (!plc) { 04908 ast_datastore_free(datastore); 04909 return; 04910 } 04911 datastore->data = plc; 04912 ast_channel_datastore_add(chan, datastore); 04913 adjust_frame_for_plc(chan, frame, datastore); 04914 }
int ast_activate_generator | ( | struct ast_channel * | chan, | |
struct ast_generator * | gen, | |||
void * | params | |||
) |
Activate a given generator
Definition at line 3148 of file channel.c.
References ast_generator::alloc, ast_channel_lock, ast_channel_unlock, ast_prod(), ast_settimeout(), ast_channel::generator, generator_force(), ast_channel::generatordata, and ast_generator::release.
Referenced by app_exec(), ast_channel_start_silence_generator(), ast_linear_stream(), ast_playtones_start(), ast_tonepair_start(), channel_spy(), eivr_comm(), local_ast_moh_start(), old_milliwatt_exec(), and transmit_audio().
03149 { 03150 int res = 0; 03151 03152 ast_channel_lock(chan); 03153 if (chan->generatordata) { 03154 struct ast_generator *generator_old = chan->generator; 03155 03156 if (generator_old && generator_old->release) { 03157 generator_old->release(chan, chan->generatordata); 03158 } 03159 chan->generatordata = NULL; 03160 } 03161 if (gen->alloc && !(chan->generatordata = gen->alloc(chan, params))) { 03162 res = -1; 03163 } 03164 if (!res) { 03165 ast_settimeout(chan, 50, generator_force, chan); 03166 chan->generator = gen; 03167 } 03168 ast_channel_unlock(chan); 03169 03170 ast_prod(chan); 03171 03172 return res; 03173 }
int ast_active_channels | ( | void | ) |
returns number of active/allocated channels
Definition at line 848 of file channel.c.
References ao2_container_count(), and channels.
Referenced by action_corestatus(), ast_var_channels(), ast_var_channels_table(), dahdi_restart(), handle_chanlist(), handle_show_settings(), and really_quit().
00849 { 00850 return channels ? ao2_container_count(channels) : 0; 00851 }
int ast_answer | ( | struct ast_channel * | chan | ) |
Answer a channel.
chan | channel to answer |
This function answers a channel and handles all necessary call setup functions.
0 | on success | |
non-zero | on failure |
Definition at line 3086 of file channel.c.
References __ast_answer().
Referenced by action_bridge(), agi_exec_full(), alarmreceiver_exec(), answer_trunk_chan(), app_exec(), ast_control_streamfile(), ast_do_pickup(), AST_LIST_HEAD(), ast_pickup_call(), auth_exec(), background_detect_exec(), bridge_exec(), builtin_parkcall(), common_exec(), conf_exec(), count_exec(), dahdiras_exec(), dial_exec_full(), dictate_exec(), directory_exec(), disa_exec(), eivr_comm(), handle_answer(), ices_exec(), login_exec(), minivm_accmess_exec(), minivm_greet_exec(), minivm_record_exec(), old_milliwatt_exec(), park_call_exec(), parked_call_exec(), pbx_builtin_background(), playback_exec(), privacy_exec(), readexten_exec(), receivefax_exec(), record_exec(), sayunixtime_exec(), send_waveform_to_channel(), sendfax_exec(), setup_privacy_args(), skel_exec(), sla_station_exec(), speech_background(), testclient_exec(), testserver_exec(), transmit(), vm_exec(), vm_execmain(), waitfor_exec(), and zapateller_exec().
03087 { 03088 return __ast_answer(chan, 0, 1); 03089 }
void ast_begin_shutdown | ( | int | hangup | ) |
Initiate system shutdown -- prevents new channels from being allocated.
hangup | If "hangup" is non-zero, all existing channels will receive soft hangups |
Definition at line 838 of file channel.c.
References ao2_callback, ast_channel_softhangup_cb(), channels, OBJ_MULTIPLE, and OBJ_NODATA.
Referenced by can_safely_quit().
00839 { 00840 shutting_down = 1; 00841 00842 if (hangup) { 00843 ao2_callback(channels, OBJ_NODATA | OBJ_MULTIPLE, ast_channel_softhangup_cb, NULL); 00844 } 00845 }
Pick the best audio codec.
Pick the best codec Choose the best codec... Uhhh... Yah.
Okay, ulaw is used by all telephony equipment, so start with it
Unless of course, you're a silly European, so then prefer ALAW
G.722 is better then all below, but not as common as the above... so give ulaw and alaw priority
Okay, well, signed linear is easy to translate into other stuff
G.726 is standard ADPCM, in RFC3551 packing order
G.726 is standard ADPCM, in AAL2 packing order
ADPCM has great sound quality and is still pretty easy to translate
Okay, we're down to vocoders now, so pick GSM because it's small and easier to translate and sounds pretty good
iLBC is not too bad
Speex is free, but computationally more expensive than GSM
Ick, LPC10 sounds terrible, but at least we have code for it, if you're tacky enough to use it
G.729a is faster than 723 and slightly less expensive
Down to G.723.1 which is proprietary but at least designed for voice
Definition at line 1062 of file channel.c.
References ARRAY_LEN, AST_FORMAT_ADPCM, AST_FORMAT_ALAW, AST_FORMAT_AUDIO_MASK, AST_FORMAT_G719, AST_FORMAT_G722, AST_FORMAT_G723_1, AST_FORMAT_G726, AST_FORMAT_G726_AAL2, AST_FORMAT_G729A, AST_FORMAT_GSM, AST_FORMAT_ILBC, AST_FORMAT_LPC10, AST_FORMAT_SIREN14, AST_FORMAT_SIREN7, AST_FORMAT_SLINEAR, AST_FORMAT_SLINEAR16, AST_FORMAT_SPEEX, AST_FORMAT_SPEEX16, AST_FORMAT_TESTLAW, AST_FORMAT_ULAW, ast_getformatname_multiple(), ast_log(), LOG_WARNING, and prefs.
Referenced by __oh323_new(), agent_call(), ast_codec_choose(), ast_iax2_new(), ast_speech_new(), bridge_make_compatible(), builtin_atxfer(), echo_exec(), findmeexec(), gtalk_new(), handle_open_receive_channel_ack_message(), iax2_request(), jingle_new(), local_new(), login_exec(), mgcp_new(), multicast_rtp_request(), set_format(), sip_new(), skinny_new(), skinny_set_rtp_peer(), socket_process(), start_rtp(), transmit_connect(), and unistim_new().
01063 { 01064 /* This just our opinion, expressed in code. We are asked to choose 01065 the best codec to use, given no information */ 01066 int x; 01067 static const format_t prefs[] = 01068 { 01069 /*! Okay, ulaw is used by all telephony equipment, so start with it */ 01070 AST_FORMAT_ULAW, 01071 /*! Unless of course, you're a silly European, so then prefer ALAW */ 01072 AST_FORMAT_ALAW, 01073 AST_FORMAT_G719, 01074 AST_FORMAT_SIREN14, 01075 AST_FORMAT_SIREN7, 01076 AST_FORMAT_TESTLAW, 01077 /*! G.722 is better then all below, but not as common as the above... so give ulaw and alaw priority */ 01078 AST_FORMAT_G722, 01079 /*! Okay, well, signed linear is easy to translate into other stuff */ 01080 AST_FORMAT_SLINEAR16, 01081 AST_FORMAT_SLINEAR, 01082 /*! G.726 is standard ADPCM, in RFC3551 packing order */ 01083 AST_FORMAT_G726, 01084 /*! G.726 is standard ADPCM, in AAL2 packing order */ 01085 AST_FORMAT_G726_AAL2, 01086 /*! ADPCM has great sound quality and is still pretty easy to translate */ 01087 AST_FORMAT_ADPCM, 01088 /*! Okay, we're down to vocoders now, so pick GSM because it's small and easier to 01089 translate and sounds pretty good */ 01090 AST_FORMAT_GSM, 01091 /*! iLBC is not too bad */ 01092 AST_FORMAT_ILBC, 01093 /*! Speex is free, but computationally more expensive than GSM */ 01094 AST_FORMAT_SPEEX16, 01095 AST_FORMAT_SPEEX, 01096 /*! Ick, LPC10 sounds terrible, but at least we have code for it, if you're tacky enough 01097 to use it */ 01098 AST_FORMAT_LPC10, 01099 /*! G.729a is faster than 723 and slightly less expensive */ 01100 AST_FORMAT_G729A, 01101 /*! Down to G.723.1 which is proprietary but at least designed for voice */ 01102 AST_FORMAT_G723_1, 01103 }; 01104 char buf[512]; 01105 01106 /* Strip out video */ 01107 fmts &= AST_FORMAT_AUDIO_MASK; 01108 01109 /* Find the first preferred codec in the format given */ 01110 for (x = 0; x < ARRAY_LEN(prefs); x++) { 01111 if (fmts & prefs[x]) 01112 return prefs[x]; 01113 } 01114 01115 ast_log(LOG_WARNING, "Don't know any of %s formats\n", ast_getformatname_multiple(buf, sizeof(buf), fmts)); 01116 01117 return 0; 01118 }
struct ast_channel* ast_bridged_channel | ( | struct ast_channel * | chan | ) | [read] |
Find bridged channel.
chan | Current channel |
Definition at line 7160 of file channel.c.
References ast_channel::_bridge, ast_channel_tech::bridged_channel, and ast_channel::tech.
Referenced by __analog_handle_event(), __analog_ss_thread(), __ast_channel_masquerade(), __ast_read(), __dahdi_exception(), _skinny_show_lines(), action_agents(), action_coreshowchannels(), agents_data_provider_get(), agents_show(), agents_show_online(), analog_attempt_transfer(), analog_exception(), analog_hangup(), analog_ss_thread(), ast_bridge_call(), ast_cel_report_event(), ast_channel_data_add_structure(), ast_channel_set_linkgroup(), ast_do_masquerade(), ast_rtp_instance_set_stats_vars(), ast_set_hangupsource(), ast_var_channel_bridge(), ast_var_channels_table(), attempt_transfer(), cb_events(), channel_spy(), check_bridge(), common_exec(), console_transfer(), create_jb(), dahdi_handle_event(), dahdi_hangup(), export_aoc_vars(), func_channel_read(), get_refer_info(), handle_chanlist(), handle_hd_hf(), handle_invite_replaces(), handle_request(), handle_request_bye(), handle_request_info(), handle_request_refer(), handle_showchan(), handle_soft_key_event_message(), handle_stimulus_message(), key_call(), key_dial_page(), local_attended_transfer(), local_queryoption(), mgcp_hangup(), mgcp_ss(), misdn_attempt_transfer(), mixmonitor_thread(), my_get_sigpvt_bridged_channel(), park_call_full(), schedule_delivery(), serialize_showchan(), sip_get_rtp_peer(), sip_get_trtp_peer(), sip_get_udptl_peer(), sip_get_vrtp_peer(), sip_hangup(), sip_set_rtp_peer(), skinny_transfer(), socket_process(), start_spying(), startmon(), TransferCallStep1(), and unistim_hangup().
07161 { 07162 struct ast_channel *bridged; 07163 bridged = chan->_bridge; 07164 if (bridged && bridged->tech->bridged_channel) 07165 bridged = bridged->tech->bridged_channel(chan, bridged); 07166 return bridged; 07167 }
int ast_call | ( | struct ast_channel * | chan, | |
char * | addr, | |||
int | timeout | |||
) |
Make a call.
chan | which channel to make the call on | |
addr | destination of the call (Should be treated as const char *) | |
timeout | time to wait on for connect |
Place a call, take no longer than timeout ms.
Definition at line 5761 of file channel.c.
References AST_CDR_FLAG_DIALED, ast_channel_lock, ast_channel_unlock, ast_check_hangup(), AST_FLAG_OUTGOING, AST_FLAG_ZOMBIE, ast_set_flag, ast_test_flag, ast_channel_tech::call, ast_channel::cdr, and ast_channel::tech.
Referenced by __ast_request_and_dial(), ast_call_forward(), begin_dial_channel(), dial_exec_full(), dial_transfer(), do_forward(), feature_request_and_dial(), findmeexec(), play_sound_file(), ring_entry(), and wait_for_answer().
05762 { 05763 /* Place an outgoing call, but don't wait any longer than timeout ms before returning. 05764 If the remote end does not answer within the timeout, then do NOT hang up, but 05765 return anyway. */ 05766 int res = -1; 05767 /* Stop if we're a zombie or need a soft hangup */ 05768 ast_channel_lock(chan); 05769 if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan)) { 05770 if (chan->cdr) { 05771 ast_set_flag(chan->cdr, AST_CDR_FLAG_DIALED); 05772 } 05773 if (chan->tech->call) 05774 res = chan->tech->call(chan, addr, timeout); 05775 ast_set_flag(chan, AST_FLAG_OUTGOING); 05776 } 05777 ast_channel_unlock(chan); 05778 return res; 05779 }
struct ast_channel* ast_call_forward | ( | struct ast_channel * | caller, | |
struct ast_channel * | orig, | |||
int * | timeout, | |||
format_t | format, | |||
struct outgoing_helper * | oh, | |||
int * | outstate | |||
) | [read] |
Forwards a call to a new channel specified by the original channel's call_forward str. If possible, the new forwarded channel is created and returned while the original one is terminated.
caller | in channel that requested orig | |
orig | channel being replaced by the call forward channel | |
timeout | maximum amount of time to wait for setup of new forward channel | |
format | requested channel format | |
oh | outgoing helper used with original channel | |
outstate | reason why unsuccessful (if uncuccessful) |
Definition at line 5386 of file channel.c.
References outgoing_helper::account, accountcode, ast_call(), AST_CDR_FLAG_ORIGINATED, ast_cdr_setaccount(), ast_channel_lock, ast_channel_lock_both, ast_channel_unlock, ast_copy_flags, ast_copy_string(), ast_hangup(), ast_log(), ast_party_connected_line_copy(), ast_party_redirecting_copy(), ast_request(), ast_set_variables(), ast_string_field_set, call_forward_inherit(), ast_channel::cdr, ast_channel::connected, ast_channel::context, handle_cause(), LOG_NOTICE, outgoing_helper::parent_channel, pbx_builtin_getvar_helper(), ast_channel::redirecting, S_OR, type, and outgoing_helper::vars.
Referenced by __ast_request_and_dial(), and feature_request_and_dial().
05387 { 05388 char tmpchan[256]; 05389 struct ast_channel *new_chan = NULL; 05390 char *data, *type; 05391 int cause = 0; 05392 int res; 05393 05394 /* gather data and request the new forward channel */ 05395 ast_copy_string(tmpchan, orig->call_forward, sizeof(tmpchan)); 05396 if ((data = strchr(tmpchan, '/'))) { 05397 *data++ = '\0'; 05398 type = tmpchan; 05399 } else { 05400 const char *forward_context; 05401 ast_channel_lock(orig); 05402 forward_context = pbx_builtin_getvar_helper(orig, "FORWARD_CONTEXT"); 05403 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", orig->call_forward, S_OR(forward_context, orig->context)); 05404 ast_channel_unlock(orig); 05405 data = tmpchan; 05406 type = "Local"; 05407 } 05408 if (!(new_chan = ast_request(type, format, orig, data, &cause))) { 05409 ast_log(LOG_NOTICE, "Unable to create channel for call forward to '%s/%s' (cause = %d)\n", type, data, cause); 05410 handle_cause(cause, outstate); 05411 ast_hangup(orig); 05412 return NULL; 05413 } 05414 05415 /* Copy/inherit important information into new channel */ 05416 if (oh) { 05417 if (oh->vars) { 05418 ast_set_variables(new_chan, oh->vars); 05419 } 05420 if (oh->parent_channel) { 05421 call_forward_inherit(new_chan, oh->parent_channel, orig); 05422 } 05423 if (oh->account) { 05424 ast_channel_lock(new_chan); 05425 ast_cdr_setaccount(new_chan, oh->account); 05426 ast_channel_unlock(new_chan); 05427 } 05428 } else if (caller) { /* no outgoing helper so use caller if available */ 05429 call_forward_inherit(new_chan, caller, orig); 05430 } 05431 05432 ast_channel_lock_both(orig, new_chan); 05433 ast_copy_flags(new_chan->cdr, orig->cdr, AST_CDR_FLAG_ORIGINATED); 05434 ast_string_field_set(new_chan, accountcode, orig->accountcode); 05435 ast_party_connected_line_copy(&new_chan->connected, &orig->connected); 05436 ast_party_redirecting_copy(&new_chan->redirecting, &orig->redirecting); 05437 ast_channel_unlock(new_chan); 05438 ast_channel_unlock(orig); 05439 05440 /* call new channel */ 05441 res = ast_call(new_chan, data, 0); 05442 if (timeout) { 05443 *timeout = res; 05444 } 05445 if (res) { 05446 ast_log(LOG_NOTICE, "Unable to call forward to channel %s/%s\n", type, (char *)data); 05447 ast_hangup(orig); 05448 ast_hangup(new_chan); 05449 return NULL; 05450 } 05451 ast_hangup(orig); 05452 05453 return new_chan; 05454 }
void ast_cancel_shutdown | ( | void | ) |
Cancel a shutdown in progress.
Cancels an existing shutdown and returns to normal operation
Definition at line 859 of file channel.c.
Referenced by handle_abort_shutdown().
00860 { 00861 shutting_down = 0; 00862 }
const char* ast_cause2str | ( | int | cause | ) |
Gives the string form of a given hangup cause.
Gives the string form of a given cause code.
Definition at line 980 of file channel.c.
References ARRAY_LEN, causes, and causes_map::desc.
Referenced by __transmit_response(), ast_channel_data_add_structure(), ast_do_masquerade(), ast_hangup(), dial_exec_full(), findmeexec(), sip_hangup(), and transmit_request_with_auth().
void ast_change_name | ( | struct ast_channel * | chan, | |
const char * | newname | |||
) |
Change channel name.
chan | the channel to change the name of | |
newname | the name to change to |
Definition at line 6229 of file channel.c.
References __ast_change_name_nolink(), ao2_link, ao2_lock, ao2_unlink, ao2_unlock, ast_channel_lock, ast_channel_unlock, and channels.
Referenced by update_name().
06230 { 06231 /* We must re-link, as the hash value will change here. */ 06232 ao2_lock(channels); 06233 ast_channel_lock(chan); 06234 ao2_unlink(channels, chan); 06235 __ast_change_name_nolink(chan, newname); 06236 ao2_link(channels, chan); 06237 ast_channel_unlock(chan); 06238 ao2_unlock(channels); 06239 }
struct ast_channel * ast_channel_alloc | ( | int | needqueue, | |
int | state, | |||
const char * | cid_num, | |||
const char * | cid_name, | |||
const char * | acctcode, | |||
const char * | exten, | |||
const char * | context, | |||
const char * | linkedid, | |||
const int | amaflag, | |||
const char * | name_fmt, | |||
... | ||||
) | [read] |
Definition at line 9825 of file channel.c.
References __ast_channel_alloc_ap().
09830 { 09831 va_list ap1, ap2; 09832 struct ast_channel *result; 09833 09834 09835 va_start(ap1, name_fmt); 09836 va_start(ap2, name_fmt); 09837 result = __ast_channel_alloc_ap(needqueue, state, cid_num, cid_name, acctcode, exten, context, 09838 linkedid, amaflag, __FILE__, __LINE__, __FUNCTION__, name_fmt, ap1, ap2); 09839 va_end(ap1); 09840 va_end(ap2); 09841 09842 return result; 09843 }
enum ast_bridge_result ast_channel_bridge | ( | struct ast_channel * | c0, | |
struct ast_channel * | c1, | |||
struct ast_bridge_config * | config, | |||
struct ast_frame ** | fo, | |||
struct ast_channel ** | rc | |||
) |
Bridge two channels together.
c0 | first channel to bridge | |
c1 | second channel to bridge | |
config | config for the channels | |
fo | destination frame(?) | |
rc | destination channel(?) |
Bridge two channels (c0 and c1) together. If an important frame occurs, we return that frame in *rf (remember, it could be NULL) and which channel (0 or 1) in rc
Definition at line 7506 of file channel.c.
References ast_channel::_bridge, ast_channel::_softhangup, AST_BRIDGE_COMPLETE, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_RETRY, ast_channel_clear_softhangup(), ast_channel_lock_both, ast_channel_make_compatible(), ast_channel_unlock, ast_check_hangup(), ast_check_hangup_locked(), ast_clear_flag, AST_CONTROL_SRCUPDATE, ast_debug, AST_FEATURE_PLAY_WARNING, AST_FEATURE_WARNING_ACTIVE, AST_FLAG_END_DTMF_ONLY, AST_FLAG_NBRIDGE, AST_FLAG_ZOMBIE, ast_framehook_list_is_empty(), ast_generic_bridge(), ast_indicate(), ast_log(), ast_manager_event_multichan, ast_samp2tv(), ast_set_flag, ast_set_owners_and_peers(), AST_SOFTHANGUP_UNBRIDGE, ast_test_flag, ast_test_suite_event_notify, ast_tvadd(), ast_tvdiff_ms(), ast_tvnow(), ast_tvsub(), ast_tvzero(), ast_verb, ast_channel::audiohooks, ast_channel_tech::bridge, bridge_play_sounds(), bridge_playfile(), ast_channel::caller, ast_bridge_config::end_sound, EVENT_FLAG_CALL, ast_bridge_config::feature_start_time, ast_bridge_config::feature_timer, ast_bridge_config::features_callee, ast_bridge_config::features_caller, ast_bridge_config::flags, ast_channel::framehooks, ast_channel::generator, ast_party_caller::id, LOG_WARNING, manager_bridge_event(), ast_channel::masq, ast_channel::masqr, ast_channel::monitor, ast_channel::nativeformats, ast_bridge_config::nexteventts, ast_party_id::number, ast_bridge_config::play_warning, ast_channel::readformat, S_COR, ast_channel_tech::send_digit_begin, ast_bridge_config::start_sound, ast_bridge_config::start_time, ast_party_number::str, ast_channel::tech, ast_bridge_config::timelimit, update_bridge_vars(), ast_party_number::valid, ast_bridge_config::warning_freq, ast_bridge_config::warning_sound, and ast_channel::writeformat.
Referenced by ast_bridge_call().
07508 { 07509 struct ast_channel *chans[2] = { c0, c1 }; 07510 enum ast_bridge_result res = AST_BRIDGE_COMPLETE; 07511 format_t o0nativeformats; 07512 format_t o1nativeformats; 07513 long time_left_ms=0; 07514 char caller_warning = 0; 07515 char callee_warning = 0; 07516 07517 *fo = NULL; 07518 07519 if (c0->_bridge) { 07520 ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 07521 c0->name, c0->_bridge->name); 07522 return -1; 07523 } 07524 if (c1->_bridge) { 07525 ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 07526 c1->name, c1->_bridge->name); 07527 return -1; 07528 } 07529 07530 /* Stop if we're a zombie or need a soft hangup */ 07531 if (ast_test_flag(c0, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c0) || 07532 ast_test_flag(c1, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c1)) 07533 return -1; 07534 07535 caller_warning = ast_test_flag(&config->features_caller, AST_FEATURE_PLAY_WARNING); 07536 callee_warning = ast_test_flag(&config->features_callee, AST_FEATURE_PLAY_WARNING); 07537 07538 if (ast_tvzero(config->start_time)) { 07539 config->start_time = ast_tvnow(); 07540 if (config->start_sound) { 07541 if (caller_warning) { 07542 bridge_playfile(c0, c1, config->start_sound, config->timelimit / 1000); 07543 } 07544 if (callee_warning) { 07545 bridge_playfile(c1, c0, config->start_sound, config->timelimit / 1000); 07546 } 07547 } 07548 } 07549 07550 /* Keep track of bridge */ 07551 ast_channel_lock_both(c0, c1); 07552 c0->_bridge = c1; 07553 c1->_bridge = c0; 07554 ast_channel_unlock(c0); 07555 ast_channel_unlock(c1); 07556 07557 ast_set_owners_and_peers(c0, c1); 07558 07559 o0nativeformats = c0->nativeformats; 07560 o1nativeformats = c1->nativeformats; 07561 07562 if (config->feature_timer && !ast_tvzero(config->nexteventts)) { 07563 config->nexteventts = ast_tvadd(config->feature_start_time, ast_samp2tv(config->feature_timer, 1000)); 07564 } else if (config->timelimit) { 07565 time_left_ms = config->timelimit - ast_tvdiff_ms(ast_tvnow(), config->start_time); 07566 config->nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->timelimit, 1000)); 07567 if ((caller_warning || callee_warning) && config->play_warning) { 07568 long next_warn = config->play_warning; 07569 if (time_left_ms < config->play_warning && config->warning_freq > 0) { 07570 /* At least one warning was played, which means we are returning after feature */ 07571 long warns_passed = (config->play_warning - time_left_ms) / config->warning_freq; 07572 /* It is 'warns_passed * warning_freq' NOT '(warns_passed + 1) * warning_freq', 07573 because nexteventts will be updated once again in the 'if (!to)' block */ 07574 next_warn = config->play_warning - warns_passed * config->warning_freq; 07575 } 07576 config->nexteventts = ast_tvsub(config->nexteventts, ast_samp2tv(next_warn, 1000)); 07577 } 07578 } else { 07579 config->nexteventts.tv_sec = 0; 07580 config->nexteventts.tv_usec = 0; 07581 } 07582 07583 if (!c0->tech->send_digit_begin) 07584 ast_set_flag(c1, AST_FLAG_END_DTMF_ONLY); 07585 if (!c1->tech->send_digit_begin) 07586 ast_set_flag(c0, AST_FLAG_END_DTMF_ONLY); 07587 manager_bridge_event(1, 1, c0, c1); 07588 07589 /* Before we enter in and bridge these two together tell them both the source of audio has changed */ 07590 ast_indicate(c0, AST_CONTROL_SRCUPDATE); 07591 ast_indicate(c1, AST_CONTROL_SRCUPDATE); 07592 07593 for (/* ever */;;) { 07594 struct timeval now = { 0, }; 07595 int to; 07596 07597 to = -1; 07598 07599 if (!ast_tvzero(config->nexteventts)) { 07600 now = ast_tvnow(); 07601 to = ast_tvdiff_ms(config->nexteventts, now); 07602 if (to <= 0) { 07603 if (!config->timelimit) { 07604 res = AST_BRIDGE_COMPLETE; 07605 break; 07606 } 07607 to = 0; 07608 } 07609 } 07610 07611 if (config->timelimit) { 07612 time_left_ms = config->timelimit - ast_tvdiff_ms(now, config->start_time); 07613 if (time_left_ms < 0) { 07614 time_left_ms = 0; 07615 } 07616 07617 if (time_left_ms < to) { 07618 to = time_left_ms; 07619 } 07620 07621 if (time_left_ms <= 0) { 07622 if (caller_warning && config->end_sound) 07623 bridge_playfile(c0, c1, config->end_sound, 0); 07624 if (callee_warning && config->end_sound) 07625 bridge_playfile(c1, c0, config->end_sound, 0); 07626 *fo = NULL; 07627 res = AST_BRIDGE_COMPLETE; 07628 ast_test_suite_event_notify("BRIDGE_TIMELIMIT", "Channel1: %s\r\nChannel2: %s", c0->name, c1->name); 07629 break; 07630 } 07631 07632 if (!to) { 07633 if (time_left_ms >= 5000 && config->warning_sound && config->play_warning && ast_test_flag(config, AST_FEATURE_WARNING_ACTIVE)) { 07634 int t = (time_left_ms + 500) / 1000; /* round to nearest second */ 07635 if (caller_warning) 07636 bridge_playfile(c0, c1, config->warning_sound, t); 07637 if (callee_warning) 07638 bridge_playfile(c1, c0, config->warning_sound, t); 07639 } 07640 07641 if (config->warning_freq && (time_left_ms > (config->warning_freq + 5000))) { 07642 config->nexteventts = ast_tvadd(config->nexteventts, ast_samp2tv(config->warning_freq, 1000)); 07643 } else { 07644 config->nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->timelimit, 1000)); 07645 } 07646 } 07647 ast_clear_flag(config, AST_FEATURE_WARNING_ACTIVE); 07648 } 07649 07650 if ((c0->_softhangup | c1->_softhangup) & AST_SOFTHANGUP_UNBRIDGE) {/* Bit operators are intentional. */ 07651 if (c0->_softhangup & AST_SOFTHANGUP_UNBRIDGE) { 07652 ast_channel_clear_softhangup(c0, AST_SOFTHANGUP_UNBRIDGE); 07653 } 07654 if (c1->_softhangup & AST_SOFTHANGUP_UNBRIDGE) { 07655 ast_channel_clear_softhangup(c1, AST_SOFTHANGUP_UNBRIDGE); 07656 } 07657 ast_channel_lock_both(c0, c1); 07658 c0->_bridge = c1; 07659 c1->_bridge = c0; 07660 ast_channel_unlock(c0); 07661 ast_channel_unlock(c1); 07662 ast_debug(1, "Unbridge signal received. Ending native bridge.\n"); 07663 continue; 07664 } 07665 07666 /* Stop if we're a zombie or need a soft hangup */ 07667 if (ast_test_flag(c0, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c0) || 07668 ast_test_flag(c1, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c1)) { 07669 *fo = NULL; 07670 res = AST_BRIDGE_COMPLETE; 07671 ast_debug(1, "Bridge stops because we're zombie or need a soft hangup: c0=%s, c1=%s, flags: %s,%s,%s,%s\n", 07672 c0->name, c1->name, 07673 ast_test_flag(c0, AST_FLAG_ZOMBIE) ? "Yes" : "No", 07674 ast_check_hangup(c0) ? "Yes" : "No", 07675 ast_test_flag(c1, AST_FLAG_ZOMBIE) ? "Yes" : "No", 07676 ast_check_hangup(c1) ? "Yes" : "No"); 07677 break; 07678 } 07679 07680 update_bridge_vars(c0, c1); 07681 07682 bridge_play_sounds(c0, c1); 07683 07684 if (c0->tech->bridge && 07685 /* if < 1 ms remains use generic bridging for accurate timing */ 07686 (!config->timelimit || to > 1000 || to == -1) && 07687 (c0->tech->bridge == c1->tech->bridge) && 07688 !c0->monitor && !c1->monitor && 07689 !c0->audiohooks && !c1->audiohooks && 07690 ast_framehook_list_is_empty(c0->framehooks) && ast_framehook_list_is_empty(c1->framehooks) && 07691 !c0->masq && !c0->masqr && !c1->masq && !c1->masqr) { 07692 int timeoutms = to - 1000 > 0 ? to - 1000 : to; 07693 /* Looks like they share a bridge method and nothing else is in the way */ 07694 ast_set_flag(c0, AST_FLAG_NBRIDGE); 07695 ast_set_flag(c1, AST_FLAG_NBRIDGE); 07696 if ((res = c0->tech->bridge(c0, c1, config->flags, fo, rc, timeoutms)) == AST_BRIDGE_COMPLETE) { 07697 ast_manager_event_multichan(EVENT_FLAG_CALL, "Unlink", 2, chans, 07698 "Channel1: %s\r\n" 07699 "Channel2: %s\r\n" 07700 "Uniqueid1: %s\r\n" 07701 "Uniqueid2: %s\r\n" 07702 "CallerID1: %s\r\n" 07703 "CallerID2: %s\r\n", 07704 c0->name, c1->name, 07705 c0->uniqueid, c1->uniqueid, 07706 S_COR(c0->caller.id.number.valid, c0->caller.id.number.str, "<unknown>"), 07707 S_COR(c1->caller.id.number.valid, c1->caller.id.number.str, "<unknown>")); 07708 07709 ast_debug(1, "Returning from native bridge, channels: %s, %s\n", c0->name, c1->name); 07710 07711 ast_clear_flag(c0, AST_FLAG_NBRIDGE); 07712 ast_clear_flag(c1, AST_FLAG_NBRIDGE); 07713 07714 if ((c0->_softhangup | c1->_softhangup) & AST_SOFTHANGUP_UNBRIDGE) {/* Bit operators are intentional. */ 07715 continue; 07716 } 07717 07718 ast_channel_lock_both(c0, c1); 07719 c0->_bridge = NULL; 07720 c1->_bridge = NULL; 07721 ast_channel_unlock(c0); 07722 ast_channel_unlock(c1); 07723 return res; 07724 } else { 07725 ast_clear_flag(c0, AST_FLAG_NBRIDGE); 07726 ast_clear_flag(c1, AST_FLAG_NBRIDGE); 07727 } 07728 switch (res) { 07729 case AST_BRIDGE_RETRY: 07730 if (config->play_warning) { 07731 ast_set_flag(config, AST_FEATURE_WARNING_ACTIVE); 07732 } 07733 continue; 07734 default: 07735 ast_verb(3, "Native bridging %s and %s ended\n", c0->name, c1->name); 07736 /* fallthrough */ 07737 case AST_BRIDGE_FAILED_NOWARN: 07738 break; 07739 } 07740 } 07741 07742 if (((c0->writeformat != c1->readformat) || (c0->readformat != c1->writeformat) || 07743 (c0->nativeformats != o0nativeformats) || (c1->nativeformats != o1nativeformats)) && 07744 !(c0->generator || c1->generator)) { 07745 if (ast_channel_make_compatible(c0, c1)) { 07746 ast_log(LOG_WARNING, "Can't make %s and %s compatible\n", c0->name, c1->name); 07747 manager_bridge_event(0, 1, c0, c1); 07748 return AST_BRIDGE_FAILED; 07749 } 07750 o0nativeformats = c0->nativeformats; 07751 o1nativeformats = c1->nativeformats; 07752 } 07753 07754 update_bridge_vars(c0, c1); 07755 07756 res = ast_generic_bridge(c0, c1, config, fo, rc); 07757 if (res != AST_BRIDGE_RETRY) { 07758 break; 07759 } else if (config->feature_timer) { 07760 /* feature timer expired but has not been updated, sending to ast_bridge_call to do so */ 07761 break; 07762 } 07763 } 07764 07765 ast_clear_flag(c0, AST_FLAG_END_DTMF_ONLY); 07766 ast_clear_flag(c1, AST_FLAG_END_DTMF_ONLY); 07767 07768 /* Now that we have broken the bridge the source will change yet again */ 07769 ast_indicate(c0, AST_CONTROL_SRCUPDATE); 07770 ast_indicate(c1, AST_CONTROL_SRCUPDATE); 07771 07772 ast_channel_lock_both(c0, c1); 07773 c0->_bridge = NULL; 07774 c1->_bridge = NULL; 07775 ast_channel_unlock(c0); 07776 ast_channel_unlock(c1); 07777 07778 ast_manager_event_multichan(EVENT_FLAG_CALL, "Unlink", 2, chans, 07779 "Channel1: %s\r\n" 07780 "Channel2: %s\r\n" 07781 "Uniqueid1: %s\r\n" 07782 "Uniqueid2: %s\r\n" 07783 "CallerID1: %s\r\n" 07784 "CallerID2: %s\r\n", 07785 c0->name, c1->name, 07786 c0->uniqueid, c1->uniqueid, 07787 S_COR(c0->caller.id.number.valid, c0->caller.id.number.str, "<unknown>"), 07788 S_COR(c1->caller.id.number.valid, c1->caller.id.number.str, "<unknown>")); 07789 ast_debug(1, "Bridge stops bridging channels %s and %s\n", c0->name, c1->name); 07790 07791 return res; 07792 }
struct ast_channel* ast_channel_callback | ( | ao2_callback_data_fn * | cb_fn, | |
void * | arg, | |||
void * | data, | |||
int | ao2_flags | |||
) | [read] |
Call a function with every active channel.
This function executes a callback one time for each active channel on the system. The channel is provided as an argument to the function.
Definition at line 1634 of file channel.c.
References ao2_callback_data, and channels.
Referenced by ast_pickup_call(), handle_core_set_debug_channel(), my_ast_get_channel_by_name_locked(), pickup_by_group(), pickup_by_mark(), pickup_by_part(), and state_notify_build_xml().
01636 { 01637 return ao2_callback_data(channels, ao2_flags, cb_fn, arg, data); 01638 }
int ast_channel_cc_params_init | ( | struct ast_channel * | chan, | |
const struct ast_cc_config_params * | base_params | |||
) |
Set up datastore with CCSS parameters for a channel.
This function makes use of datastore operations on the channel, so it is important to lock the channel before calling this function.
chan | The channel to create the datastore on | |
base_params | CCSS parameters we wish to copy into the channel |
0 | Success | |
-1 | Failure |
Definition at line 9731 of file channel.c.
References ast_cc_config_params_destroy(), ast_cc_config_params_init, ast_cc_copy_config_params(), ast_channel_datastore_add(), ast_datastore_alloc, and ast_datastore::data.
Referenced by ast_channel_get_cc_config_params(), dahdi_new(), local_call(), local_request(), and sip_new().
09733 { 09734 struct ast_cc_config_params *cc_params; 09735 struct ast_datastore *cc_datastore; 09736 09737 if (!(cc_params = ast_cc_config_params_init())) { 09738 return -1; 09739 } 09740 09741 if (!(cc_datastore = ast_datastore_alloc(&cc_channel_datastore_info, NULL))) { 09742 ast_cc_config_params_destroy(cc_params); 09743 return -1; 09744 } 09745 09746 if (base_params) { 09747 ast_cc_copy_config_params(cc_params, base_params); 09748 } 09749 cc_datastore->data = cc_params; 09750 ast_channel_datastore_add(chan, cc_datastore); 09751 return 0; 09752 }
static void ast_channel_change_linkedid | ( | struct ast_channel * | chan, | |
const char * | linkedid | |||
) | [static] |
Set the channel's linkedid to the given string, and also check to see if the channel's old linkedid is now being retired
Definition at line 6370 of file channel.c.
References ast_assert, ast_cel_check_retire_linkedid(), ast_cel_linkedid_ref(), and ast_string_field_set.
Referenced by ast_channel_set_linkgroup().
06371 { 06372 ast_assert(linkedid != NULL); 06373 /* if the linkedid for this channel is being changed from something, check... */ 06374 if (!strcmp(chan->linkedid, linkedid)) { 06375 return; 06376 } 06377 06378 ast_cel_check_retire_linkedid(chan); 06379 ast_string_field_set(chan, linkedid, linkedid); 06380 ast_cel_linkedid_ref(linkedid); 06381 }
void ast_channel_clear_softhangup | ( | struct ast_channel * | chan, | |
int | flag | |||
) |
Clear a set of softhangup flags from a channel.
Never clear a softhangup flag from a channel directly. Instead, use this function. This ensures that all aspects of the softhangup process are aborted.
chan | the channel to clear the flag on | |
flag | the flag or flags to clear |
Definition at line 2707 of file channel.c.
References ast_channel::_softhangup, ast_channel_lock, ast_channel_unlock, AST_CONTROL_END_OF_Q, AST_FRAME_CONTROL, ast_frfree, AST_LIST_LAST, AST_LIST_REMOVE, ast_frame::frametype, ast_frame_subclass::integer, and ast_frame::subclass.
Referenced by __ast_pbx_run(), ast_channel_bridge(), ast_generic_bridge(), check_goto_on_transfer(), and collect_digits().
02708 { 02709 ast_channel_lock(chan); 02710 02711 chan->_softhangup &= ~flag; 02712 02713 if (!chan->_softhangup) { 02714 struct ast_frame *fr; 02715 02716 /* If we have completely cleared the softhangup flag, 02717 * then we need to fully abort the hangup process. This requires 02718 * pulling the END_OF_Q frame out of the channel frame queue if it 02719 * still happens to be there. */ 02720 02721 fr = AST_LIST_LAST(&chan->readq); 02722 if (fr && fr->frametype == AST_FRAME_CONTROL && 02723 fr->subclass.integer == AST_CONTROL_END_OF_Q) { 02724 AST_LIST_REMOVE(&chan->readq, fr, frame_list); 02725 ast_frfree(fr); 02726 } 02727 } 02728 02729 ast_channel_unlock(chan); 02730 }
static int ast_channel_cmp_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 1720 of file channel.c.
References ast_channel_lock, ast_channel_unlock, ast_strlen_zero(), CMP_MATCH, ast_channel::context, ast_channel::exten, ast_channel::macrocontext, and ast_channel::macroexten.
Referenced by ast_channels_init().
01721 { 01722 struct ast_channel *chan = obj, *cmp_args = arg; 01723 size_t name_len; 01724 int ret = CMP_MATCH; 01725 01726 /* This is sort of a hack. Basically, we're using an arbitrary field 01727 * in ast_channel to pass the name_len for a prefix match. If this 01728 * gets changed, then the uses of ao2_find() must be changed, too. */ 01729 name_len = cmp_args->rings; 01730 01731 ast_channel_lock(chan); 01732 01733 if (!ast_strlen_zero(cmp_args->name)) { /* match by name */ 01734 if ((!name_len && strcasecmp(chan->name, cmp_args->name)) || 01735 (name_len && strncasecmp(chan->name, cmp_args->name, name_len))) { 01736 ret = 0; /* name match failed */ 01737 } 01738 } else if (!ast_strlen_zero(cmp_args->exten)) { 01739 if (cmp_args->context && strcasecmp(chan->context, cmp_args->context) && 01740 strcasecmp(chan->macrocontext, cmp_args->context)) { 01741 ret = 0; /* context match failed */ 01742 } 01743 if (ret && strcasecmp(chan->exten, cmp_args->exten) && 01744 strcasecmp(chan->macroexten, cmp_args->exten)) { 01745 ret = 0; /* exten match failed */ 01746 } 01747 } else if (!ast_strlen_zero(cmp_args->uniqueid)) { 01748 if ((!name_len && strcasecmp(chan->uniqueid, cmp_args->uniqueid)) || 01749 (name_len && strncasecmp(chan->uniqueid, cmp_args->uniqueid, name_len))) { 01750 ret = 0; /* uniqueid match failed */ 01751 } 01752 } else { 01753 ret = 0; 01754 } 01755 01756 ast_channel_unlock(chan); 01757 01758 return ret; 01759 }
int ast_channel_cmpwhentohangup | ( | struct ast_channel * | chan, | |
time_t | offset | |||
) |
Compare a offset with the settings of when to hang a channel up.
chan | channel on which to check for hang up | |
offset | offset in seconds from current time |
This function compares a offset from current time with the absolute time out on a channel (when to hang up). If the absolute time out on a channel is earlier than current time plus the offset, it returns 1, if the two time values are equal, it return 0, otherwise, it return -1.
Definition at line 900 of file channel.c.
References ast_channel_cmpwhentohangup_tv().
00901 { 00902 struct timeval when = { offset, }; 00903 return ast_channel_cmpwhentohangup_tv(chan, when); 00904 }
int ast_channel_cmpwhentohangup_tv | ( | struct ast_channel * | chan, | |
struct timeval | offset | |||
) |
Compare a offset with when to hangup channel.
Compare a offset with the settings of when to hang a channel up.
Definition at line 885 of file channel.c.
References ast_tvadd(), ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), and ast_channel::whentohangup.
Referenced by ast_channel_cmpwhentohangup().
00886 { 00887 struct timeval whentohangup; 00888 00889 if (ast_tvzero(chan->whentohangup)) 00890 return ast_tvzero(offset) ? 0 : -1; 00891 00892 if (ast_tvzero(offset)) 00893 return 1; 00894 00895 whentohangup = ast_tvadd(offset, ast_tvnow()); 00896 00897 return ast_tvdiff_ms(whentohangup, chan->whentohangup); 00898 }
int ast_channel_connected_line_macro | ( | struct ast_channel * | autoservice_chan, | |
struct ast_channel * | macro_chan, | |||
const void * | connected_info, | |||
int | caller, | |||
int | frame | |||
) |
Run a connected line interception macro and update a channel's connected line information.
autoservice_chan | Channel to place into autoservice while the macro is running. It is perfectly safe for this to be NULL | |
macro_chan | The channel to run the macro on. Also the channel from which we determine which macro we need to run. | |
connected_info | Either an ast_party_connected_line or ast_frame pointer of type AST_CONTROL_CONNECTED_LINE | |
caller | If true, then run CONNECTED_LINE_CALLER_SEND_MACRO, otherwise run CONNECTED_LINE_CALLEE_SEND_MACRO | |
frame | If true, then connected_info is an ast_frame pointer, otherwise it is an ast_party_connected_line pointer. |
0 | Success | |
-1 | Either the macro does not exist, or there was an error while attempting to run the macro |
Have multiple return codes based on the MACRO_RESULT
Make constants so that caller and frame can be more expressive than just '1' and '0'
Definition at line 9618 of file channel.c.
References ast_app_run_macro(), ast_channel_lock, ast_channel_unlock, ast_channel_update_connected_line(), ast_connected_line_parse_data(), ast_party_connected_line_copy(), ast_party_connected_line_free(), ast_party_connected_line_init(), ast_strdupa, ast_strlen_zero(), chanlist::connected, ast_channel::connected, ast_frame::data, ast_frame::datalen, pbx_builtin_getvar_helper(), ast_frame::ptr, and S_OR.
Referenced by __ast_read(), app_exec(), ast_bridge_call(), ast_do_pickup(), ast_generic_bridge(), atxfer_fail_cleanup(), builtin_atxfer(), feature_request_and_dial(), handle_frame(), local_bridge_loop(), parked_call_exec(), remote_bridge_loop(), and wait_for_answer().
09619 { 09620 const char *macro; 09621 const char *macro_args; 09622 int retval; 09623 09624 ast_channel_lock(macro_chan); 09625 macro = pbx_builtin_getvar_helper(macro_chan, is_caller 09626 ? "CONNECTED_LINE_CALLER_SEND_MACRO" : "CONNECTED_LINE_CALLEE_SEND_MACRO"); 09627 macro = ast_strdupa(S_OR(macro, "")); 09628 macro_args = pbx_builtin_getvar_helper(macro_chan, is_caller 09629 ? "CONNECTED_LINE_CALLER_SEND_MACRO_ARGS" : "CONNECTED_LINE_CALLEE_SEND_MACRO_ARGS"); 09630 macro_args = ast_strdupa(S_OR(macro_args, "")); 09631 09632 if (ast_strlen_zero(macro)) { 09633 ast_channel_unlock(macro_chan); 09634 return -1; 09635 } 09636 09637 if (is_frame) { 09638 const struct ast_frame *frame = connected_info; 09639 09640 ast_connected_line_parse_data(frame->data.ptr, frame->datalen, ¯o_chan->connected); 09641 } else { 09642 const struct ast_party_connected_line *connected = connected_info; 09643 09644 ast_party_connected_line_copy(¯o_chan->connected, connected); 09645 } 09646 ast_channel_unlock(macro_chan); 09647 09648 retval = ast_app_run_macro(autoservice_chan, macro_chan, macro, macro_args); 09649 if (!retval) { 09650 struct ast_party_connected_line saved_connected; 09651 09652 ast_party_connected_line_init(&saved_connected); 09653 ast_channel_lock(macro_chan); 09654 ast_party_connected_line_copy(&saved_connected, ¯o_chan->connected); 09655 ast_channel_unlock(macro_chan); 09656 ast_channel_update_connected_line(macro_chan, &saved_connected, NULL); 09657 ast_party_connected_line_free(&saved_connected); 09658 } 09659 09660 return retval; 09661 }
int ast_channel_data_add_structure | ( | struct ast_data * | tree, | |
struct ast_channel * | chan, | |||
int | add_bridged | |||
) |
Insert into an astdata tree, the channel structure.
[in] | tree | The ast data tree. |
[in] | chan | The channel structure to add to tree. |
[in] | add_bridged | Add the bridged channel to the structure. |
<0 | on error. | |
0 | on success. |
Definition at line 357 of file channel.c.
References ast_channel::_softhangup, ast_channel::_state, ast_channel::amaflags, ast_bridged_channel(), ast_cause2str(), ast_cdr_data_add_structure(), ast_cdr_flags2str(), ast_channel_data_add_structure(), ast_data_add_bool(), ast_data_add_codecs(), ast_data_add_int(), ast_data_add_node(), ast_data_add_str(), ast_data_add_structure, ast_data_add_uint(), AST_SOFTHANGUP_APPUNLOAD, AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_DEV, AST_SOFTHANGUP_EXPLICIT, AST_SOFTHANGUP_SHUTDOWN, AST_SOFTHANGUP_TIMEOUT, AST_SOFTHANGUP_UNBRIDGE, ast_state2str(), ast_tone_zone_data_add_structure(), ast_transfercapability2str(), ast_channel::cdr, channel_data_add_flags(), ast_channel::hangupcause, ast_channel::nativeformats, ast_channel::oldwriteformat, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::transfercapability, ast_channel::whentohangup, ast_channel::writeformat, and ast_channel::zone.
Referenced by agents_data_provider_get(), ast_channel_data_add_structure(), data_channels_provider_handler(), queues_data_provider_get_helper(), and user_add_provider_cb().
00359 { 00360 struct ast_channel *bc; 00361 struct ast_data *data_bridged; 00362 struct ast_data *data_cdr; 00363 struct ast_data *data_flags; 00364 struct ast_data *data_zones; 00365 struct ast_data *enum_node; 00366 struct ast_data *data_softhangup; 00367 #if 0 /* XXX AstData: ast_callerid no longer exists. (Equivalent code not readily apparent.) */ 00368 struct ast_data *data_callerid; 00369 char value_str[100]; 00370 #endif 00371 00372 if (!tree) { 00373 return -1; 00374 } 00375 00376 ast_data_add_structure(ast_channel, tree, chan); 00377 00378 if (add_bridged) { 00379 bc = ast_bridged_channel(chan); 00380 if (bc) { 00381 data_bridged = ast_data_add_node(tree, "bridged"); 00382 if (!data_bridged) { 00383 return -1; 00384 } 00385 ast_channel_data_add_structure(data_bridged, bc, 0); 00386 } 00387 } 00388 00389 ast_data_add_codecs(tree, "oldwriteformat", chan->oldwriteformat); 00390 ast_data_add_codecs(tree, "nativeformats", chan->nativeformats); 00391 ast_data_add_codecs(tree, "readformat", chan->readformat); 00392 ast_data_add_codecs(tree, "writeformat", chan->writeformat); 00393 ast_data_add_codecs(tree, "rawreadformat", chan->rawreadformat); 00394 ast_data_add_codecs(tree, "rawwriteformat", chan->rawwriteformat); 00395 00396 /* state */ 00397 enum_node = ast_data_add_node(tree, "state"); 00398 if (!enum_node) { 00399 return -1; 00400 } 00401 ast_data_add_str(enum_node, "text", ast_state2str(chan->_state)); 00402 ast_data_add_int(enum_node, "value", chan->_state); 00403 00404 /* hangupcause */ 00405 enum_node = ast_data_add_node(tree, "hangupcause"); 00406 if (!enum_node) { 00407 return -1; 00408 } 00409 ast_data_add_str(enum_node, "text", ast_cause2str(chan->hangupcause)); 00410 ast_data_add_int(enum_node, "value", chan->hangupcause); 00411 00412 /* amaflags */ 00413 enum_node = ast_data_add_node(tree, "amaflags"); 00414 if (!enum_node) { 00415 return -1; 00416 } 00417 ast_data_add_str(enum_node, "text", ast_cdr_flags2str(chan->amaflags)); 00418 ast_data_add_int(enum_node, "value", chan->amaflags); 00419 00420 /* transfercapability */ 00421 enum_node = ast_data_add_node(tree, "transfercapability"); 00422 if (!enum_node) { 00423 return -1; 00424 } 00425 ast_data_add_str(enum_node, "text", ast_transfercapability2str(chan->transfercapability)); 00426 ast_data_add_int(enum_node, "value", chan->transfercapability); 00427 00428 /* _softphangup */ 00429 data_softhangup = ast_data_add_node(tree, "softhangup"); 00430 if (!data_softhangup) { 00431 return -1; 00432 } 00433 ast_data_add_bool(data_softhangup, "dev", chan->_softhangup & AST_SOFTHANGUP_DEV); 00434 ast_data_add_bool(data_softhangup, "asyncgoto", chan->_softhangup & AST_SOFTHANGUP_ASYNCGOTO); 00435 ast_data_add_bool(data_softhangup, "shutdown", chan->_softhangup & AST_SOFTHANGUP_SHUTDOWN); 00436 ast_data_add_bool(data_softhangup, "timeout", chan->_softhangup & AST_SOFTHANGUP_TIMEOUT); 00437 ast_data_add_bool(data_softhangup, "appunload", chan->_softhangup & AST_SOFTHANGUP_APPUNLOAD); 00438 ast_data_add_bool(data_softhangup, "explicit", chan->_softhangup & AST_SOFTHANGUP_EXPLICIT); 00439 ast_data_add_bool(data_softhangup, "unbridge", chan->_softhangup & AST_SOFTHANGUP_UNBRIDGE); 00440 00441 /* channel flags */ 00442 data_flags = ast_data_add_node(tree, "flags"); 00443 if (!data_flags) { 00444 return -1; 00445 } 00446 channel_data_add_flags(data_flags, chan); 00447 00448 ast_data_add_uint(tree, "timetohangup", chan->whentohangup.tv_sec); 00449 00450 #if 0 /* XXX AstData: ast_callerid no longer exists. (Equivalent code not readily apparent.) */ 00451 /* callerid */ 00452 data_callerid = ast_data_add_node(tree, "callerid"); 00453 if (!data_callerid) { 00454 return -1; 00455 } 00456 ast_data_add_structure(ast_callerid, data_callerid, &(chan->cid)); 00457 /* insert the callerid ton */ 00458 enum_node = ast_data_add_node(data_callerid, "cid_ton"); 00459 if (!enum_node) { 00460 return -1; 00461 } 00462 ast_data_add_int(enum_node, "value", chan->cid.cid_ton); 00463 snprintf(value_str, sizeof(value_str), "TON: %s/Plan: %s", 00464 party_number_ton2str(chan->cid.cid_ton), 00465 party_number_plan2str(chan->cid.cid_ton)); 00466 ast_data_add_str(enum_node, "text", value_str); 00467 #endif 00468 00469 /* tone zone */ 00470 if (chan->zone) { 00471 data_zones = ast_data_add_node(tree, "zone"); 00472 if (!data_zones) { 00473 return -1; 00474 } 00475 ast_tone_zone_data_add_structure(data_zones, chan->zone); 00476 } 00477 00478 /* insert cdr */ 00479 data_cdr = ast_data_add_node(tree, "cdr"); 00480 if (!data_cdr) { 00481 return -1; 00482 } 00483 00484 ast_cdr_data_add_structure(data_cdr, chan->cdr, 1); 00485 00486 return 0; 00487 }
int ast_channel_data_cmp_structure | ( | const struct ast_data_search * | tree, | |
struct ast_channel * | chan, | |||
const char * | structure_name | |||
) |
Compare to channel structures using the data api.
[in] | tree | The search tree generated by the data api. |
[in] | chan | The channel to compare. |
[in] | structure_name | The name of the node of the channel structure. |
0 | The structure matches. | |
1 | The structure doesn't matches. |
Definition at line 489 of file channel.c.
References ast_data_search_cmp_structure.
00491 { 00492 return ast_data_search_cmp_structure(tree, ast_channel, chan, structure_name); 00493 }
int ast_channel_datastore_add | ( | struct ast_channel * | chan, | |
struct ast_datastore * | datastore | |||
) |
Add a datastore to a channel.
0 | success | |
non-zero | failure |
Definition at line 2590 of file channel.c.
References AST_LIST_INSERT_HEAD.
Referenced by __ast_channel_masquerade(), _macro_exec(), acf_curlopt_write(), acf_iaxvar_write(), acf_odbc_read(), add_features_datastore(), add_to_agi(), apply_plc(), ast_cel_fabricate_channel_from_event(), ast_channel_cc_params_init(), ast_do_pickup(), ast_iax2_new(), ast_setup_cc_recall_datastore(), audiohook_volume_get(), authenticate_reply(), calendar_query_exec(), cc_interfaces_datastore_init(), dial_exec_full(), do_notify(), dundi_query_read(), enable_jack_hook(), enum_query_read(), find_or_create_details(), find_transaction(), frame_trace_helper(), func_channel_write_real(), get_lock(), gosub_exec(), lua_get_state(), mute_add_audiohook(), pitchshift_helper(), raise_exception(), set_chan_app_data(), setup_inheritance_datastore(), setup_mixmonitor_ds(), setup_transfer_datastore(), shared_write(), smdi_msg_retrieve_read(), socket_process(), speech_create(), speex_write(), srv_datastore_setup(), try_calling(), and volume_write().
02591 { 02592 int res = 0; 02593 02594 AST_LIST_INSERT_HEAD(&chan->datastores, datastore, entry); 02595 02596 return res; 02597 }
struct ast_datastore* ast_channel_datastore_alloc | ( | const struct ast_datastore_info * | info, | |
const char * | uid | |||
) | [read] |
Create a channel data store object.
Definition at line 2563 of file channel.c.
References ast_datastore_alloc.
02564 { 02565 return ast_datastore_alloc(info, uid); 02566 }
struct ast_datastore* ast_channel_datastore_find | ( | struct ast_channel * | chan, | |
const struct ast_datastore_info * | info, | |||
const char * | uid | |||
) | [read] |
Find a datastore on a channel.
pointer | to the datastore if found | |
NULL | if not found |
Definition at line 2604 of file channel.c.
References AST_LIST_TRAVERSE, ast_datastore::info, and ast_datastore::uid.
Referenced by _macro_exec(), acf_curl_helper(), acf_curlopt_helper(), acf_curlopt_write(), acf_exception_read(), acf_fetch(), acf_iaxvar_read(), acf_iaxvar_write(), acf_odbc_read(), add_agi_cmd(), add_features_datastore(), add_to_agi(), apply_plc(), ast_can_pickup(), ast_cc_agent_set_interfaces_chanvar(), ast_cc_call_init(), ast_cc_completed(), ast_cc_extension_monitor_add_dialstring(), ast_cc_get_current_core_id(), ast_cc_is_recall(), ast_cc_offer(), ast_channel_get_cc_config_params(), ast_do_masquerade(), ast_handle_cc_control_frame(), ast_ignore_cc(), ast_odbc_retrieve_transaction_obj(), ast_set_cc_interfaces_chanvar(), attended_transfer_occurred(), audiohook_volume_callback(), audiohook_volume_get(), balance_stack(), builtin_atxfer(), calendar_event_read(), calendar_query_exec(), calendar_query_result_exec(), cc_build_payload(), clear_dialed_interfaces(), dial_exec_full(), disable_jack_hook(), dundi_result_read(), enable_jack_hook(), enum_result_read(), exec_odbcfinish(), find_details(), find_speech(), find_transaction(), frame_trace_helper(), func_channel_read(), func_channel_write_real(), func_inheritance_write(), func_mute_write(), get_agi_cmd(), get_lock(), gosub_exec(), gosub_run(), handle_gosub(), iax2_call(), jack_hook_callback(), local_read(), local_write(), lock_fixup(), lua_get_state(), manage_parked_call(), manager_mutestream(), mark_transaction_active(), mute_callback(), parked_call_exec(), pitchshift_cb(), pitchshift_helper(), pop_exec(), queue_transfer_fixup(), raise_exception(), release_transaction(), return_exec(), set_security_requirements(), shared_read(), shared_write(), smdi_msg_read(), speech_datastore_destroy(), speex_callback(), speex_read(), speex_write(), srv_query_read(), srv_result_read(), stackpeek_read(), stop_mixmonitor_exec(), try_calling(), unlock_read(), volume_callback(), and volume_write().
02605 { 02606 struct ast_datastore *datastore = NULL; 02607 02608 if (info == NULL) 02609 return NULL; 02610 02611 AST_LIST_TRAVERSE(&chan->datastores, datastore, entry) { 02612 if (datastore->info != info) { 02613 continue; 02614 } 02615 02616 if (uid == NULL) { 02617 /* matched by type only */ 02618 break; 02619 } 02620 02621 if ((datastore->uid != NULL) && !strcasecmp(uid, datastore->uid)) { 02622 /* Matched by type AND uid */ 02623 break; 02624 } 02625 } 02626 02627 return datastore; 02628 }
int ast_channel_datastore_free | ( | struct ast_datastore * | datastore | ) |
Free a channel data store object.
Definition at line 2568 of file channel.c.
References ast_datastore_free().
02569 { 02570 return ast_datastore_free(datastore); 02571 }
int ast_channel_datastore_inherit | ( | struct ast_channel * | from, | |
struct ast_channel * | to | |||
) |
Inherit datastores from a parent to a child.
Definition at line 2573 of file channel.c.
References ast_datastore_alloc, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_datastore::data, DATASTORE_INHERIT_FOREVER, ast_datastore_info::duplicate, ast_datastore::info, ast_datastore::inheritance, and ast_datastore::uid.
Referenced by __ast_request_and_dial(), begin_dial_channel(), call_forward_inherit(), dial_exec_full(), dial_transfer(), do_forward(), findmeexec(), local_call(), ring_entry(), and wait_for_answer().
02574 { 02575 struct ast_datastore *datastore = NULL, *datastore2; 02576 02577 AST_LIST_TRAVERSE(&from->datastores, datastore, entry) { 02578 if (datastore->inheritance > 0) { 02579 datastore2 = ast_datastore_alloc(datastore->info, datastore->uid); 02580 if (datastore2) { 02581 datastore2->data = datastore->info->duplicate ? datastore->info->duplicate(datastore->data) : NULL; 02582 datastore2->inheritance = datastore->inheritance == DATASTORE_INHERIT_FOREVER ? DATASTORE_INHERIT_FOREVER : datastore->inheritance - 1; 02583 AST_LIST_INSERT_TAIL(&to->datastores, datastore2, entry); 02584 } 02585 } 02586 } 02587 return 0; 02588 }
int ast_channel_datastore_remove | ( | struct ast_channel * | chan, | |
struct ast_datastore * | datastore | |||
) |
Remove a datastore from a channel.
0 | success | |
non-zero | failure |
Definition at line 2599 of file channel.c.
References AST_LIST_REMOVE.
Referenced by acf_fetch(), acf_odbc_read(), adjust_frame_for_plc(), ast_do_masquerade(), ast_do_pickup(), clear_dialed_interfaces(), dial_exec_full(), disable_jack_hook(), exec_odbcfinish(), frame_trace_helper(), lua_get_state(), queue_transfer_fixup(), speech_datastore_destroy(), speex_write(), srv_query_read(), stop_mixmonitor_exec(), and try_calling().
02600 { 02601 return AST_LIST_REMOVE(&chan->datastores, datastore, entry) ? 0 : -1; 02602 }
int ast_channel_defer_dtmf | ( | struct ast_channel * | chan | ) |
Set defer DTMF flag on channel.
Defers DTMF so that you only read things like hangups and audio.
Definition at line 1616 of file channel.c.
References AST_FLAG_DEFER_DTMF, ast_set_flag, and ast_test_flag.
Referenced by __adsi_transmit_messages(), and find_cache().
01617 { 01618 int pre = 0; 01619 01620 if (chan) { 01621 pre = ast_test_flag(chan, AST_FLAG_DEFER_DTMF); 01622 ast_set_flag(chan, AST_FLAG_DEFER_DTMF); 01623 } 01624 return pre; 01625 }
static void ast_channel_destructor | ( | void * | obj | ) | [static] |
Free a channel structure.
Definition at line 2403 of file channel.c.
References ast_channel::alertpipe, ast_app_group_discard(), ast_atomic_fetchadd_int(), ast_cdr_discard(), AST_CEL_CHANNEL_END, ast_cel_check_retire_linkedid(), ast_cel_report_event(), ast_channel_lock, AST_CHANNEL_NAME, ast_channel_unlock, ast_copy_string(), ast_datastore_free(), AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, ast_devstate_changed_literal(), AST_DEVSTATE_NOT_CACHABLE, AST_FLAG_DISABLE_DEVSTATE_CACHE, ast_free, ast_frfree, ast_jb_destroy(), AST_LIST_REMOVE_HEAD, ast_log(), AST_MAX_FDS, ast_moh_cleanup(), ast_party_caller_free(), ast_party_connected_line_free(), ast_party_dialed_free(), ast_party_redirecting_free(), ast_string_field_free_memory, ast_timer_close(), ast_tone_zone_unref(), ast_translator_free_path(), ast_var_delete(), ast_channel::caller, ast_channel::cdr, ast_channel::connected, ast_channel::dialed, ast_channel::flags, free, LOG_WARNING, ast_channel::monitor, ast_channel::music_state, ast_channel::pbx, ast_channel::readtrans, ast_channel::redirecting, ast_channel::sched, sched_context_destroy(), ast_channel_monitor::stop, ast_channel::tech_pvt, ast_channel::timer, ast_channel::varshead, ast_channel::writetrans, and ast_channel::zone.
Referenced by __ast_channel_alloc_ap().
02404 { 02405 struct ast_channel *chan = obj; 02406 int fd; 02407 #ifdef HAVE_EPOLL 02408 int i; 02409 #endif 02410 struct ast_var_t *vardata; 02411 struct ast_frame *f; 02412 struct varshead *headp; 02413 struct ast_datastore *datastore; 02414 char device_name[AST_CHANNEL_NAME]; 02415 02416 if (chan->name) { 02417 /* The string fields were initialized. */ 02418 ast_cel_report_event(chan, AST_CEL_CHANNEL_END, NULL, NULL, NULL); 02419 ast_cel_check_retire_linkedid(chan); 02420 } 02421 02422 /* Get rid of each of the data stores on the channel */ 02423 ast_channel_lock(chan); 02424 while ((datastore = AST_LIST_REMOVE_HEAD(&chan->datastores, entry))) 02425 /* Free the data store */ 02426 ast_datastore_free(datastore); 02427 ast_channel_unlock(chan); 02428 02429 /* Lock and unlock the channel just to be sure nobody has it locked still 02430 due to a reference that was stored in a datastore. (i.e. app_chanspy) */ 02431 ast_channel_lock(chan); 02432 ast_channel_unlock(chan); 02433 02434 if (chan->tech_pvt) { 02435 ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n", chan->name); 02436 ast_free(chan->tech_pvt); 02437 } 02438 02439 if (chan->sched) 02440 sched_context_destroy(chan->sched); 02441 02442 if (chan->name) { 02443 char *dashptr; 02444 02445 /* The string fields were initialized. */ 02446 ast_copy_string(device_name, chan->name, sizeof(device_name)); 02447 if ((dashptr = strrchr(device_name, '-'))) { 02448 *dashptr = '\0'; 02449 } 02450 } else { 02451 device_name[0] = '\0'; 02452 } 02453 02454 /* Stop monitoring */ 02455 if (chan->monitor) 02456 chan->monitor->stop( chan, 0 ); 02457 02458 /* If there is native format music-on-hold state, free it */ 02459 if (chan->music_state) 02460 ast_moh_cleanup(chan); 02461 02462 /* Free translators */ 02463 if (chan->readtrans) 02464 ast_translator_free_path(chan->readtrans); 02465 if (chan->writetrans) 02466 ast_translator_free_path(chan->writetrans); 02467 if (chan->pbx) 02468 ast_log(LOG_WARNING, "PBX may not have been terminated properly on '%s'\n", chan->name); 02469 02470 ast_party_dialed_free(&chan->dialed); 02471 ast_party_caller_free(&chan->caller); 02472 ast_party_connected_line_free(&chan->connected); 02473 ast_party_redirecting_free(&chan->redirecting); 02474 02475 /* Close pipes if appropriate */ 02476 if ((fd = chan->alertpipe[0]) > -1) 02477 close(fd); 02478 if ((fd = chan->alertpipe[1]) > -1) 02479 close(fd); 02480 if (chan->timer) { 02481 ast_timer_close(chan->timer); 02482 chan->timer = NULL; 02483 } 02484 #ifdef HAVE_EPOLL 02485 for (i = 0; i < AST_MAX_FDS; i++) { 02486 if (chan->epfd_data[i]) 02487 free(chan->epfd_data[i]); 02488 } 02489 close(chan->epfd); 02490 #endif 02491 while ((f = AST_LIST_REMOVE_HEAD(&chan->readq, frame_list))) 02492 ast_frfree(f); 02493 02494 /* loop over the variables list, freeing all data and deleting list items */ 02495 /* no need to lock the list, as the channel is already locked */ 02496 headp = &chan->varshead; 02497 while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries))) 02498 ast_var_delete(vardata); 02499 02500 ast_app_group_discard(chan); 02501 02502 /* Destroy the jitterbuffer */ 02503 ast_jb_destroy(chan); 02504 02505 if (chan->cdr) { 02506 ast_cdr_discard(chan->cdr); 02507 chan->cdr = NULL; 02508 } 02509 02510 if (chan->zone) { 02511 chan->zone = ast_tone_zone_unref(chan->zone); 02512 } 02513 02514 ast_string_field_free_memory(chan); 02515 02516 if (device_name[0]) { 02517 /* 02518 * We have a device name to notify of a new state. 02519 * 02520 * Queue an unknown state, because, while we know that this particular 02521 * instance is dead, we don't know the state of all other possible 02522 * instances. 02523 */ 02524 ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, (chan->flags & AST_FLAG_DISABLE_DEVSTATE_CACHE ? AST_DEVSTATE_NOT_CACHABLE : AST_DEVSTATE_CACHABLE), device_name); 02525 } 02526 ast_atomic_fetchadd_int(&chancount, -1); 02527 }
int ast_channel_early_bridge | ( | struct ast_channel * | c0, | |
struct ast_channel * | c1 | |||
) |
Bridge two channels together (early).
c0 | first channel to bridge | |
c1 | second channel to bridge |
Bridge two channels (c0 and c1) together early. This implies either side may not be answered yet.
Definition at line 7406 of file channel.c.
References ast_channel_tech::early_bridge, and ast_channel::tech.
Referenced by dial_exec_full(), and wait_for_answer().
07407 { 07408 /* Make sure we can early bridge, if not error out */ 07409 if (!c0->tech->early_bridge || (c1 && (!c1->tech->early_bridge || c0->tech->early_bridge != c1->tech->early_bridge))) 07410 return -1; 07411 07412 return c0->tech->early_bridge(c0, c1); 07413 }
struct ast_channel* ast_channel_get_by_exten | ( | const char * | exten, | |
const char * | context | |||
) | [read] |
Find a channel by extension and context.
Return a channel that is currently at the specified extension and context.
a | channel that is at the specified extension and context | |
NULL | if no channel was found |
Definition at line 1813 of file channel.c.
References ast_channel_get_full().
01814 { 01815 return ast_channel_get_full(NULL, 0, exten, context); 01816 }
struct ast_channel* ast_channel_get_by_name | ( | const char * | name | ) | [read] |
Find a channel by name.
Channel search functions
Find a channel that has the same name as the provided argument.
a | channel with the name specified by the argument | |
NULL | if no channel was found |
Definition at line 1803 of file channel.c.
References ast_channel_get_full().
Referenced by action_add_agi_cmd(), action_aocmessage(), action_atxfer(), action_getvar(), action_hangup(), action_redirect(), action_sendtext(), action_setvar(), action_status(), action_timeout(), ast_async_goto_by_name(), ast_bridge_call(), asyncgoto_exec(), change_monitor_action(), do_pause_or_unpause(), func_mchan_read(), func_mchan_write(), handle_channelstatus(), handle_cli_agi_add_cmd(), handle_core_set_debug_channel(), handle_getvariablefull(), handle_hangup(), handle_redirect(), handle_set_chanvar(), handle_show_chanvar(), handle_showchan(), handle_softhangup(), import_helper(), manager_mute_mixmonitor(), manager_mutestream(), manager_optimize_away(), manager_park(), manager_play_dtmf(), park_call_full(), pbx_builtin_importvar(), senddtmf_exec(), shared_read(), shared_write(), start_monitor_action(), and stop_monitor_action().
01804 { 01805 return ast_channel_get_full(name, 0, NULL, NULL); 01806 }
struct ast_channel* ast_channel_get_by_name_prefix | ( | const char * | name, | |
size_t | name_len | |||
) | [read] |
Find a channel by a name prefix.
Find a channel that has the same name prefix as specified by the arguments.
a | channel with the name prefix specified by the arguments | |
NULL | if no channel was found |
Definition at line 1808 of file channel.c.
References ast_channel_get_full().
Referenced by action_aocmessage(), action_bridge(), ast_parse_device_state(), bridge_exec(), cc_generic_agent_stop_ringing(), common_exec(), handle_cli_mixmonitor(), shared_read(), and shared_write().
01809 { 01810 return ast_channel_get_full(name, name_len, NULL, NULL); 01811 }
int ast_channel_get_cc_agent_type | ( | struct ast_channel * | chan, | |
char * | agent_type, | |||
size_t | size | |||
) |
Find the appropriate CC agent type to use given a channel.
During call completion, we will need to create a call completion agent structure. To figure out the type of agent to construct, we need to ask the channel driver for the appropriate type.
Prior to adding this function, the call completion core attempted to figure this out for itself by stripping the technology off the channel's name. However, in the case of chan_dahdi, there are multiple agent types registered, and so simply searching for an agent type called "DAHDI" is not possible. In a case where multiple agent types are defined, the channel driver must have a queryoption callback defined in its channel_tech, and the queryoption callback must handle AST_OPTION_CC_AGENT_TYPE
If a channel driver does not have a queryoption callback or if the queryoption callback does not handle AST_OPTION_CC_AGENT_TYPE, then the old behavior of using the technology portion of the channel name is used instead. This is perfectly suitable for channel drivers whose channel technologies are a one-to-one match with the agent types defined within.
Note that this function is only called when the agent policy on a given channel is set to "native." Generic agents' type can be determined automatically by the core.
chan | The channel for which we wish to retrieve the agent type | |
[out] | agent_type | The type of agent the channel driver wants us to use |
size | The size of the buffer to write to |
Definition at line 9793 of file channel.c.
References ast_channel_queryoption(), ast_copy_string(), and AST_OPTION_CC_AGENT_TYPE.
Referenced by find_agent_callbacks().
09794 { 09795 int len = size; 09796 char *slash; 09797 09798 if (!ast_channel_queryoption(chan, AST_OPTION_CC_AGENT_TYPE, agent_type, &len, 0)) { 09799 return 0; 09800 } 09801 09802 ast_copy_string(agent_type, chan->name, size); 09803 if ((slash = strchr(agent_type, '/'))) { 09804 *slash = '\0'; 09805 } 09806 return 0; 09807 }
struct ast_cc_config_params* ast_channel_get_cc_config_params | ( | struct ast_channel * | chan | ) | [read] |
Get the CCSS parameters from a channel.
This function makes use of datastore operations on the channel, so it is important to lock the channel before calling this function.
chan | Channel to retrieve parameters from |
NULL | Failure | |
non-NULL | The parameters desired |
Definition at line 9754 of file channel.c.
References ast_assert, ast_channel_cc_params_init(), ast_channel_datastore_find(), and ast_datastore::data.
Referenced by acf_cc_read(), acf_cc_write(), analog_call(), ast_cc_call_failed(), ast_cc_call_init(), ast_queue_cc_frame(), cc_agent_init(), cc_core_init_instance(), find_agent_callbacks(), local_call(), and local_request().
09755 { 09756 struct ast_datastore *cc_datastore; 09757 09758 if (!(cc_datastore = ast_channel_datastore_find(chan, &cc_channel_datastore_info, NULL))) { 09759 /* If we can't find the datastore, it almost definitely means that the channel type being 09760 * used has not had its driver modified to parse CC config parameters. The best action 09761 * to take here is to create the parameters on the spot with the defaults set. 09762 */ 09763 if (ast_channel_cc_params_init(chan, NULL)) { 09764 return NULL; 09765 } 09766 if (!(cc_datastore = ast_channel_datastore_find(chan, &cc_channel_datastore_info, NULL))) { 09767 /* Should be impossible */ 09768 return NULL; 09769 } 09770 } 09771 09772 ast_assert(cc_datastore->data != NULL); 09773 return cc_datastore->data; 09774 }
int ast_channel_get_device_name | ( | struct ast_channel * | chan, | |
char * | device_name, | |||
size_t | name_buffer_length | |||
) |
Get a device name given its channel structure.
A common practice in Asterisk is to determine the device being talked to by dissecting the channel name. For certain channel types, this is not accurate. For instance, an ISDN channel is named based on what B channel is used, not the device being communicated with.
This function interfaces with a channel tech's queryoption callback to retrieve the name of the device being communicated with. If the channel does not implement this specific option, then the traditional method of using the channel name is used instead.
chan | The channel to retrieve the information from | |
[out] | device_name | The buffer to place the device's name into |
name_buffer_length | The allocated space for the device_name |
Definition at line 9776 of file channel.c.
References ast_channel_queryoption(), ast_copy_string(), and AST_OPTION_DEVICE_NAME.
Referenced by ast_cc_call_failed(), ast_cc_is_recall(), ast_queue_cc_frame(), cc_core_init_instance(), cccancel_exec(), ccreq_exec(), dial_exec_full(), sip_call(), and sip_handle_cc().
09777 { 09778 int len = name_buffer_length; 09779 char *dash; 09780 if (!ast_channel_queryoption(chan, AST_OPTION_DEVICE_NAME, device_name, &len, 0)) { 09781 return 0; 09782 } 09783 09784 /* Dang. Do it the old-fashioned way */ 09785 ast_copy_string(device_name, chan->name, name_buffer_length); 09786 if ((dash = strrchr(device_name, '-'))) { 09787 *dash = '\0'; 09788 } 09789 09790 return 0; 09791 }
static struct ast_channel* ast_channel_get_full | ( | const char * | name, | |
size_t | name_len, | |||
const char * | exten, | |||
const char * | context | |||
) | [static, read] |
Definition at line 1761 of file channel.c.
References ao2_find, ast_copy_string(), ast_strlen_zero(), channels, ast_channel::context, ast_channel::exten, OBJ_POINTER, and ast_channel::rings.
Referenced by ast_channel_get_by_exten(), ast_channel_get_by_name(), and ast_channel_get_by_name_prefix().
01763 { 01764 struct ast_channel tmp_chan = { 01765 .name = name, 01766 /* This is sort of a hack. Basically, we're using an arbitrary field 01767 * in ast_channel to pass the name_len for a prefix match. If this 01768 * gets changed, then the compare callback must be changed, too. */ 01769 .rings = name_len, 01770 }; 01771 struct ast_channel *chan; 01772 01773 if (exten) { 01774 ast_copy_string(tmp_chan.exten, exten, sizeof(tmp_chan.exten)); 01775 } 01776 01777 if (context) { 01778 ast_copy_string(tmp_chan.context, context, sizeof(tmp_chan.context)); 01779 } 01780 01781 if ((chan = ao2_find(channels, &tmp_chan, 01782 (!ast_strlen_zero(name) && (name_len == 0)) ? OBJ_POINTER : 0))) { 01783 return chan; 01784 } 01785 01786 if (!name) { 01787 return NULL; 01788 } 01789 01790 /* If name was specified, but the result was NULL, 01791 * try a search on uniqueid, instead. */ 01792 01793 { 01794 struct ast_channel tmp_chan2 = { 01795 .uniqueid = name, 01796 .rings = name_len, 01797 }; 01798 01799 return ao2_find(channels, &tmp_chan2, 0); 01800 } 01801 }
static int ast_channel_hash_cb | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 8063 of file channel.c.
References ast_str_case_hash(), and ast_strlen_zero().
Referenced by ast_channels_init().
08064 { 08065 const struct ast_channel *chan = obj; 08066 08067 /* If the name isn't set, return 0 so that the ao2_find() search will 08068 * start in the first bucket. */ 08069 if (ast_strlen_zero(chan->name)) { 08070 return 0; 08071 } 08072 08073 return ast_str_case_hash(chan->name); 08074 }
void ast_channel_inherit_variables | ( | const struct ast_channel * | parent, | |
struct ast_channel * | child | |||
) |
Inherits channel variable from parent to child channel.
parent | Parent channel | |
child | Child channel |
Scans all channel variables in the parent channel, looking for those that should be copied into the child channel. Variables whose names begin with a single '_' are copied into the child channel with the prefix removed. Variables whose names begin with '__' are copied into the child channel with their names unchanged.
Definition at line 6241 of file channel.c.
References ast_debug, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_var_assign(), ast_var_full_name(), ast_var_name(), ast_var_value(), and ast_channel::varshead.
Referenced by __ast_request_and_dial(), begin_dial_channel(), call_forward_inherit(), dial_exec_full(), dial_transfer(), do_forward(), feature_request_and_dial(), findmeexec(), ring_entry(), and wait_for_answer().
06242 { 06243 struct ast_var_t *current, *newvar; 06244 const char *varname; 06245 06246 AST_LIST_TRAVERSE(&parent->varshead, current, entries) { 06247 int vartype = 0; 06248 06249 varname = ast_var_full_name(current); 06250 if (!varname) 06251 continue; 06252 06253 if (varname[0] == '_') { 06254 vartype = 1; 06255 if (varname[1] == '_') 06256 vartype = 2; 06257 } 06258 06259 switch (vartype) { 06260 case 1: 06261 newvar = ast_var_assign(&varname[1], ast_var_value(current)); 06262 if (newvar) { 06263 AST_LIST_INSERT_TAIL(&child->varshead, newvar, entries); 06264 ast_debug(1, "Inheriting variable %s from %s to %s.\n", 06265 ast_var_name(newvar), parent->name, child->name); 06266 } 06267 break; 06268 case 2: 06269 newvar = ast_var_assign(varname, ast_var_value(current)); 06270 if (newvar) { 06271 AST_LIST_INSERT_TAIL(&child->varshead, newvar, entries); 06272 ast_debug(1, "Inheriting variable %s from %s to %s.\n", 06273 ast_var_name(newvar), parent->name, child->name); 06274 } 06275 break; 06276 default: 06277 break; 06278 } 06279 } 06280 }
struct ast_channel_iterator* ast_channel_iterator_all_new | ( | void | ) | [read] |
Create a new channel iterator.
After creating an iterator using this function, the ast_channel_iterator_next() function can be used to iterate through all channels that exist.
NULL | on failure | |
a | new channel iterator |
Definition at line 1701 of file channel.c.
References ast_channel_iterator::active_iterator, ao2_iterator_init(), ast_calloc, channels, and ast_channel_iterator::simple_iterator.
Referenced by action_coreshowchannels(), action_status(), ast_complete_channels(), ast_var_channel_bridge(), ast_var_channel_types_table(), ast_var_channels_table(), common_exec(), data_channels_provider_handler(), func_channels_read(), handle_chanlist(), and handle_softhangup().
01702 { 01703 struct ast_channel_iterator *i; 01704 01705 if (!(i = ast_calloc(1, sizeof(*i)))) { 01706 return NULL; 01707 } 01708 01709 i->simple_iterator = ao2_iterator_init(channels, 0); 01710 i->active_iterator = &i->simple_iterator; 01711 01712 return i; 01713 }
struct ast_channel_iterator* ast_channel_iterator_by_exten_new | ( | const char * | exten, | |
const char * | context | |||
) | [read] |
Create a new channel iterator based on extension.
After creating an iterator using this function, the ast_channel_iterator_next() function can be used to iterate through all channels that are currently in the specified context and extension.
NULL | on failure | |
a | new channel iterator based on the specified parameters |
Definition at line 1691 of file channel.c.
References channel_iterator_search().
Referenced by common_exec(), and pickup_by_exten().
01692 { 01693 return channel_iterator_search(NULL, 0, exten, context); 01694 }
struct ast_channel_iterator* ast_channel_iterator_by_name_new | ( | const char * | name, | |
size_t | name_len | |||
) | [read] |
Create a new channel iterator based on name.
After creating an iterator using this function, the ast_channel_iterator_next() function can be used to iterate through all channels that exist that have the specified name or name prefix.
NULL | on failure | |
a | new channel iterator based on the specified parameters |
Definition at line 1696 of file channel.c.
References channel_iterator_search().
Referenced by ast_complete_channels(), common_exec(), and softhangup_exec().
01697 { 01698 return channel_iterator_search(name, name_len, NULL, NULL); 01699 }
struct ast_channel_iterator* ast_channel_iterator_destroy | ( | struct ast_channel_iterator * | i | ) | [read] |
Destroy a channel iterator.
This function is used to destroy a channel iterator that was retrieved by using one of the channel_iterator_new() functions.
Definition at line 1649 of file channel.c.
References ast_channel_iterator::active_iterator, ao2_iterator_destroy(), and ast_free.
Referenced by action_coreshowchannels(), action_status(), ast_complete_channels(), ast_var_channel_bridge(), ast_var_channel_types_table(), ast_var_channels_table(), common_exec(), data_channels_provider_handler(), func_channels_read(), handle_chanlist(), handle_softhangup(), pickup_by_exten(), and softhangup_exec().
01650 { 01651 ao2_iterator_destroy(i->active_iterator); 01652 ast_free(i); 01653 01654 return NULL; 01655 }
struct ast_channel* ast_channel_iterator_next | ( | struct ast_channel_iterator * | i | ) | [read] |
Get the next channel for a channel iterator.
This function should be used to iterate through all channels that match a specified set of parameters that were provided when the iterator was created.
the | next channel that matches the parameters used when the iterator was created. | |
NULL,if | no more channels match the iterator parameters. |
Definition at line 1715 of file channel.c.
References ast_channel_iterator::active_iterator, and ao2_iterator_next.
Referenced by action_coreshowchannels(), action_status(), ast_complete_channels(), ast_var_channel_bridge(), ast_var_channel_types_table(), ast_var_channels_table(), data_channels_provider_handler(), func_channels_read(), handle_chanlist(), handle_softhangup(), next_channel(), pickup_by_exten(), and softhangup_exec().
01716 { 01717 return ao2_iterator_next(i->active_iterator); 01718 }
int ast_channel_make_compatible | ( | struct ast_channel * | c0, | |
struct ast_channel * | c1 | |||
) |
Makes two channel formats compatible.
c0 | first channel to make compatible | |
c1 | other channel to make compatible |
Set two channels to compatible formats -- call before ast_channel_bridge in general.
Definition at line 5970 of file channel.c.
References ast_channel_make_compatible_helper().
Referenced by action_bridge(), app_exec(), ast_channel_bridge(), bridge_exec(), check_compat(), dial_exec_full(), do_forward(), multiplexed_bridge_join(), parked_call_exec(), simple_bridge_join(), try_calling(), and wait_for_answer().
05971 { 05972 /* Some callers do not check return code, and we must try to set all call legs correctly */ 05973 int rc = 0; 05974 05975 /* Set up translation from the chan to the peer */ 05976 rc = ast_channel_make_compatible_helper(chan, peer); 05977 05978 if (rc < 0) 05979 return rc; 05980 05981 /* Set up translation from the peer to the chan */ 05982 rc = ast_channel_make_compatible_helper(peer, chan); 05983 05984 return rc; 05985 }
static int ast_channel_make_compatible_helper | ( | struct ast_channel * | from, | |
struct ast_channel * | to | |||
) | [static] |
Set up translation from one channel to another.
Definition at line 5920 of file channel.c.
References ast_channel_setoption(), AST_FORMAT_AUDIO_MASK, AST_FORMAT_SLINEAR, ast_getformatname(), ast_log(), ast_opt_generic_plc, ast_opt_transcode_via_slin, AST_OPTION_MAKE_COMPATIBLE, ast_set_read_format(), ast_set_write_format(), ast_translate_path_steps(), ast_translator_best_choice(), ast_channel_tech::bridge, LOG_WARNING, ast_channel::nativeformats, ast_channel::readformat, ast_channel::tech, and ast_channel::writeformat.
Referenced by ast_channel_make_compatible().
05921 { 05922 format_t src, dst; 05923 int use_slin; 05924 05925 /* See if the channel driver can natively make these two channels compatible */ 05926 if (from->tech->bridge && from->tech->bridge == to->tech->bridge && 05927 !ast_channel_setoption(from, AST_OPTION_MAKE_COMPATIBLE, to, sizeof(struct ast_channel *), 0)) { 05928 return 0; 05929 } 05930 05931 if (from->readformat == to->writeformat && from->writeformat == to->readformat) { 05932 /* Already compatible! Moving on ... */ 05933 return 0; 05934 } 05935 05936 /* Set up translation from the 'from' channel to the 'to' channel */ 05937 src = from->nativeformats; 05938 dst = to->nativeformats; 05939 05940 /* If there's no audio in this call, don't bother with trying to find a translation path */ 05941 if ((src & AST_FORMAT_AUDIO_MASK) == 0 || (dst & AST_FORMAT_AUDIO_MASK) == 0) 05942 return 0; 05943 05944 if (ast_translator_best_choice(&dst, &src) < 0) { 05945 ast_log(LOG_WARNING, "No path to translate from %s to %s\n", from->name, to->name); 05946 return -1; 05947 } 05948 05949 /* if the best path is not 'pass through', then 05950 * transcoding is needed; if desired, force transcode path 05951 * to use SLINEAR between channels, but only if there is 05952 * no direct conversion available. If generic PLC is 05953 * desired, then transcoding via SLINEAR is a requirement 05954 */ 05955 use_slin = (src == AST_FORMAT_SLINEAR || dst == AST_FORMAT_SLINEAR); 05956 if ((src != dst) && (ast_opt_generic_plc || ast_opt_transcode_via_slin) && 05957 (ast_translate_path_steps(dst, src) != 1 || use_slin)) 05958 dst = AST_FORMAT_SLINEAR; 05959 if (ast_set_read_format(from, dst) < 0) { 05960 ast_log(LOG_WARNING, "Unable to set read format on channel %s to %s\n", from->name, ast_getformatname(dst)); 05961 return -1; 05962 } 05963 if (ast_set_write_format(to, dst) < 0) { 05964 ast_log(LOG_WARNING, "Unable to set write format on channel %s to %s\n", to->name, ast_getformatname(dst)); 05965 return -1; 05966 } 05967 return 0; 05968 }
int ast_channel_masquerade | ( | struct ast_channel * | original, | |
struct ast_channel * | clone | |||
) |
Weird function made for call transfers.
original | channel to make a copy of | |
clone | copy of the original channel |
This is a very strange and freaky function used primarily for transfer. Suppose that "original" and "clone" are two channels in random situations. This function takes the guts out of "clone" and puts them into the "original" channel, then alerts the channel driver of the change, asking it to fixup any private information (like the p->owner pointer) that is affected by the change. The physical layer of the original channel is hung up.
Definition at line 6110 of file channel.c.
References __ast_channel_masquerade().
Referenced by ast_async_goto(), ast_do_pickup(), attempt_transfer(), builtin_atxfer(), check_availability(), check_bridge(), check_goto_on_transfer(), do_bridge_masquerade(), handle_invite_replaces(), iax_park(), masq_park_call(), sip_park(), and skinny_transfer().
06111 { 06112 return __ast_channel_masquerade(original, clone, NULL); 06113 }
int ast_channel_queryoption | ( | struct ast_channel * | channel, | |
int | option, | |||
void * | data, | |||
int * | datalen, | |||
int | block | |||
) |
Checks the value of an option.
Query the value of an option Works similarly to setoption except only reads the options.
Definition at line 7815 of file channel.c.
References ast_channel_lock, ast_channel_unlock, ast_log(), errno, LOG_ERROR, ast_channel_tech::queryoption, and ast_channel::tech.
Referenced by ast_channel_get_cc_agent_type(), ast_channel_get_device_name(), ast_channel_get_t38_state(), local_queryoption(), rcvfax_exec(), and sndfax_exec().
07816 { 07817 int res; 07818 07819 ast_channel_lock(chan); 07820 if (!chan->tech->queryoption) { 07821 errno = ENOSYS; 07822 ast_channel_unlock(chan); 07823 return -1; 07824 } 07825 07826 if (block) 07827 ast_log(LOG_ERROR, "XXX Blocking not implemented yet XXX\n"); 07828 07829 res = chan->tech->queryoption(chan, option, data, datalen); 07830 ast_channel_unlock(chan); 07831 07832 return res; 07833 }
void ast_channel_queue_connected_line_update | ( | struct ast_channel * | chan, | |
const struct ast_party_connected_line * | connected, | |||
const struct ast_set_party_connected_line * | update | |||
) |
Queue a connected line update frame on a channel.
chan | Asterisk channel to indicate connected line information | |
connected | Connected line information | |
update | What connected line information to update. NULL if all. |
Definition at line 9098 of file channel.c.
References ast_connected_line_build_data(), AST_CONTROL_CONNECTED_LINE, and ast_queue_control_data().
Referenced by ast_do_pickup(), handle_request_invite(), handle_request_update(), handle_response_invite(), local_attended_transfer(), masquerade_colp_transfer(), misdn_queue_connected_line_update(), and sip_call().
09099 { 09100 unsigned char data[1024]; /* This should be large enough */ 09101 size_t datalen; 09102 09103 datalen = ast_connected_line_build_data(data, sizeof(data), connected, update); 09104 if (datalen == (size_t) -1) { 09105 return; 09106 } 09107 09108 ast_queue_control_data(chan, AST_CONTROL_CONNECTED_LINE, data, datalen); 09109 }
void ast_channel_queue_redirecting_update | ( | struct ast_channel * | chan, | |
const struct ast_party_redirecting * | redirecting, | |||
const struct ast_set_party_redirecting * | update | |||
) |
Queue a redirecting update frame on a channel.
chan | Asterisk channel to indicate redirecting id information | |
redirecting | Redirecting id information | |
update | What redirecting information to update. NULL if all. |
Definition at line 9605 of file channel.c.
References AST_CONTROL_REDIRECTING, ast_queue_control_data(), and ast_redirecting_build_data().
Referenced by cb_events(), handle_response_invite(), and misdn_facility_ie_handler().
09606 { 09607 unsigned char data[1024]; /* This should be large enough */ 09608 size_t datalen; 09609 09610 datalen = ast_redirecting_build_data(data, sizeof(data), redirecting, update); 09611 if (datalen == (size_t) -1) { 09612 return; 09613 } 09614 09615 ast_queue_control_data(chan, AST_CONTROL_REDIRECTING, data, datalen); 09616 }
const char* ast_channel_reason2str | ( | int | reason | ) |
return an english explanation of the code returned thru __ast_request_and_dial's 'outstate' argument
reason | The integer argument, usually taken from AST_CONTROL_ macros |
Definition at line 5313 of file channel.c.
References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RING, and AST_CONTROL_RINGING.
Referenced by attempt_thread().
05314 { 05315 switch (reason) /* the following appear to be the only ones actually returned by request_and_dial */ 05316 { 05317 case 0: 05318 return "Call Failure (not BUSY, and not NO_ANSWER, maybe Circuit busy or down?)"; 05319 case AST_CONTROL_HANGUP: 05320 return "Hangup"; 05321 case AST_CONTROL_RING: 05322 return "Local Ring"; 05323 case AST_CONTROL_RINGING: 05324 return "Remote end Ringing"; 05325 case AST_CONTROL_ANSWER: 05326 return "Remote end has Answered"; 05327 case AST_CONTROL_BUSY: 05328 return "Remote end is Busy"; 05329 case AST_CONTROL_CONGESTION: 05330 return "Congestion (circuits busy)"; 05331 default: 05332 return "Unknown Reason!!"; 05333 } 05334 }
int ast_channel_redirecting_macro | ( | struct ast_channel * | autoservice_chan, | |
struct ast_channel * | macro_chan, | |||
const void * | redirecting_info, | |||
int | is_caller, | |||
int | is_frame | |||
) |
Run a redirecting interception macro and update a channel's redirecting information.
Whenever we want to update a channel's redirecting information, we may need to run a macro so that an administrator can manipulate the information before sending it out. This function both runs the macro and sends the update to the channel.
autoservice_chan | Channel to place into autoservice while the macro is running. It is perfectly safe for this to be NULL | |
macro_chan | The channel to run the macro on. Also the channel from which we determine which macro we need to run. | |
redirecting_info | Either an ast_party_redirecting or ast_frame pointer of type AST_CONTROL_REDIRECTING | |
is_caller | If true, then run REDIRECTING_CALLER_SEND_MACRO, otherwise run REDIRECTING_CALLEE_SEND_MACRO | |
is_frame | If true, then redirecting_info is an ast_frame pointer, otherwise it is an ast_party_redirecting pointer. |
0 | Success | |
-1 | Either the macro does not exist, or there was an error while attempting to run the macro |
Have multiple return codes based on the MACRO_RESULT
Make constants so that caller and frame can be more expressive than just '1' and '0'
Definition at line 9663 of file channel.c.
References ast_app_run_macro(), ast_channel_lock, ast_channel_unlock, ast_channel_update_redirecting(), ast_party_redirecting_copy(), ast_party_redirecting_free(), ast_party_redirecting_init(), ast_redirecting_parse_data(), ast_strdupa, ast_strlen_zero(), ast_frame::data, ast_frame::datalen, pbx_builtin_getvar_helper(), ast_frame::ptr, ast_channel::redirecting, and S_OR.
Referenced by ast_bridge_call(), ast_generic_bridge(), call_forward_inherit(), do_forward(), feature_request_and_dial(), handle_frame(), local_bridge_loop(), remote_bridge_loop(), and wait_for_answer().
09664 { 09665 const char *macro; 09666 const char *macro_args; 09667 int retval; 09668 09669 ast_channel_lock(macro_chan); 09670 macro = pbx_builtin_getvar_helper(macro_chan, is_caller 09671 ? "REDIRECTING_CALLER_SEND_MACRO" : "REDIRECTING_CALLEE_SEND_MACRO"); 09672 macro = ast_strdupa(S_OR(macro, "")); 09673 macro_args = pbx_builtin_getvar_helper(macro_chan, is_caller 09674 ? "REDIRECTING_CALLER_SEND_MACRO_ARGS" : "REDIRECTING_CALLEE_SEND_MACRO_ARGS"); 09675 macro_args = ast_strdupa(S_OR(macro_args, "")); 09676 09677 if (ast_strlen_zero(macro)) { 09678 ast_channel_unlock(macro_chan); 09679 return -1; 09680 } 09681 09682 if (is_frame) { 09683 const struct ast_frame *frame = redirecting_info; 09684 09685 ast_redirecting_parse_data(frame->data.ptr, frame->datalen, ¯o_chan->redirecting); 09686 } else { 09687 const struct ast_party_redirecting *redirecting = redirecting_info; 09688 09689 ast_party_redirecting_copy(¯o_chan->redirecting, redirecting); 09690 } 09691 ast_channel_unlock(macro_chan); 09692 09693 retval = ast_app_run_macro(autoservice_chan, macro_chan, macro, macro_args); 09694 if (!retval) { 09695 struct ast_party_redirecting saved_redirecting; 09696 09697 ast_party_redirecting_init(&saved_redirecting); 09698 ast_channel_lock(macro_chan); 09699 ast_party_redirecting_copy(&saved_redirecting, ¯o_chan->redirecting); 09700 ast_channel_unlock(macro_chan); 09701 ast_channel_update_redirecting(macro_chan, &saved_redirecting, NULL); 09702 ast_party_redirecting_free(&saved_redirecting); 09703 } 09704 09705 return retval; 09706 }
int ast_channel_register | ( | const struct ast_channel_tech * | tech | ) |
Register a new telephony channel in Asterisk.
Register a channel technology (a new channel driver) Called by a channel module to register the kind of channels it supports.
Definition at line 907 of file channel.c.
References ast_calloc, ast_debug, ast_log(), AST_RWLIST_INSERT_HEAD, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, ast_channel_tech::description, LOG_WARNING, chanlist::tech, and ast_channel_tech::type.
Referenced by load_module(), and unload_module().
00908 { 00909 struct chanlist *chan; 00910 00911 AST_RWLIST_WRLOCK(&backends); 00912 00913 AST_RWLIST_TRAVERSE(&backends, chan, list) { 00914 if (!strcasecmp(tech->type, chan->tech->type)) { 00915 ast_log(LOG_WARNING, "Already have a handler for type '%s'\n", tech->type); 00916 AST_RWLIST_UNLOCK(&backends); 00917 return -1; 00918 } 00919 } 00920 00921 if (!(chan = ast_calloc(1, sizeof(*chan)))) { 00922 AST_RWLIST_UNLOCK(&backends); 00923 return -1; 00924 } 00925 chan->tech = tech; 00926 AST_RWLIST_INSERT_HEAD(&backends, chan, list); 00927 00928 ast_debug(1, "Registered handler for '%s' (%s)\n", chan->tech->type, chan->tech->description); 00929 00930 ast_verb(2, "Registered channel type '%s' (%s)\n", chan->tech->type, chan->tech->description); 00931 00932 AST_RWLIST_UNLOCK(&backends); 00933 00934 return 0; 00935 }
struct ast_channel* ast_channel_release | ( | struct ast_channel * | chan | ) | [read] |
Unlink and release reference to a channel.
This function will unlink the channel from the global channels container if it is still there and also release the current reference to the channel.
Definition at line 1921 of file channel.c.
References ao2_unlink, ast_channel_unref, and channels.
Referenced by agent_cleanup(), ast_iax2_new(), ast_request(), bridge_request(), do_notify(), gtalk_newcall(), local_new(), and local_request().
01922 { 01923 /* Safe, even if already unlinked. */ 01924 ao2_unlink(channels, chan); 01925 return ast_channel_unref(chan); 01926 }
int ast_channel_sendhtml | ( | struct ast_channel * | channel, | |
int | subclass, | |||
const char * | data, | |||
int | datalen | |||
) |
Sends HTML on given channel Send HTML or URL on link.
Definition at line 5907 of file channel.c.
References ast_channel_tech::send_html, and ast_channel::tech.
Referenced by agent_sendhtml(), ast_channel_sendurl(), and wait_for_answer().
int ast_channel_sendurl | ( | struct ast_channel * | channel, | |
const char * | url | |||
) |
Sends a URL on a given link Send URL on link.
Definition at line 5914 of file channel.c.
References ast_channel_sendhtml(), and AST_HTML_URL.
Referenced by dial_exec_full(), sendurl_exec(), and try_calling().
05915 { 05916 return ast_channel_sendhtml(chan, AST_HTML_URL, url, strlen(url) + 1); 05917 }
void ast_channel_set_caller | ( | struct ast_channel * | chan, | |
const struct ast_party_caller * | caller, | |||
const struct ast_set_party_caller * | update | |||
) |
Set the caller id information in the Asterisk channel.
chan | Asterisk channel to set caller id information | |
caller | Caller id information | |
update | What caller information to update. NULL if all. |
Definition at line 7079 of file channel.c.
References ast_channel_lock, ast_channel_unlock, ast_party_caller_set(), and ast_channel::caller.
07080 { 07081 if (&chan->caller == caller) { 07082 /* Don't set to self */ 07083 return; 07084 } 07085 07086 ast_channel_lock(chan); 07087 ast_party_caller_set(&chan->caller, caller, update); 07088 ast_channel_unlock(chan); 07089 }
void ast_channel_set_caller_event | ( | struct ast_channel * | chan, | |
const struct ast_party_caller * | caller, | |||
const struct ast_set_party_caller * | update | |||
) |
Set the caller id information in the Asterisk channel and generate an AMI event if the caller id name or number changed.
chan | Asterisk channel to set caller id information | |
caller | Caller id information | |
update | What caller information to update. NULL if all. |
Definition at line 7091 of file channel.c.
References ast_cdr_setcid(), ast_channel_lock, ast_channel_unlock, ast_party_caller_set(), ast_channel::caller, ast_channel::cdr, ast_party_caller::id, ast_party_id::name, ast_party_id::number, report_new_callerid(), S_COR, ast_party_name::str, ast_party_number::str, ast_party_name::valid, and ast_party_number::valid.
Referenced by callerid_write(), dial_exec_full(), do_forward(), misdn_update_caller_id(), and ring_entry().
07092 { 07093 const char *pre_set_number; 07094 const char *pre_set_name; 07095 07096 if (&chan->caller == caller) { 07097 /* Don't set to self */ 07098 return; 07099 } 07100 07101 ast_channel_lock(chan); 07102 pre_set_number = 07103 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL); 07104 pre_set_name = S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL); 07105 ast_party_caller_set(&chan->caller, caller, update); 07106 if (S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL) 07107 != pre_set_number 07108 || S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL) 07109 != pre_set_name) { 07110 /* The caller id name or number changed. */ 07111 report_new_callerid(chan); 07112 } 07113 if (chan->cdr) { 07114 ast_cdr_setcid(chan->cdr, chan); 07115 } 07116 ast_channel_unlock(chan); 07117 }
void ast_channel_set_connected_line | ( | struct ast_channel * | chan, | |
const struct ast_party_connected_line * | connected, | |||
const struct ast_set_party_connected_line * | update | |||
) |
Set the connected line information in the Asterisk channel.
chan | Asterisk channel to set connected line information | |
connected | Connected line information | |
update | What connected line information to update. NULL if all. |
Definition at line 8458 of file channel.c.
References ast_channel_lock, ast_channel_unlock, ast_party_connected_line_set(), and ast_channel::connected.
Referenced by __ast_request_and_dial(), ast_indicate_data(), connectedline_write(), dial_exec_full(), and feature_request_and_dial().
08459 { 08460 if (&chan->connected == connected) { 08461 /* Don't set to self */ 08462 return; 08463 } 08464 08465 ast_channel_lock(chan); 08466 ast_party_connected_line_set(&chan->connected, connected, update); 08467 ast_channel_unlock(chan); 08468 }
void ast_channel_set_fd | ( | struct ast_channel * | chan, | |
int | which, | |||
int | fd | |||
) |
Set the file descriptor on the channel
Definition at line 2631 of file channel.c.
References ast_calloc, ast_epoll_data::chan, ast_channel::fds, free, and ast_epoll_data::which.
Referenced by __ast_channel_alloc_ap(), __oh323_new(), __oh323_rtp_create(), __oh323_update_info(), alsa_new(), ast_do_masquerade(), dahdi_new(), deactivate_generator_nolock(), gtalk_new(), initialize_udptl(), jingle_new(), mgcp_new(), misdn_new(), my_swap_subchannels(), nbs_new(), oss_new(), phone_new(), process_sdp(), setformat(), sip_new(), sip_set_rtp_peer(), skinny_new(), start_rtp(), and swap_subs().
02632 { 02633 #ifdef HAVE_EPOLL 02634 struct epoll_event ev; 02635 struct ast_epoll_data *aed = NULL; 02636 02637 if (chan->fds[which] > -1) { 02638 epoll_ctl(chan->epfd, EPOLL_CTL_DEL, chan->fds[which], &ev); 02639 aed = chan->epfd_data[which]; 02640 } 02641 02642 /* If this new fd is valid, add it to the epoll */ 02643 if (fd > -1) { 02644 if (!aed && (!(aed = ast_calloc(1, sizeof(*aed))))) 02645 return; 02646 02647 chan->epfd_data[which] = aed; 02648 aed->chan = chan; 02649 aed->which = which; 02650 02651 ev.events = EPOLLIN | EPOLLPRI | EPOLLERR | EPOLLHUP; 02652 ev.data.ptr = aed; 02653 epoll_ctl(chan->epfd, EPOLL_CTL_ADD, fd, &ev); 02654 } else if (aed) { 02655 /* We don't have to keep around this epoll data structure now */ 02656 free(aed); 02657 chan->epfd_data[which] = NULL; 02658 } 02659 #endif 02660 chan->fds[which] = fd; 02661 return; 02662 }
void ast_channel_set_linkgroup | ( | struct ast_channel * | chan, | |
struct ast_channel * | peer | |||
) |
Propagate the oldest linkedid between associated channels.
propagate the linked id between chan and peer
Definition at line 6387 of file channel.c.
References ast_channel::_bridge, ast_bridged_channel(), ast_channel_change_linkedid(), ast_strdupa, and oldest_linkedid().
Referenced by ast_bridge_call(), and ast_do_masquerade().
06388 { 06389 const char* linkedid=NULL; 06390 struct ast_channel *bridged; 06391 06392 linkedid = oldest_linkedid(chan->linkedid, peer->linkedid); 06393 linkedid = oldest_linkedid(linkedid, chan->uniqueid); 06394 linkedid = oldest_linkedid(linkedid, peer->uniqueid); 06395 if (chan->_bridge) { 06396 bridged = ast_bridged_channel(chan); 06397 if (bridged && bridged != peer) { 06398 linkedid = oldest_linkedid(linkedid, bridged->linkedid); 06399 linkedid = oldest_linkedid(linkedid, bridged->uniqueid); 06400 } 06401 } 06402 if (peer->_bridge) { 06403 bridged = ast_bridged_channel(peer); 06404 if (bridged && bridged != chan) { 06405 linkedid = oldest_linkedid(linkedid, bridged->linkedid); 06406 linkedid = oldest_linkedid(linkedid, bridged->uniqueid); 06407 } 06408 } 06409 06410 /* just in case setting a stringfield to itself causes problems */ 06411 linkedid = ast_strdupa(linkedid); 06412 06413 ast_channel_change_linkedid(chan, linkedid); 06414 ast_channel_change_linkedid(peer, linkedid); 06415 if (chan->_bridge) { 06416 bridged = ast_bridged_channel(chan); 06417 if (bridged && bridged != peer) { 06418 ast_channel_change_linkedid(bridged, linkedid); 06419 } 06420 } 06421 if (peer->_bridge) { 06422 bridged = ast_bridged_channel(peer); 06423 if (bridged && bridged != chan) { 06424 ast_channel_change_linkedid(bridged, linkedid); 06425 } 06426 } 06427 }
void ast_channel_set_redirecting | ( | struct ast_channel * | chan, | |
const struct ast_party_redirecting * | redirecting, | |||
const struct ast_set_party_redirecting * | update | |||
) |
Set the redirecting id information in the Asterisk channel.
chan | Asterisk channel to set redirecting id information | |
redirecting | Redirecting id information | |
update | What redirecting information to update. NULL if all. |
Definition at line 9111 of file channel.c.
References ast_channel_lock, ast_channel_unlock, ast_party_redirecting_set(), and ast_channel::redirecting.
Referenced by ast_indicate_data(), handle_request_invite(), handle_response(), misdn_copy_redirecting_to_ast(), and redirecting_write().
09112 { 09113 if (&chan->redirecting == redirecting) { 09114 /* Don't set to self */ 09115 return; 09116 } 09117 09118 ast_channel_lock(chan); 09119 ast_party_redirecting_set(&chan->redirecting, redirecting, update); 09120 ast_channel_unlock(chan); 09121 }
int ast_channel_setoption | ( | struct ast_channel * | channel, | |
int | option, | |||
void * | data, | |||
int | datalen, | |||
int | block | |||
) |
Sets an option on a channel.
channel | channel to set options on | |
option | option to change | |
data | data specific to option | |
datalen | length of the data | |
block | blocking or not |
Set an option on a channel (see frame.h), optionally blocking awaiting the reply
Definition at line 7795 of file channel.c.
References ast_channel_lock, ast_channel_unlock, ast_log(), errno, LOG_ERROR, ast_channel_tech::setoption, and ast_channel::tech.
Referenced by analog_hangup(), ast_bridge_call(), ast_channel_make_compatible_helper(), common_exec(), conf_run(), dahdi_hangup(), dial_exec_full(), func_channel_write(), func_channel_write_real(), handle_tddmode(), play_record_review(), rcvfax_exec(), reset_volumes(), set_format(), set_listen_volume(), set_security_requirements(), set_talk_volume(), sndfax_exec(), try_calling(), and vm_forwardoptions().
07796 { 07797 int res; 07798 07799 ast_channel_lock(chan); 07800 if (!chan->tech->setoption) { 07801 errno = ENOSYS; 07802 ast_channel_unlock(chan); 07803 return -1; 07804 } 07805 07806 if (block) 07807 ast_log(LOG_ERROR, "XXX Blocking not implemented yet XXX\n"); 07808 07809 res = chan->tech->setoption(chan, option, data, datalen); 07810 ast_channel_unlock(chan); 07811 07812 return res; 07813 }
void ast_channel_setwhentohangup | ( | struct ast_channel * | chan, | |
time_t | offset | |||
) |
Set when to hang a channel up.
chan | channel on which to check for hang up | |
offset | offset in seconds relative to the current time of when to hang up |
This function sets the absolute time out on a channel (when to hang up).
Definition at line 878 of file channel.c.
References ast_channel_setwhentohangup_tv().
00879 { 00880 struct timeval when = { offset, }; 00881 ast_channel_setwhentohangup_tv(chan, when); 00882 }
void ast_channel_setwhentohangup_tv | ( | struct ast_channel * | chan, | |
struct timeval | offset | |||
) |
Set when to hangup channel.
Set when to hang a channel up.
Definition at line 871 of file channel.c.
References ast_null_frame, ast_queue_frame(), ast_tvadd(), ast_tvnow(), ast_tvzero(), and ast_channel::whentohangup.
Referenced by action_timeout(), ast_channel_setwhentohangup(), handle_autohangup(), and timeout_write().
00872 { 00873 chan->whentohangup = ast_tvzero(offset) ? offset : ast_tvadd(offset, ast_tvnow()); 00874 ast_queue_frame(chan, &ast_null_frame); 00875 return; 00876 }
static int ast_channel_softhangup_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 829 of file channel.c.
References ast_softhangup(), and AST_SOFTHANGUP_SHUTDOWN.
Referenced by ast_begin_shutdown().
00830 { 00831 struct ast_channel *chan = obj; 00832 00833 ast_softhangup(chan, AST_SOFTHANGUP_SHUTDOWN); 00834 00835 return 0; 00836 }
struct ast_silence_generator* ast_channel_start_silence_generator | ( | struct ast_channel * | chan | ) | [read] |
Starts a silence generator on the given channel.
chan | The channel to generate silence on |
This function will cause SLINEAR silence to be generated on the supplied channel until it is disabled; if the channel cannot be put into SLINEAR mode then the function will fail.
Definition at line 8309 of file channel.c.
References ast_activate_generator(), ast_calloc, ast_debug, AST_FORMAT_SLINEAR, ast_free, ast_log(), ast_set_write_format(), LOG_ERROR, ast_silence_generator::old_write_format, and ast_channel::writeformat.
Referenced by __ast_play_and_record(), ast_bridge_call(), ast_dtmf_stream(), ast_readstring_full(), ast_safe_sleep_conditional(), channel_spy(), record_exec(), TransferCallStep1(), waitfor_exec(), and waitforring_exec().
08310 { 08311 struct ast_silence_generator *state; 08312 08313 if (!(state = ast_calloc(1, sizeof(*state)))) { 08314 return NULL; 08315 } 08316 08317 state->old_write_format = chan->writeformat; 08318 08319 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { 08320 ast_log(LOG_ERROR, "Could not set write format to SLINEAR\n"); 08321 ast_free(state); 08322 return NULL; 08323 } 08324 08325 ast_activate_generator(chan, &silence_generator, state); 08326 08327 ast_debug(1, "Started silence generator on '%s'\n", chan->name); 08328 08329 return state; 08330 }
void ast_channel_stop_silence_generator | ( | struct ast_channel * | chan, | |
struct ast_silence_generator * | state | |||
) |
Stops a previously-started silence generator on the given channel.
chan | The channel to operate on | |
state | The ast_silence_generator pointer return by a previous call to ast_channel_start_silence_generator. |
This function will stop the operating silence generator and return the channel to its previous write format.
Definition at line 8355 of file channel.c.
References ast_debug, ast_free, ast_log(), ast_set_write_format(), deactivate_silence_generator(), LOG_ERROR, and ast_silence_generator::old_write_format.
Referenced by __ast_play_and_record(), ast_bridge_call(), ast_dtmf_stream(), ast_readstring_full(), ast_safe_sleep_conditional(), channel_spy(), HandleCallOutgoing(), key_dial_page(), record_exec(), unistim_hangup(), waitfor_exec(), and waitforring_exec().
08356 { 08357 if (!state) { 08358 return; 08359 } 08360 08361 if (deactivate_silence_generator(chan)) { 08362 ast_debug(1, "Stopped silence generator on '%s'\n", chan->name); 08363 08364 if (ast_set_write_format(chan, state->old_write_format) < 0) 08365 ast_log(LOG_ERROR, "Could not return write format to its original state\n"); 08366 } 08367 ast_free(state); 08368 }
int ast_channel_supports_html | ( | struct ast_channel * | channel | ) |
Checks for HTML support on a channel.
Definition at line 5902 of file channel.c.
References ast_channel_tech::send_html, and ast_channel::tech.
Referenced by dial_exec_full(), sendurl_exec(), and try_calling().
int ast_channel_transfer_masquerade | ( | struct ast_channel * | target_chan, | |
const struct ast_party_connected_line * | target_id, | |||
int | target_held, | |||
struct ast_channel * | transferee_chan, | |||
const struct ast_party_connected_line * | transferee_id, | |||
int | transferee_held | |||
) |
Setup a masquerade to transfer a call.
target_chan | Target of the call transfer. (Masquerade original channel) | |
target_id | New connected line information for the target channel. | |
target_held | TRUE if the target call is on hold. | |
transferee_chan | Transferee of the call transfer. (Masquerade clone channel) | |
transferee_id | New connected line information for the transferee channel. | |
transferee_held | TRUE if the transferee call is on hold. |
Party A - Transferee Party B - Transferer Party C - Target of transfer
Party B transfers A to C.
Party A is connected to bridged channel B1. Party B is connected to channels C1 and C2. Party C is connected to bridged channel B2.
Party B -- C1 == B1 -- Party A __/ / Party B -- C2 == B2 -- Party C
Bridged channel B1 is masqueraded into channel C2. Where B1 is the masquerade clone channel and C2 is the masquerade original channel.
0 | on success. | |
-1 | on error. |
Definition at line 6184 of file channel.c.
References __ast_channel_masquerade(), ast_calloc, ast_datastore_alloc, ast_datastore_free(), ast_datastore::data, party_connected_line_copy_transfer(), xfer_masquerade_ds::target_held, xfer_masquerade_ds::target_id, xfer_masquerade_ds::transferee_held, and xfer_masquerade_ds::transferee_id.
Referenced by analog_attempt_transfer(), and misdn_attempt_transfer().
06191 { 06192 struct ast_datastore *xfer_ds; 06193 struct xfer_masquerade_ds *xfer_colp; 06194 int res; 06195 06196 xfer_ds = ast_datastore_alloc(&xfer_ds_info, NULL); 06197 if (!xfer_ds) { 06198 return -1; 06199 } 06200 06201 xfer_colp = ast_calloc(1, sizeof(*xfer_colp)); 06202 if (!xfer_colp) { 06203 ast_datastore_free(xfer_ds); 06204 return -1; 06205 } 06206 party_connected_line_copy_transfer(&xfer_colp->target_id, target_id); 06207 xfer_colp->target_held = target_held; 06208 party_connected_line_copy_transfer(&xfer_colp->transferee_id, transferee_id); 06209 xfer_colp->transferee_held = transferee_held; 06210 xfer_ds->data = xfer_colp; 06211 06212 res = __ast_channel_masquerade(target_chan, transferee_chan, xfer_ds); 06213 if (res) { 06214 ast_datastore_free(xfer_ds); 06215 } 06216 return res; 06217 }
void ast_channel_undefer_dtmf | ( | struct ast_channel * | chan | ) |
Unset defer DTMF flag on channel.
Undo defer. ast_read will return any DTMF characters that were queued
Definition at line 1628 of file channel.c.
References ast_clear_flag, and AST_FLAG_DEFER_DTMF.
Referenced by __adsi_transmit_messages(), and find_cache().
01629 { 01630 if (chan) 01631 ast_clear_flag(chan, AST_FLAG_DEFER_DTMF); 01632 }
void ast_channel_unregister | ( | const struct ast_channel_tech * | tech | ) |
Unregister channel driver.
Unregister a channel technology.
Definition at line 938 of file channel.c.
References ast_debug, ast_free, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_END, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, chanlist::tech, and ast_channel_tech::type.
Referenced by __unload_module(), load_module(), and unload_module().
00939 { 00940 struct chanlist *chan; 00941 00942 ast_debug(1, "Unregistering channel type '%s'\n", tech->type); 00943 00944 AST_RWLIST_WRLOCK(&backends); 00945 00946 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&backends, chan, list) { 00947 if (chan->tech == tech) { 00948 AST_LIST_REMOVE_CURRENT(list); 00949 ast_free(chan); 00950 ast_verb(2, "Unregistered channel type '%s'\n", tech->type); 00951 break; 00952 } 00953 } 00954 AST_LIST_TRAVERSE_SAFE_END; 00955 00956 AST_RWLIST_UNLOCK(&backends); 00957 }
void ast_channel_update_connected_line | ( | struct ast_channel * | chan, | |
const struct ast_party_connected_line * | connected, | |||
const struct ast_set_party_connected_line * | update | |||
) |
Indicate that the connected line information has changed.
chan | Asterisk channel to indicate connected line information | |
connected | Connected line information | |
update | What connected line information to update. NULL if all. |
Definition at line 9085 of file channel.c.
References ast_connected_line_build_data(), AST_CONTROL_CONNECTED_LINE, and ast_indicate_data().
Referenced by app_exec(), ast_channel_connected_line_macro(), ast_do_pickup(), atxfer_fail_cleanup(), builtin_atxfer(), connectedline_write(), parked_call_exec(), and wait_for_answer().
09086 { 09087 unsigned char data[1024]; /* This should be large enough */ 09088 size_t datalen; 09089 09090 datalen = ast_connected_line_build_data(data, sizeof(data), connected, update); 09091 if (datalen == (size_t) -1) { 09092 return; 09093 } 09094 09095 ast_indicate_data(chan, AST_CONTROL_CONNECTED_LINE, data, datalen); 09096 }
void ast_channel_update_redirecting | ( | struct ast_channel * | chan, | |
const struct ast_party_redirecting * | redirecting, | |||
const struct ast_set_party_redirecting * | update | |||
) |
Indicate that the redirecting id has changed.
chan | Asterisk channel to indicate redirecting id information | |
redirecting | Redirecting id information | |
update | What redirecting information to update. NULL if all. |
Definition at line 9592 of file channel.c.
References AST_CONTROL_REDIRECTING, ast_indicate_data(), and ast_redirecting_build_data().
Referenced by ast_channel_redirecting_macro(), call_forward_inherit(), do_forward(), redirecting_write(), and wait_for_answer().
09593 { 09594 unsigned char data[1024]; /* This should be large enough */ 09595 size_t datalen; 09596 09597 datalen = ast_redirecting_build_data(data, sizeof(data), redirecting, update); 09598 if (datalen == (size_t) -1) { 09599 return; 09600 } 09601 09602 ast_indicate_data(chan, AST_CONTROL_REDIRECTING, data, datalen); 09603 }
void ast_channels_init | ( | void | ) |
Provided by channel.c
Definition at line 8221 of file channel.c.
References ao2_container_alloc, ARRAY_LEN, ast_channel_cmp_cb(), ast_channel_hash_cb(), ast_cli_register_multiple(), ast_data_register_multiple_core, ast_plc_reload(), ast_register_atexit(), channels, channels_shutdown(), cli_channel, and NUM_CHANNEL_BUCKETS.
Referenced by main().
08222 { 08223 channels = ao2_container_alloc(NUM_CHANNEL_BUCKETS, 08224 ast_channel_hash_cb, ast_channel_cmp_cb); 08225 08226 ast_cli_register_multiple(cli_channel, ARRAY_LEN(cli_channel)); 08227 08228 ast_data_register_multiple_core(channel_providers, ARRAY_LEN(channel_providers)); 08229 08230 ast_plc_reload(); 08231 08232 ast_register_atexit(channels_shutdown); 08233 }
struct ast_variable* ast_channeltype_list | ( | void | ) | [read] |
return an ast_variable list of channeltypes
Definition at line 261 of file channel.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_variable_new(), ast_channel_tech::description, chanlist::tech, ast_channel_tech::type, and var.
Referenced by ast_var_channel_types(), and ast_var_channel_types_table().
00262 { 00263 struct chanlist *cl; 00264 struct ast_variable *var = NULL, *prev = NULL; 00265 00266 AST_RWLIST_RDLOCK(&backends); 00267 AST_RWLIST_TRAVERSE(&backends, cl, list) { 00268 if (prev) { 00269 if ((prev->next = ast_variable_new(cl->tech->type, cl->tech->description, ""))) 00270 prev = prev->next; 00271 } else { 00272 var = ast_variable_new(cl->tech->type, cl->tech->description, ""); 00273 prev = var; 00274 } 00275 } 00276 AST_RWLIST_UNLOCK(&backends); 00277 00278 return var; 00279 }
int ast_check_hangup | ( | struct ast_channel * | chan | ) |
Checks to see if a channel is needing hang up.
Check to see if a channel is needing hang up.
Definition at line 806 of file channel.c.
References ast_channel::_softhangup, ast_debug, AST_SOFTHANGUP_TIMEOUT, ast_test_suite_event_notify, ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), and ast_channel::whentohangup.
Referenced by __ast_pbx_run(), __ast_read(), _macro_exec(), agent_indicate(), agi_exec(), agi_handle_command(), announce_thread(), ast_bridge_call(), ast_call(), ast_channel_bridge(), ast_check_hangup_locked(), ast_indicate_data(), AST_LIST_HEAD(), ast_raw_answer(), ast_readstring_full(), ast_recvtext(), ast_rtp_instance_bridge(), ast_sendtext(), ast_transfer(), ast_udptl_bridge(), ast_waitfordigit_full(), ast_write(), autoservice_run(), bridge_call_thread(), bridge_exec(), builtin_atxfer(), call_forward_inherit(), channel_spy(), check_bridge(), common_exec(), conf_play(), conf_run(), dahdi_sendtext(), dahdi_setoption(), dial_exec_full(), dundi_lookup_internal(), eagi_exec(), eivr_comm(), feature_request_and_dial(), findmeexec(), func_channel_read(), gosub_run(), handle_sendimage(), iax2_bridge(), launch_asyncagi(), local_bridge_loop(), local_fixup(), login_exec(), lua_check_hangup(), ospfinished_exec(), pbx_builtin_incomplete(), pbx_builtin_waitexten(), pbx_exec(), readexten_exec(), remote_bridge_loop(), run_agi(), run_ras(), try_calling(), and wait_for_answer().
00807 { 00808 if (chan->_softhangup) /* yes if soft hangup flag set */ 00809 return 1; 00810 if (ast_tvzero(chan->whentohangup)) /* no if no hangup scheduled */ 00811 return 0; 00812 if (ast_tvdiff_ms(chan->whentohangup, ast_tvnow()) > 0) /* no if hangup time has not come yet. */ 00813 return 0; 00814 ast_debug(4, "Hangup time has come: %" PRIi64 "\n", ast_tvdiff_ms(chan->whentohangup, ast_tvnow())); 00815 ast_test_suite_event_notify("HANGUP_TIME", "Channel: %s", chan->name); 00816 chan->_softhangup |= AST_SOFTHANGUP_TIMEOUT; /* record event */ 00817 return 1; 00818 }
int ast_check_hangup_locked | ( | struct ast_channel * | chan | ) |
Definition at line 820 of file channel.c.
References ast_channel_lock, ast_channel_unlock, and ast_check_hangup().
Referenced by action_redirect(), and ast_channel_bridge().
00821 { 00822 int res; 00823 ast_channel_lock(chan); 00824 res = ast_check_hangup(chan); 00825 ast_channel_unlock(chan); 00826 return res; 00827 }
int ast_connected_line_build_data | ( | unsigned char * | data, | |
size_t | datalen, | |||
const struct ast_party_connected_line * | connected, | |||
const struct ast_set_party_connected_line * | update | |||
) |
Build the connected line information data frame.
data | Buffer to fill with the frame data | |
datalen | Size of the buffer to fill | |
connected | Connected line information | |
update | What connected line information to build. NULL if all. |
-1 | if error | |
Amount | of data buffer used |
Definition at line 8825 of file channel.c.
References AST_CONNECTED_LINE_ID_PRESENTATION, AST_CONNECTED_LINE_NAME, AST_CONNECTED_LINE_NAME_CHAR_SET, AST_CONNECTED_LINE_NAME_PRESENTATION, AST_CONNECTED_LINE_NAME_VALID, AST_CONNECTED_LINE_NUMBER, AST_CONNECTED_LINE_NUMBER_PLAN, AST_CONNECTED_LINE_NUMBER_PRESENTATION, AST_CONNECTED_LINE_NUMBER_VALID, AST_CONNECTED_LINE_SOURCE, AST_CONNECTED_LINE_SUBADDRESS, AST_CONNECTED_LINE_SUBADDRESS_ODD_EVEN, AST_CONNECTED_LINE_SUBADDRESS_TYPE, AST_CONNECTED_LINE_SUBADDRESS_VALID, AST_CONNECTED_LINE_TAG, AST_CONNECTED_LINE_VERSION, ast_log(), ast_set_party_connected_line::id, ast_party_connected_line::id, LOG_WARNING, ast_party_id_ies::name, party_id_build_data(), ast_party_connected_line::source, ast_party_name_ies::str, and value.
Referenced by ast_channel_queue_connected_line_update(), ast_channel_update_connected_line(), local_attended_transfer(), local_indicate(), and masquerade_colp_transfer().
08826 { 08827 int32_t value; 08828 size_t pos = 0; 08829 int res; 08830 08831 static const struct ast_party_id_ies ies = { 08832 .name.str = AST_CONNECTED_LINE_NAME, 08833 .name.char_set = AST_CONNECTED_LINE_NAME_CHAR_SET, 08834 .name.presentation = AST_CONNECTED_LINE_NAME_PRESENTATION, 08835 .name.valid = AST_CONNECTED_LINE_NAME_VALID, 08836 08837 .number.str = AST_CONNECTED_LINE_NUMBER, 08838 .number.plan = AST_CONNECTED_LINE_NUMBER_PLAN, 08839 .number.presentation = AST_CONNECTED_LINE_NUMBER_PRESENTATION, 08840 .number.valid = AST_CONNECTED_LINE_NUMBER_VALID, 08841 08842 .subaddress.str = AST_CONNECTED_LINE_SUBADDRESS, 08843 .subaddress.type = AST_CONNECTED_LINE_SUBADDRESS_TYPE, 08844 .subaddress.odd_even_indicator = AST_CONNECTED_LINE_SUBADDRESS_ODD_EVEN, 08845 .subaddress.valid = AST_CONNECTED_LINE_SUBADDRESS_VALID, 08846 08847 .tag = AST_CONNECTED_LINE_TAG, 08848 .combined_presentation = AST_CONNECTED_LINE_ID_PRESENTATION, 08849 }; 08850 08851 /* 08852 * The size of integer values must be fixed in case the frame is 08853 * shipped to another machine. 08854 */ 08855 08856 /* Connected line frame version */ 08857 if (datalen < pos + (sizeof(data[0]) * 2) + 1) { 08858 ast_log(LOG_WARNING, "No space left for connected line frame version\n"); 08859 return -1; 08860 } 08861 data[pos++] = AST_CONNECTED_LINE_VERSION; 08862 data[pos++] = 1; 08863 data[pos++] = 2;/* Version 1 did not have a version ie */ 08864 08865 res = party_id_build_data(data + pos, datalen - pos, &connected->id, 08866 "connected line", &ies, update ? &update->id : NULL); 08867 if (res < 0) { 08868 return -1; 08869 } 08870 pos += res; 08871 08872 /* Connected line source */ 08873 if (datalen < pos + (sizeof(data[0]) * 2) + sizeof(value)) { 08874 ast_log(LOG_WARNING, "No space left for connected line source\n"); 08875 return -1; 08876 } 08877 data[pos++] = AST_CONNECTED_LINE_SOURCE; 08878 data[pos++] = sizeof(value); 08879 value = htonl(connected->source); 08880 memcpy(data + pos, &value, sizeof(value)); 08881 pos += sizeof(value); 08882 08883 return pos; 08884 }
void ast_connected_line_copy_from_caller | ( | struct ast_party_connected_line * | dest, | |
const struct ast_party_caller * | src | |||
) |
Copy the caller information to the connected line information.
dest | Destination connected line information | |
src | Source caller information |
Definition at line 8443 of file channel.c.
References ast_party_caller::ani, ast_party_connected_line::ani, ast_party_caller::ani2, ast_party_connected_line::ani2, ast_party_id_copy(), ast_party_caller::id, and ast_party_connected_line::id.
Referenced by app_exec(), ast_do_pickup(), begin_dial_channel(), builtin_atxfer(), dial_exec_full(), dial_transfer(), do_forward(), feature_request_and_dial(), findmeexec(), local_call(), parked_call_exec(), ring_entry(), and wait_for_answer().
08444 { 08445 ast_party_id_copy(&dest->id, &src->id); 08446 ast_party_id_copy(&dest->ani, &src->ani); 08447 dest->ani2 = src->ani2; 08448 }
void ast_connected_line_copy_to_caller | ( | struct ast_party_caller * | dest, | |
const struct ast_party_connected_line * | src | |||
) |
Copy the connected line information to the caller information.
dest | Destination caller information | |
src | Source connected line information |
Definition at line 8450 of file channel.c.
References ast_party_connected_line::ani, ast_party_caller::ani, ast_party_connected_line::ani2, ast_party_caller::ani2, ast_party_id_copy(), ast_party_connected_line::id, and ast_party_caller::id.
Referenced by local_call(), and local_indicate().
08451 { 08452 ast_party_id_copy(&dest->id, &src->id); 08453 ast_party_id_copy(&dest->ani, &src->ani); 08454 08455 dest->ani2 = src->ani2; 08456 }
int ast_connected_line_parse_data | ( | const unsigned char * | data, | |
size_t | datalen, | |||
struct ast_party_connected_line * | connected | |||
) |
Parse connected line indication frame data.
data | Buffer with the frame data to parse | |
datalen | Size of the buffer | |
connected | Extracted connected line information |
0 | on success. | |
-1 | on error. |
Definition at line 8886 of file channel.c.
References AST_CONNECTED_LINE_ID_PRESENTATION, AST_CONNECTED_LINE_NAME, AST_CONNECTED_LINE_NAME_CHAR_SET, AST_CONNECTED_LINE_NAME_PRESENTATION, AST_CONNECTED_LINE_NAME_VALID, AST_CONNECTED_LINE_NUMBER, AST_CONNECTED_LINE_NUMBER_PLAN, AST_CONNECTED_LINE_NUMBER_PRESENTATION, AST_CONNECTED_LINE_NUMBER_VALID, AST_CONNECTED_LINE_SOURCE, AST_CONNECTED_LINE_SUBADDRESS, AST_CONNECTED_LINE_SUBADDRESS_ODD_EVEN, AST_CONNECTED_LINE_SUBADDRESS_TYPE, AST_CONNECTED_LINE_SUBADDRESS_VALID, AST_CONNECTED_LINE_TAG, AST_CONNECTED_LINE_VERSION, ast_free, ast_log(), ast_malloc, AST_PARTY_CHAR_SET_ISO8859_1, ast_party_name::char_set, ast_party_id_ies::combined_presentation, ast_party_connected_line::id, LOG_DEBUG, LOG_WARNING, ast_party_id::name, ast_party_id::number, ast_party_subaddress::odd_even_indicator, ast_party_number::plan, ast_party_number::presentation, ast_party_name::presentation, ast_party_connected_line::source, ast_party_subaddress::str, ast_party_number::str, ast_party_name::str, ast_party_id::subaddress, ast_party_id::tag, ast_party_subaddress::type, ast_party_subaddress::valid, ast_party_number::valid, ast_party_name::valid, and value.
Referenced by __ast_read(), ast_channel_connected_line_macro(), ast_indicate_data(), feature_request_and_dial(), socket_process(), wait_for_answer(), and wait_for_winner().
08887 { 08888 size_t pos; 08889 unsigned char ie_len; 08890 unsigned char ie_id; 08891 int32_t value; 08892 int frame_version = 1; 08893 int combined_presentation = 0; 08894 int got_combined_presentation = 0;/* TRUE if got a combined name and number presentation value. */ 08895 08896 for (pos = 0; pos < datalen; pos += ie_len) { 08897 if (datalen < pos + sizeof(ie_id) + sizeof(ie_len)) { 08898 ast_log(LOG_WARNING, "Invalid connected line update\n"); 08899 return -1; 08900 } 08901 ie_id = data[pos++]; 08902 ie_len = data[pos++]; 08903 if (datalen < pos + ie_len) { 08904 ast_log(LOG_WARNING, "Invalid connected line update\n"); 08905 return -1; 08906 } 08907 08908 switch (ie_id) { 08909 /* Connected line party frame version */ 08910 case AST_CONNECTED_LINE_VERSION: 08911 if (ie_len != 1) { 08912 ast_log(LOG_WARNING, "Invalid connected line frame version (%u)\n", 08913 (unsigned) ie_len); 08914 break; 08915 } 08916 frame_version = data[pos]; 08917 break; 08918 /* Connected line party id name */ 08919 case AST_CONNECTED_LINE_NAME: 08920 ast_free(connected->id.name.str); 08921 connected->id.name.str = ast_malloc(ie_len + 1); 08922 if (connected->id.name.str) { 08923 memcpy(connected->id.name.str, data + pos, ie_len); 08924 connected->id.name.str[ie_len] = 0; 08925 } 08926 break; 08927 case AST_CONNECTED_LINE_NAME_CHAR_SET: 08928 if (ie_len != 1) { 08929 ast_log(LOG_WARNING, "Invalid connected line name char set (%u)\n", 08930 (unsigned) ie_len); 08931 break; 08932 } 08933 connected->id.name.char_set = data[pos]; 08934 break; 08935 case AST_CONNECTED_LINE_NAME_PRESENTATION: 08936 if (ie_len != 1) { 08937 ast_log(LOG_WARNING, "Invalid connected line name presentation (%u)\n", 08938 (unsigned) ie_len); 08939 break; 08940 } 08941 connected->id.name.presentation = data[pos]; 08942 break; 08943 case AST_CONNECTED_LINE_NAME_VALID: 08944 if (ie_len != 1) { 08945 ast_log(LOG_WARNING, "Invalid connected line name valid (%u)\n", 08946 (unsigned) ie_len); 08947 break; 08948 } 08949 connected->id.name.valid = data[pos]; 08950 break; 08951 /* Connected line party id number */ 08952 case AST_CONNECTED_LINE_NUMBER: 08953 ast_free(connected->id.number.str); 08954 connected->id.number.str = ast_malloc(ie_len + 1); 08955 if (connected->id.number.str) { 08956 memcpy(connected->id.number.str, data + pos, ie_len); 08957 connected->id.number.str[ie_len] = 0; 08958 } 08959 break; 08960 case AST_CONNECTED_LINE_NUMBER_PLAN: 08961 if (ie_len != 1) { 08962 ast_log(LOG_WARNING, "Invalid connected line numbering plan (%u)\n", 08963 (unsigned) ie_len); 08964 break; 08965 } 08966 connected->id.number.plan = data[pos]; 08967 break; 08968 case AST_CONNECTED_LINE_NUMBER_PRESENTATION: 08969 if (ie_len != 1) { 08970 ast_log(LOG_WARNING, "Invalid connected line number presentation (%u)\n", 08971 (unsigned) ie_len); 08972 break; 08973 } 08974 connected->id.number.presentation = data[pos]; 08975 break; 08976 case AST_CONNECTED_LINE_NUMBER_VALID: 08977 if (ie_len != 1) { 08978 ast_log(LOG_WARNING, "Invalid connected line number valid (%u)\n", 08979 (unsigned) ie_len); 08980 break; 08981 } 08982 connected->id.number.valid = data[pos]; 08983 break; 08984 /* Connected line party id combined presentation */ 08985 case AST_CONNECTED_LINE_ID_PRESENTATION: 08986 if (ie_len != 1) { 08987 ast_log(LOG_WARNING, "Invalid connected line combined presentation (%u)\n", 08988 (unsigned) ie_len); 08989 break; 08990 } 08991 combined_presentation = data[pos]; 08992 got_combined_presentation = 1; 08993 break; 08994 /* Connected line party id subaddress */ 08995 case AST_CONNECTED_LINE_SUBADDRESS: 08996 ast_free(connected->id.subaddress.str); 08997 connected->id.subaddress.str = ast_malloc(ie_len + 1); 08998 if (connected->id.subaddress.str) { 08999 memcpy(connected->id.subaddress.str, data + pos, ie_len); 09000 connected->id.subaddress.str[ie_len] = 0; 09001 } 09002 break; 09003 case AST_CONNECTED_LINE_SUBADDRESS_TYPE: 09004 if (ie_len != 1) { 09005 ast_log(LOG_WARNING, "Invalid connected line type of subaddress (%u)\n", 09006 (unsigned) ie_len); 09007 break; 09008 } 09009 connected->id.subaddress.type = data[pos]; 09010 break; 09011 case AST_CONNECTED_LINE_SUBADDRESS_ODD_EVEN: 09012 if (ie_len != 1) { 09013 ast_log(LOG_WARNING, 09014 "Invalid connected line subaddress odd-even indicator (%u)\n", 09015 (unsigned) ie_len); 09016 break; 09017 } 09018 connected->id.subaddress.odd_even_indicator = data[pos]; 09019 break; 09020 case AST_CONNECTED_LINE_SUBADDRESS_VALID: 09021 if (ie_len != 1) { 09022 ast_log(LOG_WARNING, "Invalid connected line subaddress valid (%u)\n", 09023 (unsigned) ie_len); 09024 break; 09025 } 09026 connected->id.subaddress.valid = data[pos]; 09027 break; 09028 /* Connected line party tag */ 09029 case AST_CONNECTED_LINE_TAG: 09030 ast_free(connected->id.tag); 09031 connected->id.tag = ast_malloc(ie_len + 1); 09032 if (connected->id.tag) { 09033 memcpy(connected->id.tag, data + pos, ie_len); 09034 connected->id.tag[ie_len] = 0; 09035 } 09036 break; 09037 /* Connected line party source */ 09038 case AST_CONNECTED_LINE_SOURCE: 09039 if (ie_len != sizeof(value)) { 09040 ast_log(LOG_WARNING, "Invalid connected line source (%u)\n", 09041 (unsigned) ie_len); 09042 break; 09043 } 09044 memcpy(&value, data + pos, sizeof(value)); 09045 connected->source = ntohl(value); 09046 break; 09047 /* Connected line party unknown element */ 09048 default: 09049 ast_log(LOG_DEBUG, "Unknown connected line element: %u (%u)\n", 09050 (unsigned) ie_id, (unsigned) ie_len); 09051 break; 09052 } 09053 } 09054 09055 switch (frame_version) { 09056 case 1: 09057 /* 09058 * The other end is an earlier version that we need to adjust 09059 * for compatibility. 09060 */ 09061 connected->id.name.valid = 1; 09062 connected->id.name.char_set = AST_PARTY_CHAR_SET_ISO8859_1; 09063 connected->id.number.valid = 1; 09064 if (got_combined_presentation) { 09065 connected->id.name.presentation = combined_presentation; 09066 connected->id.number.presentation = combined_presentation; 09067 } 09068 break; 09069 case 2: 09070 /* The other end is at the same level as we are. */ 09071 break; 09072 default: 09073 /* 09074 * The other end is newer than we are. 09075 * We need to assume that they are compatible with us. 09076 */ 09077 ast_log(LOG_DEBUG, "Connected line frame has newer version: %u\n", 09078 (unsigned) frame_version); 09079 break; 09080 } 09081 09082 return 0; 09083 }
AST_DATA_STRUCTURE | ( | ast_channel | , | |
DATA_EXPORT_CHANNEL | ||||
) |
void ast_deactivate_generator | ( | struct ast_channel * | chan | ) |
Deactivate an active generator
Definition at line 3107 of file channel.c.
References ast_channel_lock, ast_channel_unlock, and deactivate_generator_nolock().
Referenced by __ast_read(), app_exec(), ast_openstream_full(), ast_playtones_stop(), ast_quiet_chan(), ast_read_generator_actions(), ast_tonepair_stop(), ast_write(), cb_events(), channel_spy(), dial_exec_full(), generator_force(), local_ast_moh_stop(), old_milliwatt_exec(), transmit_audio(), and wait_for_answer().
03108 { 03109 ast_channel_lock(chan); 03110 deactivate_generator_nolock(chan); 03111 ast_channel_unlock(chan); 03112 }
int ast_do_masquerade | ( | struct ast_channel * | original | ) |
Masquerade a channel.
Start masquerading a channel.
< TRUE if the clonechan was a zombie before the masquerade.
Definition at line 6546 of file channel.c.
References __ast_change_name_nolink(), ast_channel::_bridge, ast_channel::_softhangup, ast_channel::_state, accountcode, ast_channel::adsicpe, ast_channel::alertpipe, ao2_link, ao2_lock, ao2_unlink, ao2_unlock, ast_app_group_update(), ast_autochan_new_channel(), ast_bridge_end_dtmf(), ast_bridged_channel(), ast_cause2str(), AST_CEL_BRIDGE_UPDATE, ast_cel_report_event(), ast_channel_datastore_find(), ast_channel_datastore_remove(), ast_channel_lock, ast_channel_lock_both, AST_CHANNEL_NAME, ast_channel_ref, ast_channel_set_fd(), ast_channel_set_linkgroup(), ast_channel_unlock, ast_channel_unref, ast_clear_flag, AST_CONTROL_SRCCHANGE, AST_CONTROL_UNHOLD, ast_copy_string(), ast_datastore_free(), ast_debug, AST_FLAG_BLOCKING, AST_FLAG_DISABLE_DEVSTATE_CACHE, AST_FLAG_EXCEPTION, AST_FLAG_MOH, AST_FLAG_OUTGOING, AST_FLAG_ZOMBIE, AST_GENERATOR_FD, ast_getformatname(), ast_indicate(), ast_kill_tech, AST_LIST_APPEND_LIST, AST_LIST_FIRST, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_HEAD_NOLOCK, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), ast_manager_event, ast_manager_event_multichan, AST_MAX_FDS, ast_moh_start(), ast_null_frame, ast_queue_frame(), ast_set_flag, ast_set_read_format(), ast_set_write_format(), AST_SOFTHANGUP_DEV, ast_state2str(), ast_string_field_set, ast_test_flag, AST_TIMING_FD, ast_channel::blocker, ast_channel::caller, ast_channel::cdr, ast_datastore_info::chan_fixup, channels, clone_variables(), ast_channel::connected, ast_datastore::data, ast_channel::dialed, errno, EVENT_FLAG_CALL, ast_channel::fdno, ast_channel::fds, ast_channel_tech::fixup, free_translation(), ast_channel_tech::hangup, ast_channel::hangupcause, ast_datastore::info, language, LOG_WARNING, ast_channel::masq, ast_channel::masqr, masquerade_colp_transfer(), ast_channel::monitor, musicclass, ast_channel::nativeformats, parkinglot, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::redirecting, report_new_callerid(), S_OR, ast_channel::sending_dtmf_digit, ast_channel::sending_dtmf_tv, ast_channel::tech, ast_channel::tech_pvt, ast_channel::timingfd, xfer_masquerade_ds::transferee_held, ast_channel_tech::type, ast_cdr::uniqueid, ast_channel::visible_indication, ast_channel::whentohangup, and ast_channel::writeformat.
Referenced by __ast_read(), ast_async_goto(), ast_do_pickup(), ast_hangup(), ast_waitfor_nandfds(), ast_write(), builtin_atxfer(), check_bridge(), check_goto_on_transfer(), do_bridge_masquerade(), handle_invite_replaces(), iax_park(), local_attended_transfer(), masq_park_call(), and sip_park().
06547 { 06548 int x; 06549 int i; 06550 int origstate; 06551 unsigned int orig_disablestatecache; 06552 unsigned int clone_disablestatecache; 06553 int visible_indication; 06554 int moh_is_playing; 06555 int clone_was_zombie = 0;/*!< TRUE if the clonechan was a zombie before the masquerade. */ 06556 struct ast_frame *current; 06557 const struct ast_channel_tech *t; 06558 void *t_pvt; 06559 union { 06560 struct ast_party_dialed dialed; 06561 struct ast_party_caller caller; 06562 struct ast_party_connected_line connected; 06563 struct ast_party_redirecting redirecting; 06564 } exchange; 06565 struct ast_channel *clonechan, *chans[2]; 06566 struct ast_channel *bridged; 06567 struct ast_cdr *cdr; 06568 struct ast_datastore *xfer_ds; 06569 struct xfer_masquerade_ds *xfer_colp; 06570 format_t rformat; 06571 format_t wformat; 06572 format_t tmp_format; 06573 char newn[AST_CHANNEL_NAME]; 06574 char orig[AST_CHANNEL_NAME]; 06575 char masqn[AST_CHANNEL_NAME]; 06576 char zombn[AST_CHANNEL_NAME]; 06577 char clone_sending_dtmf_digit; 06578 struct timeval clone_sending_dtmf_tv; 06579 06580 /* XXX This operation is a bit odd. We're essentially putting the guts of 06581 * the clone channel into the original channel. Start by killing off the 06582 * original channel's backend. While the features are nice, which is the 06583 * reason we're keeping it, it's still awesomely weird. XXX */ 06584 06585 /* 06586 * The reasoning for the channels ao2_container lock here is 06587 * complex. 06588 * 06589 * There is a race condition that exists for this function. 06590 * Since all pvt and channel locks must be let go before calling 06591 * ast_do_masquerade, it is possible that it could be called 06592 * multiple times for the same channel. In order to prevent the 06593 * race condition with competing threads to do the masquerade 06594 * and new masquerade attempts, the channels container must be 06595 * locked for the entire masquerade. The original and clonechan 06596 * need to be unlocked earlier to avoid potential deadlocks with 06597 * the chan_local deadlock avoidance method. 06598 * 06599 * The container lock blocks competing masquerade attempts from 06600 * starting as well as being necessary for proper locking order 06601 * because the channels must to be unlinked to change their 06602 * names. 06603 * 06604 * The original and clonechan locks must be held while the 06605 * channel contents are shuffled around for the masquerade. 06606 * 06607 * The masq and masqr pointers need to be left alone until the 06608 * masquerade has restabilized the channels to prevent another 06609 * masquerade request until the AST_FLAG_ZOMBIE can be set on 06610 * the clonechan. 06611 */ 06612 ao2_lock(channels); 06613 06614 /* 06615 * Lock the original channel to determine if the masquerade is 06616 * still required. 06617 */ 06618 ast_channel_lock(original); 06619 06620 clonechan = original->masq; 06621 if (!clonechan) { 06622 /* 06623 * The masq is already completed by another thread or never 06624 * needed to be done to begin with. 06625 */ 06626 ast_channel_unlock(original); 06627 ao2_unlock(channels); 06628 return 0; 06629 } 06630 06631 /* Bump the refs to ensure that they won't dissapear on us. */ 06632 ast_channel_ref(original); 06633 ast_channel_ref(clonechan); 06634 06635 /* unlink from channels container as name (which is the hash value) will change */ 06636 ao2_unlink(channels, original); 06637 ao2_unlink(channels, clonechan); 06638 06639 /* Get any transfer masquerade connected line exchange data. */ 06640 xfer_ds = ast_channel_datastore_find(original, &xfer_ds_info, NULL); 06641 if (xfer_ds) { 06642 ast_channel_datastore_remove(original, xfer_ds); 06643 xfer_colp = xfer_ds->data; 06644 } else { 06645 xfer_colp = NULL; 06646 } 06647 06648 moh_is_playing = ast_test_flag(original, AST_FLAG_MOH); 06649 06650 /* 06651 * Stop any visible indication on the original channel so we can 06652 * transfer it to the clonechan taking the original's place. 06653 */ 06654 visible_indication = original->visible_indication; 06655 ast_channel_unlock(original); 06656 ast_indicate(original, -1); 06657 06658 /* 06659 * Release any hold on the transferee channel before going any 06660 * further with the masquerade. 06661 */ 06662 if (xfer_colp && xfer_colp->transferee_held) { 06663 ast_indicate(clonechan, AST_CONTROL_UNHOLD); 06664 } 06665 06666 /* Start the masquerade channel contents rearangement. */ 06667 ast_channel_lock_both(original, clonechan); 06668 06669 ast_debug(4, "Actually Masquerading %s(%u) into the structure of %s(%u)\n", 06670 clonechan->name, clonechan->_state, original->name, original->_state); 06671 06672 chans[0] = clonechan; 06673 chans[1] = original; 06674 ast_manager_event_multichan(EVENT_FLAG_CALL, "Masquerade", 2, chans, 06675 "Clone: %s\r\n" 06676 "CloneState: %s\r\n" 06677 "Original: %s\r\n" 06678 "OriginalState: %s\r\n", 06679 clonechan->name, ast_state2str(clonechan->_state), original->name, ast_state2str(original->_state)); 06680 06681 /* 06682 * Remember the original read/write formats. We turn off any 06683 * translation on either one 06684 */ 06685 rformat = original->readformat; 06686 wformat = original->writeformat; 06687 free_translation(clonechan); 06688 free_translation(original); 06689 06690 /* Save the current DTMF digit being sent if any. */ 06691 clone_sending_dtmf_digit = clonechan->sending_dtmf_digit; 06692 clone_sending_dtmf_tv = clonechan->sending_dtmf_tv; 06693 06694 /* Save the original name */ 06695 ast_copy_string(orig, original->name, sizeof(orig)); 06696 /* Save the new name */ 06697 ast_copy_string(newn, clonechan->name, sizeof(newn)); 06698 /* Create the masq name */ 06699 snprintf(masqn, sizeof(masqn), "%s<MASQ>", newn); 06700 06701 /* Mangle the name of the clone channel */ 06702 __ast_change_name_nolink(clonechan, masqn); 06703 06704 /* Copy the name from the clone channel */ 06705 __ast_change_name_nolink(original, newn); 06706 06707 /* share linked id's */ 06708 ast_channel_set_linkgroup(original, clonechan); 06709 06710 /* Swap the technologies */ 06711 t = original->tech; 06712 original->tech = clonechan->tech; 06713 clonechan->tech = t; 06714 06715 t_pvt = original->tech_pvt; 06716 original->tech_pvt = clonechan->tech_pvt; 06717 clonechan->tech_pvt = t_pvt; 06718 06719 /* Swap the cdrs */ 06720 cdr = original->cdr; 06721 /* swap cdr uniqueid between channels, to get cdr uniqueid = channel uniqueid */ 06722 ast_copy_string(clonechan->cdr->uniqueid, cdr->uniqueid, sizeof(cdr->uniqueid)); 06723 original->cdr = clonechan->cdr; 06724 clonechan->cdr = cdr; 06725 06726 /* Swap the alertpipes */ 06727 for (i = 0; i < 2; i++) { 06728 x = original->alertpipe[i]; 06729 original->alertpipe[i] = clonechan->alertpipe[i]; 06730 clonechan->alertpipe[i] = x; 06731 } 06732 06733 /* 06734 * Swap the readq's. The end result should be this: 06735 * 06736 * 1) All frames should be on the new (original) channel. 06737 * 2) Any frames that were already on the new channel before this 06738 * masquerade need to be at the end of the readq, after all of the 06739 * frames on the old (clone) channel. 06740 * 3) The alertpipe needs to get poked for every frame that was already 06741 * on the new channel, since we are now using the alert pipe from the 06742 * old (clone) channel. 06743 */ 06744 { 06745 AST_LIST_HEAD_NOLOCK(, ast_frame) tmp_readq; 06746 06747 AST_LIST_HEAD_INIT_NOLOCK(&tmp_readq); 06748 AST_LIST_APPEND_LIST(&tmp_readq, &original->readq, frame_list); 06749 AST_LIST_APPEND_LIST(&original->readq, &clonechan->readq, frame_list); 06750 06751 while ((current = AST_LIST_REMOVE_HEAD(&tmp_readq, frame_list))) { 06752 AST_LIST_INSERT_TAIL(&original->readq, current, frame_list); 06753 if (original->alertpipe[1] > -1) { 06754 int poke = 0; 06755 06756 if (write(original->alertpipe[1], &poke, sizeof(poke)) < 0) { 06757 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 06758 } 06759 } 06760 } 06761 } 06762 06763 /* Swap the raw formats */ 06764 tmp_format = original->rawreadformat; 06765 original->rawreadformat = clonechan->rawreadformat; 06766 clonechan->rawreadformat = tmp_format; 06767 06768 tmp_format = original->rawwriteformat; 06769 original->rawwriteformat = clonechan->rawwriteformat; 06770 clonechan->rawwriteformat = tmp_format; 06771 06772 clonechan->_softhangup = AST_SOFTHANGUP_DEV; 06773 06774 /* And of course, so does our current state. Note we need not 06775 call ast_setstate since the event manager doesn't really consider 06776 these separate. We do this early so that the clone has the proper 06777 state of the original channel. */ 06778 origstate = original->_state; 06779 original->_state = clonechan->_state; 06780 clonechan->_state = origstate; 06781 06782 /* And the swap the cachable state too. Otherwise we'd start caching 06783 * Local channels and ignoring real ones. */ 06784 orig_disablestatecache = ast_test_flag(original, AST_FLAG_DISABLE_DEVSTATE_CACHE); 06785 clone_disablestatecache = ast_test_flag(clonechan, AST_FLAG_DISABLE_DEVSTATE_CACHE); 06786 if (orig_disablestatecache != clone_disablestatecache) { 06787 if (orig_disablestatecache) { 06788 ast_clear_flag(original, AST_FLAG_DISABLE_DEVSTATE_CACHE); 06789 ast_set_flag(clonechan, AST_FLAG_DISABLE_DEVSTATE_CACHE); 06790 } else { 06791 ast_set_flag(original, AST_FLAG_DISABLE_DEVSTATE_CACHE); 06792 ast_clear_flag(clonechan, AST_FLAG_DISABLE_DEVSTATE_CACHE); 06793 } 06794 } 06795 06796 /* Mangle the name of the clone channel */ 06797 snprintf(zombn, sizeof(zombn), "%s<ZOMBIE>", orig); /* quick, hide the brains! */ 06798 __ast_change_name_nolink(clonechan, zombn); 06799 06800 /* Update the type. */ 06801 t_pvt = original->monitor; 06802 original->monitor = clonechan->monitor; 06803 clonechan->monitor = t_pvt; 06804 06805 /* Keep the same language. */ 06806 ast_string_field_set(original, language, clonechan->language); 06807 06808 /* Keep the same parkinglot. */ 06809 ast_string_field_set(original, parkinglot, clonechan->parkinglot); 06810 06811 /* Copy the FD's other than the generator fd */ 06812 for (x = 0; x < AST_MAX_FDS; x++) { 06813 if (x != AST_GENERATOR_FD) 06814 ast_channel_set_fd(original, x, clonechan->fds[x]); 06815 } 06816 06817 ast_app_group_update(clonechan, original); 06818 06819 /* Move data stores over */ 06820 if (AST_LIST_FIRST(&clonechan->datastores)) { 06821 struct ast_datastore *ds; 06822 /* We use a safe traversal here because some fixup routines actually 06823 * remove the datastore from the list and free them. 06824 */ 06825 AST_LIST_TRAVERSE_SAFE_BEGIN(&clonechan->datastores, ds, entry) { 06826 if (ds->info->chan_fixup) 06827 ds->info->chan_fixup(ds->data, clonechan, original); 06828 } 06829 AST_LIST_TRAVERSE_SAFE_END; 06830 AST_LIST_APPEND_LIST(&original->datastores, &clonechan->datastores, entry); 06831 } 06832 06833 ast_autochan_new_channel(clonechan, original); 06834 06835 clone_variables(original, clonechan); 06836 /* Presense of ADSI capable CPE follows clone */ 06837 original->adsicpe = clonechan->adsicpe; 06838 /* Bridge remains the same */ 06839 /* CDR fields remain the same */ 06840 /* XXX What about blocking, softhangup, blocker, and lock and blockproc? XXX */ 06841 /* Application and data remain the same */ 06842 /* Clone exception becomes real one, as with fdno */ 06843 ast_set_flag(original, ast_test_flag(clonechan, AST_FLAG_EXCEPTION | AST_FLAG_OUTGOING)); 06844 original->fdno = clonechan->fdno; 06845 /* Schedule context remains the same */ 06846 /* Stream stuff stays the same */ 06847 /* Keep the original state. The fixup code will need to work with it most likely */ 06848 06849 /* 06850 * Just swap the whole structures, nevermind the allocations, 06851 * they'll work themselves out. 06852 */ 06853 exchange.dialed = original->dialed; 06854 original->dialed = clonechan->dialed; 06855 clonechan->dialed = exchange.dialed; 06856 06857 exchange.caller = original->caller; 06858 original->caller = clonechan->caller; 06859 clonechan->caller = exchange.caller; 06860 06861 exchange.connected = original->connected; 06862 original->connected = clonechan->connected; 06863 clonechan->connected = exchange.connected; 06864 06865 exchange.redirecting = original->redirecting; 06866 original->redirecting = clonechan->redirecting; 06867 clonechan->redirecting = exchange.redirecting; 06868 06869 report_new_callerid(original); 06870 06871 /* Restore original timing file descriptor */ 06872 ast_channel_set_fd(original, AST_TIMING_FD, original->timingfd); 06873 06874 /* Our native formats are different now */ 06875 original->nativeformats = clonechan->nativeformats; 06876 06877 /* Context, extension, priority, app data, jump table, remain the same */ 06878 /* pvt switches. pbx stays the same, as does next */ 06879 06880 /* Set the write format */ 06881 ast_set_write_format(original, wformat); 06882 06883 /* Set the read format */ 06884 ast_set_read_format(original, rformat); 06885 06886 /* Copy the music class */ 06887 ast_string_field_set(original, musicclass, clonechan->musicclass); 06888 06889 /* Copy whentohangup time */ 06890 original->whentohangup = clonechan->whentohangup; 06891 06892 /* copy over accuntcode and set peeraccount across the bridge */ 06893 ast_string_field_set(original, accountcode, S_OR(clonechan->accountcode, "")); 06894 if (original->_bridge) { 06895 /* XXX - should we try to lock original->_bridge here? */ 06896 ast_string_field_set(original->_bridge, peeraccount, S_OR(clonechan->accountcode, "")); 06897 ast_cel_report_event(original, AST_CEL_BRIDGE_UPDATE, NULL, NULL, NULL); 06898 } 06899 06900 ast_debug(1, "Putting channel %s in %s/%s formats\n", original->name, 06901 ast_getformatname(wformat), ast_getformatname(rformat)); 06902 06903 /* Fixup the original clonechan's physical side */ 06904 if (original->tech->fixup && original->tech->fixup(clonechan, original)) { 06905 ast_log(LOG_WARNING, "Channel type '%s' could not fixup channel %s, strange things may happen. (clonechan)\n", 06906 original->tech->type, original->name); 06907 } 06908 06909 /* Fixup the original original's physical side */ 06910 if (clonechan->tech->fixup && clonechan->tech->fixup(original, clonechan)) { 06911 ast_log(LOG_WARNING, "Channel type '%s' could not fixup channel %s, strange things may happen. (original)\n", 06912 clonechan->tech->type, clonechan->name); 06913 } 06914 06915 /* 06916 * Now, at this point, the "clone" channel is totally F'd up. 06917 * We mark it as a zombie so nothing tries to touch it. If it's 06918 * already been marked as a zombie, then we must free it (since 06919 * it already is considered invalid). 06920 * 06921 * This must be done before we unlock clonechan to prevent 06922 * setting up another masquerade on the clonechan. 06923 */ 06924 if (ast_test_flag(clonechan, AST_FLAG_ZOMBIE)) { 06925 clone_was_zombie = 1; 06926 } else { 06927 ast_set_flag(clonechan, AST_FLAG_ZOMBIE); 06928 ast_queue_frame(clonechan, &ast_null_frame); 06929 } 06930 06931 /* clear the masquerade channels */ 06932 original->masq = NULL; 06933 clonechan->masqr = NULL; 06934 06935 /* 06936 * When we unlock original here, it can be immediately setup to 06937 * masquerade again or hungup. The new masquerade or hangup 06938 * will not actually happen until we release the channels 06939 * container lock. 06940 */ 06941 ast_channel_unlock(original); 06942 06943 /* Disconnect the original original's physical side */ 06944 if (clonechan->tech->hangup && clonechan->tech->hangup(clonechan)) { 06945 ast_log(LOG_WARNING, "Hangup failed! Strange things may happen!\n"); 06946 } else { 06947 /* 06948 * We just hung up the original original's physical side of the 06949 * channel. Set the new zombie to use the kill channel driver 06950 * for safety. 06951 */ 06952 clonechan->tech = &ast_kill_tech; 06953 } 06954 06955 ast_channel_unlock(clonechan); 06956 06957 if (clone_sending_dtmf_digit) { 06958 /* 06959 * The clonechan was sending a DTMF digit that was not completed 06960 * before the masquerade. 06961 */ 06962 ast_bridge_end_dtmf(original, clone_sending_dtmf_digit, clone_sending_dtmf_tv, 06963 "masquerade"); 06964 } 06965 06966 /* 06967 * If an indication is currently playing, maintain it on the 06968 * channel that is taking the place of original. 06969 * 06970 * This is needed because the masquerade is swapping out the 06971 * internals of the channel, and the new channel private data 06972 * needs to be made aware of the current visible indication 06973 * (RINGING, CONGESTION, etc.) 06974 */ 06975 if (visible_indication) { 06976 ast_indicate(original, visible_indication); 06977 } 06978 06979 /* if moh is playing on the original channel then it needs to be 06980 maintained on the channel that is replacing it. */ 06981 if (moh_is_playing) { 06982 ast_moh_start(original, NULL, NULL); 06983 } 06984 06985 ast_channel_lock(original); 06986 06987 /* Signal any blocker */ 06988 if (ast_test_flag(original, AST_FLAG_BLOCKING)) { 06989 pthread_kill(original->blocker, SIGURG); 06990 } 06991 06992 ast_debug(1, "Done Masquerading %s (%u)\n", original->name, original->_state); 06993 06994 if ((bridged = ast_bridged_channel(original))) { 06995 ast_channel_ref(bridged); 06996 ast_channel_unlock(original); 06997 ast_indicate(bridged, AST_CONTROL_SRCCHANGE); 06998 ast_channel_unref(bridged); 06999 } else { 07000 ast_channel_unlock(original); 07001 } 07002 ast_indicate(original, AST_CONTROL_SRCCHANGE); 07003 07004 if (xfer_colp) { 07005 /* 07006 * After the masquerade, the original channel pointer actually 07007 * points to the new transferee channel and the bridged channel 07008 * is still the intended transfer target party. 07009 */ 07010 masquerade_colp_transfer(original, xfer_colp); 07011 } 07012 07013 if (xfer_ds) { 07014 ast_datastore_free(xfer_ds); 07015 } 07016 07017 if (clone_was_zombie) { 07018 ast_channel_lock(clonechan); 07019 ast_debug(1, "Destroying channel clone '%s'\n", clonechan->name); 07020 ast_manager_event(clonechan, EVENT_FLAG_CALL, "Hangup", 07021 "Channel: %s\r\n" 07022 "Uniqueid: %s\r\n" 07023 "Cause: %d\r\n" 07024 "Cause-txt: %s\r\n", 07025 clonechan->name, 07026 clonechan->uniqueid, 07027 clonechan->hangupcause, 07028 ast_cause2str(clonechan->hangupcause) 07029 ); 07030 ast_channel_unlock(clonechan); 07031 07032 /* 07033 * Drop the system reference to destroy the channel since it is 07034 * already unlinked. 07035 */ 07036 ast_channel_unref(clonechan); 07037 } else { 07038 ao2_link(channels, clonechan); 07039 } 07040 07041 ao2_link(channels, original); 07042 ao2_unlock(channels); 07043 07044 /* Release our held safety references. */ 07045 ast_channel_unref(original); 07046 ast_channel_unref(clonechan); 07047 07048 return 0; 07049 }
static void ast_dummy_channel_destructor | ( | void * | obj | ) | [static] |
Free a dummy channel structure.
Definition at line 2530 of file channel.c.
References ast_cdr_discard(), ast_datastore_free(), AST_LIST_REMOVE_HEAD, ast_party_caller_free(), ast_party_connected_line_free(), ast_party_dialed_free(), ast_party_redirecting_free(), ast_string_field_free_memory, ast_var_delete(), ast_channel::caller, ast_channel::cdr, ast_channel::connected, ast_channel::dialed, ast_channel::redirecting, and ast_channel::varshead.
Referenced by __ast_dummy_channel_alloc().
02531 { 02532 struct ast_channel *chan = obj; 02533 struct ast_var_t *vardata; 02534 struct varshead *headp; 02535 struct ast_datastore *datastore; 02536 02537 /* Get rid of each of the data stores on the channel */ 02538 while ((datastore = AST_LIST_REMOVE_HEAD(&chan->datastores, entry))) { 02539 /* Free the data store */ 02540 ast_datastore_free(datastore); 02541 } 02542 02543 headp = &chan->varshead; 02544 02545 ast_party_dialed_free(&chan->dialed); 02546 ast_party_caller_free(&chan->caller); 02547 ast_party_connected_line_free(&chan->connected); 02548 ast_party_redirecting_free(&chan->redirecting); 02549 02550 /* loop over the variables list, freeing all data and deleting list items */ 02551 /* no need to lock the list, as the channel is already locked */ 02552 while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries))) 02553 ast_var_delete(vardata); 02554 02555 if (chan->cdr) { 02556 ast_cdr_discard(chan->cdr); 02557 chan->cdr = NULL; 02558 } 02559 02560 ast_string_field_free_memory(chan); 02561 }
static enum ast_bridge_result ast_generic_bridge | ( | struct ast_channel * | c0, | |
struct ast_channel * | c1, | |||
struct ast_bridge_config * | config, | |||
struct ast_frame ** | fo, | |||
struct ast_channel ** | rc | |||
) | [static] |
Definition at line 7203 of file channel.c.
References ast_channel::_bridge, ast_channel::_softhangup, AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_IGNORE_SIGS, AST_BRIDGE_RETRY, ast_channel_clear_softhangup(), ast_channel_connected_line_macro(), ast_channel_lock_both, ast_channel_redirecting_macro(), ast_channel_unlock, ast_clear_flag, AST_CONTROL_AOC, AST_CONTROL_CONNECTED_LINE, AST_CONTROL_HOLD, AST_CONTROL_REDIRECTING, AST_CONTROL_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_T38_PARAMETERS, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, ast_debug, AST_FEATURE_WARNING_ACTIVE, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_HTML, AST_FRAME_IMAGE, AST_FRAME_MODEM, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree, ast_indicate_data(), ast_jb_do_usecheck(), ast_jb_empty_and_reset(), ast_jb_get_and_deliver(), ast_jb_get_when_to_wakeup(), ast_jb_put(), ast_poll_channel_add(), ast_poll_channel_del(), ast_read(), ast_samp2tv(), ast_set_flag, AST_SOFTHANGUP_UNBRIDGE, ast_test_flag, ast_tvadd(), ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), ast_waitfor_n(), ast_write(), ast_frame::data, ast_frame::datalen, ast_bridge_config::feature_timer, ast_bridge_config::flags, ast_frame::frametype, ast_frame_subclass::integer, ast_channel::nativeformats, ast_bridge_config::nexteventts, ast_frame::ptr, ast_frame::subclass, ast_channel::tech_pvt, and ast_bridge_config::timelimit.
Referenced by ast_channel_bridge().
07206 { 07207 /* Copy voice back and forth between the two channels. */ 07208 struct ast_channel *cs[3]; 07209 struct ast_frame *f; 07210 enum ast_bridge_result res = AST_BRIDGE_COMPLETE; 07211 format_t o0nativeformats; 07212 format_t o1nativeformats; 07213 int watch_c0_dtmf; 07214 int watch_c1_dtmf; 07215 void *pvt0, *pvt1; 07216 /* Indicates whether a frame was queued into a jitterbuffer */ 07217 int frame_put_in_jb = 0; 07218 int jb_in_use; 07219 int to; 07220 07221 cs[0] = c0; 07222 cs[1] = c1; 07223 pvt0 = c0->tech_pvt; 07224 pvt1 = c1->tech_pvt; 07225 o0nativeformats = c0->nativeformats; 07226 o1nativeformats = c1->nativeformats; 07227 watch_c0_dtmf = config->flags & AST_BRIDGE_DTMF_CHANNEL_0; 07228 watch_c1_dtmf = config->flags & AST_BRIDGE_DTMF_CHANNEL_1; 07229 07230 /* Check the need of a jitterbuffer for each channel */ 07231 jb_in_use = ast_jb_do_usecheck(c0, c1); 07232 if (jb_in_use) 07233 ast_jb_empty_and_reset(c0, c1); 07234 07235 ast_poll_channel_add(c0, c1); 07236 07237 if (config->feature_timer > 0 && ast_tvzero(config->nexteventts)) { 07238 /* nexteventts is not set when the bridge is not scheduled to 07239 * break, so calculate when the bridge should possibly break 07240 * if a partial feature match timed out */ 07241 config->nexteventts = ast_tvadd(ast_tvnow(), ast_samp2tv(config->feature_timer, 1000)); 07242 } 07243 07244 for (;;) { 07245 struct ast_channel *who, *other; 07246 07247 if ((c0->tech_pvt != pvt0) || (c1->tech_pvt != pvt1) || 07248 (o0nativeformats != c0->nativeformats) || 07249 (o1nativeformats != c1->nativeformats)) { 07250 /* Check for Masquerade, codec changes, etc */ 07251 res = AST_BRIDGE_RETRY; 07252 break; 07253 } 07254 if (config->nexteventts.tv_sec) { 07255 to = ast_tvdiff_ms(config->nexteventts, ast_tvnow()); 07256 if (to <= 0) { 07257 if (config->timelimit && !config->feature_timer && !ast_test_flag(config, AST_FEATURE_WARNING_ACTIVE)) { 07258 res = AST_BRIDGE_RETRY; 07259 /* generic bridge ending to play warning */ 07260 ast_set_flag(config, AST_FEATURE_WARNING_ACTIVE); 07261 } else if (config->feature_timer) { 07262 /* feature timer expired - make sure we do not play warning */ 07263 ast_clear_flag(config, AST_FEATURE_WARNING_ACTIVE); 07264 res = AST_BRIDGE_RETRY; 07265 } else { 07266 res = AST_BRIDGE_COMPLETE; 07267 } 07268 break; 07269 } 07270 } else { 07271 /* If a feature has been started and the bridge is configured to 07272 * to not break, leave the channel bridge when the feature timer 07273 * time has elapsed so the DTMF will be sent to the other side. 07274 */ 07275 if (!ast_tvzero(config->nexteventts)) { 07276 int diff = ast_tvdiff_ms(config->nexteventts, ast_tvnow()); 07277 if (diff <= 0) { 07278 res = AST_BRIDGE_RETRY; 07279 break; 07280 } 07281 } 07282 to = -1; 07283 } 07284 /* Calculate the appropriate max sleep interval - in general, this is the time, 07285 left to the closest jb delivery moment */ 07286 if (jb_in_use) 07287 to = ast_jb_get_when_to_wakeup(c0, c1, to); 07288 who = ast_waitfor_n(cs, 2, &to); 07289 if (!who) { 07290 /* No frame received within the specified timeout - check if we have to deliver now */ 07291 if (jb_in_use) 07292 ast_jb_get_and_deliver(c0, c1); 07293 if ((c0->_softhangup | c1->_softhangup) & AST_SOFTHANGUP_UNBRIDGE) {/* Bit operators are intentional. */ 07294 if (c0->_softhangup & AST_SOFTHANGUP_UNBRIDGE) { 07295 ast_channel_clear_softhangup(c0, AST_SOFTHANGUP_UNBRIDGE); 07296 } 07297 if (c1->_softhangup & AST_SOFTHANGUP_UNBRIDGE) { 07298 ast_channel_clear_softhangup(c1, AST_SOFTHANGUP_UNBRIDGE); 07299 } 07300 ast_channel_lock_both(c0, c1); 07301 c0->_bridge = c1; 07302 c1->_bridge = c0; 07303 ast_channel_unlock(c0); 07304 ast_channel_unlock(c1); 07305 } 07306 continue; 07307 } 07308 f = ast_read(who); 07309 if (!f) { 07310 *fo = NULL; 07311 *rc = who; 07312 ast_debug(1, "Didn't get a frame from channel: %s\n",who->name); 07313 break; 07314 } 07315 07316 other = (who == c0) ? c1 : c0; /* the 'other' channel */ 07317 /* Try add the frame info the who's bridged channel jitterbuff */ 07318 if (jb_in_use) 07319 frame_put_in_jb = !ast_jb_put(other, f); 07320 07321 if ((f->frametype == AST_FRAME_CONTROL) && !(config->flags & AST_BRIDGE_IGNORE_SIGS)) { 07322 int bridge_exit = 0; 07323 07324 switch (f->subclass.integer) { 07325 case AST_CONTROL_AOC: 07326 ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen); 07327 break; 07328 case AST_CONTROL_REDIRECTING: 07329 if (ast_channel_redirecting_macro(who, other, f, other == c0, 1)) { 07330 ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen); 07331 } 07332 break; 07333 case AST_CONTROL_CONNECTED_LINE: 07334 if (ast_channel_connected_line_macro(who, other, f, other == c0, 1)) { 07335 ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen); 07336 } 07337 break; 07338 case AST_CONTROL_HOLD: 07339 case AST_CONTROL_UNHOLD: 07340 case AST_CONTROL_VIDUPDATE: 07341 case AST_CONTROL_SRCUPDATE: 07342 case AST_CONTROL_SRCCHANGE: 07343 case AST_CONTROL_T38_PARAMETERS: 07344 ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen); 07345 if (jb_in_use) { 07346 ast_jb_empty_and_reset(c0, c1); 07347 } 07348 break; 07349 default: 07350 *fo = f; 07351 *rc = who; 07352 bridge_exit = 1; 07353 ast_debug(1, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass.integer, who->name); 07354 break; 07355 } 07356 if (bridge_exit) 07357 break; 07358 } 07359 if ((f->frametype == AST_FRAME_VOICE) || 07360 (f->frametype == AST_FRAME_DTMF_BEGIN) || 07361 (f->frametype == AST_FRAME_DTMF) || 07362 (f->frametype == AST_FRAME_VIDEO) || 07363 (f->frametype == AST_FRAME_IMAGE) || 07364 (f->frametype == AST_FRAME_HTML) || 07365 (f->frametype == AST_FRAME_MODEM) || 07366 (f->frametype == AST_FRAME_TEXT)) { 07367 /* monitored dtmf causes exit from bridge */ 07368 int monitored_source = (who == c0) ? watch_c0_dtmf : watch_c1_dtmf; 07369 07370 if (monitored_source && 07371 (f->frametype == AST_FRAME_DTMF_END || 07372 f->frametype == AST_FRAME_DTMF_BEGIN)) { 07373 *fo = f; 07374 *rc = who; 07375 ast_debug(1, "Got DTMF %s on channel (%s)\n", 07376 f->frametype == AST_FRAME_DTMF_END ? "end" : "begin", 07377 who->name); 07378 07379 break; 07380 } 07381 /* Write immediately frames, not passed through jb */ 07382 if (!frame_put_in_jb) 07383 ast_write(other, f); 07384 07385 /* Check if we have to deliver now */ 07386 if (jb_in_use) 07387 ast_jb_get_and_deliver(c0, c1); 07388 } 07389 /* XXX do we want to pass on also frames not matched above ? */ 07390 ast_frfree(f); 07391 07392 #ifndef HAVE_EPOLL 07393 /* Swap who gets priority */ 07394 cs[2] = cs[0]; 07395 cs[0] = cs[1]; 07396 cs[1] = cs[2]; 07397 #endif 07398 } 07399 07400 ast_poll_channel_del(c0, c1); 07401 07402 return res; 07403 }
struct ast_channel_tech* ast_get_channel_tech | ( | const char * | name | ) | [read] |
Get handle to channel driver based on name.
Get a channel technology structure by name.
Definition at line 960 of file channel.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, chanlist::tech, and ast_channel_tech::type.
Referenced by __ast_channel_alloc_ap(), _ast_device_state(), ast_cc_callback(), and ast_var_channel_types_table().
00961 { 00962 struct chanlist *chanls; 00963 const struct ast_channel_tech *ret = NULL; 00964 00965 AST_RWLIST_RDLOCK(&backends); 00966 00967 AST_RWLIST_TRAVERSE(&backends, chanls, list) { 00968 if (!strcasecmp(name, chanls->tech->type)) { 00969 ret = chanls->tech; 00970 break; 00971 } 00972 } 00973 00974 AST_RWLIST_UNLOCK(&backends); 00975 00976 return ret; 00977 }
ast_group_t ast_get_group | ( | const char * | s | ) |
Definition at line 7987 of file channel.c.
References ast_log(), ast_strdupa, ast_strlen_zero(), LOG_ERROR, and LOG_WARNING.
Referenced by _parse(), build_device(), build_gateway(), build_peer(), config_parse_variables(), func_channel_write_real(), process_dahdi(), and read_agent_config().
07988 { 07989 char *piece; 07990 char *c; 07991 int start=0, finish=0, x; 07992 ast_group_t group = 0; 07993 07994 if (ast_strlen_zero(s)) 07995 return 0; 07996 07997 c = ast_strdupa(s); 07998 07999 while ((piece = strsep(&c, ","))) { 08000 if (sscanf(piece, "%30d-%30d", &start, &finish) == 2) { 08001 /* Range */ 08002 } else if (sscanf(piece, "%30d", &start)) { 08003 /* Just one */ 08004 finish = start; 08005 } else { 08006 ast_log(LOG_ERROR, "Syntax error parsing group configuration '%s' at '%s'. Ignoring.\n", s, piece); 08007 continue; 08008 } 08009 for (x = start; x <= finish; x++) { 08010 if ((x > 63) || (x < 0)) { 08011 ast_log(LOG_WARNING, "Ignoring invalid group %d (maximum group is 63)\n", x); 08012 } else 08013 group |= ((ast_group_t) 1 << x); 08014 } 08015 } 08016 return group; 08017 }
int ast_hangup | ( | struct ast_channel * | chan | ) |
Hangup a channel.
Hang up a channel.
Definition at line 2804 of file channel.c.
References ao2_unlink, ast_assert, ast_autoservice_stop(), ast_cause2str(), ast_cc_offer(), ast_cdr_detach(), ast_cdr_end(), AST_CDR_FLAG_BRIDGED, AST_CDR_FLAG_DIALED, AST_CDR_FLAG_POST_DISABLED, AST_CDR_NULL, AST_CEL_HANGUP, ast_cel_report_event(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_closestream(), ast_debug, ast_do_masquerade(), AST_FLAG_BLOCKING, AST_FLAG_ZOMBIE, ast_log(), ast_manager_event, ast_set_flag, ast_test_flag, ast_channel::blocker, ast_channel::blockproc, ast_channel::caller, ast_channel::cdr, channels, ast_channel::connected, destroy_hooks(), ast_cdr::disposition, EVENT_FLAG_CALL, free_translation(), ast_channel::generator, ast_channel::generatordata, ast_channel_tech::hangup, ast_channel::hangupcause, ast_party_connected_line::id, ast_party_caller::id, LOG_WARNING, ast_channel::masq, ast_channel::masqr, ast_party_id::name, ast_party_id::number, pbx_builtin_getvar_helper(), ast_generator::release, S_COR, S_OR, ast_channel::sched, sched_context_destroy(), ast_party_name::str, ast_party_number::str, ast_channel::stream, ast_channel::tech, ast_party_name::valid, ast_party_number::valid, and ast_channel::vstream.
Referenced by __analog_handle_event(), __analog_ss_thread(), __ast_pbx_run(), __ast_request_and_dial(), __oh323_new(), action_bridge(), agent_request(), alsa_new(), analog_handle_init_event(), analog_ss_thread(), answer_exec_run(), app_exec(), ast_async_goto(), ast_call_forward(), ast_dial_destroy(), ast_dial_hangup(), ast_iax2_new(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), ast_pbx_run_app(), async_wait(), begin_dial_channel(), bridge_call_thread(), bridge_call_thread_launch(), bridge_channel_thread(), bridge_exec(), build_conf(), builtin_atxfer(), chanavail_exec(), check_availability(), check_compat(), check_goto_on_transfer(), clear_caller(), conf_free(), conf_run(), console_new(), dahdi_handle_event(), dahdi_new(), destroy_conference_bridge(), dial_exec_full(), dial_transfer(), do_forward(), do_hang(), do_monitor(), feature_attended_transfer(), feature_request_and_dial(), findmeexec(), generic_recall(), gtalk_new(), handle_call_forward(), handle_callforward_button(), handle_enbloc_call_message(), handle_frame(), handle_frame_ownerless(), handle_hd_hf(), handle_init_event(), handle_invite_replaces(), handle_offhook_message(), handle_request_invite(), handle_soft_key_event_message(), handle_stimulus_message(), handle_timeout_trip(), handle_transfer_button(), HandleCallOutgoing(), hangup_chan(), hangupcalls(), hanguptree(), iax2_request(), iax_park(), iax_park_thread(), jingle_new(), local_hangup(), manage_parked_call(), masq_park_call(), meetme_menu_admin_extended(), mgcp_new(), mgcp_ss(), monitor_dial(), mwi_thread(), my_distinctive_ring(), my_handle_notify_message(), nbs_new(), oss_new(), parkandannounce_exec(), parked_call_exec(), phone_new(), play_sound_file(), sip_park(), sip_park_thread(), sip_pickup_thread(), skinny_new(), skinny_ss(), try_calling(), unistim_new(), wait_for_answer(), and wait_for_winner().
02805 { 02806 char extra_str[64]; /* used for cel logging below */ 02807 int was_zombie; 02808 02809 ast_autoservice_stop(chan); 02810 02811 ast_channel_lock(chan); 02812 02813 /* 02814 * Do the masquerade if someone is setup to masquerade into us. 02815 * 02816 * NOTE: We must hold the channel lock after testing for a 02817 * pending masquerade and setting the channel as a zombie to 02818 * prevent __ast_channel_masquerade() from setting up a 02819 * masquerade with a dead channel. 02820 */ 02821 while (chan->masq) { 02822 ast_channel_unlock(chan); 02823 ast_do_masquerade(chan); 02824 ast_channel_lock(chan); 02825 } 02826 02827 if (chan->masqr) { 02828 /* 02829 * This channel is one which will be masqueraded into something. 02830 * Mark it as a zombie already so ast_do_masquerade() will know 02831 * to free it later. 02832 */ 02833 ast_set_flag(chan, AST_FLAG_ZOMBIE); 02834 destroy_hooks(chan); 02835 ast_channel_unlock(chan); 02836 return 0; 02837 } 02838 02839 /* Mark as a zombie so a masquerade cannot be setup on this channel. */ 02840 if (!(was_zombie = ast_test_flag(chan, AST_FLAG_ZOMBIE))) { 02841 ast_set_flag(chan, AST_FLAG_ZOMBIE); 02842 } 02843 02844 ast_channel_unlock(chan); 02845 ao2_unlink(channels, chan); 02846 ast_channel_lock(chan); 02847 02848 destroy_hooks(chan); 02849 02850 free_translation(chan); 02851 /* Close audio stream */ 02852 if (chan->stream) { 02853 ast_closestream(chan->stream); 02854 chan->stream = NULL; 02855 } 02856 /* Close video stream */ 02857 if (chan->vstream) { 02858 ast_closestream(chan->vstream); 02859 chan->vstream = NULL; 02860 } 02861 if (chan->sched) { 02862 sched_context_destroy(chan->sched); 02863 chan->sched = NULL; 02864 } 02865 02866 if (chan->generatordata) { /* Clear any tone stuff remaining */ 02867 if (chan->generator && chan->generator->release) { 02868 chan->generator->release(chan, chan->generatordata); 02869 } 02870 } 02871 chan->generatordata = NULL; 02872 chan->generator = NULL; 02873 02874 snprintf(extra_str, sizeof(extra_str), "%d,%s,%s", chan->hangupcause, chan->hangupsource, S_OR(pbx_builtin_getvar_helper(chan, "DIALSTATUS"), "")); 02875 ast_cel_report_event(chan, AST_CEL_HANGUP, NULL, extra_str, NULL); 02876 02877 if (ast_test_flag(chan, AST_FLAG_BLOCKING)) { 02878 ast_log(LOG_WARNING, "Hard hangup called by thread %ld on %s, while fd " 02879 "is blocked by thread %ld in procedure %s! Expect a failure\n", 02880 (long) pthread_self(), chan->name, (long)chan->blocker, chan->blockproc); 02881 ast_assert(ast_test_flag(chan, AST_FLAG_BLOCKING) == 0); 02882 } 02883 if (!was_zombie) { 02884 ast_debug(1, "Hanging up channel '%s'\n", chan->name); 02885 02886 if (chan->tech->hangup) { 02887 chan->tech->hangup(chan); 02888 } 02889 } else { 02890 ast_debug(1, "Hanging up zombie '%s'\n", chan->name); 02891 } 02892 02893 ast_channel_unlock(chan); 02894 02895 ast_cc_offer(chan); 02896 ast_manager_event(chan, EVENT_FLAG_CALL, "Hangup", 02897 "Channel: %s\r\n" 02898 "Uniqueid: %s\r\n" 02899 "CallerIDNum: %s\r\n" 02900 "CallerIDName: %s\r\n" 02901 "ConnectedLineNum: %s\r\n" 02902 "ConnectedLineName: %s\r\n" 02903 "Cause: %d\r\n" 02904 "Cause-txt: %s\r\n", 02905 chan->name, 02906 chan->uniqueid, 02907 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<unknown>"), 02908 S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, "<unknown>"), 02909 S_COR(chan->connected.id.number.valid, chan->connected.id.number.str, "<unknown>"), 02910 S_COR(chan->connected.id.name.valid, chan->connected.id.name.str, "<unknown>"), 02911 chan->hangupcause, 02912 ast_cause2str(chan->hangupcause) 02913 ); 02914 02915 if (chan->cdr && !ast_test_flag(chan->cdr, AST_CDR_FLAG_BRIDGED) && 02916 !ast_test_flag(chan->cdr, AST_CDR_FLAG_POST_DISABLED) && 02917 (chan->cdr->disposition != AST_CDR_NULL || ast_test_flag(chan->cdr, AST_CDR_FLAG_DIALED))) { 02918 ast_channel_lock(chan); 02919 ast_cdr_end(chan->cdr); 02920 ast_cdr_detach(chan->cdr); 02921 chan->cdr = NULL; 02922 ast_channel_unlock(chan); 02923 } 02924 02925 ast_channel_unref(chan); 02926 02927 return 0; 02928 }
int ast_indicate | ( | struct ast_channel * | chan, | |
int | condition | |||
) |
Indicates condition of channel.
chan | channel to change the indication | |
condition | which condition to indicate on the channel |
Definition at line 4393 of file channel.c.
References ast_indicate_data().
Referenced by __ast_play_and_record(), agent_request(), alsa_call(), answer_trunk_chan(), ast_bridge_call(), ast_channel_bridge(), ast_do_masquerade(), ast_dtmf_stream(), ast_raw_answer(), attempt_transfer(), builtin_atxfer(), builtin_blindtransfer(), cli_console_answer(), conf_run(), console_call(), dial_exec_full(), dial_trunk(), disa_exec(), do_forward(), feature_request_and_dial(), finishup(), handle_callforward_button(), handle_frame(), handle_recordfile(), handle_request_refer(), local_attended_transfer(), manage_parked_call(), mgcp_ss(), monitor_dial(), oss_call(), park_call_full(), parked_call_exec(), pbx_builtin_busy(), pbx_builtin_congestion(), pbx_builtin_incomplete(), pbx_builtin_proceeding(), pbx_builtin_progress(), pbx_builtin_ringing(), pbx_builtin_waitexten(), queue_exec(), record_exec(), rna(), say_periodic_announcement(), say_position(), send_waveform_to_channel(), skinny_ss(), sla_handle_hold_event(), sla_station_exec(), sla_trunk_exec(), try_calling(), and wait_for_answer().
04394 { 04395 return ast_indicate_data(chan, condition, NULL, 0); 04396 }
int ast_indicate_data | ( | struct ast_channel * | chan, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) |
Indicates condition of channel, with payload.
chan | channel to change the indication | |
condition | which condition to indicate on the channel | |
data | pointer to payload data | |
datalen | size of payload data |
Definition at line 4447 of file channel.c.
References ast_channel::_state, _XXX_AST_CONTROL_T38, ast_channel_lock, ast_channel_set_connected_line(), ast_channel_set_redirecting(), ast_channel_unlock, ast_check_hangup(), ast_connected_line_parse_data(), AST_CONTROL_ANSWER, AST_CONTROL_AOC, AST_CONTROL_BUSY, AST_CONTROL_CC, AST_CONTROL_CONGESTION, AST_CONTROL_CONNECTED_LINE, AST_CONTROL_END_OF_Q, AST_CONTROL_FLASH, AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, AST_CONTROL_OFFHOOK, AST_CONTROL_OPTION, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_READ_ACTION, AST_CONTROL_REDIRECTING, AST_CONTROL_RING, AST_CONTROL_RINGING, AST_CONTROL_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_T38_PARAMETERS, AST_CONTROL_TAKEOFFHOOK, AST_CONTROL_TRANSFER, AST_CONTROL_UNHOLD, AST_CONTROL_UPDATE_RTP_PEER, AST_CONTROL_VIDUPDATE, AST_CONTROL_WINK, ast_debug, AST_FLAG_ZOMBIE, AST_FRAME_CONTROL, ast_framehook_list_is_empty(), ast_framehook_list_write_event(), ast_frdup(), ast_frfree, ast_get_indication_tone(), ast_log(), ast_party_connected_line_free(), ast_party_connected_line_set_init(), ast_party_redirecting_free(), ast_party_redirecting_set_init(), ast_playtones_start(), ast_playtones_stop(), ast_redirecting_parse_data(), AST_STATE_UP, ast_test_flag, ast_tone_zone_sound_unref(), ast_channel::connected, ast_tone_zone_sound::data, ast_frame::data, ast_frame::datalen, ast_channel::framehooks, ast_frame::frametype, ast_channel_tech::indicate, ast_frame_subclass::integer, is_visible_indication(), LOG_WARNING, ast_frame::ptr, ast_channel::redirecting, ast_frame::subclass, ast_channel::tech, ast_channel::visible_indication, and ast_channel::zone.
Referenced by __ast_read(), action_aocmessage(), agent_hangup(), ast_bridge_call(), ast_channel_update_connected_line(), ast_channel_update_redirecting(), ast_generic_bridge(), ast_handle_cc_control_frame(), ast_indicate(), disable_t38(), feature_request_and_dial(), generic_fax_exec(), handle_frame(), local_bridge_loop(), login_exec(), manage_parked_call(), park_call_full(), pbx_builtin_waitexten(), receivefax_t38_init(), remote_bridge_loop(), sendfax_t38_init(), set_fax_t38_caps(), transmit_audio(), transmit_t38(), and wait_for_answer().
04449 { 04450 /* By using an enum, we'll get compiler warnings for values not handled 04451 * in switch statements. */ 04452 enum ast_control_frame_type condition = _condition; 04453 struct ast_tone_zone_sound *ts = NULL; 04454 int res; 04455 /* this frame is used by framehooks. if it is set, we must free it at the end of this function */ 04456 struct ast_frame *awesome_frame = NULL; 04457 04458 ast_channel_lock(chan); 04459 04460 /* Don't bother if the channel is about to go away, anyway. */ 04461 if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) { 04462 res = -1; 04463 goto indicate_cleanup; 04464 } 04465 04466 if (!ast_framehook_list_is_empty(chan->framehooks)) { 04467 /* Do framehooks now, do it, go, go now */ 04468 struct ast_frame frame = { 04469 .frametype = AST_FRAME_CONTROL, 04470 .subclass.integer = condition, 04471 .data.ptr = (void *) data, /* this cast from const is only okay because we do the ast_frdup below */ 04472 .datalen = datalen 04473 }; 04474 04475 /* we have now committed to freeing this frame */ 04476 awesome_frame = ast_frdup(&frame); 04477 04478 /* who knows what we will get back! the anticipation is killing me. */ 04479 if (!(awesome_frame = ast_framehook_list_write_event(chan->framehooks, awesome_frame)) 04480 || awesome_frame->frametype != AST_FRAME_CONTROL) { 04481 04482 res = 0; 04483 goto indicate_cleanup; 04484 } 04485 04486 condition = awesome_frame->subclass.integer; 04487 data = awesome_frame->data.ptr; 04488 datalen = awesome_frame->datalen; 04489 } 04490 04491 switch (condition) { 04492 case AST_CONTROL_CONNECTED_LINE: 04493 { 04494 struct ast_party_connected_line connected; 04495 04496 ast_party_connected_line_set_init(&connected, &chan->connected); 04497 res = ast_connected_line_parse_data(data, datalen, &connected); 04498 if (!res) { 04499 ast_channel_set_connected_line(chan, &connected, NULL); 04500 } 04501 ast_party_connected_line_free(&connected); 04502 } 04503 break; 04504 04505 case AST_CONTROL_REDIRECTING: 04506 { 04507 struct ast_party_redirecting redirecting; 04508 04509 ast_party_redirecting_set_init(&redirecting, &chan->redirecting); 04510 res = ast_redirecting_parse_data(data, datalen, &redirecting); 04511 if (!res) { 04512 ast_channel_set_redirecting(chan, &redirecting, NULL); 04513 } 04514 ast_party_redirecting_free(&redirecting); 04515 } 04516 break; 04517 04518 default: 04519 break; 04520 } 04521 04522 if (is_visible_indication(condition)) { 04523 /* A new visible indication is requested. */ 04524 chan->visible_indication = condition; 04525 } else if (condition == AST_CONTROL_UNHOLD || _condition < 0) { 04526 /* Visible indication is cleared/stopped. */ 04527 chan->visible_indication = 0; 04528 } 04529 04530 if (chan->tech->indicate) { 04531 /* See if the channel driver can handle this condition. */ 04532 res = chan->tech->indicate(chan, condition, data, datalen); 04533 } else { 04534 res = -1; 04535 } 04536 04537 if (!res) { 04538 /* The channel driver successfully handled this indication */ 04539 res = 0; 04540 goto indicate_cleanup; 04541 } 04542 04543 /* The channel driver does not support this indication, let's fake 04544 * it by doing our own tone generation if applicable. */ 04545 04546 /*!\note If we compare the enumeration type, which does not have any 04547 * negative constants, the compiler may optimize this code away. 04548 * Therefore, we must perform an integer comparison here. */ 04549 if (_condition < 0) { 04550 /* Stop any tones that are playing */ 04551 ast_playtones_stop(chan); 04552 res = 0; 04553 goto indicate_cleanup; 04554 } 04555 04556 /* Handle conditions that we have tones for. */ 04557 switch (condition) { 04558 case _XXX_AST_CONTROL_T38: 04559 /* deprecated T.38 control frame */ 04560 res = -1; 04561 goto indicate_cleanup; 04562 case AST_CONTROL_T38_PARAMETERS: 04563 /* there is no way to provide 'default' behavior for these 04564 * control frames, so we need to return failure, but there 04565 * is also no value in the log message below being emitted 04566 * since failure to handle these frames is not an 'error' 04567 * so just return right now. in addition, we want to return 04568 * whatever value the channel driver returned, in case it 04569 * has some meaning.*/ 04570 goto indicate_cleanup; 04571 case AST_CONTROL_RINGING: 04572 ts = ast_get_indication_tone(chan->zone, "ring"); 04573 /* It is common practice for channel drivers to return -1 if trying 04574 * to indicate ringing on a channel which is up. The idea is to let the 04575 * core generate the ringing inband. However, we don't want the 04576 * warning message about not being able to handle the specific indication 04577 * to print nor do we want ast_indicate_data to return an "error" for this 04578 * condition 04579 */ 04580 if (chan->_state == AST_STATE_UP) { 04581 res = 0; 04582 } 04583 break; 04584 case AST_CONTROL_BUSY: 04585 ts = ast_get_indication_tone(chan->zone, "busy"); 04586 break; 04587 case AST_CONTROL_INCOMPLETE: 04588 case AST_CONTROL_CONGESTION: 04589 ts = ast_get_indication_tone(chan->zone, "congestion"); 04590 break; 04591 case AST_CONTROL_PROGRESS: 04592 case AST_CONTROL_PROCEEDING: 04593 case AST_CONTROL_VIDUPDATE: 04594 case AST_CONTROL_SRCUPDATE: 04595 case AST_CONTROL_SRCCHANGE: 04596 case AST_CONTROL_RADIO_KEY: 04597 case AST_CONTROL_RADIO_UNKEY: 04598 case AST_CONTROL_OPTION: 04599 case AST_CONTROL_WINK: 04600 case AST_CONTROL_FLASH: 04601 case AST_CONTROL_OFFHOOK: 04602 case AST_CONTROL_TAKEOFFHOOK: 04603 case AST_CONTROL_ANSWER: 04604 case AST_CONTROL_HANGUP: 04605 case AST_CONTROL_RING: 04606 case AST_CONTROL_HOLD: 04607 case AST_CONTROL_UNHOLD: 04608 case AST_CONTROL_TRANSFER: 04609 case AST_CONTROL_CONNECTED_LINE: 04610 case AST_CONTROL_REDIRECTING: 04611 case AST_CONTROL_CC: 04612 case AST_CONTROL_READ_ACTION: 04613 case AST_CONTROL_AOC: 04614 case AST_CONTROL_END_OF_Q: 04615 case AST_CONTROL_UPDATE_RTP_PEER: 04616 /* Nothing left to do for these. */ 04617 res = 0; 04618 break; 04619 } 04620 04621 if (ts) { 04622 /* We have a tone to play, yay. */ 04623 ast_debug(1, "Driver for channel '%s' does not support indication %u, emulating it\n", chan->name, condition); 04624 res = ast_playtones_start(chan, 0, ts->data, 1); 04625 ts = ast_tone_zone_sound_unref(ts); 04626 } 04627 04628 if (res) { 04629 /* not handled */ 04630 ast_log(LOG_WARNING, "Unable to handle indication %u for '%s'\n", condition, chan->name); 04631 } 04632 04633 indicate_cleanup: 04634 ast_channel_unlock(chan); 04635 if (awesome_frame) { 04636 ast_frfree(awesome_frame); 04637 } 04638 04639 return res; 04640 }
void ast_install_music_functions | ( | int(*)(struct ast_channel *, const char *, const char *) | start_ptr, | |
void(*)(struct ast_channel *) | stop_ptr, | |||
void(*)(struct ast_channel *) | cleanup_ptr | |||
) |
Definition at line 8023 of file channel.c.
References ast_moh_cleanup_ptr, ast_moh_start_ptr, and ast_moh_stop_ptr.
Referenced by load_module(), and reload().
08026 { 08027 ast_moh_start_ptr = start_ptr; 08028 ast_moh_stop_ptr = stop_ptr; 08029 ast_moh_cleanup_ptr = cleanup_ptr; 08030 }
int ast_internal_timing_enabled | ( | struct ast_channel * | chan | ) |
Check if the channel can run in internal timing mode.
chan | The channel to check |
This function will return 1 if internal timing is enabled and the timing device is available.
Definition at line 4378 of file channel.c.
References ast_channel::timingfd.
04379 { 04380 return chan->timingfd > -1; 04381 }
int ast_is_deferrable_frame | ( | const struct ast_frame * | frame | ) |
Should we keep this frame for later?
There are functions such as ast_safe_sleep which will service a channel to ensure that it does not have a large backlog of queued frames. When this happens, we want to hold on to specific frame types and just drop others. This function will tell if the frame we just read should be held onto.
frame | The frame we just read |
1 | frame should be kept | |
0 | frame should be dropped |
Definition at line 1818 of file channel.c.
References AST_FRAME_CNG, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_HTML, AST_FRAME_IAX, AST_FRAME_IMAGE, AST_FRAME_MODEM, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, and ast_frame::frametype.
Referenced by ast_safe_sleep_conditional(), autoservice_run(), and feature_request_and_dial().
01819 { 01820 /* Do not add a default entry in this switch statement. Each new 01821 * frame type should be addressed directly as to whether it should 01822 * be queued up or not. 01823 */ 01824 switch (frame->frametype) { 01825 case AST_FRAME_CONTROL: 01826 case AST_FRAME_TEXT: 01827 case AST_FRAME_IMAGE: 01828 case AST_FRAME_HTML: 01829 return 1; 01830 01831 case AST_FRAME_DTMF_END: 01832 case AST_FRAME_DTMF_BEGIN: 01833 case AST_FRAME_VOICE: 01834 case AST_FRAME_VIDEO: 01835 case AST_FRAME_NULL: 01836 case AST_FRAME_IAX: 01837 case AST_FRAME_CNG: 01838 case AST_FRAME_MODEM: 01839 return 0; 01840 } 01841 return 0; 01842 }
void ast_moh_cleanup | ( | struct ast_channel * | chan | ) |
Definition at line 8057 of file channel.c.
References ast_moh_cleanup_ptr.
Referenced by ast_channel_destructor().
08058 { 08059 if (ast_moh_cleanup_ptr) 08060 ast_moh_cleanup_ptr(chan); 08061 }
int ast_moh_start | ( | struct ast_channel * | chan, | |
const char * | mclass, | |||
const char * | interpclass | |||
) |
Turn on music on hold on a given channel.
chan | The channel structure that will get music on hold | |
mclass | The class to use if the musicclass is not currently set on the channel structure. | |
interpclass | The class to use if the musicclass is not currently set on the channel structure or in the mclass argument. |
Zero | on success | |
non-zero | on failure |
Definition at line 8040 of file channel.c.
References ast_moh_start_ptr, and ast_verb.
Referenced by alsa_indicate(), app_exec(), ast_do_masquerade(), conf_start_moh(), console_indicate(), dahdi_indicate(), dial_exec_full(), feature_exec_app(), gtalk_indicate(), handle_setmusic(), iax2_indicate(), jingle_indicate(), key_call(), leave_conference_bridge(), local_indicate(), menu_callback(), mgcp_indicate(), misdn_indication(), moh_handle_digit(), monitor_dial(), oh323_indicate(), oss_indicate(), phone_indicate(), play_moh_exec(), post_join_marked(), post_join_unmarked(), queue_exec(), retrydial_exec(), rna(), say_periodic_announcement(), say_position(), sip_indicate(), skinny_indicate(), start_moh_exec(), TransferCallStep1(), unistim_indicate(), and wait_moh_exec().
08041 { 08042 if (ast_moh_start_ptr) 08043 return ast_moh_start_ptr(chan, mclass, interpclass); 08044 08045 ast_verb(3, "Music class %s requested but no musiconhold loaded.\n", mclass ? mclass : (interpclass ? interpclass : "default")); 08046 08047 return 0; 08048 }
void ast_moh_stop | ( | struct ast_channel * | chan | ) |
Turn off music on hold on a given channel.
Turn off music on hold on a given channel
Definition at line 8051 of file channel.c.
References ast_moh_stop_ptr.
Referenced by alsa_indicate(), app_exec(), ast_quiet_chan(), conf_run(), console_indicate(), dahdi_indicate(), dial_exec_full(), do_bridge_masquerade(), feature_exec_app(), gtalk_indicate(), handle_setmusic(), iax2_indicate(), jingle_indicate(), key_call(), key_dial_page(), local_indicate(), menu_callback(), mgcp_indicate(), misdn_indication(), moh_handle_digit(), monitor_dial(), oh323_indicate(), oss_indicate(), phone_indicate(), play_moh_exec(), post_join_marked(), post_join_unmarked(), queue_exec(), retrydial_exec(), say_periodic_announcement(), say_position(), sip_indicate(), skinny_indicate(), stop_moh_exec(), try_calling(), unistim_hangup(), unistim_indicate(), wait_for_answer(), and wait_moh_exec().
08052 { 08053 if (ast_moh_stop_ptr) 08054 ast_moh_stop_ptr(chan); 08055 }
void ast_party_caller_copy | ( | struct ast_party_caller * | dest, | |
const struct ast_party_caller * | src | |||
) |
Copy the source caller information to the destination caller.
dest | Destination caller | |
src | Source caller |
Definition at line 2276 of file channel.c.
References ast_party_caller::ani, ast_party_caller::ani2, ast_party_id_copy(), and ast_party_caller::id.
02277 { 02278 if (dest == src) { 02279 /* Don't copy to self */ 02280 return; 02281 } 02282 02283 ast_party_id_copy(&dest->id, &src->id); 02284 ast_party_id_copy(&dest->ani, &src->ani); 02285 dest->ani2 = src->ani2; 02286 }
void ast_party_caller_free | ( | struct ast_party_caller * | doomed | ) |
Destroy the caller party contents.
doomed | The caller party to destroy. |
Definition at line 2302 of file channel.c.
References ast_party_caller::ani, ast_party_id_free(), and ast_party_caller::id.
Referenced by ast_channel_destructor(), ast_dummy_channel_destructor(), callerid_write(), dial_trunk(), and sla_ring_station().
02303 { 02304 ast_party_id_free(&doomed->id); 02305 ast_party_id_free(&doomed->ani); 02306 }
void ast_party_caller_init | ( | struct ast_party_caller * | init | ) |
Initialize the given caller structure.
init | Caller structure to initialize. |
Definition at line 2269 of file channel.c.
References ast_party_caller::ani, ast_party_caller::ani2, ast_party_id_init(), and ast_party_caller::id.
Referenced by __ast_channel_alloc_ap(), dial_trunk(), and sla_ring_station().
02270 { 02271 ast_party_id_init(&init->id); 02272 ast_party_id_init(&init->ani); 02273 init->ani2 = 0; 02274 }
void ast_party_caller_set | ( | struct ast_party_caller * | dest, | |
const struct ast_party_caller * | src, | |||
const struct ast_set_party_caller * | update | |||
) |
Set the caller information based on another caller source.
This is similar to ast_party_caller_copy, except that NULL values for strings in the src parameter indicate not to update the corresponding dest values.
dest | The caller one wishes to update | |
src | The new caller values to update the dest | |
update | What caller information to update. NULL if all. |
Definition at line 2295 of file channel.c.
References ast_set_party_caller::ani, ast_party_caller::ani, ast_party_caller::ani2, ast_party_id_set(), ast_set_party_caller::id, and ast_party_caller::id.
Referenced by ast_channel_set_caller(), ast_channel_set_caller_event(), and callerid_write().
02296 { 02297 ast_party_id_set(&dest->id, &src->id, update ? &update->id : NULL); 02298 ast_party_id_set(&dest->ani, &src->ani, update ? &update->ani : NULL); 02299 dest->ani2 = src->ani2; 02300 }
void ast_party_caller_set_init | ( | struct ast_party_caller * | init, | |
const struct ast_party_caller * | guide | |||
) |
Initialize the given caller structure using the given guide for a set update operation.
The initialization is needed to allow a set operation to know if a value needs to be updated. Simple integers need the guide's original value in case the set operation is not trying to set a new value. String values are simply set to NULL pointers if they are not going to be updated.
init | Caller structure to initialize. | |
guide | Source caller to use as a guide in initializing. |
Definition at line 2288 of file channel.c.
References ast_party_caller::ani, ast_party_caller::ani2, ast_party_id_set_init(), and ast_party_caller::id.
Referenced by callerid_write(), dial_exec_full(), do_forward(), misdn_update_caller_id(), and ring_entry().
02289 { 02290 ast_party_id_set_init(&init->id, &guide->id); 02291 ast_party_id_set_init(&init->ani, &guide->ani); 02292 init->ani2 = guide->ani2; 02293 }
void ast_party_connected_line_collect_caller | ( | struct ast_party_connected_line * | connected, | |
struct ast_party_caller * | caller | |||
) |
Collect the caller party information into a connected line structure.
connected | Collected caller information for the connected line | |
caller | Caller information. |
Definition at line 2345 of file channel.c.
References ast_party_caller::ani, ast_party_connected_line::ani, ast_party_caller::ani2, ast_party_connected_line::ani2, AST_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN, ast_party_caller::id, ast_party_connected_line::id, and ast_party_connected_line::source.
void ast_party_connected_line_copy | ( | struct ast_party_connected_line * | dest, | |
const struct ast_party_connected_line * | src | |||
) |
Copy the source connected line information to the destination connected line.
dest | Destination connected line | |
src | Source connected line |
Definition at line 2316 of file channel.c.
References ast_party_connected_line::ani, ast_party_connected_line::ani2, ast_party_id_copy(), ast_party_connected_line::id, and ast_party_connected_line::source.
Referenced by __ast_read(), ast_call_forward(), ast_channel_connected_line_macro(), ast_do_pickup(), builtin_atxfer(), dial_exec_full(), do_forward(), local_attended_transfer(), misdn_attempt_transfer(), party_connected_line_copy_transfer(), try_calling(), and wait_for_answer().
02317 { 02318 if (dest == src) { 02319 /* Don't copy to self */ 02320 return; 02321 } 02322 02323 ast_party_id_copy(&dest->id, &src->id); 02324 ast_party_id_copy(&dest->ani, &src->ani); 02325 dest->ani2 = src->ani2; 02326 dest->source = src->source; 02327 }
void ast_party_connected_line_free | ( | struct ast_party_connected_line * | doomed | ) |
Destroy the connected line information contents.
doomed | The connected line information to destroy. |
Definition at line 2353 of file channel.c.
References ast_party_connected_line::ani, ast_party_id_free(), and ast_party_connected_line::id.
Referenced by __ast_read(), app_exec(), ast_channel_connected_line_macro(), ast_channel_destructor(), ast_do_pickup(), ast_dummy_channel_destructor(), ast_indicate_data(), atxfer_fail_cleanup(), builtin_atxfer(), callattempt_free(), chanlist_free(), connectedline_write(), destroy_calling_tree(), feature_request_and_dial(), findmeexec(), local_attended_transfer(), misdn_attempt_transfer(), parked_call_exec(), socket_process(), wait_for_answer(), wait_for_winner(), and xfer_ds_destroy().
02354 { 02355 ast_party_id_free(&doomed->id); 02356 ast_party_id_free(&doomed->ani); 02357 }
void ast_party_connected_line_init | ( | struct ast_party_connected_line * | init | ) |
Initialize the given connected line structure.
init | Connected line structure to initialize. |
Definition at line 2308 of file channel.c.
References ast_party_connected_line::ani, ast_party_connected_line::ani2, AST_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN, ast_party_id_init(), ast_party_connected_line::id, and ast_party_connected_line::source.
Referenced by __ast_channel_alloc_ap(), __ast_read(), ast_channel_connected_line_macro(), ast_do_pickup(), builtin_atxfer(), do_forward(), handle_request_invite(), handle_request_update(), handle_response_invite(), local_attended_transfer(), misdn_attempt_transfer(), misdn_queue_connected_line_update(), parked_call_exec(), sip_call(), socket_process(), and wait_for_answer().
02309 { 02310 ast_party_id_init(&init->id); 02311 ast_party_id_init(&init->ani); 02312 init->ani2 = 0; 02313 init->source = AST_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN; 02314 }
void ast_party_connected_line_set | ( | struct ast_party_connected_line * | dest, | |
const struct ast_party_connected_line * | src, | |||
const struct ast_set_party_connected_line * | update | |||
) |
Set the connected line information based on another connected line source.
dest | The connected line one wishes to update | |
src | The new connected line values to update the dest | |
update | What connected line information to update. NULL if all. |
Definition at line 2337 of file channel.c.
References ast_set_party_connected_line::ani, ast_party_connected_line::ani, ast_party_connected_line::ani2, ast_party_id_set(), ast_set_party_connected_line::id, ast_party_connected_line::id, and ast_party_connected_line::source.
Referenced by ast_channel_set_connected_line(), wait_for_answer(), and wait_for_winner().
void ast_party_connected_line_set_init | ( | struct ast_party_connected_line * | init, | |
const struct ast_party_connected_line * | guide | |||
) |
Initialize the given connected line structure using the given guide for a set update operation.
The initialization is needed to allow a set operation to know if a value needs to be updated. Simple integers need the guide's original value in case the set operation is not trying to set a new value. String values are simply set to NULL pointers if they are not going to be updated.
init | Connected line structure to initialize. | |
guide | Source connected line to use as a guide in initializing. |
Definition at line 2329 of file channel.c.
References ast_party_connected_line::ani, ast_party_connected_line::ani2, ast_party_id_set_init(), ast_party_connected_line::id, and ast_party_connected_line::source.
Referenced by __ast_request_and_dial(), ast_indicate_data(), connectedline_write(), dial_exec_full(), feature_request_and_dial(), wait_for_answer(), and wait_for_winner().
02330 { 02331 ast_party_id_set_init(&init->id, &guide->id); 02332 ast_party_id_set_init(&init->ani, &guide->ani); 02333 init->ani2 = guide->ani2; 02334 init->source = guide->source; 02335 }
void ast_party_dialed_copy | ( | struct ast_party_dialed * | dest, | |
const struct ast_party_dialed * | src | |||
) |
Copy the source dialed party information to the destination dialed party.
dest | Destination dialed party | |
src | Source dialed party |
Definition at line 2227 of file channel.c.
References ast_free, ast_party_subaddress_copy(), ast_strdup, ast_party_dialed::number, ast_party_dialed::plan, ast_party_dialed::str, ast_party_dialed::subaddress, and ast_party_dialed::transit_network_select.
Referenced by local_call().
02228 { 02229 if (dest == src) { 02230 /* Don't copy to self */ 02231 return; 02232 } 02233 02234 ast_free(dest->number.str); 02235 dest->number.str = ast_strdup(src->number.str); 02236 dest->number.plan = src->number.plan; 02237 ast_party_subaddress_copy(&dest->subaddress, &src->subaddress); 02238 dest->transit_network_select = src->transit_network_select; 02239 }
void ast_party_dialed_free | ( | struct ast_party_dialed * | doomed | ) |
Destroy the dialed party contents.
doomed | The dialed party to destroy. |
Definition at line 2262 of file channel.c.
References ast_free, ast_party_subaddress_free(), ast_party_dialed::number, ast_party_dialed::str, and ast_party_dialed::subaddress.
Referenced by ast_channel_destructor(), ast_dummy_channel_destructor(), and callerid_write().
02263 { 02264 ast_free(doomed->number.str); 02265 doomed->number.str = NULL; 02266 ast_party_subaddress_free(&doomed->subaddress); 02267 }
void ast_party_dialed_init | ( | struct ast_party_dialed * | init | ) |
Initialize the given dialed structure.
init | Dialed structure to initialize. |
Definition at line 2219 of file channel.c.
References ast_party_subaddress_init(), ast_party_dialed::number, ast_party_dialed::plan, ast_party_dialed::str, ast_party_dialed::subaddress, and ast_party_dialed::transit_network_select.
Referenced by __ast_channel_alloc_ap().
02220 { 02221 init->number.str = NULL; 02222 init->number.plan = 0;/* Unknown */ 02223 ast_party_subaddress_init(&init->subaddress); 02224 init->transit_network_select = 0; 02225 }
void ast_party_dialed_set | ( | struct ast_party_dialed * | dest, | |
const struct ast_party_dialed * | src | |||
) |
Set the dialed information based on another dialed source.
This is similar to ast_party_dialed_copy, except that NULL values for strings in the src parameter indicate not to update the corresponding dest values.
dest | The dialed one wishes to update | |
src | The new dialed values to update the dest |
Definition at line 2249 of file channel.c.
References ast_free, ast_party_subaddress_set(), ast_strdup, ast_party_dialed::number, ast_party_dialed::plan, ast_party_dialed::str, ast_party_dialed::subaddress, and ast_party_dialed::transit_network_select.
Referenced by callerid_write().
02250 { 02251 if (src->number.str && src->number.str != dest->number.str) { 02252 ast_free(dest->number.str); 02253 dest->number.str = ast_strdup(src->number.str); 02254 } 02255 dest->number.plan = src->number.plan; 02256 02257 ast_party_subaddress_set(&dest->subaddress, &src->subaddress); 02258 02259 dest->transit_network_select = src->transit_network_select; 02260 }
void ast_party_dialed_set_init | ( | struct ast_party_dialed * | init, | |
const struct ast_party_dialed * | guide | |||
) |
Initialize the given dialed structure using the given guide for a set update operation.
The initialization is needed to allow a set operation to know if a value needs to be updated. Simple integers need the guide's original value in case the set operation is not trying to set a new value. String values are simply set to NULL pointers if they are not going to be updated.
init | Caller structure to initialize. | |
guide | Source dialed to use as a guide in initializing. |
Definition at line 2241 of file channel.c.
References ast_party_subaddress_set_init(), ast_party_dialed::number, ast_party_dialed::plan, ast_party_dialed::str, ast_party_dialed::subaddress, and ast_party_dialed::transit_network_select.
Referenced by callerid_write().
02242 { 02243 init->number.str = NULL; 02244 init->number.plan = guide->number.plan; 02245 ast_party_subaddress_set_init(&init->subaddress, &guide->subaddress); 02246 init->transit_network_select = guide->transit_network_select; 02247 }
void ast_party_id_copy | ( | struct ast_party_id * | dest, | |
const struct ast_party_id * | src | |||
) |
Copy the source party id information to the destination party id.
dest | Destination party id | |
src | Source party id |
Definition at line 2095 of file channel.c.
References ast_free, ast_party_name_copy(), ast_party_number_copy(), ast_party_subaddress_copy(), ast_strdup, ast_party_id::name, ast_party_id::number, ast_party_id::subaddress, and ast_party_id::tag.
Referenced by ast_connected_line_copy_from_caller(), ast_connected_line_copy_to_caller(), ast_party_caller_copy(), ast_party_connected_line_copy(), ast_party_redirecting_copy(), and parkandannounce_exec().
02096 { 02097 if (dest == src) { 02098 /* Don't copy to self */ 02099 return; 02100 } 02101 02102 ast_party_name_copy(&dest->name, &src->name); 02103 ast_party_number_copy(&dest->number, &src->number); 02104 ast_party_subaddress_copy(&dest->subaddress, &src->subaddress); 02105 02106 ast_free(dest->tag); 02107 dest->tag = ast_strdup(src->tag); 02108 }
void ast_party_id_free | ( | struct ast_party_id * | doomed | ) |
Destroy the party id contents.
doomed | The party id to destroy. |
Definition at line 2141 of file channel.c.
References ast_free, ast_party_name_free(), ast_party_number_free(), ast_party_subaddress_free(), ast_party_id::name, ast_party_id::number, ast_party_id::subaddress, and ast_party_id::tag.
Referenced by ast_party_caller_free(), ast_party_connected_line_free(), ast_party_redirecting_free(), and parkandannounce_exec().
02142 { 02143 ast_party_name_free(&doomed->name); 02144 ast_party_number_free(&doomed->number); 02145 ast_party_subaddress_free(&doomed->subaddress); 02146 02147 ast_free(doomed->tag); 02148 doomed->tag = NULL; 02149 }
void ast_party_id_init | ( | struct ast_party_id * | init | ) |
Initialize the given party id structure.
init | Party id structure to initialize. |
Definition at line 2087 of file channel.c.
References ast_party_name_init(), ast_party_number_init(), ast_party_subaddress_init(), ast_party_id::name, ast_party_id::number, ast_party_id::subaddress, and ast_party_id::tag.
Referenced by ast_party_caller_init(), ast_party_connected_line_init(), ast_party_redirecting_init(), dial_exec_full(), and parkandannounce_exec().
02088 { 02089 ast_party_name_init(&init->name); 02090 ast_party_number_init(&init->number); 02091 ast_party_subaddress_init(&init->subaddress); 02092 init->tag = NULL; 02093 }
int ast_party_id_presentation | ( | const struct ast_party_id * | id | ) |
Determine the overall presentation value for the given party.
id | Party to determine the overall presentation value. |
Definition at line 2151 of file channel.c.
References AST_PRES_ALLOWED, AST_PRES_NUMBER_NOT_AVAILABLE, AST_PRES_NUMBER_TYPE, AST_PRES_RESTRICTED, AST_PRES_RESTRICTION, AST_PRES_UNAVAILABLE, AST_PRES_USER_NUMBER_UNSCREENED, ast_party_id::name, ast_party_id::number, ast_party_number::valid, and ast_party_name::valid.
Referenced by add_rpid(), ast_str_retrieve_variable(), ast_var_channels_table(), callerpres_read(), iax2_call(), initreqprep(), oh323_call(), party_id_build_data(), party_id_read(), redirecting_read(), report_new_callerid(), setup_env(), sip_call(), and socket_process().
02152 { 02153 int number_priority; 02154 int number_value; 02155 int number_screening; 02156 int name_priority; 02157 int name_value; 02158 02159 /* Determine name presentation priority. */ 02160 if (!id->name.valid) { 02161 name_value = AST_PRES_UNAVAILABLE; 02162 name_priority = 3; 02163 } else { 02164 name_value = id->name.presentation & AST_PRES_RESTRICTION; 02165 switch (name_value) { 02166 case AST_PRES_RESTRICTED: 02167 name_priority = 0; 02168 break; 02169 case AST_PRES_ALLOWED: 02170 name_priority = 1; 02171 break; 02172 case AST_PRES_UNAVAILABLE: 02173 name_priority = 2; 02174 break; 02175 default: 02176 name_value = AST_PRES_UNAVAILABLE; 02177 name_priority = 3; 02178 break; 02179 } 02180 } 02181 02182 /* Determine number presentation priority. */ 02183 if (!id->number.valid) { 02184 number_screening = AST_PRES_USER_NUMBER_UNSCREENED; 02185 number_value = AST_PRES_UNAVAILABLE; 02186 number_priority = 3; 02187 } else { 02188 number_screening = id->number.presentation & AST_PRES_NUMBER_TYPE; 02189 number_value = id->number.presentation & AST_PRES_RESTRICTION; 02190 switch (number_value) { 02191 case AST_PRES_RESTRICTED: 02192 number_priority = 0; 02193 break; 02194 case AST_PRES_ALLOWED: 02195 number_priority = 1; 02196 break; 02197 case AST_PRES_UNAVAILABLE: 02198 number_priority = 2; 02199 break; 02200 default: 02201 number_screening = AST_PRES_USER_NUMBER_UNSCREENED; 02202 number_value = AST_PRES_UNAVAILABLE; 02203 number_priority = 3; 02204 break; 02205 } 02206 } 02207 02208 /* Select the wining presentation value. */ 02209 if (name_priority < number_priority) { 02210 number_value = name_value; 02211 } 02212 if (number_value == AST_PRES_UNAVAILABLE) { 02213 return AST_PRES_NUMBER_NOT_AVAILABLE; 02214 } 02215 02216 return number_value | number_screening; 02217 }
void ast_party_id_set | ( | struct ast_party_id * | dest, | |
const struct ast_party_id * | src, | |||
const struct ast_set_party_id * | update | |||
) |
Set the source party id information into the destination party id.
dest | The id one wishes to update | |
src | The new id values to update the dest | |
update | What id information to update. NULL if all. |
Definition at line 2118 of file channel.c.
References ast_free, ast_party_name_set(), ast_party_number_set(), ast_party_subaddress_set(), ast_strdup, ast_party_id::name, ast_set_party_id::name, ast_party_id::number, ast_set_party_id::number, ast_party_id::subaddress, ast_set_party_id::subaddress, and ast_party_id::tag.
Referenced by ast_party_caller_set(), ast_party_connected_line_set(), and ast_party_redirecting_set().
02119 { 02120 if (dest == src) { 02121 /* Don't set to self */ 02122 return; 02123 } 02124 02125 if (!update || update->name) { 02126 ast_party_name_set(&dest->name, &src->name); 02127 } 02128 if (!update || update->number) { 02129 ast_party_number_set(&dest->number, &src->number); 02130 } 02131 if (!update || update->subaddress) { 02132 ast_party_subaddress_set(&dest->subaddress, &src->subaddress); 02133 } 02134 02135 if (src->tag && src->tag != dest->tag) { 02136 ast_free(dest->tag); 02137 dest->tag = ast_strdup(src->tag); 02138 } 02139 }
void ast_party_id_set_init | ( | struct ast_party_id * | init, | |
const struct ast_party_id * | guide | |||
) |
Initialize the given party id structure using the given guide for a set update operation.
The initialization is needed to allow a set operation to know if a value needs to be updated. Simple integers need the guide's original value in case the set operation is not trying to set a new value. String values are simply set to NULL pointers if they are not going to be updated.
init | Party id structure to initialize. | |
guide | Source party id to use as a guide in initializing. |
Definition at line 2110 of file channel.c.
References ast_party_name_set_init(), ast_party_number_set_init(), ast_party_subaddress_set_init(), ast_party_id::name, ast_party_id::number, ast_party_id::subaddress, and ast_party_id::tag.
Referenced by ast_party_caller_set_init(), ast_party_connected_line_set_init(), ast_party_redirecting_set_init(), and dial_exec_full().
02111 { 02112 ast_party_name_set_init(&init->name, &guide->name); 02113 ast_party_number_set_init(&init->number, &guide->number); 02114 ast_party_subaddress_set_init(&init->subaddress, &guide->subaddress); 02115 init->tag = NULL; 02116 }
void ast_party_name_copy | ( | struct ast_party_name * | dest, | |
const struct ast_party_name * | src | |||
) |
Copy the source party name information to the destination party name.
dest | Destination party name | |
src | Source party name |
Definition at line 1936 of file channel.c.
References ast_free, ast_strdup, ast_party_name::char_set, ast_party_name::presentation, ast_party_name::str, and ast_party_name::valid.
Referenced by ast_party_id_copy().
01937 { 01938 if (dest == src) { 01939 /* Don't copy to self */ 01940 return; 01941 } 01942 01943 ast_free(dest->str); 01944 dest->str = ast_strdup(src->str); 01945 dest->char_set = src->char_set; 01946 dest->presentation = src->presentation; 01947 dest->valid = src->valid; 01948 }
void ast_party_name_free | ( | struct ast_party_name * | doomed | ) |
Destroy the party name contents.
doomed | The party name to destroy. |
Definition at line 1975 of file channel.c.
References ast_free, and ast_party_name::str.
Referenced by __analog_ss_thread(), analog_ss_thread(), ast_party_id_free(), and skinny_newcall().
void ast_party_name_init | ( | struct ast_party_name * | init | ) |
Initialize the given name structure.
init | Name structure to initialize. |
Definition at line 1928 of file channel.c.
References AST_PARTY_CHAR_SET_ISO8859_1, AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, ast_party_name::char_set, ast_party_name::presentation, ast_party_name::str, and ast_party_name::valid.
Referenced by __analog_ss_thread(), analog_ss_thread(), ast_party_id_init(), and skinny_newcall().
01929 { 01930 init->str = NULL; 01931 init->char_set = AST_PARTY_CHAR_SET_ISO8859_1; 01932 init->presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED; 01933 init->valid = 0; 01934 }
void ast_party_name_set | ( | struct ast_party_name * | dest, | |
const struct ast_party_name * | src | |||
) |
Set the source party name information into the destination party name.
dest | The name one wishes to update | |
src | The new name values to update the dest |
Definition at line 1958 of file channel.c.
References ast_free, ast_strdup, ast_party_name::char_set, ast_party_name::presentation, ast_party_name::str, and ast_party_name::valid.
Referenced by ast_party_id_set().
01959 { 01960 if (dest == src) { 01961 /* Don't set to self */ 01962 return; 01963 } 01964 01965 if (src->str && src->str != dest->str) { 01966 ast_free(dest->str); 01967 dest->str = ast_strdup(src->str); 01968 } 01969 01970 dest->char_set = src->char_set; 01971 dest->presentation = src->presentation; 01972 dest->valid = src->valid; 01973 }
void ast_party_name_set_init | ( | struct ast_party_name * | init, | |
const struct ast_party_name * | guide | |||
) |
Initialize the given party name structure using the given guide for a set update operation.
The initialization is needed to allow a set operation to know if a value needs to be updated. Simple integers need the guide's original value in case the set operation is not trying to set a new value. String values are simply set to NULL pointers if they are not going to be updated.
init | Party name structure to initialize. | |
guide | Source party name to use as a guide in initializing. |
Definition at line 1950 of file channel.c.
References ast_party_name::char_set, ast_party_name::presentation, ast_party_name::str, and ast_party_name::valid.
Referenced by ast_party_id_set_init().
01951 { 01952 init->str = NULL; 01953 init->char_set = guide->char_set; 01954 init->presentation = guide->presentation; 01955 init->valid = guide->valid; 01956 }
void ast_party_number_copy | ( | struct ast_party_number * | dest, | |
const struct ast_party_number * | src | |||
) |
Copy the source party number information to the destination party number.
Definition at line 1989 of file channel.c.
References ast_free, ast_strdup, ast_party_number::plan, ast_party_number::presentation, ast_party_number::str, and ast_party_number::valid.
Referenced by ast_party_id_copy().
01990 { 01991 if (dest == src) { 01992 /* Don't copy to self */ 01993 return; 01994 } 01995 01996 ast_free(dest->str); 01997 dest->str = ast_strdup(src->str); 01998 dest->plan = src->plan; 01999 dest->presentation = src->presentation; 02000 dest->valid = src->valid; 02001 }
void ast_party_number_free | ( | struct ast_party_number * | doomed | ) |
Destroy the party number contents.
doomed | The party number to destroy. |
Definition at line 2028 of file channel.c.
References ast_free, and ast_party_number::str.
Referenced by __analog_ss_thread(), analog_ss_thread(), ast_party_id_free(), do_forward(), skinny_newcall(), and wait_for_answer().
void ast_party_number_init | ( | struct ast_party_number * | init | ) |
Initialize the given number structure.
init | Number structure to initialize. |
Definition at line 1981 of file channel.c.
References AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, ast_party_number::plan, ast_party_number::presentation, ast_party_number::str, and ast_party_number::valid.
Referenced by __analog_ss_thread(), analog_ss_thread(), ast_party_id_init(), do_forward(), skinny_newcall(), and wait_for_answer().
01982 { 01983 init->str = NULL; 01984 init->plan = 0;/* Unknown */ 01985 init->presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED; 01986 init->valid = 0; 01987 }
void ast_party_number_set | ( | struct ast_party_number * | dest, | |
const struct ast_party_number * | src | |||
) |
Set the source party number information into the destination party number.
Definition at line 2011 of file channel.c.
References ast_free, ast_strdup, ast_party_number::plan, ast_party_number::presentation, ast_party_number::str, and ast_party_number::valid.
Referenced by ast_party_id_set().
02012 { 02013 if (dest == src) { 02014 /* Don't set to self */ 02015 return; 02016 } 02017 02018 if (src->str && src->str != dest->str) { 02019 ast_free(dest->str); 02020 dest->str = ast_strdup(src->str); 02021 } 02022 02023 dest->plan = src->plan; 02024 dest->presentation = src->presentation; 02025 dest->valid = src->valid; 02026 }
void ast_party_number_set_init | ( | struct ast_party_number * | init, | |
const struct ast_party_number * | guide | |||
) |
Initialize the given party number structure using the given guide for a set update operation.
The initialization is needed to allow a set operation to know if a value needs to be updated. Simple integers need the guide's original value in case the set operation is not trying to set a new value. String values are simply set to NULL pointers if they are not going to be updated.
init | Party number structure to initialize. | |
guide | Source party number to use as a guide in initializing. |
Definition at line 2003 of file channel.c.
References ast_party_number::plan, ast_party_number::presentation, ast_party_number::str, and ast_party_number::valid.
Referenced by ast_party_id_set_init().
02004 { 02005 init->str = NULL; 02006 init->plan = guide->plan; 02007 init->presentation = guide->presentation; 02008 init->valid = guide->valid; 02009 }
void ast_party_redirecting_copy | ( | struct ast_party_redirecting * | dest, | |
const struct ast_party_redirecting * | src | |||
) |
Copy the source redirecting information to the destination redirecting.
dest | Destination redirecting | |
src | Source redirecting |
Definition at line 2367 of file channel.c.
References ast_party_id_copy(), ast_party_redirecting::count, ast_party_redirecting::from, ast_party_redirecting::reason, and ast_party_redirecting::to.
Referenced by ast_call_forward(), ast_channel_redirecting_macro(), begin_dial_channel(), call_forward_inherit(), dial_exec_full(), do_forward(), local_call(), ring_entry(), and wait_for_answer().
02368 { 02369 if (dest == src) { 02370 /* Don't copy to self */ 02371 return; 02372 } 02373 02374 ast_party_id_copy(&dest->from, &src->from); 02375 ast_party_id_copy(&dest->to, &src->to); 02376 dest->count = src->count; 02377 dest->reason = src->reason; 02378 }
void ast_party_redirecting_free | ( | struct ast_party_redirecting * | doomed | ) |
Destroy the redirecting information contents.
doomed | The redirecting information to destroy. |
Definition at line 2396 of file channel.c.
References ast_party_id_free(), ast_party_redirecting::from, and ast_party_redirecting::to.
Referenced by ast_channel_destructor(), ast_channel_redirecting_macro(), ast_dummy_channel_destructor(), ast_indicate_data(), call_forward_inherit(), do_forward(), handle_request_invite(), handle_response(), handle_response_invite(), redirecting_write(), and wait_for_answer().
02397 { 02398 ast_party_id_free(&doomed->from); 02399 ast_party_id_free(&doomed->to); 02400 }
void ast_party_redirecting_init | ( | struct ast_party_redirecting * | init | ) |
Initialize the given redirecting structure.
init | Redirecting structure to initialize. |
Definition at line 2359 of file channel.c.
References ast_party_id_init(), AST_REDIRECTING_REASON_UNKNOWN, ast_party_redirecting::count, ast_party_redirecting::from, ast_party_redirecting::reason, and ast_party_redirecting::to.
Referenced by __ast_channel_alloc_ap(), ast_channel_redirecting_macro(), call_forward_inherit(), do_forward(), handle_request_invite(), handle_response(), handle_response_invite(), and wait_for_answer().
02360 { 02361 ast_party_id_init(&init->from); 02362 ast_party_id_init(&init->to); 02363 init->count = 0; 02364 init->reason = AST_REDIRECTING_REASON_UNKNOWN; 02365 }
void ast_party_redirecting_set | ( | struct ast_party_redirecting * | dest, | |
const struct ast_party_redirecting * | src, | |||
const struct ast_set_party_redirecting * | update | |||
) |
Set the redirecting information based on another redirecting source.
This is similar to ast_party_redirecting_copy, except that NULL values for strings in the src parameter indicate not to update the corresponding dest values.
dest | The redirecting one wishes to update | |
src | The new redirecting values to update the dest | |
update | What redirecting information to update. NULL if all. |
Definition at line 2388 of file channel.c.
References ast_party_id_set(), ast_party_redirecting::count, ast_set_party_redirecting::from, ast_party_redirecting::from, ast_party_redirecting::reason, ast_set_party_redirecting::to, and ast_party_redirecting::to.
Referenced by ast_channel_set_redirecting().
void ast_party_redirecting_set_init | ( | struct ast_party_redirecting * | init, | |
const struct ast_party_redirecting * | guide | |||
) |
Initialize the given redirecting id structure using the given guide for a set update operation.
The initialization is needed to allow a set operation to know if a value needs to be updated. Simple integers need the guide's original value in case the set operation is not trying to set a new value. String values are simply set to NULL pointers if they are not going to be updated.
init | Redirecting id structure to initialize. | |
guide | Source redirecting id to use as a guide in initializing. |
Definition at line 2380 of file channel.c.
References ast_party_id_set_init(), ast_party_redirecting::count, ast_party_redirecting::from, ast_party_redirecting::reason, and ast_party_redirecting::to.
Referenced by ast_indicate_data(), misdn_copy_redirecting_to_ast(), and redirecting_write().
02381 { 02382 ast_party_id_set_init(&init->from, &guide->from); 02383 ast_party_id_set_init(&init->to, &guide->to); 02384 init->count = guide->count; 02385 init->reason = guide->reason; 02386 }
void ast_party_subaddress_copy | ( | struct ast_party_subaddress * | dest, | |
const struct ast_party_subaddress * | src | |||
) |
Copy the source party subaddress information to the destination party subaddress.
dest | Destination party subaddress | |
src | Source party subaddress |
Definition at line 2042 of file channel.c.
References ast_free, ast_strdup, ast_party_subaddress::odd_even_indicator, ast_party_subaddress::str, ast_party_subaddress::type, and ast_party_subaddress::valid.
Referenced by ast_party_dialed_copy(), and ast_party_id_copy().
02043 { 02044 if (dest == src) { 02045 /* Don't copy to self */ 02046 return; 02047 } 02048 02049 ast_free(dest->str); 02050 dest->str = ast_strdup(src->str); 02051 dest->type = src->type; 02052 dest->odd_even_indicator = src->odd_even_indicator; 02053 dest->valid = src->valid; 02054 }
void ast_party_subaddress_free | ( | struct ast_party_subaddress * | doomed | ) |
Destroy the party subaddress contents.
doomed | The party subaddress to destroy. |
Definition at line 2081 of file channel.c.
References ast_free, and ast_party_subaddress::str.
Referenced by ast_party_dialed_free(), and ast_party_id_free().
void ast_party_subaddress_init | ( | struct ast_party_subaddress * | init | ) |
Initialize the given subaddress structure.
init | Subaddress structure to initialize. |
Definition at line 2034 of file channel.c.
References ast_party_subaddress::odd_even_indicator, ast_party_subaddress::str, ast_party_subaddress::type, and ast_party_subaddress::valid.
Referenced by ast_party_dialed_init(), and ast_party_id_init().
02035 { 02036 init->str = NULL; 02037 init->type = 0; 02038 init->odd_even_indicator = 0; 02039 init->valid = 0; 02040 }
void ast_party_subaddress_set | ( | struct ast_party_subaddress * | dest, | |
const struct ast_party_subaddress * | src | |||
) |
Set the source party subaddress information into the destination party subaddress.
dest | The subaddress one wishes to update | |
src | The new subaddress values to update the dest |
Definition at line 2064 of file channel.c.
References ast_free, ast_strdup, ast_party_subaddress::odd_even_indicator, ast_party_subaddress::str, ast_party_subaddress::type, and ast_party_subaddress::valid.
Referenced by ast_party_dialed_set(), and ast_party_id_set().
02065 { 02066 if (dest == src) { 02067 /* Don't set to self */ 02068 return; 02069 } 02070 02071 if (src->str && src->str != dest->str) { 02072 ast_free(dest->str); 02073 dest->str = ast_strdup(src->str); 02074 } 02075 02076 dest->type = src->type; 02077 dest->odd_even_indicator = src->odd_even_indicator; 02078 dest->valid = src->valid; 02079 }
void ast_party_subaddress_set_init | ( | struct ast_party_subaddress * | init, | |
const struct ast_party_subaddress * | guide | |||
) |
Initialize the given party subaddress structure using the given guide for a set update operation.
The initialization is needed to allow a set operation to know if a value needs to be updated. Simple integers need the guide's original value in case the set operation is not trying to set a new value. String values are simply set to NULL pointers if they are not going to be updated.
init | Party subaddress structure to initialize. | |
guide | Source party subaddress to use as a guide in initializing. |
Definition at line 2056 of file channel.c.
References ast_party_subaddress::odd_even_indicator, ast_party_subaddress::str, ast_party_subaddress::type, and ast_party_subaddress::valid.
Referenced by ast_party_dialed_set_init(), and ast_party_id_set_init().
02057 { 02058 init->str = NULL; 02059 init->type = guide->type; 02060 init->odd_even_indicator = guide->odd_even_indicator; 02061 init->valid = guide->valid; 02062 }
int ast_plc_reload | ( | void | ) |
Reload genericplc configuration value from codecs.conf.
Implementation is in main/channel.c
Definition at line 8076 of file channel.c.
References ast_config_destroy(), ast_config_load, AST_OPT_FLAG_GENERIC_PLC, ast_options, ast_set2_flag, ast_true(), ast_variable_browse(), CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, ast_variable::name, ast_variable::next, ast_variable::value, and var.
Referenced by ast_channels_init().
08077 { 08078 struct ast_variable *var; 08079 struct ast_flags config_flags = { 0 }; 08080 struct ast_config *cfg = ast_config_load("codecs.conf", config_flags); 08081 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) 08082 return 0; 08083 for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) { 08084 if (!strcasecmp(var->name, "genericplc")) { 08085 ast_set2_flag(&ast_options, ast_true(var->value), AST_OPT_FLAG_GENERIC_PLC); 08086 } 08087 } 08088 ast_config_destroy(cfg); 08089 return 0; 08090 }
void ast_poll_channel_add | ( | struct ast_channel * | chan0, | |
struct ast_channel * | chan1 | |||
) |
Add a channel to an optimized waitfor
Definition at line 2665 of file channel.c.
References AST_MAX_FDS, and ast_channel::fds.
Referenced by ast_generic_bridge(), begin_dial_channel(), feature_request_and_dial(), local_bridge_loop(), remote_bridge_loop(), and wait_for_answer().
02666 { 02667 #ifdef HAVE_EPOLL 02668 struct epoll_event ev; 02669 int i = 0; 02670 02671 if (chan0->epfd == -1) 02672 return; 02673 02674 /* Iterate through the file descriptors on chan1, adding them to chan0 */ 02675 for (i = 0; i < AST_MAX_FDS; i++) { 02676 if (chan1->fds[i] == -1) 02677 continue; 02678 ev.events = EPOLLIN | EPOLLPRI | EPOLLERR | EPOLLHUP; 02679 ev.data.ptr = chan1->epfd_data[i]; 02680 epoll_ctl(chan0->epfd, EPOLL_CTL_ADD, chan1->fds[i], &ev); 02681 } 02682 02683 #endif 02684 return; 02685 }
void ast_poll_channel_del | ( | struct ast_channel * | chan0, | |
struct ast_channel * | chan1 | |||
) |
Delete a channel from an optimized waitfor
Definition at line 2688 of file channel.c.
References AST_MAX_FDS, and ast_channel::fds.
Referenced by ast_generic_bridge(), feature_request_and_dial(), local_bridge_loop(), monitor_dial(), remote_bridge_loop(), and wait_for_answer().
02689 { 02690 #ifdef HAVE_EPOLL 02691 struct epoll_event ev; 02692 int i = 0; 02693 02694 if (chan0->epfd == -1) 02695 return; 02696 02697 for (i = 0; i < AST_MAX_FDS; i++) { 02698 if (chan1->fds[i] == -1) 02699 continue; 02700 epoll_ctl(chan0->epfd, EPOLL_CTL_DEL, chan1->fds[i], &ev); 02701 } 02702 02703 #endif 02704 return; 02705 }
char* ast_print_group | ( | char * | buf, | |
int | buflen, | |||
ast_group_t | group | |||
) |
Print call group and pickup group ---.
print call- and pickup groups into buffer
Definition at line 8236 of file channel.c.
References first.
Referenced by _sip_show_peer(), _skinny_show_line(), func_channel_read(), function_sippeer(), misdn_cfg_get_config_string(), print_group(), read_config(), and serialize_showchan().
08237 { 08238 unsigned int i; 08239 int first = 1; 08240 char num[3]; 08241 08242 buf[0] = '\0'; 08243 08244 if (!group) /* Return empty string if no group */ 08245 return buf; 08246 08247 for (i = 0; i <= 63; i++) { /* Max group is 63 */ 08248 if (group & ((ast_group_t) 1 << i)) { 08249 if (!first) { 08250 strncat(buf, ", ", buflen - strlen(buf) - 1); 08251 } else { 08252 first = 0; 08253 } 08254 snprintf(num, sizeof(num), "%u", i); 08255 strncat(buf, num, buflen - strlen(buf) - 1); 08256 } 08257 } 08258 return buf; 08259 }
int ast_prod | ( | struct ast_channel * | chan | ) |
Send empty audio to prime a channel driver.
Definition at line 4784 of file channel.c.
References ast_channel::_state, ast_debug, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), AST_STATE_UP, ast_write(), ast_frame_subclass::codec, ast_frame::data, LOG_WARNING, ast_frame::ptr, ast_channel::rawwriteformat, ast_frame::src, and ast_frame::subclass.
Referenced by ast_activate_generator().
04785 { 04786 struct ast_frame a = { AST_FRAME_VOICE }; 04787 char nothing[128]; 04788 04789 /* Send an empty audio frame to get things moving */ 04790 if (chan->_state != AST_STATE_UP) { 04791 ast_debug(1, "Prodding channel '%s'\n", chan->name); 04792 a.subclass.codec = chan->rawwriteformat; 04793 a.data.ptr = nothing + AST_FRIENDLY_OFFSET; 04794 a.src = "ast_prod"; /* this better match check in ast_write */ 04795 if (ast_write(chan, &a)) 04796 ast_log(LOG_WARNING, "Prodding channel '%s' failed\n", chan->name); 04797 } 04798 return 0; 04799 }
int ast_queue_control | ( | struct ast_channel * | chan, | |
enum ast_control_frame_type | control | |||
) |
Queue a control frame.
Queue a control frame with payload.
Definition at line 1601 of file channel.c.
References AST_FRAME_CONTROL, and ast_queue_frame().
Referenced by __analog_handle_event(), __analog_ss_thread(), __ast_read(), __dahdi_exception(), __oh323_update_info(), analog_call(), analog_exception(), analog_hangup(), analog_ss_thread(), ast_do_pickup(), attempt_transfer(), auto_congest(), cb_events(), cli_console_answer(), cli_console_flash(), console_answer(), console_call(), console_sendtext(), dahdi_handle_event(), dahdi_hangup(), gtalk_is_answered(), gtalk_ringing_ack(), handle_hd_hf(), handle_incoming(), handle_offhook_message(), handle_request(), handle_request_bye(), handle_request_info(), handle_request_invite(), handle_request_refer(), handle_response(), handle_response_invite(), handle_response_refer(), handle_soft_key_event_message(), handle_stimulus_message(), HandleCallIncoming(), jingle_is_answered(), jingle_ringing_ack(), masquerade_colp_transfer(), misdn_facility_ie_handler(), multicast_rtp_call(), nbs_call(), phone_call(), process_sdp(), receive_digit(), remote_hold(), send_cause2ast(), setup_rtp_connection(), skinny_call(), skinny_transfer(), skinny_unhold(), unistim_call(), and update_state().
01602 { 01603 struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = control }; 01604 return ast_queue_frame(chan, &f); 01605 }
int ast_queue_control_data | ( | struct ast_channel * | chan, | |
enum ast_control_frame_type | control, | |||
const void * | data, | |||
size_t | datalen | |||
) |
Queue a control frame with payload.
chan | channel to queue frame onto | |
control | type of control frame | |
data | pointer to payload data to be included in frame | |
datalen | number of bytes of payload data |
0 | success | |
non-zero | failure |
The supplied payload data is copied into the frame, so the caller's copy is not modified nor freed, and the resulting frame will retain a copy of the data even if the caller frees their local copy.
Definition at line 1608 of file channel.c.
References AST_FRAME_CONTROL, and ast_queue_frame().
Referenced by __analog_handle_event(), analog_hangup(), ast_channel_queue_connected_line_update(), ast_channel_queue_redirecting_update(), change_t38_state(), dahdi_handle_event(), dahdi_hangup(), handle_request_notify(), handle_response_refer(), iax2_queue_control_data(), iax2_transfer(), interpret_t38_parameters(), local_attended_transfer(), masquerade_colp_transfer(), process_sdp(), sip_sipredirect(), and skinny_hold().
01610 { 01611 struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = control, .data.ptr = (void *) data, .datalen = datalen }; 01612 return ast_queue_frame(chan, &f); 01613 }
int ast_queue_frame | ( | struct ast_channel * | chan, | |
struct ast_frame * | f | |||
) |
Queue one or more frames to a channel's frame queue.
chan | the channel to queue the frame(s) on | |
f | the frame(s) to queue. Note that the frame(s) will be duplicated by this function. It is the responsibility of the caller to handle freeing the memory associated with the frame(s) being passed if necessary. |
0 | success | |
non-zero | failure |
Definition at line 1558 of file channel.c.
References __ast_queue_frame().
Referenced by __ast_channel_masquerade(), __ast_read(), __oh323_rtp_create(), __oh323_update_info(), action_atxfer(), agent_request(), alsa_call(), ast_channel_setwhentohangup_tv(), ast_do_masquerade(), ast_dsp_process(), ast_queue_cc_frame(), ast_queue_control(), ast_queue_control_data(), ast_queue_hangup(), ast_queue_hangup_with_cause(), ast_softhangup_nolock(), bridge_write(), cb_events(), cli_console_dial(), cli_console_sendtext(), console_dial(), console_do_answer(), console_flash(), console_sendtext(), dahdi_queue_frame(), dahdi_read(), dictate_exec(), do_immediate_setup(), gtalk_handle_dtmf(), handle_keypad_button_message(), handle_request_info(), handle_request_invite(), handle_response_invite(), iax2_queue_frame(), jingle_handle_dtmf(), local_queue_frame(), mgcp_queue_frame(), oh323_simulate_dtmf_end(), oss_call(), process_sdp(), queue_dtmf_readq(), receive_digit(), receive_message(), stream_monitor(), unistim_do_senddigit(), unistim_senddigit_end(), and wakeup_sub().
01559 { 01560 return __ast_queue_frame(chan, fin, 0, NULL); 01561 }
int ast_queue_frame_head | ( | struct ast_channel * | chan, | |
struct ast_frame * | f | |||
) |
Queue one or more frames to the head of a channel's frame queue.
chan | the channel to queue the frame(s) on | |
f | the frame(s) to queue. Note that the frame(s) will be duplicated by this function. It is the responsibility of the caller to handle freeing the memory associated with the frame(s) being passed if necessary. |
0 | success | |
non-zero | failure |
Definition at line 1563 of file channel.c.
References __ast_queue_frame().
Referenced by __ast_answer(), __ast_read(), ast_autoservice_stop(), ast_safe_sleep_conditional(), and feature_request_and_dial().
01564 { 01565 return __ast_queue_frame(chan, fin, 1, NULL); 01566 }
int ast_queue_hangup | ( | struct ast_channel * | chan | ) |
Queue a hangup frame for channel.
Queue a hangup frame.
Definition at line 1569 of file channel.c.
References ast_channel::_softhangup, ast_channel_trylock, ast_channel_unlock, AST_CONTROL_HANGUP, AST_FRAME_CONTROL, ast_queue_frame(), and AST_SOFTHANGUP_DEV.
Referenced by bridge_queue_hangup(), cleanup_connection(), cli_console_hangup(), close_call(), gtalk_hangup_farend(), gtalk_is_answered(), handle_onhook_message(), handle_request_bye(), handle_soft_key_event_message(), iax2_destroy(), iax2_queue_hangup(), jingle_hangup_farend(), local_fixup(), local_hangup(), mgcp_queue_hangup(), and sip_queue_hangup_cause().
01570 { 01571 struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_HANGUP }; 01572 /* Yeah, let's not change a lock-critical value without locking */ 01573 if (!ast_channel_trylock(chan)) { 01574 chan->_softhangup |= AST_SOFTHANGUP_DEV; 01575 ast_channel_unlock(chan); 01576 } 01577 return ast_queue_frame(chan, &f); 01578 }
int ast_queue_hangup_with_cause | ( | struct ast_channel * | chan, | |
int | cause | |||
) |
Queue a hangup frame for channel.
Queue a hangup frame with hangupcause set.
Definition at line 1581 of file channel.c.
References ast_channel::_softhangup, ast_channel_trylock, ast_channel_unlock, AST_CONTROL_HANGUP, AST_FRAME_CONTROL, ast_queue_frame(), AST_SOFTHANGUP_DEV, ast_frame::data, ast_channel::hangupcause, and ast_frame::uint32.
Referenced by __analog_handle_event(), __oh323_update_info(), __sip_autodestruct(), close_call(), close_client(), console_hangup(), dahdi_handle_event(), handle_request_bye(), handle_response(), handle_response_invite(), HandleCallOutgoing(), hangup_chan(), hangup_connection(), local_hangup(), misdn_answer(), retrans_pkt(), sip_queue_hangup_cause(), and TransferCallStep1().
01582 { 01583 struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_HANGUP }; 01584 01585 if (cause >= 0) 01586 f.data.uint32 = cause; 01587 01588 /* Yeah, let's not change a lock-critical value without locking */ 01589 if (!ast_channel_trylock(chan)) { 01590 chan->_softhangup |= AST_SOFTHANGUP_DEV; 01591 if (cause < 0) 01592 f.data.uint32 = chan->hangupcause; 01593 01594 ast_channel_unlock(chan); 01595 } 01596 01597 return ast_queue_frame(chan, &f); 01598 }
int ast_raw_answer | ( | struct ast_channel * | chan, | |
int | cdr_answer | |||
) |
Answer a channel.
chan | channel to answer | |
cdr_answer | flag to control whether any associated CDR should be marked as 'answered' |
This function answers a channel and handles all necessary call setup functions.
0 | on success | |
non-zero | on failure |
Definition at line 2930 of file channel.c.
References ast_channel::_state, ast_channel_tech::answer, ast_cdr_answer(), AST_CEL_ANSWER, ast_cel_report_event(), ast_channel_lock, ast_channel_unlock, ast_check_hangup(), AST_FLAG_OUTGOING, AST_FLAG_ZOMBIE, ast_indicate(), ast_setstate(), AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_test_flag, ast_channel::cdr, and ast_channel::tech.
Referenced by __ast_answer(), and ast_bridge_call().
02931 { 02932 int res = 0; 02933 02934 ast_channel_lock(chan); 02935 02936 /* You can't answer an outbound call */ 02937 if (ast_test_flag(chan, AST_FLAG_OUTGOING)) { 02938 ast_channel_unlock(chan); 02939 return 0; 02940 } 02941 02942 /* Stop if we're a zombie or need a soft hangup */ 02943 if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) { 02944 ast_channel_unlock(chan); 02945 return -1; 02946 } 02947 02948 ast_channel_unlock(chan); 02949 02950 switch (chan->_state) { 02951 case AST_STATE_RINGING: 02952 case AST_STATE_RING: 02953 ast_channel_lock(chan); 02954 if (chan->tech->answer) { 02955 res = chan->tech->answer(chan); 02956 } 02957 ast_setstate(chan, AST_STATE_UP); 02958 if (cdr_answer) { 02959 ast_cdr_answer(chan->cdr); 02960 } 02961 ast_cel_report_event(chan, AST_CEL_ANSWER, NULL, NULL, NULL); 02962 ast_channel_unlock(chan); 02963 break; 02964 case AST_STATE_UP: 02965 ast_cel_report_event(chan, AST_CEL_ANSWER, NULL, NULL, NULL); 02966 /* Calling ast_cdr_answer when it it has previously been called 02967 * is essentially a no-op, so it is safe. 02968 */ 02969 if (cdr_answer) { 02970 ast_cdr_answer(chan->cdr); 02971 } 02972 break; 02973 default: 02974 break; 02975 } 02976 02977 ast_indicate(chan, -1); 02978 02979 return res; 02980 }
struct ast_frame* ast_read | ( | struct ast_channel * | chan | ) | [read] |
Reads a frame.
chan | channel to read a frame from |
Definition at line 4383 of file channel.c.
References __ast_read().
Referenced by __adsi_transmit_messages(), __analog_ss_thread(), __ast_answer(), __ast_play_and_record(), __ast_request_and_dial(), adsi_careful_send(), agent_ack_sleep(), agent_read(), analog_ss_thread(), ast_bridge_handle_trip(), ast_generic_bridge(), ast_recvtext(), ast_safe_sleep_conditional(), ast_tonepair(), ast_transfer(), ast_udptl_bridge(), ast_waitfordigit_full(), async_agi_read_frame(), async_wait(), autoservice_run(), background_detect_exec(), channel_spy(), conf_flush(), conf_run(), dahdi_bridge(), dial_exec_full(), dictate_exec(), disa_exec(), disable_t38(), do_waiting(), echo_exec(), eivr_comm(), feature_request_and_dial(), find_cache(), generic_fax_exec(), handle_recordfile(), handle_speechrecognize(), iax2_bridge(), ices_exec(), isAnsweringMachine(), jack_exec(), local_bridge_loop(), manage_parked_call(), measurenoise(), misdn_bridge(), monitor_dial(), mp3_exec(), NBScat_exec(), receive_dtmf_digits(), receivefax_t38_init(), record_exec(), recordthread(), remote_bridge_loop(), run_agi(), send_tone_burst(), send_waveform_to_channel(), sendfax_t38_init(), sendurl_exec(), speech_background(), transmit_audio(), transmit_t38(), wait_for_answer(), wait_for_hangup(), wait_for_winner(), waitforring_exec(), and waitstream_core().
04384 { 04385 return __ast_read(chan, 0); 04386 }
static void ast_read_generator_actions | ( | struct ast_channel * | chan, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 3722 of file channel.c.
References ast_channel_lock, ast_channel_unlock, ast_deactivate_generator(), ast_debug, ast_format_rate(), AST_FRAME_VOICE, ast_frame_subclass::codec, ast_frame::datalen, ast_frame::frametype, ast_generator::generate, ast_channel::generator, generator, ast_channel::generatordata, ast_frame::samples, ast_frame::subclass, ast_channel::timingfunc, and ast_channel::writeformat.
Referenced by __ast_read().
03723 { 03724 struct ast_generator *generator; 03725 void *gendata; 03726 int res; 03727 int samples; 03728 03729 generator = chan->generator; 03730 if (!generator 03731 || !generator->generate 03732 || f->frametype != AST_FRAME_VOICE 03733 || !chan->generatordata 03734 || chan->timingfunc) { 03735 return; 03736 } 03737 03738 /* 03739 * We must generate frames in phase locked mode since 03740 * we have no internal timer available. 03741 */ 03742 03743 if (f->subclass.codec != chan->writeformat) { 03744 float factor; 03745 03746 factor = ((float) ast_format_rate(chan->writeformat)) / ((float) ast_format_rate(f->subclass.codec)); 03747 samples = (int) (((float) f->samples) * factor); 03748 } else { 03749 samples = f->samples; 03750 } 03751 03752 gendata = chan->generatordata; 03753 chan->generatordata = NULL; /* reset, to let writes go through */ 03754 03755 /* 03756 * This unlock is here based on two assumptions that hold true at 03757 * this point in the code. 1) this function is only called from 03758 * within __ast_read() and 2) all generators call ast_write() in 03759 * their generate callback. 03760 * 03761 * The reason this is added is so that when ast_write is called, 03762 * the lock that occurs there will not recursively lock the 03763 * channel. Doing this will allow deadlock avoidance to work in 03764 * deeper functions. 03765 */ 03766 ast_channel_unlock(chan); 03767 res = generator->generate(chan, gendata, f->datalen, samples); 03768 ast_channel_lock(chan); 03769 if (generator == chan->generator) { 03770 chan->generatordata = gendata; 03771 if (res) { 03772 ast_debug(1, "Auto-deactivating generator\n"); 03773 ast_deactivate_generator(chan); 03774 } 03775 } 03776 }
struct ast_frame* ast_read_noaudio | ( | struct ast_channel * | chan | ) | [read] |
Reads a frame, returning AST_FRAME_NULL frame if audio.
chan | channel to read a frame from |
Definition at line 4388 of file channel.c.
References __ast_read().
Referenced by ast_bridge_handle_trip(), and conf_run().
04389 { 04390 return __ast_read(chan, 1); 04391 }
int ast_readstring | ( | struct ast_channel * | c, | |
char * | s, | |||
int | len, | |||
int | timeout, | |||
int | rtimeout, | |||
char * | enders | |||
) |
Reads multiple digits.
c | channel to read from | |
s | string to read in to. Must be at least the size of your length | |
len | how many digits to read (maximum) | |
timeout | how long to timeout between digits | |
rtimeout | timeout to wait on the first digit | |
enders | digits to end the string |
Read in a digit string "s", max length "len", maximum timeout between digits "timeout" (-1 for none), terminated by anything in "enders". Give them rtimeout for the first digit.
Definition at line 5837 of file channel.c.
References ast_readstring_full().
Referenced by __adsi_transmit_messages(), adsi_begin_download(), adsi_get_cpeinfo(), adsi_load_session(), ast_app_getdata(), dialout(), do_directory(), forward_message(), privacy_exec(), vm_authenticate(), vm_newuser(), and vm_options().
05838 { 05839 return ast_readstring_full(c, s, len, timeout, ftimeout, enders, -1, -1); 05840 }
int ast_readstring_full | ( | struct ast_channel * | c, | |
char * | s, | |||
int | len, | |||
int | timeout, | |||
int | ftimeout, | |||
char * | enders, | |||
int | audiofd, | |||
int | ctrlfd | |||
) |
Definition at line 5842 of file channel.c.
References ast_channel_start_silence_generator(), ast_channel_stop_silence_generator(), ast_check_hangup(), AST_DIGIT_ANY, AST_FLAG_ZOMBIE, AST_GETDATA_COMPLETE, AST_GETDATA_EMPTY_END_TERMINATED, AST_GETDATA_FAILED, AST_GETDATA_INTERRUPTED, AST_GETDATA_TIMEOUT, ast_opt_transmit_silence, ast_stopstream(), ast_test_flag, ast_waitfordigit_full(), ast_waitstream_full(), and ast_channel::stream.
Referenced by ast_app_getdata_full(), and ast_readstring().
05843 { 05844 int pos = 0; /* index in the buffer where we accumulate digits */ 05845 int to = ftimeout; 05846 05847 struct ast_silence_generator *silgen = NULL; 05848 05849 /* Stop if we're a zombie or need a soft hangup */ 05850 if (ast_test_flag(c, AST_FLAG_ZOMBIE) || ast_check_hangup(c)) 05851 return -1; 05852 if (!len) 05853 return -1; 05854 for (;;) { 05855 int d; 05856 if (c->stream) { 05857 d = ast_waitstream_full(c, AST_DIGIT_ANY, audiofd, ctrlfd); 05858 ast_stopstream(c); 05859 if (!silgen && ast_opt_transmit_silence) 05860 silgen = ast_channel_start_silence_generator(c); 05861 usleep(1000); 05862 if (!d) 05863 d = ast_waitfordigit_full(c, to, audiofd, ctrlfd); 05864 } else { 05865 if (!silgen && ast_opt_transmit_silence) 05866 silgen = ast_channel_start_silence_generator(c); 05867 d = ast_waitfordigit_full(c, to, audiofd, ctrlfd); 05868 } 05869 if (d < 0) { 05870 ast_channel_stop_silence_generator(c, silgen); 05871 return AST_GETDATA_FAILED; 05872 } 05873 if (d == 0) { 05874 s[pos] = '\0'; 05875 ast_channel_stop_silence_generator(c, silgen); 05876 return AST_GETDATA_TIMEOUT; 05877 } 05878 if (d == 1) { 05879 s[pos] = '\0'; 05880 ast_channel_stop_silence_generator(c, silgen); 05881 return AST_GETDATA_INTERRUPTED; 05882 } 05883 if (strchr(enders, d) && (pos == 0)) { 05884 s[pos] = '\0'; 05885 ast_channel_stop_silence_generator(c, silgen); 05886 return AST_GETDATA_EMPTY_END_TERMINATED; 05887 } 05888 if (!strchr(enders, d)) { 05889 s[pos++] = d; 05890 } 05891 if (strchr(enders, d) || (pos >= len)) { 05892 s[pos] = '\0'; 05893 ast_channel_stop_silence_generator(c, silgen); 05894 return AST_GETDATA_COMPLETE; 05895 } 05896 to = timeout; 05897 } 05898 /* Never reached */ 05899 return 0; 05900 }
int ast_recvchar | ( | struct ast_channel * | chan, | |
int | timeout | |||
) |
Receives a text character from a channel.
chan | channel to act upon | |
timeout | timeout in milliseconds (0 for infinite wait) |
Read a char of text from a channel
Definition at line 4642 of file channel.c.
References ast_free, and ast_recvtext().
Referenced by handle_recvchar().
04643 { 04644 int c; 04645 char *buf = ast_recvtext(chan, timeout); 04646 if (buf == NULL) 04647 return -1; /* error or timeout */ 04648 c = *(unsigned char *)buf; 04649 ast_free(buf); 04650 return c; 04651 }
char* ast_recvtext | ( | struct ast_channel * | chan, | |
int | timeout | |||
) |
Receives a text string from a channel Read a string of text from a channel.
chan | channel to act upon | |
timeout | timeout in milliseconds (0 for infinite wait) |
Definition at line 4653 of file channel.c.
References ast_check_hangup(), AST_CONTROL_HANGUP, AST_FRAME_CONTROL, AST_FRAME_TEXT, ast_frfree, ast_read(), ast_remaining_ms(), ast_strndup, ast_tvnow(), ast_waitfor(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, ast_frame_subclass::integer, ast_frame::ptr, and ast_frame::subclass.
Referenced by ast_recvchar(), and handle_recvtext().
04654 { 04655 int res; 04656 char *buf = NULL; 04657 struct timeval start = ast_tvnow(); 04658 int ms; 04659 04660 while ((ms = ast_remaining_ms(start, timeout))) { 04661 struct ast_frame *f; 04662 04663 if (ast_check_hangup(chan)) { 04664 break; 04665 } 04666 res = ast_waitfor(chan, ms); 04667 if (res <= 0) {/* timeout or error */ 04668 break; 04669 } 04670 f = ast_read(chan); 04671 if (f == NULL) { 04672 break; /* no frame */ 04673 } 04674 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) { 04675 ast_frfree(f); 04676 break; 04677 } else if (f->frametype == AST_FRAME_TEXT) { /* what we want */ 04678 buf = ast_strndup((char *) f->data.ptr, f->datalen); /* dup and break */ 04679 ast_frfree(f); 04680 break; 04681 } 04682 ast_frfree(f); 04683 } 04684 return buf; 04685 }
int ast_redirecting_build_data | ( | unsigned char * | data, | |
size_t | datalen, | |||
const struct ast_party_redirecting * | redirecting, | |||
const struct ast_set_party_redirecting * | update | |||
) |
Build the redirecting id data frame.
data | Buffer to fill with the frame data | |
datalen | Size of the buffer to fill | |
redirecting | Redirecting id information | |
update | What redirecting information to build. NULL if all. |
-1 | if error | |
Amount | of data buffer used |
Definition at line 9161 of file channel.c.
References ast_log(), AST_REDIRECTING_COUNT, AST_REDIRECTING_FROM_ID_PRESENTATION, AST_REDIRECTING_FROM_NAME, AST_REDIRECTING_FROM_NAME_CHAR_SET, AST_REDIRECTING_FROM_NAME_PRESENTATION, AST_REDIRECTING_FROM_NAME_VALID, AST_REDIRECTING_FROM_NUMBER, AST_REDIRECTING_FROM_NUMBER_PLAN, AST_REDIRECTING_FROM_NUMBER_PRESENTATION, AST_REDIRECTING_FROM_NUMBER_VALID, AST_REDIRECTING_FROM_SUBADDRESS, AST_REDIRECTING_FROM_SUBADDRESS_ODD_EVEN, AST_REDIRECTING_FROM_SUBADDRESS_TYPE, AST_REDIRECTING_FROM_SUBADDRESS_VALID, AST_REDIRECTING_FROM_TAG, AST_REDIRECTING_TO_ID_PRESENTATION, AST_REDIRECTING_TO_NAME, AST_REDIRECTING_TO_NAME_CHAR_SET, AST_REDIRECTING_TO_NAME_PRESENTATION, AST_REDIRECTING_TO_NAME_VALID, AST_REDIRECTING_TO_NUMBER, AST_REDIRECTING_TO_NUMBER_PLAN, AST_REDIRECTING_TO_NUMBER_PRESENTATION, AST_REDIRECTING_TO_NUMBER_VALID, AST_REDIRECTING_TO_SUBADDRESS, AST_REDIRECTING_TO_SUBADDRESS_ODD_EVEN, AST_REDIRECTING_TO_SUBADDRESS_TYPE, AST_REDIRECTING_TO_SUBADDRESS_VALID, AST_REDIRECTING_TO_TAG, AST_REDIRECTING_VERSION, ast_party_redirecting::count, ast_set_party_redirecting::from, ast_party_redirecting::from, LOG_WARNING, ast_party_id_ies::name, party_id_build_data(), ast_party_redirecting::reason, ast_party_name_ies::str, ast_set_party_redirecting::to, ast_party_redirecting::to, and value.
Referenced by ast_channel_queue_redirecting_update(), ast_channel_update_redirecting(), and local_indicate().
09162 { 09163 int32_t value; 09164 size_t pos = 0; 09165 int res; 09166 09167 static const struct ast_party_id_ies from_ies = { 09168 .name.str = AST_REDIRECTING_FROM_NAME, 09169 .name.char_set = AST_REDIRECTING_FROM_NAME_CHAR_SET, 09170 .name.presentation = AST_REDIRECTING_FROM_NAME_PRESENTATION, 09171 .name.valid = AST_REDIRECTING_FROM_NAME_VALID, 09172 09173 .number.str = AST_REDIRECTING_FROM_NUMBER, 09174 .number.plan = AST_REDIRECTING_FROM_NUMBER_PLAN, 09175 .number.presentation = AST_REDIRECTING_FROM_NUMBER_PRESENTATION, 09176 .number.valid = AST_REDIRECTING_FROM_NUMBER_VALID, 09177 09178 .subaddress.str = AST_REDIRECTING_FROM_SUBADDRESS, 09179 .subaddress.type = AST_REDIRECTING_FROM_SUBADDRESS_TYPE, 09180 .subaddress.odd_even_indicator = AST_REDIRECTING_FROM_SUBADDRESS_ODD_EVEN, 09181 .subaddress.valid = AST_REDIRECTING_FROM_SUBADDRESS_VALID, 09182 09183 .tag = AST_REDIRECTING_FROM_TAG, 09184 .combined_presentation = AST_REDIRECTING_FROM_ID_PRESENTATION, 09185 }; 09186 static const struct ast_party_id_ies to_ies = { 09187 .name.str = AST_REDIRECTING_TO_NAME, 09188 .name.char_set = AST_REDIRECTING_TO_NAME_CHAR_SET, 09189 .name.presentation = AST_REDIRECTING_TO_NAME_PRESENTATION, 09190 .name.valid = AST_REDIRECTING_TO_NAME_VALID, 09191 09192 .number.str = AST_REDIRECTING_TO_NUMBER, 09193 .number.plan = AST_REDIRECTING_TO_NUMBER_PLAN, 09194 .number.presentation = AST_REDIRECTING_TO_NUMBER_PRESENTATION, 09195 .number.valid = AST_REDIRECTING_TO_NUMBER_VALID, 09196 09197 .subaddress.str = AST_REDIRECTING_TO_SUBADDRESS, 09198 .subaddress.type = AST_REDIRECTING_TO_SUBADDRESS_TYPE, 09199 .subaddress.odd_even_indicator = AST_REDIRECTING_TO_SUBADDRESS_ODD_EVEN, 09200 .subaddress.valid = AST_REDIRECTING_TO_SUBADDRESS_VALID, 09201 09202 .tag = AST_REDIRECTING_TO_TAG, 09203 .combined_presentation = AST_REDIRECTING_TO_ID_PRESENTATION, 09204 }; 09205 09206 /* Redirecting frame version */ 09207 if (datalen < pos + (sizeof(data[0]) * 2) + 1) { 09208 ast_log(LOG_WARNING, "No space left for redirecting frame version\n"); 09209 return -1; 09210 } 09211 data[pos++] = AST_REDIRECTING_VERSION; 09212 data[pos++] = 1; 09213 data[pos++] = 2;/* Version 1 did not have a version ie */ 09214 09215 res = party_id_build_data(data + pos, datalen - pos, &redirecting->from, 09216 "redirecting-from", &from_ies, update ? &update->from : NULL); 09217 if (res < 0) { 09218 return -1; 09219 } 09220 pos += res; 09221 09222 res = party_id_build_data(data + pos, datalen - pos, &redirecting->to, 09223 "redirecting-to", &to_ies, update ? &update->to : NULL); 09224 if (res < 0) { 09225 return -1; 09226 } 09227 pos += res; 09228 09229 /* Redirecting reason */ 09230 if (datalen < pos + (sizeof(data[0]) * 2) + sizeof(value)) { 09231 ast_log(LOG_WARNING, "No space left for redirecting reason\n"); 09232 return -1; 09233 } 09234 data[pos++] = AST_REDIRECTING_REASON; 09235 data[pos++] = sizeof(value); 09236 value = htonl(redirecting->reason); 09237 memcpy(data + pos, &value, sizeof(value)); 09238 pos += sizeof(value); 09239 09240 /* Redirecting count */ 09241 if (datalen < pos + (sizeof(data[0]) * 2) + sizeof(value)) { 09242 ast_log(LOG_WARNING, "No space left for redirecting count\n"); 09243 return -1; 09244 } 09245 data[pos++] = AST_REDIRECTING_COUNT; 09246 data[pos++] = sizeof(value); 09247 value = htonl(redirecting->count); 09248 memcpy(data + pos, &value, sizeof(value)); 09249 pos += sizeof(value); 09250 09251 return pos; 09252 }
int ast_redirecting_parse_data | ( | const unsigned char * | data, | |
size_t | datalen, | |||
struct ast_party_redirecting * | redirecting | |||
) |
Parse redirecting indication frame data.
data | Buffer with the frame data to parse | |
datalen | Size of the buffer | |
redirecting | Extracted redirecting id information |
0 | on success. | |
-1 | on error. |
Definition at line 9254 of file channel.c.
References ast_free, ast_log(), ast_malloc, AST_PARTY_CHAR_SET_ISO8859_1, AST_REDIRECTING_COUNT, AST_REDIRECTING_FROM_ID_PRESENTATION, AST_REDIRECTING_FROM_NAME, AST_REDIRECTING_FROM_NAME_CHAR_SET, AST_REDIRECTING_FROM_NAME_PRESENTATION, AST_REDIRECTING_FROM_NAME_VALID, AST_REDIRECTING_FROM_NUMBER, AST_REDIRECTING_FROM_NUMBER_PLAN, AST_REDIRECTING_FROM_NUMBER_PRESENTATION, AST_REDIRECTING_FROM_NUMBER_VALID, AST_REDIRECTING_FROM_SUBADDRESS, AST_REDIRECTING_FROM_SUBADDRESS_ODD_EVEN, AST_REDIRECTING_FROM_SUBADDRESS_TYPE, AST_REDIRECTING_FROM_SUBADDRESS_VALID, AST_REDIRECTING_FROM_TAG, AST_REDIRECTING_TO_ID_PRESENTATION, AST_REDIRECTING_TO_NAME, AST_REDIRECTING_TO_NAME_CHAR_SET, AST_REDIRECTING_TO_NAME_PRESENTATION, AST_REDIRECTING_TO_NAME_VALID, AST_REDIRECTING_TO_NUMBER, AST_REDIRECTING_TO_NUMBER_PLAN, AST_REDIRECTING_TO_NUMBER_PRESENTATION, AST_REDIRECTING_TO_NUMBER_VALID, AST_REDIRECTING_TO_SUBADDRESS, AST_REDIRECTING_TO_SUBADDRESS_ODD_EVEN, AST_REDIRECTING_TO_SUBADDRESS_TYPE, AST_REDIRECTING_TO_SUBADDRESS_VALID, AST_REDIRECTING_TO_TAG, AST_REDIRECTING_VERSION, ast_party_name::char_set, ast_party_redirecting::count, ast_party_redirecting::from, LOG_DEBUG, LOG_WARNING, ast_party_id::name, ast_party_id::number, ast_party_subaddress::odd_even_indicator, ast_party_number::plan, ast_party_number::presentation, ast_party_name::presentation, ast_party_redirecting::reason, ast_party_subaddress::str, ast_party_number::str, ast_party_name::str, ast_party_id::subaddress, ast_party_id::tag, ast_party_redirecting::to, ast_party_subaddress::type, ast_party_subaddress::valid, ast_party_number::valid, ast_party_name::valid, and value.
Referenced by ast_channel_redirecting_macro(), and ast_indicate_data().
09255 { 09256 size_t pos; 09257 unsigned char ie_len; 09258 unsigned char ie_id; 09259 int32_t value; 09260 int frame_version = 1; 09261 int from_combined_presentation = 0; 09262 int got_from_combined_presentation = 0;/* TRUE if got a combined name and number presentation value. */ 09263 int to_combined_presentation = 0; 09264 int got_to_combined_presentation = 0;/* TRUE if got a combined name and number presentation value. */ 09265 09266 for (pos = 0; pos < datalen; pos += ie_len) { 09267 if (datalen < pos + sizeof(ie_id) + sizeof(ie_len)) { 09268 ast_log(LOG_WARNING, "Invalid redirecting update\n"); 09269 return -1; 09270 } 09271 ie_id = data[pos++]; 09272 ie_len = data[pos++]; 09273 if (datalen < pos + ie_len) { 09274 ast_log(LOG_WARNING, "Invalid redirecting update\n"); 09275 return -1; 09276 } 09277 09278 switch (ie_id) { 09279 /* Redirecting frame version */ 09280 case AST_REDIRECTING_VERSION: 09281 if (ie_len != 1) { 09282 ast_log(LOG_WARNING, "Invalid redirecting frame version (%u)\n", 09283 (unsigned) ie_len); 09284 break; 09285 } 09286 frame_version = data[pos]; 09287 break; 09288 /* Redirecting-from party id name */ 09289 case AST_REDIRECTING_FROM_NAME: 09290 ast_free(redirecting->from.name.str); 09291 redirecting->from.name.str = ast_malloc(ie_len + 1); 09292 if (redirecting->from.name.str) { 09293 memcpy(redirecting->from.name.str, data + pos, ie_len); 09294 redirecting->from.name.str[ie_len] = 0; 09295 } 09296 break; 09297 case AST_REDIRECTING_FROM_NAME_CHAR_SET: 09298 if (ie_len != 1) { 09299 ast_log(LOG_WARNING, "Invalid redirecting-from name char set (%u)\n", 09300 (unsigned) ie_len); 09301 break; 09302 } 09303 redirecting->from.name.char_set = data[pos]; 09304 break; 09305 case AST_REDIRECTING_FROM_NAME_PRESENTATION: 09306 if (ie_len != 1) { 09307 ast_log(LOG_WARNING, "Invalid redirecting-from name presentation (%u)\n", 09308 (unsigned) ie_len); 09309 break; 09310 } 09311 redirecting->from.name.presentation = data[pos]; 09312 break; 09313 case AST_REDIRECTING_FROM_NAME_VALID: 09314 if (ie_len != 1) { 09315 ast_log(LOG_WARNING, "Invalid redirecting-from name valid (%u)\n", 09316 (unsigned) ie_len); 09317 break; 09318 } 09319 redirecting->from.name.valid = data[pos]; 09320 break; 09321 /* Redirecting-from party id number */ 09322 case AST_REDIRECTING_FROM_NUMBER: 09323 ast_free(redirecting->from.number.str); 09324 redirecting->from.number.str = ast_malloc(ie_len + 1); 09325 if (redirecting->from.number.str) { 09326 memcpy(redirecting->from.number.str, data + pos, ie_len); 09327 redirecting->from.number.str[ie_len] = 0; 09328 } 09329 break; 09330 case AST_REDIRECTING_FROM_NUMBER_PLAN: 09331 if (ie_len != 1) { 09332 ast_log(LOG_WARNING, "Invalid redirecting-from numbering plan (%u)\n", 09333 (unsigned) ie_len); 09334 break; 09335 } 09336 redirecting->from.number.plan = data[pos]; 09337 break; 09338 case AST_REDIRECTING_FROM_NUMBER_PRESENTATION: 09339 if (ie_len != 1) { 09340 ast_log(LOG_WARNING, "Invalid redirecting-from number presentation (%u)\n", 09341 (unsigned) ie_len); 09342 break; 09343 } 09344 redirecting->from.number.presentation = data[pos]; 09345 break; 09346 case AST_REDIRECTING_FROM_NUMBER_VALID: 09347 if (ie_len != 1) { 09348 ast_log(LOG_WARNING, "Invalid redirecting-from number valid (%u)\n", 09349 (unsigned) ie_len); 09350 break; 09351 } 09352 redirecting->from.number.valid = data[pos]; 09353 break; 09354 /* Redirecting-from party id combined presentation */ 09355 case AST_REDIRECTING_FROM_ID_PRESENTATION: 09356 if (ie_len != 1) { 09357 ast_log(LOG_WARNING, "Invalid redirecting-from combined presentation (%u)\n", 09358 (unsigned) ie_len); 09359 break; 09360 } 09361 from_combined_presentation = data[pos]; 09362 got_from_combined_presentation = 1; 09363 break; 09364 /* Redirecting-from party id subaddress */ 09365 case AST_REDIRECTING_FROM_SUBADDRESS: 09366 ast_free(redirecting->from.subaddress.str); 09367 redirecting->from.subaddress.str = ast_malloc(ie_len + 1); 09368 if (redirecting->from.subaddress.str) { 09369 memcpy(redirecting->from.subaddress.str, data + pos, ie_len); 09370 redirecting->from.subaddress.str[ie_len] = 0; 09371 } 09372 break; 09373 case AST_REDIRECTING_FROM_SUBADDRESS_TYPE: 09374 if (ie_len != 1) { 09375 ast_log(LOG_WARNING, "Invalid redirecting-from type of subaddress (%u)\n", 09376 (unsigned) ie_len); 09377 break; 09378 } 09379 redirecting->from.subaddress.type = data[pos]; 09380 break; 09381 case AST_REDIRECTING_FROM_SUBADDRESS_ODD_EVEN: 09382 if (ie_len != 1) { 09383 ast_log(LOG_WARNING, 09384 "Invalid redirecting-from subaddress odd-even indicator (%u)\n", 09385 (unsigned) ie_len); 09386 break; 09387 } 09388 redirecting->from.subaddress.odd_even_indicator = data[pos]; 09389 break; 09390 case AST_REDIRECTING_FROM_SUBADDRESS_VALID: 09391 if (ie_len != 1) { 09392 ast_log(LOG_WARNING, "Invalid redirecting-from subaddress valid (%u)\n", 09393 (unsigned) ie_len); 09394 break; 09395 } 09396 redirecting->from.subaddress.valid = data[pos]; 09397 break; 09398 /* Redirecting-from party id tag */ 09399 case AST_REDIRECTING_FROM_TAG: 09400 ast_free(redirecting->from.tag); 09401 redirecting->from.tag = ast_malloc(ie_len + 1); 09402 if (redirecting->from.tag) { 09403 memcpy(redirecting->from.tag, data + pos, ie_len); 09404 redirecting->from.tag[ie_len] = 0; 09405 } 09406 break; 09407 /* Redirecting-to party id name */ 09408 case AST_REDIRECTING_TO_NAME: 09409 ast_free(redirecting->to.name.str); 09410 redirecting->to.name.str = ast_malloc(ie_len + 1); 09411 if (redirecting->to.name.str) { 09412 memcpy(redirecting->to.name.str, data + pos, ie_len); 09413 redirecting->to.name.str[ie_len] = 0; 09414 } 09415 break; 09416 case AST_REDIRECTING_TO_NAME_CHAR_SET: 09417 if (ie_len != 1) { 09418 ast_log(LOG_WARNING, "Invalid redirecting-to name char set (%u)\n", 09419 (unsigned) ie_len); 09420 break; 09421 } 09422 redirecting->to.name.char_set = data[pos]; 09423 break; 09424 case AST_REDIRECTING_TO_NAME_PRESENTATION: 09425 if (ie_len != 1) { 09426 ast_log(LOG_WARNING, "Invalid redirecting-to name presentation (%u)\n", 09427 (unsigned) ie_len); 09428 break; 09429 } 09430 redirecting->to.name.presentation = data[pos]; 09431 break; 09432 case AST_REDIRECTING_TO_NAME_VALID: 09433 if (ie_len != 1) { 09434 ast_log(LOG_WARNING, "Invalid redirecting-to name valid (%u)\n", 09435 (unsigned) ie_len); 09436 break; 09437 } 09438 redirecting->to.name.valid = data[pos]; 09439 break; 09440 /* Redirecting-to party id number */ 09441 case AST_REDIRECTING_TO_NUMBER: 09442 ast_free(redirecting->to.number.str); 09443 redirecting->to.number.str = ast_malloc(ie_len + 1); 09444 if (redirecting->to.number.str) { 09445 memcpy(redirecting->to.number.str, data + pos, ie_len); 09446 redirecting->to.number.str[ie_len] = 0; 09447 } 09448 break; 09449 case AST_REDIRECTING_TO_NUMBER_PLAN: 09450 if (ie_len != 1) { 09451 ast_log(LOG_WARNING, "Invalid redirecting-to numbering plan (%u)\n", 09452 (unsigned) ie_len); 09453 break; 09454 } 09455 redirecting->to.number.plan = data[pos]; 09456 break; 09457 case AST_REDIRECTING_TO_NUMBER_PRESENTATION: 09458 if (ie_len != 1) { 09459 ast_log(LOG_WARNING, "Invalid redirecting-to number presentation (%u)\n", 09460 (unsigned) ie_len); 09461 break; 09462 } 09463 redirecting->to.number.presentation = data[pos]; 09464 break; 09465 case AST_REDIRECTING_TO_NUMBER_VALID: 09466 if (ie_len != 1) { 09467 ast_log(LOG_WARNING, "Invalid redirecting-to number valid (%u)\n", 09468 (unsigned) ie_len); 09469 break; 09470 } 09471 redirecting->to.number.valid = data[pos]; 09472 break; 09473 /* Redirecting-to party id combined presentation */ 09474 case AST_REDIRECTING_TO_ID_PRESENTATION: 09475 if (ie_len != 1) { 09476 ast_log(LOG_WARNING, "Invalid redirecting-to combined presentation (%u)\n", 09477 (unsigned) ie_len); 09478 break; 09479 } 09480 to_combined_presentation = data[pos]; 09481 got_to_combined_presentation = 1; 09482 break; 09483 /* Redirecting-to party id subaddress */ 09484 case AST_REDIRECTING_TO_SUBADDRESS: 09485 ast_free(redirecting->to.subaddress.str); 09486 redirecting->to.subaddress.str = ast_malloc(ie_len + 1); 09487 if (redirecting->to.subaddress.str) { 09488 memcpy(redirecting->to.subaddress.str, data + pos, ie_len); 09489 redirecting->to.subaddress.str[ie_len] = 0; 09490 } 09491 break; 09492 case AST_REDIRECTING_TO_SUBADDRESS_TYPE: 09493 if (ie_len != 1) { 09494 ast_log(LOG_WARNING, "Invalid redirecting-to type of subaddress (%u)\n", 09495 (unsigned) ie_len); 09496 break; 09497 } 09498 redirecting->to.subaddress.type = data[pos]; 09499 break; 09500 case AST_REDIRECTING_TO_SUBADDRESS_ODD_EVEN: 09501 if (ie_len != 1) { 09502 ast_log(LOG_WARNING, 09503 "Invalid redirecting-to subaddress odd-even indicator (%u)\n", 09504 (unsigned) ie_len); 09505 break; 09506 } 09507 redirecting->to.subaddress.odd_even_indicator = data[pos]; 09508 break; 09509 case AST_REDIRECTING_TO_SUBADDRESS_VALID: 09510 if (ie_len != 1) { 09511 ast_log(LOG_WARNING, "Invalid redirecting-to subaddress valid (%u)\n", 09512 (unsigned) ie_len); 09513 break; 09514 } 09515 redirecting->to.subaddress.valid = data[pos]; 09516 break; 09517 /* Redirecting-to party id tag */ 09518 case AST_REDIRECTING_TO_TAG: 09519 ast_free(redirecting->to.tag); 09520 redirecting->to.tag = ast_malloc(ie_len + 1); 09521 if (redirecting->to.tag) { 09522 memcpy(redirecting->to.tag, data + pos, ie_len); 09523 redirecting->to.tag[ie_len] = 0; 09524 } 09525 break; 09526 /* Redirecting reason */ 09527 case AST_REDIRECTING_REASON: 09528 if (ie_len != sizeof(value)) { 09529 ast_log(LOG_WARNING, "Invalid redirecting reason (%u)\n", 09530 (unsigned) ie_len); 09531 break; 09532 } 09533 memcpy(&value, data + pos, sizeof(value)); 09534 redirecting->reason = ntohl(value); 09535 break; 09536 /* Redirecting count */ 09537 case AST_REDIRECTING_COUNT: 09538 if (ie_len != sizeof(value)) { 09539 ast_log(LOG_WARNING, "Invalid redirecting count (%u)\n", 09540 (unsigned) ie_len); 09541 break; 09542 } 09543 memcpy(&value, data + pos, sizeof(value)); 09544 redirecting->count = ntohl(value); 09545 break; 09546 /* Redirecting unknown element */ 09547 default: 09548 ast_log(LOG_DEBUG, "Unknown redirecting element: %u (%u)\n", 09549 (unsigned) ie_id, (unsigned) ie_len); 09550 break; 09551 } 09552 } 09553 09554 switch (frame_version) { 09555 case 1: 09556 /* 09557 * The other end is an earlier version that we need to adjust 09558 * for compatibility. 09559 */ 09560 redirecting->from.name.valid = 1; 09561 redirecting->from.name.char_set = AST_PARTY_CHAR_SET_ISO8859_1; 09562 redirecting->from.number.valid = 1; 09563 if (got_from_combined_presentation) { 09564 redirecting->from.name.presentation = from_combined_presentation; 09565 redirecting->from.number.presentation = from_combined_presentation; 09566 } 09567 09568 redirecting->to.name.valid = 1; 09569 redirecting->to.name.char_set = AST_PARTY_CHAR_SET_ISO8859_1; 09570 redirecting->to.number.valid = 1; 09571 if (got_to_combined_presentation) { 09572 redirecting->to.name.presentation = to_combined_presentation; 09573 redirecting->to.number.presentation = to_combined_presentation; 09574 } 09575 break; 09576 case 2: 09577 /* The other end is at the same level as we are. */ 09578 break; 09579 default: 09580 /* 09581 * The other end is newer than we are. 09582 * We need to assume that they are compatible with us. 09583 */ 09584 ast_log(LOG_DEBUG, "Redirecting frame has newer version: %u\n", 09585 (unsigned) frame_version); 09586 break; 09587 } 09588 09589 return 0; 09590 }
struct ast_channel* ast_request | ( | const char * | type, | |
format_t | format, | |||
const struct ast_channel * | requestor, | |||
void * | data, | |||
int * | status | |||
) | [read] |
Requests a channel.
type | type of channel to request | |
format | requested channel format (codec) | |
requestor | channel asking for data | |
data | data to pass to the channel requester (Should be treated as const char *) | |
status | status |
Request a channel of a given type, with data as optional information used by the low level module
NULL | failure | |
non-NULL | channel on success |
Definition at line 5695 of file channel.c.
References AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, AST_CAUSE_NOSUCHDRIVER, AST_CAUSE_NOTDEFINED, ast_channel_release(), AST_FORMAT_AUDIO_MASK, AST_FORMAT_TEXT_MASK, AST_FORMAT_VIDEO_MASK, ast_getformatname_multiple(), ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_translator_best_choice(), ast_channel_tech::capabilities, capabilities, LOG_WARNING, ast_channel_tech::requester, set_security_requirements(), chanlist::tech, and ast_channel_tech::type.
Referenced by __ast_request_and_dial(), ast_call_forward(), begin_dial_channel(), build_conf(), chanavail_exec(), conf_run(), dial_exec_full(), dial_transfer(), do_forward(), feature_request_and_dial(), findmeexec(), meetme_menu_admin_extended(), play_sound_file(), ring_entry(), and wait_for_answer().
05696 { 05697 struct chanlist *chan; 05698 struct ast_channel *c; 05699 format_t capabilities; 05700 format_t fmt; 05701 int res; 05702 int foo; 05703 format_t videoformat = format & AST_FORMAT_VIDEO_MASK; 05704 format_t textformat = format & AST_FORMAT_TEXT_MASK; 05705 05706 if (!cause) 05707 cause = &foo; 05708 *cause = AST_CAUSE_NOTDEFINED; 05709 05710 if (AST_RWLIST_RDLOCK(&backends)) { 05711 ast_log(LOG_WARNING, "Unable to lock technology backend list\n"); 05712 return NULL; 05713 } 05714 05715 AST_RWLIST_TRAVERSE(&backends, chan, list) { 05716 if (strcasecmp(type, chan->tech->type)) 05717 continue; 05718 05719 capabilities = chan->tech->capabilities; 05720 fmt = format & AST_FORMAT_AUDIO_MASK; 05721 if (fmt) { 05722 /* We have audio - is it possible to connect the various calls to each other? 05723 (Avoid this check for calls without audio, like text+video calls) 05724 */ 05725 res = ast_translator_best_choice(&fmt, &capabilities); 05726 if (res < 0) { 05727 char tmp1[256], tmp2[256]; 05728 ast_log(LOG_WARNING, "No translator path exists for channel type %s (native %s) to %s\n", type, 05729 ast_getformatname_multiple(tmp1, sizeof(tmp1), chan->tech->capabilities), 05730 ast_getformatname_multiple(tmp2, sizeof(tmp2), format)); 05731 *cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; 05732 AST_RWLIST_UNLOCK(&backends); 05733 return NULL; 05734 } 05735 } 05736 AST_RWLIST_UNLOCK(&backends); 05737 if (!chan->tech->requester) 05738 return NULL; 05739 05740 if (!(c = chan->tech->requester(type, capabilities | videoformat | textformat, requestor, data, cause))) 05741 return NULL; 05742 05743 if (set_security_requirements(requestor, c)) { 05744 ast_log(LOG_WARNING, "Setting security requirements failed\n"); 05745 c = ast_channel_release(c); 05746 *cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; 05747 return NULL; 05748 } 05749 05750 /* no need to generate a Newchannel event here; it is done in the channel_alloc call */ 05751 return c; 05752 } 05753 05754 ast_log(LOG_WARNING, "No channel type registered for '%s'\n", type); 05755 *cause = AST_CAUSE_NOSUCHDRIVER; 05756 AST_RWLIST_UNLOCK(&backends); 05757 05758 return NULL; 05759 }
struct ast_channel* ast_request_and_dial | ( | const char * | type, | |
format_t | format, | |||
const struct ast_channel * | requestor, | |||
void * | data, | |||
int | timeout, | |||
int * | reason, | |||
const char * | cid_num, | |||
const char * | cid_name | |||
) | [read] |
Request a channel of a given type, with data as optional information used by the low level module and attempt to place a call on it.
type | type of channel to request | |
format | requested channel format | |
requestor | channel asking for data | |
data | data to pass to the channel requester | |
timeout | maximum amount of time to wait for an answer | |
reason | why unsuccessful (if unsuccessful) | |
cid_num | Caller-ID Number | |
cid_name | Caller-ID Name (ascii) |
Definition at line 5650 of file channel.c.
References __ast_request_and_dial().
Referenced by ast_pbx_outgoing_exten(), and generic_recall().
05651 { 05652 return __ast_request_and_dial(type, format, requestor, data, timeout, outstate, cidnum, cidname, NULL); 05653 }
int ast_safe_sleep | ( | struct ast_channel * | chan, | |
int | ms | |||
) |
Wait, look for hangups.
Wait for a specified amount of time, looking for hangups.
Definition at line 1916 of file channel.c.
References ast_safe_sleep_conditional().
Referenced by __analog_ss_thread(), adsi_transmit_message_full(), alarmreceiver_exec(), analog_ss_thread(), ast_dtmf_stream(), ast_senddigit(), builtin_atxfer(), builtin_parkcall(), conf_run(), dial_trunk(), dictate_exec(), disa_exec(), flash_exec(), handle_callforward_button(), login_exec(), mgcp_ss(), milliwatt_exec(), misdn_check_l2l1(), old_milliwatt_exec(), park_call_exec(), pbx_builtin_wait(), play_moh_exec(), playtone(), privacy_exec(), receive_ademco_contact_id(), skinny_ss(), testclient_exec(), testserver_exec(), try_calling(), wait_for_hangup(), wait_moh_exec(), waituntil_exec(), and zapateller_exec().
01917 { 01918 return ast_safe_sleep_conditional(chan, ms, NULL, NULL); 01919 }
int ast_safe_sleep_conditional | ( | struct ast_channel * | chan, | |
int | timeout_ms, | |||
int(*)(void *) | cond, | |||
void * | data | |||
) |
Wait, look for hangups and condition arg.
Wait for a specified amount of time, looking for hangups and a condition argument.
Definition at line 1845 of file channel.c.
References ast_channel_lock, ast_channel_start_silence_generator(), ast_channel_stop_silence_generator(), ast_channel_unlock, ast_frfree, ast_frisolate(), ast_is_deferrable_frame(), AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_HEAD_NOLOCK, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_HEAD, ast_opt_transmit_silence, ast_queue_frame_head(), ast_read(), ast_remaining_ms(), ast_tvnow(), ast_waitfor(), cond, and ast_channel::generatordata.
Referenced by ast_safe_sleep(), and login_exec().
01846 { 01847 struct ast_frame *f; 01848 struct ast_silence_generator *silgen = NULL; 01849 int res = 0; 01850 struct timeval start; 01851 int ms; 01852 AST_LIST_HEAD_NOLOCK(, ast_frame) deferred_frames; 01853 01854 AST_LIST_HEAD_INIT_NOLOCK(&deferred_frames); 01855 01856 /* If no other generator is present, start silencegen while waiting */ 01857 if (ast_opt_transmit_silence && !chan->generatordata) { 01858 silgen = ast_channel_start_silence_generator(chan); 01859 } 01860 01861 start = ast_tvnow(); 01862 while ((ms = ast_remaining_ms(start, timeout_ms))) { 01863 struct ast_frame *dup_f = NULL; 01864 01865 if (cond && ((*cond)(data) == 0)) { 01866 break; 01867 } 01868 ms = ast_waitfor(chan, ms); 01869 if (ms < 0) { 01870 res = -1; 01871 break; 01872 } 01873 if (ms > 0) { 01874 f = ast_read(chan); 01875 if (!f) { 01876 res = -1; 01877 break; 01878 } 01879 01880 if (!ast_is_deferrable_frame(f)) { 01881 ast_frfree(f); 01882 continue; 01883 } 01884 01885 if ((dup_f = ast_frisolate(f))) { 01886 if (dup_f != f) { 01887 ast_frfree(f); 01888 } 01889 AST_LIST_INSERT_HEAD(&deferred_frames, dup_f, frame_list); 01890 } 01891 } 01892 } 01893 01894 /* stop silgen if present */ 01895 if (silgen) { 01896 ast_channel_stop_silence_generator(chan, silgen); 01897 } 01898 01899 /* We need to free all the deferred frames, but we only need to 01900 * queue the deferred frames if there was no error and no 01901 * hangup was received 01902 */ 01903 ast_channel_lock(chan); 01904 while ((f = AST_LIST_REMOVE_HEAD(&deferred_frames, frame_list))) { 01905 if (!res) { 01906 ast_queue_frame_head(chan, f); 01907 } 01908 ast_frfree(f); 01909 } 01910 ast_channel_unlock(chan); 01911 01912 return res; 01913 }
int ast_say_character_str | ( | struct ast_channel * | chan, | |
const char * | str, | |||
const char * | ints, | |||
const char * | lang | |||
) |
Definition at line 8421 of file channel.c.
References ast_say_character_str_full.
Referenced by common_exec(), pbx_builtin_saycharacters(), play_mailbox_owner(), and vmsayname_exec().
08423 { 08424 return ast_say_character_str_full(chan, str, ints, lang, -1, -1); 08425 }
int ast_say_digit_str | ( | struct ast_channel * | chan, | |
const char * | num, | |||
const char * | ints, | |||
const char * | lang | |||
) |
says digits of a string
chan | channel to act upon | |
num | string to speak | |
ints | which dtmf to interrupt on | |
lang | language to speak in |
Vocally says the digits of a given string
0 | on succes | |
DTMF | if interrupted | |
-1 | on failure |
Definition at line 8415 of file channel.c.
References ast_say_digit_str_full.
Referenced by __analog_ss_thread(), forward_message(), invent_message(), mgcp_ss(), pbx_builtin_saydigits(), and play_message_callerid().
08417 { 08418 return ast_say_digit_str_full(chan, str, ints, lang, -1, -1); 08419 }
int ast_say_digits | ( | struct ast_channel * | chan, | |
int | num, | |||
const char * | ints, | |||
const char * | lang | |||
) |
says digits
chan | channel to act upon | |
num | number to speak | |
ints | which dtmf to interrupt on | |
lang | language to speak |
Vocally says digits of a given number
0 | on success | |
DTMF | if interrupted | |
-1 | on failure |
Definition at line 8409 of file channel.c.
References ast_say_digits_full().
Referenced by common_exec(), conf_exec(), conf_run(), park_call_full(), and parkandannounce_exec().
08411 { 08412 return ast_say_digits_full(chan, num, ints, lang, -1, -1); 08413 }
int ast_say_digits_full | ( | struct ast_channel * | chan, | |
int | num, | |||
const char * | ints, | |||
const char * | lang, | |||
int | audiofd, | |||
int | ctrlfd | |||
) |
Definition at line 8433 of file channel.c.
References ast_say_digit_str_full.
Referenced by ast_say_digits(), ast_say_enumeration_full_da(), ast_say_enumeration_full_de(), ast_say_number_full_cs(), ast_say_number_full_da(), ast_say_number_full_de(), ast_say_number_full_en(), ast_say_number_full_en_GB(), ast_say_number_full_es(), ast_say_number_full_fr(), ast_say_number_full_he(), ast_say_number_full_hu(), ast_say_number_full_it(), ast_say_number_full_ka(), ast_say_number_full_nl(), ast_say_number_full_no(), ast_say_number_full_pt(), ast_say_number_full_ru(), ast_say_number_full_se(), ast_say_number_full_th(), ast_say_number_full_ur(), ast_say_number_full_vi(), ast_say_number_full_zh(), and say_init_mode().
08435 { 08436 char buf[256]; 08437 08438 snprintf(buf, sizeof(buf), "%d", num); 08439 08440 return ast_say_digit_str_full(chan, buf, ints, lang, audiofd, ctrlfd); 08441 }
int ast_say_enumeration | ( | struct ast_channel * | chan, | |
int | num, | |||
const char * | ints, | |||
const char * | lang, | |||
const char * | options | |||
) |
says an enumeration
chan | channel to say them enumeration on | |
num | number to say on the channel | |
ints | which dtmf to interrupt on | |
lang | language to speak the enumeration | |
options | set to 'f' for female, 'm' for male, 'c' for commune, 'n' for neuter, 'p' for plural |
Vocally says an enumeration on a given channel (first, sencond, third, forth, thirtyfirst, hundredth, ....) Especially useful for dates and messages. Says 'last' if num equals to INT_MAX
0 | on success | |
DTMF | digit on interrupt | |
-1 | on failure |
Definition at line 8403 of file channel.c.
References ast_say_enumeration_full.
Referenced by ast_say_date_da(), ast_say_date_de(), ast_say_date_with_format_da(), ast_say_date_with_format_de(), ast_say_date_with_format_en(), ast_say_date_with_format_pl(), and ast_say_date_with_format_vi().
08405 { 08406 return ast_say_enumeration_full(chan, num, ints, language, options, -1, -1); 08407 }
int ast_say_number | ( | struct ast_channel * | chan, | |
int | num, | |||
const char * | ints, | |||
const char * | lang, | |||
const char * | options | |||
) |
says a number
chan | channel to say them number on | |
num | number to say on the channel | |
ints | which dtmf to interrupt on | |
lang | language to speak the number | |
options | set to 'f' for female, 'm' for male, 'c' for commune, 'n' for neuter, 'p' for plural |
Vocally says a number on a given channel
0 | on success | |
DTMF | digit on interrupt | |
-1 | on failure |
Definition at line 8397 of file channel.c.
References ast_say_number_full.
Referenced by announce_user_count(), ast_say_date_da(), ast_say_date_de(), ast_say_date_en(), ast_say_date_fr(), ast_say_date_gr(), ast_say_date_he(), ast_say_date_hu(), ast_say_date_ka(), ast_say_date_nl(), ast_say_date_pt(), ast_say_date_th(), ast_say_date_with_format_da(), ast_say_date_with_format_de(), ast_say_date_with_format_en(), ast_say_date_with_format_es(), ast_say_date_with_format_fr(), ast_say_date_with_format_it(), ast_say_date_with_format_nl(), ast_say_date_with_format_pl(), ast_say_date_with_format_pt(), ast_say_date_with_format_th(), ast_say_date_with_format_vi(), ast_say_datetime_en(), ast_say_datetime_fr(), ast_say_datetime_from_now_en(), ast_say_datetime_from_now_fr(), ast_say_datetime_from_now_he(), ast_say_datetime_from_now_ka(), ast_say_datetime_from_now_pt(), ast_say_datetime_he(), ast_say_datetime_pt(), ast_say_datetime_th(), ast_say_datetime_zh(), ast_say_time_de(), ast_say_time_en(), ast_say_time_fr(), ast_say_time_gr(), ast_say_time_hu(), ast_say_time_ka(), ast_say_time_nl(), ast_say_time_pt(), ast_say_time_pt_BR(), ast_say_time_th(), ast_say_time_zh(), bridge_playfile(), conf_run(), count_exec(), dictate_exec(), get_folder(), gr_say_number_female(), meetme_menu_admin_extended(), pbx_builtin_saynumber(), play_message(), play_message_duration(), say_and_wait(), say_position(), try_calling(), vm_intro_gr(), vm_intro_he(), vm_intro_multilang(), vm_intro_pt(), and vm_intro_pt_BR().
08399 { 08400 return ast_say_number_full(chan, num, ints, language, options, -1, -1); 08401 }
int ast_say_phonetic_str | ( | struct ast_channel * | chan, | |
const char * | str, | |||
const char * | ints, | |||
const char * | lang | |||
) |
Definition at line 8427 of file channel.c.
References ast_say_phonetic_str_full.
Referenced by pbx_builtin_sayphonetic().
08429 { 08430 return ast_say_phonetic_str_full(chan, str, ints, lang, -1, -1); 08431 }
int ast_senddigit | ( | struct ast_channel * | chan, | |
char | digit, | |||
unsigned int | duration | |||
) |
Send a DTMF digit to a channel.
chan | channel to act upon | |
digit | the DTMF digit to send, encoded in ASCII | |
duration | the duration of the digit ending in ms |
Definition at line 4774 of file channel.c.
References AST_DEFAULT_EMULATE_DTMF_DURATION, ast_safe_sleep(), ast_senddigit_begin(), ast_senddigit_end(), ast_channel_tech::send_digit_begin, and ast_channel::tech.
Referenced by ast_dtmf_stream(), dial_exec_full(), and manager_play_dtmf().
04775 { 04776 if (chan->tech->send_digit_begin) { 04777 ast_senddigit_begin(chan, digit); 04778 ast_safe_sleep(chan, (duration >= AST_DEFAULT_EMULATE_DTMF_DURATION ? duration : AST_DEFAULT_EMULATE_DTMF_DURATION)); 04779 } 04780 04781 return ast_senddigit_end(chan, digit, (duration >= AST_DEFAULT_EMULATE_DTMF_DURATION ? duration : AST_DEFAULT_EMULATE_DTMF_DURATION)); 04782 }
int ast_senddigit_begin | ( | struct ast_channel * | chan, | |
char | digit | |||
) |
Send a DTMF digit to a channel.
chan | channel to act upon | |
digit | the DTMF digit to send, encoded in ASCII |
Definition at line 4705 of file channel.c.
References ast_channel_lock, ast_channel_unlock, ast_debug, ast_playtones_start(), ast_tvnow(), ast_channel_tech::send_digit_begin, ast_channel::sending_dtmf_digit, ast_channel::sending_dtmf_tv, and ast_channel::tech.
Referenced by agent_digit_begin(), ast_senddigit(), and ast_write().
04706 { 04707 /* Device does not support DTMF tones, lets fake 04708 * it by doing our own generation. */ 04709 static const char * const dtmf_tones[] = { 04710 "941+1336", /* 0 */ 04711 "697+1209", /* 1 */ 04712 "697+1336", /* 2 */ 04713 "697+1477", /* 3 */ 04714 "770+1209", /* 4 */ 04715 "770+1336", /* 5 */ 04716 "770+1477", /* 6 */ 04717 "852+1209", /* 7 */ 04718 "852+1336", /* 8 */ 04719 "852+1477", /* 9 */ 04720 "697+1633", /* A */ 04721 "770+1633", /* B */ 04722 "852+1633", /* C */ 04723 "941+1633", /* D */ 04724 "941+1209", /* * */ 04725 "941+1477" /* # */ 04726 }; 04727 04728 if (!chan->tech->send_digit_begin) 04729 return 0; 04730 04731 ast_channel_lock(chan); 04732 chan->sending_dtmf_digit = digit; 04733 chan->sending_dtmf_tv = ast_tvnow(); 04734 ast_channel_unlock(chan); 04735 04736 if (!chan->tech->send_digit_begin(chan, digit)) 04737 return 0; 04738 04739 if (digit >= '0' && digit <='9') 04740 ast_playtones_start(chan, 0, dtmf_tones[digit-'0'], 0); 04741 else if (digit >= 'A' && digit <= 'D') 04742 ast_playtones_start(chan, 0, dtmf_tones[digit-'A'+10], 0); 04743 else if (digit == '*') 04744 ast_playtones_start(chan, 0, dtmf_tones[14], 0); 04745 else if (digit == '#') 04746 ast_playtones_start(chan, 0, dtmf_tones[15], 0); 04747 else { 04748 /* not handled */ 04749 ast_debug(1, "Unable to generate DTMF tone '%c' for '%s'\n", digit, chan->name); 04750 } 04751 04752 return 0; 04753 }
int ast_senddigit_end | ( | struct ast_channel * | chan, | |
char | digit, | |||
unsigned int | duration | |||
) |
Send a DTMF digit to a channel.
chan | channel to act upon | |
digit | the DTMF digit to send, encoded in ASCII | |
duration | the duration of the digit ending in ms |
Definition at line 4755 of file channel.c.
References ast_channel_lock, ast_channel_unlock, ast_playtones_stop(), ast_channel::generator, ast_channel_tech::send_digit_end, ast_channel::sending_dtmf_digit, and ast_channel::tech.
Referenced by agent_digit_end(), ast_bridge_end_dtmf(), ast_senddigit(), and ast_write().
04756 { 04757 int res = -1; 04758 04759 ast_channel_lock(chan); 04760 if (chan->sending_dtmf_digit == digit) { 04761 chan->sending_dtmf_digit = 0; 04762 } 04763 ast_channel_unlock(chan); 04764 04765 if (chan->tech->send_digit_end) 04766 res = chan->tech->send_digit_end(chan, digit, duration); 04767 04768 if (res && chan->generator) 04769 ast_playtones_stop(chan); 04770 04771 return 0; 04772 }
int ast_sendtext | ( | struct ast_channel * | chan, | |
const char * | text | |||
) |
Sends text to a channel.
chan | channel to act upon | |
text | string of text to send on the channel |
Write text to a display on a channel
0 | on success | |
-1 | on failure |
Definition at line 4687 of file channel.c.
References ast_channel_lock, ast_channel_unlock, ast_check_hangup(), ast_clear_flag, AST_FLAG_BLOCKING, AST_FLAG_ZOMBIE, ast_test_flag, CHECK_BLOCKING, ast_channel_tech::send_text, and ast_channel::tech.
Referenced by action_sendtext(), agent_sendtext(), handle_sendtext(), and sendtext_exec().
04688 { 04689 int res = 0; 04690 04691 ast_channel_lock(chan); 04692 /* Stop if we're a zombie or need a soft hangup */ 04693 if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) { 04694 ast_channel_unlock(chan); 04695 return -1; 04696 } 04697 CHECK_BLOCKING(chan); 04698 if (chan->tech->send_text) 04699 res = chan->tech->send_text(chan, text); 04700 ast_clear_flag(chan, AST_FLAG_BLOCKING); 04701 ast_channel_unlock(chan); 04702 return res; 04703 }
void ast_set_callerid | ( | struct ast_channel * | chan, | |
const char * | cid_num, | |||
const char * | cid_name, | |||
const char * | cid_ani | |||
) |
Set caller ID number, name and ANI and generate AMI event.
Definition at line 7051 of file channel.c.
References ast_party_caller::ani, ast_cdr_setcid(), ast_channel_lock, ast_channel_unlock, ast_free, ast_strdup, ast_channel::caller, ast_channel::cdr, ast_party_caller::id, ast_party_id::name, ast_party_id::number, report_new_callerid(), ast_party_name::str, ast_party_number::str, ast_party_name::valid, and ast_party_number::valid.
Referenced by __analog_ss_thread(), __ast_request_and_dial(), analog_ss_thread(), cb_events(), disa_exec(), get_pai(), get_rpid(), handle_setcallerid(), mgcp_ss(), privacy_exec(), ring_entry(), skinny_newcall(), and socket_process().
07052 { 07053 ast_channel_lock(chan); 07054 07055 if (cid_num) { 07056 chan->caller.id.number.valid = 1; 07057 ast_free(chan->caller.id.number.str); 07058 chan->caller.id.number.str = ast_strdup(cid_num); 07059 } 07060 if (cid_name) { 07061 chan->caller.id.name.valid = 1; 07062 ast_free(chan->caller.id.name.str); 07063 chan->caller.id.name.str = ast_strdup(cid_name); 07064 } 07065 if (cid_ani) { 07066 chan->caller.ani.number.valid = 1; 07067 ast_free(chan->caller.ani.number.str); 07068 chan->caller.ani.number.str = ast_strdup(cid_ani); 07069 } 07070 if (chan->cdr) { 07071 ast_cdr_setcid(chan->cdr, chan); 07072 } 07073 07074 report_new_callerid(chan); 07075 07076 ast_channel_unlock(chan); 07077 }
void ast_set_hangupsource | ( | struct ast_channel * | chan, | |
const char * | source, | |||
int | force | |||
) |
Set the source of the hangup in this channel and it's bridge.
chan | channel to set the field on | |
source | a string describing the source of the hangup for this channel | |
force |
Hangupsource is generally the channel name that caused the bridge to be hung up, but it can also be other things such as "dialplan/agi" This can then be logged in the CDR or CEL
Definition at line 2769 of file channel.c.
References ast_bridged_channel(), ast_channel_lock, ast_channel_ref, ast_channel_unlock, ast_channel_unref, ast_string_field_set, ast_strlen_zero(), and ast_channel::bridge.
Referenced by __dahdi_exception(), analog_exception(), func_channel_write_real(), handle_hangup(), pbx_builtin_hangup(), set_hangup_source_and_cause(), and sip_queue_hangup_cause().
02770 { 02771 struct ast_channel *bridge; 02772 02773 ast_channel_lock(chan); 02774 if (force || ast_strlen_zero(chan->hangupsource)) { 02775 ast_string_field_set(chan, hangupsource, source); 02776 } 02777 bridge = ast_bridged_channel(chan); 02778 if (bridge) { 02779 ast_channel_ref(bridge); 02780 } 02781 ast_channel_unlock(chan); 02782 02783 if (bridge) { 02784 ast_channel_lock(bridge); 02785 if (force || ast_strlen_zero(bridge->hangupsource)) { 02786 ast_string_field_set(bridge, hangupsource, source); 02787 } 02788 ast_channel_unlock(bridge); 02789 ast_channel_unref(bridge); 02790 } 02791 }
static void ast_set_owners_and_peers | ( | struct ast_channel * | chan1, | |
struct ast_channel * | chan2 | |||
) | [static] |
Definition at line 6430 of file channel.c.
References accountcode, ast_log(), ast_string_field_set, ast_strlen_zero(), and LOG_DEBUG.
Referenced by ast_channel_bridge().
06432 { 06433 if (!ast_strlen_zero(chan1->accountcode) && ast_strlen_zero(chan2->peeraccount)) { 06434 ast_log(LOG_DEBUG, "setting peeraccount to %s for %s from data on channel %s\n", 06435 chan1->accountcode, chan2->name, chan1->name); 06436 ast_string_field_set(chan2, peeraccount, chan1->accountcode); 06437 } 06438 if (!ast_strlen_zero(chan2->accountcode) && ast_strlen_zero(chan1->peeraccount)) { 06439 ast_log(LOG_DEBUG, "setting peeraccount to %s for %s from data on channel %s\n", 06440 chan2->accountcode, chan1->name, chan2->name); 06441 ast_string_field_set(chan1, peeraccount, chan2->accountcode); 06442 } 06443 if (!ast_strlen_zero(chan1->peeraccount) && ast_strlen_zero(chan2->accountcode)) { 06444 ast_log(LOG_DEBUG, "setting accountcode to %s for %s from data on channel %s\n", 06445 chan1->peeraccount, chan2->name, chan1->name); 06446 ast_string_field_set(chan2, accountcode, chan1->peeraccount); 06447 } 06448 if (!ast_strlen_zero(chan2->peeraccount) && ast_strlen_zero(chan1->accountcode)) { 06449 ast_log(LOG_DEBUG, "setting accountcode to %s for %s from data on channel %s\n", 06450 chan2->peeraccount, chan1->name, chan2->name); 06451 ast_string_field_set(chan1, accountcode, chan2->peeraccount); 06452 } 06453 if (0 != strcmp(chan1->accountcode, chan2->peeraccount)) { 06454 ast_log(LOG_DEBUG, "changing peeraccount from %s to %s on %s to match channel %s\n", 06455 chan2->peeraccount, chan1->peeraccount, chan2->name, chan1->name); 06456 ast_string_field_set(chan2, peeraccount, chan1->accountcode); 06457 } 06458 if (0 != strcmp(chan2->accountcode, chan1->peeraccount)) { 06459 ast_log(LOG_DEBUG, "changing peeraccount from %s to %s on %s to match channel %s\n", 06460 chan1->peeraccount, chan2->peeraccount, chan1->name, chan2->name); 06461 ast_string_field_set(chan1, peeraccount, chan2->accountcode); 06462 } 06463 }
int ast_set_read_format | ( | struct ast_channel * | chan, | |
format_t | format | |||
) |
Sets read format on channel chan Set read format for channel to whichever component of "format" is best.
chan | channel to change | |
format | format to change to |
Definition at line 5301 of file channel.c.
References ast_channel::rawreadformat, ast_channel::readformat, ast_channel::readtrans, and set_format().
Referenced by __ast_play_and_record(), __oh323_update_info(), adsi_transmit_message_full(), agent_call(), alarmreceiver_exec(), ast_channel_make_compatible_helper(), ast_do_masquerade(), background_detect_exec(), bridge_channel_join(), bridge_make_compatible(), build_conf(), conf_run(), dictate_exec(), do_waiting(), eagi_exec(), echo_exec(), generic_fax_exec(), gtalk_rtp_read(), handle_recordfile(), handle_speechrecognize(), ices_exec(), isAnsweringMachine(), jack_exec(), jingle_rtp_read(), login_exec(), measurenoise(), meetme_menu_admin_extended(), mgcp_rtp_read(), oh323_rtp_read(), old_milliwatt_exec(), process_sdp(), record_exec(), setup_rtp_connection(), sip_rtp_read(), skinny_rtp_read(), socket_process(), speech_background(), transmit_audio(), and unistim_rtp_read().
05302 { 05303 return set_format(chan, fmt, &chan->rawreadformat, &chan->readformat, 05304 &chan->readtrans, 0); 05305 }
void ast_set_variables | ( | struct ast_channel * | chan, | |
struct ast_variable * | vars | |||
) |
adds a list of channel variables to a channel
chan | the channel | |
vars | a linked list of variables |
Variable names can be for a regular channel variable or a dialplan function that has the ability to be written to.
Definition at line 8261 of file channel.c.
References ast_variable::name, ast_variable::next, pbx_builtin_setvar_helper(), and ast_variable::value.
Referenced by __ast_request_and_dial(), ast_call_forward(), ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().
08262 { 08263 struct ast_variable *cur; 08264 08265 for (cur = vars; cur; cur = cur->next) 08266 pbx_builtin_setvar_helper(chan, cur->name, cur->value); 08267 }
int ast_set_write_format | ( | struct ast_channel * | chan, | |
format_t | format | |||
) |
Sets write format on channel chan Set write format for channel to whichever component of "format" is best.
chan | channel to change | |
format | new format for writing |
Definition at line 5307 of file channel.c.
References ast_channel::rawwriteformat, set_format(), ast_channel::writeformat, and ast_channel::writetrans.
Referenced by __oh323_update_info(), adsi_transmit_message_full(), agent_call(), alarmreceiver_exec(), ast_channel_make_compatible_helper(), ast_channel_start_silence_generator(), ast_channel_stop_silence_generator(), ast_do_masquerade(), ast_openstream_full(), ast_stopstream(), ast_write(), bridge_channel_join(), bridge_make_compatible(), build_conf(), chanspy_exec(), conf_run(), dahdiscan_exec(), echo_exec(), extenspy_exec(), generic_fax_exec(), gtalk_rtp_read(), jack_exec(), jingle_rtp_read(), linear_alloc(), linear_release(), login_exec(), meetme_menu_admin_extended(), mgcp_rtp_read(), moh_alloc(), moh_files_release(), moh_release(), mp3_exec(), NBScat_exec(), oh323_rtp_read(), old_milliwatt_exec(), playtones_alloc(), playtones_release(), process_sdp(), send_waveform_to_channel(), setup_rtp_connection(), sip_rtp_read(), skinny_rtp_read(), socket_process(), tonepair_alloc(), tonepair_release(), transmit_audio(), and unistim_rtp_read().
05308 { 05309 return set_format(chan, fmt, &chan->rawwriteformat, &chan->writeformat, 05310 &chan->writetrans, 1); 05311 }
int ast_setstate | ( | struct ast_channel * | chan, | |
enum ast_channel_state | state | |||
) |
Change the state of a channel.
Definition at line 7119 of file channel.c.
References ast_channel::_state, AST_CHANNEL_NAME, ast_copy_string(), AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, ast_devstate_changed_literal(), AST_DEVSTATE_NOT_CACHABLE, AST_FLAG_DISABLE_DEVSTATE_CACHE, ast_manager_event, ast_state2str(), ast_channel::caller, ast_channel::connected, EVENT_FLAG_CALL, ast_channel::flags, ast_party_connected_line::id, ast_party_caller::id, ast_party_id::name, name, ast_party_id::number, S_COR, ast_party_name::str, ast_party_number::str, ast_party_name::valid, and ast_party_number::valid.
Referenced by __analog_handle_event(), __analog_ss_thread(), __ast_read(), __dahdi_exception(), __oh323_update_info(), agent_call(), alsa_answer(), analog_answer(), analog_call(), analog_exception(), analog_ss_thread(), ast_raw_answer(), cb_events(), check_availability(), console_answer(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_indicate(), dahdi_read(), do_bridge_masquerade(), gtalk_call(), gtalk_newcall(), handle_invite_replaces(), handle_offhook_message(), handle_request_invite(), handle_response_invite(), handle_soft_key_event_message(), handle_stimulus_message(), iax2_call(), jingle_call(), jingle_newcall(), local_queue_frame(), mgcp_answer(), mgcp_call(), mgcp_ss(), misdn_call(), misdn_indication(), my_set_waitingfordt(), nbs_call(), nbs_hangup(), oh323_answer(), oss_answer(), pbx_builtin_busy(), pbx_builtin_congestion(), phone_answer(), phone_call(), phone_exception(), phone_hangup(), phone_write(), release_chan(), release_chan_early(), sip_answer(), skinny_answer(), skinny_call(), skinny_newcall(), unistim_answer(), unistim_call(), unistim_new(), unistim_ss(), and update_state().
07120 { 07121 int oldstate = chan->_state; 07122 char name[AST_CHANNEL_NAME], *dashptr; 07123 07124 if (oldstate == state) 07125 return 0; 07126 07127 ast_copy_string(name, chan->name, sizeof(name)); 07128 if ((dashptr = strrchr(name, '-'))) { 07129 *dashptr = '\0'; 07130 } 07131 07132 chan->_state = state; 07133 07134 /* We have to pass AST_DEVICE_UNKNOWN here because it is entirely possible that the channel driver 07135 * for this channel is using the callback method for device state. If we pass in an actual state here 07136 * we override what they are saying the state is and things go amuck. */ 07137 ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, (chan->flags & AST_FLAG_DISABLE_DEVSTATE_CACHE ? AST_DEVSTATE_NOT_CACHABLE : AST_DEVSTATE_CACHABLE), name); 07138 07139 /* setstate used to conditionally report Newchannel; this is no more */ 07140 ast_manager_event(chan, EVENT_FLAG_CALL, "Newstate", 07141 "Channel: %s\r\n" 07142 "ChannelState: %u\r\n" 07143 "ChannelStateDesc: %s\r\n" 07144 "CallerIDNum: %s\r\n" 07145 "CallerIDName: %s\r\n" 07146 "ConnectedLineNum: %s\r\n" 07147 "ConnectedLineName: %s\r\n" 07148 "Uniqueid: %s\r\n", 07149 chan->name, chan->_state, ast_state2str(chan->_state), 07150 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""), 07151 S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, ""), 07152 S_COR(chan->connected.id.number.valid, chan->connected.id.number.str, ""), 07153 S_COR(chan->connected.id.name.valid, chan->connected.id.name.str, ""), 07154 chan->uniqueid); 07155 07156 return 0; 07157 }
int ast_settimeout | ( | struct ast_channel * | c, | |
unsigned int | rate, | |||
int(*)(const void *data) | func, | |||
void * | data | |||
) |
Enable or disable timer ticks for a channel.
c | channel | |
rate | number of timer ticks per second | |
func | callback function | |
data |
If timers are supported, force a scheduled expiration on the timer fd, at which point we call the callback function / data
Definition at line 3557 of file channel.c.
References ast_settimeout_full().
Referenced by ast_activate_generator(), ast_readaudio_callback(), deactivate_generator_nolock(), and filestream_close().
03558 { 03559 return ast_settimeout_full(c, rate, func, data, 0); 03560 }
int ast_settimeout_full | ( | struct ast_channel * | c, | |
unsigned int | rate, | |||
int(*)(const void *data) | func, | |||
void * | data, | |||
unsigned int | is_ao2_obj | |||
) |
Definition at line 3562 of file channel.c.
References ao2_ref, ast_channel_lock, ast_channel_unlock, ast_clear_flag, ast_debug, AST_FLAG_TIMINGDATA_IS_AO2_OBJ, ast_set_flag, ast_test_flag, ast_timer_get_max_rate(), ast_timer_set_rate(), AST_TIMING_FD, ast_channel::fdno, ast_channel::timer, ast_channel::timingdata, ast_channel::timingfd, and ast_channel::timingfunc.
Referenced by ast_readaudio_callback(), and ast_settimeout().
03563 { 03564 int res; 03565 unsigned int real_rate = rate, max_rate; 03566 03567 ast_channel_lock(c); 03568 03569 if (c->timingfd == -1) { 03570 ast_channel_unlock(c); 03571 return -1; 03572 } 03573 03574 if (!func) { 03575 rate = 0; 03576 data = NULL; 03577 } 03578 03579 if (rate && rate > (max_rate = ast_timer_get_max_rate(c->timer))) { 03580 real_rate = max_rate; 03581 } 03582 03583 ast_debug(1, "Scheduling timer at (%u requested / %u actual) timer ticks per second\n", rate, real_rate); 03584 03585 res = ast_timer_set_rate(c->timer, real_rate); 03586 03587 if (c->timingdata && ast_test_flag(c, AST_FLAG_TIMINGDATA_IS_AO2_OBJ)) { 03588 ao2_ref(c->timingdata, -1); 03589 } 03590 03591 c->timingfunc = func; 03592 c->timingdata = data; 03593 03594 if (data && is_ao2_obj) { 03595 ao2_ref(data, 1); 03596 ast_set_flag(c, AST_FLAG_TIMINGDATA_IS_AO2_OBJ); 03597 } else { 03598 ast_clear_flag(c, AST_FLAG_TIMINGDATA_IS_AO2_OBJ); 03599 } 03600 03601 if (func == NULL && rate == 0 && c->fdno == AST_TIMING_FD) { 03602 /* Clearing the timing func and setting the rate to 0 03603 * means that we don't want to be reading from the timingfd 03604 * any more. Setting c->fdno to -1 means we won't have any 03605 * errant reads from the timingfd, meaning we won't potentially 03606 * miss any important frames. 03607 */ 03608 c->fdno = -1; 03609 } 03610 03611 ast_channel_unlock(c); 03612 03613 return res; 03614 }
int ast_shutting_down | ( | void | ) |
Returns non-zero if Asterisk is being shut down.
Definition at line 865 of file channel.c.
Referenced by handle_request_options().
00866 { 00867 return shutting_down; 00868 }
int ast_softhangup | ( | struct ast_channel * | chan, | |
int | cause | |||
) |
Softly hangup a channel, lock.
Softly hangup up a channel.
Definition at line 2746 of file channel.c.
References ast_channel_lock, ast_channel_unlock, and ast_softhangup_nolock().
Referenced by __analog_handle_event(), __ast_module_user_hangup_all(), __ast_pbx_run(), __unload_module(), agent_hangup(), agent_logoff(), agent_read(), ast_bridge_call(), ast_channel_softhangup_cb(), ast_dial_join(), cc_generic_agent_stop_ringing(), conf_free(), dahdi_handle_event(), handle_hangup(), handle_softhangup(), login_exec(), manager_park(), mgcp_pktcgate_remove(), read_agent_config(), sla_handle_hold_event(), softhangup_exec(), start_spying(), startmon(), and unload_module().
02747 { 02748 int res; 02749 02750 ast_channel_lock(chan); 02751 res = ast_softhangup_nolock(chan, cause); 02752 ast_channel_unlock(chan); 02753 02754 return res; 02755 }
int ast_softhangup_nolock | ( | struct ast_channel * | chan, | |
int | cause | |||
) |
Softly hangup a channel, don't lock.
Softly hangup up a channel (no channel lock).
Definition at line 2733 of file channel.c.
References ast_channel::_softhangup, ast_debug, AST_FLAG_BLOCKING, ast_null_frame, ast_queue_frame(), ast_test_flag, and ast_channel::blocker.
Referenced by __analog_handle_event(), action_hangup(), analog_attempt_transfer(), ast_async_goto(), ast_softhangup(), attempt_transfer(), check_pendings(), check_rtp_timeout(), dahdi_softhangup_all(), gosub_run(), oh323_indicate(), proc_session_timer(), sip_indicate(), and skinny_indicate().
02734 { 02735 ast_debug(1, "Soft-Hanging up channel '%s'\n", chan->name); 02736 /* Inform channel driver that we need to be hung up, if it cares */ 02737 chan->_softhangup |= cause; 02738 ast_queue_frame(chan, &ast_null_frame); 02739 /* Interrupt any poll call or such */ 02740 if (ast_test_flag(chan, AST_FLAG_BLOCKING)) 02741 pthread_kill(chan->blocker, SIGURG); 02742 return 0; 02743 }
const char* ast_state2str | ( | enum ast_channel_state | state | ) |
Gives the string form of a given channel state.
Definition at line 1007 of file channel.c.
References AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DIALING_OFFHOOK, AST_STATE_DOWN, AST_STATE_OFFHOOK, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_threadstorage_get(), STATE2STR_BUFSIZE, and state2str_threadbuf.
Referenced by __ast_channel_alloc_ap(), action_coreshowchannels(), action_status(), agent_hangup(), ast_channel_data_add_structure(), ast_do_masquerade(), ast_setstate(), attempt_transfer(), func_channel_read(), handle_chanlist(), handle_showchan(), local_attended_transfer(), mgcp_new(), serialize_showchan(), sip_hangup(), and update_connectedline().
01008 { 01009 char *buf; 01010 01011 switch (state) { 01012 case AST_STATE_DOWN: 01013 return "Down"; 01014 case AST_STATE_RESERVED: 01015 return "Rsrvd"; 01016 case AST_STATE_OFFHOOK: 01017 return "OffHook"; 01018 case AST_STATE_DIALING: 01019 return "Dialing"; 01020 case AST_STATE_RING: 01021 return "Ring"; 01022 case AST_STATE_RINGING: 01023 return "Ringing"; 01024 case AST_STATE_UP: 01025 return "Up"; 01026 case AST_STATE_BUSY: 01027 return "Busy"; 01028 case AST_STATE_DIALING_OFFHOOK: 01029 return "Dialing Offhook"; 01030 case AST_STATE_PRERING: 01031 return "Pre-ring"; 01032 default: 01033 if (!(buf = ast_threadstorage_get(&state2str_threadbuf, STATE2STR_BUFSIZE))) 01034 return "Unknown"; 01035 snprintf(buf, STATE2STR_BUFSIZE, "Unknown (%u)", state); 01036 return buf; 01037 } 01038 }
int ast_str2cause | ( | const char * | name | ) |
int ast_tonepair | ( | struct ast_channel * | chan, | |
int | freq1, | |||
int | freq2, | |||
int | duration, | |||
int | vol | |||
) |
Play a tone pair for a given amount of time
Definition at line 7969 of file channel.c.
References ast_frfree, ast_read(), ast_tonepair_start(), ast_waitfor(), and ast_channel::generatordata.
Referenced by zapateller_exec().
07970 { 07971 int res; 07972 07973 if ((res = ast_tonepair_start(chan, freq1, freq2, duration, vol))) 07974 return res; 07975 07976 /* Give us some wiggle room */ 07977 while (chan->generatordata && ast_waitfor(chan, 100) >= 0) { 07978 struct ast_frame *f = ast_read(chan); 07979 if (f) 07980 ast_frfree(f); 07981 else 07982 return -1; 07983 } 07984 return 0; 07985 }
int ast_tonepair_start | ( | struct ast_channel * | chan, | |
int | freq1, | |||
int | freq2, | |||
int | duration, | |||
int | vol | |||
) |
Start a tone going
Definition at line 7951 of file channel.c.
References ast_activate_generator(), tonepair_def::duration, tonepair_def::freq1, tonepair_def::freq2, and tonepair_def::vol.
Referenced by ast_tonepair(), pbx_builtin_waitexten(), play_dialtone(), and sendnoise().
void ast_tonepair_stop | ( | struct ast_channel * | chan | ) |
Stop a tone from playing
Definition at line 7964 of file channel.c.
References ast_deactivate_generator().
Referenced by sendnoise().
07965 { 07966 ast_deactivate_generator(chan); 07967 }
int ast_transfer | ( | struct ast_channel * | chan, | |
char * | dest | |||
) |
Transfer a call to dest, if the channel supports transfer.
Transfer a channel (if supported).
Called by:
Definition at line 5788 of file channel.c.
References ast_channel_lock, ast_channel_unlock, ast_check_hangup(), AST_CONTROL_TRANSFER, AST_FLAG_ZOMBIE, AST_FRAME_CONTROL, ast_frfree, ast_read(), ast_test_flag, AST_TRANSFER_SUCCESS, ast_waitfor(), ast_frame::data, ast_frame::frametype, ast_frame_subclass::integer, ast_frame::ptr, ast_frame::subclass, ast_channel::tech, and ast_channel_tech::transfer.
Referenced by transfer_exec().
05789 { 05790 int res = -1; 05791 05792 /* Stop if we're a zombie or need a soft hangup */ 05793 ast_channel_lock(chan); 05794 if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan)) { 05795 if (chan->tech->transfer) { 05796 res = chan->tech->transfer(chan, dest); 05797 if (!res) 05798 res = 1; 05799 } else 05800 res = 0; 05801 } 05802 ast_channel_unlock(chan); 05803 05804 if (res <= 0) { 05805 return res; 05806 } 05807 05808 for (;;) { 05809 struct ast_frame *fr; 05810 05811 res = ast_waitfor(chan, -1); 05812 05813 if (res < 0 || !(fr = ast_read(chan))) { 05814 res = -1; 05815 break; 05816 } 05817 05818 if (fr->frametype == AST_FRAME_CONTROL && fr->subclass.integer == AST_CONTROL_TRANSFER) { 05819 enum ast_control_transfer *message = fr->data.ptr; 05820 05821 if (*message == AST_TRANSFER_SUCCESS) { 05822 res = 1; 05823 } else { 05824 res = -1; 05825 } 05826 05827 ast_frfree(fr); 05828 break; 05829 } 05830 05831 ast_frfree(fr); 05832 } 05833 05834 return res; 05835 }
char* ast_transfercapability2str | ( | int | transfercapability | ) | const |
Gives the string form of a given transfer capability.
transfercapability | transfer capability to get the name of |
Definition at line 1041 of file channel.c.
References AST_TRANS_CAP_3_1K_AUDIO, AST_TRANS_CAP_DIGITAL, AST_TRANS_CAP_DIGITAL_W_TONES, AST_TRANS_CAP_RESTRICTED_DIGITAL, AST_TRANS_CAP_SPEECH, and AST_TRANS_CAP_VIDEO.
Referenced by ast_channel_data_add_structure(), cb_events(), misdn_call(), and oh323_call().
01042 { 01043 switch (transfercapability) { 01044 case AST_TRANS_CAP_SPEECH: 01045 return "SPEECH"; 01046 case AST_TRANS_CAP_DIGITAL: 01047 return "DIGITAL"; 01048 case AST_TRANS_CAP_RESTRICTED_DIGITAL: 01049 return "RESTRICTED_DIGITAL"; 01050 case AST_TRANS_CAP_3_1K_AUDIO: 01051 return "3K1AUDIO"; 01052 case AST_TRANS_CAP_DIGITAL_W_TONES: 01053 return "DIGITAL_W_TONES"; 01054 case AST_TRANS_CAP_VIDEO: 01055 return "VIDEO"; 01056 default: 01057 return "UNKNOWN"; 01058 } 01059 }
int ast_undestroyed_channels | ( | void | ) |
Definition at line 853 of file channel.c.
References ast_atomic_fetchadd_int().
Referenced by can_safely_quit().
00854 { 00855 return ast_atomic_fetchadd_int(&chancount, 0); 00856 }
void ast_uninstall_music_functions | ( | void | ) |
Definition at line 8032 of file channel.c.
References ast_moh_cleanup_ptr, ast_moh_start_ptr, and ast_moh_stop_ptr.
Referenced by unload_module().
08033 { 08034 ast_moh_start_ptr = NULL; 08035 ast_moh_stop_ptr = NULL; 08036 ast_moh_cleanup_ptr = NULL; 08037 }
int ast_waitfor | ( | struct ast_channel * | chan, | |
int | ms | |||
) |
Wait for input on a channel.
chan | channel to wait on | |
ms | length of time to wait on the channel |
Wait for input on a channel for a given # of milliseconds (<0 for indefinite).
< | 0 on failure | |
0 | if nothing ever arrived | |
the | # of ms remaining otherwise |
Definition at line 3539 of file channel.c.
References ast_waitfor_nandfds().
Referenced by __adsi_transmit_messages(), __analog_ss_thread(), __ast_answer(), __ast_play_and_record(), __ast_request_and_dial(), adsi_careful_send(), agent_ack_sleep(), analog_ss_thread(), ast_dtmf_stream(), ast_recvtext(), ast_safe_sleep_conditional(), ast_tonepair(), ast_transfer(), async_wait(), background_detect_exec(), channel_spy(), conf_flush(), dictate_exec(), disa_exec(), disable_t38(), do_waiting(), echo_exec(), handle_recordfile(), handle_speechrecognize(), ices_exec(), isAnsweringMachine(), jack_exec(), launch_asyncagi(), measurenoise(), mp3_exec(), NBScat_exec(), receive_dtmf_digits(), receivefax_t38_init(), record_exec(), recordthread(), send_tone_burst(), send_waveform_to_channel(), sendfax_t38_init(), sendurl_exec(), speech_background(), transmit_audio(), transmit_t38(), wait_for_hangup(), waitforring_exec(), and waitstream_core().
03540 { 03541 if (ms < 0) { 03542 do { 03543 ms = 100000; 03544 ast_waitfor_nandfds(&c, 1, NULL, 0, NULL, NULL, &ms); 03545 } while (!ms); 03546 } else { 03547 ast_waitfor_nandfds(&c, 1, NULL, 0, NULL, NULL, &ms); 03548 } 03549 return ms; 03550 }
struct ast_channel* ast_waitfor_n | ( | struct ast_channel ** | chan, | |
int | n, | |||
int * | ms | |||
) | [read] |
Waits for input on a group of channels Wait for input on an array of channels for a given # of milliseconds.
chan | an array of pointers to channels | |
n | number of channels that are to be waited upon | |
ms | time "ms" is modified in-place, if applicable |
Definition at line 3534 of file channel.c.
References ast_waitfor_nandfds().
Referenced by ast_generic_bridge(), ast_udptl_bridge(), autoservice_run(), dahdi_bridge(), dial_exec_full(), feature_request_and_dial(), generic_thread_loop(), iax2_bridge(), local_bridge_loop(), misdn_bridge(), monitor_dial(), remote_bridge_loop(), wait_for_answer(), and wait_for_winner().
03535 { 03536 return ast_waitfor_nandfds(c, n, NULL, 0, NULL, NULL, ms); 03537 }
int ast_waitfor_n_fd | ( | int * | fds, | |
int | n, | |||
int * | ms, | |||
int * | exception | |||
) |
Wait for x amount of time on a file descriptor to have input.
Waits for input on an fd.
Definition at line 3176 of file channel.c.
References ast_waitfor_nandfds().
Referenced by dundi_lookup_internal(), dundi_precache_internal(), and softmix_bridge_thread().
03177 { 03178 int winner = -1; 03179 ast_waitfor_nandfds(NULL, 0, fds, n, exception, &winner, ms); 03180 return winner; 03181 }
struct ast_channel* ast_waitfor_nandfds | ( | struct ast_channel ** | c, | |
int | n, | |||
int * | fds, | |||
int | nfds, | |||
int * | exception, | |||
int * | outfd, | |||
int * | ms | |||
) | [read] |
Wait for x amount of time on a file descriptor to have input.
Waits for activity on a group of channels.
Definition at line 3188 of file channel.c.
References ast_channel::_softhangup, ast_add_fd(), ast_alloca, ast_channel_lock, ast_channel_unlock, ast_clear_flag, ast_do_masquerade(), AST_FLAG_BLOCKING, AST_FLAG_EXCEPTION, AST_MAX_FDS, ast_poll, ast_set_flag, AST_SOFTHANGUP_TIMEOUT, ast_test_suite_event_notify, ast_tvcmp(), ast_tvdiff_ms(), ast_tvnow(), ast_tvsub(), ast_tvzero(), CHECK_BLOCKING, errno, ast_channel::fdno, and name.
Referenced by ast_waitfor(), ast_waitfor_n(), ast_waitfor_n_fd(), ast_waitfordigit_full(), bridge_channel_join_multithreaded(), conf_run(), eivr_comm(), find_cache(), generic_fax_exec(), multiplexed_thread_function(), run_agi(), and waitstream_core().
03191 { 03192 struct timeval start = { 0 , 0 }; 03193 struct pollfd *pfds = NULL; 03194 int res; 03195 long rms; 03196 int x, y, max; 03197 int sz; 03198 struct timeval now = { 0, 0 }; 03199 struct timeval whentohangup = { 0, 0 }, diff; 03200 struct ast_channel *winner = NULL; 03201 struct fdmap { 03202 int chan; 03203 int fdno; 03204 } *fdmap = NULL; 03205 03206 if (outfd) 03207 *outfd = -99999; 03208 if (exception) 03209 *exception = 0; 03210 03211 if ((sz = n * AST_MAX_FDS + nfds)) { 03212 pfds = ast_alloca(sizeof(*pfds) * sz); 03213 fdmap = ast_alloca(sizeof(*fdmap) * sz); 03214 } else { 03215 /* nothing to allocate and no FDs to check */ 03216 return NULL; 03217 } 03218 03219 /* Perform any pending masquerades */ 03220 for (x = 0; x < n; x++) { 03221 while (c[x]->masq) { 03222 ast_do_masquerade(c[x]); 03223 } 03224 03225 ast_channel_lock(c[x]); 03226 if (!ast_tvzero(c[x]->whentohangup)) { 03227 if (ast_tvzero(whentohangup)) 03228 now = ast_tvnow(); 03229 diff = ast_tvsub(c[x]->whentohangup, now); 03230 if (diff.tv_sec < 0 || ast_tvzero(diff)) { 03231 ast_test_suite_event_notify("HANGUP_TIME", "Channel: %s", c[x]->name); 03232 /* Should already be hungup */ 03233 c[x]->_softhangup |= AST_SOFTHANGUP_TIMEOUT; 03234 ast_channel_unlock(c[x]); 03235 return c[x]; 03236 } 03237 if (ast_tvzero(whentohangup) || ast_tvcmp(diff, whentohangup) < 0) 03238 whentohangup = diff; 03239 } 03240 ast_channel_unlock(c[x]); 03241 } 03242 /* Wait full interval */ 03243 rms = *ms; 03244 /* INT_MAX, not LONG_MAX, because it matters on 64-bit */ 03245 if (!ast_tvzero(whentohangup) && whentohangup.tv_sec < INT_MAX / 1000) { 03246 rms = whentohangup.tv_sec * 1000 + whentohangup.tv_usec / 1000; /* timeout in milliseconds */ 03247 if (*ms >= 0 && *ms < rms) { /* original *ms still smaller */ 03248 rms = *ms; 03249 } 03250 } else if (!ast_tvzero(whentohangup) && rms < 0) { 03251 /* Tiny corner case... call would need to last >24 days */ 03252 rms = INT_MAX; 03253 } 03254 /* 03255 * Build the pollfd array, putting the channels' fds first, 03256 * followed by individual fds. Order is important because 03257 * individual fd's must have priority over channel fds. 03258 */ 03259 max = 0; 03260 for (x = 0; x < n; x++) { 03261 for (y = 0; y < AST_MAX_FDS; y++) { 03262 fdmap[max].fdno = y; /* fd y is linked to this pfds */ 03263 fdmap[max].chan = x; /* channel x is linked to this pfds */ 03264 max += ast_add_fd(&pfds[max], c[x]->fds[y]); 03265 } 03266 CHECK_BLOCKING(c[x]); 03267 } 03268 /* Add the individual fds */ 03269 for (x = 0; x < nfds; x++) { 03270 fdmap[max].chan = -1; 03271 max += ast_add_fd(&pfds[max], fds[x]); 03272 } 03273 03274 if (*ms > 0) 03275 start = ast_tvnow(); 03276 03277 if (sizeof(int) == 4) { /* XXX fix timeout > 600000 on linux x86-32 */ 03278 do { 03279 int kbrms = rms; 03280 if (kbrms > 600000) 03281 kbrms = 600000; 03282 res = ast_poll(pfds, max, kbrms); 03283 if (!res) 03284 rms -= kbrms; 03285 } while (!res && (rms > 0)); 03286 } else { 03287 res = ast_poll(pfds, max, rms); 03288 } 03289 for (x = 0; x < n; x++) 03290 ast_clear_flag(c[x], AST_FLAG_BLOCKING); 03291 if (res < 0) { /* Simulate a timeout if we were interrupted */ 03292 if (errno != EINTR) 03293 *ms = -1; 03294 return NULL; 03295 } 03296 if (!ast_tvzero(whentohangup)) { /* if we have a timeout, check who expired */ 03297 now = ast_tvnow(); 03298 for (x = 0; x < n; x++) { 03299 if (!ast_tvzero(c[x]->whentohangup) && ast_tvcmp(c[x]->whentohangup, now) <= 0) { 03300 ast_test_suite_event_notify("HANGUP_TIME", "Channel: %s", c[x]->name); 03301 c[x]->_softhangup |= AST_SOFTHANGUP_TIMEOUT; 03302 if (winner == NULL) 03303 winner = c[x]; 03304 } 03305 } 03306 } 03307 if (res == 0) { /* no fd ready, reset timeout and done */ 03308 *ms = 0; /* XXX use 0 since we may not have an exact timeout. */ 03309 return winner; 03310 } 03311 /* 03312 * Then check if any channel or fd has a pending event. 03313 * Remember to check channels first and fds last, as they 03314 * must have priority on setting 'winner' 03315 */ 03316 for (x = 0; x < max; x++) { 03317 res = pfds[x].revents; 03318 if (res == 0) 03319 continue; 03320 if (fdmap[x].chan >= 0) { /* this is a channel */ 03321 winner = c[fdmap[x].chan]; /* override previous winners */ 03322 if (res & POLLPRI) 03323 ast_set_flag(winner, AST_FLAG_EXCEPTION); 03324 else 03325 ast_clear_flag(winner, AST_FLAG_EXCEPTION); 03326 winner->fdno = fdmap[x].fdno; 03327 } else { /* this is an fd */ 03328 if (outfd) 03329 *outfd = pfds[x].fd; 03330 if (exception) 03331 *exception = (res & POLLPRI) ? -1 : 0; 03332 winner = NULL; 03333 } 03334 } 03335 if (*ms > 0) { 03336 *ms -= ast_tvdiff_ms(ast_tvnow(), start); 03337 if (*ms < 0) 03338 *ms = 0; 03339 } 03340 return winner; 03341 }
int ast_waitfordigit | ( | struct ast_channel * | c, | |
int | ms | |||
) |
Waits for a digit.
c | channel to wait for a digit on | |
ms | how many milliseconds to wait (<0 for indefinite). |
Definition at line 3552 of file channel.c.
References ast_waitfordigit_full().
Referenced by __analog_ss_thread(), _while_exec(), adsi_get_cpeid(), adsi_get_cpeinfo(), adsi_print(), adsi_read_encoded_dtmf(), adsi_transmit_message_full(), advanced_options(), analog_my_getsigstr(), analog_ss_thread(), ast_app_dtget(), ast_control_streamfile(), AST_LIST_HEAD(), ast_record_review(), bridge_channel_feature(), builtin_atxfer(), collect_digits(), common_exec(), cpeid_exec(), dialout(), directory_exec(), forward_message(), get_folder(), ivr_dispatch(), mgcp_ss(), my_getsigstr(), pbx_builtin_waitexten(), play_record_review(), read_newoption(), readexten_exec(), retrydial_exec(), select_item_menu(), select_item_pause(), select_item_seq(), sendnoise(), testclient_exec(), testserver_exec(), vm_execmain(), vm_forwardoptions(), vm_instructions_en(), vm_options(), vm_tempgreeting(), wait_a_bit(), and wait_our_turn().
03553 { 03554 return ast_waitfordigit_full(c, ms, -1, -1); 03555 }
int ast_waitfordigit_full | ( | struct ast_channel * | c, | |
int | ms, | |||
int | audiofd, | |||
int | ctrlfd | |||
) |
Wait for a digit Same as ast_waitfordigit() with audio fd for outputting read audio and ctrlfd to monitor for reading.
c | channel to wait for a digit on | |
ms | how many milliseconds to wait (<0 for indefinite). | |
audiofd | audio file descriptor to write to if audio frames are received | |
ctrlfd | control file descriptor to monitor for reading |
Definition at line 3616 of file channel.c.
References ast_check_hangup(), ast_clear_flag, AST_CONTROL_ANSWER, AST_CONTROL_CONNECTED_LINE, AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_REDIRECTING, AST_CONTROL_RINGING, AST_CONTROL_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, AST_CONTROL_UPDATE_RTP_PEER, AST_FLAG_END_DTMF_ONLY, AST_FLAG_ZOMBIE, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_VOICE, ast_frfree, ast_log(), ast_read(), ast_remaining_ms(), ast_set_flag, ast_test_flag, ast_tvnow(), ast_waitfor_nandfds(), ast_frame::data, ast_frame::datalen, errno, ast_frame::frametype, ast_frame_subclass::integer, LOG_WARNING, ast_frame::ptr, and ast_frame::subclass.
Referenced by ast_readstring_full(), ast_waitfordigit(), handle_getoption(), and handle_waitfordigit().
03617 { 03618 struct timeval start = ast_tvnow(); 03619 int ms; 03620 03621 /* Stop if we're a zombie or need a soft hangup */ 03622 if (ast_test_flag(c, AST_FLAG_ZOMBIE) || ast_check_hangup(c)) 03623 return -1; 03624 03625 /* Only look for the end of DTMF, don't bother with the beginning and don't emulate things */ 03626 ast_set_flag(c, AST_FLAG_END_DTMF_ONLY); 03627 03628 /* Wait for a digit, no more than timeout_ms milliseconds total. 03629 * Or, wait indefinitely if timeout_ms is <0. 03630 */ 03631 while ((ms = ast_remaining_ms(start, timeout_ms))) { 03632 struct ast_channel *rchan; 03633 int outfd = -1; 03634 03635 errno = 0; 03636 /* While ast_waitfor_nandfds tries to help by reducing the timeout by how much was waited, 03637 * it is unhelpful if it waited less than a millisecond. 03638 */ 03639 rchan = ast_waitfor_nandfds(&c, 1, &cmdfd, (cmdfd > -1) ? 1 : 0, NULL, &outfd, &ms); 03640 03641 if (!rchan && outfd < 0 && ms) { 03642 if (errno == 0 || errno == EINTR) 03643 continue; 03644 ast_log(LOG_WARNING, "Wait failed (%s)\n", strerror(errno)); 03645 ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); 03646 return -1; 03647 } else if (outfd > -1) { 03648 /* The FD we were watching has something waiting */ 03649 ast_log(LOG_WARNING, "The FD we were waiting for has something waiting. Waitfordigit returning numeric 1\n"); 03650 ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); 03651 return 1; 03652 } else if (rchan) { 03653 int res; 03654 struct ast_frame *f = ast_read(c); 03655 if (!f) 03656 return -1; 03657 03658 switch (f->frametype) { 03659 case AST_FRAME_DTMF_BEGIN: 03660 break; 03661 case AST_FRAME_DTMF_END: 03662 res = f->subclass.integer; 03663 ast_frfree(f); 03664 ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); 03665 return res; 03666 case AST_FRAME_CONTROL: 03667 switch (f->subclass.integer) { 03668 case AST_CONTROL_HANGUP: 03669 ast_frfree(f); 03670 ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); 03671 return -1; 03672 case AST_CONTROL_RINGING: 03673 case AST_CONTROL_ANSWER: 03674 case AST_CONTROL_SRCUPDATE: 03675 case AST_CONTROL_SRCCHANGE: 03676 case AST_CONTROL_CONNECTED_LINE: 03677 case AST_CONTROL_REDIRECTING: 03678 case AST_CONTROL_UPDATE_RTP_PEER: 03679 case AST_CONTROL_HOLD: 03680 case AST_CONTROL_UNHOLD: 03681 case -1: 03682 /* Unimportant */ 03683 break; 03684 default: 03685 ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", f->subclass.integer); 03686 break; 03687 } 03688 break; 03689 case AST_FRAME_VOICE: 03690 /* Write audio if appropriate */ 03691 if (audiofd > -1) { 03692 if (write(audiofd, f->data.ptr, f->datalen) < 0) { 03693 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 03694 } 03695 } 03696 default: 03697 /* Ignore */ 03698 break; 03699 } 03700 ast_frfree(f); 03701 } 03702 } 03703 03704 ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); 03705 03706 return 0; /* Time is up */ 03707 }
int ast_write | ( | struct ast_channel * | chan, | |
struct ast_frame * | frame | |||
) |
Write a frame to a channel This function writes the given frame to the indicated channel.
chan | destination channel of the frame | |
frame | frame that will be written |
Definition at line 4916 of file channel.c.
References ast_channel::_softhangup, apply_plc(), ast_audiohook_detach_list(), AST_AUDIOHOOK_DIRECTION_WRITE, ast_audiohook_write_list(), ast_audiohook_write_list_empty(), ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_check_hangup(), ast_clear_flag, AST_CONTROL_UNHOLD, ast_deactivate_generator(), ast_debug, ast_do_masquerade(), AST_FLAG_BLOCKING, AST_FLAG_WRITE_INT, AST_FLAG_ZOMBIE, AST_FORMAT_AUDIO_MASK, ast_format_rate(), AST_FORMAT_SLINEAR, AST_FORMAT_T140, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_frame_dump(), AST_FRAME_HTML, AST_FRAME_IAX, AST_FRAME_MODEM, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_framehook_list_write_event(), ast_frfree, ast_frisolate(), ast_getformatname(), ast_getformatname_multiple(), AST_LIST_NEXT, ast_log(), AST_MONITOR_RUNNING, ast_opt_generic_plc, ast_seekstream(), ast_senddigit_begin(), ast_senddigit_end(), ast_set_write_format(), AST_SOFTHANGUP_DEV, ast_test_flag, ast_translate(), ast_writestream(), ast_channel::audiohooks, calc_monitor_jump(), CHECK_BLOCKING, ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, DEBUGCHAN_FLAG, ast_filestream::fmt, ast_format::format, ast_channel::fout, FRAMECOUNT_INC, ast_channel::framehooks, ast_frame::frametype, ast_channel::generatordata, ast_channel_tech::indicate, ast_channel::insmpl, ast_frame_subclass::integer, ast_frame::len, LOG_WARNING, ast_channel::masq, ast_channel::masqr, ast_channel::monitor, ast_channel::nativeformats, chanlist::next, ast_channel::outsmpl, ast_frame::ptr, ast_channel::rawwriteformat, ast_channel_monitor::read_stream, ast_frame::samples, SEEK_FORCECUR, send_dtmf_event(), ast_channel_tech::send_html, ast_channel_tech::send_text, ast_frame::src, ast_channel_monitor::state, ast_frame::subclass, ast_channel::tech, ast_channel_tech::write, ast_channel_monitor::write_stream, ast_channel_tech::write_text, ast_channel_tech::write_video, ast_channel::writeformat, and ast_channel::writetrans.
Referenced by adsi_careful_send(), agent_write(), ast_bridge_call(), ast_generic_bridge(), ast_prod(), ast_readaudio_callback(), ast_readvideo_callback(), ast_udptl_bridge(), ast_write_video(), conf_queue_dtmf(), conf_run(), dahdi_bridge(), dictate_exec(), echo_exec(), fax_generator_generate(), feature_request_and_dial(), gen_generate(), generic_fax_exec(), handle_jack_audio(), iax2_bridge(), jb_get_and_deliver(), linear_generator(), local_bridge_loop(), milliwatt_generate(), misdn_bridge(), moh_files_generator(), moh_generate(), mp3_exec(), multiplexed_bridge_write(), NBScat_exec(), playtones_generator(), remote_bridge_loop(), send_tone_burst(), send_waveform_to_channel(), silence_generator_generate(), simple_bridge_write(), sms_generate(), softmix_bridge_poke(), softmix_bridge_write(), spy_generate(), t38_tx_packet_handler(), tonepair_generator(), and wait_for_answer().
04917 { 04918 int res = -1; 04919 struct ast_frame *f = NULL; 04920 int count = 0; 04921 04922 /*Deadlock avoidance*/ 04923 while(ast_channel_trylock(chan)) { 04924 /*cannot goto done since the channel is not locked*/ 04925 if(count++ > 10) { 04926 ast_debug(1, "Deadlock avoided for write to channel '%s'\n", chan->name); 04927 return 0; 04928 } 04929 usleep(1); 04930 } 04931 /* Stop if we're a zombie or need a soft hangup */ 04932 if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) 04933 goto done; 04934 04935 /* Handle any pending masquerades */ 04936 while (chan->masq) { 04937 ast_channel_unlock(chan); 04938 ast_do_masquerade(chan); 04939 ast_channel_lock(chan); 04940 } 04941 if (chan->masqr) { 04942 res = 0; /* XXX explain, why 0 ? */ 04943 goto done; 04944 } 04945 04946 /* Perform the framehook write event here. After the frame enters the framehook list 04947 * there is no telling what will happen, how awesome is that!!! */ 04948 if (!(fr = ast_framehook_list_write_event(chan->framehooks, fr))) { 04949 res = 0; 04950 goto done; 04951 } 04952 04953 if (chan->generatordata && (!fr->src || strcasecmp(fr->src, "ast_prod"))) { 04954 if (ast_test_flag(chan, AST_FLAG_WRITE_INT)) { 04955 ast_deactivate_generator(chan); 04956 } else { 04957 if (fr->frametype == AST_FRAME_DTMF_END) { 04958 /* There is a generator running while we're in the middle of a digit. 04959 * It's probably inband DTMF, so go ahead and pass it so it can 04960 * stop the generator */ 04961 ast_clear_flag(chan, AST_FLAG_BLOCKING); 04962 ast_channel_unlock(chan); 04963 res = ast_senddigit_end(chan, fr->subclass.integer, fr->len); 04964 ast_channel_lock(chan); 04965 CHECK_BLOCKING(chan); 04966 } else if (fr->frametype == AST_FRAME_CONTROL && fr->subclass.integer == AST_CONTROL_UNHOLD) { 04967 /* This is a side case where Echo is basically being called and the person put themselves on hold and took themselves off hold */ 04968 res = (chan->tech->indicate == NULL) ? 0 : 04969 chan->tech->indicate(chan, fr->subclass.integer, fr->data.ptr, fr->datalen); 04970 } 04971 res = 0; /* XXX explain, why 0 ? */ 04972 goto done; 04973 } 04974 } 04975 /* High bit prints debugging */ 04976 if (chan->fout & DEBUGCHAN_FLAG) 04977 ast_frame_dump(chan->name, fr, ">>"); 04978 CHECK_BLOCKING(chan); 04979 switch (fr->frametype) { 04980 case AST_FRAME_CONTROL: 04981 res = (chan->tech->indicate == NULL) ? 0 : 04982 chan->tech->indicate(chan, fr->subclass.integer, fr->data.ptr, fr->datalen); 04983 break; 04984 case AST_FRAME_DTMF_BEGIN: 04985 if (chan->audiohooks) { 04986 struct ast_frame *old_frame = fr; 04987 fr = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_WRITE, fr); 04988 if (old_frame != fr) 04989 f = fr; 04990 } 04991 send_dtmf_event(chan, "Sent", fr->subclass.integer, "Yes", "No"); 04992 ast_clear_flag(chan, AST_FLAG_BLOCKING); 04993 ast_channel_unlock(chan); 04994 res = ast_senddigit_begin(chan, fr->subclass.integer); 04995 ast_channel_lock(chan); 04996 CHECK_BLOCKING(chan); 04997 break; 04998 case AST_FRAME_DTMF_END: 04999 if (chan->audiohooks) { 05000 struct ast_frame *new_frame = fr; 05001 05002 new_frame = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_WRITE, fr); 05003 if (new_frame != fr) { 05004 ast_frfree(new_frame); 05005 } 05006 } 05007 send_dtmf_event(chan, "Sent", fr->subclass.integer, "No", "Yes"); 05008 ast_clear_flag(chan, AST_FLAG_BLOCKING); 05009 ast_channel_unlock(chan); 05010 res = ast_senddigit_end(chan, fr->subclass.integer, fr->len); 05011 ast_channel_lock(chan); 05012 CHECK_BLOCKING(chan); 05013 break; 05014 case AST_FRAME_TEXT: 05015 if (fr->subclass.integer == AST_FORMAT_T140) { 05016 res = (chan->tech->write_text == NULL) ? 0 : 05017 chan->tech->write_text(chan, fr); 05018 } else { 05019 res = (chan->tech->send_text == NULL) ? 0 : 05020 chan->tech->send_text(chan, (char *) fr->data.ptr); 05021 } 05022 break; 05023 case AST_FRAME_HTML: 05024 res = (chan->tech->send_html == NULL) ? 0 : 05025 chan->tech->send_html(chan, fr->subclass.integer, (char *) fr->data.ptr, fr->datalen); 05026 break; 05027 case AST_FRAME_VIDEO: 05028 /* XXX Handle translation of video codecs one day XXX */ 05029 res = (chan->tech->write_video == NULL) ? 0 : 05030 chan->tech->write_video(chan, fr); 05031 break; 05032 case AST_FRAME_MODEM: 05033 res = (chan->tech->write == NULL) ? 0 : 05034 chan->tech->write(chan, fr); 05035 break; 05036 case AST_FRAME_VOICE: 05037 if (chan->tech->write == NULL) 05038 break; /*! \todo XXX should return 0 maybe ? */ 05039 05040 if (ast_opt_generic_plc && fr->subclass.codec == AST_FORMAT_SLINEAR) { 05041 apply_plc(chan, fr); 05042 } 05043 05044 /* If the frame is in the raw write format, then it's easy... just use the frame - otherwise we will have to translate */ 05045 if (fr->subclass.codec == chan->rawwriteformat) { 05046 f = fr; 05047 } else { 05048 if ((!(fr->subclass.codec & chan->nativeformats)) && (chan->writeformat != fr->subclass.codec)) { 05049 char nf[512]; 05050 05051 /* 05052 * XXX Something is not right. We are not compatible with this 05053 * frame. Bad things can happen. Problems range from no audio, 05054 * one-way audio, to unexplained line hangups. As a last resort 05055 * try to adjust the format. Ideally, we do not want to do this 05056 * because it indicates a deeper problem. For now, we log these 05057 * events to reduce user impact and help identify the problem 05058 * areas. 05059 */ 05060 ast_log(LOG_WARNING, "Codec mismatch on channel %s setting write format to %s from %s native formats %s\n", 05061 chan->name, ast_getformatname(fr->subclass.codec), ast_getformatname(chan->writeformat), 05062 ast_getformatname_multiple(nf, sizeof(nf), chan->nativeformats & AST_FORMAT_AUDIO_MASK)); 05063 ast_set_write_format(chan, fr->subclass.codec); 05064 } 05065 05066 f = (chan->writetrans) ? ast_translate(chan->writetrans, fr, 0) : fr; 05067 } 05068 05069 if (!f) { 05070 res = 0; 05071 break; 05072 } 05073 05074 if (chan->audiohooks) { 05075 struct ast_frame *prev = NULL, *new_frame, *cur, *dup; 05076 int freeoldlist = 0; 05077 05078 if (f != fr) { 05079 freeoldlist = 1; 05080 } 05081 05082 /* Since ast_audiohook_write may return a new frame, and the cur frame is 05083 * an item in a list of frames, create a new list adding each cur frame back to it 05084 * regardless if the cur frame changes or not. */ 05085 for (cur = f; cur; cur = AST_LIST_NEXT(cur, frame_list)) { 05086 new_frame = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_WRITE, cur); 05087 05088 /* if this frame is different than cur, preserve the end of the list, 05089 * free the old frames, and set cur to be the new frame */ 05090 if (new_frame != cur) { 05091 05092 /* doing an ast_frisolate here seems silly, but we are not guaranteed the new_frame 05093 * isn't part of local storage, meaning if ast_audiohook_write is called multiple 05094 * times it may override the previous frame we got from it unless we dup it */ 05095 if ((dup = ast_frisolate(new_frame))) { 05096 AST_LIST_NEXT(dup, frame_list) = AST_LIST_NEXT(cur, frame_list); 05097 if (freeoldlist) { 05098 AST_LIST_NEXT(cur, frame_list) = NULL; 05099 ast_frfree(cur); 05100 } 05101 if (new_frame != dup) { 05102 ast_frfree(new_frame); 05103 } 05104 cur = dup; 05105 } 05106 } 05107 05108 /* now, regardless if cur is new or not, add it to the new list, 05109 * if the new list has not started, cur will become the first item. */ 05110 if (prev) { 05111 AST_LIST_NEXT(prev, frame_list) = cur; 05112 } else { 05113 f = cur; /* set f to be the beginning of our new list */ 05114 } 05115 prev = cur; 05116 } 05117 } 05118 05119 /* If Monitor is running on this channel, then we have to write frames out there too */ 05120 /* the translator on chan->writetrans may have returned multiple frames 05121 from the single frame we passed in; if so, feed each one of them to the 05122 monitor */ 05123 if (chan->monitor && chan->monitor->write_stream) { 05124 struct ast_frame *cur; 05125 05126 for (cur = f; cur; cur = AST_LIST_NEXT(cur, frame_list)) { 05127 /* XXX must explain this code */ 05128 #ifndef MONITOR_CONSTANT_DELAY 05129 int jump = chan->insmpl - chan->outsmpl - 4 * cur->samples; 05130 if (jump >= 0) { 05131 jump = calc_monitor_jump((chan->insmpl - chan->outsmpl), ast_format_rate(f->subclass.codec), ast_format_rate(chan->monitor->read_stream->fmt->format)); 05132 if (ast_seekstream(chan->monitor->write_stream, jump, SEEK_FORCECUR) == -1) 05133 ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n"); 05134 chan->outsmpl += (chan->insmpl - chan->outsmpl) + cur->samples; 05135 } else { 05136 chan->outsmpl += cur->samples; 05137 } 05138 #else 05139 int jump = calc_monitor_jump((chan->insmpl - chan->outsmpl), ast_format_rate(f->subclass.codec), ast_format_rate(chan->monitor->read_stream->fmt->format)); 05140 if (jump - MONITOR_DELAY >= 0) { 05141 if (ast_seekstream(chan->monitor->write_stream, jump - cur->samples, SEEK_FORCECUR) == -1) 05142 ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n"); 05143 chan->outsmpl += chan->insmpl - chan->outsmpl; 05144 } else { 05145 chan->outsmpl += cur->samples; 05146 } 05147 #endif 05148 if (chan->monitor->state == AST_MONITOR_RUNNING) { 05149 if (ast_writestream(chan->monitor->write_stream, cur) < 0) 05150 ast_log(LOG_WARNING, "Failed to write data to channel monitor write stream\n"); 05151 } 05152 } 05153 } 05154 05155 /* the translator on chan->writetrans may have returned multiple frames 05156 from the single frame we passed in; if so, feed each one of them to the 05157 channel, freeing each one after it has been written */ 05158 if ((f != fr) && AST_LIST_NEXT(f, frame_list)) { 05159 struct ast_frame *cur, *next; 05160 unsigned int skip = 0; 05161 05162 for (cur = f, next = AST_LIST_NEXT(cur, frame_list); 05163 cur; 05164 cur = next, next = cur ? AST_LIST_NEXT(cur, frame_list) : NULL) { 05165 if (!skip) { 05166 if ((res = chan->tech->write(chan, cur)) < 0) { 05167 chan->_softhangup |= AST_SOFTHANGUP_DEV; 05168 skip = 1; 05169 } else if (next) { 05170 /* don't do this for the last frame in the list, 05171 as the code outside the loop will do it once 05172 */ 05173 chan->fout = FRAMECOUNT_INC(chan->fout); 05174 } 05175 } 05176 ast_frfree(cur); 05177 } 05178 05179 /* reset f so the code below doesn't attempt to free it */ 05180 f = NULL; 05181 } else { 05182 res = chan->tech->write(chan, f); 05183 } 05184 break; 05185 case AST_FRAME_NULL: 05186 case AST_FRAME_IAX: 05187 /* Ignore these */ 05188 res = 0; 05189 break; 05190 default: 05191 /* At this point, fr is the incoming frame and f is NULL. Channels do 05192 * not expect to get NULL as a frame pointer and will segfault. Hence, 05193 * we output the original frame passed in. */ 05194 res = chan->tech->write(chan, fr); 05195 break; 05196 } 05197 05198 if (f && f != fr) 05199 ast_frfree(f); 05200 ast_clear_flag(chan, AST_FLAG_BLOCKING); 05201 05202 /* Consider a write failure to force a soft hangup */ 05203 if (res < 0) { 05204 chan->_softhangup |= AST_SOFTHANGUP_DEV; 05205 } else { 05206 chan->fout = FRAMECOUNT_INC(chan->fout); 05207 } 05208 done: 05209 if (chan->audiohooks && ast_audiohook_write_list_empty(chan->audiohooks)) { 05210 /* The list gets recreated if audiohooks are added again later */ 05211 ast_audiohook_detach_list(chan->audiohooks); 05212 chan->audiohooks = NULL; 05213 } 05214 ast_channel_unlock(chan); 05215 return res; 05216 }
int ast_write_video | ( | struct ast_channel * | chan, | |
struct ast_frame * | frame | |||
) |
Write video frame to a channel This function writes the given frame to the indicated channel.
chan | destination channel of the frame | |
frame | frame that will be written |
Definition at line 4801 of file channel.c.
References ast_write(), ast_channel::tech, and ast_channel_tech::write_video.
04802 { 04803 int res; 04804 if (!chan->tech->write_video) 04805 return 0; 04806 res = ast_write(chan, fr); 04807 if (!res) 04808 res = 1; 04809 return res; 04810 }
static void bridge_play_sounds | ( | struct ast_channel * | c0, | |
struct ast_channel * | c1 | |||
) | [static] |
Definition at line 7478 of file channel.c.
References ast_channel_lock, ast_channel_unlock, ast_strdupa, bridge_playfile(), pbx_builtin_getvar_helper(), and pbx_builtin_setvar_helper().
Referenced by ast_channel_bridge().
07479 { 07480 const char *s, *sound; 07481 07482 /* See if we need to play an audio file to any side of the bridge */ 07483 07484 ast_channel_lock(c0); 07485 if ((s = pbx_builtin_getvar_helper(c0, "BRIDGE_PLAY_SOUND"))) { 07486 sound = ast_strdupa(s); 07487 ast_channel_unlock(c0); 07488 bridge_playfile(c0, c1, sound, 0); 07489 pbx_builtin_setvar_helper(c0, "BRIDGE_PLAY_SOUND", NULL); 07490 } else { 07491 ast_channel_unlock(c0); 07492 } 07493 07494 ast_channel_lock(c1); 07495 if ((s = pbx_builtin_getvar_helper(c1, "BRIDGE_PLAY_SOUND"))) { 07496 sound = ast_strdupa(s); 07497 ast_channel_unlock(c1); 07498 bridge_playfile(c1, c0, sound, 0); 07499 pbx_builtin_setvar_helper(c1, "BRIDGE_PLAY_SOUND", NULL); 07500 } else { 07501 ast_channel_unlock(c1); 07502 } 07503 }
static void bridge_playfile | ( | struct ast_channel * | chan, | |
struct ast_channel * | peer, | |||
const char * | sound, | |||
int | remain | |||
) | [static] |
Definition at line 7169 of file channel.c.
References ast_autoservice_start(), ast_autoservice_stop(), AST_DIGIT_ANY, ast_say_number(), and ast_stream_and_wait().
Referenced by ast_channel_bridge(), and bridge_play_sounds().
07170 { 07171 int min = 0, sec = 0, check; 07172 07173 check = ast_autoservice_start(peer); 07174 if (check) 07175 return; 07176 07177 if (remain > 0) { 07178 if (remain / 60 > 1) { 07179 min = remain / 60; 07180 sec = remain % 60; 07181 } else { 07182 sec = remain; 07183 } 07184 } 07185 07186 if (!strcmp(sound,"timeleft")) { /* Queue support */ 07187 ast_stream_and_wait(chan, "vm-youhave", ""); 07188 if (min) { 07189 ast_say_number(chan, min, AST_DIGIT_ANY, chan->language, NULL); 07190 ast_stream_and_wait(chan, "queue-minutes", ""); 07191 } 07192 if (sec) { 07193 ast_say_number(chan, sec, AST_DIGIT_ANY, chan->language, NULL); 07194 ast_stream_and_wait(chan, "queue-seconds", ""); 07195 } 07196 } else { 07197 ast_stream_and_wait(chan, sound, ""); 07198 } 07199 07200 ast_autoservice_stop(peer); 07201 }
static int calc_monitor_jump | ( | int | samples, | |
int | sample_rate, | |||
int | seek_rate | |||
) | [inline, static] |
calculates the number of samples to jump forward with in a monitor stream.
number | of samples to seek forward after rate conversion. |
Definition at line 3823 of file channel.c.
Referenced by __ast_read(), and ast_write().
static void call_forward_inherit | ( | struct ast_channel * | new_chan, | |
struct ast_channel * | parent, | |||
struct ast_channel * | orig | |||
) | [static] |
Definition at line 5359 of file channel.c.
References ast_channel_datastore_inherit(), ast_channel_inherit_variables(), ast_channel_lock, ast_channel_lock_both, ast_channel_redirecting_macro(), ast_channel_unlock, ast_channel_update_redirecting(), ast_check_hangup(), AST_FLAG_ZOMBIE, ast_party_redirecting_copy(), ast_party_redirecting_free(), ast_party_redirecting_init(), ast_test_flag, and ast_channel::redirecting.
Referenced by ast_call_forward().
05360 { 05361 if (!ast_test_flag(parent, AST_FLAG_ZOMBIE) && !ast_check_hangup(parent)) { 05362 struct ast_party_redirecting redirecting; 05363 05364 /* 05365 * The parent is not a ZOMBIE or hungup so update it with the 05366 * original channel's redirecting information. 05367 */ 05368 ast_party_redirecting_init(&redirecting); 05369 ast_channel_lock(orig); 05370 ast_party_redirecting_copy(&redirecting, &orig->redirecting); 05371 ast_channel_unlock(orig); 05372 if (ast_channel_redirecting_macro(orig, parent, &redirecting, 1, 0)) { 05373 ast_channel_update_redirecting(parent, &redirecting, NULL); 05374 } 05375 ast_party_redirecting_free(&redirecting); 05376 } 05377 05378 /* Safely inherit variables and datastores from the parent channel. */ 05379 ast_channel_lock_both(parent, new_chan); 05380 ast_channel_inherit_variables(parent, new_chan); 05381 ast_channel_datastore_inherit(parent, new_chan); 05382 ast_channel_unlock(new_chan); 05383 ast_channel_unlock(parent); 05384 }
static void* channel_cc_params_copy | ( | void * | data | ) | [static] |
Definition at line 9708 of file channel.c.
References ast_cc_config_params_init, and ast_cc_copy_config_params().
09709 { 09710 const struct ast_cc_config_params *src = data; 09711 struct ast_cc_config_params *dest = ast_cc_config_params_init(); 09712 if (!dest) { 09713 return NULL; 09714 } 09715 ast_cc_copy_config_params(dest, src); 09716 return dest; 09717 }
static void channel_cc_params_destroy | ( | void * | data | ) | [static] |
Definition at line 9719 of file channel.c.
References ast_cc_config_params_destroy().
09720 { 09721 struct ast_cc_config_params *cc_params = data; 09722 ast_cc_config_params_destroy(cc_params); 09723 }
static void channel_data_add_flags | ( | struct ast_data * | tree, | |
struct ast_channel * | chan | |||
) | [static] |
Definition at line 281 of file channel.c.
References ast_data_add_bool(), AST_FLAG_ANSWERED_ELSEWHERE, AST_FLAG_BLOCKING, AST_FLAG_BRIDGE_HANGUP_DONT, AST_FLAG_BRIDGE_HANGUP_RUN, AST_FLAG_DEFER_DTMF, AST_FLAG_DISABLE_DEVSTATE_CACHE, AST_FLAG_DISABLE_WORKAROUNDS, AST_FLAG_EMULATE_DTMF, AST_FLAG_END_DTMF_ONLY, AST_FLAG_EXCEPTION, AST_FLAG_IN_AUTOLOOP, AST_FLAG_IN_DTMF, AST_FLAG_MASQ_NOSTREAM, AST_FLAG_MOH, AST_FLAG_NBRIDGE, AST_FLAG_OUTGOING, AST_FLAG_SPYING, AST_FLAG_WRITE_INT, AST_FLAG_ZOMBIE, and ast_test_flag.
Referenced by ast_channel_data_add_structure().
00283 { 00284 ast_data_add_bool(tree, "DEFER_DTMF", ast_test_flag(chan, AST_FLAG_DEFER_DTMF)); 00285 ast_data_add_bool(tree, "WRITE_INT", ast_test_flag(chan, AST_FLAG_WRITE_INT)); 00286 ast_data_add_bool(tree, "BLOCKING", ast_test_flag(chan, AST_FLAG_BLOCKING)); 00287 ast_data_add_bool(tree, "ZOMBIE", ast_test_flag(chan, AST_FLAG_ZOMBIE)); 00288 ast_data_add_bool(tree, "EXCEPTION", ast_test_flag(chan, AST_FLAG_EXCEPTION)); 00289 ast_data_add_bool(tree, "MOH", ast_test_flag(chan, AST_FLAG_MOH)); 00290 ast_data_add_bool(tree, "SPYING", ast_test_flag(chan, AST_FLAG_SPYING)); 00291 ast_data_add_bool(tree, "NBRIDGE", ast_test_flag(chan, AST_FLAG_NBRIDGE)); 00292 ast_data_add_bool(tree, "IN_AUTOLOOP", ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP)); 00293 ast_data_add_bool(tree, "OUTGOING", ast_test_flag(chan, AST_FLAG_OUTGOING)); 00294 ast_data_add_bool(tree, "IN_DTMF", ast_test_flag(chan, AST_FLAG_IN_DTMF)); 00295 ast_data_add_bool(tree, "EMULATE_DTMF", ast_test_flag(chan, AST_FLAG_EMULATE_DTMF)); 00296 ast_data_add_bool(tree, "END_DTMF_ONLY", ast_test_flag(chan, AST_FLAG_END_DTMF_ONLY)); 00297 ast_data_add_bool(tree, "ANSWERED_ELSEWHERE", ast_test_flag(chan, AST_FLAG_ANSWERED_ELSEWHERE)); 00298 ast_data_add_bool(tree, "MASQ_NOSTREAM", ast_test_flag(chan, AST_FLAG_MASQ_NOSTREAM)); 00299 ast_data_add_bool(tree, "BRIDGE_HANGUP_RUN", ast_test_flag(chan, AST_FLAG_BRIDGE_HANGUP_RUN)); 00300 ast_data_add_bool(tree, "BRIDGE_HANGUP_DONT", ast_test_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT)); 00301 ast_data_add_bool(tree, "DISABLE_WORKAROUNDS", ast_test_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS)); 00302 ast_data_add_bool(tree, "DISABLE_DEVSTATE_CACHE", ast_test_flag(chan, AST_FLAG_DISABLE_DEVSTATE_CACHE)); 00303 }
static struct ast_channel_iterator* channel_iterator_search | ( | const char * | name, | |
size_t | name_len, | |||
const char * | exten, | |||
const char * | context | |||
) | [static, read] |
Definition at line 1657 of file channel.c.
References ast_channel_iterator::active_iterator, ao2_find, ast_calloc, ast_copy_string(), ast_free, ast_strlen_zero(), channels, ast_channel::context, ast_channel::exten, OBJ_MULTIPLE, OBJ_POINTER, and ast_channel::rings.
Referenced by ast_channel_iterator_by_exten_new(), and ast_channel_iterator_by_name_new().
01660 { 01661 struct ast_channel_iterator *i; 01662 struct ast_channel tmp_chan = { 01663 .name = name, 01664 /* This is sort of a hack. Basically, we're using an arbitrary field 01665 * in ast_channel to pass the name_len for a prefix match. If this 01666 * gets changed, then the compare callback must be changed, too. */ 01667 .rings = name_len, 01668 }; 01669 01670 if (!(i = ast_calloc(1, sizeof(*i)))) { 01671 return NULL; 01672 } 01673 01674 if (exten) { 01675 ast_copy_string(tmp_chan.exten, exten, sizeof(tmp_chan.exten)); 01676 } 01677 01678 if (context) { 01679 ast_copy_string(tmp_chan.context, context, sizeof(tmp_chan.context)); 01680 } 01681 01682 if (!(i->active_iterator = ao2_find(channels, &tmp_chan, 01683 OBJ_MULTIPLE | ((!ast_strlen_zero(name) && (name_len == 0)) ? OBJ_POINTER : 0)))) { 01684 ast_free(i); 01685 return NULL; 01686 } 01687 01688 return i; 01689 }
const char* channelreloadreason2txt | ( | enum channelreloadreason | reason | ) |
Convert enum channelreloadreason to text string for manager event.
\ brief Convert channel reloadreason (ENUM) to text string for manager event
Definition at line 8372 of file channel.c.
References CHANNEL_CLI_RELOAD, CHANNEL_MODULE_LOAD, and CHANNEL_MODULE_RELOAD.
Referenced by reload_config().
08373 { 08374 switch (reason) { 08375 case CHANNEL_MODULE_LOAD: 08376 return "LOAD (Channel module load)"; 08377 08378 case CHANNEL_MODULE_RELOAD: 08379 return "RELOAD (Channel module reload)"; 08380 08381 case CHANNEL_CLI_RELOAD: 08382 return "CLIRELOAD (Channel module reload by CLI command)"; 08383 08384 default: 08385 return "MANAGERRELOAD (Channel module reload by manager)"; 08386 } 08387 };
static void channels_shutdown | ( | void | ) | [static] |
Definition at line 8211 of file channel.c.
References ao2_ref, ARRAY_LEN, ast_cli_unregister_multiple(), ast_data_unregister, channels, and cli_channel.
Referenced by ast_channels_init().
08212 { 08213 ast_data_unregister(NULL); 08214 ast_cli_unregister_multiple(cli_channel, ARRAY_LEN(cli_channel)); 08215 if (channels) { 08216 ao2_ref(channels, -1); 08217 channels = NULL; 08218 } 08219 }
static void clone_variables | ( | struct ast_channel * | original, | |
struct ast_channel * | clonechan | |||
) | [static] |
Clone channel variables from 'clone' channel into 'original' channel.
All variables except those related to app_groupcount are cloned. Variables are actually _removed_ from 'clone' channel, presumably because it will subsequently be destroyed.
Definition at line 6291 of file channel.c.
References AST_LIST_APPEND_LIST, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_var_assign(), ast_var_t::name, ast_var_t::value, and ast_channel::varshead.
Referenced by ast_do_masquerade().
06292 { 06293 struct ast_var_t *current, *newvar; 06294 /* Append variables from clone channel into original channel */ 06295 /* XXX Is this always correct? We have to in order to keep MACROS working XXX */ 06296 AST_LIST_APPEND_LIST(&original->varshead, &clonechan->varshead, entries); 06297 06298 /* then, dup the varshead list into the clone */ 06299 06300 AST_LIST_TRAVERSE(&original->varshead, current, entries) { 06301 newvar = ast_var_assign(current->name, current->value); 06302 if (newvar) 06303 AST_LIST_INSERT_TAIL(&clonechan->varshead, newvar, entries); 06304 } 06305 }
static char* complete_channeltypes | ( | struct ast_cli_args * | a | ) | [static] |
Definition at line 537 of file channel.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, ast_cli_args::n, ast_cli_args::pos, chanlist::tech, ast_channel_tech::type, and ast_cli_args::word.
Referenced by handle_cli_core_show_channeltype().
00538 { 00539 struct chanlist *cl; 00540 int which = 0; 00541 int wordlen; 00542 char *ret = NULL; 00543 00544 if (a->pos != 3) 00545 return NULL; 00546 00547 wordlen = strlen(a->word); 00548 00549 AST_RWLIST_RDLOCK(&backends); 00550 AST_RWLIST_TRAVERSE(&backends, cl, list) { 00551 if (!strncasecmp(a->word, cl->tech->type, wordlen) && ++which > a->n) { 00552 ret = ast_strdup(cl->tech->type); 00553 break; 00554 } 00555 } 00556 AST_RWLIST_UNLOCK(&backends); 00557 00558 return ret; 00559 }
static int data_channels_provider_handler | ( | const struct ast_data_search * | search, | |
struct ast_data * | root | |||
) | [static] |
Definition at line 8096 of file channel.c.
References ast_channel_data_add_structure(), ast_channel_iterator_all_new(), ast_channel_iterator_destroy(), ast_channel_iterator_next(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_data_add_node(), ast_data_remove_node(), ast_data_search_match(), ast_log(), and LOG_ERROR.
08098 { 08099 struct ast_channel *c; 08100 struct ast_channel_iterator *iter = NULL; 08101 struct ast_data *data_channel; 08102 08103 for (iter = ast_channel_iterator_all_new(); 08104 iter && (c = ast_channel_iterator_next(iter)); ast_channel_unref(c)) { 08105 ast_channel_lock(c); 08106 08107 data_channel = ast_data_add_node(root, "channel"); 08108 if (!data_channel) { 08109 ast_channel_unlock(c); 08110 continue; 08111 } 08112 08113 if (ast_channel_data_add_structure(data_channel, c, 1) < 0) { 08114 ast_log(LOG_ERROR, "Unable to add channel structure for channel: %s\n", c->name); 08115 } 08116 08117 ast_channel_unlock(c); 08118 08119 if (!ast_data_search_match(search, data_channel)) { 08120 ast_data_remove_node(root, data_channel); 08121 } 08122 } 08123 if (iter) { 08124 ast_channel_iterator_destroy(iter); 08125 } 08126 08127 return 0; 08128 }
static int data_channeltypes_provider_handler | ( | const struct ast_data_search * | search, | |
struct ast_data * | data_root | |||
) | [static] |
Definition at line 8134 of file channel.c.
References ast_channel_tech::answer, ast_data_add_bool(), ast_data_add_codecs(), ast_data_add_node(), ast_data_add_str(), ast_data_remove_node(), ast_data_search_match(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_channel_tech::bridge, ast_channel_tech::bridged_channel, ast_channel_tech::call, ast_channel_tech::capabilities, ast_channel_tech::cc_callback, ast_channel_tech::description, ast_channel_tech::devicestate, ast_channel_tech::early_bridge, ast_channel_tech::exception, ast_channel_tech::fixup, ast_channel_tech::func_channel_read, ast_channel_tech::func_channel_write, ast_channel_tech::get_base_channel, ast_channel_tech::get_pvt_uniqueid, ast_channel_tech::hangup, ast_channel_tech::indicate, ast_channel_tech::queryoption, ast_channel_tech::read, ast_channel_tech::send_digit_begin, ast_channel_tech::send_digit_end, ast_channel_tech::send_html, ast_channel_tech::send_image, ast_channel_tech::send_text, ast_channel_tech::set_base_channel, ast_channel_tech::setoption, chanlist::tech, ast_channel_tech::transfer, ast_channel_tech::type, ast_channel_tech::write, ast_channel_tech::write_text, and ast_channel_tech::write_video.
08136 { 08137 struct chanlist *cl; 08138 struct ast_data *data_type; 08139 08140 AST_RWLIST_RDLOCK(&backends); 08141 AST_RWLIST_TRAVERSE(&backends, cl, list) { 08142 data_type = ast_data_add_node(data_root, "type"); 08143 if (!data_type) { 08144 continue; 08145 } 08146 ast_data_add_str(data_type, "name", cl->tech->type); 08147 ast_data_add_str(data_type, "description", cl->tech->description); 08148 ast_data_add_bool(data_type, "devicestate", cl->tech->devicestate ? 1 : 0); 08149 ast_data_add_bool(data_type, "indications", cl->tech->indicate ? 1 : 0); 08150 ast_data_add_bool(data_type, "transfer", cl->tech->transfer ? 1 : 0); 08151 ast_data_add_bool(data_type, "send_digit_begin", cl->tech->send_digit_begin ? 1 : 0); 08152 ast_data_add_bool(data_type, "send_digit_end", cl->tech->send_digit_end ? 1 : 0); 08153 ast_data_add_bool(data_type, "call", cl->tech->call ? 1 : 0); 08154 ast_data_add_bool(data_type, "hangup", cl->tech->hangup ? 1 : 0); 08155 ast_data_add_bool(data_type, "answer", cl->tech->answer ? 1 : 0); 08156 ast_data_add_bool(data_type, "read", cl->tech->read ? 1 : 0); 08157 ast_data_add_bool(data_type, "write", cl->tech->write ? 1 : 0); 08158 ast_data_add_bool(data_type, "send_text", cl->tech->send_text ? 1 : 0); 08159 ast_data_add_bool(data_type, "send_image", cl->tech->send_image ? 1 : 0); 08160 ast_data_add_bool(data_type, "send_html", cl->tech->send_html ? 1 : 0); 08161 ast_data_add_bool(data_type, "exception", cl->tech->exception ? 1 : 0); 08162 ast_data_add_bool(data_type, "bridge", cl->tech->bridge ? 1 : 0); 08163 ast_data_add_bool(data_type, "early_bridge", cl->tech->early_bridge ? 1 : 0); 08164 ast_data_add_bool(data_type, "fixup", cl->tech->fixup ? 1 : 0); 08165 ast_data_add_bool(data_type, "setoption", cl->tech->setoption ? 1 : 0); 08166 ast_data_add_bool(data_type, "queryoption", cl->tech->queryoption ? 1 : 0); 08167 ast_data_add_bool(data_type, "write_video", cl->tech->write_video ? 1 : 0); 08168 ast_data_add_bool(data_type, "write_text", cl->tech->write_text ? 1 : 0); 08169 ast_data_add_bool(data_type, "bridged_channel", cl->tech->bridged_channel ? 1 : 0); 08170 ast_data_add_bool(data_type, "func_channel_read", cl->tech->func_channel_read ? 1 : 0); 08171 ast_data_add_bool(data_type, "func_channel_write", cl->tech->func_channel_write ? 1 : 0); 08172 ast_data_add_bool(data_type, "get_base_channel", cl->tech->get_base_channel ? 1 : 0); 08173 ast_data_add_bool(data_type, "set_base_channel", cl->tech->set_base_channel ? 1 : 0); 08174 ast_data_add_bool(data_type, "get_pvt_uniqueid", cl->tech->get_pvt_uniqueid ? 1 : 0); 08175 ast_data_add_bool(data_type, "cc_callback", cl->tech->cc_callback ? 1 : 0); 08176 08177 ast_data_add_codecs(data_type, "capabilities", cl->tech->capabilities); 08178 08179 if (!ast_data_search_match(search, data_type)) { 08180 ast_data_remove_node(data_root, data_type); 08181 } 08182 } 08183 AST_RWLIST_UNLOCK(&backends); 08184 08185 return 0; 08186 }
static void deactivate_generator_nolock | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 3091 of file channel.c.
References ast_channel_set_fd(), ast_clear_flag, AST_FLAG_WRITE_INT, AST_GENERATOR_FD, ast_settimeout(), ast_channel::generator, generator, ast_channel::generatordata, and ast_generator::release.
Referenced by ast_deactivate_generator(), and deactivate_silence_generator().
03092 { 03093 if (chan->generatordata) { 03094 struct ast_generator *generator = chan->generator; 03095 03096 if (generator && generator->release) { 03097 generator->release(chan, chan->generatordata); 03098 } 03099 chan->generatordata = NULL; 03100 chan->generator = NULL; 03101 ast_channel_set_fd(chan, AST_GENERATOR_FD, -1); 03102 ast_clear_flag(chan, AST_FLAG_WRITE_INT); 03103 ast_settimeout(chan, 0, NULL, NULL); 03104 } 03105 }
static int deactivate_silence_generator | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 8332 of file channel.c.
References ast_channel_lock, ast_channel_unlock, ast_debug, deactivate_generator_nolock(), ast_channel::generator, and ast_channel::generatordata.
Referenced by ast_channel_stop_silence_generator().
08333 { 08334 ast_channel_lock(chan); 08335 08336 if (!chan->generatordata) { 08337 ast_debug(1, "Trying to stop silence generator when there is no generator on '%s'\n", 08338 chan->name); 08339 ast_channel_unlock(chan); 08340 return 0; 08341 } 08342 if (chan->generator != &silence_generator) { 08343 ast_debug(1, "Trying to stop silence generator when it is not the current generator on '%s'\n", 08344 chan->name); 08345 ast_channel_unlock(chan); 08346 return 0; 08347 } 08348 deactivate_generator_nolock(chan); 08349 08350 ast_channel_unlock(chan); 08351 08352 return 1; 08353 }
static void destroy_hooks | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 2793 of file channel.c.
References ast_audiohook_detach_list(), ast_framehook_list_destroy(), and ast_channel::audiohooks.
Referenced by ast_hangup().
02794 { 02795 if (chan->audiohooks) { 02796 ast_audiohook_detach_list(chan->audiohooks); 02797 chan->audiohooks = NULL; 02798 } 02799 02800 ast_framehook_list_destroy(chan); 02801 }
static void free_translation | ( | struct ast_channel * | clonechan | ) | [static] |
Definition at line 2757 of file channel.c.
References ast_translator_free_path(), ast_channel::nativeformats, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readtrans, and ast_channel::writetrans.
Referenced by ast_do_masquerade(), and ast_hangup().
02758 { 02759 if (clonechan->writetrans) 02760 ast_translator_free_path(clonechan->writetrans); 02761 if (clonechan->readtrans) 02762 ast_translator_free_path(clonechan->readtrans); 02763 clonechan->writetrans = NULL; 02764 clonechan->readtrans = NULL; 02765 clonechan->rawwriteformat = clonechan->nativeformats; 02766 clonechan->rawreadformat = clonechan->nativeformats; 02767 }
static int generator_force | ( | const void * | data | ) | [static] |
Definition at line 3114 of file channel.c.
References ast_channel_lock, ast_channel_unlock, ast_deactivate_generator(), ast_debug, AST_FORMAT_AUDIO_MASK, ast_format_rate(), ast_generator::generate, ast_channel::generator, ast_channel::generatordata, and ast_channel::writeformat.
Referenced by ast_activate_generator().
03115 { 03116 /* Called if generator doesn't have data */ 03117 void *tmp; 03118 int res; 03119 int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples) = NULL; 03120 struct ast_channel *chan = (struct ast_channel *)data; 03121 03122 ast_channel_lock(chan); 03123 tmp = chan->generatordata; 03124 chan->generatordata = NULL; 03125 if (chan->generator) 03126 generate = chan->generator->generate; 03127 ast_channel_unlock(chan); 03128 03129 if (!tmp || !generate) 03130 return 0; 03131 03132 res = generate(chan, tmp, 0, ast_format_rate(chan->writeformat & AST_FORMAT_AUDIO_MASK) / 50); 03133 03134 ast_channel_lock(chan); 03135 if (chan->generator && generate == chan->generator->generate) { 03136 chan->generatordata = tmp; 03137 } 03138 ast_channel_unlock(chan); 03139 03140 if (res) { 03141 ast_debug(1, "Auto-deactivating generator\n"); 03142 ast_deactivate_generator(chan); 03143 } 03144 03145 return 0; 03146 }
static void handle_cause | ( | int | cause, | |
int * | outstate | |||
) | [static] |
Definition at line 5336 of file channel.c.
References AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CONTROL_BUSY, and AST_CONTROL_CONGESTION.
Referenced by __ast_request_and_dial(), and ast_call_forward().
05337 { 05338 if (outstate) { 05339 /* compute error and return */ 05340 if (cause == AST_CAUSE_BUSY) 05341 *outstate = AST_CONTROL_BUSY; 05342 else if (cause == AST_CAUSE_CONGESTION) 05343 *outstate = AST_CONTROL_CONGESTION; 05344 else 05345 *outstate = 0; 05346 } 05347 }
static char* handle_cli_core_show_channeltype | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Show details about a channel driver - CLI command.
Definition at line 562 of file channel.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_getformatname_multiple(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_channel_tech::capabilities, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_channeltypes(), ast_channel_tech::devicestate, ast_cli_args::fd, ast_channel_tech::indicate, ast_channel_tech::send_digit_begin, ast_channel_tech::send_digit_end, ast_channel_tech::send_html, ast_channel_tech::send_image, ast_channel_tech::send_text, chanlist::tech, ast_channel_tech::transfer, ast_channel_tech::type, and ast_cli_entry::usage.
00563 { 00564 struct chanlist *cl = NULL; 00565 char buf[512]; 00566 00567 switch (cmd) { 00568 case CLI_INIT: 00569 e->command = "core show channeltype"; 00570 e->usage = 00571 "Usage: core show channeltype <name>\n" 00572 " Show details about the specified channel type, <name>.\n"; 00573 return NULL; 00574 case CLI_GENERATE: 00575 return complete_channeltypes(a); 00576 } 00577 00578 if (a->argc != 4) 00579 return CLI_SHOWUSAGE; 00580 00581 AST_RWLIST_RDLOCK(&backends); 00582 00583 AST_RWLIST_TRAVERSE(&backends, cl, list) { 00584 if (!strncasecmp(cl->tech->type, a->argv[3], strlen(cl->tech->type))) 00585 break; 00586 } 00587 00588 00589 if (!cl) { 00590 ast_cli(a->fd, "\n%s is not a registered channel driver.\n", a->argv[3]); 00591 AST_RWLIST_UNLOCK(&backends); 00592 return CLI_FAILURE; 00593 } 00594 00595 ast_cli(a->fd, 00596 "-- Info about channel driver: %s --\n" 00597 " Device State: %s\n" 00598 " Indication: %s\n" 00599 " Transfer : %s\n" 00600 " Capabilities: %s\n" 00601 " Digit Begin: %s\n" 00602 " Digit End: %s\n" 00603 " Send HTML : %s\n" 00604 " Image Support: %s\n" 00605 " Text Support: %s\n", 00606 cl->tech->type, 00607 (cl->tech->devicestate) ? "yes" : "no", 00608 (cl->tech->indicate) ? "yes" : "no", 00609 (cl->tech->transfer) ? "yes" : "no", 00610 ast_getformatname_multiple(buf, sizeof(buf), (cl->tech->capabilities) ? cl->tech->capabilities : -1), 00611 (cl->tech->send_digit_begin) ? "yes" : "no", 00612 (cl->tech->send_digit_end) ? "yes" : "no", 00613 (cl->tech->send_html) ? "yes" : "no", 00614 (cl->tech->send_image) ? "yes" : "no", 00615 (cl->tech->send_text) ? "yes" : "no" 00616 00617 ); 00618 00619 AST_RWLIST_UNLOCK(&backends); 00620 00621 return CLI_SUCCESS; 00622 }
static char* handle_cli_core_show_channeltypes | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Show channel types - CLI command.
Definition at line 496 of file channel.c.
References ast_cli_args::argc, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_channel_tech::description, ast_channel_tech::devicestate, ast_cli_args::fd, FORMAT, ast_channel_tech::indicate, chanlist::tech, ast_channel_tech::transfer, ast_channel_tech::type, and ast_cli_entry::usage.
00497 { 00498 #define FORMAT "%-10.10s %-40.40s %-12.12s %-12.12s %-12.12s\n" 00499 struct chanlist *cl; 00500 int count_chan = 0; 00501 00502 switch (cmd) { 00503 case CLI_INIT: 00504 e->command = "core show channeltypes"; 00505 e->usage = 00506 "Usage: core show channeltypes\n" 00507 " Lists available channel types registered in your\n" 00508 " Asterisk server.\n"; 00509 return NULL; 00510 case CLI_GENERATE: 00511 return NULL; 00512 } 00513 00514 if (a->argc != 3) 00515 return CLI_SHOWUSAGE; 00516 00517 ast_cli(a->fd, FORMAT, "Type", "Description", "Devicestate", "Indications", "Transfer"); 00518 ast_cli(a->fd, FORMAT, "----------", "-----------", "-----------", "-----------", "--------"); 00519 00520 AST_RWLIST_RDLOCK(&backends); 00521 AST_RWLIST_TRAVERSE(&backends, cl, list) { 00522 ast_cli(a->fd, FORMAT, cl->tech->type, cl->tech->description, 00523 (cl->tech->devicestate) ? "yes" : "no", 00524 (cl->tech->indicate) ? "yes" : "no", 00525 (cl->tech->transfer) ? "yes" : "no"); 00526 count_chan++; 00527 } 00528 AST_RWLIST_UNLOCK(&backends); 00529 00530 ast_cli(a->fd, "----------\n%d channel drivers registered.\n", count_chan); 00531 00532 return CLI_SUCCESS; 00533 00534 #undef FORMAT 00535 }
static int attribute_const is_visible_indication | ( | enum ast_control_frame_type | condition | ) | [static] |
Definition at line 4398 of file channel.c.
References _XXX_AST_CONTROL_T38, AST_CONTROL_ANSWER, AST_CONTROL_AOC, AST_CONTROL_BUSY, AST_CONTROL_CC, AST_CONTROL_CONGESTION, AST_CONTROL_CONNECTED_LINE, AST_CONTROL_END_OF_Q, AST_CONTROL_FLASH, AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, AST_CONTROL_OFFHOOK, AST_CONTROL_OPTION, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_READ_ACTION, AST_CONTROL_REDIRECTING, AST_CONTROL_RING, AST_CONTROL_RINGING, AST_CONTROL_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_T38_PARAMETERS, AST_CONTROL_TAKEOFFHOOK, AST_CONTROL_TRANSFER, AST_CONTROL_UNHOLD, AST_CONTROL_UPDATE_RTP_PEER, AST_CONTROL_VIDUPDATE, and AST_CONTROL_WINK.
Referenced by ast_indicate_data().
04399 { 04400 /* Don't include a default case here so that we get compiler warnings 04401 * when a new type is added. */ 04402 04403 switch (condition) { 04404 case AST_CONTROL_PROGRESS: 04405 case AST_CONTROL_PROCEEDING: 04406 case AST_CONTROL_VIDUPDATE: 04407 case AST_CONTROL_SRCUPDATE: 04408 case AST_CONTROL_SRCCHANGE: 04409 case AST_CONTROL_RADIO_KEY: 04410 case AST_CONTROL_RADIO_UNKEY: 04411 case AST_CONTROL_OPTION: 04412 case AST_CONTROL_WINK: 04413 case AST_CONTROL_FLASH: 04414 case AST_CONTROL_OFFHOOK: 04415 case AST_CONTROL_TAKEOFFHOOK: 04416 case AST_CONTROL_ANSWER: 04417 case AST_CONTROL_HANGUP: 04418 case AST_CONTROL_CONNECTED_LINE: 04419 case AST_CONTROL_REDIRECTING: 04420 case AST_CONTROL_TRANSFER: 04421 case AST_CONTROL_T38_PARAMETERS: 04422 case _XXX_AST_CONTROL_T38: 04423 case AST_CONTROL_CC: 04424 case AST_CONTROL_READ_ACTION: 04425 case AST_CONTROL_AOC: 04426 case AST_CONTROL_END_OF_Q: 04427 case AST_CONTROL_UPDATE_RTP_PEER: 04428 break; 04429 04430 case AST_CONTROL_INCOMPLETE: 04431 case AST_CONTROL_CONGESTION: 04432 case AST_CONTROL_BUSY: 04433 case AST_CONTROL_RINGING: 04434 case AST_CONTROL_RING: 04435 case AST_CONTROL_HOLD: 04436 /* You can hear these */ 04437 return 1; 04438 04439 case AST_CONTROL_UNHOLD: 04440 /* This is a special case. You stop hearing this. */ 04441 break; 04442 } 04443 04444 return 0; 04445 }
static struct ast_frame* kill_exception | ( | struct ast_channel * | chan | ) | [static, read] |
static int kill_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
static int kill_hangup | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 653 of file channel.c.
References ast_channel::tech_pvt.
00654 { 00655 chan->tech_pvt = NULL; 00656 return 0; 00657 }
static struct ast_frame* kill_read | ( | struct ast_channel * | chan | ) | [static, read] |
static int kill_write | ( | struct ast_channel * | chan, | |
struct ast_frame * | frame | |||
) | [static] |
static void manager_bridge_event | ( | int | onoff, | |
int | type, | |||
struct ast_channel * | c0, | |||
struct ast_channel * | c1 | |||
) | [static] |
Send manager event for bridge link and unlink events.
onoff | Link/Unlinked | |
type | 1 for core, 2 for native | |
c0 | first channel in bridge | |
c1 | second channel in bridge |
Definition at line 7421 of file channel.c.
References ast_manager_event_multichan, ast_channel::caller, EVENT_FLAG_CALL, ast_party_caller::id, ast_party_id::number, S_COR, ast_party_number::str, and ast_party_number::valid.
Referenced by ast_channel_bridge().
07422 { 07423 struct ast_channel *chans[2] = { c0, c1 }; 07424 ast_manager_event_multichan(EVENT_FLAG_CALL, "Bridge", 2, chans, 07425 "Bridgestate: %s\r\n" 07426 "Bridgetype: %s\r\n" 07427 "Channel1: %s\r\n" 07428 "Channel2: %s\r\n" 07429 "Uniqueid1: %s\r\n" 07430 "Uniqueid2: %s\r\n" 07431 "CallerID1: %s\r\n" 07432 "CallerID2: %s\r\n", 07433 onoff ? "Link" : "Unlink", 07434 type == 1 ? "core" : "native", 07435 c0->name, c1->name, 07436 c0->uniqueid, c1->uniqueid, 07437 S_COR(c0->caller.id.number.valid, c0->caller.id.number.str, ""), 07438 S_COR(c1->caller.id.number.valid, c1->caller.id.number.str, "")); 07439 }
static void masquerade_colp_transfer | ( | struct ast_channel * | transferee, | |
struct xfer_masquerade_ds * | colp | |||
) | [static] |
Definition at line 6498 of file channel.c.
References ast_alloca, ast_channel_queue_connected_line_update(), ast_connected_line_build_data(), AST_CONTROL_READ_ACTION, AST_CONTROL_UNHOLD, AST_FRAME_READ_ACTION_CONNECTED_LINE_MACRO, ast_queue_control(), ast_queue_control_data(), frame_size, ast_control_read_action_payload::payload_size, xfer_masquerade_ds::target_held, xfer_masquerade_ds::target_id, and xfer_masquerade_ds::transferee_id.
Referenced by ast_do_masquerade().
06499 { 06500 struct ast_control_read_action_payload *frame_payload; 06501 int payload_size; 06502 int frame_size; 06503 unsigned char connected_line_data[1024]; 06504 06505 /* Release any hold on the target. */ 06506 if (colp->target_held) { 06507 ast_queue_control(transferee, AST_CONTROL_UNHOLD); 06508 } 06509 06510 /* 06511 * Since transferee may not actually be bridged to another channel, 06512 * there is no way for us to queue a frame so that its connected 06513 * line status will be updated. Instead, we use the somewhat 06514 * hackish approach of using a special control frame type that 06515 * instructs ast_read() to perform a specific action. In this 06516 * case, the frame we queue tells ast_read() to call the 06517 * connected line interception macro configured for transferee. 06518 */ 06519 payload_size = ast_connected_line_build_data(connected_line_data, 06520 sizeof(connected_line_data), &colp->target_id, NULL); 06521 if (payload_size != -1) { 06522 frame_size = payload_size + sizeof(*frame_payload); 06523 frame_payload = ast_alloca(frame_size); 06524 frame_payload->action = AST_FRAME_READ_ACTION_CONNECTED_LINE_MACRO; 06525 frame_payload->payload_size = payload_size; 06526 memcpy(frame_payload->payload, connected_line_data, payload_size); 06527 ast_queue_control_data(transferee, AST_CONTROL_READ_ACTION, frame_payload, 06528 frame_size); 06529 } 06530 /* 06531 * In addition to queueing the read action frame so that the 06532 * connected line info on transferee will be updated, we also are 06533 * going to queue a plain old connected line update on transferee to 06534 * update the target. 06535 */ 06536 ast_channel_queue_connected_line_update(transferee, &colp->transferee_id, NULL); 06537 }
static const char* oldest_linkedid | ( | const char * | a, | |
const char * | b | |||
) | [static] |
Definition at line 6320 of file channel.c.
References ast_strlen_zero().
Referenced by ast_channel_set_linkgroup().
06321 { 06322 const char *satime, *saseq; 06323 const char *sbtime, *sbseq; 06324 const char *dash; 06325 06326 unsigned int atime, aseq, btime, bseq; 06327 06328 if (ast_strlen_zero(a)) 06329 return b; 06330 06331 if (ast_strlen_zero(b)) 06332 return a; 06333 06334 satime = a; 06335 sbtime = b; 06336 06337 /* jump over the system name */ 06338 if ((dash = strrchr(satime, '-'))) { 06339 satime = dash+1; 06340 } 06341 if ((dash = strrchr(sbtime, '-'))) { 06342 sbtime = dash+1; 06343 } 06344 06345 /* the sequence comes after the '.' */ 06346 saseq = strchr(satime, '.'); 06347 sbseq = strchr(sbtime, '.'); 06348 if (!saseq || !sbseq) 06349 return NULL; 06350 saseq++; 06351 sbseq++; 06352 06353 /* convert it all to integers */ 06354 atime = atoi(satime); /* note that atoi is ignoring the '.' after the time string */ 06355 btime = atoi(sbtime); /* note that atoi is ignoring the '.' after the time string */ 06356 aseq = atoi(saseq); 06357 bseq = atoi(sbseq); 06358 06359 /* and finally compare */ 06360 if (atime == btime) { 06361 return (aseq < bseq) ? a : b; 06362 } 06363 else { 06364 return (atime < btime) ? a : b; 06365 } 06366 }
static void party_connected_line_copy_transfer | ( | struct ast_party_connected_line * | dest, | |
const struct ast_party_connected_line * | src | |||
) | [static] |
Definition at line 6125 of file channel.c.
References AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, ast_party_connected_line_copy(), and ast_party_connected_line::source.
Referenced by ast_channel_transfer_masquerade().
06126 { 06127 struct ast_party_connected_line connected; 06128 06129 connected = *((struct ast_party_connected_line *) src); 06130 connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER; 06131 06132 /* Make sure empty strings will be erased. */ 06133 if (!connected.id.name.str) { 06134 connected.id.name.str = ""; 06135 } 06136 if (!connected.id.number.str) { 06137 connected.id.number.str = ""; 06138 } 06139 if (!connected.id.subaddress.str) { 06140 connected.id.subaddress.str = ""; 06141 } 06142 if (!connected.id.tag) { 06143 connected.id.tag = ""; 06144 } 06145 06146 ast_party_connected_line_copy(dest, &connected); 06147 }
static int party_id_build_data | ( | unsigned char * | data, | |
size_t | datalen, | |||
const struct ast_party_id * | id, | |||
const char * | label, | |||
const struct ast_party_id_ies * | ies, | |||
const struct ast_set_party_id * | update | |||
) | [static] |
Definition at line 8722 of file channel.c.
References ast_log(), ast_party_id_presentation(), ast_party_id_ies::combined_presentation, LOG_WARNING, ast_party_id_ies::name, ast_party_id::name, ast_set_party_id::name, ast_party_id_ies::number, ast_party_id::number, ast_set_party_id::number, party_name_build_data(), party_number_build_data(), party_subaddress_build_data(), ast_party_id_ies::subaddress, ast_party_id::subaddress, ast_set_party_id::subaddress, ast_party_id_ies::tag, and ast_party_id::tag.
Referenced by ast_connected_line_build_data(), and ast_redirecting_build_data().
08725 { 08726 size_t length; 08727 size_t pos = 0; 08728 int res; 08729 08730 /* 08731 * The size of integer values must be fixed in case the frame is 08732 * shipped to another machine. 08733 */ 08734 08735 if (!update || update->name) { 08736 res = party_name_build_data(data + pos, datalen - pos, &id->name, label, 08737 &ies->name); 08738 if (res < 0) { 08739 return -1; 08740 } 08741 pos += res; 08742 } 08743 08744 if (!update || update->number) { 08745 res = party_number_build_data(data + pos, datalen - pos, &id->number, label, 08746 &ies->number); 08747 if (res < 0) { 08748 return -1; 08749 } 08750 pos += res; 08751 } 08752 08753 if (!update || update->subaddress) { 08754 res = party_subaddress_build_data(data + pos, datalen - pos, &id->subaddress, 08755 label, &ies->subaddress); 08756 if (res < 0) { 08757 return -1; 08758 } 08759 pos += res; 08760 } 08761 08762 /* *************** Party id user tag **************************** */ 08763 if (id->tag) { 08764 length = strlen(id->tag); 08765 if (datalen < pos + (sizeof(data[0]) * 2) + length) { 08766 ast_log(LOG_WARNING, "No space left for %s tag\n", label); 08767 return -1; 08768 } 08769 data[pos++] = ies->tag; 08770 data[pos++] = length; 08771 memcpy(data + pos, id->tag, length); 08772 pos += length; 08773 } 08774 08775 /* *************** Party id combined presentation *************** */ 08776 if (!update || update->number) { 08777 int presentation; 08778 08779 if (!update || update->name) { 08780 presentation = ast_party_id_presentation(id); 08781 } else { 08782 /* 08783 * We must compromise because not all the information is available 08784 * to determine a combined presentation value. 08785 * We will only send the number presentation instead. 08786 */ 08787 presentation = id->number.presentation; 08788 } 08789 08790 if (datalen < pos + (sizeof(data[0]) * 2) + 1) { 08791 ast_log(LOG_WARNING, "No space left for %s combined presentation\n", label); 08792 return -1; 08793 } 08794 data[pos++] = ies->combined_presentation; 08795 data[pos++] = 1; 08796 data[pos++] = presentation; 08797 } 08798 08799 return pos; 08800 }
static int party_name_build_data | ( | unsigned char * | data, | |
size_t | datalen, | |||
const struct ast_party_name * | name, | |||
const char * | label, | |||
const struct ast_party_name_ies * | ies | |||
) | [static] |
Definition at line 8496 of file channel.c.
References ast_log(), ast_party_name::char_set, ast_party_name_ies::char_set, LOG_WARNING, ast_party_name::presentation, ast_party_name_ies::presentation, ast_party_name_ies::str, ast_party_name::str, ast_party_name::valid, and ast_party_name_ies::valid.
Referenced by party_id_build_data().
08497 { 08498 size_t length; 08499 size_t pos = 0; 08500 08501 /* 08502 * The size of integer values must be fixed in case the frame is 08503 * shipped to another machine. 08504 */ 08505 if (name->str) { 08506 length = strlen(name->str); 08507 if (datalen < pos + (sizeof(data[0]) * 2) + length) { 08508 ast_log(LOG_WARNING, "No space left for %s name\n", label); 08509 return -1; 08510 } 08511 data[pos++] = ies->str; 08512 data[pos++] = length; 08513 memcpy(data + pos, name->str, length); 08514 pos += length; 08515 } 08516 08517 if (datalen < pos + (sizeof(data[0]) * 2) + 1) { 08518 ast_log(LOG_WARNING, "No space left for %s name char set\n", label); 08519 return -1; 08520 } 08521 data[pos++] = ies->char_set; 08522 data[pos++] = 1; 08523 data[pos++] = name->char_set; 08524 08525 if (datalen < pos + (sizeof(data[0]) * 2) + 1) { 08526 ast_log(LOG_WARNING, "No space left for %s name presentation\n", label); 08527 return -1; 08528 } 08529 data[pos++] = ies->presentation; 08530 data[pos++] = 1; 08531 data[pos++] = name->presentation; 08532 08533 if (datalen < pos + (sizeof(data[0]) * 2) + 1) { 08534 ast_log(LOG_WARNING, "No space left for %s name valid\n", label); 08535 return -1; 08536 } 08537 data[pos++] = ies->valid; 08538 data[pos++] = 1; 08539 data[pos++] = name->valid; 08540 08541 return pos; 08542 }
static int party_number_build_data | ( | unsigned char * | data, | |
size_t | datalen, | |||
const struct ast_party_number * | number, | |||
const char * | label, | |||
const struct ast_party_number_ies * | ies | |||
) | [static] |
Definition at line 8570 of file channel.c.
References ast_log(), LOG_WARNING, ast_party_number::plan, ast_party_number_ies::plan, ast_party_number::presentation, ast_party_number_ies::presentation, ast_party_number_ies::str, ast_party_number::str, ast_party_number::valid, and ast_party_number_ies::valid.
Referenced by party_id_build_data().
08571 { 08572 size_t length; 08573 size_t pos = 0; 08574 08575 /* 08576 * The size of integer values must be fixed in case the frame is 08577 * shipped to another machine. 08578 */ 08579 if (number->str) { 08580 length = strlen(number->str); 08581 if (datalen < pos + (sizeof(data[0]) * 2) + length) { 08582 ast_log(LOG_WARNING, "No space left for %s number\n", label); 08583 return -1; 08584 } 08585 data[pos++] = ies->str; 08586 data[pos++] = length; 08587 memcpy(data + pos, number->str, length); 08588 pos += length; 08589 } 08590 08591 if (datalen < pos + (sizeof(data[0]) * 2) + 1) { 08592 ast_log(LOG_WARNING, "No space left for %s numbering plan\n", label); 08593 return -1; 08594 } 08595 data[pos++] = ies->plan; 08596 data[pos++] = 1; 08597 data[pos++] = number->plan; 08598 08599 if (datalen < pos + (sizeof(data[0]) * 2) + 1) { 08600 ast_log(LOG_WARNING, "No space left for %s number presentation\n", label); 08601 return -1; 08602 } 08603 data[pos++] = ies->presentation; 08604 data[pos++] = 1; 08605 data[pos++] = number->presentation; 08606 08607 if (datalen < pos + (sizeof(data[0]) * 2) + 1) { 08608 ast_log(LOG_WARNING, "No space left for %s number valid\n", label); 08609 return -1; 08610 } 08611 data[pos++] = ies->valid; 08612 data[pos++] = 1; 08613 data[pos++] = number->valid; 08614 08615 return pos; 08616 }
static int party_subaddress_build_data | ( | unsigned char * | data, | |
size_t | datalen, | |||
const struct ast_party_subaddress * | subaddress, | |||
const char * | label, | |||
const struct ast_party_subaddress_ies * | ies | |||
) | [static] |
Definition at line 8644 of file channel.c.
References ast_log(), LOG_WARNING, ast_party_subaddress::odd_even_indicator, ast_party_subaddress_ies::odd_even_indicator, ast_party_subaddress_ies::str, ast_party_subaddress::str, ast_party_subaddress::type, ast_party_subaddress_ies::type, ast_party_subaddress::valid, and ast_party_subaddress_ies::valid.
Referenced by party_id_build_data().
08645 { 08646 size_t length; 08647 size_t pos = 0; 08648 08649 /* 08650 * The size of integer values must be fixed in case the frame is 08651 * shipped to another machine. 08652 */ 08653 if (subaddress->str) { 08654 length = strlen(subaddress->str); 08655 if (datalen < pos + (sizeof(data[0]) * 2) + length) { 08656 ast_log(LOG_WARNING, "No space left for %s subaddress\n", label); 08657 return -1; 08658 } 08659 data[pos++] = ies->str; 08660 data[pos++] = length; 08661 memcpy(data + pos, subaddress->str, length); 08662 pos += length; 08663 } 08664 08665 if (datalen < pos + (sizeof(data[0]) * 2) + 1) { 08666 ast_log(LOG_WARNING, "No space left for %s type of subaddress\n", label); 08667 return -1; 08668 } 08669 data[pos++] = ies->type; 08670 data[pos++] = 1; 08671 data[pos++] = subaddress->type; 08672 08673 if (datalen < pos + (sizeof(data[0]) * 2) + 1) { 08674 ast_log(LOG_WARNING, 08675 "No space left for %s subaddress odd-even indicator\n", label); 08676 return -1; 08677 } 08678 data[pos++] = ies->odd_even_indicator; 08679 data[pos++] = 1; 08680 data[pos++] = subaddress->odd_even_indicator; 08681 08682 if (datalen < pos + (sizeof(data[0]) * 2) + 1) { 08683 ast_log(LOG_WARNING, "No space left for %s subaddress valid\n", label); 08684 return -1; 08685 } 08686 data[pos++] = ies->valid; 08687 data[pos++] = 1; 08688 data[pos++] = subaddress->valid; 08689 08690 return pos; 08691 }
static void plc_ds_destroy | ( | void * | data | ) | [static] |
Definition at line 4825 of file channel.c.
References ast_free, and plc_ds::samples_buf.
04826 { 04827 struct plc_ds *plc = data; 04828 ast_free(plc->samples_buf); 04829 ast_free(plc); 04830 }
static void queue_dtmf_readq | ( | struct ast_channel * | chan, | |
struct ast_frame * | f | |||
) | [inline, static] |
Definition at line 3778 of file channel.c.
References AST_FRAME_DTMF_END, ast_queue_frame(), ast_channel::dtmff, ast_frame::frametype, ast_frame_subclass::integer, ast_frame::len, and ast_frame::subclass.
Referenced by __ast_read().
03779 { 03780 struct ast_frame *fr = &chan->dtmff; 03781 03782 fr->frametype = AST_FRAME_DTMF_END; 03783 fr->subclass.integer = f->subclass.integer; 03784 fr->len = f->len; 03785 03786 /* The only time this function will be called is for a frame that just came 03787 * out of the channel driver. So, we want to stick it on the tail of the 03788 * readq. */ 03789 03790 ast_queue_frame(chan, fr); 03791 }
static void report_new_callerid | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 6468 of file channel.c.
References ast_describe_caller_presentation(), ast_manager_event, ast_party_id_presentation(), ast_channel::caller, EVENT_FLAG_CALL, ast_party_caller::id, ast_party_id::name, ast_party_id::number, S_COR, ast_party_name::str, ast_party_number::str, ast_party_name::valid, and ast_party_number::valid.
Referenced by ast_channel_set_caller_event(), ast_do_masquerade(), and ast_set_callerid().
06469 { 06470 int pres; 06471 06472 pres = ast_party_id_presentation(&chan->caller.id); 06473 ast_manager_event(chan, EVENT_FLAG_CALL, "NewCallerid", 06474 "Channel: %s\r\n" 06475 "CallerIDNum: %s\r\n" 06476 "CallerIDName: %s\r\n" 06477 "Uniqueid: %s\r\n" 06478 "CID-CallingPres: %d (%s)\r\n", 06479 chan->name, 06480 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""), 06481 S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, ""), 06482 chan->uniqueid, 06483 pres, 06484 ast_describe_caller_presentation(pres) 06485 ); 06486 }
static void send_dtmf_event | ( | struct ast_channel * | chan, | |
const char * | direction, | |||
const char | digit, | |||
const char * | begin, | |||
const char * | end | |||
) | [static] |
Definition at line 3709 of file channel.c.
References ast_manager_event, and EVENT_FLAG_DTMF.
Referenced by __ast_read(), and ast_write().
03710 { 03711 ast_manager_event(chan, EVENT_FLAG_DTMF, 03712 "DTMF", 03713 "Channel: %s\r\n" 03714 "Uniqueid: %s\r\n" 03715 "Digit: %c\r\n" 03716 "Direction: %s\r\n" 03717 "Begin: %s\r\n" 03718 "End: %s\r\n", 03719 chan->name, chan->uniqueid, digit, direction, begin, end); 03720 }
static int set_format | ( | struct ast_channel * | chan, | |
format_t | fmt, | |||
format_t * | rawformat, | |||
format_t * | format, | |||
struct ast_trans_pvt ** | trans, | |||
const int | direction | |||
) | [static] |
Definition at line 5218 of file channel.c.
References ast_best_codec(), ast_channel_lock, ast_channel_setoption(), ast_channel_unlock, ast_debug, AST_FORMAT_AUDIO_MASK, ast_getformatname(), ast_getformatname_multiple(), ast_log(), AST_OPTION_FORMAT_READ, AST_OPTION_FORMAT_WRITE, ast_translator_best_choice(), ast_translator_build_path(), ast_translator_free_path(), LOG_WARNING, and ast_channel::nativeformats.
Referenced by ast_set_read_format(), and ast_set_write_format().
05220 { 05221 format_t native, native_fmt = ast_best_codec(fmt); 05222 int res; 05223 char from[200], to[200]; 05224 05225 /* Make sure we only consider audio */ 05226 fmt &= AST_FORMAT_AUDIO_MASK; 05227 05228 native = chan->nativeformats; 05229 05230 if (!fmt || !native) /* No audio requested */ 05231 return 0; /* Let's try a call without any sounds (video, text) */ 05232 05233 /* See if the underlying channel driver is capable of performing transcoding for us */ 05234 if (!ast_channel_setoption(chan, direction ? AST_OPTION_FORMAT_WRITE : AST_OPTION_FORMAT_READ, &native_fmt, sizeof(int*), 0)) { 05235 ast_debug(1, "Channel driver natively set channel %s to %s format %s\n", chan->name, 05236 direction ? "write" : "read", ast_getformatname(native_fmt)); 05237 chan->nativeformats = *rawformat = *format = native_fmt; 05238 if (*trans) { 05239 ast_translator_free_path(*trans); 05240 } 05241 *trans = NULL; 05242 return 0; 05243 } 05244 05245 /* Find a translation path from the native format to one of the desired formats */ 05246 if (!direction) 05247 /* reading */ 05248 res = ast_translator_best_choice(&fmt, &native); 05249 else 05250 /* writing */ 05251 res = ast_translator_best_choice(&native, &fmt); 05252 05253 if (res < 0) { 05254 ast_log(LOG_WARNING, "Unable to find a codec translation path from %s to %s\n", 05255 ast_getformatname_multiple(from, sizeof(from), native), 05256 ast_getformatname_multiple(to, sizeof(to), fmt)); 05257 return -1; 05258 } 05259 05260 /* Now we have a good choice for both. */ 05261 ast_channel_lock(chan); 05262 05263 if ((*rawformat == native) && (*format == fmt) && ((*rawformat == *format) || (*trans))) { 05264 /* the channel is already in these formats, so nothing to do */ 05265 ast_channel_unlock(chan); 05266 return 0; 05267 } 05268 05269 *rawformat = native; 05270 /* User perspective is fmt */ 05271 *format = fmt; 05272 /* Free any read translation we have right now */ 05273 if (*trans) { 05274 ast_translator_free_path(*trans); 05275 *trans = NULL; 05276 } 05277 /* Build a translation path from the raw format to the desired format */ 05278 if (*format == *rawformat) { 05279 /* 05280 * If we were able to swap the native format to the format that 05281 * has been requested, then there is no need to try to build 05282 * a translation path. 05283 */ 05284 res = 0; 05285 } else { 05286 if (!direction) { 05287 /* reading */ 05288 *trans = ast_translator_build_path(*format, *rawformat); 05289 } else { 05290 /* writing */ 05291 *trans = ast_translator_build_path(*rawformat, *format); 05292 } 05293 res = *trans ? 0 : -1; 05294 } 05295 ast_channel_unlock(chan); 05296 ast_debug(1, "Set channel %s to %s format %s\n", chan->name, 05297 direction ? "write" : "read", ast_getformatname(fmt)); 05298 return res; 05299 }
static int set_security_requirements | ( | const struct ast_channel * | requestor, | |
struct ast_channel * | out | |||
) | [static] |
Definition at line 5655 of file channel.c.
References ast_channel_datastore_find(), ast_channel_lock, ast_channel_setoption(), ast_channel_unlock, AST_OPTION_SECURE_MEDIA, AST_OPTION_SECURE_SIGNALING, ast_datastore::data, ast_secure_call_store::media, secure_call_info, and ast_secure_call_store::signaling.
Referenced by ast_request().
05656 { 05657 int ops[2][2] = { 05658 {AST_OPTION_SECURE_SIGNALING, 0}, 05659 {AST_OPTION_SECURE_MEDIA, 0}, 05660 }; 05661 int i; 05662 struct ast_channel *r = (struct ast_channel *) requestor; /* UGLY */ 05663 struct ast_datastore *ds; 05664 05665 if (!requestor || !out) { 05666 return 0; 05667 } 05668 05669 ast_channel_lock(r); 05670 if ((ds = ast_channel_datastore_find(r, &secure_call_info, NULL))) { 05671 struct ast_secure_call_store *encrypt = ds->data; 05672 ops[0][1] = encrypt->signaling; 05673 ops[1][1] = encrypt->media; 05674 } else { 05675 ast_channel_unlock(r); 05676 return 0; 05677 } 05678 ast_channel_unlock(r); 05679 05680 for (i = 0; i < 2; i++) { 05681 if (ops[i][1]) { 05682 if (ast_channel_setoption(out, ops[i][0], &ops[i][1], sizeof(ops[i][1]), 0)) { 05683 /* We require a security feature, but the channel won't provide it */ 05684 return -1; 05685 } 05686 } else { 05687 /* We don't care if we can't clear the option on a channel that doesn't support it */ 05688 ast_channel_setoption(out, ops[i][0], &ops[i][1], sizeof(ops[i][1]), 0); 05689 } 05690 } 05691 05692 return 0; 05693 }
static int should_skip_dtmf | ( | struct ast_channel * | chan | ) | [inline, static] |
Determine whether or not we should ignore DTMF in the readq.
Definition at line 3796 of file channel.c.
References AST_FLAG_DEFER_DTMF, AST_FLAG_EMULATE_DTMF, AST_MIN_DTMF_GAP, ast_test_flag, ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), and ast_channel::dtmf_tv.
Referenced by __ast_read().
03797 { 03798 if (ast_test_flag(chan, AST_FLAG_DEFER_DTMF | AST_FLAG_EMULATE_DTMF)) { 03799 /* We're in the middle of emulating a digit, or DTMF has been 03800 * explicitly deferred. Skip this digit, then. */ 03801 return 1; 03802 } 03803 03804 if (!ast_tvzero(chan->dtmf_tv) && 03805 ast_tvdiff_ms(ast_tvnow(), chan->dtmf_tv) < AST_MIN_DTMF_GAP) { 03806 /* We're not in the middle of a digit, but it hasn't been long enough 03807 * since the last digit, so we'll have to skip DTMF for now. */ 03808 return 1; 03809 } 03810 03811 return 0; 03812 }
static void* silence_generator_alloc | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
static int silence_generator_generate | ( | struct ast_channel * | chan, | |
void * | data, | |||
int | len, | |||
int | samples | |||
) | [static] |
Definition at line 8280 of file channel.c.
References AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_write(), and ast_frame::frametype.
08281 { 08282 short buf[samples]; 08283 struct ast_frame frame = { 08284 .frametype = AST_FRAME_VOICE, 08285 .subclass.codec = AST_FORMAT_SLINEAR, 08286 .data.ptr = buf, 08287 .samples = samples, 08288 .datalen = sizeof(buf), 08289 }; 08290 08291 memset(buf, 0, sizeof(buf)); 08292 08293 if (ast_write(chan, &frame)) 08294 return -1; 08295 08296 return 0; 08297 }
static void silence_generator_release | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
static void* tonepair_alloc | ( | struct ast_channel * | chan, | |
void * | params | |||
) | [static] |
Definition at line 7869 of file channel.c.
References ast_calloc, AST_FLAG_WRITE_INT, AST_FORMAT_SLINEAR, ast_log(), ast_set_flag, ast_set_write_format(), cos, tonepair_def::duration, tonepair_state::duration, tonepair_state::fac1, tonepair_state::fac2, tonepair_def::freq1, tonepair_def::freq2, LOG_WARNING, M_PI, tonepair_state::modulate, tonepair_state::origwfmt, tonepair_release(), tonepair_state::v1_1, tonepair_state::v2_1, tonepair_state::v2_2, tonepair_state::v3_1, tonepair_state::v3_2, tonepair_def::vol, and ast_channel::writeformat.
07870 { 07871 struct tonepair_state *ts; 07872 struct tonepair_def *td = params; 07873 07874 if (!(ts = ast_calloc(1, sizeof(*ts)))) 07875 return NULL; 07876 ts->origwfmt = chan->writeformat; 07877 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) { 07878 ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (write)\n", chan->name); 07879 tonepair_release(NULL, ts); 07880 ts = NULL; 07881 } else { 07882 ts->fac1 = 2.0 * cos(2.0 * M_PI * (td->freq1 / 8000.0)) * 32768.0; 07883 ts->v1_1 = 0; 07884 ts->v2_1 = sin(-4.0 * M_PI * (td->freq1 / 8000.0)) * td->vol; 07885 ts->v3_1 = sin(-2.0 * M_PI * (td->freq1 / 8000.0)) * td->vol; 07886 ts->v2_1 = 0; 07887 ts->fac2 = 2.0 * cos(2.0 * M_PI * (td->freq2 / 8000.0)) * 32768.0; 07888 ts->v2_2 = sin(-4.0 * M_PI * (td->freq2 / 8000.0)) * td->vol; 07889 ts->v3_2 = sin(-2.0 * M_PI * (td->freq2 / 8000.0)) * td->vol; 07890 ts->duration = td->duration; 07891 ts->modulate = 0; 07892 } 07893 /* Let interrupts interrupt :) */ 07894 ast_set_flag(chan, AST_FLAG_WRITE_INT); 07895 return ts; 07896 }
static int tonepair_generator | ( | struct ast_channel * | chan, | |
void * | data, | |||
int | len, | |||
int | samples | |||
) | [static] |
Definition at line 7898 of file channel.c.
References AST_FORMAT_SLINEAR, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_write(), ast_frame_subclass::codec, ast_frame::data, tonepair_state::data, ast_frame::datalen, tonepair_state::duration, tonepair_state::f, tonepair_state::fac1, tonepair_state::fac2, ast_frame::frametype, LOG_WARNING, tonepair_state::modulate, ast_frame::offset, tonepair_state::pos, ast_frame::ptr, ast_frame::samples, ast_frame::subclass, tonepair_state::v1_1, tonepair_state::v1_2, tonepair_state::v2_1, tonepair_state::v2_2, tonepair_state::v3_1, and tonepair_state::v3_2.
07899 { 07900 struct tonepair_state *ts = data; 07901 int x; 07902 07903 /* we need to prepare a frame with 16 * timelen samples as we're 07904 * generating SLIN audio 07905 */ 07906 len = samples * 2; 07907 07908 if (len > sizeof(ts->data) / 2 - 1) { 07909 ast_log(LOG_WARNING, "Can't generate that much data!\n"); 07910 return -1; 07911 } 07912 memset(&ts->f, 0, sizeof(ts->f)); 07913 for (x=0;x<len/2;x++) { 07914 ts->v1_1 = ts->v2_1; 07915 ts->v2_1 = ts->v3_1; 07916 ts->v3_1 = (ts->fac1 * ts->v2_1 >> 15) - ts->v1_1; 07917 07918 ts->v1_2 = ts->v2_2; 07919 ts->v2_2 = ts->v3_2; 07920 ts->v3_2 = (ts->fac2 * ts->v2_2 >> 15) - ts->v1_2; 07921 if (ts->modulate) { 07922 int p; 07923 p = ts->v3_2 - 32768; 07924 if (p < 0) p = -p; 07925 p = ((p * 9) / 10) + 1; 07926 ts->data[x] = (ts->v3_1 * p) >> 15; 07927 } else 07928 ts->data[x] = ts->v3_1 + ts->v3_2; 07929 } 07930 ts->f.frametype = AST_FRAME_VOICE; 07931 ts->f.subclass.codec = AST_FORMAT_SLINEAR; 07932 ts->f.datalen = len; 07933 ts->f.samples = samples; 07934 ts->f.offset = AST_FRIENDLY_OFFSET; 07935 ts->f.data.ptr = ts->data; 07936 ast_write(chan, &ts->f); 07937 ts->pos += x; 07938 if (ts->duration > 0) { 07939 if (ts->pos >= ts->duration * 8) 07940 return -1; 07941 } 07942 return 0; 07943 }
static void tonepair_release | ( | struct ast_channel * | chan, | |
void * | params | |||
) | [static] |
Definition at line 7860 of file channel.c.
References ast_free, ast_set_write_format(), and tonepair_state::origwfmt.
Referenced by tonepair_alloc().
07861 { 07862 struct tonepair_state *ts = params; 07863 07864 if (chan) 07865 ast_set_write_format(chan, ts->origwfmt); 07866 ast_free(ts); 07867 }
static void update_bridge_vars | ( | struct ast_channel * | c0, | |
struct ast_channel * | c1 | |||
) | [static] |
Definition at line 7441 of file channel.c.
References ast_channel_lock, ast_channel_unlock, ast_strdupa, ast_strlen_zero(), ast_channel_tech::get_pvt_uniqueid, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), and ast_channel::tech.
Referenced by ast_channel_bridge().
07442 { 07443 const char *c0_name; 07444 const char *c1_name; 07445 const char *c0_pvtid = NULL; 07446 const char *c1_pvtid = NULL; 07447 07448 ast_channel_lock(c1); 07449 c1_name = ast_strdupa(c1->name); 07450 if (c1->tech->get_pvt_uniqueid) { 07451 c1_pvtid = ast_strdupa(c1->tech->get_pvt_uniqueid(c1)); 07452 } 07453 ast_channel_unlock(c1); 07454 07455 ast_channel_lock(c0); 07456 if (!ast_strlen_zero(pbx_builtin_getvar_helper(c0, "BRIDGEPEER"))) { 07457 pbx_builtin_setvar_helper(c0, "BRIDGEPEER", c1_name); 07458 } 07459 if (c1_pvtid) { 07460 pbx_builtin_setvar_helper(c0, "BRIDGEPVTCALLID", c1_pvtid); 07461 } 07462 c0_name = ast_strdupa(c0->name); 07463 if (c0->tech->get_pvt_uniqueid) { 07464 c0_pvtid = ast_strdupa(c0->tech->get_pvt_uniqueid(c0)); 07465 } 07466 ast_channel_unlock(c0); 07467 07468 ast_channel_lock(c1); 07469 if (!ast_strlen_zero(pbx_builtin_getvar_helper(c1, "BRIDGEPEER"))) { 07470 pbx_builtin_setvar_helper(c1, "BRIDGEPEER", c0_name); 07471 } 07472 if (c0_pvtid) { 07473 pbx_builtin_setvar_helper(c1, "BRIDGEPVTCALLID", c0_pvtid); 07474 } 07475 ast_channel_unlock(c1); 07476 }
static void xfer_ds_destroy | ( | void * | data | ) | [static] |
Definition at line 6170 of file channel.c.
References ast_free, ast_party_connected_line_free(), xfer_masquerade_ds::target_id, and xfer_masquerade_ds::transferee_id.
06171 { 06172 struct xfer_masquerade_ds *ds = data; 06173 06174 ast_party_connected_line_free(&ds->target_id); 06175 ast_party_connected_line_free(&ds->transferee_id); 06176 ast_free(ds); 06177 }
struct ast_channel_tech ast_kill_tech |
Kill the channel channel driver technology descriptor.
The purpose of this channel technology is to encourage the channel to hangup as quickly as possible.
Definition at line 668 of file channel.c.
Referenced by ast_do_masquerade().
void(* ast_moh_cleanup_ptr)(struct ast_channel *) = NULL [static] |
Referenced by ast_install_music_functions(), ast_moh_cleanup(), and ast_uninstall_music_functions().
int(* ast_moh_start_ptr)(struct ast_channel *, const char *, const char *) = NULL [static] |
Referenced by ast_install_music_functions(), ast_moh_start(), and ast_uninstall_music_functions().
void(* ast_moh_stop_ptr)(struct ast_channel *) = NULL [static] |
Referenced by ast_install_music_functions(), ast_moh_stop(), and ast_uninstall_music_functions().
struct causes_map causes[] [static] |
Definition at line 209 of file channel.c.
Referenced by ast_cause2str(), ast_str2cause(), and dump_cause().
struct ast_datastore_info cc_channel_datastore_info [static] |
{ .type = "Call Completion", .duplicate = channel_cc_params_copy, .destroy = channel_cc_params_destroy, }
int chancount [static] |
Definition at line 102 of file channel.c.
Referenced by generic_fax_exec().
struct ast_data_entry channel_providers[] [static] |
{ AST_DATA_ENTRY("/asterisk/core/channels", &channels_provider), AST_DATA_ENTRY("/asterisk/core/channeltypes", &channeltypes_provider), }
struct ao2_container* channels [static] |
All active channels on the system.
Definition at line 197 of file channel.c.
Referenced by __ast_channel_alloc_ap(), ast_active_channels(), ast_begin_shutdown(), ast_change_name(), ast_channel_callback(), ast_channel_get_full(), ast_channel_iterator_all_new(), ast_channel_release(), ast_channels_init(), ast_do_masquerade(), ast_hangup(), channel_iterator_search(), and channels_shutdown().
struct ast_data_handler channels_provider [static] |
{ .version = AST_DATA_HANDLER_VERSION, .get = data_channels_provider_handler }
struct ast_data_handler channeltypes_provider [static] |
{ .version = AST_DATA_HANDLER_VERSION, .get = data_channeltypes_provider_handler }
struct ast_cli_entry cli_channel[] [static] |
{ AST_CLI_DEFINE(handle_cli_core_show_channeltypes, "List available channel types"), AST_CLI_DEFINE(handle_cli_core_show_channeltype, "Give more details on that channel type") }
Definition at line 624 of file channel.c.
Referenced by ast_channels_init(), and channels_shutdown().
unsigned long global_fin |
The current value of the debug flags is stored in the two variables global_fin and global_fout (declared in main/channel.c)
Definition at line 104 of file channel.c.
Referenced by handle_core_set_debug_channel().
unsigned long global_fout |
Definition at line 104 of file channel.c.
Referenced by handle_core_set_debug_channel().
struct ast_channel_tech null_tech [static] |
{ .type = "NULL", .description = "Null channel (should not see this)", }
Definition at line 1120 of file channel.c.
Referenced by __ast_channel_alloc_ap().
struct ast_datastore_info plc_ds_info [static] |
{ .type = "plc", .destroy = plc_ds_destroy, }
int shutting_down [static] |
struct ast_generator silence_generator [static] |
{ .alloc = silence_generator_alloc, .release = silence_generator_release, .generate = silence_generator_generate, }
struct ast_threadstorage state2str_threadbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_state2str_threadbuf , .custom_init = NULL , } [static] |
Definition at line 106 of file channel.c.
Referenced by ast_state2str().
struct ast_generator tonepair [static] |
{ .alloc = tonepair_alloc, .release = tonepair_release, .generate = tonepair_generator, }
struct ast_datastore_info xfer_ds_info [static] |
{ .type = "xfer_colp", .destroy = xfer_ds_destroy, }