104 .name = {
"REFER Progress", 14 },
150 pjsip_evsub_state
state)
199 pjsip_tx_data *tdata;
201 pjsip_dlg_inc_lock(notification->progress->dlg);
204 if (!(
sub = notification->progress->sub)) {
205 ast_debug(3,
"Not sending NOTIFY of response '%d' and state '%u' on progress monitor '%p' as subscription has been terminated\n",
206 notification->response, notification->state, notification->progress);
207 pjsip_dlg_dec_lock(notification->progress->dlg);
212 if (!notification->progress->sent_100) {
213 notification->progress->sent_100 = 1;
214 if (notification->response != 100) {
215 ast_debug(3,
"Sending initial 100 Trying NOTIFY for progress monitor '%p'\n",
216 notification->progress);
217 if (pjsip_xfer_notify(
sub, PJSIP_EVSUB_STATE_ACTIVE, 100,
NULL, &tdata) == PJ_SUCCESS) {
218 pjsip_xfer_send_request(
sub, tdata);
223 ast_debug(3,
"Sending NOTIFY with response '%d' and state '%u' on subscription '%p' and progress monitor '%p'\n",
224 notification->response, notification->state,
sub, notification->progress);
227 if (pjsip_xfer_notify(
sub, notification->state, notification->response,
NULL, &tdata) == PJ_SUCCESS) {
228 pjsip_xfer_send_request(
sub, tdata);
232 if (notification->progress->ari_state) {
234 if (ari_state->
transferer && notification->state == PJSIP_EVSUB_STATE_TERMINATED) {
243 pjsip_dlg_dec_lock(notification->progress->dlg);
272 if (!
progress->transfer_data->completed) {
294 ast_debug(3,
"Detaching REFER progress monitoring hook from '%s' as it has joined a bridge\n",
314 if (!
progress->transfer_data->completed) {
349 if (notification->
state == PJSIP_EVSUB_STATE_TERMINATED) {
350 ast_debug(3,
"Detaching REFER progress monitoring hook from '%s' as subscription is being terminated\n",
401 if (notification->
state == PJSIP_EVSUB_STATE_TERMINATED) {
402 ast_debug(3,
"Detaching REFER progress monitoring hook from '%s' as subscription is being terminated\n",
450 if (
progress && (pjsip_evsub_get_state(
sub) == PJSIP_EVSUB_STATE_TERMINATED)) {
504 const pj_str_t str_refer_sub = {
"Refer-Sub", 9 };
505 pjsip_generic_string_hdr *refer_sub =
NULL;
506 const pj_str_t str_true = {
"true", 4 };
513 refer_sub = pjsip_msg_find_hdr_by_name(
rdata->msg_info.msg, &str_refer_sub,
NULL);
514 if ((refer_sub && pj_strnicmp(&refer_sub->hvalue, &str_true, 4))) {
522 ast_debug(3,
"Created progress monitor '%p' for transfer occurring from channel '%s' and endpoint '%s'\n",
525 (*progress)->refer_blind_progress =
session->endpoint->refer_blind_progress;
527 (*progress)->framehook = -1;
543 (*progress)->dlg =
session->inv_session->dlg;
554 pjsip_hdr *hdr = (pjsip_hdr*)pjsip_generic_string_hdr_create(
session->inv_session->dlg->pool, &str_refer_sub, &str_true);
677 int (*task_cb)(
void *data);
680 ast_debug(3,
"Performing a REFER attended transfer - Transferer #1: %s Transferer #2: %s\n",
688 ast_debug(3,
"Final response for REFER attended transfer - Transferer #1: %s Transferer #2: %s is '%d'\n",
693 ast_debug(3,
"Received REFER request on channel '%s' but other channel has gone.\n",
702 PJSIP_EVSUB_STATE_TERMINATED);
749 pjsip_generic_string_hdr *referred_by;
751 static const pj_str_t str_referred_by = {
"Referred-By", 11 };
752 static const pj_str_t str_referred_by_s = {
"b", 1 };
753 const char *get_xfrdata;
760 PJSIP_EVSUB_STATE_TERMINATED);
774 .disable_inheritance = 1,
780 PJSIP_EVSUB_STATE_TERMINATED);
782 ast_log(
LOG_WARNING,
"Could not copy channel name '%s' during transfer - assuming success\n",
793 ao2_ref(user_data_wrapper, +1);
805 PJSIP_EVSUB_STATE_TERMINATED);
807 ast_log(
LOG_WARNING,
"Could not attach REFER transfer progress monitoring hook to channel '%s' - assuming success\n",
827 PJSIP_EVSUB_STATE_TERMINATED);
829 ast_log(
LOG_WARNING,
"Could not create bridge stasis subscription for monitoring progress on transfer of channel '%s' - assuming success\n",
858 const pjsip_msg * msg = refer->
rdata->msg_info.msg;
859 const struct pjsip_hdr *
end = &msg->hdr;
860 struct pjsip_hdr *hdr =
end->next;
863 const char *
prefix = get_xfrdata;
866 if (!strcmp(
prefix,
"*")) {
870 for (; hdr !=
end; hdr = hdr->next) {
871 if (!pj_strnicmp2(&hdr->name,
prefix, strlen(
prefix))) {
872 const int hdr_name_strlen = pj_strlen(&hdr->name);
873 const int hdr_name_bytes = hdr_name_strlen + 1;
874 char hdr_name[hdr_name_bytes];
879 len = pjsip_hdr_print_on(hdr,
buf,
sizeof(
buf) - 1);
888 value_str = strchr(
buf,
':');
895 ast_str_set(&pbxvar, -1,
"~HASH~TRANSFER_DATA~%.*s~", hdr_name_strlen, hdr_name);
897 ast_debug(5,
"On channel '%s' set TRANSFER_DATA variable '%s' to value '%s' \n",
ast_channel_name(chan), hdr_name, value_str);
906 referred_by = pjsip_msg_find_hdr_by_names(refer->
rdata->msg_info.msg,
907 &str_referred_by, &str_referred_by_s,
NULL);
909 size_t uri_size = pj_strlen(&referred_by->hvalue) + 1;
920 char *replaces_val =
NULL;
923 len = pjsip_hdr_print_on(refer->
replaces, replaces,
sizeof(replaces) - 1);
926 replaces[
len] =
'\0';
927 replaces_val = replaces +
sizeof(
"Replaces:");
935 char refer_to[PJSIP_MAX_URL_SIZE];
937 pjsip_uri_print(PJSIP_URI_IN_REQ_URI, refer->
refer_to, refer_to,
sizeof(refer_to));
952#define DETERMINE_TRANSFER_CONTEXT(context, session) \
954 ast_channel_lock((session)->channel); \
955 context = pbx_builtin_getvar_helper((session)->channel, "TRANSFER_CONTEXT"); \
956 if (ast_strlen_zero(context)) { \
957 context = (session)->endpoint->context; \
959 context = ast_strdupa(context); \
961 ast_channel_unlock((session)->channel); \
1024 uri_params = strchr(rdata->
from,
'@');
1025 if (uri_params && (uri_params = strchr(uri_params,
';'))) {
1052 static const char *hdr[] = {
1067 if (!strcasecmp(
name, hdr[i])) {
1107 .name = {
"REFER Out-of-dialog Module", 26 },
1111 .priority = PJSIP_MOD_PRIORITY_TSX_LAYER - 4,
1117 const pj_str_t REFER_TO = {
"Refer-To", 8 };
1118 pjsip_generic_string_hdr *refer_to;
1119 pjsip_uri *parsed_uri;
1121 if (!(refer_to = pjsip_msg_find_hdr_by_name(tdata->msg, &REFER_TO,
NULL))
1122 || !(parsed_uri = pjsip_parse_uri(tdata->pool, refer_to->hvalue.ptr, refer_to->hvalue.slen, 0))
1123 || (!PJSIP_URI_SCHEME_IS_SIP(parsed_uri) && !PJSIP_URI_SCHEME_IS_SIPS(parsed_uri))) {
1132 const pj_str_t REFER_TO = {
"Refer-To", 8 };
1133 pjsip_generic_string_hdr *refer_to_hdr;
1136 pjsip_uri *parsed_uri;
1137 pjsip_sip_uri *refer_to_uri;
1147 || pjsip_msg_find_hdr(tdata->msg, PJSIP_H_AUTHORIZATION,
NULL)
1148 || !(dlg = pjsip_tdata_get_dlg(tdata))
1154 refer_to_uri = pjsip_uri_get_uri(parsed_uri);
1158 refer_to_hdr = pjsip_msg_find_hdr_by_name(tdata->msg, &REFER_TO,
NULL);
1159 pj_strdup2(tdata->pool, &refer_to_hdr->hvalue,
ast_str_buffer(refer_to_str));
1203 pjsip_tx_data *tdata;
1220 if (pjsip_evsub_get_state(
sub) == PJSIP_EVSUB_STATE_ACCEPTED) {
1222 pjsip_rx_data *rdata;
1223 pjsip_generic_string_hdr *refer_sub;
1224 const pj_str_t REFER_SUB = {
"Refer-Sub", 9 };
1229 if (
event->type == PJSIP_EVENT_TSX_STATE &&
event->body.tsx_state.type == PJSIP_EVENT_RX_MSG) {
1230 rdata =
event->body.tsx_state.src.rdata;
1233 refer_sub = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &REFER_SUB,
NULL);
1239 if (refer_sub && !pj_stricmp2(&refer_sub->hvalue,
"false")) {
1244 pjsip_evsub_terminate(
sub, PJ_TRUE);
1248 }
else if (pjsip_evsub_get_state(
sub) == PJSIP_EVSUB_STATE_ACTIVE ||
1249 pjsip_evsub_get_state(
sub) == PJSIP_EVSUB_STATE_TERMINATED) {
1252 pjsip_msg_body *body;
1253 pjsip_status_line status_line = { .code = 0 };
1257 if (
event->type == PJSIP_EVENT_TSX_STATE &&
event->body.tsx_state.type == PJSIP_EVENT_RX_MSG) {
1258 pjsip_rx_data *rdata;
1260 pj_cstr(&refer_str,
"REFER");
1262 rdata =
event->body.tsx_state.src.rdata;
1263 msg = rdata->msg_info.msg;
1265 if (msg->type == PJSIP_RESPONSE_MSG
1266 && (
event->body.tsx_state.tsx->status_code == 401
1267 ||
event->body.tsx_state.tsx->status_code == 407)
1268 && pj_stristr(&refer_str, &
event->body.tsx_state.tsx->method.name)
1273 event->body.tsx_state.src.rdata,
event->body.tsx_state.tsx->last_tx, &tdata)) {
1280 if (msg->type == PJSIP_REQUEST_MSG) {
1281 if (!pjsip_method_cmp(&msg->line.req.method, pjsip_get_notify_method())) {
1283 if (body && !pj_stricmp2(&body->content_type.type,
"message")
1284 && !pj_stricmp2(&body->content_type.subtype,
"sipfrag")) {
1285 pjsip_parse_status_line((
char *)body->data, body->len, &status_line);
1289 status_line.code = msg->line.status.code;
1290 status_line.reason = msg->line.status.reason;
1293 status_line.code = 500;
1294 status_line.reason = *pjsip_get_status_text(500);
1297 is_last = (pjsip_evsub_get_state(
sub) == PJSIP_EVSUB_STATE_TERMINATED);
1299 if (status_line.code >= 200 || is_last) {
1302 refer_success = status_line.code >= 200 && status_line.code < 300;
1307 pjsip_tx_data *tdata;
1309 status = pjsip_evsub_initiate(
sub, pjsip_get_subscribe_method(), 0, &tdata);
1310 if (
status == PJ_SUCCESS) {
1311 pjsip_evsub_send_request(
sub, tdata);
1314 ast_debug(3,
"Refer completed: %d %.*s (%s)\n",
1316 (
int)status_line.reason.slen, status_line.reason.ptr,
1317 refer_success ?
"Success" :
"Failure");
1338 pjsip_tx_data *tdata;
1341 char refer_to_str[PJSIP_MAX_URL_SIZE];
1342 char disp_name_escaped[128];
1344 struct pjsip_evsub_user xfer_cb;
1354 "PJSIP REFER - Could not find endpoint '%s' and no default outbound endpoint configured\n",
1362 ast_log(
LOG_WARNING,
"PJSIP REFER - Refer to not a valid resource identifier or SIP URI\n");
1380 pj_bzero(&xfer_cb,
sizeof(xfer_cb));
1382 if (pjsip_xfer_create_uac(refer->
dlg, &xfer_cb, &
sub) != PJ_SUCCESS) {
1391 snprintf(refer_to_str,
sizeof(refer_to_str),
"\"%s\" <%s>", disp_name_escaped, tmp_str);
1393 snprintf(refer_to_str,
sizeof(refer_to_str),
"%s", tmp_str);
1400 if (pjsip_xfer_initiate(
sub, pj_cstr(&tmp, refer_to_str), &tdata) != PJ_SUCCESS) {
1405 if (refer_to_endpoint && rdata->
to_self) {
1417 ast_debug(1,
"Sending REFER to '%s' (via endpoint %s) from '%s'\n",
1420 if (pjsip_xfer_send_request(
sub, tdata) == PJ_SUCCESS) {
1427 pjsip_evsub_terminate(
sub, PJ_FALSE);
1459 int len = pj_strlen(
str) + 1;
1496 pjsip_replaces_hdr *replaces;
1497 pjsip_generic_string_hdr *referred_hdr;
1507 .disable_inheritance = 1,
1510 static const pj_str_t str_referred_by = {
"Referred-By", 11 };
1511 static const pj_str_t str_referred_by_s = {
"b", 1 };
1512 static const pj_str_t str_replaces = {
"Replaces", 8 };
1523 if (!
state->params) {
1541 referred_hdr = pjsip_msg_find_hdr_by_names(rdata->msg_info.msg,
1542 &str_referred_by, &str_referred_by_s,
NULL);
1545 if (!
state->referred_by) {
1550 if (replaces_param) {
1552 pj_str_t replaces_content = { 0, };
1553 pj_strdup_with_null(rdata->tp_info.pool, &replaces_content, &replaces_param->value);
1556 if (!(replaces = pjsip_parse_hdr(rdata->tp_info.pool, &str_replaces, replaces_content.ptr,
1557 pj_strlen(&replaces_content), &parsed_len))) {
1558 ast_log(
LOG_ERROR,
"Received REFER request on channel '%s' from endpoint '%s' with invalid Replaces header, rejecting\n",
1563 dlg = pjsip_ua_find_dialog(&replaces->call_id, &replaces->to_tag, &replaces->from_tag, PJ_TRUE);
1566 pjsip_dlg_dec_lock(dlg);
1570 if (!
state->protocol_id) {
1585 ast_log(
LOG_ERROR,
"Channel '%s' from endpoint '%s' attempted ari-only transfer but could not defer termination, rejecting\n",
1623 const pj_str_t str_replaces = {
"Replaces", 8 };
1624 pj_str_t replaces_content;
1625 pjsip_replaces_hdr *replaces;
1629 pj_strdup_with_null(rdata->tp_info.pool, &replaces_content, &replaces_param->value);
1632 if (!(replaces = pjsip_parse_hdr(rdata->tp_info.pool, &str_replaces, replaces_content.ptr,
1633 pj_strlen(&replaces_content), &parsed_len))) {
1634 ast_log(
LOG_ERROR,
"Received REFER request on channel '%s' from endpoint '%s' with invalid Replaces header, rejecting\n",
1640 if ((dlg = pjsip_ua_find_dialog(&replaces->call_id, &replaces->to_tag, &replaces->from_tag, PJ_TRUE))) {
1644 pjsip_dlg_dec_lock(dlg);
1646 if (!other_session) {
1647 ast_debug(3,
"Received REFER request on channel '%s' from endpoint '%s' for local dialog but no session exists on it\n",
1654 ast_log(
LOG_ERROR,
"Received REFER request on channel '%s' from endpoint '%s' for local dialog but could not allocate structure to complete, rejecting\n",
1660 ast_log(
LOG_ERROR,
"Received REFER request on channel '%s' from endpoint '%s' for local dialog but could not defer termination, rejecting\n",
1674 ast_debug(3,
"Attended transfer from '%s' pushed to second channel serializer\n",
1686 ast_log(
LOG_ERROR,
"Received REFER for remote session on channel '%s' from endpoint '%s' but 'external_replaces' extension not found in context %s\n",
1699 ast_log(
LOG_ERROR,
"Received REFER for remote session on channel '%s' from endpoint '%s' but could not defer termination, rejecting\n",
1709 if (response != 200) {
1740 ast_debug(3,
"Channel '%s' from endpoint '%s' attempted blind transfer to a target without extension. Target was set to 's@%s'\n",
1745 ast_log(
LOG_ERROR,
"Channel '%s' from endpoint '%s' attempted blind transfer to '%s@%s' but target does not exist\n",
1757 ast_log(
LOG_ERROR,
"Channel '%s' from endpoint '%s' attempted blind transfer but could not defer termination, rejecting\n",
1767 if (response != 200) {
1802 pjsip_dialog *other_dlg =
NULL;
1803 pjsip_tx_data *packet;
1809 if (pjsip_replaces_verify_request(rdata, &other_dlg, PJ_TRUE, &packet) != PJ_SUCCESS) {
1810 response = packet->msg->line.status.code;
1812 pjsip_tx_data_dec_ref(packet);
1813 goto inv_replace_failed;
1822 pjsip_dlg_dec_lock(other_dlg);
1825 if (
session->inv_session->dlg->state == PJSIP_DIALOG_STATE_ESTABLISHED) {
1827 goto inv_replace_failed;
1830 if (!other_session) {
1831 ast_debug(3,
"INVITE with Replaces received on channel '%s' from endpoint '%s', but requested session does not exist\n",
1834 goto inv_replace_failed;
1837 invite.
session = other_session;
1842 goto inv_replace_failed;
1850 ast_debug(3,
"INVITE with Replaces being attempted. '%s' --> '%s'\n",
1891 ast_debug(3,
"INVITE with Replaces successfully completed.\n");
1893 ast_debug(3,
"INVITE with Replaces failed on channel '%s', hanging up with cause '%d'\n",
1904 if (
session->inv_session->dlg->state != PJSIP_DIALOG_STATE_ESTABLISHED) {
1905 ast_debug(3,
"INVITE with Replaces failed on channel '%s', sending response of '%d'\n",
1910 if (pjsip_inv_end_session(
session->inv_session, response,
NULL, &packet) == PJ_SUCCESS
1915 ast_debug(3,
"INVITE with Replaces in-dialog on channel '%s', hanging up\n",
1925 pjsip_generic_string_hdr *refer_to;
1929 pjsip_sip_uri *target_uri;
1931 pjsip_param *replaces;
1934 static const pj_str_t str_refer_to = {
"Refer-To", 8 };
1935 static const pj_str_t str_refer_to_s = {
"r", 1 };
1936 static const pj_str_t str_replaces = {
"Replaces", 8 };
1941 ast_debug(3,
"Received a REFER on a session with no channel from endpoint '%s'.\n",
1946 if (!
session->endpoint->allowtransfer) {
1954 refer_to = pjsip_msg_find_hdr_by_names(rdata->msg_info.msg, &str_refer_to, &str_refer_to_s,
NULL);
1957 ast_debug(3,
"Received a REFER without Refer-To on channel '%s' from endpoint '%s'\n",
1966 uri_size = pj_strlen(&refer_to->hvalue) + 1;
1970 target = pjsip_parse_uri(rdata->tp_info.pool, uri, uri_size - 1, 0);
1973 || (!PJSIP_URI_SCHEME_IS_SIP(target)
1974 && !PJSIP_URI_SCHEME_IS_SIPS(target))) {
1977 ast_debug(3,
"Received a REFER without a parseable Refer-To ('%s') on channel '%s' from endpoint '%s'\n",
1981 target_uri = pjsip_uri_get_uri(target);
1986 ast_debug(3,
"Could not set up subscription for REFER on channel '%s' from endpoint '%s'\n",
1991 replaces = pjsip_param_find(&target_uri->header_param, &str_replaces);
1993 replaces = pjsip_param_find(&target_uri->other_param, &str_replaces);
1997 if (
session->transferhandling_ari) {
1999 }
else if (replaces) {
2007 pjsip_tx_data *tdata;
2008 const pj_str_t str_refer_sub = {
"Refer-Sub", 9 };
2009 const pj_str_t str_false = {
"false", 5 };
2012 ast_debug(3,
"Progress monitoring not requested for REFER on channel '%s' from endpoint '%s', sending immediate response of '%d'\n",
2015 if (pjsip_dlg_create_response(
session->inv_session->dlg, rdata, response,
NULL, &tdata) != PJ_SUCCESS) {
2020 hdr = (pjsip_hdr*)pjsip_generic_string_hdr_create(tdata->pool, &str_refer_sub, &str_false);
2021 pjsip_msg_add_hdr(tdata->msg, hdr);
2023 pjsip_dlg_send_response(
session->inv_session->dlg, pjsip_rdata_get_tsx(rdata), tdata);
2024 }
else if (response != 200) {
2041 if (!pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, pjsip_get_refer_method())) {
2043 }
else if (!pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_invite_method)) {
2066 const char *var_value;
2067 pj_str_t pj_header_name;
2075 pj_cstr(&pj_header_name, header_name);
2076 header = pjsip_msg_find_hdr_by_name(tdata->msg, &pj_header_name,
NULL);
2085 if (pjsip_method_cmp(&tdata->msg->line.req.method, &pjsip_invite_method)
2087 ||
session->inv_session->state != PJSIP_INV_STATE_NULL) {
2105 const pj_str_t str_norefersub = {
"norefersub", 10 };
2148 .
requires =
"res_pjsip,res_pjsip_session,res_pjsip_pubsub",
Asterisk main include file. File version handling, generic pbx functions.
static struct ast_mansession session
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define ast_strdup(str)
A wrapper for strdup()
#define ast_strdupa(s)
duplicate a string in memory from the stack
void ast_free_ptr(void *ptr)
free() wrapper
#define ast_malloc(len)
A wrapper for malloc()
@ AO2_ALLOC_OPT_LOCK_NOLOCK
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define ao2_alloc_options(data_size, destructor_fn, options)
#define ao2_alloc(data_size, destructor_fn)
int ast_bridge_impart(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features, enum ast_bridge_impart_flags flags) attribute_warn_unused_result
Impart a channel to a bridge (non-blocking)
struct ast_bridge * ast_bridge_transfer_acquire_bridge(struct ast_channel *chan)
Acquire the channel's bridge for transfer purposes.
enum ast_transfer_result ast_bridge_transfer_blind(int is_external, struct ast_channel *transferer, const char *exten, const char *context, transfer_channel_cb new_channel_cb, void *user_data)
Blind transfer target to the extension and context provided.
@ AST_BRIDGE_TRANSFER_NOT_PERMITTED
@ AST_BRIDGE_TRANSFER_SUCCESS
@ AST_BRIDGE_TRANSFER_INVALID
@ AST_BRIDGE_TRANSFER_FAIL
@ AST_BRIDGE_IMPART_CHAN_INDEPENDENT
enum ast_transfer_result ast_bridge_transfer_attended(struct ast_channel *to_transferee, struct ast_channel *to_transfer_target)
Attended transfer.
Internal Asterisk hangup causes.
#define AST_CAUSE_FAILURE
const char * ast_channel_name(const struct ast_channel *chan)
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
int ast_queue_hangup(struct ast_channel *chan)
Queue a hangup frame.
#define ast_channel_lock(chan)
#define ast_channel_ref(c)
Increase channel reference count.
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
const char * ast_channel_uniqueid(const struct ast_channel *chan)
int ast_channel_move(struct ast_channel *dest, struct ast_channel *source)
Move a channel from its current location to a new location.
int ast_queue_unhold(struct ast_channel *chan)
Queue an unhold frame.
#define ast_channel_unref(c)
Decrease channel reference count.
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
#define ast_channel_cleanup(c)
Cleanup a channel reference.
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
#define ast_channel_unlock(chan)
#define AST_MAX_EXTENSION
int ast_raw_answer(struct ast_channel *chan)
Answer a channel.
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interface *i)
Attach an framehook onto a channel for frame interception.
ast_framehook_event
These are the types of events that the framehook's event callback can receive.
@ AST_FRAMEHOOK_EVENT_WRITE
int ast_framehook_detach(struct ast_channel *chan, int framehook_id)
Detach an framehook from a channel.
#define AST_FRAMEHOOK_INTERFACE_VERSION
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
struct stasis_message_type * stasis_subscription_change_type(void)
Gets the message type for subscription change notices.
struct ast_sip_endpoint * ast_sip_dialog_get_endpoint(pjsip_dialog *dlg)
Get the endpoint associated with this dialog.
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
struct ast_taskprocessor * ast_sip_create_serializer(const char *name)
Create a new serializer for SIP tasks.
void ast_sip_dialog_set_endpoint(pjsip_dialog *dlg, struct ast_sip_endpoint *endpoint)
Set an endpoint on a SIP dialog so in-dialog requests do not undergo endpoint lookup.
int ast_sip_thread_is_servant(void)
Determine if the current thread is a SIP servant thread.
int ast_sip_push_task_wait_servant(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to SIP servants and wait for it to complete.
int ast_sip_push_task_wait_serializer(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to the serializer and wait for it to complete.
static char prefix[MAX_PREFIX]
@ AST_TRANSFER_UNAVAILABLE
struct ast_frame ast_null_frame
#define ast_debug(level,...)
Log a DEBUG message.
Asterisk module definitions.
#define ast_module_shutdown_ref(mod)
Prevent unload of the module before shutdown.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODULE_SUPPORT_CORE
#define ASTERISK_GPL_KEY
The text the key() function should return.
@ AST_MODULE_LOAD_SUCCESS
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Core PBX routines and definitions.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
Out-of-call refer support.
void ast_refer_var_unref_current(struct ast_refer_var_iterator *iter)
Unref a refer var from inside an iterator loop.
int ast_refer_tech_unregister(const struct ast_refer_tech *tech)
Unregister a refer technology.
const char * ast_refer_get_to(const struct ast_refer *refer)
Retrieve the destination of this refer.
int ast_refer_var_iterator_next(struct ast_refer_var_iterator *iter, const char **name, const char **value)
Get the next variable name and value.
struct ast_refer_var_iterator * ast_refer_var_iterator_init(const struct ast_refer *refer)
Create a new refer variable iterator.
const char * ast_refer_get_from(const struct ast_refer *refer)
Retrieve the source of this refer.
char * ast_refer_get_var_and_unlink(struct ast_refer *refer, const char *name)
Get the specified variable on the refer and unlink it from the container of variables.
struct ast_refer * ast_refer_destroy(struct ast_refer *refer)
Destroy an ast_refer.
int ast_refer_notify_transfer_request(struct ast_channel *originating_chan, const char *referred_by, const char *exten, const char *protocol_id, struct ast_channel *dest, struct ast_refer_params *params, enum ast_control_transfer state)
Notify a transfer request.
const char * ast_refer_get_refer_to(const struct ast_refer *refer)
Get the "refer-to" value of a refer.
int ast_refer_tech_register(const struct ast_refer_tech *tech)
Register a refer technology.
struct ast_refer * ast_refer_ref(struct ast_refer *refer)
Bump a refer's ref count.
int ast_refer_get_to_self(const struct ast_refer *refer)
Retrieve the "to_self" value of this refer.
void ast_refer_var_iterator_destroy(struct ast_refer_var_iterator *iter)
Destroy a refer variable iterator.
struct stasis_forward * sub
struct ast_sip_endpoint * ast_sip_get_endpoint(const char *to, int get_default_outbound, char **uri)
Retrieves an endpoint and URI from the "to" string.
unsigned int ast_sip_get_norefersub(void)
Retrieve the global setting 'norefersub'.
void ast_sip_unregister_service(pjsip_module *module)
int ast_sip_register_service(pjsip_module *module)
Register a SIP service in Asterisk.
pjsip_dialog * ast_sip_create_dialog_uac(const struct ast_sip_endpoint *endpoint, const char *aor_name, const char *request_user)
General purpose method for creating a UAC dialog with an endpoint.
int ast_sip_rewrite_uri_to_local(pjsip_sip_uri *uri, pjsip_tx_data *tdata)
Replace domain and port of SIP URI to point to (external) signaling address of this Asterisk instance...
int ast_sip_create_request_with_auth(const struct ast_sip_auth_vector *auths, pjsip_rx_data *challenge, pjsip_tx_data *tdata, pjsip_tx_data **new_request)
Create a response to an authentication challenge.
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
#define AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(str)
Truncate the URI user field options string if enabled.
int ast_sip_update_from(pjsip_tx_data *tdata, char *from)
Overwrite fields in the outbound 'From' header.
@ AST_SIP_SUPPLEMENT_PRIORITY_CHANNEL
void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
Copy a pj_str_t into a standard character buffer.
int ast_sip_send_request(pjsip_tx_data *tdata, struct pjsip_dialog *dlg, struct ast_sip_endpoint *endpoint, void *token, void(*callback)(void *token, pjsip_event *e))
General purpose method for sending a SIP request.
int ast_sip_update_to_uri(pjsip_tx_data *tdata, const char *to)
Replace the To URI in the tdata with the supplied one.
int ast_sip_add_header(pjsip_tx_data *tdata, const char *name, const char *value)
Add a header to an outbound SIP message.
#define MAX_RX_CHALLENGES
static int refer_unreference_dialog(void *obj)
static void refer_progress_on_evsub_state(pjsip_evsub *sub, pjsip_event *event)
Callback for REFER subscription state changes.
static void add_header_from_channel_var(struct ast_channel *chan, const char *var_name, const char *header_name, pjsip_tx_data *tdata)
Use the value of a channel variable as the value of a SIP header.
static void refer_client_on_evsub_state(pjsip_evsub *sub, pjsip_event *event)
static pjsip_module refer_out_of_dialog_module
REFER Out-of-dialog module, used to attach session data structure to subscription.
static struct ast_taskprocessor * refer_serializer
static int xfer_response_code2sip(enum ast_transfer_result xfer_code)
static void refer_outgoing_request(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
static struct refer_data * refer_data_create(const struct ast_refer *refer)
static void refer_progress_notification_destroy(void *obj)
Destructor for REFER Progress notification structure.
static int refer_incoming_ari_request(struct ast_sip_session *session, pjsip_rx_data *rdata, pjsip_sip_uri *target, pjsip_param *replaces_param, struct refer_progress *progress)
static struct refer_progress_notification * refer_progress_notification_alloc(struct refer_progress *progress, int response, pjsip_evsub_state state)
Allocator for REFER Progress notification structure.
static struct ast_sip_session_supplement refer_supplement
static pjsip_module refer_progress_module
REFER Progress module, used to attach REFER progress structure to subscriptions.
static int dlg_releaser_task(void *data)
static enum pjsip_status_code vars_to_headers(const struct ast_refer *refer, pjsip_tx_data *tdata)
static int is_refer_var_blocked(const char *name)
static int refer_incoming_attended_request(struct ast_sip_session *session, pjsip_rx_data *rdata, pjsip_sip_uri *target_uri, pjsip_param *replaces_param, struct refer_progress *progress)
#define DETERMINE_TRANSFER_CONTEXT(context, session)
static int refer_incoming_blind_request(struct ast_sip_session *session, pjsip_rx_data *rdata, pjsip_sip_uri *target, struct refer_progress *progress)
static const struct ast_refer_tech refer_tech
static int refer_progress_notify(void *data)
Serialized callback for subscription notification.
static int refer_incoming_invite_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
static int refer_incoming_request(struct ast_sip_session *session, pjsip_rx_data *rdata)
static void refer_blind_callback(struct ast_channel *chan, struct transfer_channel_data *user_data_wrapper, enum ast_transfer_type transfer_type)
Blind transfer callback function.
static int refer_incoming_refer_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
static char * copy_string(struct pj_str_t *str)
static void refer_attended_destroy(void *obj)
Destructor for attended transfer task.
static int sip_refer_send(const struct ast_refer *refer)
static void transfer_ari_state_destroy(void *obj)
Destructor of the state used for the ARI transfer.
static int refer_attended_task(void *data)
Task for attended transfer executed by attended->transferer_second serializer.
static pj_status_t refer_on_tx_request(pjsip_tx_data *tdata)
static void refer_params_destroy(void *obj)
static void refer_progress_destroy(void *obj)
Destructor for REFER progress sutrcture.
static int ari_notify(struct transfer_ari_state *state)
static int refer_send(void *data)
static int defer_termination_cancel_task(void *data)
static struct ast_frame * refer_ari_progress_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
Progress monitoring frame hook - examines frames to determine state of transfer. Used for the ari-onl...
static int invite_replaces(void *data)
Task for invite replaces.
static void refer_out_of_dialog_destroy(void *obj)
Destructor for REFER out of dialog structure.
static int session_end_if_deferred_task(void *data)
static int load_module(void)
static int add_refer_param(struct ast_refer_params *params, const char *key, struct pj_str_t *str)
static void refer_progress_framehook_destroy(void *data)
Destroy callback for monitoring framehook.
static int unload_module(void)
static pjsip_uri * get_refer_to_uri(pjsip_tx_data *tdata)
Helper function which returns the name-addr of the Refer-To header or NULL.
static int refer_progress_alloc(struct ast_sip_session *session, pjsip_rx_data *rdata, struct refer_progress **progress)
Internal helper function which sets up a refer progress structure if needed.
static struct ast_frame * refer_progress_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
Progress monitoring frame hook - examines frames to determine state of transfer.
static pjsip_evsub_user refer_progress_evsub_cb
Callback structure for subscription.
static void refer_progress_bridge(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static struct refer_attended * refer_attended_alloc(struct ast_sip_session *transferer, struct ast_sip_session *transferer_second, struct refer_progress *progress)
Allocator for attended transfer task.
static void refer_data_destroy(void *obj)
struct ast_sip_session * ast_sip_dialog_get_session(pjsip_dialog *dlg)
Retrieves a session from a dialog.
void ast_sip_session_defer_termination_cancel(struct ast_sip_session *session)
Cancel a pending deferred termination.
#define ast_sip_session_register_supplement(supplement)
void ast_sip_session_end_if_deferred(struct ast_sip_session *session)
End the session if it had been previously deferred.
void ast_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement)
Unregister a an supplement to SIP session processing.
int ast_sip_session_defer_termination(struct ast_sip_session *session)
Defer local termination of a session until remote side terminates, or an amount of time passes.
void ast_sip_session_send_response(struct ast_sip_session *session, pjsip_tx_data *tdata)
Send a SIP response.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
@ STASIS_SUBSCRIPTION_FILTER_SELECTIVE
int stasis_subscription_accept_message_type(struct stasis_subscription *subscription, const struct stasis_message_type *type)
Indicate to a subscription that we are interested in a message type.
int stasis_subscription_set_filter(struct stasis_subscription *subscription, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a subscription.
#define stasis_subscribe_pool(topic, callback, data)
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
int stasis_subscription_final_message(struct stasis_subscription *sub, struct stasis_message *msg)
Determine whether a message is the final message to be received on a subscription.
struct stasis_subscription * stasis_unsubscribe(struct stasis_subscription *subscription)
Cancel a subscription.
struct stasis_message_type * ast_channel_entered_bridge_type(void)
Message type for ast_channel enter bridge blob messages.
struct stasis_topic * ast_bridge_topic_all(void)
A topic which publishes the events for all bridges.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
Blob of data associated with a bridge.
struct ast_channel_snapshot * channel
Structure that contains information about a bridge.
const ast_string_field uniqueid
struct ast_channel_snapshot_base * base
Main Channel structure associated with a channel.
Data structure associated with a single frame of data.
union ast_frame::@228 data
struct ast_frame_subclass subclass
enum ast_frame_type frametype
const char *const name
Name of this refer technology.
An entity with which Asterisk communicates.
A supplement to SIP message processing.
enum ast_sip_supplement_priority priority
A structure describing a SIP session.
struct ast_channel * channel
struct ast_taskprocessor * serializer
Support for dynamic strings.
A ast_taskprocessor structure is a singleton by name.
Structure used to retrieve channel from another session.
struct ast_sip_session * session
Session we want the channel from.
struct ast_channel * channel
Channel from the session (with reference)
struct ast_bridge * bridge
Bridge the channel is in.
Structure for attended transfer task.
struct ast_sip_session * transferer
Transferer session.
struct ast_sip_session * transferer_second
Second transferer session.
struct refer_progress * progress
Optional refer progress structure.
struct ast_channel * transferer_chan
Transferer channel.
Structure for blind transfer callback details.
pjsip_replaces_hdr * replaces
Optional Replaces header.
pjsip_rx_data * rdata
REFER message.
struct refer_progress * progress
Optional progress structure.
unsigned int attended
Attended transfer flag.
const char * context
Context being used for transfer.
pjsip_sip_uri * refer_to
Optional Refer-To header.
int authentication_challenge_count
REFER Progress notification structure.
pjsip_evsub_state state
Subscription state.
int response
SIP response code to send.
struct refer_progress * progress
Refer progress structure to send notification on.
REFER Progress structure.
struct transfer_channel_data * transfer_data
Reference to transfer_channel_data related to the refer.
pjsip_rx_data * rdata
Received packet, used to construct final response in case no subscription exists.
unsigned int refer_blind_progress
Whether to notifies all the progress details on blind transfer.
pjsip_evsub * sub
Subscription to provide updates on.
int subclass
Last received subclass in frame hook.
pjsip_dialog * dlg
Dialog for subscription.
struct stasis_subscription * bridge_sub
Stasis subscription for bridge events.
struct ast_taskprocessor * serializer
Serializer for notifications.
struct transfer_ari_state * ari_state
State related to the transfer in ARI only mode.
int sent_100
Non-zero if the 100 notify has been sent.
char * transferee
Uniqueid of transferee channel.
int framehook
Frame hook for monitoring REFER progress.
struct ast_sip_session * transferer
A deferred session used by the ARI only mode.
struct ast_sip_session * other_session
char exten[AST_MAX_EXTENSION]
struct ast_channel * transferer_chan
struct ast_refer_params * params
AO2 object that wraps data for transfer_channel_cb.
An API for managing task processing threads that can be shared across modules.
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
void ast_taskprocessor_build_name(char *buf, unsigned int size, const char *format,...)
Build a taskprocessor name with a sequence number on the end.
#define AST_TASKPROCESSOR_MAX_NAME
Suggested maximum taskprocessor name length (less null terminator).
int error(const char *format,...)
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
char * ast_escape_quoted(const char *string, char *outbuf, int buflen)
Escape characters found in a quoted string.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.