]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Updated SIP 484 handling; added Incomplete control frame
authorMatthew Jordan <mjordan@digium.com>
Fri, 9 Sep 2011 16:09:09 +0000 (16:09 +0000)
committerMatthew Jordan <mjordan@digium.com>
Fri, 9 Sep 2011 16:09:09 +0000 (16:09 +0000)
When a SIP phone uses the dial application and receives a 484 Address
Incomplete response, if overlapped dialing is enabled for SIP, then
the 484 Address Incomplete is forwarded back to the SIP phone and the
HANGUPCAUSE channel variable is set to 28.  Previously, the Incomplete
application dialplan logic was automatically triggered; now, explicit
dialplan usage of the application is required.

Additionally, this patch adds a new AST_CONTOL_FRAME type called
AST_CONTROL_INCOMPLETE.  If a channel driver receives this control frame,
it is an indication that the dialplan expects more digits back from the
device.  If the device supports overlap dialing it should attempt to
notify the device that the dialplan is waiting for more digits; otherwise,
it can handle the frame in a manner appropriate to the channel driver.

(closes issue ASTERISK-17288)
Reported by: Mikael Carlsson
Tested by: Matthew Jordan

Review: https://reviewboard.asterisk.org/r/1416/

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

21 files changed:
addons/chan_ooh323.c
apps/app_dial.c
channels/chan_alsa.c
channels/chan_console.c
channels/chan_dahdi.c
channels/chan_h323.c
channels/chan_mgcp.c
channels/chan_misdn.c
channels/chan_oss.c
channels/chan_sip.c
channels/chan_skinny.c
channels/chan_unistim.c
channels/chan_usbradio.c
channels/sig_pri.c
channels/sig_ss7.c
funcs/func_frame_trace.c
include/asterisk/frame.h
main/channel.c
main/dial.c
main/features.c
main/pbx.c

index c3467769845752535278c4d6c9418f35e77c4eac..830a6232020523694b7f1eec20f06ac5b3c6ed73 100644 (file)
@@ -1226,21 +1226,24 @@ static int ooh323_indicate(struct ast_channel *ast, int condition, const void *d
         
        ast_mutex_lock(&p->lock);
        switch (condition) {
+       case AST_CONTROL_INCOMPLETE:
+               /* While h323 does support overlapped dialing, this channel driver does not
+                * at this time.  Treat a response of Incomplete as if it were congestion.
+                */
        case AST_CONTROL_CONGESTION:
                if (!ast_test_flag(p, H323_ALREADYGONE)) {
-                       ooHangCall(callToken, OO_REASON_LOCAL_CONGESTED, 
-                                               AST_CAUSE_SWITCH_CONGESTION);
+                       ooHangCall(callToken, OO_REASON_LOCAL_CONGESTED, AST_CAUSE_SWITCH_CONGESTION);
                        ast_set_flag(p, H323_ALREADYGONE);
                }
                break;
        case AST_CONTROL_BUSY:
                if (!ast_test_flag(p, H323_ALREADYGONE)) {
-                       ooHangCall(callToken, OO_REASON_LOCAL_BUSY, AST_CAUSE_USER_BUSY);
+                       ooHangCall(callToken, OO_REASON_LOCAL_BUSY, AST_CAUSE_USER_BUSY);
                        ast_set_flag(p, H323_ALREADYGONE);
                }
                break;
        case AST_CONTROL_HOLD:
-               ast_moh_start(ast, data, NULL);         
+               ast_moh_start(ast, data, NULL);
                break;
        case AST_CONTROL_UNHOLD:
                ast_moh_stop(ast);
index 515fa1b3f69cc86bcd3251d89df5c3fb0221bae0..c92dec2639e585a2f3f52c598c15202e1422a31a 100644 (file)
@@ -2423,14 +2423,6 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
                } else { /* Nobody answered, next please? */
                        res = 0;
                }
-
-               /* SIP, in particular, sends back this error code to indicate an
-                * overlap dialled number needs more digits. */
-               if (chan->hangupcause == AST_CAUSE_INVALID_NUMBER_FORMAT) {
-                       res = AST_PBX_INCOMPLETE;
-               }
-
-               /* almost done, although the 'else' block is 400 lines */
        } else {
                const char *number;
 
index 36745326da983e861429999dd334d22e5f41303b..5014da5ab7b464eb9486f521c855afbc332e6e7f 100644 (file)
@@ -537,6 +537,7 @@ static int alsa_indicate(struct ast_channel *chan, int cond, const void *data, s
        case AST_CONTROL_BUSY:
        case AST_CONTROL_CONGESTION:
        case AST_CONTROL_RINGING:
+       case AST_CONTROL_INCOMPLETE:
        case -1:
                res = -1;  /* Ask for inband indications */
                break;
index 269ccaff18131fe4faa16e40182837ee91c13630..1217392eab15286ff1005f210fbda642a3e38d2e 100644 (file)
@@ -610,6 +610,7 @@ static int console_indicate(struct ast_channel *chan, int cond, const void *data
        case AST_CONTROL_BUSY:
        case AST_CONTROL_CONGESTION:
        case AST_CONTROL_RINGING:
+       case AST_CONTROL_INCOMPLETE:
        case -1:
                res = -1;  /* Ask for inband indications */
                break;
index 909ff92b21e47daefa514565404c91de06c3c49c..3bacfb14a3d2abde71d18cef2544e53b60b99d46 100644 (file)
@@ -9315,13 +9315,18 @@ static int dahdi_indicate(struct ast_channel *chan, int condition, const void *d
                                ast_setstate(chan, AST_STATE_RINGING);
                        }
                        break;
+               case AST_CONTROL_INCOMPLETE:
+                       ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", chan->name);
+                       /* act as a progress or proceeding, allowing the caller to enter additional numbers */
+                       res = 0;
+                       break;
                case AST_CONTROL_PROCEEDING:
-                       ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
+                       ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", chan->name);
                        /* don't continue in ast_indicate */
                        res = 0;
                        break;
                case AST_CONTROL_PROGRESS:
-                       ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
+                       ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", chan->name);
                        /* don't continue in ast_indicate */
                        res = 0;
                        break;
index 0d2a9ee86b825a33968348a79769608ecd749b97..fbca7e8209b0261920c75973d7813ee50a813d6a 100644 (file)
@@ -900,6 +900,10 @@ static int oh323_indicate(struct ast_channel *c, int condition, const void *data
                        res = 0;
                }
                break;
+       case AST_CONTROL_INCOMPLETE:
+               /* While h323 does support overlapped dialing, this channel driver does not
+                * at this time.  Treat a response of Incomplete as if it were congestion.
+                */
        case AST_CONTROL_CONGESTION:
                if (c->_state != AST_STATE_UP) {
                        h323_answering_call(token, 1);
index aa98d9c10add791d18241409e94d92785b410560..49f18674604797c15266d55695873a97b7a79163 100644 (file)
@@ -1457,6 +1457,10 @@ static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, siz
        case AST_CONTROL_BUSY:
                transmit_notify_request(sub, "L/bz");
                break;
+       case AST_CONTROL_INCOMPLETE:
+               /* We do not currently support resetting of the Interdigit Timer, so treat
+                * Incomplete control frames as a congestion response
+                */
        case AST_CONTROL_CONGESTION:
                transmit_notify_request(sub, sub->parent->ncs ? "L/cg" : "G/cg");
                break;
index 76b250d8147c2fbe85e71bcbcb3ffc06b30909ec..37c4d08f33c0bfd7b10c8658afd0be13e96e8686 100644 (file)
@@ -6983,6 +6983,19 @@ static int misdn_indication(struct ast_channel *ast, int cond, const void *data,
                chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n", p->bc->pid);
                misdn_lib_send_event(p->bc, EVENT_PROCEEDING);
                break;
+       case AST_CONTROL_INCOMPLETE:
+               chan_misdn_log(1, p->bc->port, " --> *\tincomplete pid:%d\n", p->bc->pid);
+               if (!p->overlap_dial) {
+                       /* Overlapped dialing not enabled - send hangup */
+                       p->bc->out_cause = AST_CAUSE_INVALID_NUMBER_FORMAT;
+                       start_bc_tones(p);
+                       misdn_lib_send_event(p->bc, EVENT_DISCONNECT);
+
+                       if (p->bc->nt) {
+                               hanguptone_indicate(p);
+                       }
+               }
+               break;
        case AST_CONTROL_CONGESTION:
                chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n", p->bc->pid);
 
index 01f579d20c687faafccf34844015375e91d0fd20..df25ceed8d757b900cd192908358c357dc38be19 100644 (file)
@@ -755,6 +755,7 @@ static int oss_indicate(struct ast_channel *c, int cond, const void *data, size_
        int res = 0;
 
        switch (cond) {
+       case AST_CONTROL_INCOMPLETE:
        case AST_CONTROL_BUSY:
        case AST_CONTROL_CONGESTION:
        case AST_CONTROL_RINGING:
index 3f0c46f8f424821bffedfc482aadea476d60fbfa..433f3f4291a36c0aaaee6add5e8770534dbc2837 100644 (file)
@@ -6677,6 +6677,20 @@ static int sip_indicate(struct ast_channel *ast, int condition, const void *data
                }
                res = -1;
                break;
+       case AST_CONTROL_INCOMPLETE:
+               if (ast->_state != AST_STATE_UP) {
+                       if (ast_test_flag(&p->flags[1], SIP_PAGE2_ALLOWOVERLAP)) {
+                               transmit_response_reliable(p, "484 Address Incomplete", &p->initreq);
+                       } else {
+                               transmit_response_reliable(p, "404 Not Found", &p->initreq);
+                       }
+                       p->invitestate = INV_COMPLETED;
+                       sip_alreadygone(p);
+                       ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
+                       break;
+               }
+               res = 0;
+               break;
        case AST_CONTROL_PROCEEDING:
                if ((ast->_state != AST_STATE_UP) &&
                    !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) &&
@@ -20619,6 +20633,15 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
                                        if (owner)
                                                ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
                                        break;
+                               case 484: /* Address Incomplete */
+                                       if (owner && sipmethod != SIP_BYE) {
+                                               if (ast_test_flag(&p->flags[1], SIP_PAGE2_ALLOWOVERLAP)) {
+                                                       ast_queue_hangup_with_cause(p->owner, hangup_sip2cause(resp));
+                                               } else {
+                                                       ast_queue_hangup_with_cause(p->owner, hangup_sip2cause(404));
+                                               }
+                                       }
+                                       break;
                                default:
                                        /* Send hangup */       
                                        if (owner && sipmethod != SIP_BYE)
index 799b578cba59e7c36bbcd8be3208e21079358ce0..77435065f3af7c923909779bcd123d11f1399315 100644 (file)
@@ -4290,6 +4290,8 @@ static char *control2str(int ind) {
                return "Connected Line";
        case AST_CONTROL_REDIRECTING:
                return "Redirecting";
+       case AST_CONTROL_INCOMPLETE:
+               return "Incomplete";
        case -1:
                return "Stop tone";
        default:
@@ -4423,6 +4425,8 @@ static int skinny_indicate(struct ast_channel *ast, int ind, const void *data, s
                        }
                }
                return -1; /* Tell asterisk to provide inband signalling */
+       case AST_CONTROL_INCOMPLETE:
+               /* Support for incomplete not supported for chan_skinny; treat as congestion */
        case AST_CONTROL_CONGESTION:
                if (ast->_state != AST_STATE_UP) {
                        if (!d->earlyrtp) {
index eac458f0174c1734e4bdce8292c0f177d2640cda..0d48ee43ebc64c86267076a46d27fd60250e6934 100644 (file)
@@ -4182,6 +4182,10 @@ static int unistim_indicate(struct ast_channel *ast, int ind, const void *data,
                        break;
                }
                return -1;
+       case AST_CONTROL_INCOMPLETE:
+               /* Overlapped dialing is not currently supported for UNIStim.  Treat an indication
+                * of incomplete as congestion
+                */
        case AST_CONTROL_CONGESTION:
                if (ast->_state != AST_STATE_UP) {
                        sub->alreadygone = 1;
index 4c9793744134d9f3aebc2f5cea786f5af4088d01..e7a009d5c2410f6086aaaa4b5a079becfa3b772c 100644 (file)
@@ -2119,7 +2119,9 @@ static int usbradio_indicate(struct ast_channel *c, int cond, const void *data,
                case AST_CONTROL_RINGING:
                        res = cond;
                        break;
-
+               case AST_CONTROL_INCOMPLETE:
+                       res = AST_CONTROL_CONGESTION;
+                       break;
                case -1:
 #ifndef        NEW_ASTERISK
                        o->cursound = -1;
index dfdb16b5d04204c240f09c5e1ce17d8f97ac1319..46aea538c431e9736b109e3d8f7879753e99b5a0 100644 (file)
@@ -6922,6 +6922,15 @@ int sig_pri_indicate(struct sig_pri_chan *p, struct ast_channel *chan, int condi
                /* don't continue in ast_indicate */
                res = 0;
                break;
+       case AST_CONTROL_INCOMPLETE:
+               /* If we are connected or if we support overlap dialing, wait for additional digits */
+               if (p->call_level == SIG_PRI_CALL_LEVEL_CONNECT || (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
+                       res = 0;
+                       break;
+               }
+               /* Otherwise, treat as congestion */
+               chan->hangupcause = AST_CAUSE_INVALID_NUMBER_FORMAT;
+               /* Falls through */
        case AST_CONTROL_CONGESTION:
                if (p->priindication_oob || p->no_b_channel) {
                        /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
index 3677213665b3df919d915f2817ec884c2a23e69f..e484d5603b0edd80bf22fa1fb54b52d931b9ae01 100644 (file)
@@ -1559,6 +1559,14 @@ int sig_ss7_indicate(struct sig_ss7_chan *p, struct ast_channel *chan, int condi
                /* don't continue in ast_indicate */
                res = 0;
                break;
+       case AST_CONTROL_INCOMPLETE:
+               /* If the channel is connected, wait for additional input */
+               if (p->call_level == SIG_SS7_CALL_LEVEL_CONNECT) {
+                       res = 0;
+                       break;
+               }
+               chan->hangupcause = AST_CAUSE_INVALID_NUMBER_FORMAT;
+               break;
        case AST_CONTROL_CONGESTION:
                chan->hangupcause = AST_CAUSE_CONGESTION;
                break;
index e0441011a2b5584b69c7964b8d878e766c2fd0a8..1b56bab9953ef7cf0aea75153c6bfe557da4167d 100644 (file)
@@ -312,6 +312,9 @@ static void print_frame(struct ast_frame *frame)
                case AST_CONTROL_AOC:
                        ast_verbose("SubClass: AOC\n");
                        break;
+               case AST_CONTROL_INCOMPLETE:
+                       ast_verbose("SubClass: INCOMPLETE\n");
+                       break;
                }
                if (frame->subclass.integer == -1) {
                        ast_verbose("SubClass: %d\n", frame->subclass.integer);
index 15ffdb85618a34c1013a41454347c67171e8a8db..dbd217652fa3230c990dd65323f788c96df84431 100644 (file)
@@ -334,6 +334,7 @@ enum ast_control_frame_type {
        AST_CONTROL_READ_ACTION = 27,   /*!< Tell ast_read to take a specific action */
        AST_CONTROL_AOC = 28,                   /*!< Advice of Charge with encoded generic AOC payload */
        AST_CONTROL_END_OF_Q = 29,              /*!< Indicate that this position was the end of the channel queue for a softhangup. */
+       AST_CONTROL_INCOMPLETE = 30,    /*!< Indication that the extension dialed is incomplete */
 };
 
 enum ast_frame_read_action {
index afc16257e0804760a091bd4e524ebf2b235a72d0..439887949c77b306f55601ad8dbe8c0c08a89f3f 100644 (file)
@@ -4293,6 +4293,7 @@ static int attribute_const is_visible_indication(enum ast_control_frame_type con
        case AST_CONTROL_END_OF_Q:
                break;
 
+       case AST_CONTROL_INCOMPLETE:
        case AST_CONTROL_CONGESTION:
        case AST_CONTROL_BUSY:
        case AST_CONTROL_RINGING:
@@ -4449,6 +4450,7 @@ int ast_indicate_data(struct ast_channel *chan, int _condition,
        case AST_CONTROL_BUSY:
                ts = ast_get_indication_tone(chan->zone, "busy");
                break;
+       case AST_CONTROL_INCOMPLETE:
        case AST_CONTROL_CONGESTION:
                ts = ast_get_indication_tone(chan->zone, "congestion");
                break;
@@ -5346,6 +5348,12 @@ struct ast_channel *__ast_request_and_dial(const char *type, format_t format, co
                                        timeout = 0;
                                        break;
 
+                               case AST_CONTROL_INCOMPLETE:
+                                       ast_cdr_failed(chan->cdr);
+                                       *outstate = AST_CONTROL_CONGESTION;
+                                       timeout = 0;
+                                       break;
+
                                case AST_CONTROL_CONGESTION:
                                        ast_cdr_failed(chan->cdr);
                                        *outstate = f->subclass.integer;
index ba1a2bb53cf3d2c54c54dd5b0b7f9422b5bb74a8..ab1ebf748ee84ba0c6276c7815f361a885d79e06 100644 (file)
@@ -398,6 +398,10 @@ static void handle_frame(struct ast_dial *dial, struct ast_dial_channel *channel
                        ast_hangup(channel->owner);
                        channel->owner = NULL;
                        break;
+               case AST_CONTROL_INCOMPLETE:
+                       ast_verb(3, "%s dialed Incomplete extension %s\n", channel->owner->name, channel->owner->exten);
+                       ast_indicate(chan, AST_CONTROL_INCOMPLETE);
+                       break;
                case AST_CONTROL_RINGING:
                        ast_verb(3, "%s is ringing\n", channel->owner->name);
                        if (!dial->options[AST_DIAL_OPTION_MUSIC])
index a8f4a4142b80765b49d595fd20a1040f05428b12..4f2399995e9f73752703d633022fa51112ce6cca 100644 (file)
@@ -3411,6 +3411,8 @@ static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
                                        ast_indicate(caller, AST_CONTROL_BUSY);
                                        ast_frfree(f);
                                        break;
+                               } else if (f->subclass.integer == AST_CONTROL_INCOMPLETE) {
+                                       ast_verb(3, "%s dialed incomplete extension %s; ignoring\n", chan->name, chan->exten);
                                } else if (f->subclass.integer == AST_CONTROL_CONGESTION) {
                                        state = f->subclass.integer;
                                        ast_verb(3, "%s is congested\n", chan->name);
index 031db8760751b20d982026703282411ae943e7ad..4e5284042607abd74bf3a277a0277cdb3122a605 100644 (file)
@@ -9226,6 +9226,8 @@ static int pbx_builtin_incomplete(struct ast_channel *chan, const char *data)
                __ast_answer(chan, 0, 1);
        }
 
+       ast_indicate(chan, AST_CONTROL_INCOMPLETE);
+
        return AST_PBX_INCOMPLETE;
 }