32 #include <pjsip_simple.h> 46 #define BODY_SIZE 1024 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" 184 sip_sub,
"User-Agent");
186 if (!user_agent_hdr) {
190 size = pj_strlen(&user_agent_hdr->hvalue) + 1;
201 #define INITIAL_LAST_EXTEN_STATE -3 216 if (!exten_state_sub) {
231 return exten_state_sub;
293 .body_data = &
task_data->exten_state_data,
311 "exten_state", 1024, 1024);
360 static const char ds_name[] =
"exten state datastore";
378 datastore->data = exten_state_sub;
395 return datastore ? datastore->data :
NULL;
402 if (!exten_state_sub) {
413 const char *resource)
419 "Extension '%s' does not exist in context '%s' or has no associated hint\n",
440 sizeof(exten_state_sub->
context));
477 if (exten_state_data->
pool) {
486 char *subtype =
NULL;
491 if (!exten_state_data) {
495 exten_state_data->
exten = exten_state_sub->
exten;
506 sizeof(exten_state_data->
local));
508 sizeof(exten_state_data->
remote));
521 "exten_state", 1024, 1024);
522 if (!exten_state_data->
pool) {
527 return exten_state_data;
535 if (!exten_state_sub) {
548 if (!exten_state_sub) {
553 "Extension: %s\r\nExtensionStates: %s\r\n",
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);
597 pub_data->exten_state_data.exten =
ast_strdup(exten);
598 pub_data->exten_state_data.exten_state = info->
exten_state;
603 if (!pub_data->exten_state_data.exten
604 || !pub_data->exten_state_data.presence_subtype
605 || !pub_data->exten_state_data.presence_message) {
628 .body_data = &pub_data->exten_state_data,
647 pub_data->exten_state_data.pool =
pool;
656 pub_data->exten_state_data.local,
sizeof(pub_data->exten_state_data.local));
664 pub_data->exten_state_data.remote,
sizeof(pub_data->exten_state_data.remote));
671 pub_data->exten_state_data.datastores = publisher->
datastores;
678 "PUBLISH client '%s' unable to generate %s/%s PUBLISH body.\n",
705 ast_debug(5,
"Exten state publisher: %s@%s Reason:%s State:%s Presence:%s Subtype:'%s' Message:'%s'\n",
735 ast_debug(5,
"'%s' will publish exten state\n", publisher->
name);
779 const char *right_key = arg;
784 right_key = object_right->
name;
787 cmp = strcmp(object_left->
name, right_key);
826 if ((res = regcomp(regex, text, REG_EXTENDED | REG_ICASE | REG_NOSUB))) {
827 size_t len = regerror(res, regex,
NULL, 0);
829 regerror(res, regex, buf, len);
841 size_t body_type_size;
842 size_t body_subtype_size;
844 const char *body_full;
854 ast_log(
LOG_ERROR,
"Outbound extension state publisher '%s': Body not set\n",
860 body_type =
strsep(&body_subtype,
"/");
862 ast_log(
LOG_ERROR,
"Outbound extension state publisher '%s': Body '%s' missing type or subtype\n",
868 ast_log(
LOG_ERROR,
"Outbound extension state publisher '%s': '%s' body generator not registered\n",
873 name_size = strlen(name) + 1;
874 body_type_size = strlen(body_type) + 1;
875 body_subtype_size = strlen(body_subtype) + 1;
878 sizeof(*publisher) + name_size + body_type_size + body_subtype_size,
893 ast_log(
LOG_ERROR,
"Outbound extension state publisher '%s': Could not build context filter '%s'\n",
905 ast_log(
LOG_ERROR,
"Outbound extension state publisher '%s': Could not build exten filter '%s'\n",
916 ast_log(
LOG_ERROR,
"Outbound extension state publisher '%s': Could not create datastores container\n",
952 publish_exten_state_serializer =
NULL;
965 ast_log(
LOG_WARNING,
"Unable to create container to store extension state publishers\n");
970 if (!publish_exten_state_serializer) {
1011 .requires =
"res_pjsip,res_pjsip_pubsub,res_pjsip_outbound_publish",
char exten[AST_MAX_EXTENSION]
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
static int load_module(void)
enum ast_extension_states last_exten_state
struct ast_sip_subscription_handler dialog_handler
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.
struct ast_sip_exten_state_data exten_state_data
#define PUBLISHER_BUCKETS
The number of buckets to use for storing publishers.
static void * get_notify_data(struct ast_sip_subscription *sub)
struct ast_sip_event_publisher_handler dialog_publisher
void ast_sip_subscription_get_local_uri(struct ast_sip_subscription *sub, char *buf, size_t size)
Retrieve the local URI for this subscription.
A subscription for extension state.
struct ast_sip_outbound_publish_client * client
ast_extension_states
Extension states.
Asterisk main include file. File version handling, generic pbx functions.
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
const char * presence_message
struct ast_taskprocessor * ast_sip_subscription_get_serializer(struct ast_sip_subscription *sub)
Get the serializer for the subscription.
static void state_changed_destroy(int id, void *data)
static struct ao2_container * publishers
Container of active outbound extension state publishers.
int ast_sip_subscription_is_terminated(const struct ast_sip_subscription *sub)
Get whether the subscription has been terminated or not.
enum ast_presence_state last_presence_state
struct ast_sip_notifier dialog_notifier
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.
The arg parameter is a search key, but is not an object.
Data used to create bodies for NOTIFY/PUBLISH requests.
int ast_extension_state_del(int id, ast_state_cb_type change_cb)
Deletes a state change watcher by ID.
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)
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
static int notify_task(void *obj)
static void exten_state_data_destructor(void *obj)
enum ast_state_cb_update_reason reason
static pj_pool_t * pool
Global memory pool for configuration and timers.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
struct ast_sip_endpoint_subscription_configuration subscription
int ast_sip_register_subscription_handler(struct ast_sip_subscription_handler *handler)
Register a subscription handler.
char remote[PJSIP_MAX_URL_SIZE]
const ast_string_field context
Assume that the ao2_container is already locked.
Structure for a data store type.
static void notify_task_data_destructor(void *obj)
enum ast_extension_states exten_state
static int add_datastore(struct exten_state_subscription *exten_state_sub)
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.
static int exten_state_publisher_hash(const void *obj, const int flags)
Hashing function for extension state publisher.
static struct ast_sip_exten_state_data * exten_state_data_alloc(struct ast_sip_subscription *sip_sub, struct exten_state_subscription *exten_state_sub)
void ast_sip_subscription_get_remote_uri(struct ast_sip_subscription *sub, char *buf, size_t size)
Retrive the remote URI for this subscription.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
static int subscription_established(struct ast_sip_subscription *sub)
const char * ast_sip_subscription_get_resource_name(struct ast_sip_subscription *sub)
Get the name of the subscribed resource.
struct ast_taskprocessor * serializer
#define ao2_alloc_options(data_size, destructor_fn, options)
#define ao2_link_flags(container, obj, flags)
#define ast_strdup(str)
A wrapper for strdup()
Structure for a data store object.
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 int exten_state_publisher_cmp(void *obj, void *arg, int flags)
Comparator function for extension state publisher.
struct ast_sip_subscription * sub
unsigned int context_filter
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.
char context[AST_MAX_CONTEXT]
#define ast_verb(level,...)
struct ast_sip_notifier presence_notifier
struct ao2_container * datastores
static int build_regex(regex_t *regex, const char *text)
struct ao2_container * ast_sip_subscription_get_datastores(const struct ast_sip_subscription *subscription)
Get the datastores container for a subscription.
#define ast_strlen_zero(foo)
static int unload_module(void)
struct ao2_container * ast_datastores_alloc(void)
Allocate a specialized data stores container.
#define DEFAULT_DIALOG_BODY
#define AST_SIP_EXTEN_STATE_DATA
static void exten_state_pub_data_destroy(struct exten_state_pub_data *doomed)
An extension state publisher.
enum ast_extension_states exten_state
const char * ast_sorcery_object_get_extended(const void *object, const char *name)
Get an extended field value from a sorcery object.
#define ast_debug(level,...)
Log a DEBUG message.
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
void ast_sip_unregister_event_publisher_handler(struct ast_sip_event_publisher_handler *handler)
Unregister a publish handler.
static int state_changed(const char *context, const char *exten, struct ast_state_cb_info *info, void *data)
Outbound publish client state information (persists for lifetime of a publish)
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.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
enum ast_presence_state presence_state
enum ast_presence_state presence_state
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.
static int publisher_start(struct ast_sip_outbound_publish *configuration, struct ast_sip_outbound_publish_client *client)
Callbacks that event publisher handlers will define.
#define AST_MAX_EXTENSION
const char * event_name
The name of the event this handler deals with.
#define ao2_ref(o, delta)
const char * ast_extension_state2str(int extension_state)
Return string representation of the state of an extension.
const char * presence_subtype
#define ast_strdupa(s)
duplicate a string in memory from the stack
static struct exten_state_pub_data * exten_state_pub_data_alloc(const char *exten, struct ast_state_cb_info *info)
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
#define ast_malloc(len)
A wrapper for malloc()
#define AST_VECTOR(name, type)
Define a vector structure.
An entity with which Asterisk communicates.
int ast_sip_pubsub_is_body_generator_registered(const char *type, const char *subtype)
Is a body generator registered for the given type/subtype.
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
static struct exten_state_subscription * exten_state_subscription_alloc(struct ast_sip_subscription *sip_sub, struct ast_sip_endpoint *endpoint)
struct ast_sip_subscription_handler presence_handler
static force_inline char * ast_str_to_lower(char *str)
Convert a string to all lower-case.
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.
void ast_sip_subscription_destroy(struct ast_sip_subscription *sub)
Alert the pubsub core that the subscription is ready for destruction.
struct ao2_container * device_state_info
Structure representing a "virtual" SIP subscription.
struct ao2_container * device_state_info
struct ast_sip_event_publisher_handler presence_publisher
char local[PJSIP_MAX_URL_SIZE]
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
struct ast_datastore * ast_sip_subscription_alloc_datastore(const struct ast_datastore_info *info, const char *uid)
Alternative for ast_datastore_alloc()
static int publisher_stop(struct ast_sip_outbound_publish_client *client)
struct ast_taskprocessor * ast_sip_create_serializer(const char *name)
Create a new serializer for SIP tasks.
static struct ast_taskprocessor * publish_exten_state_serializer
userdata associated with baseline taskprocessor test
Outbound publish information.
#define ao2_iterator_next(iter)
#define ao2_alloc(data_size, destructor_fn)
#define DEFAULT_PRESENCE_BODY
static const char ds_name[]
unsigned int exten_filter
#define ast_calloc(num, len)
A wrapper for calloc()
static int regex(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
static void to_ami(struct ast_sip_subscription *sub, struct ast_str **buf)
void ast_sip_unregister_subscription_handler(struct ast_sip_subscription_handler *handler)
Unregister a subscription handler.
Module has failed to load, may be in an inconsistent state.
#define ao2_find(container, arg, flags)
An API for managing task processing threads that can be shared across modules.
struct ast_datastore * ast_sip_subscription_get_datastore(struct ast_sip_subscription *subscription, const char *name)
Retrieve a subscription datastore.
static void exten_state_publisher_destroy(void *obj)
Destructor for extension state publisher.
static void subscription_shutdown(struct ast_sip_subscription *sub)
static char * get_user_agent(const struct ast_sip_subscription *sip_sub)
Support for logging to various files, console and syslog Configuration in file logger.conf.
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
struct ast_sip_endpoint * ast_sip_subscription_get_endpoint(struct ast_sip_subscription *sub)
Get the endpoint that is associated with this subscription.
structure used for presence XML bodies
The arg parameter is an object of the same type.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
static struct exten_state_subscription * get_exten_state_sub(struct ast_sip_subscription *sub)
char * strsep(char **str, const char *delims)
A ast_taskprocessor structure is a singleton by name.
#define INITIAL_LAST_EXTEN_STATE
static void exten_state_subscription_destructor(void *obj)
int ast_sip_subscription_add_datastore(struct ast_sip_subscription *subscription, struct ast_datastore *datastore)
Add a datastore to a SIP subscription.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
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.
void ast_sip_subscription_remove_datastore(struct ast_sip_subscription *subscription, const char *name)
Remove a subscription datastore from the subscription.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
struct stasis_forward * sub
int ast_sip_register_event_publisher_handler(struct ast_sip_event_publisher_handler *handler)
Register an event publisher handler.
Search option field mask.
int ast_extension_state_add(const char *context, const char *exten, ast_state_cb_type change_cb, void *data)
Add watcher for extension states.
struct ao2_container * datastores
#define ASTERISK_GPL_KEY
The text the key() function should return.
const char * default_accept
Default body type defined for the event package this notifier handles.
Asterisk module definitions.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
void * ast_sip_subscription_get_header(const struct ast_sip_subscription *sub, const char *header)
Get a header value for a subscription.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
static struct ast_datastore_info ds_info
struct ast_sip_subscription * sip_sub
const char * ast_presence_state2str(enum ast_presence_state state)
Convert presence state to text string for output.
#define AST_VECTOR_CALLBACK_VOID(vec, callback,...)
Execute a callback on every element in a vector disregarding callback return.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Sorcery Data Access Layer API.
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
static int new_subscribe(struct ast_sip_endpoint *endpoint, const char *resource)
static int exten_state_publisher_cb(void *data)
struct exten_state_subscription * exten_state_sub
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.