31 #include "asterisk/res_pjsip.h"
32 #include "asterisk/res_pjsip_session.h"
35 static int is_media_type(pjsip_rx_data *rdata,
char *subtype)
37 return rdata->msg_info.ctype
38 && !pj_strcmp2(&rdata->msg_info.ctype->media.type,
"application")
39 && !pj_strcmp2(&rdata->msg_info.ctype->media.subtype, subtype);
43 struct pjsip_rx_data *rdata,
int code)
48 if (pjsip_dlg_create_response(dlg, rdata, code,
49 NULL, &tdata) == PJ_SUCCESS) {
50 struct pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata);
51 pjsip_dlg_send_response(dlg, tsx, tdata);
55 static char get_event(
const char *c)
59 if (*c ==
'!' || *c ==
'*' || *c ==
'#' ||
60 (
'A' <= *c && *c <=
'D') ||
61 (
'a' <= *c && *c <=
'd')) {
65 if ((sscanf(c,
"%30u", &event) != 1) || event > 16) {
79 return 'A' + (
event - 12);
82 static int dtmf_info_incoming_request(
struct ast_sip_session *session,
struct pjsip_rx_data *rdata)
84 pjsip_msg_body *body = rdata->msg_info.msg->body;
85 char buf[body ? body->len + 1 : 1];
89 unsigned int duration = 100;
90 char is_dtmf, is_dtmf_relay, is_flash;
97 is_dtmf = is_media_type(rdata,
"dtmf");
98 is_dtmf_relay = is_media_type(rdata,
"dtmf-relay");
99 is_flash = is_media_type(rdata,
"hook-flash");
101 if (!is_flash && !is_dtmf && !is_dtmf_relay) {
105 if (!body || !body->len) {
107 send_response(session, rdata, 200);
111 res = body->print_body(body, buf, body->len);
113 send_response(session, rdata, 500);
120 event = get_event(cur);
121 }
else if (is_dtmf_relay) {
122 while ((line = strsep(&cur,
"\r\n"))) {
125 if (!(c = strchr(line,
'='))) {
132 if (!strcasecmp(line,
"signal")) {
133 if (!(event = get_event(c))) {
136 }
else if (!strcasecmp(line,
"duration")) {
137 sscanf(c,
"%30u", &duration);
142 if (event ==
'!' || is_flash) {
145 }
else if (event !=
'\0') {
146 struct ast_frame f = { AST_FRAME_DTMF, };
151 ast_log(LOG_ERROR,
"Invalid DTMF event signal in INFO message.\n");
154 send_response(session, rdata, event ? 200 : 500);
160 .priority = AST_SIP_SUPPLEMENT_PRIORITY_FIRST,
161 .incoming_request = dtmf_info_incoming_request,
164 static int load_module(
void)
166 static const pj_str_t STR_INFO = {
"INFO", 4 };
168 if (pjsip_endpt_add_capability(ast_sip_get_pjsip_endpoint(),
169 NULL, PJSIP_H_ALLOW, NULL, 1, &STR_INFO) != PJ_SUCCESS) {
173 ast_sip_session_register_supplement(&dtmf_info_supplement);
177 static int unload_module(
void)
179 ast_sip_session_unregister_supplement(&dtmf_info_supplement);
183 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER,
"PJSIP DTMF INFO Support",
184 .support_level = AST_MODULE_SUPPORT_CORE,
186 .unload = unload_module,
188 .requires =
"res_pjsip,res_pjsip_session",
Asterisk main include file. File version handling, generic pbx functions.
struct pjsip_inv_session * inv_session
A structure describing a SIP session.
struct ast_frame_subclass subclass
struct ast_channel * channel
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Module has failed to load, may be in an inconsistent state.
A supplement to SIP message processing.
Data structure associated with a single frame of data.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.