- A new manager event, "SessionTimeout" has been added and is triggered when
a call is terminated due to RTP stream inactivity or SIP session timer
expiration.
+ - SIP_CAUSE is now deprecated. It has been modified to use the same
+ mechanism as HANGUPCAUSE. Behavior should not change, but performance
+ should be vastly improved. The HANGUPCAUSE hash should now be used instead
+ of SIP_CAUSE. Because of this, the storesipcause option in sip.conf is also
+ deprecated.
chan_unistim
- Due to massive update in chan_unistim phone keys functions and on-screen
cc_frame_received = 1;
}
break;
+ case AST_CONTROL_PVT_CAUSE_CODE:
+ ast_indicate_data(in, AST_CONTROL_PVT_CAUSE_CODE, f->data.ptr, f->datalen);
+ break;
case -1:
if (single && !caller_entertained) {
ast_verb(3, "%s stopped sounds\n", ast_channel_name(c));
* the caller.
*/
break;
+ case AST_CONTROL_PVT_CAUSE_CODE:
+ ast_indicate_data(caller, f->subclass.integer, f->data.ptr, f->datalen);
+ break;
case -1:
ast_verb(3, "%s stopped sounds\n", ast_channel_name(winner));
break;
}
}
break;
+ case AST_CONTROL_PVT_CAUSE_CODE:
+ ast_indicate_data(in, AST_CONTROL_PVT_CAUSE_CODE, f->data.ptr, f->datalen);
+ break;
default:
ast_debug(1, "Dunno what to do with control type %d\n", f->subclass.integer);
break;
case AST_CONTROL_CONGESTION:
case AST_CONTROL_RINGING:
case AST_CONTROL_INCOMPLETE:
+ case AST_CONTROL_PVT_CAUSE_CODE:
case -1:
res = -1; /* Ask for inband indications */
break;
case AST_CONTROL_CONGESTION:
case AST_CONTROL_RINGING:
case AST_CONTROL_INCOMPLETE:
+ case AST_CONTROL_PVT_CAUSE_CODE:
case -1:
res = -1; /* Ask for inband indications */
break;
break;
default:
ast_debug(3, "Don't know how to indicate condition '%d'\n", condition);
+ /* fallthrough */
+ case AST_CONTROL_PVT_CAUSE_CODE:
res = -1;
}
res = 0;
break;
case AST_CONTROL_PROCEEDING:
+ case AST_CONTROL_PVT_CAUSE_CODE:
case -1:
break;
default:
if (!ast_test_flag64(pvt, IAX_SENDCONNECTEDLINE))
goto done;
break;
+ case AST_CONTROL_PVT_CAUSE_CODE:
+ res = -1;
+ break;
}
res = send_command(pvt, AST_FRAME_CONTROL, condition, 0, data, datalen, -1);
break;
default:
ast_log(LOG_NOTICE, "Don't know how to indicate condition '%d'\n", condition);
+ /* fallthrough */
+ case AST_CONTROL_PVT_CAUSE_CODE:
res = -1;
}
break;
default:
ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
+ /* fallthrough */
+ case AST_CONTROL_PVT_CAUSE_CODE:
res = -1;
}
ast_mutex_unlock(&sub->lock);
break;
default:
chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n", cond, p->bc->pid);
+ /* fallthrough */
+ case AST_CONTROL_PVT_CAUSE_CODE:
return -1;
}
case AST_CONTROL_BUSY:
case AST_CONTROL_CONGESTION:
case AST_CONTROL_RINGING:
+ case AST_CONTROL_PVT_CAUSE_CODE:
case -1:
res = -1;
break;
case AST_CONTROL_SRCUPDATE:
res = 0;
break;
+ case AST_CONTROL_PVT_CAUSE_CODE:
+ break;
default:
ast_log(LOG_WARNING, "Condition %d is not supported on channel %s\n", condition, ast_channel_name(chan));
}
break;
case AST_CONTROL_UPDATE_RTP_PEER: /* Absorb this since it is handled by the bridge */
break;
+ case AST_CONTROL_PVT_CAUSE_CODE: /* these should be handled by the code in channel.c */
case -1:
res = -1;
break;
ast_debug(1, "Ignoring out of order response %u (expecting %u)\n", seqno, p->ocseq);
return -1;
} else {
- char causevar[256], causeval[256];
-
if ((respid == 200) || ((respid >= 300) && (respid <= 399))) {
extract_uri(p, req);
}
- handle_response(p, respid, e + len, req, seqno);
+ if (p->owner) {
+ struct ast_control_pvt_cause_code *cause_code;
+ int data_size = sizeof(*cause_code);
+ /* size of the string making up the cause code is "SIP " + cause length */
+ data_size += 4 + strlen(REQ_OFFSET_TO_STR(req, rlPart2));
+ cause_code = alloca(data_size);
- if (global_store_sip_cause && p->owner) {
- struct ast_channel *owner = p->owner;
+ ast_copy_string(cause_code->chan_name, ast_channel_name(p->owner), AST_CHANNEL_NAME);
- snprintf(causevar, sizeof(causevar), "MASTER_CHANNEL(HASH(SIP_CAUSE,%s))", ast_channel_name(owner));
- snprintf(causeval, sizeof(causeval), "SIP %s", REQ_OFFSET_TO_STR(req, rlPart2));
+ snprintf(cause_code->code, data_size - sizeof(*cause_code) + 1, "SIP %s", REQ_OFFSET_TO_STR(req, rlPart2));
- ast_channel_ref(owner);
- sip_pvt_unlock(p);
- ast_channel_unlock(owner);
- *nounlock = 1;
- pbx_builtin_setvar_helper(owner, causevar, causeval);
- ast_channel_unref(owner);
- sip_pvt_lock(p);
+ if (global_store_sip_cause) {
+ cause_code->emulate_sip_cause = 1;
+ }
+
+ ast_queue_control_data(p->owner, AST_CONTROL_PVT_CAUSE_CODE, cause_code, data_size);
}
+
+ handle_response(p, respid, e + len, req, seqno);
}
return 0;
}
}
} else if (!strcasecmp(v->name, "storesipcause")) {
global_store_sip_cause = ast_true(v->value);
+ if (global_store_sip_cause) {
+ ast_log(LOG_WARNING, "Usage of SIP_CAUSE is deprecated. Please use HANGUPCAUSE instead.\n");
+ }
} else if (!strcasecmp(v->name, "qualifygap")) {
if (sscanf(v->value, "%30d", &global_qualify_gap) != 1) {
ast_log(LOG_WARNING, "Invalid qualifygap '%s' at line %d of %s\n", v->value, v->lineno, config);
break;
default:
ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
+ /* fallthrough */
+ case AST_CONTROL_PVT_CAUSE_CODE:
return -1; /* Tell asterisk to provide inband signalling */
}
return 0;
break;
default:
ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
+ /* fallthrough */
+ case AST_CONTROL_PVT_CAUSE_CODE:
return -1;
}
case AST_CONTROL_UNHOLD:
ast_moh_stop(ast);
break;
+ case AST_CONTROL_PVT_CAUSE_CODE:
+ res = -1;
+ break;
default:
res = 0;
break;
; jblog = no ; Enables jitterbuffer frame logging. Defaults to "no".
-;----------------------------- SIP_CAUSE reporting ---------------------------------
-; storesipcause = no ; This option causes chan_sip to set the
- ; HASH(SIP_CAUSE,<channel name>) channel variable
- ; to the value of the last sip response.
- ; WARNING: enabling this option carries a
- ; significant performance burden. It should only
- ; be used in low call volume situations. This
- ; option defaults to "no".
-
;-----------------------------------------------------------------------------------
[authentication]
case AST_CONTROL_UPDATE_RTP_PEER:
ast_verbose("SubClass: UPDATE_RTP_PEER\n");
break;
+ case AST_CONTROL_PVT_CAUSE_CODE:
+ ast_verbose("SubClass: PVT_CAUSE_CODE\n");
+ break;
}
if (frame->subclass.integer == -1) {
AST_CONTROL_INCOMPLETE = 30, /*!< Indication that the extension dialed is incomplete */
AST_CONTROL_MCID = 31, /*!< Indicate that the caller is being malicious. */
AST_CONTROL_UPDATE_RTP_PEER = 32, /*!< Interrupt the bridge and have it update the peer */
+ AST_CONTROL_PVT_CAUSE_CODE = 33, /*!< Contains an update to the protocol-specific cause-code stored for branching dials */
};
enum ast_frame_read_action {
AST_TRANSFER_FAILED, /*!< Transfer request on the channel failed */
};
+struct ast_control_pvt_cause_code {
+ char chan_name[AST_CHANNEL_NAME]; /*!< Name of the channel that originated the cause information */
+ unsigned int emulate_sip_cause:1; /*!< Indicates whether this should be used to emulate SIP_CAUSE support */
+ char code[1]; /*!< Tech-specific cause code information, beginning with the name of the tech */
+};
+
#define AST_SMOOTHER_FLAG_G729 (1 << 0)
#define AST_SMOOTHER_FLAG_BE (1 << 1)
ast_frfree(f);
ast_clear_flag(ast_channel_flags(c), AST_FLAG_END_DTMF_ONLY);
return -1;
+ case AST_CONTROL_PVT_CAUSE_CODE:
case AST_CONTROL_RINGING:
case AST_CONTROL_ANSWER:
case AST_CONTROL_SRCUPDATE:
case AST_CONTROL_END_OF_Q:
case AST_CONTROL_MCID:
case AST_CONTROL_UPDATE_RTP_PEER:
+ case AST_CONTROL_PVT_CAUSE_CODE:
break;
case AST_CONTROL_INCOMPLETE:
case AST_CONTROL_CONGESTION:
ts = ast_get_indication_tone(ast_channel_zone(chan), "congestion");
break;
+ case AST_CONTROL_PVT_CAUSE_CODE:
+ {
+ char causevar[256];
+ const struct ast_control_pvt_cause_code *cause_code = data;
+
+ snprintf(causevar, sizeof(causevar), "HASH(HANGUPCAUSE,%s)", cause_code->chan_name);
+ ast_func_write(chan, causevar, cause_code->code);
+ if (cause_code->emulate_sip_cause) {
+ snprintf(causevar, sizeof(causevar), "HASH(SIP_CAUSE,%s)", cause_code->chan_name);
+ ast_func_write(chan, causevar, cause_code->code);
+ }
+
+ res = 0;
+ break;
+ }
case AST_CONTROL_PROGRESS:
case AST_CONTROL_PROCEEDING:
case AST_CONTROL_VIDUPDATE:
break;
/* Ignore these */
+ case AST_CONTROL_PVT_CAUSE_CODE:
case AST_CONTROL_PROGRESS:
case AST_CONTROL_PROCEEDING:
case AST_CONTROL_HOLD:
int bridge_exit = 0;
switch (f->subclass.integer) {
+ case AST_CONTROL_PVT_CAUSE_CODE:
case AST_CONTROL_AOC:
case AST_CONTROL_MCID:
ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
case AST_CONTROL_OFFHOOK:
case AST_CONTROL_FLASH:
break;
+ case AST_CONTROL_PVT_CAUSE_CODE:
+ ast_indicate_data(chan, AST_CONTROL_PVT_CAUSE_CODE, fr->data.ptr, fr->datalen);
+ break;
case -1:
/* Prod the channel */
ast_indicate(chan, -1);
ast_frfree(f);
ready=1;
break;
+ } else if (f->subclass.integer == AST_CONTROL_PVT_CAUSE_CODE) {
+ ast_indicate_data(caller, AST_CONTROL_PVT_CAUSE_CODE, f->data.ptr, f->datalen);
+ ast_frfree(f);
+ break;
} else if (f->subclass.integer == AST_CONTROL_CONNECTED_LINE) {
if (caller_hungup) {
struct ast_party_connected_line connected;
ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
}
break;
+ case AST_CONTROL_PVT_CAUSE_CODE:
case AST_CONTROL_AOC:
case AST_CONTROL_HOLD:
case AST_CONTROL_UNHOLD:
case AST_CONTROL_REDIRECTING:
case AST_CONTROL_AOC:
case AST_CONTROL_UPDATE_RTP_PEER:
+ case AST_CONTROL_PVT_CAUSE_CODE:
case -1:
/* Unimportant */
break;
ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen);
}
ast_frfree(fr);
+ } else if (fr->subclass.integer == AST_CONTROL_PVT_CAUSE_CODE) {
+ ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen);
+ ast_frfree(fr);
} else {
*fo = fr;
*rc = who;
ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen);
}
ast_frfree(fr);
+ } else if (fr->subclass.integer == AST_CONTROL_PVT_CAUSE_CODE) {
+ ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen);
+ ast_frfree(fr);
} else {
*fo = fr;
*rc = who;