aboutsummaryrefslogtreecommitdiffstats
path: root/channels/chan_iax2.c
diff options
context:
space:
mode:
Diffstat (limited to 'channels/chan_iax2.c')
-rw-r--r--channels/chan_iax2.c74
1 files changed, 57 insertions, 17 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index 89ec84335..3b6902e13 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -1104,7 +1104,7 @@ static int send_command_final(struct chan_iax2_pvt *, char, int, unsigned int, c
static int send_command_immediate(struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int, int);
static int send_command_locked(unsigned short callno, char, int, unsigned int, const unsigned char *, int, int);
static int send_command_transfer(struct chan_iax2_pvt *, char, int, unsigned int, const unsigned char *, int);
-static struct ast_channel *iax2_request(const char *type, int format, void *data, int *cause);
+static struct ast_channel *iax2_request(const char *type, int format, const struct ast_channel *requestor, void *data, int *cause);
static struct ast_frame *iax2_read(struct ast_channel *c);
static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly);
static struct iax2_user *build_user(const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly);
@@ -4516,7 +4516,7 @@ static int iax2_getpeertrunk(struct sockaddr_in sin)
}
/*! \brief Create new call, interface with the PBX core */
-static struct ast_channel *ast_iax2_new(int callno, int state, int capability)
+static struct ast_channel *ast_iax2_new(int callno, int state, int capability, const char *linkedid)
{
struct ast_channel *tmp;
struct chan_iax2_pvt *i;
@@ -4529,7 +4529,7 @@ static struct ast_channel *ast_iax2_new(int callno, int state, int capability)
/* Don't hold call lock */
ast_mutex_unlock(&iaxsl[callno]);
- tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "IAX2/%s-%d", i->host, i->callno);
+ tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, linkedid, i->amaflags, "IAX2/%s-%d", i->host, i->callno);
ast_mutex_lock(&iaxsl[callno]);
if (i != iaxs[callno]) {
if (tmp) {
@@ -8003,8 +8003,8 @@ static int iax_park(struct ast_channel *chan1, struct ast_channel *chan2)
struct iax_dual *d;
struct ast_channel *chan1m, *chan2m;
pthread_t th;
- chan1m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan1->exten, chan1->context, chan1->amaflags, "Parking/%s", chan1->name);
- chan2m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan2->exten, chan2->context, chan2->amaflags, "IAXPeer/%s",chan2->name);
+ chan1m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan1->exten, chan1->context, chan1->linkedid, chan1->amaflags, "Parking/%s", chan1->name);
+ chan2m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan2->exten, chan2->context, chan2->linkedid, chan2->amaflags, "IAXPeer/%s", chan2->name);
if (chan2m && chan1m) {
/* Make formats okay */
chan1m->readformat = chan1->readformat;
@@ -8512,6 +8512,35 @@ static struct ast_custom_function iaxvar_function = {
.write = acf_iaxvar_write,
};
+static void set_hangup_source_and_cause(int callno, unsigned char causecode)
+{
+ int locked = 0;
+ struct ast_channel *owner=NULL;
+
+ do {
+ if (ast_channel_trylock(iaxs[callno]->owner)) {
+ DEADLOCK_AVOIDANCE(&iaxsl[callno]);
+ }
+ else {
+ locked = 1;
+ owner = iaxs[callno]->owner;
+ }
+ }
+ while (!locked && iaxs[callno] && iaxs[callno]->owner);
+
+ if (iaxs[callno] && iaxs[callno]->owner) {
+ if (causecode) {
+ iaxs[callno]->owner->hangupcause = causecode;
+ }
+ ast_set_hangupsource(iaxs[callno]->owner, iaxs[callno]->owner->name, 0);
+ ast_channel_unlock(owner);
+ }
+ if (locked) {
+ ast_channel_unlock(owner);
+ }
+}
+
+
static int socket_process(struct iax2_thread *thread)
{
struct sockaddr_in sin;
@@ -8853,7 +8882,7 @@ static int socket_process(struct iax2_thread *thread)
(f.frametype == AST_FRAME_IAX)) {
if (ast_test_flag64(iaxs[fr->callno], IAX_DELAYPBXSTART)) {
ast_clear_flag64(iaxs[fr->callno], IAX_DELAYPBXSTART);
- if (!ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->chosenformat)) {
+ if (!ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->chosenformat, NULL)) {
ast_mutex_unlock(&iaxsl[fr->callno]);
return 1;
}
@@ -9276,17 +9305,28 @@ retryowner:
case IAX_COMMAND_HANGUP:
ast_set_flag64(iaxs[fr->callno], IAX_ALREADYGONE);
ast_debug(1, "Immediately destroying %d, having received hangup\n", fr->callno);
- /* Set hangup cause according to remote */
- if (ies.causecode && iaxs[fr->callno]->owner)
- iaxs[fr->callno]->owner->hangupcause = ies.causecode;
+ /* Set hangup cause according to remote and hangupsource */
+ if (iaxs[fr->callno]->owner) {
+ set_hangup_source_and_cause(fr->callno, ies.causecode);
+ if (!iaxs[fr->callno]) {
+ ast_mutex_unlock(&iaxsl[fr->callno]);
+ return 1;
+ }
+ }
+
/* 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(fr->callno);
break;
case IAX_COMMAND_REJECT:
- /* Set hangup cause according to remote */
- if (ies.causecode && iaxs[fr->callno]->owner)
- iaxs[fr->callno]->owner->hangupcause = ies.causecode;
+ /* Set hangup cause according to remote and hangup source */
+ if (iaxs[fr->callno]->owner) {
+ set_hangup_source_and_cause(fr->callno, ies.causecode);
+ if (!iaxs[fr->callno]) {
+ ast_mutex_unlock(&iaxsl[fr->callno]);
+ return 1;
+ }
+ }
if (!ast_test_flag64(iaxs[fr->callno], IAX_PROVISION)) {
if (iaxs[fr->callno]->owner && authdebug)
@@ -9668,7 +9708,7 @@ retryowner2:
using_prefs);
ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
- if (!(c = ast_iax2_new(fr->callno, AST_STATE_RING, format)))
+ if (!(c = ast_iax2_new(fr->callno, AST_STATE_RING, format, NULL)))
iax2_destroy(fr->callno);
else if (ies.vars) {
struct ast_datastore *variablestore;
@@ -9737,7 +9777,7 @@ immediatedial:
ast_verb(3, "Accepting DIAL from %s, formats = 0x%x\n", ast_inet_ntoa(sin.sin_addr), iaxs[fr->callno]->peerformat);
ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED);
send_command(iaxs[fr->callno], AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, 0, NULL, 0, -1);
- if (!(c = ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->peerformat)))
+ if (!(c = ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->peerformat, NULL)))
iax2_destroy(fr->callno);
else if (ies.vars) {
struct ast_datastore *variablestore;
@@ -10570,7 +10610,7 @@ static void free_context(struct iax2_context *con)
}
}
-static struct ast_channel *iax2_request(const char *type, int format, void *data, int *cause)
+static struct ast_channel *iax2_request(const char *type, int format, const struct ast_channel *requestor, void *data, int *cause)
{
int callno;
int res;
@@ -10622,7 +10662,7 @@ static struct ast_channel *iax2_request(const char *type, int format, void *data
if (cai.found)
ast_string_field_set(iaxs[callno], host, pds.peer);
- c = ast_iax2_new(callno, AST_STATE_DOWN, cai.capability);
+ c = ast_iax2_new(callno, AST_STATE_DOWN, cai.capability, requestor ? requestor->linkedid : NULL);
ast_mutex_unlock(&iaxsl[callno]);
@@ -11086,7 +11126,7 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, st
strsep(&context, "@");
if (ast_strlen_zero(context))
context = "default";
- peer->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
+ peer->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "IAX MWI subscription", NULL,
AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
AST_EVENT_IE_END);