summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKinsey Moore <kmoore@digium.com>2012-06-15 16:17:12 +0000
committerKinsey Moore <kmoore@digium.com>2012-06-15 16:17:12 +0000
commitbdab2763ac297643981b2dfbbaa0bb7d56e4417b (patch)
tree2580bde1f833148d82ab6780014741f238e871b7
parentce44b98358407f8edde9e5ebcbc054a9107fb65e (diff)
Add HANGUPCAUSE hash support to IAX2
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
-rw-r--r--channels/chan_iax2.c56
-rw-r--r--include/asterisk/frame.h24
-rw-r--r--main/frame.c222
3 files changed, 217 insertions, 85 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index 467cdb4e3..8f42bf385 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -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++;
diff --git a/include/asterisk/frame.h b/include/asterisk/frame.h
index 2c1d43cdf..66ba2eff0 100644
--- a/include/asterisk/frame.h
+++ b/include/asterisk/frame.h
@@ -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
diff --git a/main/frame.c b/main/frame.c
index 9e2136d82..6d5c07f83 100644
--- a/main/frame.c
+++ b/main/frame.c
@@ -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,