summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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,