Add HANGUPCAUSE hash support to IAX2
authorKinsey Moore <kmoore@digium.com>
Fri, 15 Jun 2012 16:17:12 +0000 (16:17 +0000)
committerKinsey Moore <kmoore@digium.com>
Fri, 15 Jun 2012 16:17:12 +0000 (16:17 +0000)
Continuing with the Who Hung Up? project for Asterisk 11, this adds
support to IAX2 for the HANGUPCAUSE hash.

Additionally, this breaks out some functionality in frame.c for getting
information about frame types and subclasses.

Review: https://reviewboard.asterisk.org/r/1941/
(issue SWP-4222)

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

channels/chan_iax2.c
include/asterisk/frame.h
main/frame.c

index 467cdb4..8f42bf3 100644 (file)
@@ -10135,6 +10135,62 @@ static int socket_process(struct iax2_thread *thread)
        }
 #endif
 
+       if (iaxs[fr->callno]->owner && (fh->type == AST_FRAME_IAX || fh->type == AST_FRAME_CONTROL)) {
+               struct ast_control_pvt_cause_code *cause_code;
+               int data_size = sizeof(*cause_code);
+               char subclass[40] = "";
+
+               /* get subclass text */
+               if (fh->type == AST_FRAME_IAX) {
+                       iax_frame_subclass2str(fh->csub, subclass, sizeof(subclass));
+               } else {
+                       struct ast_frame tmp_frame = {0,};
+                       tmp_frame.frametype = fh->type;
+                       tmp_frame.subclass.integer = fh->csub;
+                       ast_frame_subclass2str(&tmp_frame, subclass, sizeof(subclass), NULL, 0);
+               }
+
+               /* add length of "IAX2 " */
+               data_size += 5;
+               if (fh->type == AST_FRAME_CONTROL) {
+                       /* add length of "Control " */
+                       data_size += 8;
+               } else if (fh->csub == IAX_COMMAND_HANGUP
+                       || fh->csub == IAX_COMMAND_REJECT
+                       || fh->csub == IAX_COMMAND_REGREJ
+                       || fh->csub == IAX_COMMAND_TXREJ) {
+                       /* for IAX hangup frames, add length of () and number */
+                       data_size += 3;
+                       if (ies.causecode > 9) {
+                               data_size++;
+                       }
+                       if (ies.causecode > 99) {
+                               data_size++;
+                       }
+               }
+               /* add length of subclass */
+               data_size += strlen(subclass);
+
+               cause_code = alloca(data_size);
+               ast_copy_string(cause_code->chan_name, ast_channel_name(iaxs[fr->callno]->owner), AST_CHANNEL_NAME);
+
+               if (fh->type == AST_FRAME_IAX &&
+                       (fh->csub == IAX_COMMAND_HANGUP
+                       || fh->csub == IAX_COMMAND_REJECT
+                       || fh->csub == IAX_COMMAND_REGREJ
+                       || fh->csub == IAX_COMMAND_TXREJ)) {
+                       snprintf(cause_code->code, data_size - sizeof(*cause_code) + 1, "IAX2 %s(%d)", subclass, ies.causecode);
+               } else {
+                       snprintf(cause_code->code, data_size - sizeof(*cause_code) + 1, "IAX2 %s%s", (fh->type == AST_FRAME_CONTROL ? "Control " : ""), subclass);
+               }
+
+               iax2_queue_control_data(fr->callno, AST_CONTROL_PVT_CAUSE_CODE, cause_code, data_size);
+               if (!iaxs[fr->callno]) {
+                       ast_variables_destroy(ies.vars);
+                       ast_mutex_unlock(&iaxsl[fr->callno]);
+                       return 1;
+               }
+       }
 
        /* count this frame */
        iaxs[fr->callno]->frames_received++;
index 2c1d43c..66ba2ef 100644 (file)
@@ -597,10 +597,32 @@ int ast_frame_adjust_volume(struct ast_frame *f, int adjustment);
 int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2);
 
 /*!
- * \brief Clear all audio samples from an ast_frame. The frame must be AST_FRAME_VOICE and AST_FORMAT_SLINEAR 
+ * \brief Clear all audio samples from an ast_frame. The frame must be AST_FRAME_VOICE and AST_FORMAT_SLINEAR
  */
 int ast_frame_clear(struct ast_frame *frame);
 
+/*!
+ * \brief Copy the discription of a frame's subclass into the provided string
+ *
+ * \param f The frame to get the information from
+ * \param subclass Buffer to fill with subclass information
+ * \param slen Length of subclass buffer
+ * \param moreinfo Buffer to fill with additional information
+ * \param mlen Length of moreinfo buffer
+ * \since 11
+ */
+void ast_frame_subclass2str(struct ast_frame *f, char *subclass, size_t slen, char *moreinfo, size_t mlen);
+
+/*!
+ * \brief Copy the discription of a frame type into the provided string
+ *
+ * \param frame_type The frame type to be described
+ * \param ftype Buffer to fill with frame type description
+ * \param len Length of subclass buffer
+ * \since 11
+ */
+void ast_frame_type2str(enum ast_frame_type frame_type, char *ftype, size_t len);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif
index 9e2136d..6d5c07f 100644 (file)
@@ -522,96 +522,70 @@ void ast_swapcopy_samples(void *dst, const void *src, int samples)
                dst_s[i] = (src_s[i]<<8) | (src_s[i]>>8);
 }
 
-/*! Dump a frame for debugging purposes */
-void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix)
+void ast_frame_subclass2str(struct ast_frame *f, char *subclass, size_t slen, char *moreinfo, size_t mlen)
 {
-       const char noname[] = "unknown";
-       char ftype[40] = "Unknown Frametype";
-       char cft[80];
-       char subclass[40] = "Unknown Subclass";
-       char csub[80];
-       char moreinfo[40] = "";
-       char cn[60];
-       char cp[40];
-       char cmn[40];
-       const char *message = "Unknown";
-
-       if (!name)
-               name = noname;
-
-
-       if (!f) {
-               ast_verbose("%s [ %s (NULL) ] [%s]\n",
-                       term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
-                       term_color(cft, "HANGUP", COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
-                       term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
-               return;
-       }
-       /* XXX We should probably print one each of voice and video when the format changes XXX */
-       if (f->frametype == AST_FRAME_VOICE)
-               return;
-       if (f->frametype == AST_FRAME_VIDEO)
-               return;
        switch(f->frametype) {
        case AST_FRAME_DTMF_BEGIN:
-               strcpy(ftype, "DTMF Begin");
-               subclass[0] = f->subclass.integer;
-               subclass[1] = '\0';
+               if (slen > 1) {
+                       subclass[0] = f->subclass.integer;
+                       subclass[1] = '\0';
+               }
                break;
        case AST_FRAME_DTMF_END:
-               strcpy(ftype, "DTMF End");
-               subclass[0] = f->subclass.integer;
-               subclass[1] = '\0';
+               if (slen > 1) {
+                       subclass[0] = f->subclass.integer;
+                       subclass[1] = '\0';
+               }
                break;
        case AST_FRAME_CONTROL:
-               strcpy(ftype, "Control");
                switch (f->subclass.integer) {
                case AST_CONTROL_HANGUP:
-                       strcpy(subclass, "Hangup");
+                       ast_copy_string(subclass, "Hangup", slen);
                        break;
                case AST_CONTROL_RING:
-                       strcpy(subclass, "Ring");
+                       ast_copy_string(subclass, "Ring", slen);
                        break;
                case AST_CONTROL_RINGING:
-                       strcpy(subclass, "Ringing");
+                       ast_copy_string(subclass, "Ringing", slen);
                        break;
                case AST_CONTROL_ANSWER:
-                       strcpy(subclass, "Answer");
+                       ast_copy_string(subclass, "Answer", slen);
                        break;
                case AST_CONTROL_BUSY:
-                       strcpy(subclass, "Busy");
+                       ast_copy_string(subclass, "Busy", slen);
                        break;
                case AST_CONTROL_TAKEOFFHOOK:
-                       strcpy(subclass, "Take Off Hook");
+                       ast_copy_string(subclass, "Take Off Hook", slen);
                        break;
                case AST_CONTROL_OFFHOOK:
-                       strcpy(subclass, "Line Off Hook");
+                       ast_copy_string(subclass, "Line Off Hook", slen);
                        break;
                case AST_CONTROL_CONGESTION:
-                       strcpy(subclass, "Congestion");
+                       ast_copy_string(subclass, "Congestion", slen);
                        break;
                case AST_CONTROL_FLASH:
-                       strcpy(subclass, "Flash");
+                       ast_copy_string(subclass, "Flash", slen);
                        break;
                case AST_CONTROL_WINK:
-                       strcpy(subclass, "Wink");
+                       ast_copy_string(subclass, "Wink", slen);
                        break;
                case AST_CONTROL_OPTION:
-                       strcpy(subclass, "Option");
+                       ast_copy_string(subclass, "Option", slen);
                        break;
                case AST_CONTROL_RADIO_KEY:
-                       strcpy(subclass, "Key Radio");
+                       ast_copy_string(subclass, "Key Radio", slen);
                        break;
                case AST_CONTROL_RADIO_UNKEY:
-                       strcpy(subclass, "Unkey Radio");
+                       ast_copy_string(subclass, "Unkey Radio", slen);
                        break;
                case AST_CONTROL_HOLD:
-                       strcpy(subclass, "Hold");
+                       ast_copy_string(subclass, "Hold", slen);
                        break;
                case AST_CONTROL_UNHOLD:
-                       strcpy(subclass, "Unhold");
+                       ast_copy_string(subclass, "Unhold", slen);
                        break;
-               case AST_CONTROL_T38_PARAMETERS:
+               case AST_CONTROL_T38_PARAMETERS: {
+                       char *message = "Unknown";
                        if (f->datalen != sizeof(struct ast_control_t38_parameters)) {
                                message = "Invalid";
                        } else {
@@ -628,89 +602,169 @@ void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix)
                                else if (state == AST_T38_REFUSED)
                                        message = "Refused";
                        }
-                       snprintf(subclass, sizeof(subclass), "T38_Parameters/%s", message);
+                       snprintf(subclass, slen, "T38_Parameters/%s", message);
                        break;
+               }
                case -1:
-                       strcpy(subclass, "Stop generators");
+                       ast_copy_string(subclass, "Stop generators", slen);
                        break;
                default:
-                       snprintf(subclass, sizeof(subclass), "Unknown control '%d'", f->subclass.integer);
+                       snprintf(subclass, slen, "Unknown control '%d'", f->subclass.integer);
                }
                break;
        case AST_FRAME_NULL:
-               strcpy(ftype, "Null Frame");
-               strcpy(subclass, "N/A");
+               ast_copy_string(subclass, "N/A", slen);
                break;
        case AST_FRAME_IAX:
                /* Should never happen */
-               strcpy(ftype, "IAX Specific");
-               snprintf(subclass, sizeof(subclass), "IAX Frametype %d", f->subclass.integer);
+               snprintf(subclass, slen, "IAX Frametype %d", f->subclass.integer);
                break;
        case AST_FRAME_TEXT:
-               strcpy(ftype, "Text");
-               strcpy(subclass, "N/A");
-               ast_copy_string(moreinfo, f->data.ptr, sizeof(moreinfo));
+               ast_copy_string(subclass, "N/A", slen);
+               if (moreinfo) {
+                       ast_copy_string(moreinfo, f->data.ptr, mlen);
+               }
                break;
        case AST_FRAME_IMAGE:
-               strcpy(ftype, "Image");
-               snprintf(subclass, sizeof(subclass), "Image format %s\n", ast_getformatname(&f->subclass.format));
+               snprintf(subclass, slen, "Image format %s\n", ast_getformatname(&f->subclass.format));
                break;
        case AST_FRAME_HTML:
-               strcpy(ftype, "HTML");
                switch (f->subclass.integer) {
                case AST_HTML_URL:
-                       strcpy(subclass, "URL");
-                       ast_copy_string(moreinfo, f->data.ptr, sizeof(moreinfo));
+                       ast_copy_string(subclass, "URL", slen);
+                       if (moreinfo) {
+                               ast_copy_string(moreinfo, f->data.ptr, mlen);
+                       }
                        break;
                case AST_HTML_DATA:
-                       strcpy(subclass, "Data");
+                       ast_copy_string(subclass, "Data", slen);
                        break;
                case AST_HTML_BEGIN:
-                       strcpy(subclass, "Begin");
+                       ast_copy_string(subclass, "Begin", slen);
                        break;
                case AST_HTML_END:
-                       strcpy(subclass, "End");
+                       ast_copy_string(subclass, "End", slen);
                        break;
                case AST_HTML_LDCOMPLETE:
-                       strcpy(subclass, "Load Complete");
+                       ast_copy_string(subclass, "Load Complete", slen);
                        break;
                case AST_HTML_NOSUPPORT:
-                       strcpy(subclass, "No Support");
+                       ast_copy_string(subclass, "No Support", slen);
                        break;
                case AST_HTML_LINKURL:
-                       strcpy(subclass, "Link URL");
-                       ast_copy_string(moreinfo, f->data.ptr, sizeof(moreinfo));
+                       ast_copy_string(subclass, "Link URL", slen);
+                       if (moreinfo) {
+                               ast_copy_string(moreinfo, f->data.ptr, mlen);
+                       }
                        break;
                case AST_HTML_UNLINK:
-                       strcpy(subclass, "Unlink");
+                       ast_copy_string(subclass, "Unlink", slen);
                        break;
                case AST_HTML_LINKREJECT:
-                       strcpy(subclass, "Link Reject");
+                       ast_copy_string(subclass, "Link Reject", slen);
                        break;
                default:
-                       snprintf(subclass, sizeof(subclass), "Unknown HTML frame '%d'\n", f->subclass.integer);
+                       snprintf(subclass, slen, "Unknown HTML frame '%d'\n", f->subclass.integer);
                        break;
                }
                break;
        case AST_FRAME_MODEM:
-               strcpy(ftype, "Modem");
                switch (f->subclass.integer) {
                case AST_MODEM_T38:
-                       strcpy(subclass, "T.38");
+                       ast_copy_string(subclass, "T.38", slen);
                        break;
                case AST_MODEM_V150:
-                       strcpy(subclass, "V.150");
+                       ast_copy_string(subclass, "V.150", slen);
                        break;
                default:
-                       snprintf(subclass, sizeof(subclass), "Unknown MODEM frame '%d'\n", f->subclass.integer);
+                       snprintf(subclass, slen, "Unknown MODEM frame '%d'\n", f->subclass.integer);
                        break;
                }
                break;
        default:
-               snprintf(ftype, sizeof(ftype), "Unknown Frametype '%d'", f->frametype);
+               ast_copy_string(subclass, "Unknown Subclass", slen);
        }
+}
+
+void ast_frame_type2str(enum ast_frame_type frame_type, char *ftype, size_t len)
+{
+       switch (frame_type) {
+       case AST_FRAME_DTMF_BEGIN:
+               ast_copy_string(ftype, "DTMF Begin", len);
+               break;
+       case AST_FRAME_DTMF_END:
+               ast_copy_string(ftype, "DTMF End", len);
+               break;
+       case AST_FRAME_CONTROL:
+               ast_copy_string(ftype, "Control", len);
+               break;
+       case AST_FRAME_NULL:
+               ast_copy_string(ftype, "Null Frame", len);
+               break;
+       case AST_FRAME_IAX:
+               /* Should never happen */
+               ast_copy_string(ftype, "IAX Specific", len);
+               break;
+       case AST_FRAME_TEXT:
+               ast_copy_string(ftype, "Text", len);
+               break;
+       case AST_FRAME_IMAGE:
+               ast_copy_string(ftype, "Image", len);
+               break;
+       case AST_FRAME_HTML:
+               ast_copy_string(ftype, "HTML", len);
+               break;
+       case AST_FRAME_MODEM:
+               ast_copy_string(ftype, "Modem", len);
+               break;
+       case AST_FRAME_VOICE:
+               ast_copy_string(ftype, "Voice", len);
+               break;
+       case AST_FRAME_VIDEO:
+               ast_copy_string(ftype, "Video", len);
+               break;
+       default:
+               snprintf(ftype, len, "Unknown Frametype '%d'", frame_type);
+       }
+}
+
+/*! Dump a frame for debugging purposes */
+void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix)
+{
+       const char noname[] = "unknown";
+       char ftype[40] = "Unknown Frametype";
+       char cft[80];
+       char subclass[40] = "Unknown Subclass";
+       char csub[80];
+       char moreinfo[40] = "";
+       char cn[60];
+       char cp[40];
+       char cmn[40];
+
+       if (!name) {
+               name = noname;
+       }
+
+       if (!f) {
+               ast_verb(-1, "%s [ %s (NULL) ] [%s]\n",
+                       term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
+                       term_color(cft, "HANGUP", COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
+                       term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
+               return;
+       }
+       /* XXX We should probably print one each of voice and video when the format changes XXX */
+       if (f->frametype == AST_FRAME_VOICE) {
+               return;
+       }
+       if (f->frametype == AST_FRAME_VIDEO) {
+               return;
+       }
+
+       ast_frame_type2str(f->frametype, ftype, sizeof(ftype));
+       ast_frame_subclass2str(f, subclass, sizeof(subclass), moreinfo, sizeof(moreinfo));
+
        if (!ast_strlen_zero(moreinfo))
-               ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) '%s' ] [%s]\n",
+               ast_verb(-1, "%s [ TYPE: %s (%d) SUBCLASS: %s (%d) '%s' ] [%s]\n",
                            term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
                            term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
                            f->frametype,
@@ -719,7 +773,7 @@ void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix)
                            term_color(cmn, moreinfo, COLOR_BRGREEN, COLOR_BLACK, sizeof(cmn)),
                            term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
        else
-               ast_verbose("%s [ TYPE: %s (%d) SUBCLASS: %s (%d) ] [%s]\n",
+               ast_verb(-1, "%s [ TYPE: %s (%d) SUBCLASS: %s (%d) ] [%s]\n",
                            term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
                            term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
                            f->frametype,