Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Functions | Variables
app_dtmfstore.c File Reference

Technology independent asynchronous DTMF collection. More...

#include "asterisk.h"
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/framehook.h"
#include "asterisk/app.h"
#include "asterisk/conversions.h"
Include dependency graph for app_dtmfstore.c:

Go to the source code of this file.

Data Structures

struct  dtmf_store_data
 Private data structure used with the function's datastore. More...
 

Functions

 AST_MODULE_INFO_STANDARD_EXTENDED (ASTERISK_GPL_KEY, "Technology independent async DTMF storage")
 
static void datastore_destroy_cb (void *data)
 
static struct ast_framedtmf_store_framehook (struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
 Frame hook that is called to intercept digit/undigit. More...
 
static int dtmfstore_exec (struct ast_channel *chan, const char *appdata)
 
static int load_module (void)
 
static int remove_dtmf_store (struct ast_channel *chan)
 
static int unload_module (void)
 

Variables

static char * app = "StoreDTMF"
 
static const struct ast_datastore_info dtmf_store_datastore
 The channel datastore the function uses to store state. More...
 

Detailed Description

Technology independent asynchronous DTMF collection.

Author
Naveen Albert aster[email protected][email protected][email protected]phrea[email protected]knet[email protected].org

Definition in file app_dtmfstore.c.

Function Documentation

◆ AST_MODULE_INFO_STANDARD_EXTENDED()

AST_MODULE_INFO_STANDARD_EXTENDED ( ASTERISK_GPL_KEY  ,
"Technology independent async DTMF storage"   
)

Referenced by load_module().

◆ datastore_destroy_cb()

static void datastore_destroy_cb ( void *  data)
static

Definition at line 79 of file app_dtmfstore.c.

References ast_free, d, dtmf_store_data::rx_var, and dtmf_store_data::tx_var.

79  {
80  struct dtmf_store_data *d;
81  d = data;
82  if (d) {
83  if (d->rx_var) {
84  ast_free(d->rx_var);
85  }
86  if (d->tx_var) {
87  ast_free(d->tx_var);
88  }
89  ast_free(data);
90  }
91 }
static struct test_val d
Private data structure used with the function's datastore.
Definition: app_dtmfstore.c:72
#define ast_free(a)
Definition: astmm.h:182

◆ dtmf_store_framehook()

static struct ast_frame* dtmf_store_framehook ( struct ast_channel chan,
struct ast_frame f,
enum ast_framehook_event  event,
void *  data 
)
static

Frame hook that is called to intercept digit/undigit.

Definition at line 131 of file app_dtmfstore.c.

References ast_copy_string(), ast_debug, AST_FRAME_DTMF_END, AST_FRAMEHOOK_EVENT_READ, AST_FRAMEHOOK_EVENT_WRITE, ast_strlen_zero, ast_frame::frametype, ast_frame_subclass::integer, len(), dtmf_store_data::maxdigits, NULL, pbx_builtin_setvar_helper(), pbx_substitute_variables_helper(), remove_dtmf_store(), dtmf_store_data::rx_var, ast_frame::subclass, and dtmf_store_data::tx_var.

Referenced by dtmfstore_exec().

133 {
134  char currentdata[512];
135  char varnamesub[64];
136  char *varname = NULL;
137  struct dtmf_store_data *framedata = data;
138  int len;
139 
140  if (!f || !framedata) {
141  return f;
142  }
143 
145  return f;
146  }
147 
148  if (f->frametype != AST_FRAME_DTMF_END) {
149  return f;
150  }
151 
152  /* If this is DTMF then store the digits */
153  if (event == AST_FRAMEHOOK_EVENT_READ && framedata->rx_var) { /* coming from source */
154  varname = framedata->rx_var;
155  } else if (event == AST_FRAMEHOOK_EVENT_WRITE && framedata->tx_var) { /* going to source */
156  varname = framedata->tx_var;
157  }
158 
159  if (!varname) {
160  return f;
161  }
162 
163  sprintf(varnamesub, "${%s}", varname);
164  pbx_substitute_variables_helper(chan, varnamesub, currentdata, 511);
165  /* pbx_builtin_getvar_helper works for regular vars but not CDR vars */
166  if (ast_strlen_zero(currentdata)) { /* var doesn't exist yet */
167  ast_debug(3, "Creating new digit store: %s\n", varname);
168  }
169  len = strlen(currentdata);
170  if (framedata->maxdigits > 0 && len >= framedata->maxdigits) {
171  ast_debug(3, "Reached digit limit: %d\n", framedata->maxdigits);
172  remove_dtmf_store(chan); /* reached max digit count, stop now */
173  return f;
174  } else {
175  char newdata[len + 2]; /* one more char + terminator */
176  if (len > 0) {
177  ast_copy_string(newdata, currentdata, len + 2);
178  }
179  newdata[len] = (unsigned) f->subclass.integer;
180  newdata[len + 1] = '\0';
181  ast_debug(3, "Appending to digit store: now %s\n", newdata);
182  pbx_builtin_setvar_helper(chan, varname, newdata);
183  }
184  return f;
185 }
static int remove_dtmf_store(struct ast_channel *chan)
Definition: astman.c:222
#define NULL
Definition: resample.c:96
struct ast_frame_subclass subclass
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
Private data structure used with the function's datastore.
Definition: app_dtmfstore.c:72
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
Definition: ael_main.c:211
enum ast_frame_type frametype

◆ dtmfstore_exec()

static int dtmfstore_exec ( struct ast_channel chan,
const char *  appdata 
)
static

Definition at line 188 of file app_dtmfstore.c.

References args, AST_APP_ARG, ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_name(), ast_datastore_alloc, ast_datastore_free(), AST_DECLARE_APP_ARGS, ast_framehook_attach(), AST_FRAMEHOOK_INTERFACE_VERSION, ast_free, ast_log, AST_LOG_WARNING, AST_STANDARD_APP_ARGS, ast_str_to_int(), ast_strdup, ast_strdupa, ast_strlen_zero, ast_datastore::data, ast_framehook_interface::data, dtmf_store_framehook(), dtmf_store_data::framehook_id, LOG_ERROR, LOG_WARNING, dtmf_store_data::maxdigits, NULL, parse(), remove_dtmf_store(), dtmf_store_data::rx_var, SCOPED_CHANNELLOCK, dtmf_store_data::tx_var, and ast_framehook_interface::version.

Referenced by load_module().

189 {
190  struct ast_datastore *datastore;
191  struct dtmf_store_data *data;
192  static struct ast_framehook_interface digit_framehook_interface = {
194  .event_cb = dtmf_store_framehook,
195  .disable_inheritance = 1,
196  };
197  char *parse = ast_strdupa(appdata);
200  AST_APP_ARG(varname);
201  AST_APP_ARG(maxdigits);
202  );
203  SCOPED_CHANNELLOCK(chan_lock, chan);
204  AST_STANDARD_APP_ARGS(args, parse);
205 
206  if (ast_strlen_zero(appdata)) {
207  ast_log(AST_LOG_WARNING, "StoreDTMF requires an argument\n");
208  return -1;
209  }
210 
211  if (!strcasecmp(args.direction, "remove")) {
212  return remove_dtmf_store(chan);
213  }
214 
216  if (datastore) {
217  ast_log(AST_LOG_WARNING, "StoreDTMF already set on '%s'\n",
218  ast_channel_name(chan));
219  return 0;
220  }
221 
223  if (!datastore) {
224  return -1;
225  }
226 
227  data = ast_calloc(1, sizeof(*data));
228  if (!data) {
229  ast_datastore_free(datastore);
230  return -1;
231  }
232 
233  digit_framehook_interface.data = data;
234 
235  data->rx_var = NULL;
236  data->tx_var = NULL;
237  data->maxdigits = 0;
238 
239  if (!strcasecmp(args.direction, "tx")) {
240  data->tx_var = ast_strdup(args.varname);
241  } else if (!strcasecmp(args.direction, "rx")) {
242  data->rx_var = ast_strdup(args.varname);
243  } else {
244  ast_log(LOG_ERROR, "Direction must be either RX or TX\n");
245  return -1;
246  }
247 
248  if (!ast_strlen_zero(args.maxdigits)) {
249  if (ast_str_to_int(args.maxdigits,&(data->maxdigits))) {
250  ast_log(LOG_ERROR, "Invalid integer: %s\n", args.maxdigits);
251  return -1;
252  }
253  if (data->maxdigits < 0) {
254  ast_log(LOG_ERROR, "Invalid natural number: %d\n", data->maxdigits);
255  return -1;
256  } else if (data->maxdigits == 0) {
257  ast_log(LOG_WARNING, "No maximum digit count set\n");
258  }
259  }
260 
261  data->framehook_id = ast_framehook_attach(chan, &digit_framehook_interface);
262  if (data->framehook_id < 0) {
263  ast_log(AST_LOG_WARNING, "Failed to attach StoreDTMF framehook to '%s'\n",
264  ast_channel_name(chan));
265  ast_datastore_free(datastore);
266  ast_free(data);
267  return -1;
268  }
269  datastore->data = data;
270 
271  ast_channel_datastore_add(chan, datastore);
272 
273  return 0;
274 }
static struct ast_frame * dtmf_store_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
Frame hook that is called to intercept digit/undigit.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
static int remove_dtmf_store(struct ast_channel *chan)
#define AST_LOG_WARNING
Definition: logger.h:279
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2404
const char * args
#define NULL
Definition: resample.c:96
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
#define ast_strlen_zero(foo)
Definition: strings.h:52
int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interface *i)
Attach an framehook onto a channel for frame interception.
Definition: framehook.c:132
static const struct ast_datastore_info dtmf_store_datastore
The channel datastore the function uses to store state.
Definition: app_dtmfstore.c:94
#define ast_log
Definition: astobj2.c:42
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:617
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int ast_str_to_int(const char *str, int *res)
Convert the given string to a signed integer.
Definition: conversions.c:44
#define LOG_ERROR
Definition: logger.h:285
#define AST_FRAMEHOOK_INTERFACE_VERSION
Definition: framehook.h:227
Private data structure used with the function&#39;s datastore.
Definition: app_dtmfstore.c:72
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
void * data
Definition: datastore.h:70
const char * ast_channel_name(const struct ast_channel *chan)
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
direction
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2390
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ load_module()

static int load_module ( void  )
static

Definition at line 281 of file app_dtmfstore.c.

References app, AST_MODULE_INFO_STANDARD_EXTENDED(), ast_register_application_xml, ASTERISK_GPL_KEY, and dtmfstore_exec().

282 {
284 }
static int dtmfstore_exec(struct ast_channel *chan, const char *appdata)
static char * app
Definition: app_dtmfstore.c:69
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626

◆ remove_dtmf_store()

static int remove_dtmf_store ( struct ast_channel chan)
static

Definition at line 100 of file app_dtmfstore.c.

References ast_channel_datastore_find(), ast_channel_datastore_remove(), ast_channel_name(), ast_datastore_free(), ast_framehook_detach(), ast_log, AST_LOG_WARNING, ast_datastore::data, dtmf_store_data::framehook_id, NULL, and SCOPED_CHANNELLOCK.

Referenced by dtmf_store_framehook(), and dtmfstore_exec().

101 {
102  struct ast_datastore *datastore = NULL;
103  struct dtmf_store_data *data;
104  SCOPED_CHANNELLOCK(chan_lock, chan);
105 
107  if (!datastore) {
108  ast_log(AST_LOG_WARNING, "Cannot remove StoreDTMF from %s: StoreDTMF not currently enabled\n",
109  ast_channel_name(chan));
110  return -1;
111  }
112  data = datastore->data;
113 
114  if (ast_framehook_detach(chan, data->framehook_id)) {
115  ast_log(AST_LOG_WARNING, "Failed to remove StoreDTMF framehook from channel %s\n",
116  ast_channel_name(chan));
117  return -1;
118  }
119 
120  if (ast_channel_datastore_remove(chan, datastore)) {
121  ast_log(AST_LOG_WARNING, "Failed to remove StoreDTMF datastore from channel %s\n",
122  ast_channel_name(chan));
123  return -1;
124  }
125  ast_datastore_free(datastore);
126 
127  return 0;
128 }
#define AST_LOG_WARNING
Definition: logger.h:279
int ast_framehook_detach(struct ast_channel *chan, int framehook_id)
Detach an framehook from a channel.
Definition: framehook.c:177
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2404
#define NULL
Definition: resample.c:96
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
static const struct ast_datastore_info dtmf_store_datastore
The channel datastore the function uses to store state.
Definition: app_dtmfstore.c:94
#define ast_log
Definition: astobj2.c:42
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:617
Private data structure used with the function&#39;s datastore.
Definition: app_dtmfstore.c:72
void * data
Definition: datastore.h:70
const char * ast_channel_name(const struct ast_channel *chan)
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2399

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 276 of file app_dtmfstore.c.

References app, and ast_unregister_application().

277 {
279 }
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
static char * app
Definition: app_dtmfstore.c:69

Variable Documentation

◆ app

char* app = "StoreDTMF"
static

Definition at line 69 of file app_dtmfstore.c.

Referenced by load_module(), and unload_module().

◆ dtmf_store_datastore

const struct ast_datastore_info dtmf_store_datastore
static
Initial value:
= {
.type = "dtmf_store",
}
static void datastore_destroy_cb(void *data)
Definition: app_dtmfstore.c:79

The channel datastore the function uses to store state.

Definition at line 94 of file app_dtmfstore.c.