]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Ensure that pvt cause information does not break native bridging
authorKinsey Moore <kmoore@digium.com>
Tue, 19 Jun 2012 21:13:41 +0000 (21:13 +0000)
committerKinsey Moore <kmoore@digium.com>
Tue, 19 Jun 2012 21:13:41 +0000 (21:13 +0000)
Channel drivers that allow native bridging need to handle
AST_CONTROL_PVT_CAUSE_CODE frames and previously did not handle them
properly, usually breaking out of the native bridge. This change
corrects that behavior and exposes the available cause code information
to the dialplan while native bridges are in place. This required
exposing the HANGUPCAUSE hash setter outside of channel.c, so
additional documentation has been added.

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@369086 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_dahdi.c
channels/chan_iax2.c
channels/chan_misdn.c
include/asterisk/channel.h
main/channel.c
main/rtp_engine.c

index 6c5b00ef048d4702665dae349f8141a8fac33346..d90662bc9b41f7da136615c7d9545e122d6f3e67 100644 (file)
@@ -7586,6 +7586,10 @@ static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_ch
                f = ast_read(who);
                switch (f ? f->frametype : AST_FRAME_CONTROL) {
                case AST_FRAME_CONTROL:
+                       if (f && f->subclass.integer == AST_CONTROL_PVT_CAUSE_CODE) {
+                               ast_channel_hangupcause_hash_set((who == c0) ? c1 : c0, f->data.ptr);
+                               break;
+                       }
                        *fo = f;
                        *rc = who;
                        res = AST_BRIDGE_COMPLETE;
index 8f42bf3854e4b04e932f97193b1238daf62175b0..a723d2cf403559cb56f23e64be8f80f1ead196a2 100644 (file)
@@ -5593,19 +5593,24 @@ static enum ast_bridge_result iax2_bridge(struct ast_channel *c0, struct ast_cha
                        res = AST_BRIDGE_COMPLETE;
                        break;
                }
-               if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS) && (f->subclass.integer != AST_CONTROL_SRCUPDATE)) {
-                       *fo = f;
-                       *rc = who;
-                       res =  AST_BRIDGE_COMPLETE;
-                       break;
-               }
                other = (who == c0) ? c1 : c0;  /* the 'other' channel */
+               if ((f->frametype == AST_FRAME_CONTROL)) {
+                       if (f->subclass.integer == AST_CONTROL_PVT_CAUSE_CODE) {
+                               ast_channel_hangupcause_hash_set(other, f->data.ptr);
+                       } else if (!(flags & AST_BRIDGE_IGNORE_SIGS)
+                               && (f->subclass.integer != AST_CONTROL_SRCUPDATE)) {
+                               *fo = f;
+                               *rc = who;
+                               res =  AST_BRIDGE_COMPLETE;
+                               break;
+                       }
+               }
                if ((f->frametype == AST_FRAME_VOICE) ||
                        (f->frametype == AST_FRAME_TEXT) ||
                        (f->frametype == AST_FRAME_VIDEO) || 
                        (f->frametype == AST_FRAME_IMAGE) ||
                        (f->frametype == AST_FRAME_DTMF) ||
-                       (f->frametype == AST_FRAME_CONTROL)) {
+                       (f->frametype == AST_FRAME_CONTROL && f->subclass.integer != AST_CONTROL_PVT_CAUSE_CODE)) {
                        /* monitored dtmf take out of the bridge.
                         * check if we monitor the specific source.
                         */
index ffae020f8a18c8042679384bd52917af37526fa4..b81d7ca5a5b4ea9e91116731e7c76b89f4c5720d 100644 (file)
@@ -7583,7 +7583,7 @@ static enum ast_bridge_result misdn_bridge(struct ast_channel *c0,
                }
                f = ast_read(who);
 
-               if (!f || f->frametype == AST_FRAME_CONTROL) {
+               if (!f || (f->frametype == AST_FRAME_CONTROL && f->subtype.integer != AST_CONTROL_PVT_CAUSE_CODE)) {
                        /* got hangup .. */
 
                        if (!f) {
@@ -7613,7 +7613,11 @@ static enum ast_bridge_result misdn_bridge(struct ast_channel *c0,
                }
 #endif
 
-               ast_write((who == c0) ? c1 : c0, f);
+               if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_PVT_CAUSE_CODE) {
+                       ast_channel_hangupcause_hash_set((who == c0) ? c1 : c0, f->data.ptr);
+               } else {
+                       ast_write((who == c0) ? c1 : c0, f);
+               }
        }
 
        chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid + 1);
index 170755b79b4e6a4c288f9466b494392044820399..06be07b2ad823b2eca0336af5a6d36b053ec1cf8 100644 (file)
@@ -3565,6 +3565,15 @@ int ast_channel_get_cc_agent_type(struct ast_channel *chan, char *agent_type, si
  */
 void ast_channel_unlink(struct ast_channel *chan);
 
+/*!
+ * \brief Sets the HANGUPCAUSE hash and optionally the SIP_CAUSE hash 
+ * on the given channel
+ *
+ * \param chan channel on which to set the cause information
+ * \param cause_code ast_control_pvt_cause_code structure containing cause information
+ */
+void ast_channel_hangupcause_hash_set(struct ast_channel *chan, const struct ast_control_pvt_cause_code *cause_code);
+
 /* ACCESSOR FUNTIONS */
 /*! \brief Set the channel name */
 void ast_channel_name_set(struct ast_channel *chan, const char *name);
index 9955dea6868945693d7775313ca854fd02e77986..59d40dc6c531f2d8a92923c56625855d4cd3a5cc 100644 (file)
@@ -4208,12 +4208,9 @@ static int attribute_const is_visible_indication(enum ast_control_frame_type con
        return 0;
 }
 
-/*! \brief Sets the HANGUPCAUSE hash and optionally the SIP_CAUSE hash 
- * on the given channel */
-static void set_hangupcause_hash(struct ast_channel *chan, const void *data)
+void ast_channel_hangupcause_hash_set(struct ast_channel *chan, const struct ast_control_pvt_cause_code *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);
@@ -4368,7 +4365,7 @@ int ast_indicate_data(struct ast_channel *chan, int _condition,
                ts = ast_get_indication_tone(ast_channel_zone(chan), "congestion");
                break;
        case AST_CONTROL_PVT_CAUSE_CODE:
-               set_hangupcause_hash(chan, data);
+               ast_channel_hangupcause_hash_set(chan, data);
                res = 0;
                break;
        case AST_CONTROL_PROGRESS:
@@ -5515,7 +5512,7 @@ struct ast_channel *__ast_request_and_dial(const char *type, struct ast_format_c
                                        break;
 
                                case AST_CONTROL_PVT_CAUSE_CODE:
-                                       set_hangupcause_hash(chan, f->data.ptr);
+                                       ast_channel_hangupcause_hash_set(chan, f->data.ptr);
                                        break;
 
                                /* Ignore these */
index 81c2a0a5616e39cde9de6e97bf4f9f07f15736df..297bf3b77f28b611be84f090e6d51d433a1c8994 100644 (file)
@@ -933,7 +933,7 @@ static enum ast_bridge_result local_bridge_loop(struct ast_channel *c0, struct a
                                }
                                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_channel_hangupcause_hash_set(other, fr->data.ptr);
                                ast_frfree(fr);
                        } else {
                                *fo = fr;
@@ -1227,7 +1227,7 @@ static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0,
                                }
                                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_channel_hangupcause_hash_set(other, fr->data.ptr);
                                ast_frfree(fr);
                        } else {
                                *fo = fr;