32#include <pjsip_simple.h>
47#define EVENT_TYPE_SIZE 50
52#define PUBLISHER_BUCKETS 31
113#define DEFAULT_PRESENCE_BODY "application/pidf+xml"
114#define DEFAULT_DIALOG_BODY "application/dialog-info+xml"
189 if (!user_agent_hdr) {
193 size = pj_strlen(&user_agent_hdr->hvalue) + 1;
204#define INITIAL_LAST_EXTEN_STATE -3
219 if (!exten_state_sub) {
234 return exten_state_sub;
267 task_data->exten_state_sub->last_exten_state =
info->exten_state;
268 task_data->exten_state_sub->last_presence_state =
info->presence_state;
273 task_data->exten_state_data.presence_state =
info->presence_state;
283 ast_verb(2,
"Watcher for hint %s %s\n", exten,
info->exten_state
296 .body_data = &
task_data->exten_state_data,
315 "exten_state", 1024, 1024);
371static const char ds_name[] =
"exten state datastore";
389 datastore->data = exten_state_sub;
406 return datastore ? datastore->data :
NULL;
413 if (!exten_state_sub) {
424 const char *resource)
430 "Extension '%s' does not exist in context '%s' or has no associated hint\n",
439 const char *resource,
char *display_name,
int display_name_size)
443 if (!endpoint ||
ast_strlen_zero(resource) || !display_name || display_name_size <= 0) {
451 "Extension '%s' does not exist in context '%s' or has no associated hint\n",
472 sizeof(exten_state_sub->
context));
509 if (exten_state_data->
pool) {
518 char *subtype =
NULL;
523 if (!exten_state_data) {
527 exten_state_data->
exten = exten_state_sub->
exten;
538 sizeof(exten_state_data->
local));
540 sizeof(exten_state_data->
remote));
541 exten_state_data->
sub = sip_sub;
553 "exten_state", 1024, 1024);
554 if (!exten_state_data->
pool) {
559 return exten_state_data;
567 if (!exten_state_sub) {
580 if (!exten_state_sub) {
585 "Extension: %s\r\nExtensionStates: %s\r\n",
710 "PUBLISH client '%s' unable to generate %s/%s PUBLISH body.\n",
737 ast_debug(5,
"Exten state publisher: %s@%s Reason:%s State:%s Presence:%s Subtype:'%s' Message:'%s'\n",
767 ast_debug(5,
"'%s' will publish exten state\n", publisher->
name);
811 const char *right_key = arg;
816 right_key = object_right->
name;
819 cmp = strcmp(object_left->
name, right_key);
858 if ((res = regcomp(
regex,
text, REG_EXTENDED | REG_ICASE | REG_NOSUB))) {
873 size_t body_type_size;
874 size_t body_subtype_size;
876 const char *body_full;
886 ast_log(
LOG_ERROR,
"Outbound extension state publisher '%s': Body not set\n",
894 ast_log(
LOG_ERROR,
"Outbound extension state publisher '%s': Body '%s' missing type or subtype\n",
900 ast_log(
LOG_ERROR,
"Outbound extension state publisher '%s': '%s' body generator not registered\n",
905 name_size = strlen(
name) + 1;
910 sizeof(*publisher) + name_size + body_type_size + body_subtype_size,
925 ast_log(
LOG_ERROR,
"Outbound extension state publisher '%s': Could not build context filter '%s'\n",
937 ast_log(
LOG_ERROR,
"Outbound extension state publisher '%s': Could not build exten filter '%s'\n",
948 ast_log(
LOG_ERROR,
"Outbound extension state publisher '%s': Could not create datastores container\n",
1012 ast_log(
LOG_WARNING,
"Unable to create container to store extension state publishers\n");
1058 .
requires =
"res_pjsip,res_pjsip_pubsub,res_pjsip_outbound_publish",
Asterisk main include file. File version handling, generic pbx functions.
int ast_shutdown_final(void)
#define ast_strdup(str)
A wrapper for strdup()
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_calloc(num, len)
A wrapper for calloc()
#define ast_malloc(len)
A wrapper for malloc()
#define ao2_iterator_next(iter)
@ AO2_ALLOC_OPT_LOCK_NOLOCK
@ AO2_ALLOC_OPT_LOCK_MUTEX
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define ao2_link_flags(container, obj, flags)
Add an object to a container.
#define ao2_find(container, arg, flags)
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define ao2_alloc_options(data_size, destructor_fn, options)
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
@ OBJ_SEARCH_PARTIAL_KEY
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
@ OBJ_SEARCH_OBJECT
The arg parameter is an object of the same type.
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
@ OBJ_SEARCH_MASK
Search option field mask.
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
#define ao2_alloc(data_size, destructor_fn)
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
#define AST_MAX_EXTENSION
struct ao2_container * ast_datastores_alloc(void)
Allocate a specialized data stores container.
static int regex(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
struct ast_taskprocessor * ast_sip_create_serializer(const char *name)
Create a new serializer for SIP tasks.
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
char * strsep(char **str, const char *delims)
Support for logging to various files, console and syslog Configuration in file logger....
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
Asterisk module definitions.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODPRI_CHANNEL_DEPEND
@ AST_MODULE_SUPPORT_CORE
#define ASTERISK_GPL_KEY
The text the key() function should return.
@ AST_MODULE_LOAD_SUCCESS
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
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.
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.
const char * ast_extension_state2str(int extension_state)
Return string representation of the state of an extension.
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
ast_extension_states
Extension states.
@ AST_EXTENSION_DEACTIVATED
int ast_extension_state_del(int id, ast_state_cb_type change_cb)
Deletes a state change watcher by ID.
@ AST_HINT_UPDATE_PRESENCE
int ast_extension_state_add(const char *context, const char *exten, ast_state_cb_type change_cb, void *data)
Add watcher for extension states.
int ast_get_hint(char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
If an extension hint exists, return non-zero.
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.
const char * ast_presence_state2str(enum ast_presence_state state)
Convert presence state to text string for output.
struct stasis_forward * sub
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
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.
static struct exten_state_pub_data * exten_state_pub_data_alloc(const char *exten, struct ast_state_cb_info *info)
static int exten_state_publisher_hash(const void *obj, const int flags)
Hashing function for extension state publisher.
static void exten_state_subscription_destructor(void *obj)
static struct exten_state_subscription * exten_state_subscription_alloc(struct ast_sip_subscription *sip_sub, struct ast_sip_endpoint *endpoint)
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 int get_resource_display_name(struct ast_sip_endpoint *endpoint, const char *resource, char *display_name, int display_name_size)
static int publisher_start(struct ast_sip_outbound_publish *configuration, struct ast_sip_outbound_publish_client *client)
static void exten_state_data_destructor(void *obj)
static void notify_task_data_destructor(void *obj)
static void exten_state_publisher_destroy(void *obj)
Destructor for extension state publisher.
static int exten_state_publisher_cb(void *data)
static void exten_state_pub_data_destroy(struct exten_state_pub_data *doomed)
static int exten_state_publisher_cmp(void *obj, void *arg, int flags)
Comparator function for extension state publisher.
struct ast_sip_event_publisher_handler dialog_publisher
static int state_changed(const char *context, const char *exten, struct ast_state_cb_info *info, void *data)
static int publisher_stop(struct ast_sip_outbound_publish_client *client)
struct ast_sip_notifier dialog_notifier
static void subscription_shutdown(struct ast_sip_subscription *sub)
static int subscription_established(struct ast_sip_subscription *sub)
static void * get_notify_data(struct ast_sip_subscription *sub)
#define PUBLISHER_BUCKETS
The number of buckets to use for storing publishers.
static struct ast_taskprocessor * publish_exten_state_serializer
static void state_changed_destroy(int id, void *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 int build_regex(regex_t *regex, const char *text)
static struct exten_state_subscription * get_exten_state_sub(struct ast_sip_subscription *sub)
static int load_module(void)
static int unload_module(void)
#define INITIAL_LAST_EXTEN_STATE
static const char ds_name[]
struct ast_sip_subscription_handler presence_handler
static struct ao2_container * publishers
Container of active outbound extension state publishers.
struct ast_sip_event_publisher_handler presence_publisher
static int add_datastore(struct exten_state_subscription *exten_state_sub)
#define DEFAULT_DIALOG_BODY
static struct ast_datastore_info ds_info
static void to_ami(struct ast_sip_subscription *sub, struct ast_str **buf)
static int notify_task(void *obj)
static int new_subscribe(struct ast_sip_endpoint *endpoint, const char *resource)
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 DEFAULT_PRESENCE_BODY
struct ast_sip_subscription_handler dialog_handler
struct ast_sip_notifier presence_notifier
static char * get_user_agent(const struct ast_sip_subscription *sip_sub)
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.
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.
void ast_sip_unregister_event_publisher_handler(struct ast_sip_event_publisher_handler *handler)
Unregister a publish handler.
int ast_sip_register_event_publisher_handler(struct ast_sip_event_publisher_handler *handler)
Register an event publisher handler.
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.
struct ast_sip_endpoint * ast_sip_subscription_get_endpoint(struct ast_sip_subscription *sub)
Get the endpoint that is associated with this subscription.
void ast_sip_subscription_get_remote_uri(struct ast_sip_subscription *sub, char *buf, size_t size)
Retrive the remote URI for this subscription.
void ast_sip_unregister_subscription_handler(struct ast_sip_subscription_handler *handler)
Unregister a subscription handler.
int ast_sip_register_subscription_handler(struct ast_sip_subscription_handler *handler)
Register a subscription handler.
void ast_sip_subscription_destroy(struct ast_sip_subscription *sub)
Alert the pubsub core that the subscription is ready for destruction.
void ast_sip_subscription_remove_datastore(struct ast_sip_subscription *subscription, const char *name)
Remove a subscription datastore from the subscription.
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.
struct ast_datastore * ast_sip_subscription_alloc_datastore(const struct ast_datastore_info *info, const char *uid)
Alternative for ast_datastore_alloc()
struct ast_taskprocessor * ast_sip_subscription_get_serializer(struct ast_sip_subscription *sub)
Get the serializer for the subscription.
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.
int ast_sip_subscription_add_datastore(struct ast_sip_subscription *subscription, struct ast_datastore *datastore)
Add a datastore to a SIP subscription.
const char * ast_sip_subscription_get_resource_name(struct ast_sip_subscription *sub)
Get the name of the subscribed resource.
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 AST_SIP_EXTEN_STATE_DATA
int ast_sip_subscription_is_terminated(const struct ast_sip_subscription *sub)
Get whether the subscription has been terminated or not.
void ast_sip_subscription_get_local_uri(struct ast_sip_subscription *sub, char *buf, size_t size)
Retrieve the local URI for this subscription.
void * ast_sip_subscription_get_header(const struct ast_sip_subscription *sub, const char *header)
Get a header value for a subscription.
struct ao2_container * ast_sip_subscription_get_datastores(const struct ast_sip_subscription *subscription)
Get the datastores container for a subscription.
struct ast_datastore * ast_sip_subscription_get_datastore(struct ast_sip_subscription *subscription, const char *name)
Retrieve a subscription datastore.
Sorcery Data Access Layer API.
const char * ast_sorcery_object_get_extended(const void *object, const char *name)
Get an extended field value from a sorcery object.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
static force_inline char * ast_str_to_lower(char *str)
Convert a string to all lower-case.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Structure for a data store type.
Structure for a data store object.
Data used to create bodies for NOTIFY/PUBLISH requests.
char context[AST_MAX_CONTEXT]
An entity with which Asterisk communicates.
const ast_string_field context
struct ast_sip_endpoint_subscription_configuration subscription
Callbacks that event publisher handlers will define.
const char * event_name
The name of the event this handler deals with.
structure used for presence XML bodies
char local[PJSIP_MAX_URL_SIZE]
struct ast_sip_subscription * sub
enum ast_extension_states exten_state
struct ao2_container * device_state_info
struct ao2_container * datastores
char remote[PJSIP_MAX_URL_SIZE]
enum ast_presence_state presence_state
const char * default_accept
Default body type defined for the event package this notifier handles.
Outbound publish client state information (persists for lifetime of a publish)
Outbound publish information.
Structure representing a "virtual" SIP subscription.
Support for dynamic strings.
A ast_taskprocessor structure is a singleton by name.
struct ast_sip_exten_state_data exten_state_data
struct exten_state_pub_data::name pubs
An extension state publisher.
struct ast_sip_outbound_publish_client * client
unsigned int exten_filter
struct ao2_container * datastores
unsigned int context_filter
A subscription for extension state.
enum ast_presence_state last_presence_state
struct ast_sip_subscription * sip_sub
enum ast_extension_states last_exten_state
char exten[AST_MAX_EXTENSION]
struct ast_taskprocessor * serializer
char context[AST_MAX_CONTEXT]
struct exten_state_subscription * exten_state_sub
struct ast_sip_exten_state_data exten_state_data
userdata associated with baseline taskprocessor test
An API for managing task processing threads that can be shared across modules.
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
#define AST_VECTOR_CALLBACK_VOID(vec, callback,...)
Execute a callback on every element in a vector disregarding callback return.
#define AST_VECTOR(name, type)
Define a vector structure.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.