fr.frametype = AST_FRAME_CONTROL;
fr.subclass = AST_CONTROL_HANGUP;
iax2_queue_frame(f->callno, &fr);
+ iaxs[f->callno]->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
} else {
if (iaxs[f->callno]->reg) {
memset(&iaxs[f->callno]->reg->us, 0, sizeof(iaxs[f->callno]->reg->us));
{
unsigned short callno = PTR_TO_CALLNO(c->pvt->pvt);
int alreadygone;
+ struct iax_ie_data ied;
+ memset(&ied, 0, sizeof(ied));
ast_mutex_lock(&iaxsl[callno]);
if (callno && iaxs[callno]) {
ast_log(LOG_DEBUG, "We're hanging up %s now...\n", c->name);
alreadygone = ast_test_flag(iaxs[callno], IAX_ALREADYGONE);
/* Send the hangup unless we have had a transmission error or are already gone */
+ iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause);
if (!iaxs[callno]->error && !alreadygone)
- send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, NULL, 0, -1);
+ send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1);
/* Explicitly predestroy it */
iax2_predestroy_nolock(callno);
/* If we were already gone to begin with, destroy us now */
memset(&ied, 0, sizeof(ied));
if (iaxs[callno]->authfail == IAX_COMMAND_REGREJ) {
iax_ie_append_str(&ied, IAX_IE_CAUSE, "Registration Refused");
+ iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_REJECTED);
} else if (iaxs[callno]->authfail == IAX_COMMAND_REJECT) {
iax_ie_append_str(&ied, IAX_IE_CAUSE, "No authority found");
+ iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED);
}
send_command_final(iaxs[callno], AST_FRAME_IAX, iaxs[callno]->authfail, 0, ied.buf, ied.pos, -1);
}
iaxs[callno]->autoid = -1;
memset(&ied, 0, sizeof(ied));
iax_ie_append_str(&ied, IAX_IE_CAUSE, "Timeout");
+ iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_NO_USER_RESPONSE);
send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1);
}
ast_mutex_unlock(&iaxsl[callno]);
if (strcmp(iaxs[fr.callno]->exten, "TBD") && !exists) {
memset(&ied0, 0, sizeof(ied0));
iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension");
+ iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION);
send_command_final(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
if (authdebug)
ast_log(LOG_NOTICE, "Rejected connect attempt from %s, request '%s@%s' does not exist\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), iaxs[fr.callno]->exten, iaxs[fr.callno]->context);
if (!format) {
memset(&ied0, 0, sizeof(ied0));
iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
+ iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
send_command_final(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
if (authdebug)
ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability 0x%x/0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), iaxs[fr.callno]->peerformat, iaxs[fr.callno]->peercapability, iaxs[fr.callno]->capability);
if (!format) {
memset(&ied0, 0, sizeof(ied0));
iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
+ iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[fr.callno]->peercapability & iaxs[fr.callno]->capability);
send_command_final(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
if (authdebug)
case IAX_COMMAND_HANGUP:
ast_set_flag(iaxs[fr.callno], IAX_ALREADYGONE);
ast_log(LOG_DEBUG, "Immediately destroying %d, having received hangup\n", fr.callno);
+ /* Set hangup cause according to remote */
+ ast_log(LOG_NOTICE, "Remote sent causecode %d\n", ies.causecode);
+ if (ies.causecode)
+ iaxs[fr.callno]->owner->hangupcause = ies.causecode;
/* Send ack immediately, before we destroy */
send_command_immediate(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr.ts, NULL, 0,fr.iseqno);
iax2_destroy_nolock(fr.callno);
if (!(iaxs[fr.callno]->peerformat & iaxs[fr.callno]->capability)) {
memset(&ied0, 0, sizeof(ied0));
iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
+ iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
send_command_final(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
if (authdebug)
ast_log(LOG_NOTICE, "Rejected call to %s, format 0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), iaxs[fr.callno]->peerformat, iaxs[fr.callno]->capability);
ast_log(LOG_NOTICE, "Rejected connect attempt from %s, request '%s@%s' does not exist\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), iaxs[fr.callno]->exten, iaxs[fr.callno]->context);
memset(&ied0, 0, sizeof(ied0));
iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension");
+ iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION);
send_command_final(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
} else {
/* Select an appropriate format */
ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability 0x%x/0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), iaxs[fr.callno]->peerformat, iaxs[fr.callno]->peercapability, iaxs[fr.callno]->capability);
memset(&ied0, 0, sizeof(ied0));
iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
+ iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
send_command_final(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
} else {
/* Pick one... */
ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability 0x%x/0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), iaxs[fr.callno]->peerformat, iaxs[fr.callno]->peercapability, iaxs[fr.callno]->capability);
memset(&ied0, 0, sizeof(ied0));
iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec");
+ iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
send_command_final(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
}
}
ast_log(LOG_NOTICE, "Rejected dial attempt from %s, request '%s@%s' does not exist\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), iaxs[fr.callno]->exten, iaxs[fr.callno]->context);
memset(&ied0, 0, sizeof(ied0));
iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension");
+ iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION);
send_command_final(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
} else {
iaxs[fr.callno]->state |= IAX_STATE_STARTED;
if (registry_rerequest(&ies, fr.callno, &sin)) {
memset(&ied0, 0, sizeof(ied0));
iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No authority found");
+ iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED);
send_command_final(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1);
}
break;