diff options
-rw-r--r-- | channels/chan_iax2.c | 56 | ||||
-rw-r--r-- | include/asterisk/frame.h | 24 | ||||
-rw-r--r-- | main/frame.c | 222 |
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, |