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",
char * strsep(char **str, const char *delims)
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.
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.