Wed Jan 8 2020 09:49:47

Asterisk developer's documentation


evt.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2007, Digium, Inc.
5  *
6  * Russell Bryant <russell@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 /*!
20  * \file
21  * \author Russell Bryant <russell@digium.com>
22  *
23  * \brief Usage of the SAForum AIS (Application Interface Specification)
24  *
25  * \arg http://www.openais.org/
26  *
27  * This file contains the code specific to the use of the EVT
28  * (Event) Service.
29  */
30 
31 /*** MODULEINFO
32  <support_level>extended</support_level>
33  ***/
34 
35 #include "asterisk.h"
36 
37 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 369001 $");
38 
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <unistd.h>
43 #include <errno.h>
44 
45 #include "ais.h"
46 
47 #include "asterisk/module.h"
48 #include "asterisk/utils.h"
49 #include "asterisk/cli.h"
50 #include "asterisk/logger.h"
51 #include "asterisk/event.h"
52 #include "asterisk/config.h"
53 #include "asterisk/linkedlists.h"
54 #include "asterisk/devicestate.h"
55 
56 #ifndef AST_MODULE
57 /* XXX HACK */
58 #define AST_MODULE "res_ais"
59 #endif
60 
61 SaEvtHandleT evt_handle;
62 static SaAisErrorT evt_init_res;
63 
64 void evt_channel_open_cb(SaInvocationT invocation, SaEvtChannelHandleT channel_handle,
65  SaAisErrorT error);
66 void evt_event_deliver_cb(SaEvtSubscriptionIdT subscription_id,
67  const SaEvtEventHandleT event_handle, const SaSizeT event_datalen);
68 
69 static const SaEvtCallbacksT evt_callbacks = {
70  .saEvtChannelOpenCallback = evt_channel_open_cb,
71  .saEvtEventDeliverCallback = evt_event_deliver_cb,
72 };
73 
74 static const struct {
75  const char *str;
78  { "mwi", AST_EVENT_MWI },
79  { "device_state", AST_EVENT_DEVICE_STATE_CHANGE },
80 };
81 
82 /*! Used to provide unique id's to egress subscriptions */
83 static int unique_id;
84 
87  /*! This is a unique identifier to identify this subscription in the event
88  * channel through the different API calls, subscribe, unsubscribe, and
89  * the event deliver callback. */
90  SaEvtSubscriptionIdT id;
92 };
93 
94 struct publish_event {
95  AST_LIST_ENTRY(publish_event) entry;
96  /*! We subscribe to events internally so that we can publish them
97  * on this event channel. */
98  struct ast_event_sub *sub;
99  enum ast_event_type type;
100 };
101 
103  AST_RWLIST_ENTRY(event_channel) entry;
105  AST_LIST_HEAD_NOLOCK(, publish_event) publish_events;
106  SaEvtChannelHandleT handle;
107  char name[1];
108 };
109 
110 static AST_RWLIST_HEAD_STATIC(event_channels, event_channel);
111 
112 void evt_channel_open_cb(SaInvocationT invocation, SaEvtChannelHandleT channel_handle,
113  SaAisErrorT error)
114 {
115 
116 }
117 
118 static void queue_event(struct ast_event *ast_event)
119 {
120  ast_event_queue_and_cache(ast_event);
121 }
122 
123 void evt_event_deliver_cb(SaEvtSubscriptionIdT sub_id,
124  const SaEvtEventHandleT event_handle, const SaSizeT event_datalen)
125 {
126  /* It is important to note that this works because we *know* that this
127  * function will only be called by a single thread, the dispatch_thread.
128  * If this module gets changed such that this is no longer the case, this
129  * should get changed to a thread-local buffer, instead. */
130  static unsigned char buf[4096];
131  struct ast_event *event_dup, *event = (void *) buf;
132  SaAisErrorT ais_res;
133  SaSizeT len = sizeof(buf);
134 
135  if (event_datalen > len) {
136  ast_log(LOG_ERROR, "Event received with size %u, which is too big\n"
137  "for the allocated size %u. Change the code to increase the size.\n",
138  (unsigned int) event_datalen, (unsigned int) len);
139  return;
140  }
141 
142  if (event_datalen < ast_event_minimum_length()) {
143  ast_debug(1, "Ignoring event that's too small. %u < %u\n",
144  (unsigned int) event_datalen,
145  (unsigned int) ast_event_minimum_length());
146  return;
147  }
148 
149  ais_res = saEvtEventDataGet(event_handle, event, &len);
150  if (ais_res != SA_AIS_OK) {
151  ast_log(LOG_ERROR, "Error retrieving event payload: %s\n",
152  ais_err2str(ais_res));
153  return;
154  }
155 
157  /* Don't feed events back in that originated locally. */
158  return;
159  }
160 
161  if (!(event_dup = ast_malloc(len)))
162  return;
163 
164  memcpy(event_dup, event, len);
165 
166  queue_event(event_dup);
167 }
168 
169 static const char *type_to_filter_str(enum ast_event_type type)
170 {
171  const char *filter_str = NULL;
172  int i;
173 
174  for (i = 0; i < ARRAY_LEN(supported_event_types); i++) {
175  if (supported_event_types[i].type == type) {
176  filter_str = supported_event_types[i].str;
177  break;
178  }
179  }
180 
181  return filter_str;
182 }
183 
184 static void ast_event_cb(const struct ast_event *ast_event, void *data)
185 {
186  SaEvtEventHandleT event_handle;
187  SaAisErrorT ais_res;
188  struct event_channel *event_channel = data;
189  SaClmClusterNodeT local_node;
190  SaEvtEventPatternArrayT pattern_array;
191  SaEvtEventPatternT pattern;
192  SaSizeT len;
193  const char *filter_str;
194  SaEvtEventIdT event_id;
195 
196  ast_log(LOG_DEBUG, "Got an event to forward\n");
197 
199  /* If the event didn't originate from this server, don't send it back out. */
200  ast_log(LOG_DEBUG, "Returning here\n");
201  return;
202  }
203 
204  ais_res = saEvtEventAllocate(event_channel->handle, &event_handle);
205  if (ais_res != SA_AIS_OK) {
206  ast_log(LOG_ERROR, "Error allocating event: %s\n", ais_err2str(ais_res));
207  ast_log(LOG_DEBUG, "Returning here\n");
208  return;
209  }
210 
211  ais_res = saClmClusterNodeGet(clm_handle, SA_CLM_LOCAL_NODE_ID,
212  SA_TIME_ONE_SECOND, &local_node);
213  if (ais_res != SA_AIS_OK) {
214  ast_log(LOG_ERROR, "Error getting local node name: %s\n", ais_err2str(ais_res));
215  goto return_event_free;
216  }
217 
218  filter_str = type_to_filter_str(ast_event_get_type(ast_event));
219  len = strlen(filter_str) + 1;
220  pattern.pattern = (SaUint8T *) filter_str;
221  pattern.patternSize = len;
222  pattern.allocatedSize = len;
223 
224  pattern_array.allocatedNumber = 1;
225  pattern_array.patternsNumber = 1;
226  pattern_array.patterns = &pattern;
227 
228  /*!
229  * /todo Make retention time configurable
230  * /todo Make event priorities configurable
231  */
232  ais_res = saEvtEventAttributesSet(event_handle, &pattern_array,
233  SA_EVT_LOWEST_PRIORITY, SA_TIME_ONE_MINUTE, &local_node.nodeName);
234  if (ais_res != SA_AIS_OK) {
235  ast_log(LOG_ERROR, "Error setting event attributes: %s\n", ais_err2str(ais_res));
236  goto return_event_free;
237  }
238 
239  for (;;) {
240  ais_res = saEvtEventPublish(event_handle,
241  ast_event, ast_event_get_size(ast_event), &event_id);
242  if (ais_res != SA_AIS_ERR_TRY_AGAIN) {
243  break;
244  }
245  sched_yield();
246  }
247 
248  if (ais_res != SA_AIS_OK) {
249  ast_log(LOG_ERROR, "Error publishing event: %s\n", ais_err2str(ais_res));
250  goto return_event_free;
251  }
252 
253 return_event_free:
254  ais_res = saEvtEventFree(event_handle);
255  if (ais_res != SA_AIS_OK) {
256  ast_log(LOG_ERROR, "Error freeing allocated event: %s\n", ais_err2str(ais_res));
257  }
258  ast_log(LOG_DEBUG, "Returning here (event_free)\n");
259 }
260 
261 static char *ais_evt_show_event_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
262 {
263  struct event_channel *event_channel;
264 
265  switch (cmd) {
266  case CLI_INIT:
267  e->command = "ais evt show event channels";
268  e->usage =
269  "Usage: ais evt show event channels\n"
270  " List configured event channels for the (EVT) Eventing service.\n";
271  return NULL;
272 
273  case CLI_GENERATE:
274  return NULL; /* no completion */
275  }
276 
277  if (a->argc != e->args)
278  return CLI_SHOWUSAGE;
279 
280  ast_cli(a->fd, "\n"
281  "=============================================================\n"
282  "=== Event Channels ==========================================\n"
283  "=============================================================\n"
284  "===\n");
285 
287  AST_RWLIST_TRAVERSE(&event_channels, event_channel, entry) {
288  struct publish_event *publish_event;
290 
291  ast_cli(a->fd, "=== ---------------------------------------------------------\n"
292  "=== Event Channel Name: %s\n", event_channel->name);
293 
294  AST_LIST_TRAVERSE(&event_channel->publish_events, publish_event, entry) {
295  ast_cli(a->fd, "=== ==> Publishing Event Type: %s\n",
296  type_to_filter_str(publish_event->type));
297  }
298 
299  AST_LIST_TRAVERSE(&event_channel->subscribe_events, subscribe_event, entry) {
300  ast_cli(a->fd, "=== ==> Subscribing to Event Type: %s\n",
301  type_to_filter_str(subscribe_event->type));
302  }
303 
304  ast_cli(a->fd, "=== ---------------------------------------------------------\n"
305  "===\n");
306  }
308 
309  ast_cli(a->fd, "=============================================================\n"
310  "\n");
311 
312  return CLI_SUCCESS;
313 }
314 
315 static struct ast_cli_entry ais_cli[] = {
316  AST_CLI_DEFINE(ais_evt_show_event_channels, "Show configured event channels"),
317 };
318 
320 {
321  struct event_channel *ec;
322 
324  AST_RWLIST_TRAVERSE(&event_channels, ec, entry) {
325  struct publish_event *pe;
326 
327  AST_LIST_TRAVERSE(&ec->publish_events, pe, entry) {
328  ast_debug(1, "Dumping cache for event channel '%s'\n", ec->name);
330  }
331  }
333 }
334 
335 static void add_publish_event(struct event_channel *event_channel, const char *event_type)
336 {
337  int i;
338  enum ast_event_type type = -1;
339  struct publish_event *publish_event;
340 
341  for (i = 0; i < ARRAY_LEN(supported_event_types); i++) {
342  if (!strcasecmp(event_type, supported_event_types[i].str)) {
343  type = supported_event_types[i].type;
344  break;
345  }
346  }
347 
348  if (type == -1) {
349  ast_log(LOG_WARNING, "publish_event option given with invalid value '%s'\n", event_type);
350  return;
351  }
352 
354  return;
355  }
356 
357  if (!(publish_event = ast_calloc(1, sizeof(*publish_event)))) {
358  return;
359  }
360 
361  publish_event->type = type;
362  ast_log(LOG_DEBUG, "Subscribing to event type %d\n", type);
363  publish_event->sub = ast_event_subscribe(type, ast_event_cb, "AIS", event_channel,
365  ast_event_dump_cache(publish_event->sub);
366 
367  AST_LIST_INSERT_TAIL(&event_channel->publish_events, publish_event, entry);
368 }
369 
370 static SaAisErrorT set_egress_subscription(struct event_channel *event_channel,
372 {
373  SaAisErrorT ais_res;
374  SaEvtEventFilterArrayT filter_array;
375  SaEvtEventFilterT filter;
376  const char *filter_str = NULL;
377  SaSizeT len;
378 
379  /* We know it's going to be valid. It was checked earlier. */
380  filter_str = type_to_filter_str(subscribe_event->type);
381 
382  filter.filterType = SA_EVT_EXACT_FILTER;
383  len = strlen(filter_str) + 1;
384  filter.filter.allocatedSize = len;
385  filter.filter.patternSize = len;
386  filter.filter.pattern = (SaUint8T *) filter_str;
387 
388  filter_array.filtersNumber = 1;
389  filter_array.filters = &filter;
390 
391  ais_res = saEvtEventSubscribe(event_channel->handle, &filter_array,
392  subscribe_event->id);
393 
394  return ais_res;
395 }
396 
397 static void add_subscribe_event(struct event_channel *event_channel, const char *event_type)
398 {
399  int i;
400  enum ast_event_type type = -1;
402  SaAisErrorT ais_res;
403 
404  for (i = 0; i < ARRAY_LEN(supported_event_types); i++) {
405  if (!strcasecmp(event_type, supported_event_types[i].str)) {
406  type = supported_event_types[i].type;
407  break;
408  }
409  }
410 
411  if (type == -1) {
412  ast_log(LOG_WARNING, "subscribe_event option given with invalid value '%s'\n", event_type);
413  return;
414  }
415 
417  return;
418  }
419 
420  if (!(subscribe_event = ast_calloc(1, sizeof(*subscribe_event)))) {
421  return;
422  }
423 
424  subscribe_event->type = type;
425  subscribe_event->id = ast_atomic_fetchadd_int(&unique_id, +1);
426 
427  ais_res = set_egress_subscription(event_channel, subscribe_event);
428  if (ais_res != SA_AIS_OK) {
429  ast_log(LOG_ERROR, "Error setting up egress subscription: %s\n",
430  ais_err2str(ais_res));
431  free(subscribe_event);
432  return;
433  }
434 
435  AST_LIST_INSERT_TAIL(&event_channel->subscribe_events, subscribe_event, entry);
436 }
437 
438 static void build_event_channel(struct ast_config *cfg, const char *cat)
439 {
440  struct ast_variable *var;
441  struct event_channel *event_channel;
442  SaAisErrorT ais_res;
443  SaNameT sa_name = { 0, };
444 
446  AST_RWLIST_TRAVERSE(&event_channels, event_channel, entry) {
447  if (!strcasecmp(event_channel->name, cat))
448  break;
449  }
451  if (event_channel) {
452  ast_log(LOG_WARNING, "Event channel '%s' was specified twice in "
453  "configuration. Second instance ignored.\n", cat);
454  return;
455  }
456 
457  if (!(event_channel = ast_calloc(1, sizeof(*event_channel) + strlen(cat))))
458  return;
459 
460  strcpy(event_channel->name, cat);
461  ast_copy_string((char *) sa_name.value, cat, sizeof(sa_name.value));
462  sa_name.length = strlen((char *) sa_name.value);
463  ais_res = saEvtChannelOpen(evt_handle, &sa_name,
464  SA_EVT_CHANNEL_PUBLISHER | SA_EVT_CHANNEL_SUBSCRIBER | SA_EVT_CHANNEL_CREATE,
465  SA_TIME_MAX, &event_channel->handle);
466  if (ais_res != SA_AIS_OK) {
467  ast_log(LOG_ERROR, "Error opening event channel: %s\n", ais_err2str(ais_res));
468  free(event_channel);
469  return;
470  }
471 
472  for (var = ast_variable_browse(cfg, cat); var; var = var->next) {
473  if (!strcasecmp(var->name, "type")) {
474  continue;
475  } else if (!strcasecmp(var->name, "publish_event")) {
476  add_publish_event(event_channel, var->value);
477  } else if (!strcasecmp(var->name, "subscribe_event")) {
478  add_subscribe_event(event_channel, var->value);
479  } else {
480  ast_log(LOG_WARNING, "Event channel '%s' contains invalid option '%s'\n",
481  event_channel->name, var->name);
482  }
483  }
484 
486  AST_RWLIST_INSERT_TAIL(&event_channels, event_channel, entry);
488 }
489 
490 static void load_config(void)
491 {
492  static const char filename[] = "ais.conf";
493  struct ast_config *cfg;
494  const char *cat = NULL;
495  struct ast_flags config_flags = { 0 };
496 
497  if (!(cfg = ast_config_load(filename, config_flags)) || cfg == CONFIG_STATUS_FILEINVALID)
498  return;
499 
500  while ((cat = ast_category_browse(cfg, cat))) {
501  const char *type;
502 
503  if (!strcasecmp(cat, "general"))
504  continue;
505 
506  if (!(type = ast_variable_retrieve(cfg, cat, "type"))) {
507  ast_log(LOG_WARNING, "Invalid entry in %s defined with no type!\n",
508  filename);
509  continue;
510  }
511 
512  if (!strcasecmp(type, "event_channel")) {
513  build_event_channel(cfg, cat);
514  } else {
515  ast_log(LOG_WARNING, "Entry in %s defined with invalid type '%s'\n",
516  filename, type);
517  }
518  }
519 
520  ast_config_destroy(cfg);
521 }
522 
523 static void publish_event_destroy(struct publish_event *publish_event)
524 {
525  ast_event_unsubscribe(publish_event->sub);
526 
527  free(publish_event);
528 }
529 
530 static void subscribe_event_destroy(const struct event_channel *event_channel,
532 {
533  SaAisErrorT ais_res;
534 
535  /* saEvtChannelClose() will actually do this automatically, but it just
536  * feels cleaner to go ahead and do it manually ... */
537  ais_res = saEvtEventUnsubscribe(event_channel->handle, subscribe_event->id);
538  if (ais_res != SA_AIS_OK) {
539  ast_log(LOG_ERROR, "Error unsubscribing: %s\n", ais_err2str(ais_res));
540  }
541 
542  free(subscribe_event);
543 }
544 
545 static void event_channel_destroy(struct event_channel *event_channel)
546 {
547  struct publish_event *publish_event;
549  SaAisErrorT ais_res;
550 
551  while ((publish_event = AST_LIST_REMOVE_HEAD(&event_channel->publish_events, entry)))
552  publish_event_destroy(publish_event);
553  while ((subscribe_event = AST_LIST_REMOVE_HEAD(&event_channel->subscribe_events, entry)))
554  subscribe_event_destroy(event_channel, subscribe_event);
555 
556  ais_res = saEvtChannelClose(event_channel->handle);
557  if (ais_res != SA_AIS_OK) {
558  ast_log(LOG_ERROR, "Error closing event channel '%s': %s\n",
559  event_channel->name, ais_err2str(ais_res));
560  }
561 
562  free(event_channel);
563 }
564 
565 static void destroy_event_channels(void)
566 {
567  struct event_channel *event_channel;
568 
570  while ((event_channel = AST_RWLIST_REMOVE_HEAD(&event_channels, entry))) {
571  event_channel_destroy(event_channel);
572  }
574 }
575 
577 {
578  evt_init_res = saEvtInitialize(&evt_handle, &evt_callbacks, &ais_version);
579  if (evt_init_res != SA_AIS_OK) {
580  ast_log(LOG_ERROR, "Could not initialize eventing service: %s\n",
582  return -1;
583  }
584 
585  load_config();
586 
587  ast_cli_register_multiple(ais_cli, ARRAY_LEN(ais_cli));
588 
589  return 0;
590 }
591 
593 {
594  SaAisErrorT ais_res;
595 
596  if (evt_init_res != SA_AIS_OK) {
597  return 0;
598  }
599 
601 
602  ais_res = saEvtFinalize(evt_handle);
603  if (ais_res != SA_AIS_OK) {
604  ast_log(LOG_ERROR, "Problem stopping eventing service: %s\n",
605  ais_err2str(ais_res));
606  return -1;
607  }
608 
609  return 0;
610 }
struct event_channel::@356 publish_events
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:191
An event.
Definition: event.c:85
void evt_event_deliver_cb(SaEvtSubscriptionIdT subscription_id, const SaEvtEventHandleT event_handle, const SaSizeT event_datalen)
Definition: evt.c:123
Asterisk main include file. File version handling, generic pbx functions.
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
Definition: config.c:625
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static struct ast_cli_entry ais_cli[]
Definition: evt.c:315
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
Definition: linkedlists.h:332
int ast_ais_evt_load_module(void)
Definition: evt.c:576
enum ast_event_type ast_event_get_type(const struct ast_event *event)
Get the type for an event.
Definition: event.c:1070
void ast_ais_evt_membership_changed(void)
Definition: evt.c:319
SaEvtHandleT evt_handle
Definition: evt.c:61
Device state management.
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
static void add_publish_event(struct event_channel *event_channel, const char *event_type)
Definition: evt.c:335
int ast_event_queue_and_cache(struct ast_event *event)
Queue and cache an event.
Definition: event.c:1465
descriptor for a cli entry.
Definition: cli.h:165
const int argc
Definition: cli.h:154
#define LOG_WARNING
Definition: logger.h:144
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
Definition: config.c:597
static void event_channel_destroy(struct event_channel *event_channel)
Definition: evt.c:545
static void load_config(void)
Definition: evt.c:490
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
static void queue_event(struct ast_event *ast_event)
Definition: evt.c:118
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
#define var
Definition: ast_expr2f.c:606
int ast_enable_distributed_devstate(void)
Enable distributed device state processing.
Definition: devicestate.c:796
Definition: cli.h:146
struct subscribe_event::@354 entry
static char * ais_evt_show_event_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: evt.c:261
Configuration File Parser.
static const SaEvtCallbacksT evt_callbacks
Definition: evt.c:69
static void publish_event_destroy(struct publish_event *publish_event)
Definition: evt.c:523
const char * str
Definition: app_jack.c:144
static void add_subscribe_event(struct event_channel *event_channel, const char *event_type)
Definition: evt.c:397
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
#define LOG_DEBUG
Definition: logger.h:122
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
SaVersionT ais_version
Definition: res_ais.c:70
Entity ID Used by All events Payload type: RAW This IE indicates which server the event originated fr...
Definition: event_defs.h:266
static void build_event_channel(struct ast_config *cfg, const char *cat)
Definition: evt.c:438
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: netsock.c:320
Utility functions.
int args
This gets set in ast_cli_register()
Definition: cli.h:179
static void subscribe_event_destroy(const struct event_channel *event_channel, struct subscribe_event *subscribe_event)
Definition: evt.c:530
enum ast_event_type type
Definition: evt.c:91
static struct @353 supported_event_types[]
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
ast_event_type
Event types.
Definition: event_defs.h:30
const char * value
Definition: config.h:79
const int fd
Definition: cli.h:153
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
Usage of the SAForum AIS (Application Interface Specification)
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
Definition: config.c:810
A set of macros to manage forward-linked lists.
const char * name
Definition: config.h:77
void evt_channel_open_cb(SaInvocationT invocation, SaEvtChannelHandleT channel_handle, SaAisErrorT error)
Definition: evt.c:112
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
static int unique_id
Definition: evt.c:83
enum ast_event_type type
Definition: evt.c:99
const void * ast_event_get_ie_raw(const struct ast_event *event, enum ast_event_ie_type ie_type)
Get the value of an information element that has a raw payload.
Definition: event.c:1111
void ast_event_dump_cache(const struct ast_event_sub *event_sub)
Dump the event cache for the subscriber.
Definition: event.c:654
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
Definition: linkedlists.h:224
#define LOG_ERROR
Definition: logger.h:155
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
#define free(a)
Definition: astmm.h:94
#define CLI_SHOWUSAGE
Definition: cli.h:44
subscribe_events
Definition: evt.c:104
static const char * type_to_filter_str(enum ast_event_type type)
Definition: evt.c:169
Event subscription.
Definition: event.c:124
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static void ast_event_cb(const struct ast_event *ast_event, void *data)
Definition: evt.c:184
SaClmHandleT clm_handle
Definition: clm.c:52
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
struct ast_event_sub * sub
Definition: evt.c:98
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:409
int ast_ais_evt_unload_module(void)
Definition: evt.c:592
static const char name[]
char * command
Definition: cli.h:180
size_t ast_event_minimum_length(void)
Get the minimum length of an ast_event.
Definition: event.c:1854
#define AST_RWLIST_REMOVE_HEAD
Definition: linkedlists.h:829
static const char type[]
Definition: chan_nbs.c:57
Structure used to handle boolean flags.
Definition: utils.h:200
Support for logging to various files, console and syslog Configuration in file logger.conf.
#define AST_RWLIST_ENTRY
Definition: linkedlists.h:414
const char * usage
Definition: cli.h:171
struct ast_eid ast_eid_default
Global EID.
Definition: asterisk.c:192
static void destroy_event_channels(void)
Definition: evt.c:565
#define CLI_SUCCESS
Definition: cli.h:43
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:726
SaEvtChannelHandleT handle
Definition: evt.c:106
Standard Command Line Interface.
#define ast_calloc(a, b)
Definition: astmm.h:82
struct ast_event_sub * ast_event_subscribe(enum ast_event_type event_type, ast_event_cb_t cb, const char *description, void *userdata,...)
Subscribe to events.
Definition: event.c:909
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
Definition: cli.c:2167
const char * ais_err2str(SaAisErrorT error)
Definition: res_ais.c:105
static SaAisErrorT evt_init_res
Definition: evt.c:62
static SaAisErrorT set_egress_subscription(struct event_channel *event_channel, struct subscribe_event *subscribe_event)
Definition: evt.c:370
size_t ast_event_get_size(const struct ast_event *event)
Get the size of an event.
Definition: event.c:340
struct ast_variable * next
Definition: config.h:82
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
static int filter(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
Definition: func_strings.c:694
#define ast_malloc(a)
Definition: astmm.h:91
Asterisk module definitions.
struct ast_event_sub * ast_event_unsubscribe(struct ast_event_sub *event_sub)
Un-subscribe from events.
Definition: event.c:987
SaEvtSubscriptionIdT id
Definition: evt.c:90
char name[1]
Definition: evt.c:107
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180