Asterisk - The Open Source Telephony Project  18.5.0
test_amihooks.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2009, Digium, Inc.
5  *
6  * David Brooks <[email protected]>
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 Test AMI hook
22  *
23  * \author David Brooks <[email protected]> based off of code written by Russell Bryant <[email protected]>
24  *
25  * This started, and continues to serves, as an example illustrating the ability
26  * for a custom module to hook into AMI. Registration for AMI events and sending
27  * of AMI actions is shown. A test has also been created that utilizes the original
28  * example in order to make sure the ami event hook gets raised.
29  */
30 
31 /*** MODULEINFO
32  <depend>TEST_FRAMEWORK</depend>
33  <support_level>core</support_level>
34  ***/
35 
36 #include "asterisk.h"
37 
38 #include "asterisk/module.h"
39 #include "asterisk/cli.h"
40 #include "asterisk/utils.h"
41 #include "asterisk/manager.h"
42 #include "asterisk/test.h"
43 
44 #define CATEGORY "/main/amihooks/"
45 
48 int done;
49 
50 static int wait_for_hook(struct ast_test *test)
51 {
52  struct timeval start = ast_tvnow();
53  struct timespec timeout = {
54  .tv_sec = start.tv_sec + 2,
55  .tv_nsec = start.tv_usec * 1000
56  };
57  int res = 0;
58 
60  while (!done) {
61  if (ast_cond_timedwait(&hook_cond, &hook_lock, &timeout) == ETIMEDOUT) {
62  ast_test_status_update(test, "Test timed out while waiting for hook event\n");
63  res = -1;
64  break;
65  }
66  }
68 
69  return res;
70 }
71 
72 AST_TEST_DEFINE(amihook_cli_send)
73 {
74  switch (cmd) {
75  case TEST_INIT:
76  info->name = __func__;
77  info->category = CATEGORY;
78  info->summary = "Execute an action using an AMI hook";
79  info->description = info->summary;
80  return AST_TEST_NOT_RUN;
81  case TEST_EXECUTE:
82  break;
83  }
84 
85  done = 0;
86  if (ast_cli_command(-1, "amihook send")) {
87  return AST_TEST_FAIL;
88  }
89 
91 }
92 
93 /* The helper function is required by struct manager_custom_hook.
94  * See __ast_manager_event_multichan for details */
95 static int amihook_helper(int category, const char *event, char *content)
96 {
97  ast_log(LOG_NOTICE, "AMI Event: \nCategory: %d Event: %s\n%s\n", category, event, content);
98 
100  done = 1;
103  return 0;
104 }
105 
107  .file = __FILE__,
108  .helper = &amihook_helper,
109 };
110 
111 static int hook_send(void) {
112  int res;
113 
114  /* Send a test action (core show version) to the AMI */
115  res = ast_hook_send_action(&test_hook, "Action: Command\nCommand: core show version\nActionID: 987654321\n");
116 
117  return res;
118 }
119 
120 static void register_hook(void) {
121 
122  /* Unregister the hook, we don't want a double-registration (Bad Things(tm) happen) */
123  ast_manager_unregister_hook(&test_hook);
124 
125  /* Register the hook for AMI events */
126  ast_manager_register_hook(&test_hook);
127 
128 }
129 
130 static void unregister_hook(void) {
131 
132  /* Unregister the hook */
133  ast_manager_unregister_hook(&test_hook);
134 
135 }
136 
137 static char *handle_cli_amihook_send(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
138 {
139  switch (cmd) {
140  case CLI_INIT:
141  e->command = "amihook send";
142  e->usage = ""
143  "Usage: amihook send"
144  "";
145  return NULL;
146  case CLI_GENERATE:
147  return NULL;
148  case CLI_HANDLER:
149  hook_send();
150  return CLI_SUCCESS;
151  }
152 
153  return CLI_FAILURE;
154 }
155 
156 static char *handle_cli_amihook_register_hook(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
157 {
158  switch (cmd) {
159  case CLI_INIT:
160  e->command = "amihook register";
161  e->usage = ""
162  "Usage: amihook register"
163  "";
164  return NULL;
165  case CLI_GENERATE:
166  return NULL;
167  case CLI_HANDLER:
168  register_hook();
169  return CLI_SUCCESS;
170  }
171 
172  return CLI_FAILURE;
173 }
174 
175 static char *handle_cli_amihook_unregister_hook(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
176 {
177  switch (cmd) {
178  case CLI_INIT:
179  e->command = "amihook unregister";
180  e->usage = ""
181  "Usage: amihook unregister"
182  "";
183  return NULL;
184  case CLI_GENERATE:
185  return NULL;
186  case CLI_HANDLER:
187  unregister_hook();
188  return CLI_SUCCESS;
189  }
190 
191  return CLI_FAILURE;
192 }
193 
194 static struct ast_cli_entry cli_amihook_evt[] = {
195  AST_CLI_DEFINE(handle_cli_amihook_send, "Send an AMI event"),
196  AST_CLI_DEFINE(handle_cli_amihook_register_hook, "Register module for AMI hook"),
197  AST_CLI_DEFINE(handle_cli_amihook_unregister_hook, "Unregister module for AMI hook"),
198 };
199 
200 static int unload_module(void)
201 {
202  AST_TEST_UNREGISTER(amihook_cli_send);
203  ast_manager_unregister_hook(&test_hook);
204  return ast_cli_unregister_multiple(cli_amihook_evt, ARRAY_LEN(cli_amihook_evt));
205 }
206 
207 static int load_module(void)
208 {
209  int res;
210 
211  res = ast_cli_register_multiple(cli_amihook_evt, ARRAY_LEN(cli_amihook_evt));
212 
213  AST_TEST_REGISTER(amihook_cli_send);
214 
216 }
217 
static char * handle_cli_amihook_unregister_hook(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
AST_TEST_DEFINE(amihook_cli_send)
Definition: test_amihooks.c:72
static int wait_for_hook(struct ast_test *test)
Definition: test_amihooks.c:50
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
Asterisk main include file. File version handling, generic pbx functions.
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
void ast_manager_unregister_hook(struct manager_custom_hook *hook)
Delete a custom hook to be called when an event is fired.
Definition: manager.c:1942
static ast_mutex_t hook_lock
Definition: test_amihooks.c:46
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
int ast_hook_send_action(struct manager_custom_hook *hook, const char *msg)
Registered hooks can call this function to invoke actions and they will receive responses through reg...
Definition: manager.c:2937
void ast_manager_register_hook(struct manager_custom_hook *hook)
Add a custom hook to be called when an event is fired.
Definition: manager.c:1934
static int load_module(void)
static char * handle_cli_amihook_register_hook(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
descriptor for a cli entry.
Definition: cli.h:171
#define CATEGORY
Definition: test_amihooks.c:44
Test Framework API.
static int hook_send(void)
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
Definition: cli.h:152
Definition: astman.c:222
ast_cond_t hook_cond
Definition: test_amihooks.c:47
static void unregister_hook(void)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
#define ast_cond_signal(cond)
Definition: lock.h:201
Utility functions.
pthread_cond_t ast_cond_t
Definition: lock.h:176
int done
Definition: test_amihooks.c:48
#define ast_log
Definition: astobj2.c:42
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
static int unload_module(void)
ast_cli_command
calling arguments for new-style handlers.
Definition: cli.h:151
static int amihook_helper(int category, const char *event, char *content)
Definition: test_amihooks.c:95
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
def info(msg)
#define LOG_NOTICE
Definition: logger.h:263
#define CLI_FAILURE
Definition: cli.h:46
char * command
Definition: cli.h:186
static struct manager_custom_hook test_hook
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
Definition: test.c:65
Standard Command Line Interface.
static struct ast_cli_entry cli_amihook_evt[]
static char * handle_cli_amihook_send(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Asterisk module definitions.
static void register_hook(void)
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:204
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:518
#define ast_mutex_unlock(a)
Definition: lock.h:188
static struct test_val a