Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Functions | Variables
res_pjsip_exten_state.c File Reference
#include "asterisk.h"
#include <regex.h>
#include <pjsip.h>
#include <pjsip_simple.h>
#include <pjlib.h>
#include "asterisk/res_pjsip.h"
#include "asterisk/res_pjsip_outbound_publish.h"
#include "asterisk/res_pjsip_pubsub.h"
#include "asterisk/res_pjsip_body_generator_types.h"
#include "asterisk/module.h"
#include "asterisk/logger.h"
#include "asterisk/astobj2.h"
#include "asterisk/sorcery.h"
#include "asterisk/app.h"
#include "asterisk/taskprocessor.h"
Include dependency graph for res_pjsip_exten_state.c:

Go to the source code of this file.

Data Structures

struct  exten_state_pub_data
 
struct  exten_state_publisher
 An extension state publisher. More...
 
struct  exten_state_subscription
 A subscription for extension state. More...
 
struct  notify_task_data
 

Macros

#define BODY_SIZE   1024
 
#define DEFAULT_DIALOG_BODY   "application/dialog-info+xml"
 
#define DEFAULT_PRESENCE_BODY   "application/pidf+xml"
 
#define EVENT_TYPE_SIZE   50
 
#define INITIAL_LAST_EXTEN_STATE   -3
 
#define PUBLISHER_BUCKETS   31
 The number of buckets to use for storing publishers. More...
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static int add_datastore (struct exten_state_subscription *exten_state_sub)
 
static struct notify_task_dataalloc_notify_task_data (const char *exten, struct exten_state_subscription *exten_state_sub, struct ast_state_cb_info *info)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int build_regex (regex_t *regex, const char *text)
 
static struct ast_sip_exten_state_dataexten_state_data_alloc (struct ast_sip_subscription *sip_sub, struct exten_state_subscription *exten_state_sub)
 
static void exten_state_data_destructor (void *obj)
 
static struct exten_state_pub_dataexten_state_pub_data_alloc (const char *exten, struct ast_state_cb_info *info)
 
static void exten_state_pub_data_destroy (struct exten_state_pub_data *doomed)
 
static int exten_state_publisher_cb (void *data)
 
static int exten_state_publisher_cmp (void *obj, void *arg, int flags)
 Comparator function for extension state publisher. More...
 
static void exten_state_publisher_destroy (void *obj)
 Destructor for extension state publisher. More...
 
static int exten_state_publisher_hash (const void *obj, const int flags)
 Hashing function for extension state publisher. More...
 
static int exten_state_publisher_state_cb (const char *context, const char *exten, struct ast_state_cb_info *info, void *data)
 Global extension state callback function. More...
 
static struct exten_state_subscriptionexten_state_subscription_alloc (struct ast_sip_subscription *sip_sub, struct ast_sip_endpoint *endpoint)
 
static void exten_state_subscription_destructor (void *obj)
 
static struct exten_state_subscriptionget_exten_state_sub (struct ast_sip_subscription *sub)
 
static void * get_notify_data (struct ast_sip_subscription *sub)
 
static char * get_user_agent (const struct ast_sip_subscription *sip_sub)
 
static int load_module (void)
 
static int new_subscribe (struct ast_sip_endpoint *endpoint, const char *resource)
 
static int notify_task (void *obj)
 
static void notify_task_data_destructor (void *obj)
 
static int publisher_start (struct ast_sip_outbound_publish *configuration, struct ast_sip_outbound_publish_client *client)
 
static int publisher_stop (struct ast_sip_outbound_publish_client *client)
 
static int state_changed (const char *context, const char *exten, struct ast_state_cb_info *info, void *data)
 
static void state_changed_destroy (int id, void *data)
 
static int subscription_established (struct ast_sip_subscription *sub)
 
static void subscription_shutdown (struct ast_sip_subscription *sub)
 
static void to_ami (struct ast_sip_subscription *sub, struct ast_str **buf)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP Extension State Notifications" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND + 5, .requires = "res_pjsip,res_pjsip_pubsub,res_pjsip_outbound_publish", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
struct ast_sip_subscription_handler dialog_handler
 
struct ast_sip_notifier dialog_notifier
 
struct ast_sip_event_publisher_handler dialog_publisher
 
static struct ast_datastore_info ds_info = { }
 
static const char ds_name [] = "exten state datastore"
 
struct ast_sip_subscription_handler presence_handler
 
struct ast_sip_notifier presence_notifier
 
struct ast_sip_event_publisher_handler presence_publisher
 
static struct ast_taskprocessorpublish_exten_state_serializer
 
static struct ao2_containerpublishers
 Container of active outbound extension state publishers. More...
 

Macro Definition Documentation

◆ BODY_SIZE

#define BODY_SIZE   1024

Definition at line 46 of file res_pjsip_exten_state.c.

◆ DEFAULT_DIALOG_BODY

#define DEFAULT_DIALOG_BODY   "application/dialog-info+xml"

Definition at line 114 of file res_pjsip_exten_state.c.

◆ DEFAULT_PRESENCE_BODY

#define DEFAULT_PRESENCE_BODY   "application/pidf+xml"

Definition at line 113 of file res_pjsip_exten_state.c.

◆ EVENT_TYPE_SIZE

#define EVENT_TYPE_SIZE   50

Definition at line 47 of file res_pjsip_exten_state.c.

◆ INITIAL_LAST_EXTEN_STATE

#define INITIAL_LAST_EXTEN_STATE   -3

Definition at line 201 of file res_pjsip_exten_state.c.

Referenced by exten_state_subscription_alloc().

◆ PUBLISHER_BUCKETS

#define PUBLISHER_BUCKETS   31

The number of buckets to use for storing publishers.

Definition at line 52 of file res_pjsip_exten_state.c.

Referenced by load_module().

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1012 of file res_pjsip_exten_state.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1012 of file res_pjsip_exten_state.c.

◆ add_datastore()

static int add_datastore ( struct exten_state_subscription exten_state_sub)
static

Definition at line 369 of file res_pjsip_exten_state.c.

References ao2_cleanup, ao2_ref, ast_sip_subscription_add_datastore(), ast_sip_subscription_alloc_datastore(), ds_name, RAII_VAR, and exten_state_subscription::sip_sub.

Referenced by subscription_established().

370 {
371  RAII_VAR(struct ast_datastore *, datastore,
373 
374  if (!datastore) {
375  return -1;
376  }
377 
378  datastore->data = exten_state_sub;
379  ast_sip_subscription_add_datastore(exten_state_sub->sip_sub, datastore);
380  ao2_ref(exten_state_sub, +1);
381  return 0;
382 }
Structure for a data store object.
Definition: datastore.h:68
#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:911
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_datastore * ast_sip_subscription_alloc_datastore(const struct ast_datastore_info *info, const char *uid)
Alternative for ast_datastore_alloc()
static const char ds_name[]
int ast_sip_subscription_add_datastore(struct ast_sip_subscription *subscription, struct ast_datastore *datastore)
Add a datastore to a SIP subscription.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct ast_datastore_info ds_info
struct ast_sip_subscription * sip_sub

◆ alloc_notify_task_data()

static struct notify_task_data* alloc_notify_task_data ( const char *  exten,
struct exten_state_subscription exten_state_sub,
struct ast_state_cb_info info 
)
static

Definition at line 251 of file res_pjsip_exten_state.c.

References ao2_alloc, ao2_bump, ao2_ref, AST_EXTENSION_DEACTIVATED, AST_EXTENSION_REMOVED, ast_log, ast_sip_subscription_get_datastores(), ast_strdup, ast_verb, ast_sip_exten_state_data::datastores, ast_sip_exten_state_data::device_state_info, ast_state_cb_info::device_state_info, ast_sip_exten_state_data::exten, exten_state_subscription::exten, ast_sip_exten_state_data::exten_state, ast_state_cb_info::exten_state, notify_task_data::exten_state_data, notify_task_data::exten_state_sub, exten_state_subscription::last_exten_state, exten_state_subscription::last_presence_state, LOG_WARNING, notify_task_data_destructor(), NULL, ast_sip_exten_state_data::presence_message, ast_state_cb_info::presence_message, ast_sip_exten_state_data::presence_state, ast_state_cb_info::presence_state, ast_sip_exten_state_data::presence_subtype, ast_state_cb_info::presence_subtype, exten_state_subscription::sip_sub, ast_sip_exten_state_data::sub, notify_task_data::terminate, ast_sip_exten_state_data::user_agent, and exten_state_subscription::user_agent.

Referenced by state_changed().

254 {
255  struct notify_task_data *task_data =
256  ao2_alloc(sizeof(*task_data), notify_task_data_destructor);
257 
258  if (!task_data) {
259  ast_log(LOG_WARNING, "Unable to create notify task data\n");
260  return NULL;
261  }
262 
263  task_data->exten_state_sub = exten_state_sub;
264  task_data->exten_state_sub->last_exten_state = info->exten_state;
266  ao2_ref(task_data->exten_state_sub, +1);
267 
268  task_data->exten_state_data.exten = exten_state_sub->exten;
269  task_data->exten_state_data.exten_state = info->exten_state;
273  task_data->exten_state_data.user_agent = ast_strdup(exten_state_sub->user_agent);
275  task_data->exten_state_data.sub = exten_state_sub->sip_sub;
277 
278  if ((info->exten_state == AST_EXTENSION_DEACTIVATED) ||
279  (info->exten_state == AST_EXTENSION_REMOVED)) {
280  ast_verb(2, "Watcher for hint %s %s\n", exten, info->exten_state
281  == AST_EXTENSION_REMOVED ? "removed" : "deactivated");
282  task_data->terminate = 1;
283  }
284 
285  return task_data;
286 }
char exten[AST_MAX_EXTENSION]
enum ast_extension_states last_exten_state
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
struct ast_sip_exten_state_data exten_state_data
const char * presence_message
Definition: pbx.h:108
enum ast_presence_state last_presence_state
#define LOG_WARNING
Definition: logger.h:274
static void notify_task_data_destructor(void *obj)
enum ast_extension_states exten_state
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
struct ast_sip_subscription * sub
#define ast_verb(level,...)
Definition: logger.h:463
struct ao2_container * ast_sip_subscription_get_datastores(const struct ast_sip_subscription *subscription)
Get the datastores container for a subscription.
#define ao2_bump(obj)
Definition: astobj2.h:491
enum ast_extension_states exten_state
Definition: pbx.h:104
#define ast_log
Definition: astobj2.c:42
enum ast_presence_state presence_state
Definition: pbx.h:106
enum ast_presence_state presence_state
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char * presence_subtype
Definition: pbx.h:107
struct ao2_container * device_state_info
Definition: pbx.h:105
struct ao2_container * device_state_info
userdata associated with baseline taskprocessor test
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
struct ast_sip_subscription * sip_sub
struct exten_state_subscription * exten_state_sub

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 1012 of file res_pjsip_exten_state.c.

◆ build_regex()

static int build_regex ( regex_t *  regex,
const char *  text 
)
static

Definition at line 822 of file res_pjsip_exten_state.c.

References ast_log, buf, len(), LOG_ERROR, and NULL.

Referenced by publisher_start().

823 {
824  int res;
825 
826  if ((res = regcomp(regex, text, REG_EXTENDED | REG_ICASE | REG_NOSUB))) {
827  size_t len = regerror(res, regex, NULL, 0);
828  char buf[len];
829  regerror(res, regex, buf, len);
830  ast_log(LOG_ERROR, "Could not compile regex '%s': %s\n", text, buf);
831  return -1;
832  }
833 
834  return 0;
835 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
char * text
Definition: app_queue.c:1508
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static int regex(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
Definition: func_strings.c:948

◆ exten_state_data_alloc()

static struct ast_sip_exten_state_data* exten_state_data_alloc ( struct ast_sip_subscription sip_sub,
struct exten_state_subscription exten_state_sub 
)
static

Definition at line 482 of file res_pjsip_exten_state.c.

References ao2_alloc, ao2_cleanup, ast_extension_state_extended(), ast_hint_presence_state(), AST_PRESENCE_INVALID, ast_sip_get_pjsip_endpoint(), ast_sip_subscription_get_datastores(), ast_sip_subscription_get_local_uri(), ast_sip_subscription_get_remote_uri(), exten_state_subscription::context, ast_sip_exten_state_data::datastores, ast_sip_exten_state_data::device_state_info, ast_sip_exten_state_data::exten, exten_state_subscription::exten, ast_sip_exten_state_data::exten_state, exten_state_data_destructor(), ast_sip_exten_state_data::local, NULL, ast_sip_exten_state_data::pool, ast_sip_exten_state_data::presence_message, ast_sip_exten_state_data::presence_state, ast_sip_exten_state_data::presence_subtype, ast_sip_exten_state_data::remote, exten_state_subscription::sip_sub, ast_sip_exten_state_data::sub, ast_sip_exten_state_data::user_agent, and exten_state_subscription::user_agent.

Referenced by get_notify_data().

484 {
485  struct ast_sip_exten_state_data *exten_state_data;
486  char *subtype = NULL;
487  char *message = NULL;
488  int presence_state;
489 
490  exten_state_data = ao2_alloc(sizeof(*exten_state_data), exten_state_data_destructor);
491  if (!exten_state_data) {
492  return NULL;
493  }
494 
495  exten_state_data->exten = exten_state_sub->exten;
496  presence_state = ast_hint_presence_state(NULL, exten_state_sub->context, exten_state_sub->exten, &subtype, &message);
497  if (presence_state == -1 || presence_state == AST_PRESENCE_INVALID) {
498  ao2_cleanup(exten_state_data);
499  return NULL;
500  }
501  exten_state_data->presence_state = presence_state;
502  exten_state_data->presence_subtype = subtype;
503  exten_state_data->presence_message = message;
504  exten_state_data->user_agent = exten_state_sub->user_agent;
505  ast_sip_subscription_get_local_uri(sip_sub, exten_state_data->local,
506  sizeof(exten_state_data->local));
507  ast_sip_subscription_get_remote_uri(sip_sub, exten_state_data->remote,
508  sizeof(exten_state_data->remote));
509  exten_state_data->sub = sip_sub;
510  exten_state_data->datastores = ast_sip_subscription_get_datastores(sip_sub);
511 
512  exten_state_data->exten_state = ast_extension_state_extended(
513  NULL, exten_state_sub->context, exten_state_sub->exten,
514  &exten_state_data->device_state_info);
515  if (exten_state_data->exten_state < 0) {
516  ao2_cleanup(exten_state_data);
517  return NULL;
518  }
519 
520  exten_state_data->pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(),
521  "exten_state", 1024, 1024);
522  if (!exten_state_data->pool) {
523  ao2_cleanup(exten_state_data);
524  return NULL;
525  }
526 
527  return exten_state_data;
528 }
char exten[AST_MAX_EXTENSION]
void ast_sip_subscription_get_local_uri(struct ast_sip_subscription *sub, char *buf, size_t size)
Retrieve the local URI for this subscription.
static void exten_state_data_destructor(void *obj)
enum ast_extension_states exten_state
void ast_sip_subscription_get_remote_uri(struct ast_sip_subscription *sub, char *buf, size_t size)
Retrive the remote URI for this subscription.
#define NULL
Definition: resample.c:96
struct ast_sip_subscription * sub
int ast_hint_presence_state(struct ast_channel *c, const char *context, const char *exten, char **subtype, char **message)
Uses hint and presence state callback to get the presence state of an extension.
Definition: pbx.c:3226
char context[AST_MAX_CONTEXT]
struct ao2_container * ast_sip_subscription_get_datastores(const struct ast_sip_subscription *subscription)
Get the datastores container for a subscription.
enum ast_presence_state presence_state
int ast_extension_state_extended(struct ast_channel *c, const char *context, const char *exten, struct ao2_container **device_state_info)
Uses hint and devicestate callback to get the extended state of an extension.
Definition: pbx.c:3176
struct ao2_container * device_state_info
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718
structure used for presence XML bodies
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ exten_state_data_destructor()

static void exten_state_data_destructor ( void *  obj)
static

Definition at line 470 of file res_pjsip_exten_state.c.

References ao2_cleanup, ast_free, ast_sip_get_pjsip_endpoint(), ast_sip_exten_state_data::device_state_info, ast_sip_exten_state_data::pool, ast_sip_exten_state_data::presence_message, and ast_sip_exten_state_data::presence_subtype.

Referenced by exten_state_data_alloc().

471 {
472  struct ast_sip_exten_state_data *exten_state_data = obj;
473 
474  ao2_cleanup(exten_state_data->device_state_info);
475  ast_free(exten_state_data->presence_subtype);
476  ast_free(exten_state_data->presence_message);
477  if (exten_state_data->pool) {
478  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), exten_state_data->pool);
479  }
480 }
struct ao2_container * device_state_info
#define ast_free(a)
Definition: astmm.h:182
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718
structure used for presence XML bodies
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ exten_state_pub_data_alloc()

static struct exten_state_pub_data* exten_state_pub_data_alloc ( const char *  exten,
struct ast_state_cb_info info 
)
static

Definition at line 582 of file res_pjsip_exten_state.c.

References ao2_bump, ao2_container_count(), ast_calloc, ast_strdup, AST_VECTOR_INIT, ast_state_cb_info::device_state_info, ast_state_cb_info::exten_state, exten_state_pub_data_destroy(), NULL, ast_state_cb_info::presence_message, ast_state_cb_info::presence_state, and ast_state_cb_info::presence_subtype.

Referenced by exten_state_publisher_state_cb().

583 {
584  struct exten_state_pub_data *pub_data;
585 
586  pub_data = ast_calloc(1, sizeof(*pub_data));
587  if (!pub_data) {
588  return NULL;
589  }
590 
591  if (AST_VECTOR_INIT(&pub_data->pubs, ao2_container_count(publishers))) {
593  return NULL;
594  }
595 
596  /* Save off currently known information for the body generators. */
597  pub_data->exten_state_data.exten = ast_strdup(exten);
598  pub_data->exten_state_data.exten_state = info->exten_state;
599  pub_data->exten_state_data.presence_state = info->presence_state;
600  pub_data->exten_state_data.presence_subtype = ast_strdup(info->presence_subtype);
601  pub_data->exten_state_data.presence_message = ast_strdup(info->presence_message);
602  pub_data->exten_state_data.device_state_info = ao2_bump(info->device_state_info);
603  if (!pub_data->exten_state_data.exten
604  || !pub_data->exten_state_data.presence_subtype
605  || !pub_data->exten_state_data.presence_message) {
607  return NULL;
608  }
609  return pub_data;
610 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
const char * presence_message
Definition: pbx.h:108
static struct ao2_container * publishers
Container of active outbound extension state publishers.
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
#define ao2_bump(obj)
Definition: astobj2.h:491
static void exten_state_pub_data_destroy(struct exten_state_pub_data *doomed)
enum ast_extension_states exten_state
Definition: pbx.h:104
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
enum ast_presence_state presence_state
Definition: pbx.h:106
const char * presence_subtype
Definition: pbx.h:107
struct ao2_container * device_state_info
Definition: pbx.h:105
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204

◆ exten_state_pub_data_destroy()

static void exten_state_pub_data_destroy ( struct exten_state_pub_data doomed)
static

Definition at line 565 of file res_pjsip_exten_state.c.

References ao2_cleanup, ao2_ref, ast_free, AST_VECTOR_CALLBACK_VOID, and AST_VECTOR_FREE.

Referenced by exten_state_pub_data_alloc(), exten_state_publisher_cb(), and exten_state_publisher_state_cb().

566 {
567  if (!doomed) {
568  return;
569  }
570 
571  ast_free((void *) doomed->exten_state_data.exten);
572  ast_free(doomed->exten_state_data.presence_subtype);
573  ast_free(doomed->exten_state_data.presence_message);
574  ao2_cleanup(doomed->exten_state_data.device_state_info);
575 
576  AST_VECTOR_CALLBACK_VOID(&doomed->pubs, ao2_ref, -1);
577  AST_VECTOR_FREE(&doomed->pubs);
578 
579  ast_free(doomed);
580 }
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_free(a)
Definition: astmm.h:182
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
#define AST_VECTOR_CALLBACK_VOID(vec, callback,...)
Execute a callback on every element in a vector disregarding callback return.
Definition: vector.h:865

◆ exten_state_publisher_cb()

static int exten_state_publisher_cb ( void *  data)
static

Definition at line 619 of file res_pjsip_exten_state.c.

References ast_free, ast_log, AST_SIP_EXTEN_STATE_DATA, ast_sip_get_pjsip_endpoint(), ast_sip_publish_client_get_user_from_uri(), ast_sip_publish_client_get_user_to_uri(), ast_sip_publish_client_user_send(), ast_sip_pubsub_generate_body_content(), ast_str_buffer(), ast_str_create, ast_strlen_zero, AST_VECTOR_GET, AST_VECTOR_SIZE, exten_state_publisher::body_subtype, ast_sip_body::body_text, exten_state_publisher::body_type, ast_sip_body_data::body_type, exten_state_publisher::client, exten_state_publisher::datastores, exten_state_pub_data_destroy(), LOG_WARNING, exten_state_publisher::name, pool, ast_sip_body::subtype, and ast_sip_body::type.

Referenced by exten_state_publisher_state_cb().

620 {
621  struct exten_state_pub_data *pub_data = data;
622  struct exten_state_publisher *publisher;
623  size_t idx;
624  struct ast_str *body_text;
625  pj_pool_t *pool;
626  struct ast_sip_body_data gen_data = {
628  .body_data = &pub_data->exten_state_data,
629  };
630  struct ast_sip_body body;
631 
632  body_text = ast_str_create(64);
633  if (!body_text) {
635  return 0;
636  }
637 
638  /* Need a PJSIP memory pool to generate the bodies. */
639  pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "pub_state_body",
640  1024, 1024);
641  if (!pool) {
642  ast_log(LOG_WARNING, "Exten state publishing unable to create memory pool\n");
644  ast_free(body_text);
645  return 0;
646  }
647  pub_data->exten_state_data.pool = pool;
648 
649  for (idx = 0; idx < AST_VECTOR_SIZE(&pub_data->pubs); ++idx) {
650  const char *uri;
651  int res;
652 
653  publisher = AST_VECTOR_GET(&pub_data->pubs, idx);
654 
655  uri = ast_sip_publish_client_get_user_from_uri(publisher->client, pub_data->exten_state_data.exten,
656  pub_data->exten_state_data.local, sizeof(pub_data->exten_state_data.local));
657  if (ast_strlen_zero(uri)) {
658  ast_log(LOG_WARNING, "PUBLISH client '%s' has no from_uri or server_uri defined.\n",
659  publisher->name);
660  continue;
661  }
662 
663  uri = ast_sip_publish_client_get_user_to_uri(publisher->client, pub_data->exten_state_data.exten,
664  pub_data->exten_state_data.remote, sizeof(pub_data->exten_state_data.remote));
665  if (ast_strlen_zero(uri)) {
666  ast_log(LOG_WARNING, "PUBLISH client '%s' has no to_uri or server_uri defined.\n",
667  publisher->name);
668  continue;
669  }
670 
671  pub_data->exten_state_data.datastores = publisher->datastores;
672 
674  publisher->body_subtype, &gen_data, &body_text);
675  pj_pool_reset(pool);
676  if (res) {
678  "PUBLISH client '%s' unable to generate %s/%s PUBLISH body.\n",
679  publisher->name, publisher->body_type, publisher->body_subtype);
680  continue;
681  }
682 
683  body.type = publisher->body_type;
684  body.subtype = publisher->body_subtype;
685  body.body_text = ast_str_buffer(body_text);
686  ast_sip_publish_client_user_send(publisher->client, pub_data->exten_state_data.exten, &body);
687  }
688 
689  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
690 
691  ast_free(body_text);
693  return 0;
694 }
struct ast_sip_outbound_publish_client * client
int ast_sip_publish_client_user_send(struct ast_sip_outbound_publish_client *client, const char *user, const struct ast_sip_body *body)
Send an outgoing PUBLISH message based on the user.
const char * body_type
Data used to create bodies for NOTIFY/PUBLISH requests.
#define LOG_WARNING
Definition: logger.h:274
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
static pj_pool_t * pool
Global memory pool for configuration and timers.
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define AST_SIP_EXTEN_STATE_DATA
static void exten_state_pub_data_destroy(struct exten_state_pub_data *doomed)
An extension state publisher.
#define ast_log
Definition: astobj2.c:42
int ast_sip_pubsub_generate_body_content(const char *content_type, const char *content_subtype, struct ast_sip_body_data *data, struct ast_str **str)
Generate body content for a PUBLISH or NOTIFY.
const char * ast_sip_publish_client_get_user_to_uri(struct ast_sip_outbound_publish_client *client, const char *user, char *uri, size_t size)
Get the To URI the client will use for a specific user.
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
#define ast_free(a)
Definition: astmm.h:182
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
struct ao2_container * datastores
SIP body description.
Definition: res_pjsip.h:2027
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
const char * ast_sip_publish_client_get_user_from_uri(struct ast_sip_outbound_publish_client *client, const char *user, char *uri, size_t size)
Get the From URI the client will use for a specific user.

◆ exten_state_publisher_cmp()

static int exten_state_publisher_cmp ( void *  obj,
void *  arg,
int  flags 
)
static

Comparator function for extension state publisher.

Definition at line 775 of file res_pjsip_exten_state.c.

References ast_assert, CMP_MATCH, exten_state_publisher::name, OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, and OBJ_SEARCH_PARTIAL_KEY.

Referenced by load_module().

776 {
777  const struct exten_state_publisher *object_left = obj;
778  const struct exten_state_publisher *object_right = arg;
779  const char *right_key = arg;
780  int cmp;
781 
782  switch (flags & OBJ_SEARCH_MASK) {
783  case OBJ_SEARCH_OBJECT:
784  right_key = object_right->name;
785  /* Fall through */
786  case OBJ_SEARCH_KEY:
787  cmp = strcmp(object_left->name, right_key);
788  break;
790  /* Not supported by container. */
791  ast_assert(0);
792  return 0;
793  default:
794  cmp = 0;
795  break;
796  }
797  if (cmp) {
798  return 0;
799  }
800  return CMP_MATCH;
801 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define ast_assert(a)
Definition: utils.h:695
An extension state publisher.
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1120
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
Search option field mask.
Definition: astobj2.h:1076

◆ exten_state_publisher_destroy()

static void exten_state_publisher_destroy ( void *  obj)
static

Destructor for extension state publisher.

Definition at line 806 of file res_pjsip_exten_state.c.

References ao2_cleanup, exten_state_publisher::client, exten_state_publisher::context_filter, exten_state_publisher::context_regex, exten_state_publisher::datastores, exten_state_publisher::exten_filter, and exten_state_publisher::exten_regex.

Referenced by publisher_start().

807 {
808  struct exten_state_publisher *publisher = obj;
809 
810  if (publisher->context_filter) {
811  regfree(&publisher->context_regex);
812  }
813 
814  if (publisher->exten_filter) {
815  regfree(&publisher->exten_regex);
816  }
817 
818  ao2_cleanup(publisher->client);
819  ao2_cleanup(publisher->datastores);
820 }
struct ast_sip_outbound_publish_client * client
An extension state publisher.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ao2_container * datastores

◆ exten_state_publisher_hash()

static int exten_state_publisher_hash ( const void *  obj,
const int  flags 
)
static

Hashing function for extension state publisher.

Definition at line 752 of file res_pjsip_exten_state.c.

References ast_assert, ast_str_hash(), OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, and OBJ_SEARCH_OBJECT.

Referenced by load_module().

753 {
754  const struct exten_state_publisher *object;
755  const char *key;
756 
757  switch (flags & OBJ_SEARCH_MASK) {
758  case OBJ_SEARCH_KEY:
759  key = obj;
760  break;
761  case OBJ_SEARCH_OBJECT:
762  object = obj;
763  key = object->name;
764  break;
765  default:
766  ast_assert(0);
767  return 0;
768  }
769  return ast_str_hash(key);
770 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define ast_assert(a)
Definition: utils.h:695
An extension state publisher.
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
Search option field mask.
Definition: astobj2.h:1076
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition: strings.h:1206

◆ exten_state_publisher_state_cb()

static int exten_state_publisher_state_cb ( const char *  context,
const char *  exten,
struct ast_state_cb_info info,
void *  data 
)
static

Global extension state callback function.

Definition at line 699 of file res_pjsip_exten_state.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_debug, ast_extension_state2str(), AST_HINT_UPDATE_DEVICE, AST_HINT_UPDATE_PRESENCE, ast_presence_state2str(), ast_sip_push_task(), AST_VECTOR_APPEND, exten_state_publisher::context_filter, exten_state_publisher::context_regex, exten_state_publisher::exten_filter, exten_state_publisher::exten_regex, ast_state_cb_info::exten_state, exten_state_pub_data_alloc(), exten_state_pub_data_destroy(), exten_state_publisher_cb(), exten_state_publisher::name, NULL, ast_state_cb_info::presence_message, ast_state_cb_info::presence_state, ast_state_cb_info::presence_subtype, ast_state_cb_info::reason, and S_OR.

Referenced by publisher_start(), and unload_module().

700 {
701  struct ao2_iterator publisher_iter;
702  struct exten_state_publisher *publisher;
703  struct exten_state_pub_data *pub_data = NULL;
704 
705  ast_debug(5, "Exten state publisher: %s@%s Reason:%s State:%s Presence:%s Subtype:'%s' Message:'%s'\n",
706  exten, context,
708  ? "Device"
710  ? "Presence"
711  : "Unknown",
714  S_OR(info->presence_subtype, ""),
715  S_OR(info->presence_message, ""));
716  publisher_iter = ao2_iterator_init(publishers, 0);
717  for (; (publisher = ao2_iterator_next(&publisher_iter)); ao2_ref(publisher, -1)) {
718  if ((publisher->context_filter && regexec(&publisher->context_regex, context, 0, NULL, 0)) ||
719  (publisher->exten_filter && regexec(&publisher->exten_regex, exten, 0, NULL, 0))) {
720  continue;
721  }
722 
723  if (!pub_data) {
724  pub_data = exten_state_pub_data_alloc(exten, info);
725  if (!pub_data) {
726  ao2_ref(publisher, -1);
727  break;
728  }
729  }
730 
731  ao2_ref(publisher, +1);
732  if (AST_VECTOR_APPEND(&pub_data->pubs, publisher)) {
733  ao2_ref(publisher, -1);
734  } else {
735  ast_debug(5, "'%s' will publish exten state\n", publisher->name);
736  }
737  }
738  ao2_iterator_destroy(&publisher_iter);
739 
740  if (pub_data
742  pub_data)) {
744  }
745 
746  return 0;
747 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
const char * presence_message
Definition: pbx.h:108
static struct ao2_container * publishers
Container of active outbound extension state publishers.
enum ast_state_cb_update_reason reason
Definition: pbx.h:103
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define NULL
Definition: resample.c:96
static void exten_state_pub_data_destroy(struct exten_state_pub_data *doomed)
An extension state publisher.
enum ast_extension_states exten_state
Definition: pbx.h:104
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
enum ast_presence_state presence_state
Definition: pbx.h:106
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char * ast_extension_state2str(int extension_state)
Return string representation of the state of an extension.
Definition: pbx.c:3126
const char * presence_subtype
Definition: pbx.h:107
static struct exten_state_pub_data * exten_state_pub_data_alloc(const char *exten, struct ast_state_cb_info *info)
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Definition: res_pjsip.c:5138
static struct ast_taskprocessor * publish_exten_state_serializer
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
const char * ast_presence_state2str(enum ast_presence_state state)
Convert presence state to text string for output.
static int exten_state_publisher_cb(void *data)

◆ exten_state_subscription_alloc()

static struct exten_state_subscription* exten_state_subscription_alloc ( struct ast_sip_subscription sip_sub,
struct ast_sip_endpoint endpoint 
)
static

Definition at line 210 of file res_pjsip_exten_state.c.

References ao2_alloc, ao2_bump, AST_PRESENCE_NOT_SET, ast_sip_subscription_get_serializer(), exten_state_subscription_destructor(), get_user_agent(), INITIAL_LAST_EXTEN_STATE, exten_state_subscription::last_exten_state, exten_state_subscription::last_presence_state, NULL, exten_state_subscription::serializer, exten_state_subscription::sip_sub, and exten_state_subscription::user_agent.

Referenced by subscription_established().

212 {
213  struct exten_state_subscription * exten_state_sub;
214 
215  exten_state_sub = ao2_alloc(sizeof(*exten_state_sub), exten_state_subscription_destructor);
216  if (!exten_state_sub) {
217  return NULL;
218  }
219 
220  exten_state_sub->sip_sub = sip_sub;
221 
222  /* We keep our own reference to the serializer as there is no guarantee in state_changed
223  * that the subscription tree is still valid when it is called. This can occur when
224  * the subscription is terminated at around the same time as the state_changed
225  * callback is invoked.
226  */
227  exten_state_sub->serializer = ao2_bump(ast_sip_subscription_get_serializer(sip_sub));
228  exten_state_sub->last_exten_state = INITIAL_LAST_EXTEN_STATE;
229  exten_state_sub->last_presence_state = AST_PRESENCE_NOT_SET;
230  exten_state_sub->user_agent = get_user_agent(sip_sub);
231  return exten_state_sub;
232 }
enum ast_extension_states last_exten_state
A subscription for extension state.
struct ast_taskprocessor * ast_sip_subscription_get_serializer(struct ast_sip_subscription *sub)
Get the serializer for the subscription.
enum ast_presence_state last_presence_state
struct ast_taskprocessor * serializer
#define NULL
Definition: resample.c:96
#define ao2_bump(obj)
Definition: astobj2.h:491
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
static char * get_user_agent(const struct ast_sip_subscription *sip_sub)
#define INITIAL_LAST_EXTEN_STATE
static void exten_state_subscription_destructor(void *obj)
struct ast_sip_subscription * sip_sub

◆ exten_state_subscription_destructor()

static void exten_state_subscription_destructor ( void *  obj)
static

Definition at line 170 of file res_pjsip_exten_state.c.

References ast_free, ast_sip_subscription_destroy(), ast_taskprocessor_unreference(), exten_state_subscription::serializer, exten_state_subscription::sip_sub, sub, and exten_state_subscription::user_agent.

Referenced by exten_state_subscription_alloc().

171 {
172  struct exten_state_subscription *sub = obj;
173 
174  ast_free(sub->user_agent);
177 }
A subscription for extension state.
struct ast_taskprocessor * serializer
void ast_sip_subscription_destroy(struct ast_sip_subscription *sub)
Alert the pubsub core that the subscription is ready for destruction.
#define ast_free(a)
Definition: astmm.h:182
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
struct stasis_forward * sub
Definition: res_corosync.c:240
struct ast_sip_subscription * sip_sub

◆ get_exten_state_sub()

static struct exten_state_subscription* get_exten_state_sub ( struct ast_sip_subscription sub)
static

Definition at line 389 of file res_pjsip_exten_state.c.

References ao2_cleanup, ast_sip_subscription_get_datastore(), ds_name, NULL, and RAII_VAR.

Referenced by get_notify_data(), subscription_shutdown(), and to_ami().

391 {
392  RAII_VAR(struct ast_datastore *, datastore,
394 
395  return datastore ? datastore->data : NULL;
396 }
Structure for a data store object.
Definition: datastore.h:68
#define NULL
Definition: resample.c:96
#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:911
static const char ds_name[]
struct ast_datastore * ast_sip_subscription_get_datastore(struct ast_sip_subscription *subscription, const char *name)
Retrieve a subscription datastore.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ get_notify_data()

static void * get_notify_data ( struct ast_sip_subscription sub)
static

Definition at line 530 of file res_pjsip_exten_state.c.

References exten_state_data_alloc(), get_exten_state_sub(), and NULL.

531 {
532  struct exten_state_subscription *exten_state_sub;
533 
534  exten_state_sub = get_exten_state_sub(sub);
535  if (!exten_state_sub) {
536  return NULL;
537  }
538 
539  return exten_state_data_alloc(sub, exten_state_sub);
540 }
A subscription for extension state.
static struct ast_sip_exten_state_data * exten_state_data_alloc(struct ast_sip_subscription *sip_sub, struct exten_state_subscription *exten_state_sub)
#define NULL
Definition: resample.c:96
static struct exten_state_subscription * get_exten_state_sub(struct ast_sip_subscription *sub)

◆ get_user_agent()

static char* get_user_agent ( const struct ast_sip_subscription sip_sub)
static

Definition at line 179 of file res_pjsip_exten_state.c.

References ast_copy_pj_str(), ast_malloc, ast_sip_subscription_get_header(), ast_str_to_lower(), NULL, and exten_state_subscription::user_agent.

Referenced by exten_state_subscription_alloc().

180 {
181  size_t size;
182  char *user_agent = NULL;
183  pjsip_user_agent_hdr *user_agent_hdr = ast_sip_subscription_get_header(
184  sip_sub, "User-Agent");
185 
186  if (!user_agent_hdr) {
187  return NULL;
188  }
189 
190  size = pj_strlen(&user_agent_hdr->hvalue) + 1;
191  user_agent = ast_malloc(size);
192  ast_copy_pj_str(user_agent, &user_agent_hdr->hvalue, size);
193  return ast_str_to_lower(user_agent);
194 }
void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
Copy a pj_str_t into a standard character buffer.
Definition: res_pjsip.c:5240
#define NULL
Definition: resample.c:96
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
static force_inline char * ast_str_to_lower(char *str)
Convert a string to all lower-case.
Definition: strings.h:1268
void * ast_sip_subscription_get_header(const struct ast_sip_subscription *sub, const char *header)
Get a header value for a subscription.

◆ load_module()

static int load_module ( void  )
static

Definition at line 960 of file res_pjsip_exten_state.c.

References AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_hash, ast_log, AST_MODFLAG_LOAD_ORDER, AST_MODPRI_CHANNEL_DEPEND, AST_MODULE_INFO(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, AST_MODULE_SUPPORT_CORE, ast_sip_create_serializer(), ast_sip_register_event_publisher_handler(), ast_sip_register_subscription_handler(), ASTERISK_GPL_KEY, ast_sip_event_publisher_handler::event_name, ast_sip_subscription_handler::event_name, exten_state_publisher_cmp(), exten_state_publisher_hash(), LOG_WARNING, NULL, PUBLISHER_BUCKETS, and unload_module().

961 {
964  if (!publishers) {
965  ast_log(LOG_WARNING, "Unable to create container to store extension state publishers\n");
967  }
968 
971  unload_module();
973  }
974 
976  ast_log(LOG_WARNING, "Unable to register subscription handler %s\n",
978  unload_module();
980  }
981 
983  ast_log(LOG_WARNING, "Unable to register presence publisher %s\n",
985  unload_module();
987  }
988 
990  ast_log(LOG_WARNING, "Unable to register subscription handler %s\n",
992  unload_module();
994  }
995 
997  ast_log(LOG_WARNING, "Unable to register presence publisher %s\n",
999  unload_module();
1000  return AST_MODULE_LOAD_DECLINE;
1001  }
1002 
1003  return AST_MODULE_LOAD_SUCCESS;
1004 }
struct ast_sip_subscription_handler dialog_handler
#define PUBLISHER_BUCKETS
The number of buckets to use for storing publishers.
struct ast_sip_event_publisher_handler dialog_publisher
static struct ao2_container * publishers
Container of active outbound extension state publishers.
#define LOG_WARNING
Definition: logger.h:274
int ast_sip_register_subscription_handler(struct ast_sip_subscription_handler *handler)
Register a subscription handler.
static int exten_state_publisher_hash(const void *obj, const int flags)
Hashing function for extension state publisher.
static int exten_state_publisher_cmp(void *obj, void *arg, int flags)
Comparator function for extension state publisher.
#define NULL
Definition: resample.c:96
static int unload_module(void)
#define ast_log
Definition: astobj2.c:42
const char * event_name
The name of the event this handler deals with.
struct ast_sip_subscription_handler presence_handler
struct ast_sip_event_publisher_handler presence_publisher
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
struct ast_taskprocessor * ast_sip_create_serializer(const char *name)
Create a new serializer for SIP tasks.
Definition: res_pjsip.c:5133
static struct ast_taskprocessor * publish_exten_state_serializer
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
int ast_sip_register_event_publisher_handler(struct ast_sip_event_publisher_handler *handler)
Register an event publisher handler.

◆ new_subscribe()

static int new_subscribe ( struct ast_sip_endpoint endpoint,
const char *  resource 
)
static

Definition at line 412 of file res_pjsip_exten_state.c.

References ast_exists_extension(), ast_log, ast_sorcery_object_get_id(), exten_state_subscription::context, ast_sip_endpoint_subscription_configuration::context, ast_sip_endpoint::context, LOG_NOTICE, NULL, PRIORITY_HINT, S_OR, and ast_sip_endpoint::subscription.

414 {
415  const char *context = S_OR(endpoint->subscription.context, endpoint->context);
416 
417  if (!ast_exists_extension(NULL, context, resource, PRIORITY_HINT, NULL)) {
418  ast_log(LOG_NOTICE, "Endpoint '%s' state subscription failed: "
419  "Extension '%s' does not exist in context '%s' or has no associated hint\n",
420  ast_sorcery_object_get_id(endpoint), resource, context);
421  return 404;
422  }
423 
424  return 200;
425 }
struct ast_sip_endpoint_subscription_configuration subscription
Definition: res_pjsip.h:843
const ast_string_field context
Definition: res_pjsip.h:815
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
#define PRIORITY_HINT
Definition: pbx.h:54
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:4179
#define LOG_NOTICE
Definition: logger.h:263
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ notify_task()

static int notify_task ( void *  obj)
static

Definition at line 288 of file res_pjsip_exten_state.c.

References ao2_cleanup, AST_SIP_EXTEN_STATE_DATA, ast_sip_get_pjsip_endpoint(), ast_sip_subscription_get_datastores(), ast_sip_subscription_get_local_uri(), ast_sip_subscription_get_remote_uri(), ast_sip_subscription_is_terminated(), ast_sip_subscription_notify(), ast_sip_body_data::body_type, and RAII_VAR.

Referenced by state_changed().

289 {
291  struct ast_sip_body_data data = {
293  .body_data = &task_data->exten_state_data,
294  };
295 
296  /* Terminated subscriptions are no longer associated with a valid tree, and sending
297  * NOTIFY messages on a subscription which has already been terminated won't work.
298  */
299  if (ast_sip_subscription_is_terminated(task_data->exten_state_sub->sip_sub)) {
300  return 0;
301  }
302 
303  /* All access to the subscription must occur within a task executed within its serializer */
304  ast_sip_subscription_get_local_uri(task_data->exten_state_sub->sip_sub,
305  task_data->exten_state_data.local, sizeof(task_data->exten_state_data.local));
306  ast_sip_subscription_get_remote_uri(task_data->exten_state_sub->sip_sub,
307  task_data->exten_state_data.remote, sizeof(task_data->exten_state_data.remote));
308 
309  /* Pool allocation has to happen here so that we allocate within a PJLIB thread */
310  task_data->exten_state_data.pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(),
311  "exten_state", 1024, 1024);
312  if (!task_data->exten_state_data.pool) {
313  return -1;
314  }
315 
316  task_data->exten_state_data.sub = task_data->exten_state_sub->sip_sub;
317  task_data->exten_state_data.datastores = ast_sip_subscription_get_datastores(task_data->exten_state_sub->sip_sub);
318 
319  ast_sip_subscription_notify(task_data->exten_state_sub->sip_sub, &data,
320  task_data->terminate);
321 
322  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(),
323  task_data->exten_state_data.pool);
324  return 0;
325 }
void ast_sip_subscription_get_local_uri(struct ast_sip_subscription *sub, char *buf, size_t size)
Retrieve the local URI for this subscription.
int ast_sip_subscription_is_terminated(const struct ast_sip_subscription *sub)
Get whether the subscription has been terminated or not.
const char * body_type
Data used to create bodies for NOTIFY/PUBLISH requests.
void ast_sip_subscription_get_remote_uri(struct ast_sip_subscription *sub, char *buf, size_t size)
Retrive the remote URI for this subscription.
struct ao2_container * ast_sip_subscription_get_datastores(const struct ast_sip_subscription *subscription)
Get the datastores container for a subscription.
#define AST_SIP_EXTEN_STATE_DATA
#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:911
userdata associated with baseline taskprocessor test
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
int ast_sip_subscription_notify(struct ast_sip_subscription *sub, struct ast_sip_body_data *notify_data, int terminate)
Notify a SIP subscription of a state change.

◆ notify_task_data_destructor()

static void notify_task_data_destructor ( void *  obj)
static

Definition at line 240 of file res_pjsip_exten_state.c.

References ao2_cleanup, ao2_ref, ast_free, ast_sip_exten_state_data::device_state_info, notify_task_data::exten_state_data, notify_task_data::exten_state_sub, ast_sip_exten_state_data::presence_message, ast_sip_exten_state_data::presence_subtype, and ast_sip_exten_state_data::user_agent.

Referenced by alloc_notify_task_data().

241 {
242  struct notify_task_data *task_data = obj;
243 
244  ao2_ref(task_data->exten_state_sub, -1);
249 }
struct ast_sip_exten_state_data exten_state_data
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ao2_container * device_state_info
userdata associated with baseline taskprocessor test
#define ast_free(a)
Definition: astmm.h:182
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct exten_state_subscription * exten_state_sub

◆ publisher_start()

static int publisher_start ( struct ast_sip_outbound_publish configuration,
struct ast_sip_outbound_publish_client client 
)
static

Definition at line 837 of file res_pjsip_exten_state.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_bump, ao2_container_count(), ao2_link_flags, ao2_lock, ao2_ref, ao2_unlock, ast_copy_string(), ast_datastores_alloc(), ast_extension_state_add(), ast_log, ast_sip_pubsub_is_body_generator_registered(), ast_sorcery_object_get_extended(), ast_sorcery_object_get_id(), ast_strdupa, ast_strlen_zero, exten_state_publisher::body_subtype, exten_state_publisher::body_type, build_regex(), exten_state_publisher::client, exten_state_subscription::context, exten_state_publisher::context_filter, exten_state_publisher::context_regex, exten_state_publisher::datastores, exten_state_subscription::exten, exten_state_publisher::exten_filter, exten_state_publisher::exten_regex, exten_state_publisher_destroy(), exten_state_publisher_state_cb(), LOG_ERROR, name, exten_state_publisher::name, NULL, OBJ_NOLOCK, and strsep().

838 {
839  struct exten_state_publisher *publisher;
840  size_t name_size;
841  size_t body_type_size;
842  size_t body_subtype_size;
843  char *body_subtype;
844  const char *body_full;
845  const char *body_type;
846  const char *name;
847  const char *context;
848  const char *exten;
849 
850  name = ast_sorcery_object_get_id(configuration);
851 
852  body_full = ast_sorcery_object_get_extended(configuration, "body");
853  if (ast_strlen_zero(body_full)) {
854  ast_log(LOG_ERROR, "Outbound extension state publisher '%s': Body not set\n",
855  name);
856  return -1;
857  }
858 
859  body_subtype = ast_strdupa(body_full);
860  body_type = strsep(&body_subtype, "/");
861  if (ast_strlen_zero(body_type) || ast_strlen_zero(body_subtype)) {
862  ast_log(LOG_ERROR, "Outbound extension state publisher '%s': Body '%s' missing type or subtype\n",
863  name, body_full);
864  return -1;
865  }
866 
867  if (!ast_sip_pubsub_is_body_generator_registered(body_type, body_subtype)) {
868  ast_log(LOG_ERROR, "Outbound extension state publisher '%s': '%s' body generator not registered\n",
869  name, body_full);
870  return -1;
871  }
872 
873  name_size = strlen(name) + 1;
874  body_type_size = strlen(body_type) + 1;
875  body_subtype_size = strlen(body_subtype) + 1;
876 
877  publisher = ao2_alloc_options(
878  sizeof(*publisher) + name_size + body_type_size + body_subtype_size,
880  if (!publisher) {
881  return -1;
882  }
883 
884  ast_copy_string(publisher->name, name, name_size);
885  publisher->body_type = publisher->name + name_size;
886  ast_copy_string(publisher->body_type, body_type, body_type_size);
887  publisher->body_subtype = publisher->body_type + body_type_size;
888  ast_copy_string(publisher->body_subtype, body_subtype, body_subtype_size);
889 
890  context = ast_sorcery_object_get_extended(configuration, "context");
891  if (!ast_strlen_zero(context)) {
892  if (build_regex(&publisher->context_regex, context)) {
893  ast_log(LOG_ERROR, "Outbound extension state publisher '%s': Could not build context filter '%s'\n",
894  name, context);
895  ao2_ref(publisher, -1);
896  return -1;
897  }
898 
899  publisher->context_filter = 1;
900  }
901 
902  exten = ast_sorcery_object_get_extended(configuration, "exten");
903  if (!ast_strlen_zero(exten)) {
904  if (build_regex(&publisher->exten_regex, exten)) {
905  ast_log(LOG_ERROR, "Outbound extension state publisher '%s': Could not build exten filter '%s'\n",
906  name, exten);
907  ao2_ref(publisher, -1);
908  return -1;
909  }
910 
911  publisher->exten_filter = 1;
912  }
913 
914  publisher->datastores = ast_datastores_alloc();
915  if (!publisher->datastores) {
916  ast_log(LOG_ERROR, "Outbound extension state publisher '%s': Could not create datastores container\n",
917  name);
918  ao2_ref(publisher, -1);
919  return -1;
920  }
921 
922  publisher->client = ao2_bump(client);
923 
927  }
928  ao2_link_flags(publishers, publisher, OBJ_NOLOCK);
930 
931  ao2_ref(publisher, -1);
932 
933  return 0;
934 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
struct ast_sip_outbound_publish_client * client
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
static struct ao2_container * publishers
Container of active outbound extension state publishers.
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067
static int exten_state_publisher_state_cb(const char *context, const char *exten, struct ast_state_cb_info *info, void *data)
Global extension state callback function.
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define ao2_link_flags(container, obj, flags)
Definition: astobj2.h:1572
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
static int build_regex(regex_t *regex, const char *text)
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ao2_container * ast_datastores_alloc(void)
Allocate a specialized data stores container.
Definition: datastore.c:95
#define ao2_bump(obj)
Definition: astobj2.h:491
An extension state publisher.
const char * ast_sorcery_object_get_extended(const void *object, const char *name)
Get an extended field value from a sorcery object.
Definition: sorcery.c:2330
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
int ast_sip_pubsub_is_body_generator_registered(const char *type, const char *subtype)
Is a body generator registered for the given type/subtype.
#define LOG_ERROR
Definition: logger.h:285
static const char name[]
Definition: cdr_mysql.c:74
static void exten_state_publisher_destroy(void *obj)
Destructor for extension state publisher.
char * strsep(char **str, const char *delims)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
int ast_extension_state_add(const char *context, const char *exten, ast_state_cb_type change_cb, void *data)
Add watcher for extension states.
Definition: pbx.c:3825
struct ao2_container * datastores

◆ publisher_stop()

static int publisher_stop ( struct ast_sip_outbound_publish_client client)
static

Definition at line 936 of file res_pjsip_exten_state.c.

References ao2_find, ast_sorcery_object_get_id(), OBJ_NODATA, OBJ_SEARCH_KEY, and OBJ_UNLINK.

937 {
939  return 0;
940 }
static struct ao2_container * publishers
Container of active outbound extension state publishers.
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756

◆ state_changed()

static int state_changed ( const char *  context,
const char *  exten,
struct ast_state_cb_info info,
void *  data 
)
static

Definition at line 333 of file res_pjsip_exten_state.c.

References alloc_notify_task_data(), ao2_cleanup, ast_sip_push_task(), notify_task_data::exten_state_sub, notify_task(), and exten_state_subscription::serializer.

Referenced by subscription_established(), and subscription_shutdown().

335 {
336  struct notify_task_data *task_data;
337  struct exten_state_subscription *exten_state_sub = data;
338 
339  if (!(task_data = alloc_notify_task_data(exten, exten_state_sub, info))) {
340  return -1;
341  }
342 
343  /* safe to push this async since we copy the data from info and
344  add a ref for the device state info */
346  task_data)) {
347  ao2_cleanup(task_data);
348  return -1;
349  }
350  return 0;
351 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
A subscription for extension state.
static struct notify_task_data * alloc_notify_task_data(const char *exten, struct exten_state_subscription *exten_state_sub, struct ast_state_cb_info *info)
static int notify_task(void *obj)
struct ast_taskprocessor * serializer
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Definition: res_pjsip.c:5138
userdata associated with baseline taskprocessor test
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct exten_state_subscription * exten_state_sub

◆ state_changed_destroy()

static void state_changed_destroy ( int  id,
void *  data 
)
static

Definition at line 353 of file res_pjsip_exten_state.c.

References ao2_cleanup.

Referenced by subscription_established().

354 {
355  struct exten_state_subscription *exten_state_sub = data;
356  ao2_cleanup(exten_state_sub);
357 }
A subscription for extension state.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ subscription_established()

static int subscription_established ( struct ast_sip_subscription sub)
static

Definition at line 427 of file res_pjsip_exten_state.c.

References add_datastore(), ao2_cleanup, ao2_ref, ast_copy_string(), ast_extension_state_add_destroy_extended(), ast_log, ast_sip_subscription_get_endpoint(), ast_sip_subscription_get_resource_name(), ast_sorcery_object_get_id(), exten_state_subscription::context, ast_sip_endpoint_subscription_configuration::context, ast_sip_endpoint::context, exten_state_subscription::exten, exten_state_subscription_alloc(), exten_state_subscription::id, LOG_WARNING, S_OR, state_changed(), state_changed_destroy(), and ast_sip_endpoint::subscription.

428 {
429  struct ast_sip_endpoint *endpoint = ast_sip_subscription_get_endpoint(sip_sub);
430  const char *resource = ast_sip_subscription_get_resource_name(sip_sub);
431  struct exten_state_subscription *exten_state_sub;
432 
433  if (!(exten_state_sub = exten_state_subscription_alloc(sip_sub, endpoint))) {
434  ao2_cleanup(endpoint);
435  return -1;
436  }
437 
438  ast_copy_string(exten_state_sub->context,
439  S_OR(endpoint->subscription.context, endpoint->context),
440  sizeof(exten_state_sub->context));
441  ast_copy_string(exten_state_sub->exten, resource, sizeof(exten_state_sub->exten));
442 
443  if ((exten_state_sub->id = ast_extension_state_add_destroy_extended(
444  exten_state_sub->context, exten_state_sub->exten,
445  state_changed, state_changed_destroy, exten_state_sub)) < 0) {
446  ast_log(LOG_WARNING, "Unable to subscribe endpoint '%s' to extension '%s@%s'\n",
447  ast_sorcery_object_get_id(endpoint), exten_state_sub->exten,
448  exten_state_sub->context);
449  ao2_cleanup(endpoint);
450  ao2_cleanup(exten_state_sub);
451  return -1;
452  }
453 
454  /* Go ahead and cleanup the endpoint since we don't need it anymore */
455  ao2_cleanup(endpoint);
456 
457  /* bump the ref since ast_extension_state_add holds a reference */
458  ao2_ref(exten_state_sub, +1);
459 
460  if (add_datastore(exten_state_sub)) {
461  ast_log(LOG_WARNING, "Unable to add to subscription datastore.\n");
462  ao2_cleanup(exten_state_sub);
463  return -1;
464  }
465 
466  ao2_cleanup(exten_state_sub);
467  return 0;
468 }
char exten[AST_MAX_EXTENSION]
int ast_extension_state_add_destroy_extended(const char *context, const char *exten, ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data)
Add watcher for extended extension states with destructor.
Definition: pbx.c:3831
A subscription for extension state.
static void state_changed_destroy(int id, void *data)
#define LOG_WARNING
Definition: logger.h:274
struct ast_sip_endpoint_subscription_configuration subscription
Definition: res_pjsip.h:843
const ast_string_field context
Definition: res_pjsip.h:815
static int add_datastore(struct exten_state_subscription *exten_state_sub)
const char * ast_sip_subscription_get_resource_name(struct ast_sip_subscription *sub)
Get the name of the subscribed resource.
char context[AST_MAX_CONTEXT]
#define ast_log
Definition: astobj2.c:42
static int state_changed(const char *context, const char *exten, struct ast_state_cb_info *info, void *data)
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
static struct exten_state_subscription * exten_state_subscription_alloc(struct ast_sip_subscription *sip_sub, struct ast_sip_endpoint *endpoint)
struct ast_sip_endpoint * ast_sip_subscription_get_endpoint(struct ast_sip_subscription *sub)
Get the endpoint that is associated with this subscription.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
struct ast_sip_subscription * sip_sub

◆ subscription_shutdown()

static void subscription_shutdown ( struct ast_sip_subscription sub)
static

Definition at line 398 of file res_pjsip_exten_state.c.

References ao2_cleanup, ast_extension_state_del(), ast_sip_subscription_remove_datastore(), ds_name, get_exten_state_sub(), exten_state_subscription::id, exten_state_subscription::sip_sub, and state_changed().

399 {
400  struct exten_state_subscription *exten_state_sub = get_exten_state_sub(sub);
401 
402  if (!exten_state_sub) {
403  return;
404  }
405 
406  ast_extension_state_del(exten_state_sub->id, state_changed);
408  /* remove data store reference */
409  ao2_cleanup(exten_state_sub);
410 }
A subscription for extension state.
int ast_extension_state_del(int id, ast_state_cb_type change_cb)
Deletes a state change watcher by ID.
Definition: pbx.c:3858
static int state_changed(const char *context, const char *exten, struct ast_state_cb_info *info, void *data)
static const char ds_name[]
static struct exten_state_subscription * get_exten_state_sub(struct ast_sip_subscription *sub)
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void ast_sip_subscription_remove_datastore(struct ast_sip_subscription *subscription, const char *name)
Remove a subscription datastore from the subscription.
struct ast_sip_subscription * sip_sub

◆ to_ami()

static void to_ami ( struct ast_sip_subscription sub,
struct ast_str **  buf 
)
static

Definition at line 542 of file res_pjsip_exten_state.c.

References ast_extension_state2str(), ast_str_append(), exten_state_subscription::exten, get_exten_state_sub(), and exten_state_subscription::last_exten_state.

Referenced by agi_async_end_to_ami(), aoc_e_to_ami(), ast_rtp_publish_rtcp_message(), contactstatus_to_json(), dahdichannel_to_ami(), declined_handler(), load_module(), peerstatus_to_json(), queue_agent_ringnoanswer_to_ami(), queue_caller_abandon_to_ami(), queue_member_ringinuse_to_ami(), security_event_to_ami(), stasis_message_can_be_ami(), stasis_message_to_ami(), test_suite_event_to_ami(), unhold_to_json(), and unload_module().

544 {
545  struct exten_state_subscription *exten_state_sub =
546  get_exten_state_sub(sub);
547 
548  if (!exten_state_sub) {
549  return;
550  }
551 
552  ast_str_append(buf, 0, "SubscriptionType: extension_state\r\n"
553  "Extension: %s\r\nExtensionStates: %s\r\n",
554  exten_state_sub->exten, ast_extension_state2str(
555  exten_state_sub->last_exten_state));
556 }
char exten[AST_MAX_EXTENSION]
enum ast_extension_states last_exten_state
A subscription for extension state.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
const char * ast_extension_state2str(int extension_state)
Return string representation of the state of an extension.
Definition: pbx.c:3126
static struct exten_state_subscription * get_exten_state_sub(struct ast_sip_subscription *sub)

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 942 of file res_pjsip_exten_state.c.

References ao2_cleanup, ast_extension_state_del(), ast_sip_unregister_event_publisher_handler(), ast_sip_unregister_subscription_handler(), ast_taskprocessor_unreference(), exten_state_publisher_state_cb(), and NULL.

Referenced by load_module().

943 {
948 
950 
953 
955  publishers = NULL;
956 
957  return 0;
958 }
struct ast_sip_subscription_handler dialog_handler
struct ast_sip_event_publisher_handler dialog_publisher
static struct ao2_container * publishers
Container of active outbound extension state publishers.
int ast_extension_state_del(int id, ast_state_cb_type change_cb)
Deletes a state change watcher by ID.
Definition: pbx.c:3858
static int exten_state_publisher_state_cb(const char *context, const char *exten, struct ast_state_cb_info *info, void *data)
Global extension state callback function.
#define NULL
Definition: resample.c:96
void ast_sip_unregister_event_publisher_handler(struct ast_sip_event_publisher_handler *handler)
Unregister a publish handler.
struct ast_sip_subscription_handler presence_handler
struct ast_sip_event_publisher_handler presence_publisher
static struct ast_taskprocessor * publish_exten_state_serializer
void ast_sip_unregister_subscription_handler(struct ast_sip_subscription_handler *handler)
Unregister a subscription handler.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP Extension State Notifications" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND + 5, .requires = "res_pjsip,res_pjsip_pubsub,res_pjsip_outbound_publish", }
static

Definition at line 1012 of file res_pjsip_exten_state.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1012 of file res_pjsip_exten_state.c.

◆ dialog_handler

struct ast_sip_subscription_handler dialog_handler

Definition at line 155 of file res_pjsip_exten_state.c.

◆ dialog_notifier

struct ast_sip_notifier dialog_notifier

Definition at line 133 of file res_pjsip_exten_state.c.

◆ dialog_publisher

struct ast_sip_event_publisher_handler dialog_publisher
Initial value:
= {
.event_name = "dialog",
.start_publishing = publisher_start,
.stop_publishing = publisher_stop,
}
static int publisher_start(struct ast_sip_outbound_publish *configuration, struct ast_sip_outbound_publish_client *client)
static int publisher_stop(struct ast_sip_outbound_publish_client *client)

Definition at line 164 of file res_pjsip_exten_state.c.

◆ ds_info

struct ast_datastore_info ds_info = { }
static

Definition at line 359 of file res_pjsip_exten_state.c.

◆ ds_name

const char ds_name[] = "exten state datastore"
static

◆ presence_handler

struct ast_sip_subscription_handler presence_handler

Definition at line 140 of file res_pjsip_exten_state.c.

◆ presence_notifier

struct ast_sip_notifier presence_notifier

Definition at line 126 of file res_pjsip_exten_state.c.

◆ presence_publisher

struct ast_sip_event_publisher_handler presence_publisher
Initial value:
= {
.event_name = "presence",
.start_publishing = publisher_start,
.stop_publishing = publisher_stop,
}
static int publisher_start(struct ast_sip_outbound_publish *configuration, struct ast_sip_outbound_publish_client *client)
static int publisher_stop(struct ast_sip_outbound_publish_client *client)

Definition at line 149 of file res_pjsip_exten_state.c.

◆ publish_exten_state_serializer

struct ast_taskprocessor* publish_exten_state_serializer
static

Serializer for outbound extension state publishing.

Definition at line 60 of file res_pjsip_exten_state.c.

◆ publishers

struct ao2_container* publishers
static

Container of active outbound extension state publishers.

Definition at line 57 of file res_pjsip_exten_state.c.

Referenced by AST_TEST_DEFINE(), and explicit_publish_cb().