Asterisk - The Open Source Telephony Project GIT-master-545c459
Loading...
Searching...
No Matches
Macros | Functions | Variables
res_websocket_client.c File Reference
#include "asterisk.h"
#include "asterisk/module.h"
#include "asterisk/astobj2.h"
#include "asterisk/strings.h"
#include "asterisk/vector.h"
#include "asterisk/websocket_client.h"
Include dependency graph for res_websocket_client.c:

Go to the source code of this file.

Macros

#define DEFAULT_RECONNECT_ATTEMPTS   -2147483648
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
void ast_websocket_client_add_uri_params (struct ast_websocket_client *wc, const char *uri_params)
 Add additional parameters to the URI.
 
struct ast_websocketast_websocket_client_connect (struct ast_websocket_client *wc, void *lock_obj, const char *display_name, enum ast_websocket_result *result)
 Connect to a websocket server using the configured authentication, retry and TLS options.
 
enum ast_ws_client_fields ast_websocket_client_get_field_diff (struct ast_websocket_client *old_wc, struct ast_websocket_client *new_wc)
 Detect changes between two websocket client configurations.
 
int ast_websocket_client_observer_add (const struct ast_sorcery_observer *callbacks)
 Add sorcery observers for websocket client events.
 
void ast_websocket_client_observer_remove (const struct ast_sorcery_observer *callbacks)
 Remove sorcery observers for websocket client events.
 
int ast_websocket_client_reload (void)
 Force res_websocket_client to reload its configuration.
 
struct ao2_containerast_websocket_client_retrieve_all (void)
 Retrieve a container of all websocket client objects.
 
struct ast_websocket_clientast_websocket_client_retrieve_by_id (const char *id)
 Retrieve a websocket client object by ID.
 
static int load_module (void)
 
static int reload_module (void)
 
static int unload_module (void)
 
static void * wc_alloc (const char *id)
 
static int wc_apply (const struct ast_sorcery *sorcery, void *obj)
 
static void wc_dtor (void *obj)
 
static int websocket_client_connection_type_from_str (const struct aco_option *opt, struct ast_variable *var, void *obj)
 
static int websocket_client_connection_type_to_str (const void *obj, const intptr_t *args, char **buf)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "WebSocket Client Support" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, .requires = "res_http_websocket", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_sorcerysorcery = NULL
 

Macro Definition Documentation

◆ DEFAULT_RECONNECT_ATTEMPTS

#define DEFAULT_RECONNECT_ATTEMPTS   -2147483648

Definition at line 628 of file res_websocket_client.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 911 of file res_websocket_client.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 911 of file res_websocket_client.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 911 of file res_websocket_client.c.

◆ ast_websocket_client_add_uri_params()

void ast_websocket_client_add_uri_params ( struct ast_websocket_client wc,
const char *  uri_params 
)

Add additional parameters to the URI.

Parameters
wcA pointer to the ast_websocket_structure
uri_paramsA string containing URLENCODED parameters to append to the URI.

Definition at line 412 of file res_websocket_client.c.

414{
415 ast_string_field_set(wc, uri_params, uri_params);
416}
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.

References ast_string_field_set.

Referenced by webchan_call().

◆ ast_websocket_client_connect()

struct ast_websocket * ast_websocket_client_connect ( struct ast_websocket_client wc,
void *  lock_obj,
const char *  display_name,
enum ast_websocket_result result 
)

Connect to a websocket server using the configured authentication, retry and TLS options.

Parameters
wcA pointer to the ast_websocket_structure
lock_objA pointer to an ao2 object to lock while the connection is being attempted or NULL if no locking is needed.
display_nameAn id string to use for logging messages. If NULL or empty the connection's ID will be used.
resultA pointer to an enum ast_websocket_result to store the result of the connection attempt.
Returns
A pointer to the ast_websocket structure on success, or NULL on failure.
Warning
The returned websocket must be closed with ast_websocket_close and its reference count decremented with ast_websocket_unref when it's no longer needed.

Definition at line 418 of file res_websocket_client.c.

420{
421 int reconnect_counter = wc->reconnect_attempts;
422 char *uri = NULL;
423
424 if (ast_strlen_zero(display_name)) {
425 display_name = ast_sorcery_object_get_id(wc);
426 }
427
428 if (!ast_strlen_zero(wc->uri_params)) {
429 /*
430 * If the configured URI doesn't already contain parameters, we append the
431 * new ones to the URI path component with '?'. If it does, we append the
432 * new ones to the existing ones with a '&'.
433 */
434 char sep = '?';
435 uri = ast_alloca(strlen(wc->uri) + strlen(wc->uri_params) + 2);
436 if (strchr(wc->uri, '?')) {
437 sep = '&';
438 }
439 sprintf(uri, "%s%c%s", wc->uri, sep, wc->uri_params); /*Safe */
440 }
441
442 while (1) {
443 struct ast_websocket *astws = NULL;
445 .uri = S_OR(uri, wc->uri),
446 .protocols = wc->protocols,
447 .username = wc->username,
448 .password = wc->password,
449 .timeout = wc->connect_timeout,
450 .write_timeout = wc->write_timeout != INT_MAX ? wc->write_timeout : AST_DEFAULT_WEBSOCKET_WRITE_TIMEOUT,
451 .suppress_connection_msgs = 1,
452 .proxy_host = wc->proxy_host,
453 .proxy_username = wc->proxy_username,
454 .proxy_password = wc->proxy_password,
456 .tcp_keepalive_time = wc->tcp_keepalive_time,
457 .tcp_keepalive_interval = wc->tcp_keepalive_interval,
458 .tcp_keepalive_probes = wc->tcp_keepalive_probes,
459 .pingpongs = wc->pingpongs,
460 .pingpong_interval = wc->pingpong_interval,
461 .pingpong_probes = wc->pingpong_probes,
462 .tls_cfg = NULL,
463 };
464
465 if (lock_obj) {
466 ao2_lock(lock_obj);
467 }
468
469 if (wc->tls_enabled) {
470 /*
471 * tls_cfg and its contents are freed automatically
472 * by res_http_websocket when the connection ends.
473 * We create it even if tls is not enabled to we can
474 * suppress connection error messages and print our own.
475 */
476 options.tls_cfg = ast_calloc(1, sizeof(*options.tls_cfg));
477 if (!options.tls_cfg) {
478 if (lock_obj) {
479 ao2_unlock(lock_obj);
480 }
481 return NULL;
482 }
483 /* TLS options */
484 options.tls_cfg->enabled = wc->tls_enabled;
485 options.tls_cfg->cafile = ast_strdup(wc->ca_list_file);
486 options.tls_cfg->capath = ast_strdup(wc->ca_list_path);
487 options.tls_cfg->certfile = ast_strdup(wc->cert_file);
488 options.tls_cfg->pvtfile = ast_strdup(wc->priv_key_file);
491 }
492
494 if (astws && *result == WS_OK) {
495 if (lock_obj) {
496 ao2_unlock(lock_obj);
497 }
498 return astws;
499 }
500
501 reconnect_counter--;
502 if (reconnect_counter <= 0) {
505 "%s: Websocket connection to %s failed after %d tries: %s%s%s%s. Retrying in %d ms.\n",
506 display_name,
507 wc->uri,
510 errno ? " (" : "",
511 errno ? strerror(errno) : "",
512 errno ? ")" : "",
513 wc->reconnect_interval
514 );
515 } else {
517 "%s: Websocket connection to %s failed after %d tries: %s%s%s%s. Hanging up after exhausting retries.\n",
518 display_name,
519 wc->uri,
522 errno ? " (" : "",
523 errno ? strerror(errno) : "",
524 errno ? ")" : ""
525 );
526 }
527 break;
528 }
529
530 if (lock_obj) {
531 ao2_unlock(lock_obj);
532 }
533 usleep(wc->reconnect_interval * 1000);
534 }
535
536 if (lock_obj) {
537 ao2_unlock(lock_obj);
538 }
539
540 return NULL;
541}
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition astmm.h:288
#define ast_strdup(str)
A wrapper for strdup()
Definition astmm.h:241
#define ast_calloc(num, len)
A wrapper for calloc()
Definition astmm.h:202
#define ast_log
Definition astobj2.c:42
#define ao2_unlock(a)
Definition astobj2.h:729
#define ao2_lock(a)
Definition astobj2.h:717
static PGresult * result
Definition cel_pgsql.c:84
@ WS_OK
struct ast_websocket *AST_OPTIONAL_API_NAME() ast_websocket_client_create_with_options(struct ast_websocket_client_options *options, enum ast_websocket_result *result)
Create, and connect, a websocket client using given options.
#define AST_DEFAULT_WEBSOCKET_WRITE_TIMEOUT
Default websocket write timeout, in ms.
@ AST_WS_TYPE_CLIENT_PERSISTENT
const char *AST_OPTIONAL_API_NAME() ast_websocket_result_to_str(enum ast_websocket_result result)
Convert a websocket result code to a string.
#define LOG_WARNING
int errno
#define NULL
Definition resample.c:96
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition sorcery.c:2381
#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
Options used for a websocket client.
unsigned int pingpong_interval
unsigned int reconnect_interval
const ast_string_field uri
enum ast_websocket_type connection_type
const ast_string_field ca_list_path
const ast_string_field cert_file
const ast_string_field password
const ast_string_field username
const ast_string_field ca_list_file
unsigned int tcp_keepalive_time
const ast_string_field protocols
unsigned int tcp_keepalive_interval
unsigned int tcp_keepalive_probes
const ast_string_field priv_key_file
unsigned int reconnect_attempts
Structure definition for session.
@ AST_SSL_DONT_VERIFY_SERVER
Definition tcptls.h:69
@ AST_SSL_IGNORE_COMMON_NAME
Definition tcptls.h:71
static struct test_options options
#define ast_set2_flag(p, value, flag)
Definition utils.h:95

References ao2_lock, ao2_unlock, ast_alloca, ast_calloc, AST_DEFAULT_WEBSOCKET_WRITE_TIMEOUT, ast_log, ast_set2_flag, ast_sorcery_object_get_id(), AST_SSL_DONT_VERIFY_SERVER, AST_SSL_IGNORE_COMMON_NAME, ast_strdup, ast_strlen_zero(), ast_websocket_client_create_with_options(), ast_websocket_result_to_str(), AST_WS_TYPE_CLIENT_PERSISTENT, ast_websocket_client::ca_list_file, ast_websocket_client::ca_list_path, ast_websocket_client::cert_file, ast_websocket_client::connect_timeout, ast_websocket_client::connection_type, errno, LOG_WARNING, NULL, options, ast_websocket_client::password, ast_websocket_client::pingpong_interval, ast_websocket_client::pingpong_probes, ast_websocket_client::pingpongs, ast_websocket_client::priv_key_file, ast_websocket_client::protocols, ast_websocket_client::reconnect_attempts, ast_websocket_client::reconnect_interval, result, S_OR, ast_websocket_client::tcp_keepalive_interval, ast_websocket_client::tcp_keepalive_probes, ast_websocket_client::tcp_keepalive_time, ast_websocket_client::tcp_keepalives, ast_websocket_client::tls_enabled, ast_websocket_client_options::uri, ast_websocket_client::uri, ast_websocket_client::username, ast_websocket_client::verify_server_cert, ast_websocket_client::verify_server_hostname, ast_websocket_client::write_timeout, and WS_OK.

Referenced by outbound_session_handler_thread(), and webchan_call().

◆ ast_websocket_client_get_field_diff()

enum ast_ws_client_fields ast_websocket_client_get_field_diff ( struct ast_websocket_client old_wc,
struct ast_websocket_client new_wc 
)

Detect changes between two websocket client configurations.

Parameters
old_owThe old websocket configuration.
new_owThe new websocket configuration.
Returns
A bitmask of changed fields.

Definition at line 708 of file res_websocket_client.c.

711{
713 const char *new_id = ast_sorcery_object_get_id(new_wc);
714 RAII_VAR(struct ast_variable *, changes, NULL, ast_variables_destroy);
715 struct ast_variable *v = NULL;
716 int res = 0;
717 int changes_found = 0;
718
719 ast_debug(2, "%s: Detecting changes\n", new_id);
720
721 res = ast_sorcery_diff(sorcery, old_wc, new_wc, &changes);
722 if (res != 0) {
723 ast_log(LOG_WARNING, "%s: Failed to create changeset\n", new_id);
725 }
726
727 for (v = changes; v; v = v->next) {
728 changes_found = 1;
729 ast_debug(2, "%s: %s changed to %s\n", new_id, v->name, v->value);
730 if (ast_strings_equal(v->name, "connection_type")) {
732 } else if (ast_strings_equal(v->name, "uri")) {
733 changed |= AST_WS_CLIENT_FIELD_URI;
734 } else if (ast_strings_equal(v->name, "protocols")) {
736 } else if (ast_strings_equal(v->name, "username")) {
738 } else if (ast_strings_equal(v->name, "password")) {
740 } else if (ast_strings_equal(v->name, "tls_enabled")) {
742 } else if (ast_strings_equal(v->name, "ca_list_file")) {
744 } else if (ast_strings_equal(v->name, "ca_list_path")) {
746 } else if (ast_strings_equal(v->name, "cert_file")) {
748 } else if (ast_strings_equal(v->name, "priv_key_file")) {
750 } else if (ast_strings_equal(v->name, "reconnect_interval")) {
752 } else if (ast_strings_equal(v->name, "reconnect_attempts")) {
754 } else if (ast_strings_equal(v->name, "connection_timeout")) {
756 } else if (ast_strings_equal(v->name, "verify_server_cert")) {
758 } else if (ast_strings_equal(v->name, "verify_server_hostname")) {
760 } else if (ast_strings_equal(v->name, "proxy_host")) {
762 } else if (ast_strings_equal(v->name, "proxy_username")) {
764 } else if (ast_strings_equal(v->name, "proxy_password")) {
766 } else if (ast_strings_equal(v->name, "enable_tcp_keepalives")) {
768 } else if (ast_strings_equal(v->name, "tcp_keepalive_time")) {
770 } else if (ast_strings_equal(v->name, "tcp_keepalive_interval")) {
772 } else if (ast_strings_equal(v->name, "tcp_keepalive_probes")) {
774 } else if (ast_strings_equal(v->name, "enable_pingpongs")) {
776 } else if (ast_strings_equal(v->name, "pingpong_interval")) {
778 } else if (ast_strings_equal(v->name, "pingpong_probes")) {
780 } else if (ast_strings_equal(v->name, "write_timeout")) {
782 } else {
783 ast_debug(2, "%s: Unknown change %s\n", new_id, v->name);
784 }
785 }
786
787 if (!changes_found) {
788 ast_debug(2, "%s: No changes found %p %p\n", new_id,
789 old_wc,new_wc);
790 }
791 return changed;
792
793}
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition extconf.c:1260
#define ast_debug(level,...)
Log a DEBUG message.
static struct ast_sorcery * sorcery
int ast_sorcery_diff(const struct ast_sorcery *sorcery, const void *original, const void *modified, struct ast_variable **changes)
Create a changeset of two objects.
Definition sorcery.c:1869
int ast_strings_equal(const char *str1, const char *str2)
Compare strings for equality checking for NULL.
Definition strings.c:238
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition utils.h:981
ast_ws_client_fields
@ AST_WS_CLIENT_FIELD_RECONNECT_INTERVAL
@ AST_WS_CLIENT_FIELD_NONE
@ AST_WS_CLIENT_FIELD_URI
@ AST_WS_CLIENT_FIELD_PROTOCOLS
@ AST_WS_CLIENT_FIELD_TCP_KEEPALIVES
@ AST_WS_CLIENT_FIELD_CA_LIST_PATH
@ AST_WS_CLIENT_FIELD_TLS_ENABLED
@ AST_WS_CLIENT_FIELD_PROXY_PASSWORD
@ AST_WS_CLIENT_FIELD_TCP_KEEPALIVE_TIME
@ AST_WS_CLIENT_FIELD_CA_LIST_FILE
@ AST_WS_CLIENT_FIELD_PINGPONG_PROBES
@ AST_WS_CLIENT_FIELD_USERNAME
@ AST_WS_CLIENT_FIELD_VERIFY_SERVER_CERT
@ AST_WS_CLIENT_FIELD_PASSWORD
@ AST_WS_CLIENT_FIELD_PROXY_USERNAME
@ AST_WS_CLIENT_FIELD_CONNECTION_TIMEOUT
@ AST_WS_CLIENT_FIELD_PINGPONG_INTERVAL
@ AST_WS_CLIENT_FIELD_RECONNECT_ATTEMPTS
@ AST_WS_CLIENT_FIELD_WRITE_TIMEOUT
@ AST_WS_CLIENT_FIELD_CONNECTION_TYPE
@ AST_WS_CLIENT_FIELD_TCP_KEEPALIVE_PROBES
@ AST_WS_CLIENT_FIELD_VERIFY_SERVER_HOSTNAME
@ AST_WS_CLIENT_FIELD_PINGPONGS
@ AST_WS_CLIENT_FIELD_TCP_KEEPALIVE_INTERVAL
@ AST_WS_CLIENT_FIELD_CERT_FILE
@ AST_WS_CLIENT_FIELD_PRIV_KEY_FILE
@ AST_WS_CLIENT_FIELD_PROXY_HOST

References ast_debug, ast_log, ast_sorcery_diff(), ast_sorcery_object_get_id(), ast_strings_equal(), ast_variables_destroy(), AST_WS_CLIENT_FIELD_CA_LIST_FILE, AST_WS_CLIENT_FIELD_CA_LIST_PATH, AST_WS_CLIENT_FIELD_CERT_FILE, AST_WS_CLIENT_FIELD_CONNECTION_TIMEOUT, AST_WS_CLIENT_FIELD_CONNECTION_TYPE, AST_WS_CLIENT_FIELD_NONE, AST_WS_CLIENT_FIELD_PASSWORD, AST_WS_CLIENT_FIELD_PINGPONG_INTERVAL, AST_WS_CLIENT_FIELD_PINGPONG_PROBES, AST_WS_CLIENT_FIELD_PINGPONGS, AST_WS_CLIENT_FIELD_PRIV_KEY_FILE, AST_WS_CLIENT_FIELD_PROTOCOLS, AST_WS_CLIENT_FIELD_PROXY_HOST, AST_WS_CLIENT_FIELD_PROXY_PASSWORD, AST_WS_CLIENT_FIELD_PROXY_USERNAME, AST_WS_CLIENT_FIELD_RECONNECT_ATTEMPTS, AST_WS_CLIENT_FIELD_RECONNECT_INTERVAL, AST_WS_CLIENT_FIELD_TCP_KEEPALIVE_INTERVAL, AST_WS_CLIENT_FIELD_TCP_KEEPALIVE_PROBES, AST_WS_CLIENT_FIELD_TCP_KEEPALIVE_TIME, AST_WS_CLIENT_FIELD_TCP_KEEPALIVES, AST_WS_CLIENT_FIELD_TLS_ENABLED, AST_WS_CLIENT_FIELD_URI, AST_WS_CLIENT_FIELD_USERNAME, AST_WS_CLIENT_FIELD_VERIFY_SERVER_CERT, AST_WS_CLIENT_FIELD_VERIFY_SERVER_HOSTNAME, AST_WS_CLIENT_FIELD_WRITE_TIMEOUT, LOG_WARNING, ast_variable::name, ast_variable::next, NULL, RAII_VAR, sorcery, and ast_variable::value.

Referenced by ari_conf_owc_detect_changes().

◆ ast_websocket_client_observer_add()

int ast_websocket_client_observer_add ( const struct ast_sorcery_observer callbacks)

Add sorcery observers for websocket client events.

Parameters
callbacksThe observer callbacks to add.
Returns
0 on success, -1 on failure.

Definition at line 795 of file res_websocket_client.c.

796{
797 if (!sorcery || !callbacks) {
798 return -1;
799 }
800
801 if (ast_sorcery_observer_add(sorcery, "websocket_client", callbacks)) {
802 ast_log(LOG_ERROR, "Failed to register websocket client observers\n");
803 return -1;
804 }
805
806 return 0;
807}
#define LOG_ERROR
struct @510 callbacks
int ast_sorcery_observer_add(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Add an observer to a specific object type.
Definition sorcery.c:2455

References ast_log, ast_sorcery_observer_add(), callbacks, LOG_ERROR, and sorcery.

Referenced by ari_conf_init().

◆ ast_websocket_client_observer_remove()

void ast_websocket_client_observer_remove ( const struct ast_sorcery_observer callbacks)

Remove sorcery observers for websocket client events.

Parameters
callbacksThe observer callbacks to remove.

Definition at line 809 of file res_websocket_client.c.

810{
811 if (!sorcery || !callbacks) {
812 return;
813 }
814
815 ast_sorcery_observer_remove(sorcery, "websocket_client", callbacks);
816}
void ast_sorcery_observer_remove(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Remove an observer from a specific object type.
Definition sorcery.c:2487

References ast_sorcery_observer_remove(), callbacks, and sorcery.

Referenced by ari_conf_destroy().

◆ ast_websocket_client_reload()

int ast_websocket_client_reload ( void  )

Force res_websocket_client to reload its configuration.

Returns
0 on success, -1 on failure.

Definition at line 884 of file res_websocket_client.c.

885{
886 ast_debug(2, "Reloading Websocket Client Configuration\n");
887 if (sorcery) {
889 }
890
891 return 0;
892}
void ast_sorcery_reload(const struct ast_sorcery *sorcery)
Inform any wizards to reload persistent objects.
Definition sorcery.c:1472

References ast_debug, ast_sorcery_reload(), and sorcery.

Referenced by ari_conf_load().

◆ ast_websocket_client_retrieve_all()

struct ao2_container * ast_websocket_client_retrieve_all ( void  )

Retrieve a container of all websocket client objects.

Returns
The container. It may be empty but must always be cleaned up by the caller.

Definition at line 689 of file res_websocket_client.c.

690{
691 if (!sorcery) {
692 return NULL;
693 }
694
695 return ast_sorcery_retrieve_by_fields(sorcery, "websocket_client",
697}
@ 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_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:1961

References AST_RETRIEVE_FLAG_ALL, AST_RETRIEVE_FLAG_MULTIPLE, ast_sorcery_retrieve_by_fields(), NULL, and sorcery.

◆ ast_websocket_client_retrieve_by_id()

struct ast_websocket_client * ast_websocket_client_retrieve_by_id ( const char *  id)

Retrieve a websocket client object by ID.

Parameters
idThe ID of the websocket client object.
Returns
The websocket client ao2 object or NULL if not found. The reference must be cleaned up by the caller.

Definition at line 699 of file res_websocket_client.c.

700{
701 if (!sorcery) {
702 return NULL;
703 }
704
705 return ast_sorcery_retrieve_by_id(sorcery, "websocket_client", id);
706}
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:1917

References ast_sorcery_retrieve_by_id(), NULL, and sorcery.

Referenced by ast_ari_channels_external_media(), outbound_websocket_websocket_client_id_from_str(), and websocket_new().

◆ load_module()

static int load_module ( void  )
static

Definition at line 819 of file res_websocket_client.c.

820{
821 ast_debug(2, "Initializing Websocket Client Configuration\n");
823 if (!sorcery) {
824 ast_log(LOG_ERROR, "Failed to open sorcery\n");
825 return -1;
826 }
827
828 ast_sorcery_apply_default(sorcery, "websocket_client", "config",
829 "websocket_client.conf,criteria=type=websocket_client");
830
831 if (ast_sorcery_object_register(sorcery, "websocket_client", wc_alloc,
832 NULL, wc_apply)) {
833 ast_log(LOG_ERROR, "Failed to register websocket_client object with sorcery\n");
835 sorcery = NULL;
836 return -1;
837 }
838
839 ast_sorcery_object_field_register(sorcery, "websocket_client", "type", "", OPT_NOOP_T, 0, 0);
840 ast_sorcery_register_cust(websocket_client, connection_type, "");
845 ast_sorcery_register_sf(websocket_client, ast_websocket_client, ca_list_file, ca_list_file, "");
846 ast_sorcery_register_sf(websocket_client, ast_websocket_client, ca_list_path, ca_list_path, "");
848 ast_sorcery_register_sf(websocket_client, ast_websocket_client, priv_key_file, priv_key_file, "");
849 ast_sorcery_register_bool(websocket_client, ast_websocket_client, tls_enabled, tls_enabled, "no");
850 ast_sorcery_register_bool(websocket_client, ast_websocket_client, verify_server_cert, verify_server_cert, "yes");
851 ast_sorcery_register_bool(websocket_client, ast_websocket_client, verify_server_hostname, verify_server_hostname, "yes");
852 ast_sorcery_register_int(websocket_client, ast_websocket_client, connection_timeout, connect_timeout, 500);
853 ast_sorcery_register_int(websocket_client, ast_websocket_client, reconnect_attempts, reconnect_attempts, 4);
854 ast_sorcery_register_int(websocket_client, ast_websocket_client, reconnect_interval, reconnect_interval, 500);
856 ast_sorcery_register_sf(websocket_client, ast_websocket_client, proxy_username, proxy_username, "");
857 ast_sorcery_register_sf(websocket_client, ast_websocket_client, proxy_password, proxy_password, "");
858 ast_sorcery_register_bool(websocket_client, ast_websocket_client, enable_tcp_keepalives, tcp_keepalives, "no");
859 ast_sorcery_register_uint(websocket_client, ast_websocket_client, tcp_keepalive_time, tcp_keepalive_time, 20);
860 ast_sorcery_register_uint(websocket_client, ast_websocket_client, tcp_keepalive_interval, tcp_keepalive_interval, 20);
861 ast_sorcery_register_uint(websocket_client, ast_websocket_client, tcp_keepalive_probes, tcp_keepalive_probes, 3);
862 ast_sorcery_register_bool(websocket_client, ast_websocket_client, enable_pingpongs, pingpongs, "no");
863 ast_sorcery_register_uint(websocket_client, ast_websocket_client, pingpong_interval, pingpong_interval, 20);
864 ast_sorcery_register_uint(websocket_client, ast_websocket_client, pingpong_probes, pingpong_probes, 3);
865 /*
866 * The default for write_timeout needs to be INT_MAX so we can tell that it's not set.
867 * This allows the modules using this capability to apply their own default value.
868 */
869 ast_sorcery_register_int(websocket_client, ast_websocket_client, write_timeout, write_timeout, INT_MAX);
870
872
873 return 0;
874}
@ OPT_NOOP_T
Type for a default handler that should do nothing.
static void * wc_alloc(const char *id)
static int wc_apply(const struct ast_sorcery *sorcery, void *obj)
#define ast_sorcery_unref(sorcery)
Decrease the reference count of a sorcery structure.
Definition sorcery.h:1500
#define ast_sorcery_register_cust(object, option, def_value)
Register a custom field within an object.
Definition sorcery.h:1767
void ast_sorcery_load(const struct ast_sorcery *sorcery)
Inform any wizards to load persistent objects.
Definition sorcery.c:1441
#define ast_sorcery_register_uint(object, structure, option, field, def_value)
Register an unsigned int field as type OPT_UINT_T within an object.
Definition sorcery.h:1728
#define ast_sorcery_object_register(sorcery, type, alloc, transform, apply)
Register an object type.
Definition sorcery.h:837
#define ast_sorcery_register_int(object, structure, option, field, def_value)
Register an int field as type OPT_INT_T within an object.
Definition sorcery.h:1710
#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_register_bool(object, structure, option, field, def_value)
Register a boolean field as type OPT_YESNO_T within an object.
Definition sorcery.h:1684
#define ast_sorcery_open()
Open a new sorcery structure.
Definition sorcery.h:406
#define ast_sorcery_register_sf(object, structure, option, field, def_value)
Register a stringfield field as type OPT_STRINGFIELD_T within an object.
Definition sorcery.h:1746

References ast_debug, ast_log, ast_sorcery_apply_default, ast_sorcery_load(), ast_sorcery_object_field_register, ast_sorcery_object_register, ast_sorcery_open, ast_sorcery_register_bool, ast_sorcery_register_cust, ast_sorcery_register_int, ast_sorcery_register_sf, ast_sorcery_register_uint, ast_sorcery_unref, LOG_ERROR, NULL, OPT_NOOP_T, sorcery, wc_alloc(), and wc_apply().

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 876 of file res_websocket_client.c.

877{
878 ast_debug(2, "Reloading Websocket Client Configuration\n");
880
881 return 0;
882}

References ast_debug, ast_sorcery_reload(), and sorcery.

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 894 of file res_websocket_client.c.

895{
896 ast_debug(2, "Unloading Websocket Client Configuration\n");
897 if (sorcery) {
899 sorcery = NULL;
900 }
901 return 0;
902}

References ast_debug, ast_sorcery_unref, NULL, and sorcery.

◆ wc_alloc()

static void * wc_alloc ( const char *  id)
static

Definition at line 554 of file res_websocket_client.c.

555{
556 struct ast_websocket_client *wc = NULL;
557
558 wc = ast_sorcery_generic_alloc(sizeof(*wc), wc_dtor);
559 if (!wc) {
560 return NULL;
561 }
562
563 if (ast_string_field_init(wc, 1024) != 0) {
564 ao2_cleanup(wc);
565 return NULL;
566 }
567
568 if (ast_string_field_init_extended(wc, uri_params) != 0) {
569 ao2_cleanup(wc);
570 return NULL;
571 }
572
573 if (ast_string_field_init_extended(wc, proxy_host) != 0) {
574 ao2_cleanup(wc);
575 return NULL;
576 }
577
578 if (ast_string_field_init_extended(wc, proxy_username) != 0) {
579 ao2_cleanup(wc);
580 return NULL;
581 }
582
583 if (ast_string_field_init_extended(wc, proxy_password) != 0) {
584 ao2_cleanup(wc);
585 return NULL;
586 }
587
588 ast_debug(2, "%s: Allocated websocket client config\n", id);
589 return wc;
590}
#define ao2_cleanup(obj)
Definition astobj2.h:1934
static void wc_dtor(void *obj)
void * ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
Allocate a generic sorcery capable object.
Definition sorcery.c:1792
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ast_string_field_init_extended(x, field)
Initialize an extended string field.

References ao2_cleanup, ast_debug, ast_sorcery_generic_alloc(), ast_string_field_init, ast_string_field_init_extended, NULL, and wc_dtor().

Referenced by load_module().

◆ wc_apply()

static int wc_apply ( const struct ast_sorcery sorcery,
void *  obj 
)
static

Definition at line 630 of file res_websocket_client.c.

631{
632 struct ast_websocket_client *wc = obj;
633 const char *id = ast_sorcery_object_get_id(wc);
634 int res = 0;
635
636 ast_debug(3, "%s: Applying config\n", id);
637
638 if (ast_strlen_zero(wc->uri)) {
639 ast_log(LOG_WARNING, "%s: Websocket client missing uri\n", id);
640 res = -1;
641 }
642
643 if (!ast_strlen_zero(wc->proxy_host)) {
644 char *host = NULL;
645 char *port = NULL;
646 char *s = ast_strdupa(wc->proxy_host);
647 if (!ast_sockaddr_split_hostport(s, &host, &port, PARSE_PORT_REQUIRE)) {
648 ast_log(LOG_WARNING, "%s: proxy_host '%s' is missing a port\n", id, wc->proxy_host);
649 res = -1;
650 }
651 }
652
653 if (wc->tcp_keepalives) {
655 ast_log(LOG_WARNING, "%s: tcp_keepalive_time, tcp_keepalive_interval and tcp_keepalive_probes must all be non-zero\n", id);
656 res = -1;
657 }
658 }
659
660 if (wc->pingpongs) {
661 if (!wc->pingpong_interval || !wc->pingpong_probes) {
662 ast_log(LOG_WARNING, "%s: pingpong_interval and pingpong_probes must be non-zero\n", id);
663 res = -1;
664 }
665 }
666
667 if (wc->write_timeout <= 0) {
668 ast_log(LOG_WARNING, "The write_timeout parameter must be > 0\n");
669 res = -1;
670 }
671
672 if (res != 0) {
673 ast_log(LOG_WARNING, "%s: Websocket client configuration failed\n", id);
674 } else {
675 ast_debug(3, "%s: Websocket client configuration succeeded\n", id);
676
679 wc->reconnect_attempts = INT_MAX;
680 } else {
681 wc->reconnect_attempts = 4;
682 }
683 }
684 }
685
686 return res;
687}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition astmm.h:298
int ast_sockaddr_split_hostport(char *str, char **host, char **port, int flags)
Splits a string into its host and port components.
Definition netsock2.c:164
#define DEFAULT_RECONNECT_ATTEMPTS

References ast_debug, ast_log, ast_sockaddr_split_hostport(), ast_sorcery_object_get_id(), ast_strdupa, ast_strlen_zero(), AST_WS_TYPE_CLIENT_PERSISTENT, ast_websocket_client::connection_type, DEFAULT_RECONNECT_ATTEMPTS, LOG_WARNING, NULL, PARSE_PORT_REQUIRE, ast_websocket_client::pingpong_interval, ast_websocket_client::pingpong_probes, ast_websocket_client::pingpongs, ast_websocket_client::reconnect_attempts, ast_websocket_client::tcp_keepalive_interval, ast_websocket_client::tcp_keepalive_probes, ast_websocket_client::tcp_keepalive_time, ast_websocket_client::tcp_keepalives, ast_websocket_client::uri, and ast_websocket_client::write_timeout.

Referenced by load_module().

◆ wc_dtor()

static void wc_dtor ( void *  obj)
static

Definition at line 545 of file res_websocket_client.c.

546{
547 struct ast_websocket_client *wc = obj;
548
549 ast_debug(3, "%s: Disposing of websocket client config\n",
552}
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object

References ast_debug, ast_sorcery_object_get_id(), and ast_string_field_free_memory.

Referenced by wc_alloc().

◆ websocket_client_connection_type_from_str()

static int websocket_client_connection_type_from_str ( const struct aco_option opt,
struct ast_variable var,
void *  obj 
)
static

Definition at line 592 of file res_websocket_client.c.

594{
595 struct ast_websocket_client *ws = obj;
596
597 if (strcasecmp(var->value, "persistent") == 0) {
599 } else if (strcasecmp(var->value, "per_call_config") == 0) {
601 } else {
602 return -1;
603 }
604
605 return 0;
606}
#define var
Definition ast_expr2f.c:605
@ AST_WS_TYPE_CLIENT_PER_CALL_CONFIG

References AST_WS_TYPE_CLIENT_PER_CALL_CONFIG, AST_WS_TYPE_CLIENT_PERSISTENT, ast_websocket_client::connection_type, and var.

◆ websocket_client_connection_type_to_str()

static int websocket_client_connection_type_to_str ( const void *  obj,
const intptr_t *  args,
char **  buf 
)
static

Definition at line 608 of file res_websocket_client.c.

609{
610 const struct ast_websocket_client *wc = obj;
611
613 *buf = ast_strdup("persistent");
615 *buf = ast_strdup("per_call_config");
616 } else {
617 return -1;
618 }
619
620 return 0;
621}
char buf[BUFSIZE]
Definition eagi_proxy.c:66

References ast_strdup, AST_WS_TYPE_CLIENT_PER_CALL_CONFIG, AST_WS_TYPE_CLIENT_PERSISTENT, buf, and ast_websocket_client::connection_type.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "WebSocket Client Support" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, .requires = "res_http_websocket", }
static

Definition at line 911 of file res_websocket_client.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 911 of file res_websocket_client.c.

◆ sorcery

struct ast_sorcery* sorcery = NULL
static