[asterisk-commits] kharwell: branch kharwell/pimp_sip_state r388428 - in /team/kharwell/pimp_sip...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Fri May 10 17:16:16 CDT 2013
Author: kharwell
Date: Fri May 10 17:16:14 2013
New Revision: 388428
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=388428
Log:
addressed review issues. still need to look into suggestion about using pjsip for creating pidf body
Modified:
team/kharwell/pimp_sip_state/include/asterisk/res_sip_exten_state.h
team/kharwell/pimp_sip_state/include/asterisk/res_sip_pubsub.h
team/kharwell/pimp_sip_state/res/res_sip_exten_state.c
team/kharwell/pimp_sip_state/res/res_sip_providers/include/res_sip_providers.h
team/kharwell/pimp_sip_state/res/res_sip_providers/res_sip_pidf.c
Modified: team/kharwell/pimp_sip_state/include/asterisk/res_sip_exten_state.h
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_state/include/asterisk/res_sip_exten_state.h?view=diff&rev=388428&r1=388427&r2=388428
==============================================================================
--- team/kharwell/pimp_sip_state/include/asterisk/res_sip_exten_state.h (original)
+++ team/kharwell/pimp_sip_state/include/asterisk/res_sip_exten_state.h Fri May 10 17:16:14 2013
@@ -21,39 +21,51 @@
#include "asterisk/stringfields.h"
#include "asterisk/linkedlists.h"
+
+#include "asterisk/pbx.h"
#include "asterisk/presencestate.h"
-struct ast_exten_state {
+/*!
+ * \brief Contains information pertaining to extension/device state changes.
+ */
+struct ast_sip_exten_state_data {
/*! The extension of the current state change */
const char *exten;
/*! The extension state of the change */
- int exten_state;
+ enum ast_extension_states exten_state;
/*! The presence state of the change */
enum ast_presence_state presence_state;
/*! Current device state information */
- struct ao2_container *device_state;
+ struct ao2_container *device_state_info;
};
/*!
* \brief Extension state provider.
*/
-struct ast_exten_state_provider {
+struct ast_sip_exten_state_provider {
/*! The name of the event this provider registers for */
const char *event_name;
- /*! The type of body this provider accepts */
- const char *accept;
+ /*! Type of the body, ex: "application" */
+ const char *type;
+ /*! Subtype of the body, ex: "pidf+xml" */
+ const char *subtype;
/*!
* \brief Create the body text of a NOTIFY request.
*
* Implementors use this to create body information within the given
* ast_str. That information is then added to the NOTIFY request.
+ *
+ * \param data Current extension state changes
+ * \param local URI of the dialog's local party, e.g. 'from'
+ * \param remote URI of the dialog's remote party, e.g. 'to'
+ * \param body_text Out parameter used to populate the NOTIFY msg body
*/
- void (*create_body)(struct ast_exten_state *data, const char *local,
- const char *remote,struct ast_str **body_text);
+ int (*create_body)(struct ast_sip_exten_state_data *data, const char *local,
+ const char *remote, struct ast_str **body_text);
/*! Next item in the list */
- AST_LIST_ENTRY(ast_exten_state_provider) next;
+ AST_LIST_ENTRY(ast_sip_exten_state_provider) next;
};
#endif
Modified: team/kharwell/pimp_sip_state/include/asterisk/res_sip_pubsub.h
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_state/include/asterisk/res_sip_pubsub.h?view=diff&rev=388428&r1=388427&r2=388428
==============================================================================
--- team/kharwell/pimp_sip_state/include/asterisk/res_sip_pubsub.h (original)
+++ team/kharwell/pimp_sip_state/include/asterisk/res_sip_pubsub.h Fri May 10 17:16:14 2013
@@ -276,7 +276,7 @@
* \retval non-NULL The underlying pjsip_dialog
*/
pjsip_dialog *ast_sip_subscription_get_dlg(struct ast_sip_subscription *sub);
-
+
/*!
* \brief Send a request created via a PJSIP evsub method
*
Modified: team/kharwell/pimp_sip_state/res/res_sip_exten_state.c
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_state/res/res_sip_exten_state.c?view=diff&rev=388428&r1=388427&r2=388428
==============================================================================
--- team/kharwell/pimp_sip_state/res/res_sip_exten_state.c (original)
+++ team/kharwell/pimp_sip_state/res/res_sip_exten_state.c Fri May 10 17:16:14 2013
@@ -37,22 +37,44 @@
#include "asterisk/astobj2.h"
#include "asterisk/sorcery.h"
#include "asterisk/app.h"
-#include "asterisk/pbx.h"
#include "res_sip_providers/include/res_sip_providers.h"
-AST_RWLIST_HEAD_STATIC(providers, ast_exten_state_provider);
-
-static int register_exten_state_provider(struct ast_exten_state_provider *obj)
+#define BODY_SIZE 1024
+#define BODY_TYPE_SIZE 50
+#define EVENT_TYPE_SIZE 50
+
+AST_RWLIST_HEAD_STATIC(providers, ast_sip_exten_state_provider);
+
+static int register_sip_exten_state_provider(struct ast_sip_exten_state_provider *obj)
{
SCOPED_LOCK(lock, &providers, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
+
+ if (ast_strlen_zero(obj->type)) {
+ ast_log(LOG_WARNING, "Type not specified on provider for event %s\n",
+ obj->event_name);
+ return -1;
+ }
+
+ if (ast_strlen_zero(obj->subtype)) {
+ ast_log(LOG_WARNING, "Subtype not specified on provider for event %s\n",
+ obj->event_name);
+ return -1;
+ }
+
+ if (!obj->create_body) {
+ ast_log(LOG_WARNING, "Body handler not specified on provide for event %s\n",
+ obj->event_name);
+ return -1;
+ }
+
AST_RWLIST_INSERT_TAIL(&providers, obj, next);
ast_module_ref(ast_module_info->self);
return 0;
}
-static void unregister_exten_state_provider(struct ast_exten_state_provider *obj)
-{
- struct ast_exten_state_provider *i;
+static void unregister_sip_exten_state_provider(struct ast_sip_exten_state_provider *obj)
+{
+ struct ast_sip_exten_state_provider *i;
SCOPED_LOCK(lock, &providers, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&providers, i, next) {
if (i == obj) {
@@ -68,12 +90,14 @@
* \internal
* \brief Find a provider based on the given accept type.
*/
-static struct ast_exten_state_provider *provider_by_accept(const char *accept)
-{
- struct ast_exten_state_provider *i;
- SCOPED_LOCK(lock, &providers, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
+static struct ast_sip_exten_state_provider *provider_by_accept(const char *accept)
+{
+ struct ast_str *type = ast_str_alloca(BODY_TYPE_SIZE);
+ struct ast_sip_exten_state_provider *i;
+ SCOPED_LOCK(lock, &providers, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK);
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&providers, i, next) {
- if (!strcmp(i->accept, accept)) {
+ ast_str_set(&type, -1, "%s/%s", i->type, i->subtype);
+ if (!strcmp(ast_str_buffer(type), accept)) {
return i;
}
}
@@ -83,18 +107,16 @@
/*!
* \internal
- * \brief Find a provider based on a given message accept type.
+ * \brief Find a provider based on a given message body's type/subtype.
*
* Attempts to locate accept headers in the given request data. If found
* tries to find a provider for the accept type.
*/
-static struct ast_exten_state_provider *provider_by_req(pjsip_rx_data *rdata)
+static struct ast_sip_exten_state_provider *provider_by_req(pjsip_rx_data *rdata)
{
int i;
- char type[50];
pjsip_accept_hdr *hdr = (pjsip_accept_hdr*)
pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_ACCEPT, NULL);
- struct ast_exten_state_provider *res;
if (!hdr) {
ast_log(LOG_WARNING, "No Accept header found in subscribe\n");
@@ -102,6 +124,9 @@
}
for (i = 0; i < hdr->count; ++i) {
+ struct ast_sip_exten_state_provider *res;
+ char type[BODY_TYPE_SIZE];
+
ast_copy_pj_str(type, &hdr->values[i], sizeof(type));
if ((res = provider_by_accept(type))) {
return res;
@@ -139,38 +164,38 @@
* also keeps a pointer to an associated "provider" so when a state changes
* a notify data creator is quickly accessible.
*/
-struct state_sub {
+struct exten_state_subscription {
/*! Watcher id when registering for extension state changes */
int id;
/*! The SIP subscription */
struct ast_sip_subscription *sip_sub;
/*! The notify data creator */
- struct ast_exten_state_provider *provider;
+ struct ast_sip_exten_state_provider *provider;
/*! Context in which subscription looks for updates */
- const char *context;
+ char context[AST_MAX_CONTEXT];
/*! Extension within the context to receive updates from */
char exten[AST_MAX_EXTENSION];
/*! pjsip state for NOTIFY request */
- pjsip_evsub_state state;
+ pjsip_evsub_state evsub_state;
};
-static void state_sub_destructor(void *obj)
-{
- struct state_sub *sub = obj;
+static void exten_state_subscription_destructor(void *obj)
+{
+ struct exten_state_subscription *sub = obj;
ao2_cleanup(sub->sip_sub);
}
/*!
* \internal
- * \brief Find a subscription handler based on a given event type.
+ * \brief Find a subscription handler based on a given message's event type.
*
* Attempts to locate an event header in the given request data. If found
* tries to find a subscription handler for the event type.
*/
static struct ast_sip_subscription_handler *sub_handler_by_req(pjsip_rx_data *rdata)
{
- char type[25];
- pj_str_t event_name = { "Event", 5 };
+ char type[EVENT_TYPE_SIZE];
+ static const pj_str_t event_name = { "Event", 5 };
pjsip_event_hdr *hdr = (pjsip_event_hdr*)
pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &event_name, NULL);
@@ -181,83 +206,73 @@
ast_copy_pj_str(type, &hdr->event_type, sizeof(type));
- return (struct ast_sip_subscription_handler*)
- ao2_find(sub_handlers, type, OBJ_KEY | OBJ_NOLOCK);
-}
-
-/*!
- * \internal
- * \brief Allocates an state_sub object.
+ return ao2_find(sub_handlers, type, OBJ_KEY | OBJ_NOLOCK);
+}
+
+/*!
+ * \internal
+ * \brief Allocates a exten_state_subscription object.
*
* Creates the underlying SIP subscription for the given request. First makes
* sure that there are registered handler and provider objects available.
*/
-static struct state_sub *state_sub_alloc(struct ast_sip_endpoint *endpoint,
- enum ast_sip_subscription_role role, pjsip_rx_data *rdata)
+static struct exten_state_subscription *exten_state_subscription_alloc(
+ struct ast_sip_endpoint *endpoint, enum ast_sip_subscription_role role, pjsip_rx_data *rdata)
{
struct ast_sip_subscription_handler *handler;
- struct state_sub *ssub;
-
- if (!(ssub = ao2_alloc(sizeof(*ssub), state_sub_destructor))) {
+ RAII_VAR(struct exten_state_subscription *, exten_state_sub,
+ ao2_alloc(sizeof(*exten_state_sub), exten_state_subscription_destructor), ao2_cleanup);
+
+ if (!exten_state_sub) {
return NULL;
}
if (!(handler = sub_handler_by_req(rdata))) {
ast_log(LOG_WARNING, "Handler not found for subscription event\n");
- ao2_cleanup(ssub);
- return NULL;
- }
-
- if (!(ssub->provider = provider_by_req(rdata))) {
+ return NULL;
+ }
+
+ if (!(exten_state_sub->provider = provider_by_req(rdata))) {
ast_log(LOG_WARNING, "Unable to locate subscription handler provider\n");
- ao2_cleanup(ssub);
- return NULL;
- }
-
- if (!(ssub->sip_sub = ast_sip_create_subscription(handler, role, endpoint, rdata))) {
+ return NULL;
+ }
+
+ if (!(exten_state_sub->sip_sub = ast_sip_create_subscription(handler, role, endpoint, rdata))) {
ast_log(LOG_WARNING, "Unable to create SIP subscription for endpoint %s\n",
ast_sorcery_object_get_id(endpoint));
- ao2_cleanup(ssub);
- return NULL;
- }
-
- return ssub;
+ return NULL;
+ }
+
+ ao2_ref(exten_state_sub, +1);
+ return exten_state_sub;
}
/*!
* \internal
* \brief Create and send a NOTIFY request to the subscriber.
*/
-static void create_send_notify(struct state_sub *ssub, const char *reason,
- struct ast_exten_state *data)
-{
- RAII_VAR(struct ast_str *, body_text, ast_str_create(1024), ast_free_ptr);
+static void create_send_notify(struct exten_state_subscription *exten_state_sub, const char *reason,
+ struct ast_sip_exten_state_data *exten_state_data)
+{
+ RAII_VAR(struct ast_str *, body_text, ast_str_create(BODY_SIZE), ast_free_ptr);
pj_str_t reason_str;
const pj_str_t *reason_str_ptr = NULL;
pjsip_tx_data *tdata;
pjsip_dialog *dlg;
- struct ast_sip_body body;
- char type[50], local[256], remote[256];
-
- if (!(body.subtype = strchr(ssub->provider->accept, '/'))) {
- ast_log(LOG_WARNING, "Subtype not specified for provider\n");
- return;
- }
-
- ast_copy_string(type, ssub->provider->accept,
- ++body.subtype - ssub->provider->accept);
- body.type = type;
-
- if (!ssub->provider->create_body) {
- ast_log(LOG_WARNING, "Body handler not specified for provider\n");
- return;
- }
-
- dlg = ast_sip_subscription_get_dlg(ssub->sip_sub);
+ char local[256], remote[256];
+ struct ast_sip_body body = {
+ .type = exten_state_sub->provider->type,
+ .subtype = exten_state_sub->provider->subtype
+ };
+
+ dlg = ast_sip_subscription_get_dlg(exten_state_sub->sip_sub);
ast_copy_pj_str(local, &dlg->local.info_str, sizeof(local));
ast_copy_pj_str(remote, &dlg->remote.info_str, sizeof(remote));
- ssub->provider->create_body(data, local, remote, &body_text);
+ if (exten_state_sub->provider->create_body(exten_state_data, local, remote, &body_text)) {
+ return;
+ }
+
body.body_text = ast_str_buffer(body_text);
if (reason) {
@@ -265,8 +280,8 @@
reason_str_ptr = &reason_str;
}
- if (pjsip_evsub_notify(ast_sip_subscription_get_evsub(ssub->sip_sub), ssub->state,
- NULL, reason_str_ptr, &tdata) != PJ_SUCCESS) {
+ if (pjsip_evsub_notify(ast_sip_subscription_get_evsub(exten_state_sub->sip_sub),
+ exten_state_sub->evsub_state, NULL, reason_str_ptr, &tdata) != PJ_SUCCESS) {
ast_log(LOG_WARNING, "Unable to create NOTIFY request\n");
return;
}
@@ -277,7 +292,7 @@
return;
}
- if (ast_sip_subscription_send_request(ssub->sip_sub, tdata) != PJ_SUCCESS) {
+ if (ast_sip_subscription_send_request(exten_state_sub->sip_sub, tdata) != PJ_SUCCESS) {
ast_log(LOG_WARNING, "Unable to send NOTIFY request\n");
pjsip_tx_data_dec_ref(tdata);
}
@@ -287,47 +302,67 @@
* \internal
* \brief Get device state information and send notification to the subscriber.
*/
-static void send_notify(struct state_sub *ssub, const char *reason)
+static void send_notify(struct exten_state_subscription *exten_state_sub, const char *reason)
{
RAII_VAR(struct ao2_container*, info, NULL, ao2_cleanup);
char *subtype = NULL, *message = NULL;
- struct ast_exten_state sdata = {
- .exten = ssub->exten,
- .presence_state = ast_hint_presence_state(NULL, ssub->context,
- ssub->exten, &subtype, &message),
+ struct ast_sip_exten_state_data exten_state_data = {
+ .exten = exten_state_sub->exten,
+ .presence_state = ast_hint_presence_state(NULL, exten_state_sub->context,
+ exten_state_sub->exten, &subtype, &message),
};
- if ((sdata.exten_state = ast_extension_state_extended(
- NULL, ssub->context, ssub->exten, &info)) < 0) {
+ if ((exten_state_data.exten_state = ast_extension_state_extended(
+ NULL, exten_state_sub->context, exten_state_sub->exten, &info)) < 0) {
ast_log(LOG_WARNING, "Unable to get device hint/info for extension %s\n",
- ssub->exten);
+ exten_state_sub->exten);
return;
}
- sdata.device_state = info;
- create_send_notify(ssub, reason, &sdata);
-}
-
-struct serialized_userdata {
- struct ast_exten_state *sdata;
- struct state_sub *ssub;
+ exten_state_data.device_state_info = info;
+ create_send_notify(exten_state_sub, reason, &exten_state_data);
+}
+
+struct notify_task_data {
+ struct ast_sip_exten_state_data exten_state_data;
+ struct exten_state_subscription *exten_state_sub;
};
-static int serialized_notify(void *userdata)
-{
- struct serialized_userdata *udata = userdata;
-
- create_send_notify(udata->ssub, udata->ssub->state == PJSIP_EVSUB_STATE_TERMINATED ?
- "noresource" : NULL, udata->sdata);
-
- ao2_ref(udata->ssub, -1);
- if (udata->sdata->device_state) {
- ao2_ref(udata->sdata->device_state, -1);
- }
-
- ast_free(udata->sdata);
+static void notify_task_data_destructor(void *obj)
+{
+ struct notify_task_data *task_data = obj;
+
+ ao2_ref(task_data->exten_state_sub, -1);
+ if (task_data->exten_state_data.device_state_info) {
+ ao2_ref(task_data->exten_state_data.device_state_info, -1);
+ }
+}
+
+static struct notify_task_data *alloc_notify_task_data(struct exten_state_subscription *exten_state_sub)
+{
+ struct notify_task_data *task_data =
+ ao2_alloc(sizeof(*task_data), notify_task_data_destructor);
+
+ if (!task_data) {
+ ast_log(LOG_WARNING, "Unable to create notify task data\n");
+ return NULL;
+ }
+
+ task_data->exten_state_sub = exten_state_sub;
+ task_data->exten_state_sub->evsub_state = PJSIP_EVSUB_STATE_ACTIVE;
+ task_data->exten_state_data.exten = exten_state_sub->exten;
+
+ return task_data;
+}
+
+static int notify_task(void *obj)
+{
+ RAII_VAR(struct notify_task_data *, task_data, obj, ao2_cleanup);
+
+ create_send_notify(task_data->exten_state_sub, task_data->exten_state_sub->evsub_state ==
+ PJSIP_EVSUB_STATE_TERMINATED ? "noresource" : NULL, &task_data->exten_state_data);
return 0;
}
@@ -337,34 +372,32 @@
*
* Upon state change, send the appropriate notification to the subscriber.
*/
-static int state_changed(char *context, char *exten,
+static int state_changed(char *context, char *exten,
struct ast_state_cb_info *info, void *data)
{
- struct serialized_userdata *udata = ast_malloc(sizeof(*udata));
- struct ast_exten_state *sdata = ast_malloc(sizeof(*sdata));
-
- udata->ssub = data;
- ao2_ref(udata->ssub, +1);
-
- sdata->exten = udata->ssub->exten;
- sdata->exten_state = info->exten_state;
- sdata->presence_state = info->presence_state;
- sdata->device_state = info->device_state_info;
- if (sdata->device_state) {
- ao2_ref(sdata->device_state, +1);
- }
- udata->sdata = sdata;
-
- udata->ssub->state = PJSIP_EVSUB_STATE_ACTIVE;
+ struct notify_task_data *task_data = alloc_notify_task_data(data);
+
+ if (!task_data) {
+ return -1;
+ }
+
+ task_data->exten_state_data.exten_state = info->exten_state;
+ task_data->exten_state_data.presence_state = info->presence_state;
+ task_data->exten_state_data.device_state_info = info->device_state_info;
+
+ if (task_data->exten_state_data.device_state_info) {
+ ao2_ref(task_data->exten_state_data.device_state_info, +1);
+ }
+
if ((info->exten_state == AST_EXTENSION_DEACTIVATED) ||
(info->exten_state == AST_EXTENSION_REMOVED)) {
- udata->ssub->state = PJSIP_EVSUB_STATE_TERMINATED;
- ast_log(LOG_NOTICE, "Watcher for hint %s %s\n", exten, info->exten_state
+ task_data->exten_state_sub->evsub_state = PJSIP_EVSUB_STATE_TERMINATED;
+ ast_log(LOG_WARNING, "Watcher for hint %s %s\n", exten, info->exten_state
== AST_EXTENSION_REMOVED ? "removed" : "deactivated");
}
- ast_sip_push_task(ast_sip_subscription_get_serializer(udata->ssub->sip_sub),
- serialized_notify, udata);
+ ast_sip_push_task(ast_sip_subscription_get_serializer(task_data->exten_state_sub->sip_sub),
+ notify_task, task_data);
return 0;
}
@@ -373,14 +406,14 @@
/*!
* \internal
- * \brief Add a datastore for exten state_sub.
- *
- * Adds the state_sub wrapper object to a datastore so it can be retrieved
+ * \brief Add a datastore for exten exten_state_subscription.
+ *
+ * Adds the exten_state_subscription wrapper object to a datastore so it can be retrieved
* later based upon its association with the ast_sip_subscription.
*/
-static int add_datastore(struct state_sub *sub)
-{
- RAII_VAR(struct ast_datastore *, datastore,
+static int add_datastore(struct exten_state_subscription *sub)
+{
+ RAII_VAR(struct ast_datastore *, datastore,
ast_sip_subscription_alloc_datastore(&ds_info, ds_name), ao2_cleanup);
if (!datastore) {
@@ -394,10 +427,11 @@
/*!
* \internal
- * \brief Get the state_sub object associated with the given
+ * \brief Get the exten_state_subscription object associated with the given
* ast_sip_subscription in the datastore.
*/
-static struct state_sub *from_datastore(struct ast_sip_subscription *sub)
+static struct exten_state_subscription *get_exten_state_sub(
+ struct ast_sip_subscription *sub)
{
RAII_VAR(struct ast_datastore *, datastore,
ast_sip_subscription_get_datastore(sub, ds_name), ao2_cleanup);
@@ -407,11 +441,11 @@
static void subscription_shutdown(struct ast_sip_subscription *sub)
{
- struct state_sub *ssub = from_datastore(sub);
-
- if (ssub) {
- ast_extension_state_del(ssub->id, state_changed);
- ao2_cleanup(ssub);
+ struct exten_state_subscription *exten_state_sub = get_exten_state_sub(sub);
+
+ if (exten_state_sub) {
+ ast_extension_state_del(exten_state_sub->id, state_changed);
+ ao2_cleanup(exten_state_sub);
}
}
@@ -420,85 +454,90 @@
{
pjsip_uri *uri = rdata->msg_info.msg->line.req.uri;
pjsip_sip_uri *sip_uri = pjsip_uri_get_uri(uri);
- struct state_sub *ssub;
+ RAII_VAR(struct exten_state_subscription *, exten_state_sub, NULL, ao2_cleanup);
if (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri)) {
ast_log(LOG_WARNING, "Attempt to SUBSCRIBE to a non-SIP URI\n");
return NULL;
}
- if (!(ssub = state_sub_alloc(endpoint, AST_SIP_NOTIFIER, rdata))) {
- return NULL;
- }
-
- ssub->context = endpoint->context;
- ast_copy_pj_str(ssub->exten, &sip_uri->user, sizeof(ssub->exten));
-
- if ((ssub->id = ast_extension_state_add(ssub->context, ssub->exten,
- state_changed, ssub)) < 0) {
+ if (!(exten_state_sub = exten_state_subscription_alloc(endpoint, AST_SIP_NOTIFIER, rdata))) {
+ return NULL;
+ }
+
+ strncpy(exten_state_sub->context, endpoint->context, AST_MAX_CONTEXT);
+ ast_copy_pj_str(exten_state_sub->exten, &sip_uri->user, sizeof(exten_state_sub->exten));
+
+ if ((exten_state_sub->id = ast_extension_state_add(exten_state_sub->context, exten_state_sub->exten,
+ state_changed, exten_state_sub)) < 0) {
ast_log(LOG_WARNING, "Unable to subscribe extension %s\n",
- ssub->exten);
- ao2_cleanup(ssub);
- return NULL;
- }
-
- if (add_datastore(ssub)) {
+ exten_state_sub->exten);
+ return NULL;
+ }
+
+ /* bump the ref since ast_extension_state_add holds a reference */
+ ao2_ref(exten_state_sub, +1);
+
+ if (add_datastore(exten_state_sub)) {
ast_log(LOG_WARNING, "Unable to add to subscription datastore.\n");
- ao2_cleanup(ssub);
- return NULL;
- }
-
- pjsip_evsub_accept(ast_sip_subscription_get_evsub(ssub->sip_sub),
- rdata, 200, NULL);
-
- ssub->state = PJSIP_EVSUB_STATE_ACTIVE;
- send_notify(ssub, NULL);
- return ssub->sip_sub;
+ return NULL;
+ }
+
+ if (pjsip_evsub_accept(ast_sip_subscription_get_evsub(exten_state_sub->sip_sub),
+ rdata, 200, NULL) != PJ_SUCCESS) {
+ ast_log(LOG_WARNING, "Unable to accept the incoming extension state subscription.\n");
+ return NULL;
+ }
+
+ exten_state_sub->evsub_state = PJSIP_EVSUB_STATE_ACTIVE;
+ send_notify(exten_state_sub, NULL);
+ return exten_state_sub->sip_sub;
}
static void resubscribe(struct ast_sip_subscription *sub, pjsip_rx_data *rdata,
struct ast_sip_subscription_response_data *response_data)
{
- struct state_sub *ssub = from_datastore(sub);
-
- if (ssub) {
- ssub->state = PJSIP_EVSUB_STATE_ACTIVE;
- send_notify(ssub, NULL);
+ struct exten_state_subscription *exten_state_sub = get_exten_state_sub(sub);
+
+ if (exten_state_sub) {
+ exten_state_sub->evsub_state = PJSIP_EVSUB_STATE_ACTIVE;
+ send_notify(exten_state_sub, NULL);
}
}
static void subscription_timeout(struct ast_sip_subscription *sub)
{
- struct state_sub *ssub = from_datastore(sub);
-
- if (!ssub) {
+ struct exten_state_subscription *exten_state_sub = get_exten_state_sub(sub);
+
+ if (!exten_state_sub) {
return;
}
- ast_log(LOG_NOTICE, "Subscription for has timed out.\n");
- ssub->state = PJSIP_EVSUB_STATE_TERMINATED;
- send_notify(ssub, "timeout");
+ ast_verbose(VERBOSE_PREFIX_3 "Subscription for has timed out.\n");
+ exten_state_sub->evsub_state = PJSIP_EVSUB_STATE_TERMINATED;
+ send_notify(exten_state_sub, "timeout");
}
static void subscription_terminated(struct ast_sip_subscription *sub,
pjsip_rx_data *rdata)
{
- struct state_sub *ssub = from_datastore(sub);
-
- if (!ssub) {
+ struct exten_state_subscription *exten_state_sub = get_exten_state_sub(sub);
+
+ if (!exten_state_sub) {
return;
}
- ast_log(LOG_NOTICE, "Subscription has been terminated\n");
- ssub->state = PJSIP_EVSUB_STATE_TERMINATED;
- send_notify(ssub, NULL);
+ ast_verbose(VERBOSE_PREFIX_3 "Subscription has been terminated.\n");
+ exten_state_sub->evsub_state = PJSIP_EVSUB_STATE_TERMINATED;
+ send_notify(exten_state_sub, NULL);
}
/*!
* \internal
* \brief Checks to see if the given value is in the given accept array.
- */
-static int has_accept(const char *accept[], const char *value)
+ * If it isn't return the index to the next usable space in the array.
+ */
+static int in_accept_or_index(const char *accept[], const char *value)
{
int i;
/* search all items or until we find a null/empty element */
@@ -519,10 +558,10 @@
*/
static void add_accept(const char* dest[], const char* accept)
{
- int i = has_accept(dest, accept);
+ int i = in_accept_or_index(dest, accept);
if (i < 0) {
- /* already in list */
+ /* already in accept list */
return;
}
@@ -544,9 +583,9 @@
static struct ast_sip_subscription_handler *create_sub_handler(const char *event_name,
const char *accept)
{
- struct ast_sip_subscription_handler *handler =
+ struct ast_sip_subscription_handler *handler =
ao2_alloc(sizeof(*handler), NULL);
-
+
if (!handler) {
return NULL;
}
@@ -568,7 +607,7 @@
* \brief Create a collection of subscription handlers.
*
* Currently pjsip only allows one event_name to be registered for a given
- * list of body type/application (accept) values. This list of values
+ * list of body type/application (accept) values. This list of values
* cannot be modified once a particular event_name has been registered.
* This means all accept values must be specified before registering a
* subcription handler for an event_name with the pub/sub framework.
@@ -581,23 +620,25 @@
*/
static void create_sub_handlers(void)
{
- struct ast_exten_state_provider *i;
- SCOPED_LOCK(lock, &providers, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
-
+ struct ast_sip_exten_state_provider *i;
+ SCOPED_LOCK(lock, &providers, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK);
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&providers, i, next) {
struct ast_sip_subscription_handler *handler =
ao2_find(sub_handlers, i->event_name, OBJ_NOLOCK | OBJ_KEY);
+ struct ast_str *type = ast_str_alloca(BODY_TYPE_SIZE);
+ ast_str_set(&type, -1, "%s/%s", i->type, i->subtype);
+
if (handler) {
/* if handler exists just assign those accept values to
it from the provider that have not already been set */
- add_accept(handler->accept, i->accept);
+ add_accept(handler->accept, ast_str_buffer(type));
continue;
}
- /* if handler does not exist yet, create it and add to
+ /* if handler does not exist yet, create it and add to
container - note accept values assigned in create */
- if ((handler = create_sub_handler(i->event_name, i->accept))) {
+ if ((handler = create_sub_handler(i->event_name, ast_str_buffer(type)))) {
ao2_link(sub_handlers, handler);
}
}
@@ -644,11 +685,14 @@
}
/* register providers - for now they have to be specifically added here
- because of a limitation in pjsip. if pjsip ever gets modified these
+ because pjsip requires a registered event type and all associated
+ body types be done once (i.e. you can't register 'presence' with
+ 'application/pidf+xml' and then later try to re-register 'presence'
+ along with 'application/xpidf'). if pjsip ever gets modified these
can be moved to their respective module files */
- register_exten_state_provider(ast_sip_pidf_xml_provider());
- register_exten_state_provider(ast_sip_xml_pidf_provider());
- register_exten_state_provider(ast_sip_cpim_pidf_xml_provider());
+ register_sip_exten_state_provider(ast_sip_pidf_xml_provider());
+ register_sip_exten_state_provider(ast_sip_xpidf_xml_provider());
+ register_sip_exten_state_provider(ast_sip_cpim_pidf_xml_provider());
/* create the subscription handlers based upon the providers */
create_sub_handlers();
@@ -666,10 +710,10 @@
ao2_callback(sub_handlers, OBJ_NODATA | OBJ_NOLOCK,
unregister_sub_handlers, NULL);
- /* unregister providers here, again due to pjsip limitation */
- unregister_exten_state_provider(ast_sip_cpim_pidf_xml_provider());
- unregister_exten_state_provider(ast_sip_xml_pidf_provider());
- unregister_exten_state_provider(ast_sip_pidf_xml_provider());
+ /* unregister providers here, again due to pjsip limitation mentioned above */
+ unregister_sip_exten_state_provider(ast_sip_cpim_pidf_xml_provider());
+ unregister_sip_exten_state_provider(ast_sip_xpidf_xml_provider());
+ unregister_sip_exten_state_provider(ast_sip_pidf_xml_provider());
ao2_cleanup(sub_handlers);
Modified: team/kharwell/pimp_sip_state/res/res_sip_providers/include/res_sip_providers.h
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_state/res/res_sip_providers/include/res_sip_providers.h?view=diff&rev=388428&r1=388427&r2=388428
==============================================================================
--- team/kharwell/pimp_sip_state/res/res_sip_providers/include/res_sip_providers.h (original)
+++ team/kharwell/pimp_sip_state/res/res_sip_providers/include/res_sip_providers.h Fri May 10 17:16:14 2013
@@ -35,8 +35,8 @@
added here in order to be accessible by res_sip_extern_state.
*/
-struct ast_exten_state_provider *ast_sip_pidf_xml_provider(void);
-struct ast_exten_state_provider *ast_sip_xml_pidf_provider(void);
-struct ast_exten_state_provider *ast_sip_cpim_pidf_xml_provider(void);
+struct ast_sip_exten_state_provider *ast_sip_pidf_xml_provider(void);
+struct ast_sip_exten_state_provider *ast_sip_xpidf_xml_provider(void);
+struct ast_sip_exten_state_provider *ast_sip_cpim_pidf_xml_provider(void);
#endif
Modified: team/kharwell/pimp_sip_state/res/res_sip_providers/res_sip_pidf.c
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_state/res/res_sip_providers/res_sip_pidf.c?view=diff&rev=388428&r1=388427&r2=388428
==============================================================================
--- team/kharwell/pimp_sip_state/res/res_sip_providers/res_sip_pidf.c (original)
+++ team/kharwell/pimp_sip_state/res/res_sip_providers/res_sip_pidf.c Fri May 10 17:16:14 2013
@@ -25,7 +25,6 @@
***/
#include "asterisk.h"
-#include "asterisk/pbx.h"
#include "asterisk/res_sip_exten_state.h"
#include "include/res_sip_providers.h"
@@ -81,8 +80,8 @@
}
}
-static void pidf_xml_create_body(struct ast_exten_state *data, const char *local,
- const char *remote, struct ast_str **body_text)
+static int pidf_xml_create_body(struct ast_sip_exten_state_data *data, const char *local,
+ const char *remote, struct ast_str **body_text)
{
char *statestring = NULL, *pidfstate = NULL, *pidfnote = NULL;
int local_state;
@@ -112,20 +111,23 @@
ast_str_append(body_text, 0, "<status><basic>%s</basic></status>\n", (local_state != NOTIFY_CLOSED) ? "open" : "closed");
}
ast_str_append(body_text, 0, "</tuple>\n</presence>\n");
+
+ return 0;
}
-static struct ast_exten_state_provider _pidf_xml_provider = {
+static struct ast_sip_exten_state_provider _pidf_xml_provider = {
.event_name = "presence",
- .accept = "application/pidf+xml",
+ .type = "application",
+ .subtype = "pidf+xml",
.create_body = pidf_xml_create_body
};
-struct ast_exten_state_provider *ast_sip_pidf_xml_provider(void)
+struct ast_sip_exten_state_provider *ast_sip_pidf_xml_provider(void)
{
return &_pidf_xml_provider;
}
-static void xml_pidf_create_body(struct ast_exten_state *data, const char *local,
+static int xpidf_xml_create_body(struct ast_sip_exten_state_data *data, const char *local,
const char *remote, struct ast_str **body_text)
{
char *statestring = NULL, *pidfstate = NULL, *pidfnote = NULL;
@@ -148,24 +150,28 @@
(local_state == NOTIFY_OPEN) ? "online" :
(local_state == NOTIFY_INUSE) ? "onthephone" : "offline");
ast_str_append(body_text, 0, "</address>\n</atom>\n</presence>\n");
+
+ return 0;
}
-static struct ast_exten_state_provider _xml_pidf_provider = {
+static struct ast_sip_exten_state_provider _xpidf_xml_provider = {
.event_name = "presence",
- .accept = "application/xml+pidf",
- .create_body = xml_pidf_create_body
+ .type = "application",
+ .subtype = "xpidf+xml",
+ .create_body = xpidf_xml_create_body
};
-struct ast_exten_state_provider *ast_sip_xml_pidf_provider(void) {
- return &_xml_pidf_provider;
+struct ast_sip_exten_state_provider *ast_sip_xpidf_xml_provider(void) {
+ return &_xpidf_xml_provider;
}
-static struct ast_exten_state_provider _cpim_pidf_xml_provider = {
+static struct ast_sip_exten_state_provider _cpim_pidf_xml_provider = {
.event_name = "presence",
- .accept = "application/cpim+pidf+xml",
- .create_body = xml_pidf_create_body
+ .type = "application",
+ .subtype = "cpim-pidf+xml",
+ .create_body = xpidf_xml_create_body
};
-struct ast_exten_state_provider *ast_sip_cpim_pidf_xml_provider(void) {
+struct ast_sip_exten_state_provider *ast_sip_cpim_pidf_xml_provider(void) {
return &_cpim_pidf_xml_provider;
}
More information about the asterisk-commits
mailing list