Asterisk - The Open Source Telephony Project GIT-master-a358458
res_aeap.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2021, Sangoma Technologies Corporation
5 *
6 * Ben Ford <bford@sangoma.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/*** MODULEINFO
20 <depend>res_http_websocket</depend>
21 <support_level>core</support_level>
22 ***/
23
24#include "asterisk.h"
25
26#include "asterisk/astobj2.h"
27#include "asterisk/module.h"
28#include "asterisk/sorcery.h"
29#include "asterisk/cli.h"
30#include "asterisk/format.h"
31#include "asterisk/format_cap.h"
32#include "asterisk/res_aeap.h"
33
34#include "res_aeap/general.h"
35
36/*** DOCUMENTATION
37 <configInfo name="res_aeap" language="en_US">
38 <synopsis>Asterisk External Application Protocol (AEAP) module for Asterisk</synopsis>
39 <configFile name="aeap.conf">
40 <configObject name="client">
41 <synopsis>AEAP client options</synopsis>
42 <configOption name="type">
43 <synopsis>Must be of type 'client'.</synopsis>
44 </configOption>
45 <configOption name="url">
46 <synopsis>The URL of the server to connect to.</synopsis>
47 </configOption>
48 <configOption name="protocol">
49 <synopsis>The application protocol.</synopsis>
50 </configOption>
51 <configOption name="codecs">
52 <synopsis>Optional media codec(s)</synopsis>
53 <description><para>
54 If this is specified, Asterisk will use this for codec related negotiations
55 with the external application. Otherwise, Asterisk will default to using the
56 codecs configured on the endpoint.
57 </para></description>
58 </configOption>
59 </configObject>
60 </configFile>
61 </configInfo>
62 ***/
63
64/* Asterisk External Application Protocol sorcery object */
66
68 return aeap_sorcery;
69}
70
72{
75 /*! The URL of the server to connect to */
77 /*! The application protocol */
79 );
80 /*! An optional list of codecs that will be used if provided */
82};
83
84static void client_config_destructor(void *obj)
85{
86 struct ast_aeap_client_config *cfg = obj;
87
89 ao2_cleanup(cfg->codecs);
90}
91
92static void *client_config_alloc(const char *name)
93{
94 struct ast_aeap_client_config *cfg;
95
97 if (!cfg) {
98 return NULL;
99 }
100
101 if (ast_string_field_init(cfg, 512)) {
102 ao2_ref(cfg, -1);
103 return NULL;
104 }
105
107 ao2_ref(cfg, -1);
108 return NULL;
109 }
110
111 return cfg;
112}
113
114static int client_config_apply(const struct ast_sorcery *sorcery, void *obj)
115{
116 struct ast_aeap_client_config *cfg = obj;
117
118 if (ast_strlen_zero(cfg->url)) {
119 ast_log(LOG_ERROR, "AEAP - URL must be present for '%s'\n", ast_sorcery_object_get_id(cfg));
120 return -1;
121 }
122
123 if (!ast_begins_with(cfg->url, "ws")) {
124 ast_log(LOG_ERROR, "AEAP - URL must be ws or wss for '%s'\n", ast_sorcery_object_get_id(cfg));
125 return -1;
126 }
127
128 return 0;
129}
130
132{
133 return cfg->codecs;
134}
135
137 const char *protocol)
138{
139 return !strcmp(protocol, cfg->protocol);
140}
141
142struct ao2_container *ast_aeap_client_configs_get(const char *protocol)
143{
144 struct ao2_container *container;
145 struct ast_variable *var;
146
147 var = protocol ? ast_variable_new("protocol ==", protocol, "") : NULL;
148
151
153
154 return container;
155}
156
157static struct ast_aeap_client_config *client_config_get(const char *id)
158{
160}
161
162static char *aeap_tab_complete_name(const char *word, struct ao2_container *container)
163{
164 void *obj;
165 struct ao2_iterator it;
166 int wordlen = strlen(word);
167 int ret;
168
170 while ((obj = ao2_iterator_next(&it))) {
171 if (!strncasecmp(word, ast_sorcery_object_get_id(obj), wordlen)) {
173 if (ret) {
174 ao2_ref(obj, -1);
175 break;
176 }
177 }
178 ao2_ref(obj, -1);
179 }
181
182 ao2_ref(container, -1);
183
184 return NULL;
185}
186
187static int aeap_cli_show(void *obj, void *arg, int flags)
188{
189 struct ast_cli_args *a = arg;
190 struct ast_variable *options;
191 struct ast_variable *i;
192
193 if (!obj) {
194 ast_cli(a->fd, "No AEAP configuration found\n");
195 return 0;
196 }
197
199 if (!options) {
200 return 0;
201 }
202
203 ast_cli(a->fd, "%s: %s\n", ast_sorcery_object_get_type(obj),
205
206 for (i = options; i; i = i->next) {
207 ast_cli(a->fd, "\t%s: %s\n", i->name, i->value);
208 }
209
210 ast_cli(a->fd, "\n");
211
213
214 return 0;
215}
216
217static char *client_config_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
218{
219 struct ast_aeap_client_config *cfg;
220
221 switch(cmd) {
222 case CLI_INIT:
223 e->command = "aeap show client";
224 e->usage =
225 "Usage: aeap show client <id>\n"
226 " Show the AEAP settings for a given client\n";
227 return NULL;
228 case CLI_GENERATE:
229 if (a->pos == 3) {
231 } else {
232 return NULL;
233 }
234 }
235
236 if (a->argc != 4) {
237 return CLI_SHOWUSAGE;
238 }
239
240 cfg = client_config_get(a->argv[3]);
241 aeap_cli_show(cfg, a, 0);
242 ao2_cleanup(cfg);
243
244 return CLI_SUCCESS;
245}
246
247static char *client_config_show_all(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
248{
249 struct ao2_container *container;
250
251 switch(cmd) {
252 case CLI_INIT:
253 e->command = "aeap show clients";
254 e->usage =
255 "Usage: aeap show clients\n"
256 " Show all configured AEAP clients\n";
257 return NULL;
258 case CLI_GENERATE:
259 return NULL;
260 }
261
262 if (a->argc != 3) {
263 return CLI_SHOWUSAGE;
264 }
265
268 ast_cli(a->fd, "No AEAP clients found\n");
270 return CLI_SUCCESS;
271 }
272
274 ao2_ref(container, -1);
275
276 return CLI_SUCCESS;
277}
278
279static struct ast_cli_entry aeap_cli[] = {
280 AST_CLI_DEFINE(client_config_show, "Show AEAP client configuration by id"),
281 AST_CLI_DEFINE(client_config_show_all, "Show all AEAP client configurations"),
282};
283
284static struct ast_aeap *aeap_create(const char *id, const struct ast_aeap_params *params,
285 int connect, int timeout)
286{
287 struct ast_aeap_client_config *cfg;
288 struct ast_aeap *aeap;
289 const char *url = NULL;
290 const char *protocol = NULL;
291
292 cfg = client_config_get(id);
293 if (cfg) {
294 url = cfg->url;
295 protocol = cfg->protocol;
296 }
297
298#ifdef TEST_FRAMEWORK
299 else if (ast_begins_with(id, "_aeap_test_")) {
300 url = "ws://127.0.0.1:8088/ws";
301 protocol = id;
302 }
303#endif
304
305 if (!url && !protocol) {
306 ast_log(LOG_ERROR, "AEAP: unable to get configuration for '%s'\n", id);
307 return NULL;
308 }
309
310 aeap = connect ? ast_aeap_create_and_connect(url, params, url, protocol, timeout) :
312
313 ao2_cleanup(cfg);
314 return aeap;
315}
316
317struct ast_aeap *ast_aeap_create_by_id(const char *id, const struct ast_aeap_params *params)
318{
319 return aeap_create(id, params, 0, 0);
320}
321
323 const struct ast_aeap_params *params, int timeout)
324{
325 return aeap_create(id, params, 1, timeout);
326}
327
329{
330 struct ast_aeap_client_config *cfg;
331 struct ast_variable *vars;
332
333 cfg = client_config_get(id);
334 if (!cfg) {
335 ast_log(LOG_WARNING, "AEAP: no client configuration '%s' to get fields\n", id);
336 return NULL;
337 }
338
340
341 ao2_ref(cfg, -1);
342 return vars;
343}
344
345static int reload_module(void)
346{
348
349 return 0;
350}
351
352static int unload_module(void)
353{
356
358
360
361 return 0;
362}
363
364static int load_module(void)
365{
368 }
369
371 {
372 ast_log(LOG_ERROR, "AEAP - failed to open sorcery\n");
374 }
375
376 ast_sorcery_apply_default(aeap_sorcery, AEAP_CONFIG_CLIENT, "config", "aeap.conf,criteria=type=client");
377
380 ast_log(LOG_ERROR, "AEAP - failed to register client sorcery object\n");
382 }
383
388
390
392
393 return 0;
394}
395
397 "Asterisk External Application Protocol Module for Asterisk",
398 .support_level = AST_MODULE_SUPPORT_CORE,
399 .load = load_module,
400 .unload = unload_module,
402 .load_pri = AST_MODPRI_CHANNEL_DEPEND,
403 .requires = "res_http_websocket",
enum queue_result id
Definition: app_queue.c:1638
#define var
Definition: ast_expr2f.c:605
Asterisk main include file. File version handling, generic pbx functions.
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_log
Definition: astobj2.c:42
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
@ OBJ_NODATA
Definition: astobj2.h:1044
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
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
Definition: main/cli.c:2756
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ 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 struct ao2_container * codecs
Registered codecs.
Definition: codec.c:48
short word
#define STRFLDSET(type,...)
Convert a struct and a list of stringfield fields to an argument list of field offsets.
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
@ OPT_NOOP_T
Type for a default handler that should do nothing.
@ OPT_CODEC_T
Type for default option handler for format capabilities.
@ OPT_STRINGFIELD_T
Type for default option handler for stringfields.
Media Format API.
Format Capabilities API.
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
static const char name[]
Definition: format_mp3.c:68
int aeap_general_initialize(void)
Initialize general/common AEAP facilities.
Definition: general.c:42
void aeap_general_finalize(void)
Finalize/cleanup general AEAP facilities.
Definition: general.c:34
struct ast_variable * ast_variable_list_sort(struct ast_variable *head)
Performs an in-place sort on the variable list by ascending name.
Definition: main/config.c:620
#define ast_variable_new(name, value, filename)
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
#define LOG_ERROR
#define LOG_WARNING
Asterisk module definitions.
@ AST_MODFLAG_LOAD_ORDER
Definition: module.h:317
@ AST_MODFLAG_GLOBAL_SYMBOLS
Definition: module.h:316
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:543
@ AST_MODPRI_CHANNEL_DEPEND
Definition: module.h:326
@ AST_MODULE_SUPPORT_CORE
Definition: module.h:121
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static char * aeap_tab_complete_name(const char *word, struct ao2_container *container)
Definition: res_aeap.c:162
struct ast_aeap * ast_aeap_create_and_connect_by_id(const char *id, const struct ast_aeap_params *params, int timeout)
Create and connect to an Asterisk external application by sorcery id.
Definition: res_aeap.c:322
static void * client_config_alloc(const char *name)
Definition: res_aeap.c:92
static char * client_config_show_all(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: res_aeap.c:247
int ast_aeap_client_config_has_protocol(const struct ast_aeap_client_config *cfg, const char *protocol)
Check a given protocol against that in an Asterisk external application configuration.
Definition: res_aeap.c:136
static struct ast_cli_entry aeap_cli[]
Definition: res_aeap.c:279
static int reload_module(void)
Definition: res_aeap.c:345
static void client_config_destructor(void *obj)
Definition: res_aeap.c:84
struct ast_variable * ast_aeap_custom_fields_get(const char *id)
Retrieve a list of custom configuration fields.
Definition: res_aeap.c:328
static char * client_config_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: res_aeap.c:217
struct ast_sorcery * ast_aeap_sorcery(void)
Retrieve the AEAP sorcery object.
Definition: res_aeap.c:67
struct ast_aeap * ast_aeap_create_by_id(const char *id, const struct ast_aeap_params *params)
Create an Asterisk external application object by sorcery id.
Definition: res_aeap.c:317
static int aeap_cli_show(void *obj, void *arg, int flags)
Definition: res_aeap.c:187
struct ao2_container * ast_aeap_client_configs_get(const char *protocol)
Retrieve a listing of all client configuration objects by protocol.
Definition: res_aeap.c:142
static struct ast_aeap * aeap_create(const char *id, const struct ast_aeap_params *params, int connect, int timeout)
Definition: res_aeap.c:284
static struct ast_sorcery * aeap_sorcery
Definition: res_aeap.c:65
static int load_module(void)
Definition: res_aeap.c:364
static struct ast_aeap_client_config * client_config_get(const char *id)
Definition: res_aeap.c:157
static int client_config_apply(const struct ast_sorcery *sorcery, void *obj)
Definition: res_aeap.c:114
static int unload_module(void)
Definition: res_aeap.c:352
const struct ast_format_cap * ast_aeap_client_config_codecs(const struct ast_aeap_client_config *cfg)
Retrieve codec capabilities from the configuration.
Definition: res_aeap.c:131
Asterisk External Application Protocol API.
struct ast_aeap * ast_aeap_create(const char *type, const struct ast_aeap_params *params)
Create an Asterisk external application object.
Definition: aeap.c:88
#define AEAP_CONFIG_CLIENT
Definition: res_aeap.h:35
struct ast_aeap * ast_aeap_create_and_connect(const char *type, const struct ast_aeap_params *params, const char *url, const char *protocol, int timeout)
Create and connect to an Asterisk external application.
Definition: aeap.c:363
static char url[512]
static int reload(void)
struct ao2_container * container
Definition: res_fax.c:501
static struct ast_sorcery * sorcery
#define NULL
Definition: resample.c:96
Sorcery Data Access Layer API.
#define ast_sorcery_unref(sorcery)
Decrease the reference count of a sorcery structure.
Definition: sorcery.h:1500
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
#define ast_sorcery_objectset_create(sorcery, object)
Create an object set (KVP list) for an object.
Definition: sorcery.h:1137
@ AST_RETRIEVE_FLAG_MULTIPLE
Return all matching objects.
Definition: sorcery.h:120
@ AST_RETRIEVE_FLAG_ALL
Perform no matching, return all objects.
Definition: sorcery.h:123
void ast_sorcery_load(const struct ast_sorcery *sorcery)
Inform any wizards to load persistent objects.
Definition: sorcery.c:1377
const char * ast_sorcery_object_get_type(const void *object)
Get the type of a sorcery object.
Definition: sorcery.c:2324
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Definition: sorcery.c:1853
#define ast_sorcery_object_register(sorcery, type, alloc, transform, apply)
Register an object type.
Definition: sorcery.h:837
void ast_sorcery_reload(const struct ast_sorcery *sorcery)
Inform any wizards to reload persistent objects.
Definition: sorcery.c:1408
void * ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
Allocate a generic sorcery capable object.
Definition: sorcery.c:1728
#define ast_sorcery_object_field_register(sorcery, type, name, default_val, opt_type, flags,...)
Register a field within an object.
Definition: sorcery.h:955
#define ast_sorcery_apply_default(sorcery, type, name, data)
Definition: sorcery.h:476
#define ast_sorcery_open()
Open a new sorcery structure.
Definition: sorcery.h:406
void * ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
Retrieve an object or multiple objects using specific fields.
Definition: sorcery.c:1897
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
Definition: stringfields.h:341
#define AST_STRING_FIELD(name)
Declare a string field.
Definition: stringfields.h:303
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Checks whether a string begins with another.
Definition: strings.h:97
Generic container type.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
const ast_string_field url
Definition: res_aeap.c:79
struct ast_format_cap * codecs
Definition: res_aeap.c:81
const ast_string_field protocol
Definition: res_aeap.c:79
Callbacks and other parameters used by an Asterisk external application object.
Definition: res_aeap.h:144
Definition: aeap.c:47
const struct ast_aeap_params * params
Definition: aeap.c:49
descriptor for a cli entry.
Definition: cli.h:171
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
Full structure for sorcery.
Definition: sorcery.c:230
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
static struct test_options options
static struct test_val a
#define ARRAY_LEN(a)
Definition: utils.h:666