Asterisk - The Open Source Telephony Project GIT-master-8924258
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
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 <since>
43 <version>10.0.0</version>
44 </since>
45 <synopsis>
46 View internal ast_frames as they are read and written on a channel.
47 </synopsis>
48 <syntax>
49 <parameter name="filter list type" required="true">
50 <para>A filter can be applied to the trace to limit what frames are viewed. This
51 filter can either be a <literal>white</literal> or <literal>black</literal> list
52 of frame types. When no filter type is present, <literal>white</literal> is
53 used. If no arguments are provided at all, all frames will be output.
54 </para>
55
56 <para>Below are the different types of frames that can be filtered.</para>
57 <enumlist>
58 <enum name = "DTMF_BEGIN" />
59 <enum name = "DTMF_END" />
60 <enum name = "VOICE" />
61 <enum name = "VIDEO" />
62 <enum name = "CONTROL" />
63 <enum name = "NULL" />
64 <enum name = "IAX" />
65 <enum name = "TEXT" />
66 <enum name = "TEXT_DATA" />
67 <enum name = "IMAGE" />
68 <enum name = "HTML" />
69 <enum name = "CNG" />
70 <enum name = "MODEM" />
71 </enumlist>
72 </parameter>
73 </syntax>
74 <description>
75 <para>Examples:</para>
76 <example title="View only DTMF frames">
77 exten => 1,1,Set(FRAME_TRACE(white)=DTMF_BEGIN,DTMF_END)
78 </example>
79 <example title="View only DTMF frames">
80 exten => 1,1,Set(FRAME_TRACE()=DTMF_BEGIN,DTMF_END)
81 </example>
82 <example title="View everything except DTMF frames">
83 exten => 1,1,Set(FRAME_TRACE(black)=DTMF_BEGIN,DTMF_END)
84 </example>
85 </description>
86 </function>
87 ***/
88
89static void print_frame(struct ast_frame *frame);
90static struct {
92 const char *str;
93} frametype2str[] = {
94 { AST_FRAME_DTMF_BEGIN, "DTMF_BEGIN" },
95 { AST_FRAME_DTMF_END, "DTMF_END" },
96 { AST_FRAME_VOICE, "VOICE" },
97 { AST_FRAME_VIDEO, "VIDEO" },
98 { AST_FRAME_CONTROL, "CONTROL" },
99 { AST_FRAME_NULL, "NULL" },
100 { AST_FRAME_IAX, "IAX" },
101 { AST_FRAME_TEXT, "TEXT" },
102 { AST_FRAME_TEXT_DATA, "TEXT_DATA" },
103 { AST_FRAME_IMAGE, "IMAGE" },
104 { AST_FRAME_HTML, "HTML" },
105 { AST_FRAME_CNG, "CNG" },
106 { AST_FRAME_MODEM, "MODEM" },
108
110 int list_type; /* 0 = white, 1 = black */
112};
113
114static void datastore_destroy_cb(void *data) {
115 ast_free(data);
116}
117
119 .type = "frametrace",
120 .destroy = datastore_destroy_cb
121};
122
123static void hook_destroy_cb(void *framedata)
124{
125 ast_free(framedata);
126}
127
128static struct ast_frame *hook_event_cb(struct ast_channel *chan, struct ast_frame *frame, enum ast_framehook_event event, void *data)
129{
130 int i;
131 int show_frame = 0;
132 struct frame_trace_data *framedata = data;
133 if (!frame) {
134 return frame;
135 }
136
138 return frame;
139 }
140
141 for (i = 0; i < ARRAY_LEN(frametype2str); i++) {
142 if (frame->frametype == frametype2str[i].type) {
143 if ((framedata->list_type == 0) && (framedata->values[i])) { /* white list */
144 show_frame = 1;
145 } else if ((framedata->list_type == 1) && (!framedata->values[i])){ /* black list */
146 show_frame = 1;
147 }
148 break;
149 }
150 }
151
152 if (show_frame) {
153 ast_verbose("%s on Channel %s\n", event == AST_FRAMEHOOK_EVENT_READ ? "<--Read" : "--> Write", ast_channel_name(chan));
154 print_frame(frame);
155 }
156 return frame;
157}
158
159static int frame_trace_helper(struct ast_channel *chan, const char *cmd, char *data, const char *value)
160{
161 struct frame_trace_data *framedata;
162 struct ast_datastore *datastore = NULL;
163 struct ast_framehook_interface interface = {
165 .event_cb = hook_event_cb,
166 .destroy_cb = hook_destroy_cb,
167 };
168 int i = 0;
169
170 if (!chan) {
171 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
172 return -1;
173 }
174
175 if (!(framedata = ast_calloc(1, sizeof(*framedata)))) {
176 return 0;
177 }
178
179 interface.data = framedata;
180
181 if (!strcasecmp(data, "black")) {
182 framedata->list_type = 1;
183 }
184 for (i = 0; i < ARRAY_LEN(frametype2str); i++) {
186 framedata->values[i] = 1;
187 }
188 }
189
190 ast_channel_lock(chan);
191 i = ast_framehook_attach(chan, &interface);
192 if (i >= 0) {
193 int *id;
194 if ((datastore = ast_channel_datastore_find(chan, &frame_trace_datastore, NULL))) {
195 id = datastore->data;
196 ast_framehook_detach(chan, *id);
197 ast_channel_datastore_remove(chan, datastore);
198 ast_datastore_free(datastore);
199 }
200
201 if (!(datastore = ast_datastore_alloc(&frame_trace_datastore, NULL))) {
202 ast_framehook_detach(chan, i);
203 ast_channel_unlock(chan);
204 return 0;
205 }
206
207 if (!(id = ast_calloc(1, sizeof(int)))) {
208 ast_datastore_free(datastore);
209 ast_framehook_detach(chan, i);
210 ast_channel_unlock(chan);
211 return 0;
212 }
213
214 *id = i; /* Store off the id. The channel is still locked so it is safe to access this ptr. */
215 datastore->data = id;
216 ast_channel_datastore_add(chan, datastore);
217 }
218 ast_channel_unlock(chan);
219
220 return 0;
221}
222
223static void print_frame(struct ast_frame *frame)
224{
225 switch (frame->frametype) {
227 ast_verbose("FrameType: DTMF END\n");
228 ast_verbose("Digit: 0x%02X '%c'\n", (unsigned)frame->subclass.integer,
229 frame->subclass.integer < ' ' ? ' ' : frame->subclass.integer);
230 break;
231 case AST_FRAME_VOICE:
232 ast_verbose("FrameType: VOICE\n");
233 ast_verbose("Codec: %s\n", ast_format_get_name(frame->subclass.format));
234 ast_verbose("MS: %ld\n", frame->len);
235 ast_verbose("Samples: %d\n", frame->samples);
236 ast_verbose("Bytes: %d\n", frame->datalen);
237 break;
238 case AST_FRAME_VIDEO:
239 ast_verbose("FrameType: VIDEO\n");
240 ast_verbose("Codec: %s\n", ast_format_get_name(frame->subclass.format));
241 ast_verbose("MS: %ld\n", frame->len);
242 ast_verbose("Samples: %d\n", frame->samples);
243 ast_verbose("Bytes: %d\n", frame->datalen);
244 break;
246 ast_verbose("FrameType: CONTROL\n");
247 switch ((enum ast_control_frame_type) frame->subclass.integer) {
249 ast_verbose("SubClass: HANGUP\n");
250 break;
251 case AST_CONTROL_RING:
252 ast_verbose("SubClass: RING\n");
253 break;
255 ast_verbose("SubClass: RINGING\n");
256 break;
258 ast_verbose("SubClass: ANSWER\n");
259 break;
260 case AST_CONTROL_BUSY:
261 ast_verbose("SubClass: BUSY\n");
262 break;
264 ast_verbose("SubClass: TAKEOFFHOOK\n");
265 break;
267 ast_verbose("SubClass: OFFHOOK\n");
268 break;
270 ast_verbose("SubClass: CONGESTION\n");
271 break;
273 ast_verbose("SubClass: FLASH\n");
274 break;
275 case AST_CONTROL_WINK:
276 ast_verbose("SubClass: WINK\n");
277 break;
279 ast_verbose("SubClass: OPTION\n");
280 break;
282 ast_verbose("SubClass: RADIO KEY\n");
283 break;
285 ast_verbose("SubClass: RADIO UNKEY\n");
286 break;
288 ast_verbose("SubClass: PROGRESS\n");
289 break;
291 ast_verbose("SubClass: PROCEEDING\n");
292 break;
293 case AST_CONTROL_HOLD:
294 ast_verbose("SubClass: HOLD\n");
295 break;
297 ast_verbose("SubClass: UNHOLD\n");
298 break;
300 ast_verbose("SubClass: VIDUPDATE\n");
301 break;
303 ast_verbose("SubClass: XXX T38\n");
304 break;
306 ast_verbose("SubClass: SRCUPDATE\n");
307 break;
309 ast_verbose("SubClass: TRANSFER\n");
310 break;
312 ast_verbose("SubClass: CONNECTED LINE\n");
313 break;
315 ast_verbose("SubClass: REDIRECTING\n");
316 break;
318 ast_verbose("SubClass: T38 PARAMETERS\n");
319 break;
320 case AST_CONTROL_CC:
321 ast_verbose("SubClass: CC\n");
322 break;
324 ast_verbose("SubClass: SRCCHANGE\n");
325 break;
327 ast_verbose("SubClass: READ ACTION\n");
328 break;
329 case AST_CONTROL_AOC:
330 ast_verbose("SubClass: AOC\n");
331 break;
332 case AST_CONTROL_MCID:
333 ast_verbose("SubClass: MCID\n");
334 break;
336 ast_verbose("SubClass: INCOMPLETE\n");
337 break;
339 ast_verbose("SubClass: END_OF_Q\n");
340 break;
342 ast_verbose("SubClass: UPDATE_RTP_PEER\n");
343 break;
345 ast_verbose("SubClass: PVT_CAUSE_CODE\n");
346 break;
348 ast_verbose("SubClass: MASQUERADE_NOTIFY\n");
349 break;
351 ast_verbose("SubClass: STREAM_TOPOLOGY_REQUEST_CHANGE\n");
352 break;
354 ast_verbose("SubClass: STREAM_TOPOLOGY_CHANGED\n");
355 break;
357 ast_verbose("SubClass: STREAM_TOPOLOGY_SOURCE_CHANGED\n");
358 break;
360 ast_verbose("SubClass: STREAM_STOP\n");
361 break;
363 ast_verbose("SubClass: STREAM_SUSPEND\n");
364 break;
366 ast_verbose("SubClass: STREAM_RESTART\n");
367 break;
369 ast_verbose("SubClass: STREAM_REVERSE\n");
370 break;
372 ast_verbose("SubClass: STREAM_FORWARD\n");
373 break;
375 ast_verbose("SubClass: RECORD_CANCEL\n");
376 break;
378 ast_verbose("SubClass: RECORD_STOP\n");
379 break;
381 ast_verbose("SubClass: RECORD_SUSPEND\n");
382 break;
384 ast_verbose("SubClass: RECORD_MUTE\n");
385 break;
386 }
387
388 if (frame->subclass.integer == -1) {
389 ast_verbose("SubClass: %d\n", frame->subclass.integer);
390 }
391 ast_verbose("Bytes: %d\n", frame->datalen);
392 break;
393 case AST_FRAME_RTCP:
394 ast_verbose("FrameType: RTCP\n");
395 break;
396 case AST_FRAME_NULL:
397 ast_verbose("FrameType: NULL\n");
398 break;
399 case AST_FRAME_IAX:
400 ast_verbose("FrameType: IAX\n");
401 break;
402 case AST_FRAME_TEXT:
403 ast_verbose("FrameType: TXT\n");
404 ast_verbose("Text: %.*s\n", frame->datalen, (char*) frame->data.ptr);
405 break;
407 ast_verbose("FrameType: TXT_DATA\n");
408 break;
409 case AST_FRAME_IMAGE:
410 ast_verbose("FrameType: IMAGE\n");
411 break;
412 case AST_FRAME_HTML:
413 ast_verbose("FrameType: HTML\n");
414 break;
415 case AST_FRAME_CNG:
416 ast_verbose("FrameType: CNG\n");
417 break;
418 case AST_FRAME_MODEM:
419 ast_verbose("FrameType: MODEM\n");
420 break;
422 ast_verbose("FrameType: DTMF BEGIN\n");
423 ast_verbose("Digit: 0x%02X '%c'\n", (unsigned)frame->subclass.integer,
424 frame->subclass.integer < ' ' ? ' ' : frame->subclass.integer);
425 break;
427 ast_verbose("FrameType: Bridge\n");
428 ast_verbose("SubClass: %d\n", frame->subclass.integer);
429 break;
431 ast_verbose("Frametype: Synchronous Bridge\n");
432 ast_verbose("Subclass: %d\n", frame->subclass.integer);
433 break;
434 }
435
436 ast_verbose("Src: %s\n", ast_strlen_zero(frame->src) ? "NOT PRESENT" : frame->src);
437 ast_verbose("\n");
438}
439
441 .name = "FRAME_TRACE",
442 .write = frame_trace_helper,
443};
444
445static char *handle_dump_frames(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
446{
447 struct ast_channel *chan;
448 struct ast_frame *f;
449 int c = 1;
450
451 switch (cmd) {
452 case CLI_INIT:
453 e->command = "channel dump frames";
454 e->usage =
455 "Usage: channel dump frames <channel>\n"
456 " List all frames queued to a channel.\n";
457 return NULL;
458 case CLI_GENERATE:
459 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
460 }
461
462 if (a->argc != 4) {
463 return CLI_SHOWUSAGE;
464 }
465
466 chan = ast_channel_get_by_name(a->argv[3]);
467 if (!chan) {
468 ast_cli(a->fd, "%s is not a known channel\n", a->argv[3]);
469 return CLI_SUCCESS;
470 }
471
472 ast_channel_lock(chan);
473
474 ast_cli(a->fd, "== Frame list for %s ==\n", ast_channel_name(chan));
475 ast_cli(a->fd, "%5s %6s %6s %-15s (%-20s) - %s\n", "#", "Seqno", "Stream", "Frame Type", "Frame Subclass", "Src");
477 char type[64];
478 char subclass[64];
481 ast_cli(a->fd, "%5d %6d %6d %-15s (%-20s) - %s\n", c++, f->seqno, f->stream_num, type, subclass, S_OR(f->src, ""));
482 }
483
484 ast_channel_unlock(chan);
485 ast_channel_unref(chan);
486 return CLI_SUCCESS;
487}
488
489static struct ast_cli_entry cli_frames[] = {
490 AST_CLI_DEFINE(handle_dump_frames, "Display frames queued on a specific channel")
491};
492
493static int unload_module(void)
494{
497}
498
499static int load_module(void)
500{
504}
505
506AST_MODULE_INFO_STANDARD_EXTENDED(ASTERISK_GPL_KEY, "Frame Trace for internal ast_frame debugging.");
enum queue_result id
Definition: app_queue.c:1808
char * strcasestr(const char *, const char *)
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:2414
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2423
#define ast_channel_lock(chan)
Definition: channel.h:2970
struct ast_readq_list * ast_channel_readq(struct ast_channel *chan)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3006
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1481
#define ast_channel_unlock(chan)
Definition: channel.h:2971
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:2428
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 * 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:1559
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.
union ast_frame::@228 data
struct ast_frame_subclass subclass
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