Merge Tilghman's cause codes patch (bug #3032)
authorMark Spencer <markster@digium.com>
Sun, 26 Dec 2004 22:33:25 +0000 (22:33 +0000)
committerMark Spencer <markster@digium.com>
Sun, 26 Dec 2004 22:33:25 +0000 (22:33 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4558 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_iax2.c
channels/iax2-parser.c
channels/iax2-parser.h
channels/iax2.h

index bec162f..9bb48a9 100755 (executable)
@@ -1474,6 +1474,7 @@ static int attempt_transmit(void *data)
                                                        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));
@@ -2366,13 +2367,16 @@ static int iax2_hangup(struct ast_channel *c)
 {
        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 */
@@ -4653,8 +4657,10 @@ static int auth_reject(void *nothing)
                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);
        }
@@ -4690,6 +4696,7 @@ static int auto_hangup(void *nothing)
                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]);
@@ -5479,6 +5486,7 @@ retryowner:
                                        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);
@@ -5490,6 +5498,7 @@ retryowner:
                                                        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);
@@ -5499,6 +5508,7 @@ retryowner:
                                                                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)
@@ -5549,6 +5559,10 @@ retryowner:
                        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);
@@ -5615,6 +5629,7 @@ retryowner:
                                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);
@@ -5777,6 +5792,7 @@ retryowner2:
                                                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 */
@@ -5789,6 +5805,7 @@ retryowner2:
                                                                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... */
@@ -5799,6 +5816,7 @@ retryowner2:
                                                                        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);
                                                        }
                                                }
@@ -5834,6 +5852,7 @@ retryowner2:
                                                        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;
@@ -5903,6 +5922,7 @@ retryowner2:
                                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;
index 90d4822..5ce9191 100755 (executable)
@@ -648,6 +648,14 @@ int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen)
                case IAX_IE_CAUSE:
                        ies->cause = data + 2;
                        break;
+               case IAX_IE_CAUSECODE:
+                       if (len != 1) {
+                               snprintf(tmp, (int)sizeof(tmp), "Expecting causecode to be single byte but was %d\n", len);
+                               errorf(tmp);
+                       } else {
+                               ies->causecode = data[2];
+                       }
+                       break;
                case IAX_IE_IAX_UNKNOWN:
                        if (len == 1)
                                ies->iax_unknown = data[2];
index cb29a08..8f74d24 100755 (executable)
@@ -41,6 +41,7 @@ struct iax_ies {
        unsigned short dpstatus;
        unsigned short callno;
        char *cause;
+       unsigned char causecode;
        unsigned char iax_unknown;
        int msgcount;
        int autoanswer;
index 8381744..f145b45 100755 (executable)
 #define IAX_IE_CALLINGTON                      39              /* Calling type of number (u8) */
 #define IAX_IE_CALLINGTNS                      40              /* Calling transit network select (u16) */
 #define IAX_IE_SAMPLINGRATE                    41              /* Supported sampling rates (u16) */
+#define IAX_IE_CAUSECODE                       42              /* Hangup cause (u8) */
 
 #define IAX_AUTH_PLAINTEXT                     (1 << 0)
 #define IAX_AUTH_MD5                           (1 << 1)