Asterisk - The Open Source Telephony Project GIT-master-f36a736
func_frame_trace.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2010, Digium, Inc.
5 *
6 * David Vossel <dvossel@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19/*! \file
20 *
21 * \brief Trace internal ast_frames on a channel.
22 *
23 * \author David Vossel <dvossel@digium.com>
24 *
25 * \ingroup functions
26 */
27
28/*** MODULEINFO
29 <support_level>extended</support_level>
30 ***/
31
32#include "asterisk.h"
33
34#include "asterisk/module.h"
35#include "asterisk/channel.h"
36#include "asterisk/pbx.h"
37#include "asterisk/framehook.h"
38#include "asterisk/cli.h"
39
40/*** DOCUMENTATION
41 <function name="FRAME_TRACE" language="en_US">
42 <synopsis>
43 View internal ast_frames as they are read and written on a channel.
44 </synopsis>
45 <syntax>
46 <parameter name="filter list type" required="true">
47 <para>A filter can be applied to the trace to limit what frames are viewed. This
48 filter can either be a <literal>white</literal> or <literal>black</literal> list
49 of frame types. When no filter type is present, <literal>white</literal> is
50 used. If no arguments are provided at all, all frames will be output.
51 </para>
52
53 <para>Below are the different types of frames that can be filtered.</para>
54 <enumlist>
55 <enum name = "DTMF_BEGIN" />
56 <enum name = "DTMF_END" />
57 <enum name = "VOICE" />
58 <enum name = "VIDEO" />
59 <enum name = "CONTROL" />
60 <enum name = "NULL" />
61 <enum name = "IAX" />
62 <enum name = "TEXT" />
63 <enum name = "TEXT_DATA" />
64 <enum name = "IMAGE" />
65 <enum name = "HTML" />
66 <enum name = "CNG" />
67 <enum name = "MODEM" />
68 </enumlist>
69 </parameter>
70 </syntax>
71 <description>
72 <para>Examples:</para>
73 <example title="View only DTMF frames">
74 exten => 1,1,Set(FRAME_TRACE(white)=DTMF_BEGIN,DTMF_END)
75 </example>
76 <example title="View only DTMF frames">
77 exten => 1,1,Set(FRAME_TRACE()=DTMF_BEGIN,DTMF_END)
78 </example>
79 <example title="View everything except DTMF frames">
80 exten => 1,1,Set(FRAME_TRACE(black)=DTMF_BEGIN,DTMF_END)
81 </example>
82 </description>
83 </function>
84 ***/
85
86static void print_frame(struct ast_frame *frame);
87static struct {
89 const char *str;
90} frametype2str[] = {
91 { AST_FRAME_DTMF_BEGIN, "DTMF_BEGIN" },
92 { AST_FRAME_DTMF_END, "DTMF_END" },
93 { AST_FRAME_VOICE, "VOICE" },
94 { AST_FRAME_VIDEO, "VIDEO" },
95 { AST_FRAME_CONTROL, "CONTROL" },
96 { AST_FRAME_NULL, "NULL" },
97 { AST_FRAME_IAX, "IAX" },
98 { AST_FRAME_TEXT, "TEXT" },
99 { AST_FRAME_TEXT_DATA, "TEXT_DATA" },
100 { AST_FRAME_IMAGE, "IMAGE" },
101 { AST_FRAME_HTML, "HTML" },
102 { AST_FRAME_CNG, "CNG" },
103 { AST_FRAME_MODEM, "MODEM" },
105
107 int list_type; /* 0 = white, 1 = black */
109};
110
111static void datastore_destroy_cb(void *data) {
112 ast_free(data);
113}
114
116 .type = "frametrace",
117 .destroy = datastore_destroy_cb
118};
119
120static void hook_destroy_cb(void *framedata)
121{
122 ast_free(framedata);
123}
124
125static struct ast_frame *hook_event_cb(struct ast_channel *chan, struct ast_frame *frame, enum ast_framehook_event event, void *data)
126{
127 int i;
128 int show_frame = 0;
129 struct frame_trace_data *framedata = data;
130 if (!frame) {
131 return frame;
132 }
133
135 return frame;
136 }
137
138 for (i = 0; i < ARRAY_LEN(frametype2str); i++) {
139 if (frame->frametype == frametype2str[i].type) {
140 if ((framedata->list_type == 0) && (framedata->values[i])) { /* white list */
141 show_frame = 1;
142 } else if ((framedata->list_type == 1) && (!framedata->values[i])){ /* black list */
143 show_frame = 1;
144 }
145 break;
146 }
147 }
148
149 if (show_frame) {
150 ast_verbose("%s on Channel %s\n", event == AST_FRAMEHOOK_EVENT_READ ? "<--Read" : "--> Write", ast_channel_name(chan));
151 print_frame(frame);
152 }
153 return frame;
154}
155
156static int frame_trace_helper(struct ast_channel *chan, const char *cmd, char *data, const char *value)
157{
158 struct frame_trace_data *framedata;
159 struct ast_datastore *datastore = NULL;
160 struct ast_framehook_interface interface = {
162 .event_cb = hook_event_cb,
163 .destroy_cb = hook_destroy_cb,
164 };
165 int i = 0;
166
167 if (!chan) {
168 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
169 return -1;
170 }
171
172 if (!(framedata = ast_calloc(1, sizeof(*framedata)))) {
173 return 0;
174 }
175
176 interface.data = framedata;
177
178 if (!strcasecmp(data, "black")) {
179 framedata->list_type = 1;
180 }
181 for (i = 0; i < ARRAY_LEN(frametype2str); i++) {
183 framedata->values[i] = 1;
184 }
185 }
186
187 ast_channel_lock(chan);
188 i = ast_framehook_attach(chan, &interface);
189 if (i >= 0) {
190 int *id;
191 if ((datastore = ast_channel_datastore_find(chan, &frame_trace_datastore, NULL))) {
192 id = datastore->data;
193 ast_framehook_detach(chan, *id);
194 ast_channel_datastore_remove(chan, datastore);
195 ast_datastore_free(datastore);
196 }
197
198 if (!(datastore = ast_datastore_alloc(&frame_trace_datastore, NULL))) {
199 ast_framehook_detach(chan, i);
200 ast_channel_unlock(chan);
201 return 0;
202 }
203
204 if (!(id = ast_calloc(1, sizeof(int)))) {
205 ast_datastore_free(datastore);
206 ast_framehook_detach(chan, i);
207 ast_channel_unlock(chan);
208 return 0;
209 }
210
211 *id = i; /* Store off the id. The channel is still locked so it is safe to access this ptr. */
212 datastore->data = id;
213 ast_channel_datastore_add(chan, datastore);
214 }
215 ast_channel_unlock(chan);
216
217 return 0;
218}
219
220static void print_frame(struct ast_frame *frame)
221{
222 switch (frame->frametype) {
224 ast_verbose("FrameType: DTMF END\n");
225 ast_verbose("Digit: 0x%02X '%c'\n", (unsigned)frame->subclass.integer,
226 frame->subclass.integer < ' ' ? ' ' : frame->subclass.integer);
227 break;
228 case AST_FRAME_VOICE:
229 ast_verbose("FrameType: VOICE\n");
230 ast_verbose("Codec: %s\n", ast_format_get_name(frame->subclass.format));
231 ast_verbose("MS: %ld\n", frame->len);
232 ast_verbose("Samples: %d\n", frame->samples);
233 ast_verbose("Bytes: %d\n", frame->datalen);
234 break;
235 case AST_FRAME_VIDEO:
236 ast_verbose("FrameType: VIDEO\n");
237 ast_verbose("Codec: %s\n", ast_format_get_name(frame->subclass.format));
238 ast_verbose("MS: %ld\n", frame->len);
239 ast_verbose("Samples: %d\n", frame->samples);
240 ast_verbose("Bytes: %d\n", frame->datalen);
241 break;
243 ast_verbose("FrameType: CONTROL\n");
244 switch ((enum ast_control_frame_type) frame->subclass.integer) {
246 ast_verbose("SubClass: HANGUP\n");
247 break;
248 case AST_CONTROL_RING:
249 ast_verbose("SubClass: RING\n");
250 break;
252 ast_verbose("SubClass: RINGING\n");
253 break;
255 ast_verbose("SubClass: ANSWER\n");
256 break;
257 case AST_CONTROL_BUSY:
258 ast_verbose("SubClass: BUSY\n");
259 break;
261 ast_verbose("SubClass: TAKEOFFHOOK\n");
262 break;
264 ast_verbose("SubClass: OFFHOOK\n");
265 break;
267 ast_verbose("SubClass: CONGESTION\n");
268 break;
270 ast_verbose("SubClass: FLASH\n");
271 break;
272 case AST_CONTROL_WINK:
273 ast_verbose("SubClass: WINK\n");
274 break;
276 ast_verbose("SubClass: OPTION\n");
277 break;
279 ast_verbose("SubClass: RADIO KEY\n");
280 break;
282 ast_verbose("SubClass: RADIO UNKEY\n");
283 break;
285 ast_verbose("SubClass: PROGRESS\n");
286 break;
288 ast_verbose("SubClass: PROCEEDING\n");
289 break;
290 case AST_CONTROL_HOLD:
291 ast_verbose("SubClass: HOLD\n");
292 break;
294 ast_verbose("SubClass: UNHOLD\n");
295 break;
297 ast_verbose("SubClass: VIDUPDATE\n");
298 break;
300 ast_verbose("SubClass: XXX T38\n");
301 break;
303 ast_verbose("SubClass: SRCUPDATE\n");
304 break;
306 ast_verbose("SubClass: TRANSFER\n");
307 break;
309 ast_verbose("SubClass: CONNECTED LINE\n");
310 break;
312 ast_verbose("SubClass: REDIRECTING\n");
313 break;
315 ast_verbose("SubClass: T38 PARAMETERS\n");
316 break;
317 case AST_CONTROL_CC:
318 ast_verbose("SubClass: CC\n");
319 break;
321 ast_verbose("SubClass: SRCCHANGE\n");
322 break;
324 ast_verbose("SubClass: READ ACTION\n");
325 break;
326 case AST_CONTROL_AOC:
327 ast_verbose("SubClass: AOC\n");
328 break;
329 case AST_CONTROL_MCID:
330 ast_verbose("SubClass: MCID\n");
331 break;
333 ast_verbose("SubClass: INCOMPLETE\n");
334 break;
336 ast_verbose("SubClass: END_OF_Q\n");
337 break;
339 ast_verbose("SubClass: UPDATE_RTP_PEER\n");
340 break;
342 ast_verbose("SubClass: PVT_CAUSE_CODE\n");
343 break;
345 ast_verbose("SubClass: MASQUERADE_NOTIFY\n");
346 break;
348 ast_verbose("SubClass: STREAM_TOPOLOGY_REQUEST_CHANGE\n");
349 break;
351 ast_verbose("SubClass: STREAM_TOPOLOGY_CHANGED\n");
352 break;
354 ast_verbose("SubClass: STREAM_TOPOLOGY_SOURCE_CHANGED\n");
355 break;
357 ast_verbose("SubClass: STREAM_STOP\n");
358 break;
360 ast_verbose("SubClass: STREAM_SUSPEND\n");
361 break;
363 ast_verbose("SubClass: STREAM_RESTART\n");
364 break;
366 ast_verbose("SubClass: STREAM_REVERSE\n");
367 break;
369 ast_verbose("SubClass: STREAM_FORWARD\n");
370 break;
372 ast_verbose("SubClass: RECORD_CANCEL\n");
373 break;
375 ast_verbose("SubClass: RECORD_STOP\n");
376 break;
378 ast_verbose("SubClass: RECORD_SUSPEND\n");
379 break;
381 ast_verbose("SubClass: RECORD_MUTE\n");
382 break;
383 }
384
385 if (frame->subclass.integer == -1) {
386 ast_verbose("SubClass: %d\n", frame->subclass.integer);
387 }
388 ast_verbose("Bytes: %d\n", frame->datalen);
389 break;
390 case AST_FRAME_RTCP:
391 ast_verbose("FrameType: RTCP\n");
392 break;
393 case AST_FRAME_NULL:
394 ast_verbose("FrameType: NULL\n");
395 break;
396 case AST_FRAME_IAX:
397 ast_verbose("FrameType: IAX\n");
398 break;
399 case AST_FRAME_TEXT:
400 ast_verbose("FrameType: TXT\n");
401 ast_verbose("Text: %.*s\n", frame->datalen, (char*) frame->data.ptr);
402 break;
404 ast_verbose("FrameType: TXT_DATA\n");
405 break;
406 case AST_FRAME_IMAGE:
407 ast_verbose("FrameType: IMAGE\n");
408 break;
409 case AST_FRAME_HTML:
410 ast_verbose("FrameType: HTML\n");
411 break;
412 case AST_FRAME_CNG:
413 ast_verbose("FrameType: CNG\n");
414 break;
415 case AST_FRAME_MODEM:
416 ast_verbose("FrameType: MODEM\n");
417 break;
419 ast_verbose("FrameType: DTMF BEGIN\n");
420 ast_verbose("Digit: 0x%02X '%c'\n", (unsigned)frame->subclass.integer,
421 frame->subclass.integer < ' ' ? ' ' : frame->subclass.integer);
422 break;
424 ast_verbose("FrameType: Bridge\n");
425 ast_verbose("SubClass: %d\n", frame->subclass.integer);
426 break;
428 ast_verbose("Frametype: Synchronous Bridge\n");
429 ast_verbose("Subclass: %d\n", frame->subclass.integer);
430 break;
431 }
432
433 ast_verbose("Src: %s\n", ast_strlen_zero(frame->src) ? "NOT PRESENT" : frame->src);
434 ast_verbose("\n");
435}
436
438 .name = "FRAME_TRACE",
439 .write = frame_trace_helper,
440};
441
442static char *handle_dump_frames(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
443{
444 struct ast_channel *chan;
445 struct ast_frame *f;
446 int c = 1;
447
448 switch (cmd) {
449 case CLI_INIT:
450 e->command = "channel dump frames";
451 e->usage =
452 "Usage: channel dump frames <channel>\n"
453 " List all frames queued to a channel.\n";
454 return NULL;
455 case CLI_GENERATE:
456 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
457 }
458
459 if (a->argc != 4) {
460 return CLI_SHOWUSAGE;
461 }
462
463 chan = ast_channel_get_by_name(a->argv[3]);
464 if (!chan) {
465 ast_cli(a->fd, "%s is not a known channel\n", a->argv[3]);
466 return CLI_SUCCESS;
467 }
468
469 ast_channel_lock(chan);
470
471 ast_cli(a->fd, "== Frame list for %s ==\n", ast_channel_name(chan));
472 ast_cli(a->fd, "%5s %6s %6s %-15s (%-20s) - %s\n", "#", "Seqno", "Stream", "Frame Type", "Frame Subclass", "Src");
474 char type[64];
475 char subclass[64];
478 ast_cli(a->fd, "%5d %6d %6d %-15s (%-20s) - %s\n", c++, f->seqno, f->stream_num, type, subclass, S_OR(f->src, ""));
479 }
480
481 ast_channel_unlock(chan);
482 ast_channel_unref(chan);
483 return CLI_SUCCESS;
484}
485
486static struct ast_cli_entry cli_frames[] = {
487 AST_CLI_DEFINE(handle_dump_frames, "Display frames queued on a specific channel")
488};
489
490static int unload_module(void)
491{
494}
495
496static int load_module(void)
497{
501}
502
503AST_MODULE_INFO_STANDARD_EXTENDED(ASTERISK_GPL_KEY, "Frame Trace for internal ast_frame debugging.");
enum queue_result id
Definition: app_queue.c:1667
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_log
Definition: astobj2.c:42
General Asterisk PBX channel definitions.
const char * ast_channel_name(const struct ast_channel *chan)
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2404
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2413
#define ast_channel_lock(chan)
Definition: channel.h:2968
struct ast_readq_list * ast_channel_readq(struct ast_channel *chan)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3004
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1473
#define ast_channel_unlock(chan)
Definition: channel.h:2969
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:2418
Standard Command Line Interface.
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
char * ast_complete_channels(const char *line, const char *word, int pos, int state, int rpos)
Command completion for the list of active channels.
Definition: main/cli.c:1872
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static void show_frame(struct video_desc *env, int out)
Definition: console_gui.c:98
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:85
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2206
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
FrameHook Architecture.
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
ast_framehook_event
These are the types of events that the framehook's event callback can receive.
Definition: framehook.h:151
@ AST_FRAMEHOOK_EVENT_WRITE
Definition: framehook.h:153
@ AST_FRAMEHOOK_EVENT_READ
Definition: framehook.h:152
int ast_framehook_detach(struct ast_channel *chan, int framehook_id)
Detach an framehook from a channel.
Definition: framehook.c:177
#define AST_FRAMEHOOK_INTERFACE_VERSION
Definition: framehook.h:227
static const struct ast_datastore_info frame_trace_datastore
static char * handle_dump_frames(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct ast_cli_entry cli_frames[]
static int frame_trace_helper(struct ast_channel *chan, const char *cmd, char *data, const char *value)
enum ast_frame_type type
static void print_frame(struct ast_frame *frame)
AST_MODULE_INFO_STANDARD_EXTENDED(ASTERISK_GPL_KEY, "Frame Trace for internal ast_frame debugging.")
static struct ast_custom_function frame_trace_function
static struct ast_frame * hook_event_cb(struct ast_channel *chan, struct ast_frame *frame, enum ast_framehook_event event, void *data)
static void hook_destroy_cb(void *framedata)
static void datastore_destroy_cb(void *data)
static int load_module(void)
static int unload_module(void)
static struct @172 frametype2str[]
const char * str
char * strcasestr(const char *, const char *)
char * ast_frame_type2str(enum ast_frame_type frame_type, char *ftype, size_t len)
Copy the discription of a frame type into the provided string.
Definition: main/frame.c:671
char * ast_frame_subclass2str(struct ast_frame *f, char *subclass, size_t slen, char *moreinfo, size_t mlen)
Copy the discription of a frame's subclass into the provided string.
Definition: main/frame.c:406
ast_frame_type
Frame types.
@ AST_FRAME_VIDEO
@ AST_FRAME_NULL
@ AST_FRAME_HTML
@ AST_FRAME_IMAGE
@ AST_FRAME_DTMF_END
@ AST_FRAME_DTMF_BEGIN
@ AST_FRAME_BRIDGE_ACTION_SYNC
@ AST_FRAME_VOICE
@ AST_FRAME_RTCP
@ AST_FRAME_MODEM
@ AST_FRAME_TEXT_DATA
@ AST_FRAME_CONTROL
@ AST_FRAME_BRIDGE_ACTION
@ AST_FRAME_TEXT
ast_control_frame_type
Internal control frame subtype field values.
@ AST_CONTROL_RING
@ AST_CONTROL_SRCUPDATE
@ AST_CONTROL_RECORD_CANCEL
@ AST_CONTROL_WINK
@ AST_CONTROL_PROGRESS
@ AST_CONTROL_STREAM_TOPOLOGY_SOURCE_CHANGED
@ AST_CONTROL_OFFHOOK
@ AST_CONTROL_STREAM_RESTART
@ AST_CONTROL_STREAM_SUSPEND
@ AST_CONTROL_RADIO_UNKEY
@ AST_CONTROL_BUSY
@ AST_CONTROL_UNHOLD
@ AST_CONTROL_VIDUPDATE
@ AST_CONTROL_STREAM_TOPOLOGY_REQUEST_CHANGE
@ AST_CONTROL_STREAM_REVERSE
@ AST_CONTROL_PROCEEDING
@ AST_CONTROL_REDIRECTING
@ AST_CONTROL_TAKEOFFHOOK
@ AST_CONTROL_MCID
@ AST_CONTROL_T38_PARAMETERS
@ AST_CONTROL_READ_ACTION
@ AST_CONTROL_RECORD_STOP
@ AST_CONTROL_CONGESTION
@ AST_CONTROL_CC
@ AST_CONTROL_ANSWER
@ AST_CONTROL_RECORD_MUTE
@ AST_CONTROL_RINGING
@ AST_CONTROL_HANGUP
@ AST_CONTROL_STREAM_STOP
@ AST_CONTROL_RADIO_KEY
@ AST_CONTROL_HOLD
@ AST_CONTROL_OPTION
@ AST_CONTROL_STREAM_TOPOLOGY_CHANGED
@ AST_CONTROL_CONNECTED_LINE
@ AST_CONTROL_END_OF_Q
@ AST_CONTROL_TRANSFER
@ AST_CONTROL_STREAM_FORWARD
@ AST_CONTROL_FLASH
@ AST_CONTROL_RECORD_SUSPEND
@ AST_CONTROL_AOC
@ AST_CONTROL_SRCCHANGE
@ AST_CONTROL_INCOMPLETE
@ _XXX_AST_CONTROL_T38
@ AST_CONTROL_MASQUERADE_NOTIFY
@ AST_CONTROL_PVT_CAUSE_CODE
@ AST_CONTROL_UPDATE_RTP_PEER
#define LOG_WARNING
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
Asterisk module definitions.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
Core PBX routines and definitions.
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1558
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
#define NULL
Definition: resample.c:96
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
Main Channel structure associated with a channel.
descriptor for a cli entry.
Definition: cli.h:171
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
const char * name
Definition: pbx.h:119
Structure for a data store type.
Definition: datastore.h:31
const char * type
Definition: datastore.h:32
Structure for a data store object.
Definition: datastore.h:64
void * data
Definition: datastore.h:66
struct ast_format * format
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
union ast_frame::@226 data
enum ast_frame_type frametype
const char * src
Definition: astman.c:222
int values[ARRAY_LEN(frametype2str)]
int value
Definition: syslog.c:37
static struct test_val a
static struct test_val c
#define ARRAY_LEN(a)
Definition: utils.h:666