📜 ⬆️ ⬇️

Asterisk cluster. Centralization of registration information

Most of the administrators who work with Asterisk-based telephony in companies where the staff exceeds 500+ employees, sooner or later the question arises about the full Active / Active clustering. Prerequisites for this may be the presence of regional branches, and the desire to make the system more reliable. The topic is extensive and is not the goal of this article in full, which is written to show one of the fastest and most reliable ways to obtain information on the registration of devices on servers in a cluster, with a view to subsequent centralization or / and distribution within the cluster. It is logical to assume that the most productive way is to be a part of Asterisk itself.

Therefore, in order not to pull the cat by the tail, the template of the loadable module for Asterisk:

#include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision: $") #include "asterisk/module.h" #include "asterisk/logger.h" static int load_module(void){ // Init code here return AST_MODULE_LOAD_SUCCESS; } static int unload_module(void){ // Destroy code here return 0; } AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Hello World"); 

This is the minimum required code that needs to be placed in the Asterisk folder in the res subdirectory. When compiling, a new module will be assembled with the name “as a file name” and the “Hello World” description.

Great, inside Asterisk we hit, what's next? We need to get information about the registration of the phone, we want to know the phone's IP address as a bonus, maybe its jeeter and status (USE / NOT_USE / HOLD).
')
In Asterisk for this there is Stasis . Unfortunately, the only way to understand how this mechanism works is to study the source codes. So, we will make 3 simple steps:

1. We subscribe to receive events from the stasis bus

 stasis_subscribe(ast_endpoint_topic_all(),acl_change_stasis_dev_status,NULL); 

ast_endpoint_topic_all () - returns the name of the "Topic" of the message.
acl_change_stasis_dev_status - This is the function that will be called when the necessary message for us from the specified topic appears in stasis.

2. Create a function in which we will catch the necessary messages.
 static void acl_change_stasis_dev_status(void *data, struct stasis_subscription *sub, struct stasis_message *msg){ } 

3. Actually the most delicious - event handling code.
Before you draw your own, you need to understand, and in what form will it come to us? To do this, we climb into the sorts and find this piece:

 ast_endpoint_blob_publish(peer->endpoint, ast_endpoint_state_type(), blob); 

and further:

 void ast_endpoint_blob_publish(struct ast_endpoint *endpoint, struct stasis_message_type *type, struct ast_json *blob) { RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup); if (blob) { message = ast_endpoint_blob_create(endpoint, type, blob); } if (message) { stasis_publish(ast_endpoint_topic(endpoint), message); } } struct stasis_message *ast_endpoint_blob_create(struct ast_endpoint *endpoint, struct stasis_message_type *type, struct ast_json *blob) { RAII_VAR(struct ast_endpoint_blob *, obj, NULL, ao2_cleanup); RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup); if (!type) { return NULL; } if (!blob) { blob = ast_json_null(); } if (!(obj = ao2_alloc(sizeof(*obj), endpoint_blob_dtor))) { return NULL; } if (endpoint) { if (!(obj->snapshot = ast_endpoint_snapshot_create(endpoint))) { return NULL; } } obj->blob = ast_json_ref(blob); if (!(msg = stasis_message_create(type, obj))) { return NULL; } ao2_ref(msg, +1); return msg; } 

What does this piece of code give us? Understanding that as a payload to our function we get ast_endpoint_blob, inside of which will be ast_endpoint_snapshot and JSON.

Now our code is:

  if(ast_endpoint_state_type() != stasis_message_type(msg))return; // ,     ? //       Asterisk      struct ast_endpoint_blob * n=stasis_message_data(msg); //          ast_endpoint_blob //      JSON struct ast_json * m; struct ast_endpoint_snapshot *snap; //        c JSON   ast_endpoint_snapshot snap=n->snapshot; //     m=n->blob; //  JSON char buffer[1050]; sprintf(buffer,"Device %s (%s): %s\n",snap->id,ast_endpoint_state_to_string(snap->state),ast_json_dump_string_format(m,AST_JSON_COMPACT)); ast_log(LOG_NOTICE,buffer); //     

The structures described above will pull the following insets:

  #include "asterisk/stasis_endpoints.h" #include "asterisk/stasis.h" #include "asterisk/stasis_message_router.h" #include "asterisk/stasis_channels.h" #include "asterisk/stasis_bridges.h" #include "asterisk/stasis_system.h" #include "asterisk/devicestate.h" #include "asterisk/json.h" 

About them, too, need not forget when creating a module.

Total:

 #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision: $") #include "asterisk/module.h" #include "asterisk/logger.h" #include "asterisk/stasis_endpoints.h" #include "asterisk/stasis.h" #include "asterisk/stasis_message_router.h" #include "asterisk/stasis_channels.h" #include "asterisk/stasis_bridges.h" #include "asterisk/stasis_system.h" #include "asterisk/devicestate.h" #include "asterisk/json.h" static void acl_change_stasis_dev_status(void *data, struct stasis_subscription *sub, struct stasis_message *msg){ if(ast_endpoint_state_type() != stasis_message_type(msg))return; struct ast_endpoint_blob * n=stasis_message_data(msg); struct ast_json * m; struct ast_endpoint_snapshot *snap; snap=n->snapshot; m=n->blob; char buffer[1050]; sprintf(buffer,"Device %s (%s): %s\n",snap->id,ast_endpoint_state_to_string(snap->state),ast_json_dump_string_format(m,AST_JSON_COMPACT)); ast_log(LOG_NOTICE,buffer); } static int load_module(void){ stasis_subscribe(ast_endpoint_topic_all(),acl_change_stasis_dev_status,NULL); return AST_MODULE_LOAD_SUCCESS; } static int unload_module(void){ //      return 0; } 

What is it for? The resulting information can be put into a single cluster database, which will always know on which particular server the device is registered. Smarshutizirovat call, based on this information is already possible by means of dialplan.

And, actually, what it looks like:

image

Source: https://habr.com/ru/post/312630/


All Articles