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_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 | 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 | internal_deactivate_generator (struct ast_channel *chan, void *generator) |
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 8732 of file channel.c.
08732 { 08733 AST_CONNECTED_LINE_NUMBER, 08734 AST_CONNECTED_LINE_NAME, 08735 AST_CONNECTED_LINE_NUMBER_PLAN, 08736 AST_CONNECTED_LINE_ID_PRESENTATION,/* Combined number and name presentation. */ 08737 AST_CONNECTED_LINE_SOURCE, 08738 AST_CONNECTED_LINE_SUBADDRESS, 08739 AST_CONNECTED_LINE_SUBADDRESS_TYPE, 08740 AST_CONNECTED_LINE_SUBADDRESS_ODD_EVEN, 08741 AST_CONNECTED_LINE_SUBADDRESS_VALID, 08742 AST_CONNECTED_LINE_TAG, 08743 AST_CONNECTED_LINE_VERSION, 08744 AST_CONNECTED_LINE_NAME_VALID, 08745 AST_CONNECTED_LINE_NAME_CHAR_SET, 08746 AST_CONNECTED_LINE_NAME_PRESENTATION, 08747 AST_CONNECTED_LINE_NUMBER_VALID, 08748 AST_CONNECTED_LINE_NUMBER_PRESENTATION, 08749 };
anonymous enum |
Element identifiers for redirecting indication frame data.
Definition at line 9053 of file channel.c.
09053 { 09054 AST_REDIRECTING_FROM_NUMBER, 09055 AST_REDIRECTING_FROM_NAME, 09056 AST_REDIRECTING_FROM_NUMBER_PLAN, 09057 AST_REDIRECTING_FROM_ID_PRESENTATION, 09058 AST_REDIRECTING_TO_NUMBER, 09059 AST_REDIRECTING_TO_NAME, 09060 AST_REDIRECTING_TO_NUMBER_PLAN, 09061 AST_REDIRECTING_TO_ID_PRESENTATION, 09062 AST_REDIRECTING_REASON, 09063 AST_REDIRECTING_COUNT, 09064 AST_REDIRECTING_FROM_SUBADDRESS, 09065 AST_REDIRECTING_FROM_SUBADDRESS_TYPE, 09066 AST_REDIRECTING_FROM_SUBADDRESS_ODD_EVEN, 09067 AST_REDIRECTING_FROM_SUBADDRESS_VALID, 09068 AST_REDIRECTING_TO_SUBADDRESS, 09069 AST_REDIRECTING_TO_SUBADDRESS_TYPE, 09070 AST_REDIRECTING_TO_SUBADDRESS_ODD_EVEN, 09071 AST_REDIRECTING_TO_SUBADDRESS_VALID, 09072 AST_REDIRECTING_FROM_TAG, 09073 AST_REDIRECTING_TO_TAG, 09074 AST_REDIRECTING_VERSION, 09075 AST_REDIRECTING_FROM_NAME_VALID, 09076 AST_REDIRECTING_FROM_NAME_CHAR_SET, 09077 AST_REDIRECTING_FROM_NAME_PRESENTATION, 09078 AST_REDIRECTING_FROM_NUMBER_VALID, 09079 AST_REDIRECTING_FROM_NUMBER_PRESENTATION, 09080 AST_REDIRECTING_TO_NAME_VALID, 09081 AST_REDIRECTING_TO_NAME_CHAR_SET, 09082 AST_REDIRECTING_TO_NAME_PRESENTATION, 09083 AST_REDIRECTING_TO_NUMBER_VALID, 09084 AST_REDIRECTING_TO_NUMBER_PRESENTATION, 09085 };
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 %d 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 6180 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().
06181 { 06182 ast_manager_event(chan, EVENT_FLAG_CALL, "Rename", "Channel: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", chan->name, newname, chan->uniqueid); 06183 ast_string_field_set(chan, name, newname); 06184 }
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 5944 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().
05945 { 05946 int res = -1; 05947 struct ast_channel *final_orig, *final_clone, *base; 05948 05949 for (;;) { 05950 final_orig = original; 05951 final_clone = clonechan; 05952 05953 ast_channel_lock_both(original, clonechan); 05954 05955 if (ast_test_flag(original, AST_FLAG_ZOMBIE) 05956 || ast_test_flag(clonechan, AST_FLAG_ZOMBIE)) { 05957 /* Zombies! Run! */ 05958 ast_log(LOG_WARNING, 05959 "Can't setup masquerade. One or both channels is dead. (%s <-- %s)\n", 05960 original->name, clonechan->name); 05961 ast_channel_unlock(clonechan); 05962 ast_channel_unlock(original); 05963 return -1; 05964 } 05965 05966 /* 05967 * Each of these channels may be sitting behind a channel proxy 05968 * (i.e. chan_agent) and if so, we don't really want to 05969 * masquerade it, but its proxy 05970 */ 05971 if (original->_bridge 05972 && (original->_bridge != ast_bridged_channel(original)) 05973 && (original->_bridge->_bridge != original)) { 05974 final_orig = original->_bridge; 05975 } 05976 if (clonechan->_bridge 05977 && (clonechan->_bridge != ast_bridged_channel(clonechan)) 05978 && (clonechan->_bridge->_bridge != clonechan)) { 05979 final_clone = clonechan->_bridge; 05980 } 05981 if (final_clone->tech->get_base_channel 05982 && (base = final_clone->tech->get_base_channel(final_clone))) { 05983 final_clone = base; 05984 } 05985 05986 if ((final_orig != original) || (final_clone != clonechan)) { 05987 /* 05988 * Lots and lots of deadlock avoidance. The main one we're 05989 * competing with is ast_write(), which locks channels 05990 * recursively, when working with a proxy channel. 05991 */ 05992 if (ast_channel_trylock(final_orig)) { 05993 ast_channel_unlock(clonechan); 05994 ast_channel_unlock(original); 05995 05996 /* Try again */ 05997 continue; 05998 } 05999 if (ast_channel_trylock(final_clone)) { 06000 ast_channel_unlock(final_orig); 06001 ast_channel_unlock(clonechan); 06002 ast_channel_unlock(original); 06003 06004 /* Try again */ 06005 continue; 06006 } 06007 ast_channel_unlock(clonechan); 06008 ast_channel_unlock(original); 06009 original = final_orig; 06010 clonechan = final_clone; 06011 06012 if (ast_test_flag(original, AST_FLAG_ZOMBIE) 06013 || ast_test_flag(clonechan, AST_FLAG_ZOMBIE)) { 06014 /* Zombies! Run! */ 06015 ast_log(LOG_WARNING, 06016 "Can't setup masquerade. One or both channels is dead. (%s <-- %s)\n", 06017 original->name, clonechan->name); 06018 ast_channel_unlock(clonechan); 06019 ast_channel_unlock(original); 06020 return -1; 06021 } 06022 } 06023 break; 06024 } 06025 06026 if (original == clonechan) { 06027 ast_log(LOG_WARNING, "Can't masquerade channel '%s' into itself!\n", original->name); 06028 ast_channel_unlock(clonechan); 06029 ast_channel_unlock(original); 06030 return -1; 06031 } 06032 06033 ast_debug(1, "Planning to masquerade channel %s into the structure of %s\n", 06034 clonechan->name, original->name); 06035 06036 if (!original->masqr && !original->masq && !clonechan->masq && !clonechan->masqr) { 06037 original->masq = clonechan; 06038 clonechan->masqr = original; 06039 if (xfer_ds) { 06040 ast_channel_datastore_add(original, xfer_ds); 06041 } 06042 ast_queue_frame(original, &ast_null_frame); 06043 ast_queue_frame(clonechan, &ast_null_frame); 06044 ast_debug(1, "Done planning to masquerade channel %s into the structure of %s\n", clonechan->name, original->name); 06045 res = 0; 06046 } else if (original->masq) { 06047 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 06048 original->masq->name, original->name); 06049 } else if (original->masqr) { 06050 /* not yet as a previously planned masq hasn't yet happened */ 06051 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 06052 original->name, original->masqr->name); 06053 } else if (clonechan->masq) { 06054 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 06055 clonechan->masq->name, clonechan->name); 06056 } else { /* (clonechan->masqr) */ 06057 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n", 06058 clonechan->name, clonechan->masqr->name); 06059 } 06060 06061 ast_channel_unlock(clonechan); 06062 ast_channel_unlock(original); 06063 06064 return res; 06065 }
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 = %d): %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 3801 of file channel.c.
References __ast_queue_frame(), ast_channel::_softhangup, ast_channel::_state, ast_control_read_action_payload::action, ast_channel::alertpipe, 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_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().
03802 { 03803 struct ast_frame *f = NULL; /* the return value */ 03804 int blah; 03805 int prestate; 03806 int cause = 0; 03807 03808 /* this function is very long so make sure there is only one return 03809 * point at the end (there are only two exceptions to this). 03810 */ 03811 03812 if (chan->masq) { 03813 ast_do_masquerade(chan); 03814 return &ast_null_frame; 03815 } 03816 03817 /* if here, no masq has happened, lock the channel and proceed */ 03818 ast_channel_lock(chan); 03819 03820 /* Stop if we're a zombie or need a soft hangup */ 03821 if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) { 03822 if (chan->generator) 03823 ast_deactivate_generator(chan); 03824 03825 /* 03826 * It is possible for chan->_softhangup to be set and there 03827 * still be control frames that need to be read. Instead of 03828 * just going to 'done' in the case of ast_check_hangup(), we 03829 * need to queue the end-of-Q frame so that it can mark the end 03830 * of the read queue. If there are frames to be read, 03831 * ast_queue_control() will be called repeatedly, but will only 03832 * queue the first end-of-Q frame. 03833 */ 03834 if (chan->_softhangup) { 03835 ast_queue_control(chan, AST_CONTROL_END_OF_Q); 03836 } else { 03837 goto done; 03838 } 03839 } else { 03840 #ifdef AST_DEVMODE 03841 /* 03842 * The ast_waitfor() code records which of the channel's file 03843 * descriptors reported that data is available. In theory, 03844 * ast_read() should only be called after ast_waitfor() reports 03845 * that a channel has data available for reading. However, 03846 * there still may be some edge cases throughout the code where 03847 * ast_read() is called improperly. This can potentially cause 03848 * problems, so if this is a developer build, make a lot of 03849 * noise if this happens so that it can be addressed. 03850 * 03851 * One of the potential problems is blocking on a dead channel. 03852 */ 03853 if (chan->fdno == -1) { 03854 ast_log(LOG_ERROR, 03855 "ast_read() on chan '%s' called with no recorded file descriptor.\n", 03856 chan->name); 03857 } 03858 #endif 03859 } 03860 03861 prestate = chan->_state; 03862 if (chan->timingfd > -1 && chan->fdno == AST_TIMING_FD) { 03863 enum ast_timer_event res; 03864 03865 ast_clear_flag(chan, AST_FLAG_EXCEPTION); 03866 03867 res = ast_timer_get_event(chan->timer); 03868 03869 switch (res) { 03870 case AST_TIMING_EVENT_EXPIRED: 03871 if (ast_timer_ack(chan->timer, 1) < 0) { 03872 ast_log(LOG_ERROR, "Failed to acknoweldge timer in ast_read\n"); 03873 goto done; 03874 } 03875 03876 if (chan->timingfunc) { 03877 /* save a copy of func/data before unlocking the channel */ 03878 int (*func)(const void *) = chan->timingfunc; 03879 void *data = chan->timingdata; 03880 chan->fdno = -1; 03881 ast_channel_unlock(chan); 03882 func(data); 03883 } else { 03884 ast_timer_set_rate(chan->timer, 0); 03885 chan->fdno = -1; 03886 ast_channel_unlock(chan); 03887 } 03888 03889 /* cannot 'goto done' because the channel is already unlocked */ 03890 return &ast_null_frame; 03891 03892 case AST_TIMING_EVENT_CONTINUOUS: 03893 if (AST_LIST_EMPTY(&chan->readq) || 03894 !AST_LIST_NEXT(AST_LIST_FIRST(&chan->readq), frame_list)) { 03895 ast_timer_disable_continuous(chan->timer); 03896 } 03897 break; 03898 } 03899 03900 } else if (chan->fds[AST_GENERATOR_FD] > -1 && chan->fdno == AST_GENERATOR_FD) { 03901 /* if the AST_GENERATOR_FD is set, call the generator with args 03902 * set to -1 so it can do whatever it needs to. 03903 */ 03904 void *tmp = chan->generatordata; 03905 chan->generatordata = NULL; /* reset to let ast_write get through */ 03906 chan->generator->generate(chan, tmp, -1, -1); 03907 chan->generatordata = tmp; 03908 f = &ast_null_frame; 03909 chan->fdno = -1; 03910 goto done; 03911 } 03912 03913 /* Read and ignore anything on the alertpipe, but read only 03914 one sizeof(blah) per frame that we send from it */ 03915 if (chan->alertpipe[0] > -1) { 03916 int flags = fcntl(chan->alertpipe[0], F_GETFL); 03917 /* For some odd reason, the alertpipe occasionally loses nonblocking status, 03918 * which immediately causes a deadlock scenario. Detect and prevent this. */ 03919 if ((flags & O_NONBLOCK) == 0) { 03920 ast_log(LOG_ERROR, "Alertpipe on channel %s lost O_NONBLOCK?!!\n", chan->name); 03921 if (fcntl(chan->alertpipe[0], F_SETFL, flags | O_NONBLOCK) < 0) { 03922 ast_log(LOG_WARNING, "Unable to set alertpipe nonblocking! (%d: %s)\n", errno, strerror(errno)); 03923 f = &ast_null_frame; 03924 goto done; 03925 } 03926 } 03927 if (read(chan->alertpipe[0], &blah, sizeof(blah)) < 0) { 03928 if (errno != EINTR && errno != EAGAIN) 03929 ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno)); 03930 } 03931 } 03932 03933 03934 /* Check for pending read queue */ 03935 if (!AST_LIST_EMPTY(&chan->readq)) { 03936 int skip_dtmf = should_skip_dtmf(chan); 03937 03938 AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->readq, f, frame_list) { 03939 /* We have to be picky about which frame we pull off of the readq because 03940 * there are cases where we want to leave DTMF frames on the queue until 03941 * some later time. */ 03942 03943 if ( (f->frametype == AST_FRAME_DTMF_BEGIN || f->frametype == AST_FRAME_DTMF_END) && skip_dtmf) { 03944 continue; 03945 } 03946 03947 AST_LIST_REMOVE_CURRENT(frame_list); 03948 break; 03949 } 03950 AST_LIST_TRAVERSE_SAFE_END; 03951 03952 if (!f) { 03953 /* There were no acceptable frames on the readq. */ 03954 f = &ast_null_frame; 03955 if (chan->alertpipe[0] > -1) { 03956 int poke = 0; 03957 /* Restore the state of the alertpipe since we aren't ready for any 03958 * of the frames in the readq. */ 03959 if (write(chan->alertpipe[1], &poke, sizeof(poke)) != sizeof(poke)) { 03960 ast_log(LOG_ERROR, "Failed to write to alertpipe: %s\n", strerror(errno)); 03961 } 03962 } 03963 } 03964 03965 /* Interpret hangup and end-of-Q frames to return NULL */ 03966 /* XXX why not the same for frames from the channel ? */ 03967 if (f->frametype == AST_FRAME_CONTROL) { 03968 switch (f->subclass.integer) { 03969 case AST_CONTROL_HANGUP: 03970 chan->_softhangup |= AST_SOFTHANGUP_DEV; 03971 cause = f->data.uint32; 03972 /* Fall through */ 03973 case AST_CONTROL_END_OF_Q: 03974 ast_frfree(f); 03975 f = NULL; 03976 break; 03977 default: 03978 break; 03979 } 03980 } 03981 } else { 03982 chan->blocker = pthread_self(); 03983 if (ast_test_flag(chan, AST_FLAG_EXCEPTION)) { 03984 if (chan->tech->exception) 03985 f = chan->tech->exception(chan); 03986 else { 03987 ast_log(LOG_WARNING, "Exception flag set on '%s', but no exception handler\n", chan->name); 03988 f = &ast_null_frame; 03989 } 03990 /* Clear the exception flag */ 03991 ast_clear_flag(chan, AST_FLAG_EXCEPTION); 03992 } else if (chan->tech && chan->tech->read) 03993 f = chan->tech->read(chan); 03994 else 03995 ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name); 03996 } 03997 03998 /* 03999 * Reset the recorded file descriptor that triggered this read so that we can 04000 * easily detect when ast_read() is called without properly using ast_waitfor(). 04001 */ 04002 chan->fdno = -1; 04003 04004 /* Perform the framehook read event here. After the frame enters the framehook list 04005 * there is no telling what will happen, <insert mad scientist laugh here>!!! */ 04006 f = ast_framehook_list_read_event(chan->framehooks, f); 04007 04008 if (f) { 04009 struct ast_frame *readq_tail = AST_LIST_LAST(&chan->readq); 04010 struct ast_control_read_action_payload *read_action_payload; 04011 struct ast_party_connected_line connected; 04012 04013 /* if the channel driver returned more than one frame, stuff the excess 04014 into the readq for the next ast_read call 04015 */ 04016 if (AST_LIST_NEXT(f, frame_list)) { 04017 ast_queue_frame(chan, AST_LIST_NEXT(f, frame_list)); 04018 ast_frfree(AST_LIST_NEXT(f, frame_list)); 04019 AST_LIST_NEXT(f, frame_list) = NULL; 04020 } 04021 04022 switch (f->frametype) { 04023 case AST_FRAME_CONTROL: 04024 if (f->subclass.integer == AST_CONTROL_ANSWER) { 04025 if (!ast_test_flag(chan, AST_FLAG_OUTGOING)) { 04026 ast_debug(1, "Ignoring answer on an inbound call!\n"); 04027 ast_frfree(f); 04028 f = &ast_null_frame; 04029 } else if (prestate == AST_STATE_UP && ast_bridged_channel(chan)) { 04030 ast_debug(1, "Dropping duplicate answer!\n"); 04031 ast_frfree(f); 04032 f = &ast_null_frame; 04033 } else { 04034 /* Answer the CDR */ 04035 ast_setstate(chan, AST_STATE_UP); 04036 /* removed a call to ast_cdr_answer(chan->cdr) from here. */ 04037 ast_cel_report_event(chan, AST_CEL_ANSWER, NULL, NULL, NULL); 04038 } 04039 } else if (f->subclass.integer == AST_CONTROL_READ_ACTION) { 04040 read_action_payload = f->data.ptr; 04041 switch (read_action_payload->action) { 04042 case AST_FRAME_READ_ACTION_CONNECTED_LINE_MACRO: 04043 ast_party_connected_line_init(&connected); 04044 ast_party_connected_line_copy(&connected, &chan->connected); 04045 if (ast_connected_line_parse_data(read_action_payload->payload, 04046 read_action_payload->payload_size, &connected)) { 04047 ast_party_connected_line_free(&connected); 04048 break; 04049 } 04050 ast_channel_unlock(chan); 04051 if (ast_channel_connected_line_macro(NULL, chan, &connected, 1, 0)) { 04052 ast_indicate_data(chan, AST_CONTROL_CONNECTED_LINE, 04053 read_action_payload->payload, 04054 read_action_payload->payload_size); 04055 } 04056 ast_party_connected_line_free(&connected); 04057 ast_channel_lock(chan); 04058 break; 04059 } 04060 ast_frfree(f); 04061 f = &ast_null_frame; 04062 } 04063 break; 04064 case AST_FRAME_DTMF_END: 04065 send_dtmf_event(chan, "Received", f->subclass.integer, "No", "Yes"); 04066 ast_log(LOG_DTMF, "DTMF end '%c' received on %s, duration %ld ms\n", f->subclass.integer, chan->name, f->len); 04067 /* Queue it up if DTMF is deferred, or if DTMF emulation is forced. */ 04068 if (ast_test_flag(chan, AST_FLAG_DEFER_DTMF) || ast_test_flag(chan, AST_FLAG_EMULATE_DTMF)) { 04069 queue_dtmf_readq(chan, f); 04070 ast_frfree(f); 04071 f = &ast_null_frame; 04072 } else if (!ast_test_flag(chan, AST_FLAG_IN_DTMF | AST_FLAG_END_DTMF_ONLY)) { 04073 if (!ast_tvzero(chan->dtmf_tv) && 04074 ast_tvdiff_ms(ast_tvnow(), chan->dtmf_tv) < AST_MIN_DTMF_GAP) { 04075 /* If it hasn't been long enough, defer this digit */ 04076 queue_dtmf_readq(chan, f); 04077 ast_frfree(f); 04078 f = &ast_null_frame; 04079 } else { 04080 /* There was no begin, turn this into a begin and send the end later */ 04081 f->frametype = AST_FRAME_DTMF_BEGIN; 04082 ast_set_flag(chan, AST_FLAG_EMULATE_DTMF); 04083 chan->emulate_dtmf_digit = f->subclass.integer; 04084 chan->dtmf_tv = ast_tvnow(); 04085 if (f->len) { 04086 if (f->len > AST_MIN_DTMF_DURATION) 04087 chan->emulate_dtmf_duration = f->len; 04088 else 04089 chan->emulate_dtmf_duration = AST_MIN_DTMF_DURATION; 04090 } else 04091 chan->emulate_dtmf_duration = AST_DEFAULT_EMULATE_DTMF_DURATION; 04092 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); 04093 } 04094 if (chan->audiohooks) { 04095 struct ast_frame *old_frame = f; 04096 /*! 04097 * \todo XXX It is possible to write a digit to the audiohook twice 04098 * if the digit was originally read while the channel was in autoservice. */ 04099 f = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_READ, f); 04100 if (old_frame != f) 04101 ast_frfree(old_frame); 04102 } 04103 } else { 04104 struct timeval now = ast_tvnow(); 04105 if (ast_test_flag(chan, AST_FLAG_IN_DTMF)) { 04106 ast_log(LOG_DTMF, "DTMF end accepted with begin '%c' on %s\n", f->subclass.integer, chan->name); 04107 ast_clear_flag(chan, AST_FLAG_IN_DTMF); 04108 if (!f->len) 04109 f->len = ast_tvdiff_ms(now, chan->dtmf_tv); 04110 04111 /* detect tones that were received on 04112 * the wire with durations shorter than 04113 * AST_MIN_DTMF_DURATION and set f->len 04114 * to the actual duration of the DTMF 04115 * frames on the wire. This will cause 04116 * dtmf emulation to be triggered later 04117 * on. 04118 */ 04119 if (ast_tvdiff_ms(now, chan->dtmf_tv) < AST_MIN_DTMF_DURATION) { 04120 f->len = ast_tvdiff_ms(now, chan->dtmf_tv); 04121 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); 04122 } 04123 } else if (!f->len) { 04124 ast_log(LOG_DTMF, "DTMF end accepted without begin '%c' on %s\n", f->subclass.integer, chan->name); 04125 f->len = AST_MIN_DTMF_DURATION; 04126 } 04127 if (f->len < AST_MIN_DTMF_DURATION && !ast_test_flag(chan, AST_FLAG_END_DTMF_ONLY)) { 04128 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); 04129 ast_set_flag(chan, AST_FLAG_EMULATE_DTMF); 04130 chan->emulate_dtmf_digit = f->subclass.integer; 04131 chan->emulate_dtmf_duration = AST_MIN_DTMF_DURATION - f->len; 04132 ast_frfree(f); 04133 f = &ast_null_frame; 04134 } else { 04135 ast_log(LOG_DTMF, "DTMF end passthrough '%c' on %s\n", f->subclass.integer, chan->name); 04136 if (f->len < AST_MIN_DTMF_DURATION) { 04137 f->len = AST_MIN_DTMF_DURATION; 04138 } 04139 chan->dtmf_tv = now; 04140 } 04141 if (chan->audiohooks) { 04142 struct ast_frame *old_frame = f; 04143 f = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_READ, f); 04144 if (old_frame != f) 04145 ast_frfree(old_frame); 04146 } 04147 } 04148 break; 04149 case AST_FRAME_DTMF_BEGIN: 04150 send_dtmf_event(chan, "Received", f->subclass.integer, "Yes", "No"); 04151 ast_log(LOG_DTMF, "DTMF begin '%c' received on %s\n", f->subclass.integer, chan->name); 04152 if ( ast_test_flag(chan, AST_FLAG_DEFER_DTMF | AST_FLAG_END_DTMF_ONLY | AST_FLAG_EMULATE_DTMF) || 04153 (!ast_tvzero(chan->dtmf_tv) && 04154 ast_tvdiff_ms(ast_tvnow(), chan->dtmf_tv) < AST_MIN_DTMF_GAP) ) { 04155 ast_log(LOG_DTMF, "DTMF begin ignored '%c' on %s\n", f->subclass.integer, chan->name); 04156 ast_frfree(f); 04157 f = &ast_null_frame; 04158 } else { 04159 ast_set_flag(chan, AST_FLAG_IN_DTMF); 04160 chan->dtmf_tv = ast_tvnow(); 04161 ast_log(LOG_DTMF, "DTMF begin passthrough '%c' on %s\n", f->subclass.integer, chan->name); 04162 } 04163 break; 04164 case AST_FRAME_NULL: 04165 /* The EMULATE_DTMF flag must be cleared here as opposed to when the duration 04166 * is reached , because we want to make sure we pass at least one 04167 * voice frame through before starting the next digit, to ensure a gap 04168 * between DTMF digits. */ 04169 if (ast_test_flag(chan, AST_FLAG_EMULATE_DTMF)) { 04170 struct timeval now = ast_tvnow(); 04171 if (!chan->emulate_dtmf_duration) { 04172 ast_clear_flag(chan, AST_FLAG_EMULATE_DTMF); 04173 chan->emulate_dtmf_digit = 0; 04174 } else if (ast_tvdiff_ms(now, chan->dtmf_tv) >= chan->emulate_dtmf_duration) { 04175 chan->emulate_dtmf_duration = 0; 04176 ast_frfree(f); 04177 f = &chan->dtmff; 04178 f->frametype = AST_FRAME_DTMF_END; 04179 f->subclass.integer = chan->emulate_dtmf_digit; 04180 f->len = ast_tvdiff_ms(now, chan->dtmf_tv); 04181 chan->dtmf_tv = now; 04182 ast_clear_flag(chan, AST_FLAG_EMULATE_DTMF); 04183 chan->emulate_dtmf_digit = 0; 04184 ast_log(LOG_DTMF, "DTMF end emulation of '%c' queued on %s\n", f->subclass.integer, chan->name); 04185 if (chan->audiohooks) { 04186 struct ast_frame *old_frame = f; 04187 f = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_READ, f); 04188 if (old_frame != f) { 04189 ast_frfree(old_frame); 04190 } 04191 } 04192 } 04193 } 04194 break; 04195 case AST_FRAME_VOICE: 04196 /* The EMULATE_DTMF flag must be cleared here as opposed to when the duration 04197 * is reached , because we want to make sure we pass at least one 04198 * voice frame through before starting the next digit, to ensure a gap 04199 * between DTMF digits. */ 04200 if (ast_test_flag(chan, AST_FLAG_EMULATE_DTMF) && !chan->emulate_dtmf_duration) { 04201 ast_clear_flag(chan, AST_FLAG_EMULATE_DTMF); 04202 chan->emulate_dtmf_digit = 0; 04203 } 04204 04205 if (dropaudio || ast_test_flag(chan, AST_FLAG_IN_DTMF)) { 04206 if (dropaudio) 04207 ast_read_generator_actions(chan, f); 04208 ast_frfree(f); 04209 f = &ast_null_frame; 04210 } 04211 04212 if (ast_test_flag(chan, AST_FLAG_EMULATE_DTMF) && !ast_test_flag(chan, AST_FLAG_IN_DTMF)) { 04213 struct timeval now = ast_tvnow(); 04214 if (ast_tvdiff_ms(now, chan->dtmf_tv) >= chan->emulate_dtmf_duration) { 04215 chan->emulate_dtmf_duration = 0; 04216 ast_frfree(f); 04217 f = &chan->dtmff; 04218 f->frametype = AST_FRAME_DTMF_END; 04219 f->subclass.integer = chan->emulate_dtmf_digit; 04220 f->len = ast_tvdiff_ms(now, chan->dtmf_tv); 04221 chan->dtmf_tv = now; 04222 if (chan->audiohooks) { 04223 struct ast_frame *old_frame = f; 04224 f = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_READ, f); 04225 if (old_frame != f) 04226 ast_frfree(old_frame); 04227 } 04228 ast_log(LOG_DTMF, "DTMF end emulation of '%c' queued on %s\n", f->subclass.integer, chan->name); 04229 } else { 04230 /* Drop voice frames while we're still in the middle of the digit */ 04231 ast_frfree(f); 04232 f = &ast_null_frame; 04233 } 04234 } else if ((f->frametype == AST_FRAME_VOICE) && !(f->subclass.codec & chan->nativeformats)) { 04235 /* This frame is not one of the current native formats -- drop it on the floor */ 04236 char to[200]; 04237 ast_log(LOG_NOTICE, "Dropping incompatible voice frame on %s of format %s since our native format has changed to %s\n", 04238 chan->name, ast_getformatname(f->subclass.codec), ast_getformatname_multiple(to, sizeof(to), chan->nativeformats)); 04239 ast_frfree(f); 04240 f = &ast_null_frame; 04241 } else if ((f->frametype == AST_FRAME_VOICE)) { 04242 /* Send frame to audiohooks if present */ 04243 if (chan->audiohooks) { 04244 struct ast_frame *old_frame = f; 04245 f = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_READ, f); 04246 if (old_frame != f) 04247 ast_frfree(old_frame); 04248 } 04249 if (chan->monitor && chan->monitor->read_stream ) { 04250 /* XXX what does this do ? */ 04251 #ifndef MONITOR_CONSTANT_DELAY 04252 int jump = chan->outsmpl - chan->insmpl - 4 * f->samples; 04253 if (jump >= 0) { 04254 jump = calc_monitor_jump((chan->outsmpl - chan->insmpl), ast_format_rate(f->subclass.codec), ast_format_rate(chan->monitor->read_stream->fmt->format)); 04255 if (ast_seekstream(chan->monitor->read_stream, jump, SEEK_FORCECUR) == -1) 04256 ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n"); 04257 chan->insmpl += (chan->outsmpl - chan->insmpl) + f->samples; 04258 } else 04259 chan->insmpl+= f->samples; 04260 #else 04261 int jump = calc_monitor_jump((chan->outsmpl - chan->insmpl), ast_format_rate(f->subclass.codec), ast_format_rate(chan->monitor->read_stream->fmt->format)); 04262 if (jump - MONITOR_DELAY >= 0) { 04263 if (ast_seekstream(chan->monitor->read_stream, jump - f->samples, SEEK_FORCECUR) == -1) 04264 ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n"); 04265 chan->insmpl += chan->outsmpl - chan->insmpl; 04266 } else 04267 chan->insmpl += f->samples; 04268 #endif 04269 if (chan->monitor->state == AST_MONITOR_RUNNING) { 04270 if (ast_writestream(chan->monitor->read_stream, f) < 0) 04271 ast_log(LOG_WARNING, "Failed to write data to channel monitor read stream\n"); 04272 } 04273 } 04274 04275 if (chan->readtrans && (f = ast_translate(chan->readtrans, f, 1)) == NULL) { 04276 f = &ast_null_frame; 04277 } 04278 04279 /* it is possible for the translation process on chan->readtrans to have 04280 produced multiple frames from the single input frame we passed it; if 04281 this happens, queue the additional frames *before* the frames we may 04282 have queued earlier. if the readq was empty, put them at the head of 04283 the queue, and if it was not, put them just after the frame that was 04284 at the end of the queue. 04285 */ 04286 if (AST_LIST_NEXT(f, frame_list)) { 04287 if (!readq_tail) { 04288 ast_queue_frame_head(chan, AST_LIST_NEXT(f, frame_list)); 04289 } else { 04290 __ast_queue_frame(chan, AST_LIST_NEXT(f, frame_list), 0, readq_tail); 04291 } 04292 ast_frfree(AST_LIST_NEXT(f, frame_list)); 04293 AST_LIST_NEXT(f, frame_list) = NULL; 04294 } 04295 04296 /* Run generator sitting on the line if timing device not available 04297 * and synchronous generation of outgoing frames is necessary */ 04298 ast_read_generator_actions(chan, f); 04299 } 04300 break; 04301 default: 04302 /* Just pass it on! */ 04303 break; 04304 } 04305 } else { 04306 /* Make sure we always return NULL in the future */ 04307 if (!chan->_softhangup) { 04308 chan->_softhangup |= AST_SOFTHANGUP_DEV; 04309 } 04310 if (cause) 04311 chan->hangupcause = cause; 04312 if (chan->generator) 04313 ast_deactivate_generator(chan); 04314 /* We no longer End the CDR here */ 04315 } 04316 04317 /* High bit prints debugging */ 04318 if (chan->fin & DEBUGCHAN_FLAG) 04319 ast_frame_dump(chan->name, f, "<<"); 04320 chan->fin = FRAMECOUNT_INC(chan->fin); 04321 04322 done: 04323 if (chan->music_state && chan->generator && chan->generator->digit && f && f->frametype == AST_FRAME_DTMF_END) 04324 chan->generator->digit(chan, f->subclass.integer); 04325 04326 if (chan->audiohooks && ast_audiohook_write_list_empty(chan->audiohooks)) { 04327 /* The list gets recreated if audiohooks are added again later */ 04328 ast_audiohook_detach_list(chan->audiohooks); 04329 chan->audiohooks = NULL; 04330 } 04331 ast_channel_unlock(chan); 04332 return f; 04333 }
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 5413 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().
05414 { 05415 int dummy_outstate; 05416 int cause = 0; 05417 struct ast_channel *chan; 05418 int res = 0; 05419 int last_subclass = 0; 05420 struct ast_party_connected_line connected; 05421 05422 if (outstate) 05423 *outstate = 0; 05424 else 05425 outstate = &dummy_outstate; /* make outstate always a valid pointer */ 05426 05427 chan = ast_request(type, format, requestor, data, &cause); 05428 if (!chan) { 05429 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data); 05430 handle_cause(cause, outstate); 05431 return NULL; 05432 } 05433 05434 if (oh) { 05435 if (oh->vars) { 05436 ast_set_variables(chan, oh->vars); 05437 } 05438 if (!ast_strlen_zero(oh->cid_num) && !ast_strlen_zero(oh->cid_name)) { 05439 /* 05440 * Use the oh values instead of the function parameters for the 05441 * outgoing CallerID. 05442 */ 05443 cid_num = oh->cid_num; 05444 cid_name = oh->cid_name; 05445 } 05446 if (oh->parent_channel) { 05447 /* Safely inherit variables and datastores from the parent channel. */ 05448 ast_channel_lock_both(oh->parent_channel, chan); 05449 ast_channel_inherit_variables(oh->parent_channel, chan); 05450 ast_channel_datastore_inherit(oh->parent_channel, chan); 05451 ast_channel_unlock(oh->parent_channel); 05452 ast_channel_unlock(chan); 05453 } 05454 if (oh->account) { 05455 ast_channel_lock(chan); 05456 ast_cdr_setaccount(chan, oh->account); 05457 ast_channel_unlock(chan); 05458 } 05459 } 05460 05461 /* 05462 * I seems strange to set the CallerID on an outgoing call leg 05463 * to whom we are calling, but this function's callers are doing 05464 * various Originate methods. This call leg goes to the local 05465 * user. Once the local user answers, the dialplan needs to be 05466 * able to access the CallerID from the CALLERID function as if 05467 * the local user had placed this call. 05468 */ 05469 ast_set_callerid(chan, cid_num, cid_name, cid_num); 05470 05471 ast_set_flag(chan->cdr, AST_CDR_FLAG_ORIGINATED); 05472 ast_party_connected_line_set_init(&connected, &chan->connected); 05473 if (cid_num) { 05474 connected.id.number.valid = 1; 05475 connected.id.number.str = (char *) cid_num; 05476 connected.id.number.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED; 05477 } 05478 if (cid_name) { 05479 connected.id.name.valid = 1; 05480 connected.id.name.str = (char *) cid_name; 05481 connected.id.name.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED; 05482 } 05483 ast_channel_set_connected_line(chan, &connected, NULL); 05484 05485 if (ast_call(chan, data, 0)) { /* ast_call failed... */ 05486 ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data); 05487 } else { 05488 struct timeval start = ast_tvnow(); 05489 res = 1; /* mark success in case chan->_state is already AST_STATE_UP */ 05490 while (timeout && chan->_state != AST_STATE_UP) { 05491 struct ast_frame *f; 05492 int ms = ast_remaining_ms(start, timeout); 05493 05494 res = ast_waitfor(chan, ms); 05495 if (res == 0) { /* timeout, treat it like ringing */ 05496 *outstate = AST_CONTROL_RINGING; 05497 break; 05498 } 05499 if (res < 0) /* error or done */ 05500 break; 05501 if (!ast_strlen_zero(chan->call_forward)) { 05502 if (!(chan = ast_call_forward(NULL, chan, NULL, format, oh, outstate))) { 05503 return NULL; 05504 } 05505 continue; 05506 } 05507 05508 f = ast_read(chan); 05509 if (!f) { 05510 *outstate = AST_CONTROL_HANGUP; 05511 res = 0; 05512 break; 05513 } 05514 if (f->frametype == AST_FRAME_CONTROL) { 05515 switch (f->subclass.integer) { 05516 case AST_CONTROL_RINGING: /* record but keep going */ 05517 *outstate = f->subclass.integer; 05518 break; 05519 05520 case AST_CONTROL_BUSY: 05521 ast_cdr_busy(chan->cdr); 05522 *outstate = f->subclass.integer; 05523 timeout = 0; 05524 break; 05525 05526 case AST_CONTROL_INCOMPLETE: 05527 ast_cdr_failed(chan->cdr); 05528 *outstate = AST_CONTROL_CONGESTION; 05529 timeout = 0; 05530 break; 05531 05532 case AST_CONTROL_CONGESTION: 05533 ast_cdr_failed(chan->cdr); 05534 *outstate = f->subclass.integer; 05535 timeout = 0; 05536 break; 05537 05538 case AST_CONTROL_ANSWER: 05539 ast_cdr_answer(chan->cdr); 05540 *outstate = f->subclass.integer; 05541 timeout = 0; /* trick to force exit from the while() */ 05542 break; 05543 05544 /* Ignore these */ 05545 case AST_CONTROL_PROGRESS: 05546 case AST_CONTROL_PROCEEDING: 05547 case AST_CONTROL_HOLD: 05548 case AST_CONTROL_UNHOLD: 05549 case AST_CONTROL_VIDUPDATE: 05550 case AST_CONTROL_SRCUPDATE: 05551 case AST_CONTROL_SRCCHANGE: 05552 case AST_CONTROL_CONNECTED_LINE: 05553 case AST_CONTROL_REDIRECTING: 05554 case AST_CONTROL_CC: 05555 case -1: /* Ignore -- just stopping indications */ 05556 break; 05557 05558 default: 05559 ast_log(LOG_NOTICE, "Don't know what to do with control frame %d\n", f->subclass.integer); 05560 } 05561 last_subclass = f->subclass.integer; 05562 } 05563 ast_frfree(f); 05564 } 05565 } 05566 05567 /* Final fixups */ 05568 if (oh) { 05569 if (!ast_strlen_zero(oh->context)) 05570 ast_copy_string(chan->context, oh->context, sizeof(chan->context)); 05571 if (!ast_strlen_zero(oh->exten)) 05572 ast_copy_string(chan->exten, oh->exten, sizeof(chan->exten)); 05573 if (oh->priority) 05574 chan->priority = oh->priority; 05575 } 05576 if (chan->_state == AST_STATE_UP) 05577 *outstate = AST_CONTROL_ANSWER; 05578 05579 if (res <= 0) { 05580 ast_channel_lock(chan); 05581 if (AST_CONTROL_RINGING == last_subclass) { 05582 chan->hangupcause = AST_CAUSE_NO_ANSWER; 05583 } 05584 if (!chan->cdr && (chan->cdr = ast_cdr_alloc())) { 05585 ast_cdr_init(chan->cdr, chan); 05586 } 05587 if (chan->cdr) { 05588 char tmp[256]; 05589 05590 snprintf(tmp, sizeof(tmp), "%s/%s", type, (char *)data); 05591 ast_cdr_setapp(chan->cdr, "Dial", tmp); 05592 ast_cdr_update(chan); 05593 ast_cdr_start(chan->cdr); 05594 ast_cdr_end(chan->cdr); 05595 /* If the cause wasn't handled properly */ 05596 if (ast_cdr_disposition(chan->cdr, chan->hangupcause)) { 05597 ast_cdr_failed(chan->cdr); 05598 } 05599 } 05600 ast_channel_unlock(chan); 05601 ast_hangup(chan); 05602 chan = NULL; 05603 } 05604 return chan; 05605 }
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 4794 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().
04795 { 04796 int num_new_samples = frame->samples; 04797 struct plc_ds *plc = datastore->data; 04798 04799 /* As a general note, let me explain the somewhat odd calculations used when taking 04800 * the frame offset into account here. According to documentation in frame.h, the frame's 04801 * offset field indicates the number of bytes that the audio is offset. The plc->samples_buf 04802 * is not an array of bytes, but rather an array of 16-bit integers since it holds SLIN 04803 * samples. So I had two choices to make here with the offset. 04804 * 04805 * 1. Make the offset AST_FRIENDLY_OFFSET bytes. The main downside for this is that 04806 * I can't just add AST_FRIENDLY_OFFSET to the plc->samples_buf and have the pointer 04807 * arithmetic come out right. I would have to do some odd casting or division for this to 04808 * work as I wanted. 04809 * 2. Make the offset AST_FRIENDLY_OFFSET * 2 bytes. This allows the pointer arithmetic 04810 * to work out better with the plc->samples_buf. The downside here is that the buffer's 04811 * allocation contains an extra 64 bytes of unused space. 04812 * 04813 * I decided to go with option 2. This is why in the calloc statement and the statement that 04814 * sets the frame's offset, AST_FRIENDLY_OFFSET is multiplied by 2. 04815 */ 04816 04817 /* If this audio frame has no samples to fill in, ignore it */ 04818 if (!num_new_samples) { 04819 return; 04820 } 04821 04822 /* First, we need to be sure that our buffer is large enough to accomodate 04823 * the samples we need to fill in. This will likely only occur on the first 04824 * frame we write. 04825 */ 04826 if (plc->num_samples < num_new_samples) { 04827 ast_free(plc->samples_buf); 04828 plc->samples_buf = ast_calloc(1, (num_new_samples * sizeof(*plc->samples_buf)) + (AST_FRIENDLY_OFFSET * 2)); 04829 if (!plc->samples_buf) { 04830 ast_channel_datastore_remove(chan, datastore); 04831 ast_datastore_free(datastore); 04832 return; 04833 } 04834 plc->num_samples = num_new_samples; 04835 } 04836 04837 if (frame->datalen == 0) { 04838 plc_fillin(&plc->plc_state, plc->samples_buf + AST_FRIENDLY_OFFSET, frame->samples); 04839 frame->data.ptr = plc->samples_buf + AST_FRIENDLY_OFFSET; 04840 frame->datalen = num_new_samples * 2; 04841 frame->offset = AST_FRIENDLY_OFFSET * 2; 04842 } else { 04843 plc_rx(&plc->plc_state, frame->data.ptr, frame->samples); 04844 } 04845 }
static void apply_plc | ( | struct ast_channel * | chan, | |
struct ast_frame * | frame | |||
) | [static] |
Definition at line 4847 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().
04848 { 04849 struct ast_datastore *datastore; 04850 struct plc_ds *plc; 04851 04852 datastore = ast_channel_datastore_find(chan, &plc_ds_info, NULL); 04853 if (datastore) { 04854 plc = datastore->data; 04855 adjust_frame_for_plc(chan, frame, datastore); 04856 return; 04857 } 04858 04859 datastore = ast_datastore_alloc(&plc_ds_info, NULL); 04860 if (!datastore) { 04861 return; 04862 } 04863 plc = ast_calloc(1, sizeof(*plc)); 04864 if (!plc) { 04865 ast_datastore_free(datastore); 04866 return; 04867 } 04868 datastore->data = plc; 04869 ast_channel_datastore_add(chan, datastore); 04870 adjust_frame_for_plc(chan, frame, datastore); 04871 }
int ast_activate_generator | ( | struct ast_channel * | chan, | |
struct ast_generator * | gen, | |||
void * | params | |||
) |
Activate a given generator
Definition at line 3140 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().
03141 { 03142 int res = 0; 03143 03144 ast_channel_lock(chan); 03145 if (chan->generatordata) { 03146 if (chan->generator && chan->generator->release) 03147 chan->generator->release(chan, chan->generatordata); 03148 chan->generatordata = NULL; 03149 } 03150 if (gen->alloc && !(chan->generatordata = gen->alloc(chan, params))) { 03151 res = -1; 03152 } 03153 if (!res) { 03154 ast_settimeout(chan, 50, generator_force, chan); 03155 chan->generator = gen; 03156 } 03157 ast_channel_unlock(chan); 03158 03159 ast_prod(chan); 03160 03161 return res; 03162 }
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_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(), read_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 7086 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().
07087 { 07088 struct ast_channel *bridged; 07089 bridged = chan->_bridge; 07090 if (bridged && bridged->tech->bridged_channel) 07091 bridged = bridged->tech->bridged_channel(chan, bridged); 07092 return bridged; 07093 }
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 5718 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().
05719 { 05720 /* Place an outgoing call, but don't wait any longer than timeout ms before returning. 05721 If the remote end does not answer within the timeout, then do NOT hang up, but 05722 return anyway. */ 05723 int res = -1; 05724 /* Stop if we're a zombie or need a soft hangup */ 05725 ast_channel_lock(chan); 05726 if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan)) { 05727 if (chan->cdr) { 05728 ast_set_flag(chan->cdr, AST_CDR_FLAG_DIALED); 05729 } 05730 if (chan->tech->call) 05731 res = chan->tech->call(chan, addr, timeout); 05732 ast_set_flag(chan, AST_FLAG_OUTGOING); 05733 } 05734 ast_channel_unlock(chan); 05735 return res; 05736 }
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 5343 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().
05344 { 05345 char tmpchan[256]; 05346 struct ast_channel *new_chan = NULL; 05347 char *data, *type; 05348 int cause = 0; 05349 int res; 05350 05351 /* gather data and request the new forward channel */ 05352 ast_copy_string(tmpchan, orig->call_forward, sizeof(tmpchan)); 05353 if ((data = strchr(tmpchan, '/'))) { 05354 *data++ = '\0'; 05355 type = tmpchan; 05356 } else { 05357 const char *forward_context; 05358 ast_channel_lock(orig); 05359 forward_context = pbx_builtin_getvar_helper(orig, "FORWARD_CONTEXT"); 05360 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", orig->call_forward, S_OR(forward_context, orig->context)); 05361 ast_channel_unlock(orig); 05362 data = tmpchan; 05363 type = "Local"; 05364 } 05365 if (!(new_chan = ast_request(type, format, orig, data, &cause))) { 05366 ast_log(LOG_NOTICE, "Unable to create channel for call forward to '%s/%s' (cause = %d)\n", type, data, cause); 05367 handle_cause(cause, outstate); 05368 ast_hangup(orig); 05369 return NULL; 05370 } 05371 05372 /* Copy/inherit important information into new channel */ 05373 if (oh) { 05374 if (oh->vars) { 05375 ast_set_variables(new_chan, oh->vars); 05376 } 05377 if (oh->parent_channel) { 05378 call_forward_inherit(new_chan, oh->parent_channel, orig); 05379 } 05380 if (oh->account) { 05381 ast_channel_lock(new_chan); 05382 ast_cdr_setaccount(new_chan, oh->account); 05383 ast_channel_unlock(new_chan); 05384 } 05385 } else if (caller) { /* no outgoing helper so use caller if avaliable */ 05386 call_forward_inherit(new_chan, caller, orig); 05387 } 05388 05389 ast_channel_lock_both(orig, new_chan); 05390 ast_copy_flags(new_chan->cdr, orig->cdr, AST_CDR_FLAG_ORIGINATED); 05391 ast_string_field_set(new_chan, accountcode, orig->accountcode); 05392 ast_party_connected_line_copy(&new_chan->connected, &orig->connected); 05393 ast_party_redirecting_copy(&new_chan->redirecting, &orig->redirecting); 05394 ast_channel_unlock(new_chan); 05395 ast_channel_unlock(orig); 05396 05397 /* call new channel */ 05398 res = ast_call(new_chan, data, 0); 05399 if (timeout) { 05400 *timeout = res; 05401 } 05402 if (res) { 05403 ast_log(LOG_NOTICE, "Unable to call forward to channel %s/%s\n", type, (char *)data); 05404 ast_hangup(orig); 05405 ast_hangup(new_chan); 05406 return NULL; 05407 } 05408 ast_hangup(orig); 05409 05410 return new_chan; 05411 }
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 6186 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().
06187 { 06188 /* We must re-link, as the hash value will change here. */ 06189 ao2_lock(channels); 06190 ast_channel_lock(chan); 06191 ao2_unlink(channels, chan); 06192 __ast_change_name_nolink(chan, newname); 06193 ao2_link(channels, chan); 06194 ast_channel_unlock(chan); 06195 ao2_unlock(channels); 06196 }
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 9751 of file channel.c.
References __ast_channel_alloc_ap().
09756 { 09757 va_list ap1, ap2; 09758 struct ast_channel *result; 09759 09760 09761 va_start(ap1, name_fmt); 09762 va_start(ap2, name_fmt); 09763 result = __ast_channel_alloc_ap(needqueue, state, cid_num, cid_name, acctcode, exten, context, 09764 linkedid, amaflag, __FILE__, __LINE__, __FUNCTION__, name_fmt, ap1, ap2); 09765 va_end(ap1); 09766 va_end(ap2); 09767 09768 return result; 09769 }
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 7432 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().
07434 { 07435 struct ast_channel *chans[2] = { c0, c1 }; 07436 enum ast_bridge_result res = AST_BRIDGE_COMPLETE; 07437 format_t o0nativeformats; 07438 format_t o1nativeformats; 07439 long time_left_ms=0; 07440 char caller_warning = 0; 07441 char callee_warning = 0; 07442 07443 *fo = NULL; 07444 07445 if (c0->_bridge) { 07446 ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 07447 c0->name, c0->_bridge->name); 07448 return -1; 07449 } 07450 if (c1->_bridge) { 07451 ast_log(LOG_WARNING, "%s is already in a bridge with %s\n", 07452 c1->name, c1->_bridge->name); 07453 return -1; 07454 } 07455 07456 /* Stop if we're a zombie or need a soft hangup */ 07457 if (ast_test_flag(c0, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c0) || 07458 ast_test_flag(c1, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c1)) 07459 return -1; 07460 07461 caller_warning = ast_test_flag(&config->features_caller, AST_FEATURE_PLAY_WARNING); 07462 callee_warning = ast_test_flag(&config->features_callee, AST_FEATURE_PLAY_WARNING); 07463 07464 if (ast_tvzero(config->start_time)) { 07465 config->start_time = ast_tvnow(); 07466 if (config->start_sound) { 07467 if (caller_warning) { 07468 bridge_playfile(c0, c1, config->start_sound, config->timelimit / 1000); 07469 } 07470 if (callee_warning) { 07471 bridge_playfile(c1, c0, config->start_sound, config->timelimit / 1000); 07472 } 07473 } 07474 } 07475 07476 /* Keep track of bridge */ 07477 ast_channel_lock_both(c0, c1); 07478 c0->_bridge = c1; 07479 c1->_bridge = c0; 07480 ast_channel_unlock(c0); 07481 ast_channel_unlock(c1); 07482 07483 ast_set_owners_and_peers(c0, c1); 07484 07485 o0nativeformats = c0->nativeformats; 07486 o1nativeformats = c1->nativeformats; 07487 07488 if (config->feature_timer && !ast_tvzero(config->nexteventts)) { 07489 config->nexteventts = ast_tvadd(config->feature_start_time, ast_samp2tv(config->feature_timer, 1000)); 07490 } else if (config->timelimit) { 07491 time_left_ms = config->timelimit - ast_tvdiff_ms(ast_tvnow(), config->start_time); 07492 config->nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->timelimit, 1000)); 07493 if ((caller_warning || callee_warning) && config->play_warning) { 07494 long next_warn = config->play_warning; 07495 if (time_left_ms < config->play_warning && config->warning_freq > 0) { 07496 /* At least one warning was played, which means we are returning after feature */ 07497 long warns_passed = (config->play_warning - time_left_ms) / config->warning_freq; 07498 /* It is 'warns_passed * warning_freq' NOT '(warns_passed + 1) * warning_freq', 07499 because nexteventts will be updated once again in the 'if (!to)' block */ 07500 next_warn = config->play_warning - warns_passed * config->warning_freq; 07501 } 07502 config->nexteventts = ast_tvsub(config->nexteventts, ast_samp2tv(next_warn, 1000)); 07503 } 07504 } else { 07505 config->nexteventts.tv_sec = 0; 07506 config->nexteventts.tv_usec = 0; 07507 } 07508 07509 if (!c0->tech->send_digit_begin) 07510 ast_set_flag(c1, AST_FLAG_END_DTMF_ONLY); 07511 if (!c1->tech->send_digit_begin) 07512 ast_set_flag(c0, AST_FLAG_END_DTMF_ONLY); 07513 manager_bridge_event(1, 1, c0, c1); 07514 07515 /* Before we enter in and bridge these two together tell them both the source of audio has changed */ 07516 ast_indicate(c0, AST_CONTROL_SRCUPDATE); 07517 ast_indicate(c1, AST_CONTROL_SRCUPDATE); 07518 07519 for (/* ever */;;) { 07520 struct timeval now = { 0, }; 07521 int to; 07522 07523 to = -1; 07524 07525 if (!ast_tvzero(config->nexteventts)) { 07526 now = ast_tvnow(); 07527 to = ast_tvdiff_ms(config->nexteventts, now); 07528 if (to <= 0) { 07529 if (!config->timelimit) { 07530 res = AST_BRIDGE_COMPLETE; 07531 break; 07532 } 07533 to = 0; 07534 } 07535 } 07536 07537 if (config->timelimit) { 07538 time_left_ms = config->timelimit - ast_tvdiff_ms(now, config->start_time); 07539 if (time_left_ms < to) 07540 to = time_left_ms; 07541 07542 if (time_left_ms <= 0) { 07543 if (caller_warning && config->end_sound) 07544 bridge_playfile(c0, c1, config->end_sound, 0); 07545 if (callee_warning && config->end_sound) 07546 bridge_playfile(c1, c0, config->end_sound, 0); 07547 *fo = NULL; 07548 res = 0; 07549 ast_test_suite_event_notify("BRIDGE_TIMELIMIT", "Channel1: %s\r\nChannel2: %s", c0->name, c1->name); 07550 break; 07551 } 07552 07553 if (!to) { 07554 if (time_left_ms >= 5000 && config->warning_sound && config->play_warning && ast_test_flag(config, AST_FEATURE_WARNING_ACTIVE)) { 07555 int t = (time_left_ms + 500) / 1000; /* round to nearest second */ 07556 if (caller_warning) 07557 bridge_playfile(c0, c1, config->warning_sound, t); 07558 if (callee_warning) 07559 bridge_playfile(c1, c0, config->warning_sound, t); 07560 } 07561 07562 if (config->warning_freq && (time_left_ms > (config->warning_freq + 5000))) { 07563 config->nexteventts = ast_tvadd(config->nexteventts, ast_samp2tv(config->warning_freq, 1000)); 07564 } else { 07565 config->nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->timelimit, 1000)); 07566 } 07567 } 07568 ast_clear_flag(config, AST_FEATURE_WARNING_ACTIVE); 07569 } 07570 07571 if ((c0->_softhangup | c1->_softhangup) & AST_SOFTHANGUP_UNBRIDGE) {/* Bit operators are intentional. */ 07572 if (c0->_softhangup & AST_SOFTHANGUP_UNBRIDGE) { 07573 ast_channel_clear_softhangup(c0, AST_SOFTHANGUP_UNBRIDGE); 07574 } 07575 if (c1->_softhangup & AST_SOFTHANGUP_UNBRIDGE) { 07576 ast_channel_clear_softhangup(c1, AST_SOFTHANGUP_UNBRIDGE); 07577 } 07578 ast_channel_lock_both(c0, c1); 07579 c0->_bridge = c1; 07580 c1->_bridge = c0; 07581 ast_channel_unlock(c0); 07582 ast_channel_unlock(c1); 07583 ast_debug(1, "Unbridge signal received. Ending native bridge.\n"); 07584 continue; 07585 } 07586 07587 /* Stop if we're a zombie or need a soft hangup */ 07588 if (ast_test_flag(c0, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c0) || 07589 ast_test_flag(c1, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c1)) { 07590 *fo = NULL; 07591 res = 0; 07592 ast_debug(1, "Bridge stops because we're zombie or need a soft hangup: c0=%s, c1=%s, flags: %s,%s,%s,%s\n", 07593 c0->name, c1->name, 07594 ast_test_flag(c0, AST_FLAG_ZOMBIE) ? "Yes" : "No", 07595 ast_check_hangup(c0) ? "Yes" : "No", 07596 ast_test_flag(c1, AST_FLAG_ZOMBIE) ? "Yes" : "No", 07597 ast_check_hangup(c1) ? "Yes" : "No"); 07598 break; 07599 } 07600 07601 update_bridge_vars(c0, c1); 07602 07603 bridge_play_sounds(c0, c1); 07604 07605 if (c0->tech->bridge && 07606 /* if < 1 ms remains use generic bridging for accurate timing */ 07607 (!config->timelimit || to > 1000 || to == 0) && 07608 (c0->tech->bridge == c1->tech->bridge) && 07609 !c0->monitor && !c1->monitor && 07610 !c0->audiohooks && !c1->audiohooks && 07611 ast_framehook_list_is_empty(c0->framehooks) && ast_framehook_list_is_empty(c1->framehooks) && 07612 !c0->masq && !c0->masqr && !c1->masq && !c1->masqr) { 07613 int timeoutms = to - 1000 > 0 ? to - 1000 : to; 07614 /* Looks like they share a bridge method and nothing else is in the way */ 07615 ast_set_flag(c0, AST_FLAG_NBRIDGE); 07616 ast_set_flag(c1, AST_FLAG_NBRIDGE); 07617 if ((res = c0->tech->bridge(c0, c1, config->flags, fo, rc, timeoutms)) == AST_BRIDGE_COMPLETE) { 07618 ast_manager_event_multichan(EVENT_FLAG_CALL, "Unlink", 2, chans, 07619 "Channel1: %s\r\n" 07620 "Channel2: %s\r\n" 07621 "Uniqueid1: %s\r\n" 07622 "Uniqueid2: %s\r\n" 07623 "CallerID1: %s\r\n" 07624 "CallerID2: %s\r\n", 07625 c0->name, c1->name, 07626 c0->uniqueid, c1->uniqueid, 07627 S_COR(c0->caller.id.number.valid, c0->caller.id.number.str, "<unknown>"), 07628 S_COR(c1->caller.id.number.valid, c1->caller.id.number.str, "<unknown>")); 07629 07630 ast_debug(1, "Returning from native bridge, channels: %s, %s\n", c0->name, c1->name); 07631 07632 ast_clear_flag(c0, AST_FLAG_NBRIDGE); 07633 ast_clear_flag(c1, AST_FLAG_NBRIDGE); 07634 07635 if ((c0->_softhangup | c1->_softhangup) & AST_SOFTHANGUP_UNBRIDGE) {/* Bit operators are intentional. */ 07636 continue; 07637 } 07638 07639 ast_channel_lock_both(c0, c1); 07640 c0->_bridge = NULL; 07641 c1->_bridge = NULL; 07642 ast_channel_unlock(c0); 07643 ast_channel_unlock(c1); 07644 return res; 07645 } else { 07646 ast_clear_flag(c0, AST_FLAG_NBRIDGE); 07647 ast_clear_flag(c1, AST_FLAG_NBRIDGE); 07648 } 07649 switch (res) { 07650 case AST_BRIDGE_RETRY: 07651 if (config->play_warning) { 07652 ast_set_flag(config, AST_FEATURE_WARNING_ACTIVE); 07653 } 07654 continue; 07655 default: 07656 ast_verb(3, "Native bridging %s and %s ended\n", c0->name, c1->name); 07657 /* fallthrough */ 07658 case AST_BRIDGE_FAILED_NOWARN: 07659 break; 07660 } 07661 } 07662 07663 if (((c0->writeformat != c1->readformat) || (c0->readformat != c1->writeformat) || 07664 (c0->nativeformats != o0nativeformats) || (c1->nativeformats != o1nativeformats)) && 07665 !(c0->generator || c1->generator)) { 07666 if (ast_channel_make_compatible(c0, c1)) { 07667 ast_log(LOG_WARNING, "Can't make %s and %s compatible\n", c0->name, c1->name); 07668 manager_bridge_event(0, 1, c0, c1); 07669 return AST_BRIDGE_FAILED; 07670 } 07671 o0nativeformats = c0->nativeformats; 07672 o1nativeformats = c1->nativeformats; 07673 } 07674 07675 update_bridge_vars(c0, c1); 07676 07677 res = ast_generic_bridge(c0, c1, config, fo, rc); 07678 if (res != AST_BRIDGE_RETRY) { 07679 break; 07680 } else if (config->feature_timer) { 07681 /* feature timer expired but has not been updated, sending to ast_bridge_call to do so */ 07682 break; 07683 } 07684 } 07685 07686 ast_clear_flag(c0, AST_FLAG_END_DTMF_ONLY); 07687 ast_clear_flag(c1, AST_FLAG_END_DTMF_ONLY); 07688 07689 /* Now that we have broken the bridge the source will change yet again */ 07690 ast_indicate(c0, AST_CONTROL_SRCUPDATE); 07691 ast_indicate(c1, AST_CONTROL_SRCUPDATE); 07692 07693 ast_channel_lock_both(c0, c1); 07694 c0->_bridge = NULL; 07695 c1->_bridge = NULL; 07696 ast_channel_unlock(c0); 07697 ast_channel_unlock(c1); 07698 07699 ast_manager_event_multichan(EVENT_FLAG_CALL, "Unlink", 2, chans, 07700 "Channel1: %s\r\n" 07701 "Channel2: %s\r\n" 07702 "Uniqueid1: %s\r\n" 07703 "Uniqueid2: %s\r\n" 07704 "CallerID1: %s\r\n" 07705 "CallerID2: %s\r\n", 07706 c0->name, c1->name, 07707 c0->uniqueid, c1->uniqueid, 07708 S_COR(c0->caller.id.number.valid, c0->caller.id.number.str, "<unknown>"), 07709 S_COR(c1->caller.id.number.valid, c1->caller.id.number.str, "<unknown>")); 07710 ast_debug(1, "Bridge stops bridging channels %s and %s\n", c0->name, c1->name); 07711 07712 return res; 07713 }
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 9657 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().
09659 { 09660 struct ast_cc_config_params *cc_params; 09661 struct ast_datastore *cc_datastore; 09662 09663 if (!(cc_params = ast_cc_config_params_init())) { 09664 return -1; 09665 } 09666 09667 if (!(cc_datastore = ast_datastore_alloc(&cc_channel_datastore_info, NULL))) { 09668 ast_cc_config_params_destroy(cc_params); 09669 return -1; 09670 } 09671 09672 if (base_params) { 09673 ast_cc_copy_config_params(cc_params, base_params); 09674 } 09675 cc_datastore->data = cc_params; 09676 ast_channel_datastore_add(chan, cc_datastore); 09677 return 0; 09678 }
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 6326 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().
06327 { 06328 ast_assert(linkedid != NULL); 06329 /* if the linkedid for this channel is being changed from something, check... */ 06330 if (!strcmp(chan->linkedid, linkedid)) { 06331 return; 06332 } 06333 06334 ast_cel_check_retire_linkedid(chan); 06335 ast_string_field_set(chan, linkedid, linkedid); 06336 ast_cel_linkedid_ref(linkedid); 06337 }
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 9544 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().
09545 { 09546 const char *macro; 09547 const char *macro_args; 09548 int retval; 09549 09550 ast_channel_lock(macro_chan); 09551 macro = pbx_builtin_getvar_helper(macro_chan, is_caller 09552 ? "CONNECTED_LINE_CALLER_SEND_MACRO" : "CONNECTED_LINE_CALLEE_SEND_MACRO"); 09553 macro = ast_strdupa(S_OR(macro, "")); 09554 macro_args = pbx_builtin_getvar_helper(macro_chan, is_caller 09555 ? "CONNECTED_LINE_CALLER_SEND_MACRO_ARGS" : "CONNECTED_LINE_CALLEE_SEND_MACRO_ARGS"); 09556 macro_args = ast_strdupa(S_OR(macro_args, "")); 09557 09558 if (ast_strlen_zero(macro)) { 09559 ast_channel_unlock(macro_chan); 09560 return -1; 09561 } 09562 09563 if (is_frame) { 09564 const struct ast_frame *frame = connected_info; 09565 09566 ast_connected_line_parse_data(frame->data.ptr, frame->datalen, ¯o_chan->connected); 09567 } else { 09568 const struct ast_party_connected_line *connected = connected_info; 09569 09570 ast_party_connected_line_copy(¯o_chan->connected, connected); 09571 } 09572 ast_channel_unlock(macro_chan); 09573 09574 retval = ast_app_run_macro(autoservice_chan, macro_chan, macro, macro_args); 09575 if (!retval) { 09576 struct ast_party_connected_line saved_connected; 09577 09578 ast_party_connected_line_init(&saved_connected); 09579 ast_channel_lock(macro_chan); 09580 ast_party_connected_line_copy(&saved_connected, ¯o_chan->connected); 09581 ast_channel_unlock(macro_chan); 09582 ast_channel_update_connected_line(macro_chan, &saved_connected, NULL); 09583 ast_party_connected_line_free(&saved_connected); 09584 } 09585 09586 return retval; 09587 }
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(), 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(), 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_background(), speech_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_background(), speech_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 7332 of file channel.c.
References ast_channel_tech::early_bridge, and ast_channel::tech.
Referenced by dial_exec_full(), and wait_for_answer().
07333 { 07334 /* Make sure we can early bridge, if not error out */ 07335 if (!c0->tech->early_bridge || (c1 && (!c1->tech->early_bridge || c0->tech->early_bridge != c1->tech->early_bridge))) 07336 return -1; 07337 07338 return c0->tech->early_bridge(c0, c1); 07339 }
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 9719 of file channel.c.
References ast_channel_queryoption(), ast_copy_string(), and AST_OPTION_CC_AGENT_TYPE.
Referenced by find_agent_callbacks().
09720 { 09721 int len = size; 09722 char *slash; 09723 09724 if (!ast_channel_queryoption(chan, AST_OPTION_CC_AGENT_TYPE, agent_type, &len, 0)) { 09725 return 0; 09726 } 09727 09728 ast_copy_string(agent_type, chan->name, size); 09729 if ((slash = strchr(agent_type, '/'))) { 09730 *slash = '\0'; 09731 } 09732 return 0; 09733 }
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 9680 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().
09681 { 09682 struct ast_datastore *cc_datastore; 09683 09684 if (!(cc_datastore = ast_channel_datastore_find(chan, &cc_channel_datastore_info, NULL))) { 09685 /* If we can't find the datastore, it almost definitely means that the channel type being 09686 * used has not had its driver modified to parse CC config parameters. The best action 09687 * to take here is to create the parameters on the spot with the defaults set. 09688 */ 09689 if (ast_channel_cc_params_init(chan, NULL)) { 09690 return NULL; 09691 } 09692 if (!(cc_datastore = ast_channel_datastore_find(chan, &cc_channel_datastore_info, NULL))) { 09693 /* Should be impossible */ 09694 return NULL; 09695 } 09696 } 09697 09698 ast_assert(cc_datastore->data != NULL); 09699 return cc_datastore->data; 09700 }
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 9702 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().
09703 { 09704 int len = name_buffer_length; 09705 char *dash; 09706 if (!ast_channel_queryoption(chan, AST_OPTION_DEVICE_NAME, device_name, &len, 0)) { 09707 return 0; 09708 } 09709 09710 /* Dang. Do it the old-fashioned way */ 09711 ast_copy_string(device_name, chan->name, name_buffer_length); 09712 if ((dash = strrchr(device_name, '-'))) { 09713 *dash = '\0'; 09714 } 09715 09716 return 0; 09717 }
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 7984 of file channel.c.
References ast_str_case_hash(), and ast_strlen_zero().
Referenced by ast_channels_init().
07985 { 07986 const struct ast_channel *chan = obj; 07987 07988 /* If the name isn't set, return 0 so that the ao2_find() search will 07989 * start in the first bucket. */ 07990 if (ast_strlen_zero(chan->name)) { 07991 return 0; 07992 } 07993 07994 return ast_str_case_hash(chan->name); 07995 }
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 6198 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().
06199 { 06200 struct ast_var_t *current, *newvar; 06201 const char *varname; 06202 06203 AST_LIST_TRAVERSE(&parent->varshead, current, entries) { 06204 int vartype = 0; 06205 06206 varname = ast_var_full_name(current); 06207 if (!varname) 06208 continue; 06209 06210 if (varname[0] == '_') { 06211 vartype = 1; 06212 if (varname[1] == '_') 06213 vartype = 2; 06214 } 06215 06216 switch (vartype) { 06217 case 1: 06218 newvar = ast_var_assign(&varname[1], ast_var_value(current)); 06219 if (newvar) { 06220 AST_LIST_INSERT_TAIL(&child->varshead, newvar, entries); 06221 ast_debug(1, "Copying soft-transferable variable %s.\n", ast_var_name(newvar)); 06222 } 06223 break; 06224 case 2: 06225 newvar = ast_var_assign(varname, ast_var_value(current)); 06226 if (newvar) { 06227 AST_LIST_INSERT_TAIL(&child->varshead, newvar, entries); 06228 ast_debug(1, "Copying hard-transferable variable %s.\n", ast_var_name(newvar)); 06229 } 06230 break; 06231 default: 06232 ast_debug(1, "Not copying variable %s.\n", ast_var_name(current)); 06233 break; 06234 } 06235 } 06236 }
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 5927 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().
05928 { 05929 /* Some callers do not check return code, and we must try to set all call legs correctly */ 05930 int rc = 0; 05931 05932 /* Set up translation from the chan to the peer */ 05933 rc = ast_channel_make_compatible_helper(chan, peer); 05934 05935 if (rc < 0) 05936 return rc; 05937 05938 /* Set up translation from the peer to the chan */ 05939 rc = ast_channel_make_compatible_helper(peer, chan); 05940 05941 return rc; 05942 }
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 5877 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().
05878 { 05879 format_t src, dst; 05880 int use_slin; 05881 05882 /* See if the channel driver can natively make these two channels compatible */ 05883 if (from->tech->bridge && from->tech->bridge == to->tech->bridge && 05884 !ast_channel_setoption(from, AST_OPTION_MAKE_COMPATIBLE, to, sizeof(struct ast_channel *), 0)) { 05885 return 0; 05886 } 05887 05888 if (from->readformat == to->writeformat && from->writeformat == to->readformat) { 05889 /* Already compatible! Moving on ... */ 05890 return 0; 05891 } 05892 05893 /* Set up translation from the 'from' channel to the 'to' channel */ 05894 src = from->nativeformats; 05895 dst = to->nativeformats; 05896 05897 /* If there's no audio in this call, don't bother with trying to find a translation path */ 05898 if ((src & AST_FORMAT_AUDIO_MASK) == 0 || (dst & AST_FORMAT_AUDIO_MASK) == 0) 05899 return 0; 05900 05901 if (ast_translator_best_choice(&dst, &src) < 0) { 05902 ast_log(LOG_WARNING, "No path to translate from %s to %s\n", from->name, to->name); 05903 return -1; 05904 } 05905 05906 /* if the best path is not 'pass through', then 05907 * transcoding is needed; if desired, force transcode path 05908 * to use SLINEAR between channels, but only if there is 05909 * no direct conversion available. If generic PLC is 05910 * desired, then transcoding via SLINEAR is a requirement 05911 */ 05912 use_slin = (src == AST_FORMAT_SLINEAR || dst == AST_FORMAT_SLINEAR); 05913 if ((src != dst) && (ast_opt_generic_plc || ast_opt_transcode_via_slin) && 05914 (ast_translate_path_steps(dst, src) != 1 || use_slin)) 05915 dst = AST_FORMAT_SLINEAR; 05916 if (ast_set_read_format(from, dst) < 0) { 05917 ast_log(LOG_WARNING, "Unable to set read format on channel %s to %s\n", from->name, ast_getformatname(dst)); 05918 return -1; 05919 } 05920 if (ast_set_write_format(to, dst) < 0) { 05921 ast_log(LOG_WARNING, "Unable to set write format on channel %s to %s\n", to->name, ast_getformatname(dst)); 05922 return -1; 05923 } 05924 return 0; 05925 }
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 6067 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().
06068 { 06069 return __ast_channel_masquerade(original, clone, NULL); 06070 }
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 7736 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().
07737 { 07738 int res; 07739 07740 ast_channel_lock(chan); 07741 if (!chan->tech->queryoption) { 07742 errno = ENOSYS; 07743 ast_channel_unlock(chan); 07744 return -1; 07745 } 07746 07747 if (block) 07748 ast_log(LOG_ERROR, "XXX Blocking not implemented yet XXX\n"); 07749 07750 res = chan->tech->queryoption(chan, option, data, datalen); 07751 ast_channel_unlock(chan); 07752 07753 return res; 07754 }
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 9024 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().
09025 { 09026 unsigned char data[1024]; /* This should be large enough */ 09027 size_t datalen; 09028 09029 datalen = ast_connected_line_build_data(data, sizeof(data), connected, update); 09030 if (datalen == (size_t) -1) { 09031 return; 09032 } 09033 09034 ast_queue_control_data(chan, AST_CONTROL_CONNECTED_LINE, data, datalen); 09035 }
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 9531 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().
09532 { 09533 unsigned char data[1024]; /* This should be large enough */ 09534 size_t datalen; 09535 09536 datalen = ast_redirecting_build_data(data, sizeof(data), redirecting, update); 09537 if (datalen == (size_t) -1) { 09538 return; 09539 } 09540 09541 ast_queue_control_data(chan, AST_CONTROL_REDIRECTING, data, datalen); 09542 }
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 5270 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().
05271 { 05272 switch (reason) /* the following appear to be the only ones actually returned by request_and_dial */ 05273 { 05274 case 0: 05275 return "Call Failure (not BUSY, and not NO_ANSWER, maybe Circuit busy or down?)"; 05276 case AST_CONTROL_HANGUP: 05277 return "Hangup"; 05278 case AST_CONTROL_RING: 05279 return "Local Ring"; 05280 case AST_CONTROL_RINGING: 05281 return "Remote end Ringing"; 05282 case AST_CONTROL_ANSWER: 05283 return "Remote end has Answered"; 05284 case AST_CONTROL_BUSY: 05285 return "Remote end is Busy"; 05286 case AST_CONTROL_CONGESTION: 05287 return "Congestion (circuits busy)"; 05288 default: 05289 return "Unknown Reason!!"; 05290 } 05291 }
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 9589 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().
09590 { 09591 const char *macro; 09592 const char *macro_args; 09593 int retval; 09594 09595 ast_channel_lock(macro_chan); 09596 macro = pbx_builtin_getvar_helper(macro_chan, is_caller 09597 ? "REDIRECTING_CALLER_SEND_MACRO" : "REDIRECTING_CALLEE_SEND_MACRO"); 09598 macro = ast_strdupa(S_OR(macro, "")); 09599 macro_args = pbx_builtin_getvar_helper(macro_chan, is_caller 09600 ? "REDIRECTING_CALLER_SEND_MACRO_ARGS" : "REDIRECTING_CALLEE_SEND_MACRO_ARGS"); 09601 macro_args = ast_strdupa(S_OR(macro_args, "")); 09602 09603 if (ast_strlen_zero(macro)) { 09604 ast_channel_unlock(macro_chan); 09605 return -1; 09606 } 09607 09608 if (is_frame) { 09609 const struct ast_frame *frame = redirecting_info; 09610 09611 ast_redirecting_parse_data(frame->data.ptr, frame->datalen, ¯o_chan->redirecting); 09612 } else { 09613 const struct ast_party_redirecting *redirecting = redirecting_info; 09614 09615 ast_party_redirecting_copy(¯o_chan->redirecting, redirecting); 09616 } 09617 ast_channel_unlock(macro_chan); 09618 09619 retval = ast_app_run_macro(autoservice_chan, macro_chan, macro, macro_args); 09620 if (!retval) { 09621 struct ast_party_redirecting saved_redirecting; 09622 09623 ast_party_redirecting_init(&saved_redirecting); 09624 ast_channel_lock(macro_chan); 09625 ast_party_redirecting_copy(&saved_redirecting, ¯o_chan->redirecting); 09626 ast_channel_unlock(macro_chan); 09627 ast_channel_update_redirecting(macro_chan, &saved_redirecting, NULL); 09628 ast_party_redirecting_free(&saved_redirecting); 09629 } 09630 09631 return retval; 09632 }
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 5864 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 5871 of file channel.c.
References ast_channel_sendhtml(), and AST_HTML_URL.
Referenced by dial_exec_full(), sendurl_exec(), and try_calling().
05872 { 05873 return ast_channel_sendhtml(chan, AST_HTML_URL, url, strlen(url) + 1); 05874 }
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 7005 of file channel.c.
References ast_channel_lock, ast_channel_unlock, ast_party_caller_set(), and ast_channel::caller.
07006 { 07007 if (&chan->caller == caller) { 07008 /* Don't set to self */ 07009 return; 07010 } 07011 07012 ast_channel_lock(chan); 07013 ast_party_caller_set(&chan->caller, caller, update); 07014 ast_channel_unlock(chan); 07015 }
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 7017 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().
07018 { 07019 const char *pre_set_number; 07020 const char *pre_set_name; 07021 07022 if (&chan->caller == caller) { 07023 /* Don't set to self */ 07024 return; 07025 } 07026 07027 ast_channel_lock(chan); 07028 pre_set_number = 07029 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL); 07030 pre_set_name = S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL); 07031 ast_party_caller_set(&chan->caller, caller, update); 07032 if (S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL) 07033 != pre_set_number 07034 || S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL) 07035 != pre_set_name) { 07036 /* The caller id name or number changed. */ 07037 report_new_callerid(chan); 07038 } 07039 if (chan->cdr) { 07040 ast_cdr_setcid(chan->cdr, chan); 07041 } 07042 ast_channel_unlock(chan); 07043 }
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 8384 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().
08385 { 08386 if (&chan->connected == connected) { 08387 /* Don't set to self */ 08388 return; 08389 } 08390 08391 ast_channel_lock(chan); 08392 ast_party_connected_line_set(&chan->connected, connected, update); 08393 ast_channel_unlock(chan); 08394 }
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_deactivate_generator(), ast_do_masquerade(), dahdi_new(), gtalk_new(), initialize_udptl(), internal_deactivate_generator(), 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 6343 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().
06344 { 06345 const char* linkedid=NULL; 06346 struct ast_channel *bridged; 06347 06348 linkedid = oldest_linkedid(chan->linkedid, peer->linkedid); 06349 linkedid = oldest_linkedid(linkedid, chan->uniqueid); 06350 linkedid = oldest_linkedid(linkedid, peer->uniqueid); 06351 if (chan->_bridge) { 06352 bridged = ast_bridged_channel(chan); 06353 if (bridged != peer) { 06354 linkedid = oldest_linkedid(linkedid, bridged->linkedid); 06355 linkedid = oldest_linkedid(linkedid, bridged->uniqueid); 06356 } 06357 } 06358 if (peer->_bridge) { 06359 bridged = ast_bridged_channel(peer); 06360 if (bridged != chan) { 06361 linkedid = oldest_linkedid(linkedid, bridged->linkedid); 06362 linkedid = oldest_linkedid(linkedid, bridged->uniqueid); 06363 } 06364 } 06365 06366 /* just in case setting a stringfield to itself causes problems */ 06367 linkedid = ast_strdupa(linkedid); 06368 06369 ast_channel_change_linkedid(chan, linkedid); 06370 ast_channel_change_linkedid(peer, linkedid); 06371 if (chan->_bridge) { 06372 bridged = ast_bridged_channel(chan); 06373 if (bridged != peer) { 06374 ast_channel_change_linkedid(bridged, linkedid); 06375 } 06376 } 06377 if (peer->_bridge) { 06378 bridged = ast_bridged_channel(peer); 06379 if (bridged != chan) { 06380 ast_channel_change_linkedid(bridged, linkedid); 06381 } 06382 } 06383 }
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 9037 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().
09038 { 09039 if (&chan->redirecting == redirecting) { 09040 /* Don't set to self */ 09041 return; 09042 } 09043 09044 ast_channel_lock(chan); 09045 ast_party_redirecting_set(&chan->redirecting, redirecting, update); 09046 ast_channel_unlock(chan); 09047 }
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 7716 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().
07717 { 07718 int res; 07719 07720 ast_channel_lock(chan); 07721 if (!chan->tech->setoption) { 07722 errno = ENOSYS; 07723 ast_channel_unlock(chan); 07724 return -1; 07725 } 07726 07727 if (block) 07728 ast_log(LOG_ERROR, "XXX Blocking not implemented yet XXX\n"); 07729 07730 res = chan->tech->setoption(chan, option, data, datalen); 07731 ast_channel_unlock(chan); 07732 07733 return res; 07734 }
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 8230 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().
08231 { 08232 struct ast_silence_generator *state; 08233 08234 if (!(state = ast_calloc(1, sizeof(*state)))) { 08235 return NULL; 08236 } 08237 08238 state->old_write_format = chan->writeformat; 08239 08240 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { 08241 ast_log(LOG_ERROR, "Could not set write format to SLINEAR\n"); 08242 ast_free(state); 08243 return NULL; 08244 } 08245 08246 ast_activate_generator(chan, &silence_generator, state); 08247 08248 ast_debug(1, "Started silence generator on '%s'\n", chan->name); 08249 08250 return state; 08251 }
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 8282 of file channel.c.
References ast_debug, ast_free, ast_log(), ast_set_write_format(), internal_deactivate_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().
08283 { 08284 if (!state) 08285 return; 08286 08287 if (internal_deactivate_generator(chan, &silence_generator)) { 08288 ast_debug(1, "Stopped silence generator on '%s'\n", chan->name); 08289 08290 if (ast_set_write_format(chan, state->old_write_format) < 0) 08291 ast_log(LOG_ERROR, "Could not return write format to its original state\n"); 08292 } 08293 ast_free(state); 08294 }
int ast_channel_supports_html | ( | struct ast_channel * | channel | ) |
Checks for HTML support on a channel.
Definition at line 5859 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 6141 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().
06148 { 06149 struct ast_datastore *xfer_ds; 06150 struct xfer_masquerade_ds *xfer_colp; 06151 int res; 06152 06153 xfer_ds = ast_datastore_alloc(&xfer_ds_info, NULL); 06154 if (!xfer_ds) { 06155 return -1; 06156 } 06157 06158 xfer_colp = ast_calloc(1, sizeof(*xfer_colp)); 06159 if (!xfer_colp) { 06160 ast_datastore_free(xfer_ds); 06161 return -1; 06162 } 06163 party_connected_line_copy_transfer(&xfer_colp->target_id, target_id); 06164 xfer_colp->target_held = target_held; 06165 party_connected_line_copy_transfer(&xfer_colp->transferee_id, transferee_id); 06166 xfer_colp->transferee_held = transferee_held; 06167 xfer_ds->data = xfer_colp; 06168 06169 res = __ast_channel_masquerade(target_chan, transferee_chan, xfer_ds); 06170 if (res) { 06171 ast_datastore_free(xfer_ds); 06172 } 06173 return res; 06174 }
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 9011 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().
09012 { 09013 unsigned char data[1024]; /* This should be large enough */ 09014 size_t datalen; 09015 09016 datalen = ast_connected_line_build_data(data, sizeof(data), connected, update); 09017 if (datalen == (size_t) -1) { 09018 return; 09019 } 09020 09021 ast_indicate_data(chan, AST_CONTROL_CONNECTED_LINE, data, datalen); 09022 }
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 9518 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().
09519 { 09520 unsigned char data[1024]; /* This should be large enough */ 09521 size_t datalen; 09522 09523 datalen = ast_redirecting_build_data(data, sizeof(data), redirecting, update); 09524 if (datalen == (size_t) -1) { 09525 return; 09526 } 09527 09528 ast_indicate_data(chan, AST_CONTROL_REDIRECTING, data, datalen); 09529 }
void ast_channels_init | ( | void | ) |
Provided by channel.c
Definition at line 8142 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().
08143 { 08144 channels = ao2_container_alloc(NUM_CHANNEL_BUCKETS, 08145 ast_channel_hash_cb, ast_channel_cmp_cb); 08146 08147 ast_cli_register_multiple(cli_channel, ARRAY_LEN(cli_channel)); 08148 08149 ast_data_register_multiple_core(channel_providers, ARRAY_LEN(channel_providers)); 08150 08151 ast_plc_reload(); 08152 08153 ast_register_atexit(channels_shutdown); 08154 }
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_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(), 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(), read_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 8751 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().
08752 { 08753 int32_t value; 08754 size_t pos = 0; 08755 int res; 08756 08757 static const struct ast_party_id_ies ies = { 08758 .name.str = AST_CONNECTED_LINE_NAME, 08759 .name.char_set = AST_CONNECTED_LINE_NAME_CHAR_SET, 08760 .name.presentation = AST_CONNECTED_LINE_NAME_PRESENTATION, 08761 .name.valid = AST_CONNECTED_LINE_NAME_VALID, 08762 08763 .number.str = AST_CONNECTED_LINE_NUMBER, 08764 .number.plan = AST_CONNECTED_LINE_NUMBER_PLAN, 08765 .number.presentation = AST_CONNECTED_LINE_NUMBER_PRESENTATION, 08766 .number.valid = AST_CONNECTED_LINE_NUMBER_VALID, 08767 08768 .subaddress.str = AST_CONNECTED_LINE_SUBADDRESS, 08769 .subaddress.type = AST_CONNECTED_LINE_SUBADDRESS_TYPE, 08770 .subaddress.odd_even_indicator = AST_CONNECTED_LINE_SUBADDRESS_ODD_EVEN, 08771 .subaddress.valid = AST_CONNECTED_LINE_SUBADDRESS_VALID, 08772 08773 .tag = AST_CONNECTED_LINE_TAG, 08774 .combined_presentation = AST_CONNECTED_LINE_ID_PRESENTATION, 08775 }; 08776 08777 /* 08778 * The size of integer values must be fixed in case the frame is 08779 * shipped to another machine. 08780 */ 08781 08782 /* Connected line frame version */ 08783 if (datalen < pos + (sizeof(data[0]) * 2) + 1) { 08784 ast_log(LOG_WARNING, "No space left for connected line frame version\n"); 08785 return -1; 08786 } 08787 data[pos++] = AST_CONNECTED_LINE_VERSION; 08788 data[pos++] = 1; 08789 data[pos++] = 2;/* Version 1 did not have a version ie */ 08790 08791 res = party_id_build_data(data + pos, datalen - pos, &connected->id, 08792 "connected line", &ies, update ? &update->id : NULL); 08793 if (res < 0) { 08794 return -1; 08795 } 08796 pos += res; 08797 08798 /* Connected line source */ 08799 if (datalen < pos + (sizeof(data[0]) * 2) + sizeof(value)) { 08800 ast_log(LOG_WARNING, "No space left for connected line source\n"); 08801 return -1; 08802 } 08803 data[pos++] = AST_CONNECTED_LINE_SOURCE; 08804 data[pos++] = sizeof(value); 08805 value = htonl(connected->source); 08806 memcpy(data + pos, &value, sizeof(value)); 08807 pos += sizeof(value); 08808 08809 return pos; 08810 }
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 8369 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().
08370 { 08371 ast_party_id_copy(&dest->id, &src->id); 08372 ast_party_id_copy(&dest->ani, &src->ani); 08373 dest->ani2 = src->ani2; 08374 }
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 8376 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().
08377 { 08378 ast_party_id_copy(&dest->id, &src->id); 08379 ast_party_id_copy(&dest->ani, &src->ani); 08380 08381 dest->ani2 = src->ani2; 08382 }
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 8812 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().
08813 { 08814 size_t pos; 08815 unsigned char ie_len; 08816 unsigned char ie_id; 08817 int32_t value; 08818 int frame_version = 1; 08819 int combined_presentation = 0; 08820 int got_combined_presentation = 0;/* TRUE if got a combined name and number presentation value. */ 08821 08822 for (pos = 0; pos < datalen; pos += ie_len) { 08823 if (datalen < pos + sizeof(ie_id) + sizeof(ie_len)) { 08824 ast_log(LOG_WARNING, "Invalid connected line update\n"); 08825 return -1; 08826 } 08827 ie_id = data[pos++]; 08828 ie_len = data[pos++]; 08829 if (datalen < pos + ie_len) { 08830 ast_log(LOG_WARNING, "Invalid connected line update\n"); 08831 return -1; 08832 } 08833 08834 switch (ie_id) { 08835 /* Connected line party frame version */ 08836 case AST_CONNECTED_LINE_VERSION: 08837 if (ie_len != 1) { 08838 ast_log(LOG_WARNING, "Invalid connected line frame version (%u)\n", 08839 (unsigned) ie_len); 08840 break; 08841 } 08842 frame_version = data[pos]; 08843 break; 08844 /* Connected line party id name */ 08845 case AST_CONNECTED_LINE_NAME: 08846 ast_free(connected->id.name.str); 08847 connected->id.name.str = ast_malloc(ie_len + 1); 08848 if (connected->id.name.str) { 08849 memcpy(connected->id.name.str, data + pos, ie_len); 08850 connected->id.name.str[ie_len] = 0; 08851 } 08852 break; 08853 case AST_CONNECTED_LINE_NAME_CHAR_SET: 08854 if (ie_len != 1) { 08855 ast_log(LOG_WARNING, "Invalid connected line name char set (%u)\n", 08856 (unsigned) ie_len); 08857 break; 08858 } 08859 connected->id.name.char_set = data[pos]; 08860 break; 08861 case AST_CONNECTED_LINE_NAME_PRESENTATION: 08862 if (ie_len != 1) { 08863 ast_log(LOG_WARNING, "Invalid connected line name presentation (%u)\n", 08864 (unsigned) ie_len); 08865 break; 08866 } 08867 connected->id.name.presentation = data[pos]; 08868 break; 08869 case AST_CONNECTED_LINE_NAME_VALID: 08870 if (ie_len != 1) { 08871 ast_log(LOG_WARNING, "Invalid connected line name valid (%u)\n", 08872 (unsigned) ie_len); 08873 break; 08874 } 08875 connected->id.name.valid = data[pos]; 08876 break; 08877 /* Connected line party id number */ 08878 case AST_CONNECTED_LINE_NUMBER: 08879 ast_free(connected->id.number.str); 08880 connected->id.number.str = ast_malloc(ie_len + 1); 08881 if (connected->id.number.str) { 08882 memcpy(connected->id.number.str, data + pos, ie_len); 08883 connected->id.number.str[ie_len] = 0; 08884 } 08885 break; 08886 case AST_CONNECTED_LINE_NUMBER_PLAN: 08887 if (ie_len != 1) { 08888 ast_log(LOG_WARNING, "Invalid connected line numbering plan (%u)\n", 08889 (unsigned) ie_len); 08890 break; 08891 } 08892 connected->id.number.plan = data[pos]; 08893 break; 08894 case AST_CONNECTED_LINE_NUMBER_PRESENTATION: 08895 if (ie_len != 1) { 08896 ast_log(LOG_WARNING, "Invalid connected line number presentation (%u)\n", 08897 (unsigned) ie_len); 08898 break; 08899 } 08900 connected->id.number.presentation = data[pos]; 08901 break; 08902 case AST_CONNECTED_LINE_NUMBER_VALID: 08903 if (ie_len != 1) { 08904 ast_log(LOG_WARNING, "Invalid connected line number valid (%u)\n", 08905 (unsigned) ie_len); 08906 break; 08907 } 08908 connected->id.number.valid = data[pos]; 08909 break; 08910 /* Connected line party id combined presentation */ 08911 case AST_CONNECTED_LINE_ID_PRESENTATION: 08912 if (ie_len != 1) { 08913 ast_log(LOG_WARNING, "Invalid connected line combined presentation (%u)\n", 08914 (unsigned) ie_len); 08915 break; 08916 } 08917 combined_presentation = data[pos]; 08918 got_combined_presentation = 1; 08919 break; 08920 /* Connected line party id subaddress */ 08921 case AST_CONNECTED_LINE_SUBADDRESS: 08922 ast_free(connected->id.subaddress.str); 08923 connected->id.subaddress.str = ast_malloc(ie_len + 1); 08924 if (connected->id.subaddress.str) { 08925 memcpy(connected->id.subaddress.str, data + pos, ie_len); 08926 connected->id.subaddress.str[ie_len] = 0; 08927 } 08928 break; 08929 case AST_CONNECTED_LINE_SUBADDRESS_TYPE: 08930 if (ie_len != 1) { 08931 ast_log(LOG_WARNING, "Invalid connected line type of subaddress (%u)\n", 08932 (unsigned) ie_len); 08933 break; 08934 } 08935 connected->id.subaddress.type = data[pos]; 08936 break; 08937 case AST_CONNECTED_LINE_SUBADDRESS_ODD_EVEN: 08938 if (ie_len != 1) { 08939 ast_log(LOG_WARNING, 08940 "Invalid connected line subaddress odd-even indicator (%u)\n", 08941 (unsigned) ie_len); 08942 break; 08943 } 08944 connected->id.subaddress.odd_even_indicator = data[pos]; 08945 break; 08946 case AST_CONNECTED_LINE_SUBADDRESS_VALID: 08947 if (ie_len != 1) { 08948 ast_log(LOG_WARNING, "Invalid connected line subaddress valid (%u)\n", 08949 (unsigned) ie_len); 08950 break; 08951 } 08952 connected->id.subaddress.valid = data[pos]; 08953 break; 08954 /* Connected line party tag */ 08955 case AST_CONNECTED_LINE_TAG: 08956 ast_free(connected->id.tag); 08957 connected->id.tag = ast_malloc(ie_len + 1); 08958 if (connected->id.tag) { 08959 memcpy(connected->id.tag, data + pos, ie_len); 08960 connected->id.tag[ie_len] = 0; 08961 } 08962 break; 08963 /* Connected line party source */ 08964 case AST_CONNECTED_LINE_SOURCE: 08965 if (ie_len != sizeof(value)) { 08966 ast_log(LOG_WARNING, "Invalid connected line source (%u)\n", 08967 (unsigned) ie_len); 08968 break; 08969 } 08970 memcpy(&value, data + pos, sizeof(value)); 08971 connected->source = ntohl(value); 08972 break; 08973 /* Connected line party unknown element */ 08974 default: 08975 ast_log(LOG_DEBUG, "Unknown connected line element: %u (%u)\n", 08976 (unsigned) ie_id, (unsigned) ie_len); 08977 break; 08978 } 08979 } 08980 08981 switch (frame_version) { 08982 case 1: 08983 /* 08984 * The other end is an earlier version that we need to adjust 08985 * for compatibility. 08986 */ 08987 connected->id.name.valid = 1; 08988 connected->id.name.char_set = AST_PARTY_CHAR_SET_ISO8859_1; 08989 connected->id.number.valid = 1; 08990 if (got_combined_presentation) { 08991 connected->id.name.presentation = combined_presentation; 08992 connected->id.number.presentation = combined_presentation; 08993 } 08994 break; 08995 case 2: 08996 /* The other end is at the same level as we are. */ 08997 break; 08998 default: 08999 /* 09000 * The other end is newer than we are. 09001 * We need to assume that they are compatible with us. 09002 */ 09003 ast_log(LOG_DEBUG, "Connected line frame has newer version: %u\n", 09004 (unsigned) frame_version); 09005 break; 09006 } 09007 09008 return 0; 09009 }
AST_DATA_STRUCTURE | ( | ast_channel | , | |
DATA_EXPORT_CHANNEL | ||||
) |
void ast_deactivate_generator | ( | struct ast_channel * | chan | ) |
Deactivate an active generator
Definition at line 3091 of file channel.c.
References ast_channel_lock, ast_channel_set_fd(), ast_channel_unlock, ast_clear_flag, AST_FLAG_WRITE_INT, AST_GENERATOR_FD, ast_settimeout(), ast_channel::generator, ast_channel::generatordata, and ast_generator::release.
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().
03092 { 03093 ast_channel_lock(chan); 03094 if (chan->generatordata) { 03095 if (chan->generator && chan->generator->release) 03096 chan->generator->release(chan, chan->generatordata); 03097 chan->generatordata = NULL; 03098 chan->generator = NULL; 03099 ast_channel_set_fd(chan, AST_GENERATOR_FD, -1); 03100 ast_clear_flag(chan, AST_FLAG_WRITE_INT); 03101 ast_settimeout(chan, 0, NULL, NULL); 03102 } 03103 ast_channel_unlock(chan); 03104 }
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 6502 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_CONTROL_SRCCHANGE, AST_CONTROL_UNHOLD, ast_copy_string(), ast_datastore_free(), ast_debug, AST_FLAG_BLOCKING, AST_FLAG_EXCEPTION, 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_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_channel::visible_indication, 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().
06503 { 06504 int x; 06505 int i; 06506 int origstate; 06507 int visible_indication; 06508 int clone_was_zombie = 0;/*!< TRUE if the clonechan was a zombie before the masquerade. */ 06509 struct ast_frame *current; 06510 const struct ast_channel_tech *t; 06511 void *t_pvt; 06512 union { 06513 struct ast_party_dialed dialed; 06514 struct ast_party_caller caller; 06515 struct ast_party_connected_line connected; 06516 struct ast_party_redirecting redirecting; 06517 } exchange; 06518 struct ast_channel *clonechan, *chans[2]; 06519 struct ast_channel *bridged; 06520 struct ast_cdr *cdr; 06521 struct ast_datastore *xfer_ds; 06522 struct xfer_masquerade_ds *xfer_colp; 06523 format_t rformat; 06524 format_t wformat; 06525 format_t tmp_format; 06526 char newn[AST_CHANNEL_NAME]; 06527 char orig[AST_CHANNEL_NAME]; 06528 char masqn[AST_CHANNEL_NAME]; 06529 char zombn[AST_CHANNEL_NAME]; 06530 char clone_sending_dtmf_digit; 06531 struct timeval clone_sending_dtmf_tv; 06532 06533 /* XXX This operation is a bit odd. We're essentially putting the guts of 06534 * the clone channel into the original channel. Start by killing off the 06535 * original channel's backend. While the features are nice, which is the 06536 * reason we're keeping it, it's still awesomely weird. XXX */ 06537 06538 /* 06539 * The reasoning for the channels ao2_container lock here is 06540 * complex. 06541 * 06542 * There is a race condition that exists for this function. 06543 * Since all pvt and channel locks must be let go before calling 06544 * ast_do_masquerade, it is possible that it could be called 06545 * multiple times for the same channel. In order to prevent the 06546 * race condition with competing threads to do the masquerade 06547 * and new masquerade attempts, the channels container must be 06548 * locked for the entire masquerade. The original and clonechan 06549 * need to be unlocked earlier to avoid potential deadlocks with 06550 * the chan_local deadlock avoidance method. 06551 * 06552 * The container lock blocks competing masquerade attempts from 06553 * starting as well as being necessary for proper locking order 06554 * because the channels must to be unlinked to change their 06555 * names. 06556 * 06557 * The original and clonechan locks must be held while the 06558 * channel contents are shuffled around for the masquerade. 06559 * 06560 * The masq and masqr pointers need to be left alone until the 06561 * masquerade has restabilized the channels to prevent another 06562 * masquerade request until the AST_FLAG_ZOMBIE can be set on 06563 * the clonechan. 06564 */ 06565 ao2_lock(channels); 06566 06567 /* 06568 * Lock the original channel to determine if the masquerade is 06569 * still required. 06570 */ 06571 ast_channel_lock(original); 06572 06573 clonechan = original->masq; 06574 if (!clonechan) { 06575 /* 06576 * The masq is already completed by another thread or never 06577 * needed to be done to begin with. 06578 */ 06579 ast_channel_unlock(original); 06580 ao2_unlock(channels); 06581 return 0; 06582 } 06583 06584 /* Bump the refs to ensure that they won't dissapear on us. */ 06585 ast_channel_ref(original); 06586 ast_channel_ref(clonechan); 06587 06588 /* unlink from channels container as name (which is the hash value) will change */ 06589 ao2_unlink(channels, original); 06590 ao2_unlink(channels, clonechan); 06591 06592 /* Get any transfer masquerade connected line exchange data. */ 06593 xfer_ds = ast_channel_datastore_find(original, &xfer_ds_info, NULL); 06594 if (xfer_ds) { 06595 ast_channel_datastore_remove(original, xfer_ds); 06596 xfer_colp = xfer_ds->data; 06597 } else { 06598 xfer_colp = NULL; 06599 } 06600 06601 /* 06602 * Stop any visible indication on the original channel so we can 06603 * transfer it to the clonechan taking the original's place. 06604 */ 06605 visible_indication = original->visible_indication; 06606 ast_channel_unlock(original); 06607 ast_indicate(original, -1); 06608 06609 /* 06610 * Release any hold on the transferee channel before going any 06611 * further with the masquerade. 06612 */ 06613 if (xfer_colp && xfer_colp->transferee_held) { 06614 ast_indicate(clonechan, AST_CONTROL_UNHOLD); 06615 } 06616 06617 /* Start the masquerade channel contents rearangement. */ 06618 ast_channel_lock_both(original, clonechan); 06619 06620 ast_debug(4, "Actually Masquerading %s(%d) into the structure of %s(%d)\n", 06621 clonechan->name, clonechan->_state, original->name, original->_state); 06622 06623 chans[0] = clonechan; 06624 chans[1] = original; 06625 ast_manager_event_multichan(EVENT_FLAG_CALL, "Masquerade", 2, chans, 06626 "Clone: %s\r\n" 06627 "CloneState: %s\r\n" 06628 "Original: %s\r\n" 06629 "OriginalState: %s\r\n", 06630 clonechan->name, ast_state2str(clonechan->_state), original->name, ast_state2str(original->_state)); 06631 06632 /* 06633 * Remember the original read/write formats. We turn off any 06634 * translation on either one 06635 */ 06636 rformat = original->readformat; 06637 wformat = original->writeformat; 06638 free_translation(clonechan); 06639 free_translation(original); 06640 06641 /* Save the current DTMF digit being sent if any. */ 06642 clone_sending_dtmf_digit = clonechan->sending_dtmf_digit; 06643 clone_sending_dtmf_tv = clonechan->sending_dtmf_tv; 06644 06645 /* Save the original name */ 06646 ast_copy_string(orig, original->name, sizeof(orig)); 06647 /* Save the new name */ 06648 ast_copy_string(newn, clonechan->name, sizeof(newn)); 06649 /* Create the masq name */ 06650 snprintf(masqn, sizeof(masqn), "%s<MASQ>", newn); 06651 06652 /* Mangle the name of the clone channel */ 06653 __ast_change_name_nolink(clonechan, masqn); 06654 06655 /* Copy the name from the clone channel */ 06656 __ast_change_name_nolink(original, newn); 06657 06658 /* share linked id's */ 06659 ast_channel_set_linkgroup(original, clonechan); 06660 06661 /* Swap the technologies */ 06662 t = original->tech; 06663 original->tech = clonechan->tech; 06664 clonechan->tech = t; 06665 06666 t_pvt = original->tech_pvt; 06667 original->tech_pvt = clonechan->tech_pvt; 06668 clonechan->tech_pvt = t_pvt; 06669 06670 /* Swap the cdrs */ 06671 cdr = original->cdr; 06672 original->cdr = clonechan->cdr; 06673 clonechan->cdr = cdr; 06674 06675 /* Swap the alertpipes */ 06676 for (i = 0; i < 2; i++) { 06677 x = original->alertpipe[i]; 06678 original->alertpipe[i] = clonechan->alertpipe[i]; 06679 clonechan->alertpipe[i] = x; 06680 } 06681 06682 /* 06683 * Swap the readq's. The end result should be this: 06684 * 06685 * 1) All frames should be on the new (original) channel. 06686 * 2) Any frames that were already on the new channel before this 06687 * masquerade need to be at the end of the readq, after all of the 06688 * frames on the old (clone) channel. 06689 * 3) The alertpipe needs to get poked for every frame that was already 06690 * on the new channel, since we are now using the alert pipe from the 06691 * old (clone) channel. 06692 */ 06693 { 06694 AST_LIST_HEAD_NOLOCK(, ast_frame) tmp_readq; 06695 06696 AST_LIST_HEAD_INIT_NOLOCK(&tmp_readq); 06697 AST_LIST_APPEND_LIST(&tmp_readq, &original->readq, frame_list); 06698 AST_LIST_APPEND_LIST(&original->readq, &clonechan->readq, frame_list); 06699 06700 while ((current = AST_LIST_REMOVE_HEAD(&tmp_readq, frame_list))) { 06701 AST_LIST_INSERT_TAIL(&original->readq, current, frame_list); 06702 if (original->alertpipe[1] > -1) { 06703 int poke = 0; 06704 06705 if (write(original->alertpipe[1], &poke, sizeof(poke)) < 0) { 06706 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 06707 } 06708 } 06709 } 06710 } 06711 06712 /* Swap the raw formats */ 06713 tmp_format = original->rawreadformat; 06714 original->rawreadformat = clonechan->rawreadformat; 06715 clonechan->rawreadformat = tmp_format; 06716 06717 tmp_format = original->rawwriteformat; 06718 original->rawwriteformat = clonechan->rawwriteformat; 06719 clonechan->rawwriteformat = tmp_format; 06720 06721 clonechan->_softhangup = AST_SOFTHANGUP_DEV; 06722 06723 /* And of course, so does our current state. Note we need not 06724 call ast_setstate since the event manager doesn't really consider 06725 these separate. We do this early so that the clone has the proper 06726 state of the original channel. */ 06727 origstate = original->_state; 06728 original->_state = clonechan->_state; 06729 clonechan->_state = origstate; 06730 06731 /* Mangle the name of the clone channel */ 06732 snprintf(zombn, sizeof(zombn), "%s<ZOMBIE>", orig); /* quick, hide the brains! */ 06733 __ast_change_name_nolink(clonechan, zombn); 06734 06735 /* Update the type. */ 06736 t_pvt = original->monitor; 06737 original->monitor = clonechan->monitor; 06738 clonechan->monitor = t_pvt; 06739 06740 /* Keep the same language. */ 06741 ast_string_field_set(original, language, clonechan->language); 06742 06743 /* Keep the same parkinglot. */ 06744 ast_string_field_set(original, parkinglot, clonechan->parkinglot); 06745 06746 /* Copy the FD's other than the generator fd */ 06747 for (x = 0; x < AST_MAX_FDS; x++) { 06748 if (x != AST_GENERATOR_FD) 06749 ast_channel_set_fd(original, x, clonechan->fds[x]); 06750 } 06751 06752 ast_app_group_update(clonechan, original); 06753 06754 /* Move data stores over */ 06755 if (AST_LIST_FIRST(&clonechan->datastores)) { 06756 struct ast_datastore *ds; 06757 /* We use a safe traversal here because some fixup routines actually 06758 * remove the datastore from the list and free them. 06759 */ 06760 AST_LIST_TRAVERSE_SAFE_BEGIN(&clonechan->datastores, ds, entry) { 06761 if (ds->info->chan_fixup) 06762 ds->info->chan_fixup(ds->data, clonechan, original); 06763 } 06764 AST_LIST_TRAVERSE_SAFE_END; 06765 AST_LIST_APPEND_LIST(&original->datastores, &clonechan->datastores, entry); 06766 } 06767 06768 ast_autochan_new_channel(clonechan, original); 06769 06770 clone_variables(original, clonechan); 06771 /* Presense of ADSI capable CPE follows clone */ 06772 original->adsicpe = clonechan->adsicpe; 06773 /* Bridge remains the same */ 06774 /* CDR fields remain the same */ 06775 /* XXX What about blocking, softhangup, blocker, and lock and blockproc? XXX */ 06776 /* Application and data remain the same */ 06777 /* Clone exception becomes real one, as with fdno */ 06778 ast_set_flag(original, ast_test_flag(clonechan, AST_FLAG_EXCEPTION | AST_FLAG_OUTGOING)); 06779 original->fdno = clonechan->fdno; 06780 /* Schedule context remains the same */ 06781 /* Stream stuff stays the same */ 06782 /* Keep the original state. The fixup code will need to work with it most likely */ 06783 06784 /* 06785 * Just swap the whole structures, nevermind the allocations, 06786 * they'll work themselves out. 06787 */ 06788 exchange.dialed = original->dialed; 06789 original->dialed = clonechan->dialed; 06790 clonechan->dialed = exchange.dialed; 06791 06792 exchange.caller = original->caller; 06793 original->caller = clonechan->caller; 06794 clonechan->caller = exchange.caller; 06795 06796 exchange.connected = original->connected; 06797 original->connected = clonechan->connected; 06798 clonechan->connected = exchange.connected; 06799 06800 exchange.redirecting = original->redirecting; 06801 original->redirecting = clonechan->redirecting; 06802 clonechan->redirecting = exchange.redirecting; 06803 06804 report_new_callerid(original); 06805 06806 /* Restore original timing file descriptor */ 06807 ast_channel_set_fd(original, AST_TIMING_FD, original->timingfd); 06808 06809 /* Our native formats are different now */ 06810 original->nativeformats = clonechan->nativeformats; 06811 06812 /* Context, extension, priority, app data, jump table, remain the same */ 06813 /* pvt switches. pbx stays the same, as does next */ 06814 06815 /* Set the write format */ 06816 ast_set_write_format(original, wformat); 06817 06818 /* Set the read format */ 06819 ast_set_read_format(original, rformat); 06820 06821 /* Copy the music class */ 06822 ast_string_field_set(original, musicclass, clonechan->musicclass); 06823 06824 /* copy over accuntcode and set peeraccount across the bridge */ 06825 ast_string_field_set(original, accountcode, S_OR(clonechan->accountcode, "")); 06826 if (original->_bridge) { 06827 /* XXX - should we try to lock original->_bridge here? */ 06828 ast_string_field_set(original->_bridge, peeraccount, S_OR(clonechan->accountcode, "")); 06829 ast_cel_report_event(original, AST_CEL_BRIDGE_UPDATE, NULL, NULL, NULL); 06830 } 06831 06832 ast_debug(1, "Putting channel %s in %s/%s formats\n", original->name, 06833 ast_getformatname(wformat), ast_getformatname(rformat)); 06834 06835 /* Fixup the original clonechan's physical side */ 06836 if (original->tech->fixup && original->tech->fixup(clonechan, original)) { 06837 ast_log(LOG_WARNING, "Channel type '%s' could not fixup channel %s, strange things may happen. (clonechan)\n", 06838 original->tech->type, original->name); 06839 } 06840 06841 /* Fixup the original original's physical side */ 06842 if (clonechan->tech->fixup && clonechan->tech->fixup(original, clonechan)) { 06843 ast_log(LOG_WARNING, "Channel type '%s' could not fixup channel %s, strange things may happen. (original)\n", 06844 clonechan->tech->type, clonechan->name); 06845 } 06846 06847 /* 06848 * Now, at this point, the "clone" channel is totally F'd up. 06849 * We mark it as a zombie so nothing tries to touch it. If it's 06850 * already been marked as a zombie, then we must free it (since 06851 * it already is considered invalid). 06852 * 06853 * This must be done before we unlock clonechan to prevent 06854 * setting up another masquerade on the clonechan. 06855 */ 06856 if (ast_test_flag(clonechan, AST_FLAG_ZOMBIE)) { 06857 clone_was_zombie = 1; 06858 } else { 06859 ast_set_flag(clonechan, AST_FLAG_ZOMBIE); 06860 ast_queue_frame(clonechan, &ast_null_frame); 06861 } 06862 06863 /* clear the masquerade channels */ 06864 original->masq = NULL; 06865 clonechan->masqr = NULL; 06866 06867 /* 06868 * When we unlock original here, it can be immediately setup to 06869 * masquerade again or hungup. The new masquerade or hangup 06870 * will not actually happen until we release the channels 06871 * container lock. 06872 */ 06873 ast_channel_unlock(original); 06874 06875 /* Disconnect the original original's physical side */ 06876 if (clonechan->tech->hangup && clonechan->tech->hangup(clonechan)) { 06877 ast_log(LOG_WARNING, "Hangup failed! Strange things may happen!\n"); 06878 } else { 06879 /* 06880 * We just hung up the original original's physical side of the 06881 * channel. Set the new zombie to use the kill channel driver 06882 * for safety. 06883 */ 06884 clonechan->tech = &ast_kill_tech; 06885 } 06886 06887 ast_channel_unlock(clonechan); 06888 06889 if (clone_sending_dtmf_digit) { 06890 /* 06891 * The clonechan was sending a DTMF digit that was not completed 06892 * before the masquerade. 06893 */ 06894 ast_bridge_end_dtmf(original, clone_sending_dtmf_digit, clone_sending_dtmf_tv, 06895 "masquerade"); 06896 } 06897 06898 /* 06899 * If an indication is currently playing, maintain it on the 06900 * channel that is taking the place of original. 06901 * 06902 * This is needed because the masquerade is swapping out the 06903 * internals of the channel, and the new channel private data 06904 * needs to be made aware of the current visible indication 06905 * (RINGING, CONGESTION, etc.) 06906 */ 06907 if (visible_indication) { 06908 ast_indicate(original, visible_indication); 06909 } 06910 06911 ast_channel_lock(original); 06912 06913 /* Signal any blocker */ 06914 if (ast_test_flag(original, AST_FLAG_BLOCKING)) { 06915 pthread_kill(original->blocker, SIGURG); 06916 } 06917 06918 ast_debug(1, "Done Masquerading %s (%d)\n", original->name, original->_state); 06919 06920 if ((bridged = ast_bridged_channel(original))) { 06921 ast_channel_ref(bridged); 06922 ast_channel_unlock(original); 06923 ast_indicate(bridged, AST_CONTROL_SRCCHANGE); 06924 ast_channel_unref(bridged); 06925 } else { 06926 ast_channel_unlock(original); 06927 } 06928 ast_indicate(original, AST_CONTROL_SRCCHANGE); 06929 06930 if (xfer_colp) { 06931 /* 06932 * After the masquerade, the original channel pointer actually 06933 * points to the new transferee channel and the bridged channel 06934 * is still the intended transfer target party. 06935 */ 06936 masquerade_colp_transfer(original, xfer_colp); 06937 } 06938 06939 if (xfer_ds) { 06940 ast_datastore_free(xfer_ds); 06941 } 06942 06943 if (clone_was_zombie) { 06944 ast_channel_lock(clonechan); 06945 ast_debug(1, "Destroying channel clone '%s'\n", clonechan->name); 06946 ast_manager_event(clonechan, EVENT_FLAG_CALL, "Hangup", 06947 "Channel: %s\r\n" 06948 "Uniqueid: %s\r\n" 06949 "Cause: %d\r\n" 06950 "Cause-txt: %s\r\n", 06951 clonechan->name, 06952 clonechan->uniqueid, 06953 clonechan->hangupcause, 06954 ast_cause2str(clonechan->hangupcause) 06955 ); 06956 ast_channel_unlock(clonechan); 06957 06958 /* 06959 * Drop the system reference to destroy the channel since it is 06960 * already unlinked. 06961 */ 06962 ast_channel_unref(clonechan); 06963 } else { 06964 ao2_link(channels, clonechan); 06965 } 06966 06967 ao2_link(channels, original); 06968 ao2_unlock(channels); 06969 06970 /* Release our held safety references. */ 06971 ast_channel_unref(original); 06972 ast_channel_unref(clonechan); 06973 06974 return 0; 06975 }
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 7129 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().
07132 { 07133 /* Copy voice back and forth between the two channels. */ 07134 struct ast_channel *cs[3]; 07135 struct ast_frame *f; 07136 enum ast_bridge_result res = AST_BRIDGE_COMPLETE; 07137 format_t o0nativeformats; 07138 format_t o1nativeformats; 07139 int watch_c0_dtmf; 07140 int watch_c1_dtmf; 07141 void *pvt0, *pvt1; 07142 /* Indicates whether a frame was queued into a jitterbuffer */ 07143 int frame_put_in_jb = 0; 07144 int jb_in_use; 07145 int to; 07146 07147 cs[0] = c0; 07148 cs[1] = c1; 07149 pvt0 = c0->tech_pvt; 07150 pvt1 = c1->tech_pvt; 07151 o0nativeformats = c0->nativeformats; 07152 o1nativeformats = c1->nativeformats; 07153 watch_c0_dtmf = config->flags & AST_BRIDGE_DTMF_CHANNEL_0; 07154 watch_c1_dtmf = config->flags & AST_BRIDGE_DTMF_CHANNEL_1; 07155 07156 /* Check the need of a jitterbuffer for each channel */ 07157 jb_in_use = ast_jb_do_usecheck(c0, c1); 07158 if (jb_in_use) 07159 ast_jb_empty_and_reset(c0, c1); 07160 07161 ast_poll_channel_add(c0, c1); 07162 07163 if (config->feature_timer > 0 && ast_tvzero(config->nexteventts)) { 07164 /* nexteventts is not set when the bridge is not scheduled to 07165 * break, so calculate when the bridge should possibly break 07166 * if a partial feature match timed out */ 07167 config->nexteventts = ast_tvadd(ast_tvnow(), ast_samp2tv(config->feature_timer, 1000)); 07168 } 07169 07170 for (;;) { 07171 struct ast_channel *who, *other; 07172 07173 if ((c0->tech_pvt != pvt0) || (c1->tech_pvt != pvt1) || 07174 (o0nativeformats != c0->nativeformats) || 07175 (o1nativeformats != c1->nativeformats)) { 07176 /* Check for Masquerade, codec changes, etc */ 07177 res = AST_BRIDGE_RETRY; 07178 break; 07179 } 07180 if (config->nexteventts.tv_sec) { 07181 to = ast_tvdiff_ms(config->nexteventts, ast_tvnow()); 07182 if (to <= 0) { 07183 if (config->timelimit && !config->feature_timer && !ast_test_flag(config, AST_FEATURE_WARNING_ACTIVE)) { 07184 res = AST_BRIDGE_RETRY; 07185 /* generic bridge ending to play warning */ 07186 ast_set_flag(config, AST_FEATURE_WARNING_ACTIVE); 07187 } else if (config->feature_timer) { 07188 /* feature timer expired - make sure we do not play warning */ 07189 ast_clear_flag(config, AST_FEATURE_WARNING_ACTIVE); 07190 res = AST_BRIDGE_RETRY; 07191 } else { 07192 res = AST_BRIDGE_COMPLETE; 07193 } 07194 break; 07195 } 07196 } else { 07197 /* If a feature has been started and the bridge is configured to 07198 * to not break, leave the channel bridge when the feature timer 07199 * time has elapsed so the DTMF will be sent to the other side. 07200 */ 07201 if (!ast_tvzero(config->nexteventts)) { 07202 int diff = ast_tvdiff_ms(config->nexteventts, ast_tvnow()); 07203 if (diff <= 0) { 07204 res = AST_BRIDGE_RETRY; 07205 break; 07206 } 07207 } 07208 to = -1; 07209 } 07210 /* Calculate the appropriate max sleep interval - in general, this is the time, 07211 left to the closest jb delivery moment */ 07212 if (jb_in_use) 07213 to = ast_jb_get_when_to_wakeup(c0, c1, to); 07214 who = ast_waitfor_n(cs, 2, &to); 07215 if (!who) { 07216 /* No frame received within the specified timeout - check if we have to deliver now */ 07217 if (jb_in_use) 07218 ast_jb_get_and_deliver(c0, c1); 07219 if ((c0->_softhangup | c1->_softhangup) & AST_SOFTHANGUP_UNBRIDGE) {/* Bit operators are intentional. */ 07220 if (c0->_softhangup & AST_SOFTHANGUP_UNBRIDGE) { 07221 ast_channel_clear_softhangup(c0, AST_SOFTHANGUP_UNBRIDGE); 07222 } 07223 if (c1->_softhangup & AST_SOFTHANGUP_UNBRIDGE) { 07224 ast_channel_clear_softhangup(c1, AST_SOFTHANGUP_UNBRIDGE); 07225 } 07226 ast_channel_lock_both(c0, c1); 07227 c0->_bridge = c1; 07228 c1->_bridge = c0; 07229 ast_channel_unlock(c0); 07230 ast_channel_unlock(c1); 07231 } 07232 continue; 07233 } 07234 f = ast_read(who); 07235 if (!f) { 07236 *fo = NULL; 07237 *rc = who; 07238 ast_debug(1, "Didn't get a frame from channel: %s\n",who->name); 07239 break; 07240 } 07241 07242 other = (who == c0) ? c1 : c0; /* the 'other' channel */ 07243 /* Try add the frame info the who's bridged channel jitterbuff */ 07244 if (jb_in_use) 07245 frame_put_in_jb = !ast_jb_put(other, f); 07246 07247 if ((f->frametype == AST_FRAME_CONTROL) && !(config->flags & AST_BRIDGE_IGNORE_SIGS)) { 07248 int bridge_exit = 0; 07249 07250 switch (f->subclass.integer) { 07251 case AST_CONTROL_AOC: 07252 ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen); 07253 break; 07254 case AST_CONTROL_REDIRECTING: 07255 if (ast_channel_redirecting_macro(who, other, f, other == c0, 1)) { 07256 ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen); 07257 } 07258 break; 07259 case AST_CONTROL_CONNECTED_LINE: 07260 if (ast_channel_connected_line_macro(who, other, f, other == c0, 1)) { 07261 ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen); 07262 } 07263 break; 07264 case AST_CONTROL_HOLD: 07265 case AST_CONTROL_UNHOLD: 07266 case AST_CONTROL_VIDUPDATE: 07267 case AST_CONTROL_SRCUPDATE: 07268 case AST_CONTROL_SRCCHANGE: 07269 case AST_CONTROL_T38_PARAMETERS: 07270 ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen); 07271 if (jb_in_use) { 07272 ast_jb_empty_and_reset(c0, c1); 07273 } 07274 break; 07275 default: 07276 *fo = f; 07277 *rc = who; 07278 bridge_exit = 1; 07279 ast_debug(1, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass.integer, who->name); 07280 break; 07281 } 07282 if (bridge_exit) 07283 break; 07284 } 07285 if ((f->frametype == AST_FRAME_VOICE) || 07286 (f->frametype == AST_FRAME_DTMF_BEGIN) || 07287 (f->frametype == AST_FRAME_DTMF) || 07288 (f->frametype == AST_FRAME_VIDEO) || 07289 (f->frametype == AST_FRAME_IMAGE) || 07290 (f->frametype == AST_FRAME_HTML) || 07291 (f->frametype == AST_FRAME_MODEM) || 07292 (f->frametype == AST_FRAME_TEXT)) { 07293 /* monitored dtmf causes exit from bridge */ 07294 int monitored_source = (who == c0) ? watch_c0_dtmf : watch_c1_dtmf; 07295 07296 if (monitored_source && 07297 (f->frametype == AST_FRAME_DTMF_END || 07298 f->frametype == AST_FRAME_DTMF_BEGIN)) { 07299 *fo = f; 07300 *rc = who; 07301 ast_debug(1, "Got DTMF %s on channel (%s)\n", 07302 f->frametype == AST_FRAME_DTMF_END ? "end" : "begin", 07303 who->name); 07304 07305 break; 07306 } 07307 /* Write immediately frames, not passed through jb */ 07308 if (!frame_put_in_jb) 07309 ast_write(other, f); 07310 07311 /* Check if we have to deliver now */ 07312 if (jb_in_use) 07313 ast_jb_get_and_deliver(c0, c1); 07314 } 07315 /* XXX do we want to pass on also frames not matched above ? */ 07316 ast_frfree(f); 07317 07318 #ifndef HAVE_EPOLL 07319 /* Swap who gets priority */ 07320 cs[2] = cs[0]; 07321 cs[0] = cs[1]; 07322 cs[1] = cs[2]; 07323 #endif 07324 } 07325 07326 ast_poll_channel_del(c0, c1); 07327 07328 return res; 07329 }
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 7908 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().
07909 { 07910 char *piece; 07911 char *c; 07912 int start=0, finish=0, x; 07913 ast_group_t group = 0; 07914 07915 if (ast_strlen_zero(s)) 07916 return 0; 07917 07918 c = ast_strdupa(s); 07919 07920 while ((piece = strsep(&c, ","))) { 07921 if (sscanf(piece, "%30d-%30d", &start, &finish) == 2) { 07922 /* Range */ 07923 } else if (sscanf(piece, "%30d", &start)) { 07924 /* Just one */ 07925 finish = start; 07926 } else { 07927 ast_log(LOG_ERROR, "Syntax error parsing group configuration '%s' at '%s'. Ignoring.\n", s, piece); 07928 continue; 07929 } 07930 for (x = start; x <= finish; x++) { 07931 if ((x > 63) || (x < 0)) { 07932 ast_log(LOG_WARNING, "Ignoring invalid group %d (maximum group is 63)\n", x); 07933 } else 07934 group |= ((ast_group_t) 1 << x); 07935 } 07936 } 07937 return group; 07938 }
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 4350 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().
04351 { 04352 return ast_indicate_data(chan, condition, NULL, 0); 04353 }
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 4404 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().
04406 { 04407 /* By using an enum, we'll get compiler warnings for values not handled 04408 * in switch statements. */ 04409 enum ast_control_frame_type condition = _condition; 04410 struct ast_tone_zone_sound *ts = NULL; 04411 int res; 04412 /* this frame is used by framehooks. if it is set, we must free it at the end of this function */ 04413 struct ast_frame *awesome_frame = NULL; 04414 04415 ast_channel_lock(chan); 04416 04417 /* Don't bother if the channel is about to go away, anyway. */ 04418 if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) { 04419 res = -1; 04420 goto indicate_cleanup; 04421 } 04422 04423 if (!ast_framehook_list_is_empty(chan->framehooks)) { 04424 /* Do framehooks now, do it, go, go now */ 04425 struct ast_frame frame = { 04426 .frametype = AST_FRAME_CONTROL, 04427 .subclass.integer = condition, 04428 .data.ptr = (void *) data, /* this cast from const is only okay because we do the ast_frdup below */ 04429 .datalen = datalen 04430 }; 04431 04432 /* we have now committed to freeing this frame */ 04433 awesome_frame = ast_frdup(&frame); 04434 04435 /* who knows what we will get back! the anticipation is killing me. */ 04436 if (!(awesome_frame = ast_framehook_list_write_event(chan->framehooks, awesome_frame)) 04437 || awesome_frame->frametype != AST_FRAME_CONTROL) { 04438 04439 res = 0; 04440 goto indicate_cleanup; 04441 } 04442 04443 condition = awesome_frame->subclass.integer; 04444 data = awesome_frame->data.ptr; 04445 datalen = awesome_frame->datalen; 04446 } 04447 04448 switch (condition) { 04449 case AST_CONTROL_CONNECTED_LINE: 04450 { 04451 struct ast_party_connected_line connected; 04452 04453 ast_party_connected_line_set_init(&connected, &chan->connected); 04454 res = ast_connected_line_parse_data(data, datalen, &connected); 04455 if (!res) { 04456 ast_channel_set_connected_line(chan, &connected, NULL); 04457 } 04458 ast_party_connected_line_free(&connected); 04459 } 04460 break; 04461 04462 case AST_CONTROL_REDIRECTING: 04463 { 04464 struct ast_party_redirecting redirecting; 04465 04466 ast_party_redirecting_set_init(&redirecting, &chan->redirecting); 04467 res = ast_redirecting_parse_data(data, datalen, &redirecting); 04468 if (!res) { 04469 ast_channel_set_redirecting(chan, &redirecting, NULL); 04470 } 04471 ast_party_redirecting_free(&redirecting); 04472 } 04473 break; 04474 04475 default: 04476 break; 04477 } 04478 04479 if (is_visible_indication(condition)) { 04480 /* A new visible indication is requested. */ 04481 chan->visible_indication = condition; 04482 } else if (condition == AST_CONTROL_UNHOLD || _condition < 0) { 04483 /* Visible indication is cleared/stopped. */ 04484 chan->visible_indication = 0; 04485 } 04486 04487 if (chan->tech->indicate) { 04488 /* See if the channel driver can handle this condition. */ 04489 res = chan->tech->indicate(chan, condition, data, datalen); 04490 } else { 04491 res = -1; 04492 } 04493 04494 if (!res) { 04495 /* The channel driver successfully handled this indication */ 04496 res = 0; 04497 goto indicate_cleanup; 04498 } 04499 04500 /* The channel driver does not support this indication, let's fake 04501 * it by doing our own tone generation if applicable. */ 04502 04503 /*!\note If we compare the enumeration type, which does not have any 04504 * negative constants, the compiler may optimize this code away. 04505 * Therefore, we must perform an integer comparison here. */ 04506 if (_condition < 0) { 04507 /* Stop any tones that are playing */ 04508 ast_playtones_stop(chan); 04509 res = 0; 04510 goto indicate_cleanup; 04511 } 04512 04513 /* Handle conditions that we have tones for. */ 04514 switch (condition) { 04515 case _XXX_AST_CONTROL_T38: 04516 /* deprecated T.38 control frame */ 04517 res = -1; 04518 goto indicate_cleanup; 04519 case AST_CONTROL_T38_PARAMETERS: 04520 /* there is no way to provide 'default' behavior for these 04521 * control frames, so we need to return failure, but there 04522 * is also no value in the log message below being emitted 04523 * since failure to handle these frames is not an 'error' 04524 * so just return right now. in addition, we want to return 04525 * whatever value the channel driver returned, in case it 04526 * has some meaning.*/ 04527 goto indicate_cleanup; 04528 case AST_CONTROL_RINGING: 04529 ts = ast_get_indication_tone(chan->zone, "ring"); 04530 /* It is common practice for channel drivers to return -1 if trying 04531 * to indicate ringing on a channel which is up. The idea is to let the 04532 * core generate the ringing inband. However, we don't want the 04533 * warning message about not being able to handle the specific indication 04534 * to print nor do we want ast_indicate_data to return an "error" for this 04535 * condition 04536 */ 04537 if (chan->_state == AST_STATE_UP) { 04538 res = 0; 04539 } 04540 break; 04541 case AST_CONTROL_BUSY: 04542 ts = ast_get_indication_tone(chan->zone, "busy"); 04543 break; 04544 case AST_CONTROL_INCOMPLETE: 04545 case AST_CONTROL_CONGESTION: 04546 ts = ast_get_indication_tone(chan->zone, "congestion"); 04547 break; 04548 case AST_CONTROL_PROGRESS: 04549 case AST_CONTROL_PROCEEDING: 04550 case AST_CONTROL_VIDUPDATE: 04551 case AST_CONTROL_SRCUPDATE: 04552 case AST_CONTROL_SRCCHANGE: 04553 case AST_CONTROL_RADIO_KEY: 04554 case AST_CONTROL_RADIO_UNKEY: 04555 case AST_CONTROL_OPTION: 04556 case AST_CONTROL_WINK: 04557 case AST_CONTROL_FLASH: 04558 case AST_CONTROL_OFFHOOK: 04559 case AST_CONTROL_TAKEOFFHOOK: 04560 case AST_CONTROL_ANSWER: 04561 case AST_CONTROL_HANGUP: 04562 case AST_CONTROL_RING: 04563 case AST_CONTROL_HOLD: 04564 case AST_CONTROL_UNHOLD: 04565 case AST_CONTROL_TRANSFER: 04566 case AST_CONTROL_CONNECTED_LINE: 04567 case AST_CONTROL_REDIRECTING: 04568 case AST_CONTROL_CC: 04569 case AST_CONTROL_READ_ACTION: 04570 case AST_CONTROL_AOC: 04571 case AST_CONTROL_END_OF_Q: 04572 case AST_CONTROL_UPDATE_RTP_PEER: 04573 /* Nothing left to do for these. */ 04574 res = 0; 04575 break; 04576 } 04577 04578 if (ts) { 04579 /* We have a tone to play, yay. */ 04580 ast_debug(1, "Driver for channel '%s' does not support indication %d, emulating it\n", chan->name, condition); 04581 res = ast_playtones_start(chan, 0, ts->data, 1); 04582 ts = ast_tone_zone_sound_unref(ts); 04583 } 04584 04585 if (res) { 04586 /* not handled */ 04587 ast_log(LOG_WARNING, "Unable to handle indication %d for '%s'\n", condition, chan->name); 04588 } 04589 04590 indicate_cleanup: 04591 ast_channel_unlock(chan); 04592 if (awesome_frame) { 04593 ast_frfree(awesome_frame); 04594 } 04595 04596 return res; 04597 }
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 7944 of file channel.c.
References ast_moh_cleanup_ptr, ast_moh_start_ptr, and ast_moh_stop_ptr.
Referenced by load_module(), and reload().
07947 { 07948 ast_moh_start_ptr = start_ptr; 07949 ast_moh_stop_ptr = stop_ptr; 07950 ast_moh_cleanup_ptr = cleanup_ptr; 07951 }
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 4335 of file channel.c.
References ast_opt_internal_timing, and ast_channel::timingfd.
Referenced by add_sdp(), and ast_read_generator_actions().
04336 { 04337 return (ast_opt_internal_timing && chan->timingfd > -1); 04338 }
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 7978 of file channel.c.
References ast_moh_cleanup_ptr.
Referenced by ast_channel_destructor().
07979 { 07980 if (ast_moh_cleanup_ptr) 07981 ast_moh_cleanup_ptr(chan); 07982 }
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 7961 of file channel.c.
References ast_moh_start_ptr, and ast_verb.
Referenced by alsa_indicate(), app_exec(), 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().
07962 { 07963 if (ast_moh_start_ptr) 07964 return ast_moh_start_ptr(chan, mclass, interpclass); 07965 07966 ast_verb(3, "Music class %s requested but no musiconhold loaded.\n", mclass ? mclass : (interpclass ? interpclass : "default")); 07967 07968 return 0; 07969 }
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 7972 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().
07973 { 07974 if (ast_moh_stop_ptr) 07975 ast_moh_stop_ptr(chan); 07976 }
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 7997 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().
07998 { 07999 struct ast_variable *var; 08000 struct ast_flags config_flags = { 0 }; 08001 struct ast_config *cfg = ast_config_load("codecs.conf", config_flags); 08002 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) 08003 return 0; 08004 for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) { 08005 if (!strcasecmp(var->name, "genericplc")) { 08006 ast_set2_flag(&ast_options, ast_true(var->value), AST_OPT_FLAG_GENERIC_PLC); 08007 } 08008 } 08009 ast_config_destroy(cfg); 08010 return 0; 08011 }
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 8157 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().
08158 { 08159 unsigned int i; 08160 int first = 1; 08161 char num[3]; 08162 08163 buf[0] = '\0'; 08164 08165 if (!group) /* Return empty string if no group */ 08166 return buf; 08167 08168 for (i = 0; i <= 63; i++) { /* Max group is 63 */ 08169 if (group & ((ast_group_t) 1 << i)) { 08170 if (!first) { 08171 strncat(buf, ", ", buflen - strlen(buf) - 1); 08172 } else { 08173 first = 0; 08174 } 08175 snprintf(num, sizeof(num), "%u", i); 08176 strncat(buf, num, buflen - strlen(buf) - 1); 08177 } 08178 } 08179 return buf; 08180 }
int ast_prod | ( | struct ast_channel * | chan | ) |
Send empty audio to prime a channel driver.
Definition at line 4741 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().
04742 { 04743 struct ast_frame a = { AST_FRAME_VOICE }; 04744 char nothing[128]; 04745 04746 /* Send an empty audio frame to get things moving */ 04747 if (chan->_state != AST_STATE_UP) { 04748 ast_debug(1, "Prodding channel '%s'\n", chan->name); 04749 a.subclass.codec = chan->rawwriteformat; 04750 a.data.ptr = nothing + AST_FRIENDLY_OFFSET; 04751 a.src = "ast_prod"; /* this better match check in ast_write */ 04752 if (ast_write(chan, &a)) 04753 ast_log(LOG_WARNING, "Prodding channel '%s' failed\n", chan->name); 04754 } 04755 return 0; 04756 }
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(), 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 4340 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().
04341 { 04342 return __ast_read(chan, 0); 04343 }
static void ast_read_generator_actions | ( | struct ast_channel * | chan, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 3695 of file channel.c.
References ast_channel_lock, ast_channel_unlock, ast_deactivate_generator(), ast_debug, ast_format_rate(), AST_FRAME_CNG, ast_internal_timing_enabled(), ast_settimeout(), ast_frame_subclass::codec, ast_frame::datalen, ast_frame::frametype, ast_generator::generate, ast_channel::generator, generator_force(), ast_channel::generatordata, ast_frame::samples, ast_frame::subclass, ast_channel::timingfd, ast_channel::timingfunc, and ast_channel::writeformat.
Referenced by __ast_read().
03696 { 03697 if (chan->generator && chan->generator->generate && chan->generatordata && !ast_internal_timing_enabled(chan)) { 03698 void *tmp = chan->generatordata; 03699 int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples) = chan->generator->generate; 03700 int res; 03701 int samples; 03702 03703 if (chan->timingfunc) { 03704 ast_debug(1, "Generator got voice, switching to phase locked mode\n"); 03705 ast_settimeout(chan, 0, NULL, NULL); 03706 } 03707 03708 chan->generatordata = NULL; /* reset, to let writes go through */ 03709 03710 if (f->subclass.codec != chan->writeformat) { 03711 float factor; 03712 factor = ((float) ast_format_rate(chan->writeformat)) / ((float) ast_format_rate(f->subclass.codec)); 03713 samples = (int) ( ((float) f->samples) * factor ); 03714 } else { 03715 samples = f->samples; 03716 } 03717 03718 /* This unlock is here based on two assumptions that hold true at this point in the 03719 * code. 1) this function is only called from within __ast_read() and 2) all generators 03720 * call ast_write() in their generate callback. 03721 * 03722 * The reason this is added is so that when ast_write is called, the lock that occurs 03723 * there will not recursively lock the channel. Doing this will cause intended deadlock 03724 * avoidance not to work in deeper functions 03725 */ 03726 ast_channel_unlock(chan); 03727 res = generate(chan, tmp, f->datalen, samples); 03728 ast_channel_lock(chan); 03729 chan->generatordata = tmp; 03730 if (res) { 03731 ast_debug(1, "Auto-deactivating generator\n"); 03732 ast_deactivate_generator(chan); 03733 } 03734 03735 } else if (f->frametype == AST_FRAME_CNG) { 03736 if (chan->generator && !chan->timingfunc && (chan->timingfd > -1)) { 03737 ast_debug(1, "Generator got CNG, switching to timed mode\n"); 03738 ast_settimeout(chan, 50, generator_force, chan); 03739 } 03740 } 03741 }
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 4345 of file channel.c.
References __ast_read().
Referenced by ast_bridge_handle_trip(), and conf_run().
04346 { 04347 return __ast_read(chan, 1); 04348 }
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 5794 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().
05795 { 05796 return ast_readstring_full(c, s, len, timeout, ftimeout, enders, -1, -1); 05797 }
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 5799 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().
05800 { 05801 int pos = 0; /* index in the buffer where we accumulate digits */ 05802 int to = ftimeout; 05803 05804 struct ast_silence_generator *silgen = NULL; 05805 05806 /* Stop if we're a zombie or need a soft hangup */ 05807 if (ast_test_flag(c, AST_FLAG_ZOMBIE) || ast_check_hangup(c)) 05808 return -1; 05809 if (!len) 05810 return -1; 05811 for (;;) { 05812 int d; 05813 if (c->stream) { 05814 d = ast_waitstream_full(c, AST_DIGIT_ANY, audiofd, ctrlfd); 05815 ast_stopstream(c); 05816 if (!silgen && ast_opt_transmit_silence) 05817 silgen = ast_channel_start_silence_generator(c); 05818 usleep(1000); 05819 if (!d) 05820 d = ast_waitfordigit_full(c, to, audiofd, ctrlfd); 05821 } else { 05822 if (!silgen && ast_opt_transmit_silence) 05823 silgen = ast_channel_start_silence_generator(c); 05824 d = ast_waitfordigit_full(c, to, audiofd, ctrlfd); 05825 } 05826 if (d < 0) { 05827 ast_channel_stop_silence_generator(c, silgen); 05828 return AST_GETDATA_FAILED; 05829 } 05830 if (d == 0) { 05831 s[pos] = '\0'; 05832 ast_channel_stop_silence_generator(c, silgen); 05833 return AST_GETDATA_TIMEOUT; 05834 } 05835 if (d == 1) { 05836 s[pos] = '\0'; 05837 ast_channel_stop_silence_generator(c, silgen); 05838 return AST_GETDATA_INTERRUPTED; 05839 } 05840 if (strchr(enders, d) && (pos == 0)) { 05841 s[pos] = '\0'; 05842 ast_channel_stop_silence_generator(c, silgen); 05843 return AST_GETDATA_EMPTY_END_TERMINATED; 05844 } 05845 if (!strchr(enders, d)) { 05846 s[pos++] = d; 05847 } 05848 if (strchr(enders, d) || (pos >= len)) { 05849 s[pos] = '\0'; 05850 ast_channel_stop_silence_generator(c, silgen); 05851 return AST_GETDATA_COMPLETE; 05852 } 05853 to = timeout; 05854 } 05855 /* Never reached */ 05856 return 0; 05857 }
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 4599 of file channel.c.
References ast_free, and ast_recvtext().
Referenced by handle_recvchar().
04600 { 04601 int c; 04602 char *buf = ast_recvtext(chan, timeout); 04603 if (buf == NULL) 04604 return -1; /* error or timeout */ 04605 c = *(unsigned char *)buf; 04606 ast_free(buf); 04607 return c; 04608 }
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 4610 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().
04611 { 04612 int res; 04613 char *buf = NULL; 04614 struct timeval start = ast_tvnow(); 04615 int ms; 04616 04617 while ((ms = ast_remaining_ms(start, timeout))) { 04618 struct ast_frame *f; 04619 04620 if (ast_check_hangup(chan)) { 04621 break; 04622 } 04623 res = ast_waitfor(chan, ms); 04624 if (res <= 0) {/* timeout or error */ 04625 break; 04626 } 04627 f = ast_read(chan); 04628 if (f == NULL) { 04629 break; /* no frame */ 04630 } 04631 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) { 04632 ast_frfree(f); 04633 break; 04634 } else if (f->frametype == AST_FRAME_TEXT) { /* what we want */ 04635 buf = ast_strndup((char *) f->data.ptr, f->datalen); /* dup and break */ 04636 ast_frfree(f); 04637 break; 04638 } 04639 ast_frfree(f); 04640 } 04641 return buf; 04642 }
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 9087 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().
09088 { 09089 int32_t value; 09090 size_t pos = 0; 09091 int res; 09092 09093 static const struct ast_party_id_ies from_ies = { 09094 .name.str = AST_REDIRECTING_FROM_NAME, 09095 .name.char_set = AST_REDIRECTING_FROM_NAME_CHAR_SET, 09096 .name.presentation = AST_REDIRECTING_FROM_NAME_PRESENTATION, 09097 .name.valid = AST_REDIRECTING_FROM_NAME_VALID, 09098 09099 .number.str = AST_REDIRECTING_FROM_NUMBER, 09100 .number.plan = AST_REDIRECTING_FROM_NUMBER_PLAN, 09101 .number.presentation = AST_REDIRECTING_FROM_NUMBER_PRESENTATION, 09102 .number.valid = AST_REDIRECTING_FROM_NUMBER_VALID, 09103 09104 .subaddress.str = AST_REDIRECTING_FROM_SUBADDRESS, 09105 .subaddress.type = AST_REDIRECTING_FROM_SUBADDRESS_TYPE, 09106 .subaddress.odd_even_indicator = AST_REDIRECTING_FROM_SUBADDRESS_ODD_EVEN, 09107 .subaddress.valid = AST_REDIRECTING_FROM_SUBADDRESS_VALID, 09108 09109 .tag = AST_REDIRECTING_FROM_TAG, 09110 .combined_presentation = AST_REDIRECTING_FROM_ID_PRESENTATION, 09111 }; 09112 static const struct ast_party_id_ies to_ies = { 09113 .name.str = AST_REDIRECTING_TO_NAME, 09114 .name.char_set = AST_REDIRECTING_TO_NAME_CHAR_SET, 09115 .name.presentation = AST_REDIRECTING_TO_NAME_PRESENTATION, 09116 .name.valid = AST_REDIRECTING_TO_NAME_VALID, 09117 09118 .number.str = AST_REDIRECTING_TO_NUMBER, 09119 .number.plan = AST_REDIRECTING_TO_NUMBER_PLAN, 09120 .number.presentation = AST_REDIRECTING_TO_NUMBER_PRESENTATION, 09121 .number.valid = AST_REDIRECTING_TO_NUMBER_VALID, 09122 09123 .subaddress.str = AST_REDIRECTING_TO_SUBADDRESS, 09124 .subaddress.type = AST_REDIRECTING_TO_SUBADDRESS_TYPE, 09125 .subaddress.odd_even_indicator = AST_REDIRECTING_TO_SUBADDRESS_ODD_EVEN, 09126 .subaddress.valid = AST_REDIRECTING_TO_SUBADDRESS_VALID, 09127 09128 .tag = AST_REDIRECTING_TO_TAG, 09129 .combined_presentation = AST_REDIRECTING_TO_ID_PRESENTATION, 09130 }; 09131 09132 /* Redirecting frame version */ 09133 if (datalen < pos + (sizeof(data[0]) * 2) + 1) { 09134 ast_log(LOG_WARNING, "No space left for redirecting frame version\n"); 09135 return -1; 09136 } 09137 data[pos++] = AST_REDIRECTING_VERSION; 09138 data[pos++] = 1; 09139 data[pos++] = 2;/* Version 1 did not have a version ie */ 09140 09141 res = party_id_build_data(data + pos, datalen - pos, &redirecting->from, 09142 "redirecting-from", &from_ies, update ? &update->from : NULL); 09143 if (res < 0) { 09144 return -1; 09145 } 09146 pos += res; 09147 09148 res = party_id_build_data(data + pos, datalen - pos, &redirecting->to, 09149 "redirecting-to", &to_ies, update ? &update->to : NULL); 09150 if (res < 0) { 09151 return -1; 09152 } 09153 pos += res; 09154 09155 /* Redirecting reason */ 09156 if (datalen < pos + (sizeof(data[0]) * 2) + sizeof(value)) { 09157 ast_log(LOG_WARNING, "No space left for redirecting reason\n"); 09158 return -1; 09159 } 09160 data[pos++] = AST_REDIRECTING_REASON; 09161 data[pos++] = sizeof(value); 09162 value = htonl(redirecting->reason); 09163 memcpy(data + pos, &value, sizeof(value)); 09164 pos += sizeof(value); 09165 09166 /* Redirecting count */ 09167 if (datalen < pos + (sizeof(data[0]) * 2) + sizeof(value)) { 09168 ast_log(LOG_WARNING, "No space left for redirecting count\n"); 09169 return -1; 09170 } 09171 data[pos++] = AST_REDIRECTING_COUNT; 09172 data[pos++] = sizeof(value); 09173 value = htonl(redirecting->count); 09174 memcpy(data + pos, &value, sizeof(value)); 09175 pos += sizeof(value); 09176 09177 return pos; 09178 }
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 9180 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().
09181 { 09182 size_t pos; 09183 unsigned char ie_len; 09184 unsigned char ie_id; 09185 int32_t value; 09186 int frame_version = 1; 09187 int from_combined_presentation = 0; 09188 int got_from_combined_presentation = 0;/* TRUE if got a combined name and number presentation value. */ 09189 int to_combined_presentation = 0; 09190 int got_to_combined_presentation = 0;/* TRUE if got a combined name and number presentation value. */ 09191 09192 for (pos = 0; pos < datalen; pos += ie_len) { 09193 if (datalen < pos + sizeof(ie_id) + sizeof(ie_len)) { 09194 ast_log(LOG_WARNING, "Invalid redirecting update\n"); 09195 return -1; 09196 } 09197 ie_id = data[pos++]; 09198 ie_len = data[pos++]; 09199 if (datalen < pos + ie_len) { 09200 ast_log(LOG_WARNING, "Invalid redirecting update\n"); 09201 return -1; 09202 } 09203 09204 switch (ie_id) { 09205 /* Redirecting frame version */ 09206 case AST_REDIRECTING_VERSION: 09207 if (ie_len != 1) { 09208 ast_log(LOG_WARNING, "Invalid redirecting frame version (%u)\n", 09209 (unsigned) ie_len); 09210 break; 09211 } 09212 frame_version = data[pos]; 09213 break; 09214 /* Redirecting-from party id name */ 09215 case AST_REDIRECTING_FROM_NAME: 09216 ast_free(redirecting->from.name.str); 09217 redirecting->from.name.str = ast_malloc(ie_len + 1); 09218 if (redirecting->from.name.str) { 09219 memcpy(redirecting->from.name.str, data + pos, ie_len); 09220 redirecting->from.name.str[ie_len] = 0; 09221 } 09222 break; 09223 case AST_REDIRECTING_FROM_NAME_CHAR_SET: 09224 if (ie_len != 1) { 09225 ast_log(LOG_WARNING, "Invalid redirecting-from name char set (%u)\n", 09226 (unsigned) ie_len); 09227 break; 09228 } 09229 redirecting->from.name.char_set = data[pos]; 09230 break; 09231 case AST_REDIRECTING_FROM_NAME_PRESENTATION: 09232 if (ie_len != 1) { 09233 ast_log(LOG_WARNING, "Invalid redirecting-from name presentation (%u)\n", 09234 (unsigned) ie_len); 09235 break; 09236 } 09237 redirecting->from.name.presentation = data[pos]; 09238 break; 09239 case AST_REDIRECTING_FROM_NAME_VALID: 09240 if (ie_len != 1) { 09241 ast_log(LOG_WARNING, "Invalid redirecting-from name valid (%u)\n", 09242 (unsigned) ie_len); 09243 break; 09244 } 09245 redirecting->from.name.valid = data[pos]; 09246 break; 09247 /* Redirecting-from party id number */ 09248 case AST_REDIRECTING_FROM_NUMBER: 09249 ast_free(redirecting->from.number.str); 09250 redirecting->from.number.str = ast_malloc(ie_len + 1); 09251 if (redirecting->from.number.str) { 09252 memcpy(redirecting->from.number.str, data + pos, ie_len); 09253 redirecting->from.number.str[ie_len] = 0; 09254 } 09255 break; 09256 case AST_REDIRECTING_FROM_NUMBER_PLAN: 09257 if (ie_len != 1) { 09258 ast_log(LOG_WARNING, "Invalid redirecting-from numbering plan (%u)\n", 09259 (unsigned) ie_len); 09260 break; 09261 } 09262 redirecting->from.number.plan = data[pos]; 09263 break; 09264 case AST_REDIRECTING_FROM_NUMBER_PRESENTATION: 09265 if (ie_len != 1) { 09266 ast_log(LOG_WARNING, "Invalid redirecting-from number presentation (%u)\n", 09267 (unsigned) ie_len); 09268 break; 09269 } 09270 redirecting->from.number.presentation = data[pos]; 09271 break; 09272 case AST_REDIRECTING_FROM_NUMBER_VALID: 09273 if (ie_len != 1) { 09274 ast_log(LOG_WARNING, "Invalid redirecting-from number valid (%u)\n", 09275 (unsigned) ie_len); 09276 break; 09277 } 09278 redirecting->from.number.valid = data[pos]; 09279 break; 09280 /* Redirecting-from party id combined presentation */ 09281 case AST_REDIRECTING_FROM_ID_PRESENTATION: 09282 if (ie_len != 1) { 09283 ast_log(LOG_WARNING, "Invalid redirecting-from combined presentation (%u)\n", 09284 (unsigned) ie_len); 09285 break; 09286 } 09287 from_combined_presentation = data[pos]; 09288 got_from_combined_presentation = 1; 09289 break; 09290 /* Redirecting-from party id subaddress */ 09291 case AST_REDIRECTING_FROM_SUBADDRESS: 09292 ast_free(redirecting->from.subaddress.str); 09293 redirecting->from.subaddress.str = ast_malloc(ie_len + 1); 09294 if (redirecting->from.subaddress.str) { 09295 memcpy(redirecting->from.subaddress.str, data + pos, ie_len); 09296 redirecting->from.subaddress.str[ie_len] = 0; 09297 } 09298 break; 09299 case AST_REDIRECTING_FROM_SUBADDRESS_TYPE: 09300 if (ie_len != 1) { 09301 ast_log(LOG_WARNING, "Invalid redirecting-from type of subaddress (%u)\n", 09302 (unsigned) ie_len); 09303 break; 09304 } 09305 redirecting->from.subaddress.type = data[pos]; 09306 break; 09307 case AST_REDIRECTING_FROM_SUBADDRESS_ODD_EVEN: 09308 if (ie_len != 1) { 09309 ast_log(LOG_WARNING, 09310 "Invalid redirecting-from subaddress odd-even indicator (%u)\n", 09311 (unsigned) ie_len); 09312 break; 09313 } 09314 redirecting->from.subaddress.odd_even_indicator = data[pos]; 09315 break; 09316 case AST_REDIRECTING_FROM_SUBADDRESS_VALID: 09317 if (ie_len != 1) { 09318 ast_log(LOG_WARNING, "Invalid redirecting-from subaddress valid (%u)\n", 09319 (unsigned) ie_len); 09320 break; 09321 } 09322 redirecting->from.subaddress.valid = data[pos]; 09323 break; 09324 /* Redirecting-from party id tag */ 09325 case AST_REDIRECTING_FROM_TAG: 09326 ast_free(redirecting->from.tag); 09327 redirecting->from.tag = ast_malloc(ie_len + 1); 09328 if (redirecting->from.tag) { 09329 memcpy(redirecting->from.tag, data + pos, ie_len); 09330 redirecting->from.tag[ie_len] = 0; 09331 } 09332 break; 09333 /* Redirecting-to party id name */ 09334 case AST_REDIRECTING_TO_NAME: 09335 ast_free(redirecting->to.name.str); 09336 redirecting->to.name.str = ast_malloc(ie_len + 1); 09337 if (redirecting->to.name.str) { 09338 memcpy(redirecting->to.name.str, data + pos, ie_len); 09339 redirecting->to.name.str[ie_len] = 0; 09340 } 09341 break; 09342 case AST_REDIRECTING_TO_NAME_CHAR_SET: 09343 if (ie_len != 1) { 09344 ast_log(LOG_WARNING, "Invalid redirecting-to name char set (%u)\n", 09345 (unsigned) ie_len); 09346 break; 09347 } 09348 redirecting->to.name.char_set = data[pos]; 09349 break; 09350 case AST_REDIRECTING_TO_NAME_PRESENTATION: 09351 if (ie_len != 1) { 09352 ast_log(LOG_WARNING, "Invalid redirecting-to name presentation (%u)\n", 09353 (unsigned) ie_len); 09354 break; 09355 } 09356 redirecting->to.name.presentation = data[pos]; 09357 break; 09358 case AST_REDIRECTING_TO_NAME_VALID: 09359 if (ie_len != 1) { 09360 ast_log(LOG_WARNING, "Invalid redirecting-to name valid (%u)\n", 09361 (unsigned) ie_len); 09362 break; 09363 } 09364 redirecting->to.name.valid = data[pos]; 09365 break; 09366 /* Redirecting-to party id number */ 09367 case AST_REDIRECTING_TO_NUMBER: 09368 ast_free(redirecting->to.number.str); 09369 redirecting->to.number.str = ast_malloc(ie_len + 1); 09370 if (redirecting->to.number.str) { 09371 memcpy(redirecting->to.number.str, data + pos, ie_len); 09372 redirecting->to.number.str[ie_len] = 0; 09373 } 09374 break; 09375 case AST_REDIRECTING_TO_NUMBER_PLAN: 09376 if (ie_len != 1) { 09377 ast_log(LOG_WARNING, "Invalid redirecting-to numbering plan (%u)\n", 09378 (unsigned) ie_len); 09379 break; 09380 } 09381 redirecting->to.number.plan = data[pos]; 09382 break; 09383 case AST_REDIRECTING_TO_NUMBER_PRESENTATION: 09384 if (ie_len != 1) { 09385 ast_log(LOG_WARNING, "Invalid redirecting-to number presentation (%u)\n", 09386 (unsigned) ie_len); 09387 break; 09388 } 09389 redirecting->to.number.presentation = data[pos]; 09390 break; 09391 case AST_REDIRECTING_TO_NUMBER_VALID: 09392 if (ie_len != 1) { 09393 ast_log(LOG_WARNING, "Invalid redirecting-to number valid (%u)\n", 09394 (unsigned) ie_len); 09395 break; 09396 } 09397 redirecting->to.number.valid = data[pos]; 09398 break; 09399 /* Redirecting-to party id combined presentation */ 09400 case AST_REDIRECTING_TO_ID_PRESENTATION: 09401 if (ie_len != 1) { 09402 ast_log(LOG_WARNING, "Invalid redirecting-to combined presentation (%u)\n", 09403 (unsigned) ie_len); 09404 break; 09405 } 09406 to_combined_presentation = data[pos]; 09407 got_to_combined_presentation = 1; 09408 break; 09409 /* Redirecting-to party id subaddress */ 09410 case AST_REDIRECTING_TO_SUBADDRESS: 09411 ast_free(redirecting->to.subaddress.str); 09412 redirecting->to.subaddress.str = ast_malloc(ie_len + 1); 09413 if (redirecting->to.subaddress.str) { 09414 memcpy(redirecting->to.subaddress.str, data + pos, ie_len); 09415 redirecting->to.subaddress.str[ie_len] = 0; 09416 } 09417 break; 09418 case AST_REDIRECTING_TO_SUBADDRESS_TYPE: 09419 if (ie_len != 1) { 09420 ast_log(LOG_WARNING, "Invalid redirecting-to type of subaddress (%u)\n", 09421 (unsigned) ie_len); 09422 break; 09423 } 09424 redirecting->to.subaddress.type = data[pos]; 09425 break; 09426 case AST_REDIRECTING_TO_SUBADDRESS_ODD_EVEN: 09427 if (ie_len != 1) { 09428 ast_log(LOG_WARNING, 09429 "Invalid redirecting-to subaddress odd-even indicator (%u)\n", 09430 (unsigned) ie_len); 09431 break; 09432 } 09433 redirecting->to.subaddress.odd_even_indicator = data[pos]; 09434 break; 09435 case AST_REDIRECTING_TO_SUBADDRESS_VALID: 09436 if (ie_len != 1) { 09437 ast_log(LOG_WARNING, "Invalid redirecting-to subaddress valid (%u)\n", 09438 (unsigned) ie_len); 09439 break; 09440 } 09441 redirecting->to.subaddress.valid = data[pos]; 09442 break; 09443 /* Redirecting-to party id tag */ 09444 case AST_REDIRECTING_TO_TAG: 09445 ast_free(redirecting->to.tag); 09446 redirecting->to.tag = ast_malloc(ie_len + 1); 09447 if (redirecting->to.tag) { 09448 memcpy(redirecting->to.tag, data + pos, ie_len); 09449 redirecting->to.tag[ie_len] = 0; 09450 } 09451 break; 09452 /* Redirecting reason */ 09453 case AST_REDIRECTING_REASON: 09454 if (ie_len != sizeof(value)) { 09455 ast_log(LOG_WARNING, "Invalid redirecting reason (%u)\n", 09456 (unsigned) ie_len); 09457 break; 09458 } 09459 memcpy(&value, data + pos, sizeof(value)); 09460 redirecting->reason = ntohl(value); 09461 break; 09462 /* Redirecting count */ 09463 case AST_REDIRECTING_COUNT: 09464 if (ie_len != sizeof(value)) { 09465 ast_log(LOG_WARNING, "Invalid redirecting count (%u)\n", 09466 (unsigned) ie_len); 09467 break; 09468 } 09469 memcpy(&value, data + pos, sizeof(value)); 09470 redirecting->count = ntohl(value); 09471 break; 09472 /* Redirecting unknown element */ 09473 default: 09474 ast_log(LOG_DEBUG, "Unknown redirecting element: %u (%u)\n", 09475 (unsigned) ie_id, (unsigned) ie_len); 09476 break; 09477 } 09478 } 09479 09480 switch (frame_version) { 09481 case 1: 09482 /* 09483 * The other end is an earlier version that we need to adjust 09484 * for compatibility. 09485 */ 09486 redirecting->from.name.valid = 1; 09487 redirecting->from.name.char_set = AST_PARTY_CHAR_SET_ISO8859_1; 09488 redirecting->from.number.valid = 1; 09489 if (got_from_combined_presentation) { 09490 redirecting->from.name.presentation = from_combined_presentation; 09491 redirecting->from.number.presentation = from_combined_presentation; 09492 } 09493 09494 redirecting->to.name.valid = 1; 09495 redirecting->to.name.char_set = AST_PARTY_CHAR_SET_ISO8859_1; 09496 redirecting->to.number.valid = 1; 09497 if (got_to_combined_presentation) { 09498 redirecting->to.name.presentation = to_combined_presentation; 09499 redirecting->to.number.presentation = to_combined_presentation; 09500 } 09501 break; 09502 case 2: 09503 /* The other end is at the same level as we are. */ 09504 break; 09505 default: 09506 /* 09507 * The other end is newer than we are. 09508 * We need to assume that they are compatible with us. 09509 */ 09510 ast_log(LOG_DEBUG, "Redirecting frame has newer version: %u\n", 09511 (unsigned) frame_version); 09512 break; 09513 } 09514 09515 return 0; 09516 }
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 5652 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().
05653 { 05654 struct chanlist *chan; 05655 struct ast_channel *c; 05656 format_t capabilities; 05657 format_t fmt; 05658 int res; 05659 int foo; 05660 format_t videoformat = format & AST_FORMAT_VIDEO_MASK; 05661 format_t textformat = format & AST_FORMAT_TEXT_MASK; 05662 05663 if (!cause) 05664 cause = &foo; 05665 *cause = AST_CAUSE_NOTDEFINED; 05666 05667 if (AST_RWLIST_RDLOCK(&backends)) { 05668 ast_log(LOG_WARNING, "Unable to lock technology backend list\n"); 05669 return NULL; 05670 } 05671 05672 AST_RWLIST_TRAVERSE(&backends, chan, list) { 05673 if (strcasecmp(type, chan->tech->type)) 05674 continue; 05675 05676 capabilities = chan->tech->capabilities; 05677 fmt = format & AST_FORMAT_AUDIO_MASK; 05678 if (fmt) { 05679 /* We have audio - is it possible to connect the various calls to each other? 05680 (Avoid this check for calls without audio, like text+video calls) 05681 */ 05682 res = ast_translator_best_choice(&fmt, &capabilities); 05683 if (res < 0) { 05684 char tmp1[256], tmp2[256]; 05685 ast_log(LOG_WARNING, "No translator path exists for channel type %s (native %s) to %s\n", type, 05686 ast_getformatname_multiple(tmp1, sizeof(tmp1), chan->tech->capabilities), 05687 ast_getformatname_multiple(tmp2, sizeof(tmp2), format)); 05688 *cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; 05689 AST_RWLIST_UNLOCK(&backends); 05690 return NULL; 05691 } 05692 } 05693 AST_RWLIST_UNLOCK(&backends); 05694 if (!chan->tech->requester) 05695 return NULL; 05696 05697 if (!(c = chan->tech->requester(type, capabilities | videoformat | textformat, requestor, data, cause))) 05698 return NULL; 05699 05700 if (set_security_requirements(requestor, c)) { 05701 ast_log(LOG_WARNING, "Setting security requirements failed\n"); 05702 c = ast_channel_release(c); 05703 *cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; 05704 return NULL; 05705 } 05706 05707 /* no need to generate a Newchannel event here; it is done in the channel_alloc call */ 05708 return c; 05709 } 05710 05711 ast_log(LOG_WARNING, "No channel type registered for '%s'\n", type); 05712 *cause = AST_CAUSE_NOSUCHDRIVER; 05713 AST_RWLIST_UNLOCK(&backends); 05714 05715 return NULL; 05716 }
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 5607 of file channel.c.
References __ast_request_and_dial().
Referenced by ast_pbx_outgoing_exten(), and generic_recall().
05608 { 05609 return __ast_request_and_dial(type, format, requestor, data, timeout, outstate, cidnum, cidname, NULL); 05610 }
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 8347 of file channel.c.
References ast_say_character_str_full.
Referenced by common_exec(), pbx_builtin_saycharacters(), play_mailbox_owner(), and vmsayname_exec().
08349 { 08350 return ast_say_character_str_full(chan, str, ints, lang, -1, -1); 08351 }
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 8341 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().
08343 { 08344 return ast_say_digit_str_full(chan, str, ints, lang, -1, -1); 08345 }
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 8335 of file channel.c.
References ast_say_digits_full().
Referenced by common_exec(), conf_exec(), conf_run(), park_call_full(), and parkandannounce_exec().
08337 { 08338 return ast_say_digits_full(chan, num, ints, lang, -1, -1); 08339 }
int ast_say_digits_full | ( | struct ast_channel * | chan, | |
int | num, | |||
const char * | ints, | |||
const char * | lang, | |||
int | audiofd, | |||
int | ctrlfd | |||
) |
Definition at line 8359 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().
08361 { 08362 char buf[256]; 08363 08364 snprintf(buf, sizeof(buf), "%d", num); 08365 08366 return ast_say_digit_str_full(chan, buf, ints, lang, audiofd, ctrlfd); 08367 }
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 8329 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().
08331 { 08332 return ast_say_enumeration_full(chan, num, ints, language, options, -1, -1); 08333 }
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 8323 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().
08325 { 08326 return ast_say_number_full(chan, num, ints, language, options, -1, -1); 08327 }
int ast_say_phonetic_str | ( | struct ast_channel * | chan, | |
const char * | str, | |||
const char * | ints, | |||
const char * | lang | |||
) |
Definition at line 8353 of file channel.c.
References ast_say_phonetic_str_full.
Referenced by pbx_builtin_sayphonetic().
08355 { 08356 return ast_say_phonetic_str_full(chan, str, ints, lang, -1, -1); 08357 }
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 4731 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().
04732 { 04733 if (chan->tech->send_digit_begin) { 04734 ast_senddigit_begin(chan, digit); 04735 ast_safe_sleep(chan, (duration >= AST_DEFAULT_EMULATE_DTMF_DURATION ? duration : AST_DEFAULT_EMULATE_DTMF_DURATION)); 04736 } 04737 04738 return ast_senddigit_end(chan, digit, (duration >= AST_DEFAULT_EMULATE_DTMF_DURATION ? duration : AST_DEFAULT_EMULATE_DTMF_DURATION)); 04739 }
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 4662 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().
04663 { 04664 /* Device does not support DTMF tones, lets fake 04665 * it by doing our own generation. */ 04666 static const char * const dtmf_tones[] = { 04667 "941+1336", /* 0 */ 04668 "697+1209", /* 1 */ 04669 "697+1336", /* 2 */ 04670 "697+1477", /* 3 */ 04671 "770+1209", /* 4 */ 04672 "770+1336", /* 5 */ 04673 "770+1477", /* 6 */ 04674 "852+1209", /* 7 */ 04675 "852+1336", /* 8 */ 04676 "852+1477", /* 9 */ 04677 "697+1633", /* A */ 04678 "770+1633", /* B */ 04679 "852+1633", /* C */ 04680 "941+1633", /* D */ 04681 "941+1209", /* * */ 04682 "941+1477" /* # */ 04683 }; 04684 04685 if (!chan->tech->send_digit_begin) 04686 return 0; 04687 04688 ast_channel_lock(chan); 04689 chan->sending_dtmf_digit = digit; 04690 chan->sending_dtmf_tv = ast_tvnow(); 04691 ast_channel_unlock(chan); 04692 04693 if (!chan->tech->send_digit_begin(chan, digit)) 04694 return 0; 04695 04696 if (digit >= '0' && digit <='9') 04697 ast_playtones_start(chan, 0, dtmf_tones[digit-'0'], 0); 04698 else if (digit >= 'A' && digit <= 'D') 04699 ast_playtones_start(chan, 0, dtmf_tones[digit-'A'+10], 0); 04700 else if (digit == '*') 04701 ast_playtones_start(chan, 0, dtmf_tones[14], 0); 04702 else if (digit == '#') 04703 ast_playtones_start(chan, 0, dtmf_tones[15], 0); 04704 else { 04705 /* not handled */ 04706 ast_debug(1, "Unable to generate DTMF tone '%c' for '%s'\n", digit, chan->name); 04707 } 04708 04709 return 0; 04710 }
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 4712 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().
04713 { 04714 int res = -1; 04715 04716 ast_channel_lock(chan); 04717 if (chan->sending_dtmf_digit == digit) { 04718 chan->sending_dtmf_digit = 0; 04719 } 04720 ast_channel_unlock(chan); 04721 04722 if (chan->tech->send_digit_end) 04723 res = chan->tech->send_digit_end(chan, digit, duration); 04724 04725 if (res && chan->generator) 04726 ast_playtones_stop(chan); 04727 04728 return 0; 04729 }
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 4644 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().
04645 { 04646 int res = 0; 04647 04648 ast_channel_lock(chan); 04649 /* Stop if we're a zombie or need a soft hangup */ 04650 if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) { 04651 ast_channel_unlock(chan); 04652 return -1; 04653 } 04654 CHECK_BLOCKING(chan); 04655 if (chan->tech->send_text) 04656 res = chan->tech->send_text(chan, text); 04657 ast_clear_flag(chan, AST_FLAG_BLOCKING); 04658 ast_channel_unlock(chan); 04659 return res; 04660 }
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 6977 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().
06978 { 06979 ast_channel_lock(chan); 06980 06981 if (cid_num) { 06982 chan->caller.id.number.valid = 1; 06983 ast_free(chan->caller.id.number.str); 06984 chan->caller.id.number.str = ast_strdup(cid_num); 06985 } 06986 if (cid_name) { 06987 chan->caller.id.name.valid = 1; 06988 ast_free(chan->caller.id.name.str); 06989 chan->caller.id.name.str = ast_strdup(cid_name); 06990 } 06991 if (cid_ani) { 06992 chan->caller.ani.number.valid = 1; 06993 ast_free(chan->caller.ani.number.str); 06994 chan->caller.ani.number.str = ast_strdup(cid_ani); 06995 } 06996 if (chan->cdr) { 06997 ast_cdr_setcid(chan->cdr, chan); 06998 } 06999 07000 report_new_callerid(chan); 07001 07002 ast_channel_unlock(chan); 07003 }
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 6386 of file channel.c.
References accountcode, ast_log(), ast_string_field_set, ast_strlen_zero(), and LOG_DEBUG.
Referenced by ast_channel_bridge().
06388 { 06389 if (!ast_strlen_zero(chan1->accountcode) && ast_strlen_zero(chan2->peeraccount)) { 06390 ast_log(LOG_DEBUG, "setting peeraccount to %s for %s from data on channel %s\n", 06391 chan1->accountcode, chan2->name, chan1->name); 06392 ast_string_field_set(chan2, peeraccount, chan1->accountcode); 06393 } 06394 if (!ast_strlen_zero(chan2->accountcode) && ast_strlen_zero(chan1->peeraccount)) { 06395 ast_log(LOG_DEBUG, "setting peeraccount to %s for %s from data on channel %s\n", 06396 chan2->accountcode, chan1->name, chan2->name); 06397 ast_string_field_set(chan1, peeraccount, chan2->accountcode); 06398 } 06399 if (!ast_strlen_zero(chan1->peeraccount) && ast_strlen_zero(chan2->accountcode)) { 06400 ast_log(LOG_DEBUG, "setting accountcode to %s for %s from data on channel %s\n", 06401 chan1->peeraccount, chan2->name, chan1->name); 06402 ast_string_field_set(chan2, accountcode, chan1->peeraccount); 06403 } 06404 if (!ast_strlen_zero(chan2->peeraccount) && ast_strlen_zero(chan1->accountcode)) { 06405 ast_log(LOG_DEBUG, "setting accountcode to %s for %s from data on channel %s\n", 06406 chan2->peeraccount, chan1->name, chan2->name); 06407 ast_string_field_set(chan1, accountcode, chan2->peeraccount); 06408 } 06409 if (0 != strcmp(chan1->accountcode, chan2->peeraccount)) { 06410 ast_log(LOG_DEBUG, "changing peeraccount from %s to %s on %s to match channel %s\n", 06411 chan2->peeraccount, chan1->peeraccount, chan2->name, chan1->name); 06412 ast_string_field_set(chan2, peeraccount, chan1->accountcode); 06413 } 06414 if (0 != strcmp(chan2->accountcode, chan1->peeraccount)) { 06415 ast_log(LOG_DEBUG, "changing peeraccount from %s to %s on %s to match channel %s\n", 06416 chan1->peeraccount, chan2->peeraccount, chan1->name, chan2->name); 06417 ast_string_field_set(chan1, peeraccount, chan2->accountcode); 06418 } 06419 }
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 5258 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().
05259 { 05260 return set_format(chan, fmt, &chan->rawreadformat, &chan->readformat, 05261 &chan->readtrans, 0); 05262 }
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 8182 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().
08183 { 08184 struct ast_variable *cur; 08185 08186 for (cur = vars; cur; cur = cur->next) 08187 pbx_builtin_setvar_helper(chan, cur->name, cur->value); 08188 }
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 5264 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().
05265 { 05266 return set_format(chan, fmt, &chan->rawwriteformat, &chan->writeformat, 05267 &chan->writetrans, 1); 05268 }
int ast_setstate | ( | struct ast_channel * | chan, | |
enum ast_channel_state | state | |||
) |
Change the state of a channel.
Definition at line 7045 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().
07046 { 07047 int oldstate = chan->_state; 07048 char name[AST_CHANNEL_NAME], *dashptr; 07049 07050 if (oldstate == state) 07051 return 0; 07052 07053 ast_copy_string(name, chan->name, sizeof(name)); 07054 if ((dashptr = strrchr(name, '-'))) { 07055 *dashptr = '\0'; 07056 } 07057 07058 chan->_state = state; 07059 07060 /* We have to pass AST_DEVICE_UNKNOWN here because it is entirely possible that the channel driver 07061 * for this channel is using the callback method for device state. If we pass in an actual state here 07062 * we override what they are saying the state is and things go amuck. */ 07063 ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, (chan->flags & AST_FLAG_DISABLE_DEVSTATE_CACHE ? AST_DEVSTATE_NOT_CACHABLE : AST_DEVSTATE_CACHABLE), name); 07064 07065 /* setstate used to conditionally report Newchannel; this is no more */ 07066 ast_manager_event(chan, EVENT_FLAG_CALL, "Newstate", 07067 "Channel: %s\r\n" 07068 "ChannelState: %d\r\n" 07069 "ChannelStateDesc: %s\r\n" 07070 "CallerIDNum: %s\r\n" 07071 "CallerIDName: %s\r\n" 07072 "ConnectedLineNum: %s\r\n" 07073 "ConnectedLineName: %s\r\n" 07074 "Uniqueid: %s\r\n", 07075 chan->name, chan->_state, ast_state2str(chan->_state), 07076 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""), 07077 S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, ""), 07078 S_COR(chan->connected.id.number.valid, chan->connected.id.number.str, ""), 07079 S_COR(chan->connected.id.name.valid, chan->connected.id.name.str, ""), 07080 chan->uniqueid); 07081 07082 return 0; 07083 }
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 3546 of file channel.c.
References ast_channel_lock, ast_channel_unlock, ast_debug, 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_activate_generator(), ast_deactivate_generator(), ast_read_generator_actions(), ast_readaudio_callback(), filestream_close(), and internal_deactivate_generator().
03547 { 03548 int res; 03549 unsigned int real_rate = rate, max_rate; 03550 03551 ast_channel_lock(c); 03552 03553 if (c->timingfd == -1) { 03554 ast_channel_unlock(c); 03555 return -1; 03556 } 03557 03558 if (!func) { 03559 rate = 0; 03560 data = NULL; 03561 } 03562 03563 if (rate && rate > (max_rate = ast_timer_get_max_rate(c->timer))) { 03564 real_rate = max_rate; 03565 } 03566 03567 ast_debug(1, "Scheduling timer at (%u requested / %u actual) timer ticks per second\n", rate, real_rate); 03568 03569 res = ast_timer_set_rate(c->timer, real_rate); 03570 03571 c->timingfunc = func; 03572 c->timingdata = data; 03573 03574 if (func == NULL && rate == 0 && c->fdno == AST_TIMING_FD) { 03575 /* Clearing the timing func and setting the rate to 0 03576 * means that we don't want to be reading from the timingfd 03577 * any more. Setting c->fdno to -1 means we won't have any 03578 * errant reads from the timingfd, meaning we won't potentially 03579 * miss any important frames. 03580 */ 03581 c->fdno = -1; 03582 } 03583 03584 ast_channel_unlock(c); 03585 03586 return res; 03587 }
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(), ast_async_goto(), ast_softhangup(), attempt_transfer(), check_pendings(), check_rtp_timeout(), dahdi_softhangup_all(), 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 (%d)", 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 7890 of file channel.c.
References ast_frfree, ast_read(), ast_tonepair_start(), ast_waitfor(), and ast_channel::generatordata.
Referenced by zapateller_exec().
07891 { 07892 int res; 07893 07894 if ((res = ast_tonepair_start(chan, freq1, freq2, duration, vol))) 07895 return res; 07896 07897 /* Give us some wiggle room */ 07898 while (chan->generatordata && ast_waitfor(chan, 100) >= 0) { 07899 struct ast_frame *f = ast_read(chan); 07900 if (f) 07901 ast_frfree(f); 07902 else 07903 return -1; 07904 } 07905 return 0; 07906 }
int ast_tonepair_start | ( | struct ast_channel * | chan, | |
int | freq1, | |||
int | freq2, | |||
int | duration, | |||
int | vol | |||
) |
Start a tone going
Definition at line 7872 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 7885 of file channel.c.
References ast_deactivate_generator().
Referenced by sendnoise().
07886 { 07887 ast_deactivate_generator(chan); 07888 }
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 5745 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().
05746 { 05747 int res = -1; 05748 05749 /* Stop if we're a zombie or need a soft hangup */ 05750 ast_channel_lock(chan); 05751 if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan)) { 05752 if (chan->tech->transfer) { 05753 res = chan->tech->transfer(chan, dest); 05754 if (!res) 05755 res = 1; 05756 } else 05757 res = 0; 05758 } 05759 ast_channel_unlock(chan); 05760 05761 if (res <= 0) { 05762 return res; 05763 } 05764 05765 for (;;) { 05766 struct ast_frame *fr; 05767 05768 res = ast_waitfor(chan, -1); 05769 05770 if (res < 0 || !(fr = ast_read(chan))) { 05771 res = -1; 05772 break; 05773 } 05774 05775 if (fr->frametype == AST_FRAME_CONTROL && fr->subclass.integer == AST_CONTROL_TRANSFER) { 05776 enum ast_control_transfer *message = fr->data.ptr; 05777 05778 if (*message == AST_TRANSFER_SUCCESS) { 05779 res = 1; 05780 } else { 05781 res = -1; 05782 } 05783 05784 ast_frfree(fr); 05785 break; 05786 } 05787 05788 ast_frfree(fr); 05789 } 05790 05791 return res; 05792 }
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 7953 of file channel.c.
References ast_moh_cleanup_ptr, ast_moh_start_ptr, and ast_moh_stop_ptr.
Referenced by unload_module().
07954 { 07955 ast_moh_start_ptr = NULL; 07956 ast_moh_stop_ptr = NULL; 07957 ast_moh_cleanup_ptr = NULL; 07958 }
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 3528 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().
03529 { 03530 if (ms < 0) { 03531 do { 03532 ms = 100000; 03533 ast_waitfor_nandfds(&c, 1, NULL, 0, NULL, NULL, &ms); 03534 } while (!ms); 03535 } else { 03536 ast_waitfor_nandfds(&c, 1, NULL, 0, NULL, NULL, &ms); 03537 } 03538 return ms; 03539 }
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 3523 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().
03524 { 03525 return ast_waitfor_nandfds(c, n, NULL, 0, NULL, NULL, ms); 03526 }
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 3165 of file channel.c.
References ast_waitfor_nandfds().
Referenced by dundi_lookup_internal(), dundi_precache_internal(), and softmix_bridge_thread().
03166 { 03167 int winner = -1; 03168 ast_waitfor_nandfds(NULL, 0, fds, n, exception, &winner, ms); 03169 return winner; 03170 }
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 3177 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().
03180 { 03181 struct timeval start = { 0 , 0 }; 03182 struct pollfd *pfds = NULL; 03183 int res; 03184 long rms; 03185 int x, y, max; 03186 int sz; 03187 struct timeval now = { 0, 0 }; 03188 struct timeval whentohangup = { 0, 0 }, diff; 03189 struct ast_channel *winner = NULL; 03190 struct fdmap { 03191 int chan; 03192 int fdno; 03193 } *fdmap = NULL; 03194 03195 if (outfd) 03196 *outfd = -99999; 03197 if (exception) 03198 *exception = 0; 03199 03200 if ((sz = n * AST_MAX_FDS + nfds)) { 03201 pfds = ast_alloca(sizeof(*pfds) * sz); 03202 fdmap = ast_alloca(sizeof(*fdmap) * sz); 03203 } else { 03204 /* nothing to allocate and no FDs to check */ 03205 return NULL; 03206 } 03207 03208 /* Perform any pending masquerades */ 03209 for (x = 0; x < n; x++) { 03210 while (c[x]->masq) { 03211 ast_do_masquerade(c[x]); 03212 } 03213 03214 ast_channel_lock(c[x]); 03215 if (!ast_tvzero(c[x]->whentohangup)) { 03216 if (ast_tvzero(whentohangup)) 03217 now = ast_tvnow(); 03218 diff = ast_tvsub(c[x]->whentohangup, now); 03219 if (diff.tv_sec < 0 || ast_tvzero(diff)) { 03220 ast_test_suite_event_notify("HANGUP_TIME", "Channel: %s", c[x]->name); 03221 /* Should already be hungup */ 03222 c[x]->_softhangup |= AST_SOFTHANGUP_TIMEOUT; 03223 ast_channel_unlock(c[x]); 03224 return c[x]; 03225 } 03226 if (ast_tvzero(whentohangup) || ast_tvcmp(diff, whentohangup) < 0) 03227 whentohangup = diff; 03228 } 03229 ast_channel_unlock(c[x]); 03230 } 03231 /* Wait full interval */ 03232 rms = *ms; 03233 /* INT_MAX, not LONG_MAX, because it matters on 64-bit */ 03234 if (!ast_tvzero(whentohangup) && whentohangup.tv_sec < INT_MAX / 1000) { 03235 rms = whentohangup.tv_sec * 1000 + whentohangup.tv_usec / 1000; /* timeout in milliseconds */ 03236 if (*ms >= 0 && *ms < rms) { /* original *ms still smaller */ 03237 rms = *ms; 03238 } 03239 } else if (!ast_tvzero(whentohangup) && rms < 0) { 03240 /* Tiny corner case... call would need to last >24 days */ 03241 rms = INT_MAX; 03242 } 03243 /* 03244 * Build the pollfd array, putting the channels' fds first, 03245 * followed by individual fds. Order is important because 03246 * individual fd's must have priority over channel fds. 03247 */ 03248 max = 0; 03249 for (x = 0; x < n; x++) { 03250 for (y = 0; y < AST_MAX_FDS; y++) { 03251 fdmap[max].fdno = y; /* fd y is linked to this pfds */ 03252 fdmap[max].chan = x; /* channel x is linked to this pfds */ 03253 max += ast_add_fd(&pfds[max], c[x]->fds[y]); 03254 } 03255 CHECK_BLOCKING(c[x]); 03256 } 03257 /* Add the individual fds */ 03258 for (x = 0; x < nfds; x++) { 03259 fdmap[max].chan = -1; 03260 max += ast_add_fd(&pfds[max], fds[x]); 03261 } 03262 03263 if (*ms > 0) 03264 start = ast_tvnow(); 03265 03266 if (sizeof(int) == 4) { /* XXX fix timeout > 600000 on linux x86-32 */ 03267 do { 03268 int kbrms = rms; 03269 if (kbrms > 600000) 03270 kbrms = 600000; 03271 res = ast_poll(pfds, max, kbrms); 03272 if (!res) 03273 rms -= kbrms; 03274 } while (!res && (rms > 0)); 03275 } else { 03276 res = ast_poll(pfds, max, rms); 03277 } 03278 for (x = 0; x < n; x++) 03279 ast_clear_flag(c[x], AST_FLAG_BLOCKING); 03280 if (res < 0) { /* Simulate a timeout if we were interrupted */ 03281 if (errno != EINTR) 03282 *ms = -1; 03283 return NULL; 03284 } 03285 if (!ast_tvzero(whentohangup)) { /* if we have a timeout, check who expired */ 03286 now = ast_tvnow(); 03287 for (x = 0; x < n; x++) { 03288 if (!ast_tvzero(c[x]->whentohangup) && ast_tvcmp(c[x]->whentohangup, now) <= 0) { 03289 ast_test_suite_event_notify("HANGUP_TIME", "Channel: %s", c[x]->name); 03290 c[x]->_softhangup |= AST_SOFTHANGUP_TIMEOUT; 03291 if (winner == NULL) 03292 winner = c[x]; 03293 } 03294 } 03295 } 03296 if (res == 0) { /* no fd ready, reset timeout and done */ 03297 *ms = 0; /* XXX use 0 since we may not have an exact timeout. */ 03298 return winner; 03299 } 03300 /* 03301 * Then check if any channel or fd has a pending event. 03302 * Remember to check channels first and fds last, as they 03303 * must have priority on setting 'winner' 03304 */ 03305 for (x = 0; x < max; x++) { 03306 res = pfds[x].revents; 03307 if (res == 0) 03308 continue; 03309 if (fdmap[x].chan >= 0) { /* this is a channel */ 03310 winner = c[fdmap[x].chan]; /* override previous winners */ 03311 if (res & POLLPRI) 03312 ast_set_flag(winner, AST_FLAG_EXCEPTION); 03313 else 03314 ast_clear_flag(winner, AST_FLAG_EXCEPTION); 03315 winner->fdno = fdmap[x].fdno; 03316 } else { /* this is an fd */ 03317 if (outfd) 03318 *outfd = pfds[x].fd; 03319 if (exception) 03320 *exception = (res & POLLPRI) ? -1 : 0; 03321 winner = NULL; 03322 } 03323 } 03324 if (*ms > 0) { 03325 *ms -= ast_tvdiff_ms(ast_tvnow(), start); 03326 if (*ms < 0) 03327 *ms = 0; 03328 } 03329 return winner; 03330 }
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 3541 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_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_exec(), 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().
03542 { 03543 return ast_waitfordigit_full(c, ms, -1, -1); 03544 }
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 3589 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().
03590 { 03591 struct timeval start = ast_tvnow(); 03592 int ms; 03593 03594 /* Stop if we're a zombie or need a soft hangup */ 03595 if (ast_test_flag(c, AST_FLAG_ZOMBIE) || ast_check_hangup(c)) 03596 return -1; 03597 03598 /* Only look for the end of DTMF, don't bother with the beginning and don't emulate things */ 03599 ast_set_flag(c, AST_FLAG_END_DTMF_ONLY); 03600 03601 /* Wait for a digit, no more than timeout_ms milliseconds total. 03602 * Or, wait indefinitely if timeout_ms is <0. 03603 */ 03604 while ((ms = ast_remaining_ms(start, timeout_ms))) { 03605 struct ast_channel *rchan; 03606 int outfd = -1; 03607 03608 errno = 0; 03609 /* While ast_waitfor_nandfds tries to help by reducing the timeout by how much was waited, 03610 * it is unhelpful if it waited less than a millisecond. 03611 */ 03612 rchan = ast_waitfor_nandfds(&c, 1, &cmdfd, (cmdfd > -1) ? 1 : 0, NULL, &outfd, &ms); 03613 03614 if (!rchan && outfd < 0 && ms) { 03615 if (errno == 0 || errno == EINTR) 03616 continue; 03617 ast_log(LOG_WARNING, "Wait failed (%s)\n", strerror(errno)); 03618 ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); 03619 return -1; 03620 } else if (outfd > -1) { 03621 /* The FD we were watching has something waiting */ 03622 ast_log(LOG_WARNING, "The FD we were waiting for has something waiting. Waitfordigit returning numeric 1\n"); 03623 ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); 03624 return 1; 03625 } else if (rchan) { 03626 int res; 03627 struct ast_frame *f = ast_read(c); 03628 if (!f) 03629 return -1; 03630 03631 switch (f->frametype) { 03632 case AST_FRAME_DTMF_BEGIN: 03633 break; 03634 case AST_FRAME_DTMF_END: 03635 res = f->subclass.integer; 03636 ast_frfree(f); 03637 ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); 03638 return res; 03639 case AST_FRAME_CONTROL: 03640 switch (f->subclass.integer) { 03641 case AST_CONTROL_HANGUP: 03642 ast_frfree(f); 03643 ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); 03644 return -1; 03645 case AST_CONTROL_RINGING: 03646 case AST_CONTROL_ANSWER: 03647 case AST_CONTROL_SRCUPDATE: 03648 case AST_CONTROL_SRCCHANGE: 03649 case AST_CONTROL_CONNECTED_LINE: 03650 case AST_CONTROL_REDIRECTING: 03651 case AST_CONTROL_UPDATE_RTP_PEER: 03652 case AST_CONTROL_HOLD: 03653 case AST_CONTROL_UNHOLD: 03654 case -1: 03655 /* Unimportant */ 03656 break; 03657 default: 03658 ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", f->subclass.integer); 03659 break; 03660 } 03661 break; 03662 case AST_FRAME_VOICE: 03663 /* Write audio if appropriate */ 03664 if (audiofd > -1) { 03665 if (write(audiofd, f->data.ptr, f->datalen) < 0) { 03666 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 03667 } 03668 } 03669 default: 03670 /* Ignore */ 03671 break; 03672 } 03673 ast_frfree(f); 03674 } 03675 } 03676 03677 ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY); 03678 03679 return 0; /* Time is up */ 03680 }
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 4873 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().
04874 { 04875 int res = -1; 04876 struct ast_frame *f = NULL; 04877 int count = 0; 04878 04879 /*Deadlock avoidance*/ 04880 while(ast_channel_trylock(chan)) { 04881 /*cannot goto done since the channel is not locked*/ 04882 if(count++ > 10) { 04883 ast_debug(1, "Deadlock avoided for write to channel '%s'\n", chan->name); 04884 return 0; 04885 } 04886 usleep(1); 04887 } 04888 /* Stop if we're a zombie or need a soft hangup */ 04889 if (ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) 04890 goto done; 04891 04892 /* Handle any pending masquerades */ 04893 while (chan->masq) { 04894 ast_channel_unlock(chan); 04895 ast_do_masquerade(chan); 04896 ast_channel_lock(chan); 04897 } 04898 if (chan->masqr) { 04899 res = 0; /* XXX explain, why 0 ? */ 04900 goto done; 04901 } 04902 04903 /* Perform the framehook write event here. After the frame enters the framehook list 04904 * there is no telling what will happen, how awesome is that!!! */ 04905 if (!(fr = ast_framehook_list_write_event(chan->framehooks, fr))) { 04906 res = 0; 04907 goto done; 04908 } 04909 04910 if (chan->generatordata && (!fr->src || strcasecmp(fr->src, "ast_prod"))) { 04911 if (ast_test_flag(chan, AST_FLAG_WRITE_INT)) { 04912 ast_deactivate_generator(chan); 04913 } else { 04914 if (fr->frametype == AST_FRAME_DTMF_END) { 04915 /* There is a generator running while we're in the middle of a digit. 04916 * It's probably inband DTMF, so go ahead and pass it so it can 04917 * stop the generator */ 04918 ast_clear_flag(chan, AST_FLAG_BLOCKING); 04919 ast_channel_unlock(chan); 04920 res = ast_senddigit_end(chan, fr->subclass.integer, fr->len); 04921 ast_channel_lock(chan); 04922 CHECK_BLOCKING(chan); 04923 } else if (fr->frametype == AST_FRAME_CONTROL && fr->subclass.integer == AST_CONTROL_UNHOLD) { 04924 /* This is a side case where Echo is basically being called and the person put themselves on hold and took themselves off hold */ 04925 res = (chan->tech->indicate == NULL) ? 0 : 04926 chan->tech->indicate(chan, fr->subclass.integer, fr->data.ptr, fr->datalen); 04927 } 04928 res = 0; /* XXX explain, why 0 ? */ 04929 goto done; 04930 } 04931 } 04932 /* High bit prints debugging */ 04933 if (chan->fout & DEBUGCHAN_FLAG) 04934 ast_frame_dump(chan->name, fr, ">>"); 04935 CHECK_BLOCKING(chan); 04936 switch (fr->frametype) { 04937 case AST_FRAME_CONTROL: 04938 res = (chan->tech->indicate == NULL) ? 0 : 04939 chan->tech->indicate(chan, fr->subclass.integer, fr->data.ptr, fr->datalen); 04940 break; 04941 case AST_FRAME_DTMF_BEGIN: 04942 if (chan->audiohooks) { 04943 struct ast_frame *old_frame = fr; 04944 fr = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_WRITE, fr); 04945 if (old_frame != fr) 04946 f = fr; 04947 } 04948 send_dtmf_event(chan, "Sent", fr->subclass.integer, "Yes", "No"); 04949 ast_clear_flag(chan, AST_FLAG_BLOCKING); 04950 ast_channel_unlock(chan); 04951 res = ast_senddigit_begin(chan, fr->subclass.integer); 04952 ast_channel_lock(chan); 04953 CHECK_BLOCKING(chan); 04954 break; 04955 case AST_FRAME_DTMF_END: 04956 if (chan->audiohooks) { 04957 struct ast_frame *new_frame = fr; 04958 04959 new_frame = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_WRITE, fr); 04960 if (new_frame != fr) { 04961 ast_frfree(new_frame); 04962 } 04963 } 04964 send_dtmf_event(chan, "Sent", fr->subclass.integer, "No", "Yes"); 04965 ast_clear_flag(chan, AST_FLAG_BLOCKING); 04966 ast_channel_unlock(chan); 04967 res = ast_senddigit_end(chan, fr->subclass.integer, fr->len); 04968 ast_channel_lock(chan); 04969 CHECK_BLOCKING(chan); 04970 break; 04971 case AST_FRAME_TEXT: 04972 if (fr->subclass.integer == AST_FORMAT_T140) { 04973 res = (chan->tech->write_text == NULL) ? 0 : 04974 chan->tech->write_text(chan, fr); 04975 } else { 04976 res = (chan->tech->send_text == NULL) ? 0 : 04977 chan->tech->send_text(chan, (char *) fr->data.ptr); 04978 } 04979 break; 04980 case AST_FRAME_HTML: 04981 res = (chan->tech->send_html == NULL) ? 0 : 04982 chan->tech->send_html(chan, fr->subclass.integer, (char *) fr->data.ptr, fr->datalen); 04983 break; 04984 case AST_FRAME_VIDEO: 04985 /* XXX Handle translation of video codecs one day XXX */ 04986 res = (chan->tech->write_video == NULL) ? 0 : 04987 chan->tech->write_video(chan, fr); 04988 break; 04989 case AST_FRAME_MODEM: 04990 res = (chan->tech->write == NULL) ? 0 : 04991 chan->tech->write(chan, fr); 04992 break; 04993 case AST_FRAME_VOICE: 04994 if (chan->tech->write == NULL) 04995 break; /*! \todo XXX should return 0 maybe ? */ 04996 04997 if (ast_opt_generic_plc && fr->subclass.codec == AST_FORMAT_SLINEAR) { 04998 apply_plc(chan, fr); 04999 } 05000 05001 /* If the frame is in the raw write format, then it's easy... just use the frame - otherwise we will have to translate */ 05002 if (fr->subclass.codec == chan->rawwriteformat) { 05003 f = fr; 05004 } else { 05005 if ((!(fr->subclass.codec & chan->nativeformats)) && (chan->writeformat != fr->subclass.codec)) { 05006 char nf[512]; 05007 05008 /* 05009 * XXX Something is not right. We are not compatible with this 05010 * frame. Bad things can happen. Problems range from no audio, 05011 * one-way audio, to unexplained line hangups. As a last resort 05012 * try to adjust the format. Ideally, we do not want to do this 05013 * because it indicates a deeper problem. For now, we log these 05014 * events to reduce user impact and help identify the problem 05015 * areas. 05016 */ 05017 ast_log(LOG_WARNING, "Codec mismatch on channel %s setting write format to %s from %s native formats %s\n", 05018 chan->name, ast_getformatname(fr->subclass.codec), ast_getformatname(chan->writeformat), 05019 ast_getformatname_multiple(nf, sizeof(nf), chan->nativeformats & AST_FORMAT_AUDIO_MASK)); 05020 ast_set_write_format(chan, fr->subclass.codec); 05021 } 05022 05023 f = (chan->writetrans) ? ast_translate(chan->writetrans, fr, 0) : fr; 05024 } 05025 05026 if (!f) { 05027 res = 0; 05028 break; 05029 } 05030 05031 if (chan->audiohooks) { 05032 struct ast_frame *prev = NULL, *new_frame, *cur, *dup; 05033 int freeoldlist = 0; 05034 05035 if (f != fr) { 05036 freeoldlist = 1; 05037 } 05038 05039 /* Since ast_audiohook_write may return a new frame, and the cur frame is 05040 * an item in a list of frames, create a new list adding each cur frame back to it 05041 * regardless if the cur frame changes or not. */ 05042 for (cur = f; cur; cur = AST_LIST_NEXT(cur, frame_list)) { 05043 new_frame = ast_audiohook_write_list(chan, chan->audiohooks, AST_AUDIOHOOK_DIRECTION_WRITE, cur); 05044 05045 /* if this frame is different than cur, preserve the end of the list, 05046 * free the old frames, and set cur to be the new frame */ 05047 if (new_frame != cur) { 05048 05049 /* doing an ast_frisolate here seems silly, but we are not guaranteed the new_frame 05050 * isn't part of local storage, meaning if ast_audiohook_write is called multiple 05051 * times it may override the previous frame we got from it unless we dup it */ 05052 if ((dup = ast_frisolate(new_frame))) { 05053 AST_LIST_NEXT(dup, frame_list) = AST_LIST_NEXT(cur, frame_list); 05054 if (freeoldlist) { 05055 AST_LIST_NEXT(cur, frame_list) = NULL; 05056 ast_frfree(cur); 05057 } 05058 if (new_frame != dup) { 05059 ast_frfree(new_frame); 05060 } 05061 cur = dup; 05062 } 05063 } 05064 05065 /* now, regardless if cur is new or not, add it to the new list, 05066 * if the new list has not started, cur will become the first item. */ 05067 if (prev) { 05068 AST_LIST_NEXT(prev, frame_list) = cur; 05069 } else { 05070 f = cur; /* set f to be the beginning of our new list */ 05071 } 05072 prev = cur; 05073 } 05074 } 05075 05076 /* If Monitor is running on this channel, then we have to write frames out there too */ 05077 /* the translator on chan->writetrans may have returned multiple frames 05078 from the single frame we passed in; if so, feed each one of them to the 05079 monitor */ 05080 if (chan->monitor && chan->monitor->write_stream) { 05081 struct ast_frame *cur; 05082 05083 for (cur = f; cur; cur = AST_LIST_NEXT(cur, frame_list)) { 05084 /* XXX must explain this code */ 05085 #ifndef MONITOR_CONSTANT_DELAY 05086 int jump = chan->insmpl - chan->outsmpl - 4 * cur->samples; 05087 if (jump >= 0) { 05088 jump = calc_monitor_jump((chan->insmpl - chan->outsmpl), ast_format_rate(f->subclass.codec), ast_format_rate(chan->monitor->read_stream->fmt->format)); 05089 if (ast_seekstream(chan->monitor->write_stream, jump, SEEK_FORCECUR) == -1) 05090 ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n"); 05091 chan->outsmpl += (chan->insmpl - chan->outsmpl) + cur->samples; 05092 } else { 05093 chan->outsmpl += cur->samples; 05094 } 05095 #else 05096 int jump = calc_monitor_jump((chan->insmpl - chan->outsmpl), ast_format_rate(f->subclass.codec), ast_format_rate(chan->monitor->read_stream->fmt->format)); 05097 if (jump - MONITOR_DELAY >= 0) { 05098 if (ast_seekstream(chan->monitor->write_stream, jump - cur->samples, SEEK_FORCECUR) == -1) 05099 ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n"); 05100 chan->outsmpl += chan->insmpl - chan->outsmpl; 05101 } else { 05102 chan->outsmpl += cur->samples; 05103 } 05104 #endif 05105 if (chan->monitor->state == AST_MONITOR_RUNNING) { 05106 if (ast_writestream(chan->monitor->write_stream, cur) < 0) 05107 ast_log(LOG_WARNING, "Failed to write data to channel monitor write stream\n"); 05108 } 05109 } 05110 } 05111 05112 /* the translator on chan->writetrans may have returned multiple frames 05113 from the single frame we passed in; if so, feed each one of them to the 05114 channel, freeing each one after it has been written */ 05115 if ((f != fr) && AST_LIST_NEXT(f, frame_list)) { 05116 struct ast_frame *cur, *next; 05117 unsigned int skip = 0; 05118 05119 for (cur = f, next = AST_LIST_NEXT(cur, frame_list); 05120 cur; 05121 cur = next, next = cur ? AST_LIST_NEXT(cur, frame_list) : NULL) { 05122 if (!skip) { 05123 if ((res = chan->tech->write(chan, cur)) < 0) { 05124 chan->_softhangup |= AST_SOFTHANGUP_DEV; 05125 skip = 1; 05126 } else if (next) { 05127 /* don't do this for the last frame in the list, 05128 as the code outside the loop will do it once 05129 */ 05130 chan->fout = FRAMECOUNT_INC(chan->fout); 05131 } 05132 } 05133 ast_frfree(cur); 05134 } 05135 05136 /* reset f so the code below doesn't attempt to free it */ 05137 f = NULL; 05138 } else { 05139 res = chan->tech->write(chan, f); 05140 } 05141 break; 05142 case AST_FRAME_NULL: 05143 case AST_FRAME_IAX: 05144 /* Ignore these */ 05145 res = 0; 05146 break; 05147 default: 05148 /* At this point, fr is the incoming frame and f is NULL. Channels do 05149 * not expect to get NULL as a frame pointer and will segfault. Hence, 05150 * we output the original frame passed in. */ 05151 res = chan->tech->write(chan, fr); 05152 break; 05153 } 05154 05155 if (f && f != fr) 05156 ast_frfree(f); 05157 ast_clear_flag(chan, AST_FLAG_BLOCKING); 05158 05159 /* Consider a write failure to force a soft hangup */ 05160 if (res < 0) { 05161 chan->_softhangup |= AST_SOFTHANGUP_DEV; 05162 } else { 05163 chan->fout = FRAMECOUNT_INC(chan->fout); 05164 } 05165 done: 05166 if (chan->audiohooks && ast_audiohook_write_list_empty(chan->audiohooks)) { 05167 /* The list gets recreated if audiohooks are added again later */ 05168 ast_audiohook_detach_list(chan->audiohooks); 05169 chan->audiohooks = NULL; 05170 } 05171 ast_channel_unlock(chan); 05172 return res; 05173 }
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 4758 of file channel.c.
References ast_write(), ast_channel::tech, and ast_channel_tech::write_video.
04759 { 04760 int res; 04761 if (!chan->tech->write_video) 04762 return 0; 04763 res = ast_write(chan, fr); 04764 if (!res) 04765 res = 1; 04766 return res; 04767 }
static void bridge_play_sounds | ( | struct ast_channel * | c0, | |
struct ast_channel * | c1 | |||
) | [static] |
Definition at line 7404 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().
07405 { 07406 const char *s, *sound; 07407 07408 /* See if we need to play an audio file to any side of the bridge */ 07409 07410 ast_channel_lock(c0); 07411 if ((s = pbx_builtin_getvar_helper(c0, "BRIDGE_PLAY_SOUND"))) { 07412 sound = ast_strdupa(s); 07413 ast_channel_unlock(c0); 07414 bridge_playfile(c0, c1, sound, 0); 07415 pbx_builtin_setvar_helper(c0, "BRIDGE_PLAY_SOUND", NULL); 07416 } else { 07417 ast_channel_unlock(c0); 07418 } 07419 07420 ast_channel_lock(c1); 07421 if ((s = pbx_builtin_getvar_helper(c1, "BRIDGE_PLAY_SOUND"))) { 07422 sound = ast_strdupa(s); 07423 ast_channel_unlock(c1); 07424 bridge_playfile(c1, c0, sound, 0); 07425 pbx_builtin_setvar_helper(c1, "BRIDGE_PLAY_SOUND", NULL); 07426 } else { 07427 ast_channel_unlock(c1); 07428 } 07429 }
static void bridge_playfile | ( | struct ast_channel * | chan, | |
struct ast_channel * | peer, | |||
const char * | sound, | |||
int | remain | |||
) | [static] |
Definition at line 7095 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().
07096 { 07097 int min = 0, sec = 0, check; 07098 07099 check = ast_autoservice_start(peer); 07100 if (check) 07101 return; 07102 07103 if (remain > 0) { 07104 if (remain / 60 > 1) { 07105 min = remain / 60; 07106 sec = remain % 60; 07107 } else { 07108 sec = remain; 07109 } 07110 } 07111 07112 if (!strcmp(sound,"timeleft")) { /* Queue support */ 07113 ast_stream_and_wait(chan, "vm-youhave", ""); 07114 if (min) { 07115 ast_say_number(chan, min, AST_DIGIT_ANY, chan->language, NULL); 07116 ast_stream_and_wait(chan, "queue-minutes", ""); 07117 } 07118 if (sec) { 07119 ast_say_number(chan, sec, AST_DIGIT_ANY, chan->language, NULL); 07120 ast_stream_and_wait(chan, "queue-seconds", ""); 07121 } 07122 } else { 07123 ast_stream_and_wait(chan, sound, ""); 07124 } 07125 07126 ast_autoservice_stop(peer); 07127 }
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 3788 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 5316 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().
05317 { 05318 if (!ast_test_flag(parent, AST_FLAG_ZOMBIE) && !ast_check_hangup(parent)) { 05319 struct ast_party_redirecting redirecting; 05320 05321 /* 05322 * The parent is not a ZOMBIE or hungup so update it with the 05323 * original channel's redirecting information. 05324 */ 05325 ast_party_redirecting_init(&redirecting); 05326 ast_channel_lock(orig); 05327 ast_party_redirecting_copy(&redirecting, &orig->redirecting); 05328 ast_channel_unlock(orig); 05329 if (ast_channel_redirecting_macro(orig, parent, &redirecting, 1, 0)) { 05330 ast_channel_update_redirecting(parent, &redirecting, NULL); 05331 } 05332 ast_party_redirecting_free(&redirecting); 05333 } 05334 05335 /* Safely inherit variables and datastores from the parent channel. */ 05336 ast_channel_lock_both(parent, new_chan); 05337 ast_channel_inherit_variables(parent, new_chan); 05338 ast_channel_datastore_inherit(parent, new_chan); 05339 ast_channel_unlock(new_chan); 05340 ast_channel_unlock(parent); 05341 }
static void* channel_cc_params_copy | ( | void * | data | ) | [static] |
Definition at line 9634 of file channel.c.
References ast_cc_config_params_init, and ast_cc_copy_config_params().
09635 { 09636 const struct ast_cc_config_params *src = data; 09637 struct ast_cc_config_params *dest = ast_cc_config_params_init(); 09638 if (!dest) { 09639 return NULL; 09640 } 09641 ast_cc_copy_config_params(dest, src); 09642 return dest; 09643 }
static void channel_cc_params_destroy | ( | void * | data | ) | [static] |
Definition at line 9645 of file channel.c.
References ast_cc_config_params_destroy().
09646 { 09647 struct ast_cc_config_params *cc_params = data; 09648 ast_cc_config_params_destroy(cc_params); 09649 }
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 8298 of file channel.c.
References CHANNEL_CLI_RELOAD, CHANNEL_MODULE_LOAD, and CHANNEL_MODULE_RELOAD.
Referenced by reload_config().
08299 { 08300 switch (reason) { 08301 case CHANNEL_MODULE_LOAD: 08302 return "LOAD (Channel module load)"; 08303 08304 case CHANNEL_MODULE_RELOAD: 08305 return "RELOAD (Channel module reload)"; 08306 08307 case CHANNEL_CLI_RELOAD: 08308 return "CLIRELOAD (Channel module reload by CLI command)"; 08309 08310 default: 08311 return "MANAGERRELOAD (Channel module reload by manager)"; 08312 } 08313 };
static void channels_shutdown | ( | void | ) | [static] |
Definition at line 8132 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().
08133 { 08134 ast_data_unregister(NULL); 08135 ast_cli_unregister_multiple(cli_channel, ARRAY_LEN(cli_channel)); 08136 if (channels) { 08137 ao2_ref(channels, -1); 08138 channels = NULL; 08139 } 08140 }
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 6247 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().
06248 { 06249 struct ast_var_t *current, *newvar; 06250 /* Append variables from clone channel into original channel */ 06251 /* XXX Is this always correct? We have to in order to keep MACROS working XXX */ 06252 AST_LIST_APPEND_LIST(&original->varshead, &clonechan->varshead, entries); 06253 06254 /* then, dup the varshead list into the clone */ 06255 06256 AST_LIST_TRAVERSE(&original->varshead, current, entries) { 06257 newvar = ast_var_assign(current->name, current->value); 06258 if (newvar) 06259 AST_LIST_INSERT_TAIL(&clonechan->varshead, newvar, entries); 06260 } 06261 }
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 8017 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.
08019 { 08020 struct ast_channel *c; 08021 struct ast_channel_iterator *iter = NULL; 08022 struct ast_data *data_channel; 08023 08024 for (iter = ast_channel_iterator_all_new(); 08025 iter && (c = ast_channel_iterator_next(iter)); ast_channel_unref(c)) { 08026 ast_channel_lock(c); 08027 08028 data_channel = ast_data_add_node(root, "channel"); 08029 if (!data_channel) { 08030 ast_channel_unlock(c); 08031 continue; 08032 } 08033 08034 if (ast_channel_data_add_structure(data_channel, c, 1) < 0) { 08035 ast_log(LOG_ERROR, "Unable to add channel structure for channel: %s\n", c->name); 08036 } 08037 08038 ast_channel_unlock(c); 08039 08040 if (!ast_data_search_match(search, data_channel)) { 08041 ast_data_remove_node(root, data_channel); 08042 } 08043 } 08044 if (iter) { 08045 ast_channel_iterator_destroy(iter); 08046 } 08047 08048 return 0; 08049 }
static int data_channeltypes_provider_handler | ( | const struct ast_data_search * | search, | |
struct ast_data * | data_root | |||
) | [static] |
Definition at line 8055 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.
08057 { 08058 struct chanlist *cl; 08059 struct ast_data *data_type; 08060 08061 AST_RWLIST_RDLOCK(&backends); 08062 AST_RWLIST_TRAVERSE(&backends, cl, list) { 08063 data_type = ast_data_add_node(data_root, "type"); 08064 if (!data_type) { 08065 continue; 08066 } 08067 ast_data_add_str(data_type, "name", cl->tech->type); 08068 ast_data_add_str(data_type, "description", cl->tech->description); 08069 ast_data_add_bool(data_type, "devicestate", cl->tech->devicestate ? 1 : 0); 08070 ast_data_add_bool(data_type, "indications", cl->tech->indicate ? 1 : 0); 08071 ast_data_add_bool(data_type, "transfer", cl->tech->transfer ? 1 : 0); 08072 ast_data_add_bool(data_type, "send_digit_begin", cl->tech->send_digit_begin ? 1 : 0); 08073 ast_data_add_bool(data_type, "send_digit_end", cl->tech->send_digit_end ? 1 : 0); 08074 ast_data_add_bool(data_type, "call", cl->tech->call ? 1 : 0); 08075 ast_data_add_bool(data_type, "hangup", cl->tech->hangup ? 1 : 0); 08076 ast_data_add_bool(data_type, "answer", cl->tech->answer ? 1 : 0); 08077 ast_data_add_bool(data_type, "read", cl->tech->read ? 1 : 0); 08078 ast_data_add_bool(data_type, "write", cl->tech->write ? 1 : 0); 08079 ast_data_add_bool(data_type, "send_text", cl->tech->send_text ? 1 : 0); 08080 ast_data_add_bool(data_type, "send_image", cl->tech->send_image ? 1 : 0); 08081 ast_data_add_bool(data_type, "send_html", cl->tech->send_html ? 1 : 0); 08082 ast_data_add_bool(data_type, "exception", cl->tech->exception ? 1 : 0); 08083 ast_data_add_bool(data_type, "bridge", cl->tech->bridge ? 1 : 0); 08084 ast_data_add_bool(data_type, "early_bridge", cl->tech->early_bridge ? 1 : 0); 08085 ast_data_add_bool(data_type, "fixup", cl->tech->fixup ? 1 : 0); 08086 ast_data_add_bool(data_type, "setoption", cl->tech->setoption ? 1 : 0); 08087 ast_data_add_bool(data_type, "queryoption", cl->tech->queryoption ? 1 : 0); 08088 ast_data_add_bool(data_type, "write_video", cl->tech->write_video ? 1 : 0); 08089 ast_data_add_bool(data_type, "write_text", cl->tech->write_text ? 1 : 0); 08090 ast_data_add_bool(data_type, "bridged_channel", cl->tech->bridged_channel ? 1 : 0); 08091 ast_data_add_bool(data_type, "func_channel_read", cl->tech->func_channel_read ? 1 : 0); 08092 ast_data_add_bool(data_type, "func_channel_write", cl->tech->func_channel_write ? 1 : 0); 08093 ast_data_add_bool(data_type, "get_base_channel", cl->tech->get_base_channel ? 1 : 0); 08094 ast_data_add_bool(data_type, "set_base_channel", cl->tech->set_base_channel ? 1 : 0); 08095 ast_data_add_bool(data_type, "get_pvt_uniqueid", cl->tech->get_pvt_uniqueid ? 1 : 0); 08096 ast_data_add_bool(data_type, "cc_callback", cl->tech->cc_callback ? 1 : 0); 08097 08098 ast_data_add_codecs(data_type, "capabilities", cl->tech->capabilities); 08099 08100 if (!ast_data_search_match(search, data_type)) { 08101 ast_data_remove_node(data_root, data_type); 08102 } 08103 } 08104 AST_RWLIST_UNLOCK(&backends); 08105 08106 return 0; 08107 }
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 3106 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(), and ast_read_generator_actions().
03107 { 03108 /* Called if generator doesn't have data */ 03109 void *tmp; 03110 int res; 03111 int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples) = NULL; 03112 struct ast_channel *chan = (struct ast_channel *)data; 03113 03114 ast_channel_lock(chan); 03115 tmp = chan->generatordata; 03116 chan->generatordata = NULL; 03117 if (chan->generator) 03118 generate = chan->generator->generate; 03119 ast_channel_unlock(chan); 03120 03121 if (!tmp || !generate) 03122 return 0; 03123 03124 res = generate(chan, tmp, 0, ast_format_rate(chan->writeformat & AST_FORMAT_AUDIO_MASK) / 50); 03125 03126 ast_channel_lock(chan); 03127 if (chan->generator && generate == chan->generator->generate) { 03128 chan->generatordata = tmp; 03129 } 03130 ast_channel_unlock(chan); 03131 03132 if (res) { 03133 ast_debug(1, "Auto-deactivating generator\n"); 03134 ast_deactivate_generator(chan); 03135 } 03136 03137 return 0; 03138 }
static void handle_cause | ( | int | cause, | |
int * | outstate | |||
) | [static] |
Definition at line 5293 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().
05294 { 05295 if (outstate) { 05296 /* compute error and return */ 05297 if (cause == AST_CAUSE_BUSY) 05298 *outstate = AST_CONTROL_BUSY; 05299 else if (cause == AST_CAUSE_CONGESTION) 05300 *outstate = AST_CONTROL_CONGESTION; 05301 else 05302 *outstate = 0; 05303 } 05304 }
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 internal_deactivate_generator | ( | struct ast_channel * | chan, | |
void * | generator | |||
) | [static] |
Definition at line 8253 of file channel.c.
References ast_channel_lock, ast_channel_set_fd(), ast_channel_unlock, ast_clear_flag, ast_debug, AST_FLAG_WRITE_INT, AST_GENERATOR_FD, ast_settimeout(), ast_channel::generator, ast_channel::generatordata, and ast_generator::release.
Referenced by ast_channel_stop_silence_generator().
08254 { 08255 ast_channel_lock(chan); 08256 08257 if (!chan->generatordata) { 08258 ast_debug(1, "Trying to stop silence generator when there is no " 08259 "generator on '%s'\n", chan->name); 08260 ast_channel_unlock(chan); 08261 return 0; 08262 } 08263 if (chan->generator != generator) { 08264 ast_debug(1, "Trying to stop silence generator when it is not the current " 08265 "generator on '%s'\n", chan->name); 08266 ast_channel_unlock(chan); 08267 return 0; 08268 } 08269 if (chan->generator && chan->generator->release) { 08270 chan->generator->release(chan, chan->generatordata); 08271 } 08272 chan->generatordata = NULL; 08273 chan->generator = NULL; 08274 ast_channel_set_fd(chan, AST_GENERATOR_FD, -1); 08275 ast_clear_flag(chan, AST_FLAG_WRITE_INT); 08276 ast_settimeout(chan, 0, NULL, NULL); 08277 ast_channel_unlock(chan); 08278 08279 return 1; 08280 }
static int attribute_const is_visible_indication | ( | enum ast_control_frame_type | condition | ) | [static] |
Definition at line 4355 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().
04356 { 04357 /* Don't include a default case here so that we get compiler warnings 04358 * when a new type is added. */ 04359 04360 switch (condition) { 04361 case AST_CONTROL_PROGRESS: 04362 case AST_CONTROL_PROCEEDING: 04363 case AST_CONTROL_VIDUPDATE: 04364 case AST_CONTROL_SRCUPDATE: 04365 case AST_CONTROL_SRCCHANGE: 04366 case AST_CONTROL_RADIO_KEY: 04367 case AST_CONTROL_RADIO_UNKEY: 04368 case AST_CONTROL_OPTION: 04369 case AST_CONTROL_WINK: 04370 case AST_CONTROL_FLASH: 04371 case AST_CONTROL_OFFHOOK: 04372 case AST_CONTROL_TAKEOFFHOOK: 04373 case AST_CONTROL_ANSWER: 04374 case AST_CONTROL_HANGUP: 04375 case AST_CONTROL_CONNECTED_LINE: 04376 case AST_CONTROL_REDIRECTING: 04377 case AST_CONTROL_TRANSFER: 04378 case AST_CONTROL_T38_PARAMETERS: 04379 case _XXX_AST_CONTROL_T38: 04380 case AST_CONTROL_CC: 04381 case AST_CONTROL_READ_ACTION: 04382 case AST_CONTROL_AOC: 04383 case AST_CONTROL_END_OF_Q: 04384 case AST_CONTROL_UPDATE_RTP_PEER: 04385 break; 04386 04387 case AST_CONTROL_INCOMPLETE: 04388 case AST_CONTROL_CONGESTION: 04389 case AST_CONTROL_BUSY: 04390 case AST_CONTROL_RINGING: 04391 case AST_CONTROL_RING: 04392 case AST_CONTROL_HOLD: 04393 /* You can hear these */ 04394 return 1; 04395 04396 case AST_CONTROL_UNHOLD: 04397 /* This is a special case. You stop hearing this. */ 04398 break; 04399 } 04400 04401 return 0; 04402 }
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 7347 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().
07348 { 07349 struct ast_channel *chans[2] = { c0, c1 }; 07350 ast_manager_event_multichan(EVENT_FLAG_CALL, "Bridge", 2, chans, 07351 "Bridgestate: %s\r\n" 07352 "Bridgetype: %s\r\n" 07353 "Channel1: %s\r\n" 07354 "Channel2: %s\r\n" 07355 "Uniqueid1: %s\r\n" 07356 "Uniqueid2: %s\r\n" 07357 "CallerID1: %s\r\n" 07358 "CallerID2: %s\r\n", 07359 onoff ? "Link" : "Unlink", 07360 type == 1 ? "core" : "native", 07361 c0->name, c1->name, 07362 c0->uniqueid, c1->uniqueid, 07363 S_COR(c0->caller.id.number.valid, c0->caller.id.number.str, ""), 07364 S_COR(c1->caller.id.number.valid, c1->caller.id.number.str, "")); 07365 }
static void masquerade_colp_transfer | ( | struct ast_channel * | transferee, | |
struct xfer_masquerade_ds * | colp | |||
) | [static] |
Definition at line 6454 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().
06455 { 06456 struct ast_control_read_action_payload *frame_payload; 06457 int payload_size; 06458 int frame_size; 06459 unsigned char connected_line_data[1024]; 06460 06461 /* Release any hold on the target. */ 06462 if (colp->target_held) { 06463 ast_queue_control(transferee, AST_CONTROL_UNHOLD); 06464 } 06465 06466 /* 06467 * Since transferee may not actually be bridged to another channel, 06468 * there is no way for us to queue a frame so that its connected 06469 * line status will be updated. Instead, we use the somewhat 06470 * hackish approach of using a special control frame type that 06471 * instructs ast_read() to perform a specific action. In this 06472 * case, the frame we queue tells ast_read() to call the 06473 * connected line interception macro configured for transferee. 06474 */ 06475 payload_size = ast_connected_line_build_data(connected_line_data, 06476 sizeof(connected_line_data), &colp->target_id, NULL); 06477 if (payload_size != -1) { 06478 frame_size = payload_size + sizeof(*frame_payload); 06479 frame_payload = ast_alloca(frame_size); 06480 frame_payload->action = AST_FRAME_READ_ACTION_CONNECTED_LINE_MACRO; 06481 frame_payload->payload_size = payload_size; 06482 memcpy(frame_payload->payload, connected_line_data, payload_size); 06483 ast_queue_control_data(transferee, AST_CONTROL_READ_ACTION, frame_payload, 06484 frame_size); 06485 } 06486 /* 06487 * In addition to queueing the read action frame so that the 06488 * connected line info on transferee will be updated, we also are 06489 * going to queue a plain old connected line update on transferee to 06490 * update the target. 06491 */ 06492 ast_channel_queue_connected_line_update(transferee, &colp->transferee_id, NULL); 06493 }
static const char* oldest_linkedid | ( | const char * | a, | |
const char * | b | |||
) | [static] |
Definition at line 6276 of file channel.c.
References ast_strlen_zero().
Referenced by ast_channel_set_linkgroup().
06277 { 06278 const char *satime, *saseq; 06279 const char *sbtime, *sbseq; 06280 const char *dash; 06281 06282 unsigned int atime, aseq, btime, bseq; 06283 06284 if (ast_strlen_zero(a)) 06285 return b; 06286 06287 if (ast_strlen_zero(b)) 06288 return a; 06289 06290 satime = a; 06291 sbtime = b; 06292 06293 /* jump over the system name */ 06294 if ((dash = strrchr(satime, '-'))) { 06295 satime = dash+1; 06296 } 06297 if ((dash = strrchr(sbtime, '-'))) { 06298 sbtime = dash+1; 06299 } 06300 06301 /* the sequence comes after the '.' */ 06302 saseq = strchr(satime, '.'); 06303 sbseq = strchr(sbtime, '.'); 06304 if (!saseq || !sbseq) 06305 return NULL; 06306 saseq++; 06307 sbseq++; 06308 06309 /* convert it all to integers */ 06310 atime = atoi(satime); /* note that atoi is ignoring the '.' after the time string */ 06311 btime = atoi(sbtime); /* note that atoi is ignoring the '.' after the time string */ 06312 aseq = atoi(saseq); 06313 bseq = atoi(sbseq); 06314 06315 /* and finally compare */ 06316 if (atime == btime) { 06317 return (aseq < bseq) ? a : b; 06318 } 06319 else { 06320 return (atime < btime) ? a : b; 06321 } 06322 }
static void party_connected_line_copy_transfer | ( | struct ast_party_connected_line * | dest, | |
const struct ast_party_connected_line * | src | |||
) | [static] |
Definition at line 6082 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().
06083 { 06084 struct ast_party_connected_line connected; 06085 06086 connected = *((struct ast_party_connected_line *) src); 06087 connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER; 06088 06089 /* Make sure empty strings will be erased. */ 06090 if (!connected.id.name.str) { 06091 connected.id.name.str = ""; 06092 } 06093 if (!connected.id.number.str) { 06094 connected.id.number.str = ""; 06095 } 06096 if (!connected.id.subaddress.str) { 06097 connected.id.subaddress.str = ""; 06098 } 06099 if (!connected.id.tag) { 06100 connected.id.tag = ""; 06101 } 06102 06103 ast_party_connected_line_copy(dest, &connected); 06104 }
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 8648 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().
08651 { 08652 size_t length; 08653 size_t pos = 0; 08654 int res; 08655 08656 /* 08657 * The size of integer values must be fixed in case the frame is 08658 * shipped to another machine. 08659 */ 08660 08661 if (!update || update->name) { 08662 res = party_name_build_data(data + pos, datalen - pos, &id->name, label, 08663 &ies->name); 08664 if (res < 0) { 08665 return -1; 08666 } 08667 pos += res; 08668 } 08669 08670 if (!update || update->number) { 08671 res = party_number_build_data(data + pos, datalen - pos, &id->number, label, 08672 &ies->number); 08673 if (res < 0) { 08674 return -1; 08675 } 08676 pos += res; 08677 } 08678 08679 if (!update || update->subaddress) { 08680 res = party_subaddress_build_data(data + pos, datalen - pos, &id->subaddress, 08681 label, &ies->subaddress); 08682 if (res < 0) { 08683 return -1; 08684 } 08685 pos += res; 08686 } 08687 08688 /* *************** Party id user tag **************************** */ 08689 if (id->tag) { 08690 length = strlen(id->tag); 08691 if (datalen < pos + (sizeof(data[0]) * 2) + length) { 08692 ast_log(LOG_WARNING, "No space left for %s tag\n", label); 08693 return -1; 08694 } 08695 data[pos++] = ies->tag; 08696 data[pos++] = length; 08697 memcpy(data + pos, id->tag, length); 08698 pos += length; 08699 } 08700 08701 /* *************** Party id combined presentation *************** */ 08702 if (!update || update->number) { 08703 int presentation; 08704 08705 if (!update || update->name) { 08706 presentation = ast_party_id_presentation(id); 08707 } else { 08708 /* 08709 * We must compromise because not all the information is available 08710 * to determine a combined presentation value. 08711 * We will only send the number presentation instead. 08712 */ 08713 presentation = id->number.presentation; 08714 } 08715 08716 if (datalen < pos + (sizeof(data[0]) * 2) + 1) { 08717 ast_log(LOG_WARNING, "No space left for %s combined presentation\n", label); 08718 return -1; 08719 } 08720 data[pos++] = ies->combined_presentation; 08721 data[pos++] = 1; 08722 data[pos++] = presentation; 08723 } 08724 08725 return pos; 08726 }
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 8422 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().
08423 { 08424 size_t length; 08425 size_t pos = 0; 08426 08427 /* 08428 * The size of integer values must be fixed in case the frame is 08429 * shipped to another machine. 08430 */ 08431 if (name->str) { 08432 length = strlen(name->str); 08433 if (datalen < pos + (sizeof(data[0]) * 2) + length) { 08434 ast_log(LOG_WARNING, "No space left for %s name\n", label); 08435 return -1; 08436 } 08437 data[pos++] = ies->str; 08438 data[pos++] = length; 08439 memcpy(data + pos, name->str, length); 08440 pos += length; 08441 } 08442 08443 if (datalen < pos + (sizeof(data[0]) * 2) + 1) { 08444 ast_log(LOG_WARNING, "No space left for %s name char set\n", label); 08445 return -1; 08446 } 08447 data[pos++] = ies->char_set; 08448 data[pos++] = 1; 08449 data[pos++] = name->char_set; 08450 08451 if (datalen < pos + (sizeof(data[0]) * 2) + 1) { 08452 ast_log(LOG_WARNING, "No space left for %s name presentation\n", label); 08453 return -1; 08454 } 08455 data[pos++] = ies->presentation; 08456 data[pos++] = 1; 08457 data[pos++] = name->presentation; 08458 08459 if (datalen < pos + (sizeof(data[0]) * 2) + 1) { 08460 ast_log(LOG_WARNING, "No space left for %s name valid\n", label); 08461 return -1; 08462 } 08463 data[pos++] = ies->valid; 08464 data[pos++] = 1; 08465 data[pos++] = name->valid; 08466 08467 return pos; 08468 }
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 8496 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().
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 (number->str) { 08506 length = strlen(number->str); 08507 if (datalen < pos + (sizeof(data[0]) * 2) + length) { 08508 ast_log(LOG_WARNING, "No space left for %s number\n", label); 08509 return -1; 08510 } 08511 data[pos++] = ies->str; 08512 data[pos++] = length; 08513 memcpy(data + pos, number->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 numbering plan\n", label); 08519 return -1; 08520 } 08521 data[pos++] = ies->plan; 08522 data[pos++] = 1; 08523 data[pos++] = number->plan; 08524 08525 if (datalen < pos + (sizeof(data[0]) * 2) + 1) { 08526 ast_log(LOG_WARNING, "No space left for %s number presentation\n", label); 08527 return -1; 08528 } 08529 data[pos++] = ies->presentation; 08530 data[pos++] = 1; 08531 data[pos++] = number->presentation; 08532 08533 if (datalen < pos + (sizeof(data[0]) * 2) + 1) { 08534 ast_log(LOG_WARNING, "No space left for %s number valid\n", label); 08535 return -1; 08536 } 08537 data[pos++] = ies->valid; 08538 data[pos++] = 1; 08539 data[pos++] = number->valid; 08540 08541 return pos; 08542 }
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 8570 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().
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 (subaddress->str) { 08580 length = strlen(subaddress->str); 08581 if (datalen < pos + (sizeof(data[0]) * 2) + length) { 08582 ast_log(LOG_WARNING, "No space left for %s subaddress\n", label); 08583 return -1; 08584 } 08585 data[pos++] = ies->str; 08586 data[pos++] = length; 08587 memcpy(data + pos, subaddress->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 type of subaddress\n", label); 08593 return -1; 08594 } 08595 data[pos++] = ies->type; 08596 data[pos++] = 1; 08597 data[pos++] = subaddress->type; 08598 08599 if (datalen < pos + (sizeof(data[0]) * 2) + 1) { 08600 ast_log(LOG_WARNING, 08601 "No space left for %s subaddress odd-even indicator\n", label); 08602 return -1; 08603 } 08604 data[pos++] = ies->odd_even_indicator; 08605 data[pos++] = 1; 08606 data[pos++] = subaddress->odd_even_indicator; 08607 08608 if (datalen < pos + (sizeof(data[0]) * 2) + 1) { 08609 ast_log(LOG_WARNING, "No space left for %s subaddress valid\n", label); 08610 return -1; 08611 } 08612 data[pos++] = ies->valid; 08613 data[pos++] = 1; 08614 data[pos++] = subaddress->valid; 08615 08616 return pos; 08617 }
static void plc_ds_destroy | ( | void * | data | ) | [static] |
Definition at line 4782 of file channel.c.
References ast_free, and plc_ds::samples_buf.
04783 { 04784 struct plc_ds *plc = data; 04785 ast_free(plc->samples_buf); 04786 ast_free(plc); 04787 }
static void queue_dtmf_readq | ( | struct ast_channel * | chan, | |
struct ast_frame * | f | |||
) | [inline, static] |
Definition at line 3743 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().
03744 { 03745 struct ast_frame *fr = &chan->dtmff; 03746 03747 fr->frametype = AST_FRAME_DTMF_END; 03748 fr->subclass.integer = f->subclass.integer; 03749 fr->len = f->len; 03750 03751 /* The only time this function will be called is for a frame that just came 03752 * out of the channel driver. So, we want to stick it on the tail of the 03753 * readq. */ 03754 03755 ast_queue_frame(chan, fr); 03756 }
static void report_new_callerid | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 6424 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().
06425 { 06426 int pres; 06427 06428 pres = ast_party_id_presentation(&chan->caller.id); 06429 ast_manager_event(chan, EVENT_FLAG_CALL, "NewCallerid", 06430 "Channel: %s\r\n" 06431 "CallerIDNum: %s\r\n" 06432 "CallerIDName: %s\r\n" 06433 "Uniqueid: %s\r\n" 06434 "CID-CallingPres: %d (%s)\r\n", 06435 chan->name, 06436 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""), 06437 S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, ""), 06438 chan->uniqueid, 06439 pres, 06440 ast_describe_caller_presentation(pres) 06441 ); 06442 }
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 3682 of file channel.c.
References ast_manager_event, and EVENT_FLAG_DTMF.
Referenced by __ast_read(), and ast_write().
03683 { 03684 ast_manager_event(chan, EVENT_FLAG_DTMF, 03685 "DTMF", 03686 "Channel: %s\r\n" 03687 "Uniqueid: %s\r\n" 03688 "Digit: %c\r\n" 03689 "Direction: %s\r\n" 03690 "Begin: %s\r\n" 03691 "End: %s\r\n", 03692 chan->name, chan->uniqueid, digit, direction, begin, end); 03693 }
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 5175 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().
05177 { 05178 format_t native, native_fmt = ast_best_codec(fmt); 05179 int res; 05180 char from[200], to[200]; 05181 05182 /* Make sure we only consider audio */ 05183 fmt &= AST_FORMAT_AUDIO_MASK; 05184 05185 native = chan->nativeformats; 05186 05187 if (!fmt || !native) /* No audio requested */ 05188 return 0; /* Let's try a call without any sounds (video, text) */ 05189 05190 /* See if the underlying channel driver is capable of performing transcoding for us */ 05191 if (!ast_channel_setoption(chan, direction ? AST_OPTION_FORMAT_WRITE : AST_OPTION_FORMAT_READ, &native_fmt, sizeof(int*), 0)) { 05192 ast_debug(1, "Channel driver natively set channel %s to %s format %s\n", chan->name, 05193 direction ? "write" : "read", ast_getformatname(native_fmt)); 05194 chan->nativeformats = *rawformat = *format = native_fmt; 05195 if (*trans) { 05196 ast_translator_free_path(*trans); 05197 } 05198 *trans = NULL; 05199 return 0; 05200 } 05201 05202 /* Find a translation path from the native format to one of the desired formats */ 05203 if (!direction) 05204 /* reading */ 05205 res = ast_translator_best_choice(&fmt, &native); 05206 else 05207 /* writing */ 05208 res = ast_translator_best_choice(&native, &fmt); 05209 05210 if (res < 0) { 05211 ast_log(LOG_WARNING, "Unable to find a codec translation path from %s to %s\n", 05212 ast_getformatname_multiple(from, sizeof(from), native), 05213 ast_getformatname_multiple(to, sizeof(to), fmt)); 05214 return -1; 05215 } 05216 05217 /* Now we have a good choice for both. */ 05218 ast_channel_lock(chan); 05219 05220 if ((*rawformat == native) && (*format == fmt) && ((*rawformat == *format) || (*trans))) { 05221 /* the channel is already in these formats, so nothing to do */ 05222 ast_channel_unlock(chan); 05223 return 0; 05224 } 05225 05226 *rawformat = native; 05227 /* User perspective is fmt */ 05228 *format = fmt; 05229 /* Free any read translation we have right now */ 05230 if (*trans) { 05231 ast_translator_free_path(*trans); 05232 *trans = NULL; 05233 } 05234 /* Build a translation path from the raw format to the desired format */ 05235 if (*format == *rawformat) { 05236 /* 05237 * If we were able to swap the native format to the format that 05238 * has been requested, then there is no need to try to build 05239 * a translation path. 05240 */ 05241 res = 0; 05242 } else { 05243 if (!direction) { 05244 /* reading */ 05245 *trans = ast_translator_build_path(*format, *rawformat); 05246 } else { 05247 /* writing */ 05248 *trans = ast_translator_build_path(*rawformat, *format); 05249 } 05250 res = *trans ? 0 : -1; 05251 } 05252 ast_channel_unlock(chan); 05253 ast_debug(1, "Set channel %s to %s format %s\n", chan->name, 05254 direction ? "write" : "read", ast_getformatname(fmt)); 05255 return res; 05256 }
static int set_security_requirements | ( | const struct ast_channel * | requestor, | |
struct ast_channel * | out | |||
) | [static] |
Definition at line 5612 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().
05613 { 05614 int ops[2][2] = { 05615 {AST_OPTION_SECURE_SIGNALING, 0}, 05616 {AST_OPTION_SECURE_MEDIA, 0}, 05617 }; 05618 int i; 05619 struct ast_channel *r = (struct ast_channel *) requestor; /* UGLY */ 05620 struct ast_datastore *ds; 05621 05622 if (!requestor || !out) { 05623 return 0; 05624 } 05625 05626 ast_channel_lock(r); 05627 if ((ds = ast_channel_datastore_find(r, &secure_call_info, NULL))) { 05628 struct ast_secure_call_store *encrypt = ds->data; 05629 ops[0][1] = encrypt->signaling; 05630 ops[1][1] = encrypt->media; 05631 } else { 05632 ast_channel_unlock(r); 05633 return 0; 05634 } 05635 ast_channel_unlock(r); 05636 05637 for (i = 0; i < 2; i++) { 05638 if (ops[i][1]) { 05639 if (ast_channel_setoption(out, ops[i][0], &ops[i][1], sizeof(ops[i][1]), 0)) { 05640 /* We require a security feature, but the channel won't provide it */ 05641 return -1; 05642 } 05643 } else { 05644 /* We don't care if we can't clear the option on a channel that doesn't support it */ 05645 ast_channel_setoption(out, ops[i][0], &ops[i][1], sizeof(ops[i][1]), 0); 05646 } 05647 } 05648 05649 return 0; 05650 }
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 3761 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().
03762 { 03763 if (ast_test_flag(chan, AST_FLAG_DEFER_DTMF | AST_FLAG_EMULATE_DTMF)) { 03764 /* We're in the middle of emulating a digit, or DTMF has been 03765 * explicitly deferred. Skip this digit, then. */ 03766 return 1; 03767 } 03768 03769 if (!ast_tvzero(chan->dtmf_tv) && 03770 ast_tvdiff_ms(ast_tvnow(), chan->dtmf_tv) < AST_MIN_DTMF_GAP) { 03771 /* We're not in the middle of a digit, but it hasn't been long enough 03772 * since the last digit, so we'll have to skip DTMF for now. */ 03773 return 1; 03774 } 03775 03776 return 0; 03777 }
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 8201 of file channel.c.
References AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_write(), and ast_frame::frametype.
08202 { 08203 short buf[samples]; 08204 struct ast_frame frame = { 08205 .frametype = AST_FRAME_VOICE, 08206 .subclass.codec = AST_FORMAT_SLINEAR, 08207 .data.ptr = buf, 08208 .samples = samples, 08209 .datalen = sizeof(buf), 08210 }; 08211 08212 memset(buf, 0, sizeof(buf)); 08213 08214 if (ast_write(chan, &frame)) 08215 return -1; 08216 08217 return 0; 08218 }
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 7790 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.
07791 { 07792 struct tonepair_state *ts; 07793 struct tonepair_def *td = params; 07794 07795 if (!(ts = ast_calloc(1, sizeof(*ts)))) 07796 return NULL; 07797 ts->origwfmt = chan->writeformat; 07798 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) { 07799 ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (write)\n", chan->name); 07800 tonepair_release(NULL, ts); 07801 ts = NULL; 07802 } else { 07803 ts->fac1 = 2.0 * cos(2.0 * M_PI * (td->freq1 / 8000.0)) * 32768.0; 07804 ts->v1_1 = 0; 07805 ts->v2_1 = sin(-4.0 * M_PI * (td->freq1 / 8000.0)) * td->vol; 07806 ts->v3_1 = sin(-2.0 * M_PI * (td->freq1 / 8000.0)) * td->vol; 07807 ts->v2_1 = 0; 07808 ts->fac2 = 2.0 * cos(2.0 * M_PI * (td->freq2 / 8000.0)) * 32768.0; 07809 ts->v2_2 = sin(-4.0 * M_PI * (td->freq2 / 8000.0)) * td->vol; 07810 ts->v3_2 = sin(-2.0 * M_PI * (td->freq2 / 8000.0)) * td->vol; 07811 ts->duration = td->duration; 07812 ts->modulate = 0; 07813 } 07814 /* Let interrupts interrupt :) */ 07815 ast_set_flag(chan, AST_FLAG_WRITE_INT); 07816 return ts; 07817 }
static int tonepair_generator | ( | struct ast_channel * | chan, | |
void * | data, | |||
int | len, | |||
int | samples | |||
) | [static] |
Definition at line 7819 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.
07820 { 07821 struct tonepair_state *ts = data; 07822 int x; 07823 07824 /* we need to prepare a frame with 16 * timelen samples as we're 07825 * generating SLIN audio 07826 */ 07827 len = samples * 2; 07828 07829 if (len > sizeof(ts->data) / 2 - 1) { 07830 ast_log(LOG_WARNING, "Can't generate that much data!\n"); 07831 return -1; 07832 } 07833 memset(&ts->f, 0, sizeof(ts->f)); 07834 for (x=0;x<len/2;x++) { 07835 ts->v1_1 = ts->v2_1; 07836 ts->v2_1 = ts->v3_1; 07837 ts->v3_1 = (ts->fac1 * ts->v2_1 >> 15) - ts->v1_1; 07838 07839 ts->v1_2 = ts->v2_2; 07840 ts->v2_2 = ts->v3_2; 07841 ts->v3_2 = (ts->fac2 * ts->v2_2 >> 15) - ts->v1_2; 07842 if (ts->modulate) { 07843 int p; 07844 p = ts->v3_2 - 32768; 07845 if (p < 0) p = -p; 07846 p = ((p * 9) / 10) + 1; 07847 ts->data[x] = (ts->v3_1 * p) >> 15; 07848 } else 07849 ts->data[x] = ts->v3_1 + ts->v3_2; 07850 } 07851 ts->f.frametype = AST_FRAME_VOICE; 07852 ts->f.subclass.codec = AST_FORMAT_SLINEAR; 07853 ts->f.datalen = len; 07854 ts->f.samples = samples; 07855 ts->f.offset = AST_FRIENDLY_OFFSET; 07856 ts->f.data.ptr = ts->data; 07857 ast_write(chan, &ts->f); 07858 ts->pos += x; 07859 if (ts->duration > 0) { 07860 if (ts->pos >= ts->duration * 8) 07861 return -1; 07862 } 07863 return 0; 07864 }
static void tonepair_release | ( | struct ast_channel * | chan, | |
void * | params | |||
) | [static] |
Definition at line 7781 of file channel.c.
References ast_free, ast_set_write_format(), and tonepair_state::origwfmt.
Referenced by tonepair_alloc().
07782 { 07783 struct tonepair_state *ts = params; 07784 07785 if (chan) 07786 ast_set_write_format(chan, ts->origwfmt); 07787 ast_free(ts); 07788 }
static void update_bridge_vars | ( | struct ast_channel * | c0, | |
struct ast_channel * | c1 | |||
) | [static] |
Definition at line 7367 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().
07368 { 07369 const char *c0_name; 07370 const char *c1_name; 07371 const char *c0_pvtid = NULL; 07372 const char *c1_pvtid = NULL; 07373 07374 ast_channel_lock(c1); 07375 c1_name = ast_strdupa(c1->name); 07376 if (c1->tech->get_pvt_uniqueid) { 07377 c1_pvtid = ast_strdupa(c1->tech->get_pvt_uniqueid(c1)); 07378 } 07379 ast_channel_unlock(c1); 07380 07381 ast_channel_lock(c0); 07382 if (!ast_strlen_zero(pbx_builtin_getvar_helper(c0, "BRIDGEPEER"))) { 07383 pbx_builtin_setvar_helper(c0, "BRIDGEPEER", c1_name); 07384 } 07385 if (c1_pvtid) { 07386 pbx_builtin_setvar_helper(c0, "BRIDGEPVTCALLID", c1_pvtid); 07387 } 07388 c0_name = ast_strdupa(c0->name); 07389 if (c0->tech->get_pvt_uniqueid) { 07390 c0_pvtid = ast_strdupa(c0->tech->get_pvt_uniqueid(c0)); 07391 } 07392 ast_channel_unlock(c0); 07393 07394 ast_channel_lock(c1); 07395 if (!ast_strlen_zero(pbx_builtin_getvar_helper(c1, "BRIDGEPEER"))) { 07396 pbx_builtin_setvar_helper(c1, "BRIDGEPEER", c0_name); 07397 } 07398 if (c0_pvtid) { 07399 pbx_builtin_setvar_helper(c1, "BRIDGEPVTCALLID", c0_pvtid); 07400 } 07401 ast_channel_unlock(c1); 07402 }
static void xfer_ds_destroy | ( | void * | data | ) | [static] |
Definition at line 6127 of file channel.c.
References ast_free, ast_party_connected_line_free(), xfer_masquerade_ds::target_id, and xfer_masquerade_ds::transferee_id.
06128 { 06129 struct xfer_masquerade_ds *ds = data; 06130 06131 ast_party_connected_line_free(&ds->target_id); 06132 ast_party_connected_line_free(&ds->transferee_id); 06133 ast_free(ds); 06134 }
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, }