[asterisk-commits] mmichelson: branch mmichelson/subscription_abstraction r416417 - in /team/mmi...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Jun 16 13:31:25 CDT 2014
Author: mmichelson
Date: Mon Jun 16 13:31:19 2014
New Revision: 416417
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=416417
Log:
Commit more progress.
At this point, res_pjsip_mwi and res_pjsip_pubsub
compile.
The plan for the moment:
1) Fill in stubs in res_pjsip_pubsub.c
2) Test MWI.
3) Correct bugs found from MWI tests.
4) Convert res_pjsip_exten_state.
5) Test presence.
6) Correct bugs found from presence tests.
7) Address remaining TODOs in code.
8) Re-test.
Modified:
team/mmichelson/subscription_abstraction/include/asterisk/res_pjsip_pubsub.h
team/mmichelson/subscription_abstraction/res/res_pjsip_mwi.c
team/mmichelson/subscription_abstraction/res/res_pjsip_pubsub.c
Modified: team/mmichelson/subscription_abstraction/include/asterisk/res_pjsip_pubsub.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/subscription_abstraction/include/asterisk/res_pjsip_pubsub.h?view=diff&rev=416417&r1=416416&r2=416417
==============================================================================
--- team/mmichelson/subscription_abstraction/include/asterisk/res_pjsip_pubsub.h (original)
+++ team/mmichelson/subscription_abstraction/include/asterisk/res_pjsip_pubsub.h Mon Jun 16 13:31:19 2014
@@ -34,6 +34,15 @@
*/
struct ast_sip_publication;
+enum ast_sip_publish_state {
+ /*! Publication has just been initialized */
+ AST_SIP_PUBLISH_STATE_INITIALIZED,
+ /*! Publication is currently active */
+ AST_SIP_PUBLISH_STATE_ACTIVE,
+ /*! Publication has been terminated */
+ AST_SIP_PUBLISH_STATE_TERMINATED,
+};
+
/*!
* \brief Callbacks that publication handlers will define
*/
@@ -47,60 +56,38 @@
/*!
* \brief Called when a PUBLISH to establish a new publication arrives.
*
- * \param endpoint The endpoint from whom the PUBLISH arrived
- * \param rdata The PUBLISH request
- * \retval NULL PUBLISH was not accepted
- * \retval non-NULL New publication
- *
- * \note The callback is expected to send a response for the PUBLISH in success cases.
- */
- struct ast_sip_publication *(*new_publication)(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata);
-
- /*!
- * \brief Called when a PUBLISH for an existing publication arrives.
- *
- * This PUBLISH may be intending to change state or it may be simply renewing
- * the publication since the publication is nearing expiration. The callback
- * is expected to send a response to the PUBLISH.
- *
- * \param pub The publication on which the PUBLISH arrived
- * \param rdata The PUBLISH request
- * \retval 0 Publication was accepted
- * \retval non-zero Publication was denied
- *
- * \note The callback is expected to send a response for the PUBLISH.
- */
- int (*publish_refresh)(struct ast_sip_publication *pub, pjsip_rx_data *rdata);
-
+ * \param endpoint The endpoint from whom the PUBLISH arrived.
+ * \param resource The resource whose state is being published.
+ * \return Response code for the incoming PUBLISH
+ */
+ int (*new_publication)(struct ast_sip_endpoint *endpoint, const char *resource);
/*!
* \brief Called when a publication has reached its expiration.
*/
void (*publish_expire)(struct ast_sip_publication *pub);
-
- /*!
- * \brief Called when a PUBLISH arrives to terminate a publication.
- *
- * \param pub The publication that is terminating
- * \param rdata The PUBLISH request terminating the publication
- *
- * \note The callback is expected to send a response for the PUBLISH.
- */
- void (*publish_termination)(struct ast_sip_publication *pub, pjsip_rx_data *rdata);
-
+ /*!
+ * \brief Published resource has changed states.
+ *
+ * The state parameter can be used to take further action. For instance,
+ * if the state is AST_SIP_PUBLISH_STATE_INITIALIZED, then this is the initial
+ * PUBLISH request. This is a good time to set up datastores on the publication
+ * or any other initial needs.
+ *
+ * AST_SIP_PUBLISH_STATE_TERMINATED is used when the remote end is terminating
+ * its publication. This is a good opportunity to free any resources associated with
+ * the publication.
+ *
+ * AST_SIP_PUBLISH_STATE_ACTIVE is used when a publication that modifies state
+ * arrives.
+ *
+ * \param pub The publication whose state has changed
+ * \param body The body of the inbound PUBLISH
+ * \param state The state of the publication
+ */
+ int (*publication_state_change)(struct ast_sip_publication *pub, pjsip_msg_body *body,
+ enum ast_sip_publish_state state);
AST_LIST_ENTRY(ast_sip_publish_handler) next;
};
-
-/*!
- * \brief Create a new publication
- *
- * Publication handlers should call this when a PUBLISH arrives to establish a new publication.
- *
- * \param endpoint The endpoint from whom the PUBLISHes arrive
- * \param rdata The PUBLISH that established the publication
- * \retval NULL Failed to create a publication
- * \retval non-NULL The newly-created publication
- */
-struct ast_sip_publication *ast_sip_create_publication(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata);
/*!
* \brief Given a publication, get the associated endpoint
@@ -110,29 +97,6 @@
* \retval non-NULL The associated endpoint
*/
struct ast_sip_endpoint *ast_sip_publication_get_endpoint(struct ast_sip_publication *pub);
-
-/*!
- * \brief Create a response to an inbound PUBLISH
- *
- * The created response must be sent using ast_sip_publication_send_response
- *
- * \param pub The publication
- * \param status code The status code to place in the response
- * \param rdata The request to which the response is being made
- * \param[out] tdata The created response
- */
-int ast_sip_publication_create_response(struct ast_sip_publication *pub, int status_code, pjsip_rx_data *rdata,
- pjsip_tx_data **tdata);
-
-/*!
- * \brief Send a response for an inbound PUBLISH
- *
- * \param pub The publication
- * \param rdata The request to which the response was made
- * \param tdata The response to the request
- */
-pj_status_t ast_sip_publication_send_response(struct ast_sip_publication *pub, pjsip_rx_data *rdata,
- pjsip_tx_data *tdata);
/*!
* \brief Register a publish handler
@@ -257,8 +221,7 @@
* \param resource The name of the resource to which the subscription is being made
* \return The response code to send to the SUBSCRIBE.
*/
- struct ast_sip_subscription *(*new_subscribe)(struct ast_sip_endpoint *endpoint,
- const char *resource);
+ int (*new_subscribe)(struct ast_sip_endpoint *endpoint, const char *resource);
/*!
* \brief The subscription is in need of a NOTIFY request.
*
@@ -273,8 +236,10 @@
*
* \param sub The subscription to send the NOTIFY on.
* \param reason The reason why the NOTIFY is being sent.
- */
- void (notify_required)(struct ast_sip_subscription *sub, enum ast_sip_subscription_notify_reason reason);
+ * \retval 0 Success
+ * \retval -1 Failure
+ */
+ int (*notify_required)(struct ast_sip_subscription *sub, enum ast_sip_subscription_notify_reason reason);
};
struct ast_sip_subscriber {
@@ -293,7 +258,7 @@
* \param body The body of the NOTIFY
* \param state The subscription state
*/
- void (*state_change)(struct ast_sip_subscription *sub, const char *body, enum pjsip_evsub_state state);
+ void (*state_change)(struct ast_sip_subscription *sub, pjsip_msg_body *body, enum pjsip_evsub_state state);
};
struct ast_sip_subscription_handler {
@@ -317,7 +282,7 @@
/*! Subscriber callbacks for this handler */
struct ast_sip_subscriber *subscriber;
/*! Notifier callbacks for this handler */
- struct ast_sip_subscriber *notifier;
+ struct ast_sip_notifier *notifier;
AST_LIST_ENTRY(ast_sip_subscription_handler) next;
};
@@ -380,7 +345,9 @@
void ast_sip_subscription_get_remote_uri(struct ast_sip_subscription *sub, char *buf, size_t size);
/*! Terminate an active SIP subscription. */
-void ast_sip_subscription_terminate(struct ast_sip_subscripiton *sub);
+void ast_sip_subscription_terminate(struct ast_sip_subscription *sub);
+
+const char *ast_sip_subscription_get_resource_name(struct ast_sip_subscription *sub);
/*!
* \brief Accept a subscription request
@@ -463,30 +430,17 @@
void ast_sip_subscription_remove_datastore(struct ast_sip_subscription *subscription, const char *name);
/*!
- * \brief Register a notifier
- *
- * \retval 0 Notifier was registered successfully
- * \retval non-zero Notifier was not registered successfully
- */
-int ast_sip_register_notifier(struct ast_sip_notifier *notifier);
-
-/*!
- * \brief Unregister a notifier
- */
-void ast_sip_unregister_notifier(struct ast_sip_notifier *notifier);
-
-/*!
- * \brief Register a subscriber
- *
- * \retval 0 Subscriber was registered successfully
- * \retval non-zero Subscriber was not registered successfully
- */
-int ast_sip_register_subscriber(struct ast_sip_subscriber *subscriber);
-
-/*!
- * \brief Unregister a subscriber
- */
-void ast_sip_unregister_subscriber(struct ast_sip_subscriber *subscriber);
+ * \brief Register a subscription handler
+ *
+ * \retval 0 Handler was registered successfully
+ * \retval non-zero Handler was not registered successfully
+ */
+int ast_sip_register_subscription_handler(struct ast_sip_subscription_handler *handler);
+
+/*!
+ * \brief Unregister a subscription handler
+ */
+void ast_sip_unregister_subscription_handler(struct ast_sip_subscription_handler *handler);
/*!
* \brief Pubsub body generator
Modified: team/mmichelson/subscription_abstraction/res/res_pjsip_mwi.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/subscription_abstraction/res/res_pjsip_mwi.c?view=diff&rev=416417&r1=416416&r2=416417
==============================================================================
--- team/mmichelson/subscription_abstraction/res/res_pjsip_mwi.c (original)
+++ team/mmichelson/subscription_abstraction/res/res_pjsip_mwi.c Mon Jun 16 13:31:19 2014
@@ -49,31 +49,23 @@
#define MWI_SUBTYPE "simple-message-summary"
static void mwi_subscription_shutdown(struct ast_sip_subscription *sub);
-static struct ast_sip_subscription *mwi_new_subscribe(struct ast_sip_endpoint *endpoint,
- pjsip_rx_data *rdata);
-static void mwi_resubscribe(struct ast_sip_subscription *sub, pjsip_rx_data *rdata,
- struct ast_sip_subscription_response_data *response_data);
-static void mwi_subscription_timeout(struct ast_sip_subscription *sub);
-static void mwi_subscription_terminated(struct ast_sip_subscription *sub, pjsip_rx_data *rdata);
-static void mwi_notify_response(struct ast_sip_subscription *sub, pjsip_rx_data *rdata);
-static void mwi_notify_request(struct ast_sip_subscription *sub, pjsip_rx_data *rdata,
- struct ast_sip_subscription_response_data *response_data);
-static int mwi_refresh_subscription(struct ast_sip_subscription *sub);
static void mwi_to_ami(struct ast_sip_subscription *sub, struct ast_str **buf);
+static int mwi_new_subscribe(struct ast_sip_endpoint *endpoint,
+ const char *resource);
+static int mwi_notify_required(struct ast_sip_subscription *sip_sub,
+ enum ast_sip_subscription_notify_reason reason);
+
+static struct ast_sip_notifier mwi_notifier = {
+ .default_accept = MWI_TYPE"/"MWI_SUBTYPE,
+ .new_subscribe = mwi_new_subscribe,
+ .notify_required = mwi_notify_required,
+};
static struct ast_sip_subscription_handler mwi_handler = {
.event_name = "message-summary",
- .accept = { MWI_TYPE"/"MWI_SUBTYPE, },
- .default_accept = MWI_TYPE"/"MWI_SUBTYPE,
.subscription_shutdown = mwi_subscription_shutdown,
- .new_subscribe = mwi_new_subscribe,
- .resubscribe = mwi_resubscribe,
- .subscription_timeout = mwi_subscription_timeout,
- .subscription_terminated = mwi_subscription_terminated,
- .notify_response = mwi_notify_response,
- .notify_request = mwi_notify_request,
- .refresh_subscription = mwi_refresh_subscription,
.to_ami = mwi_to_ami,
+ .notifier = &mwi_notifier,
};
/*!
@@ -202,7 +194,7 @@
}
static struct mwi_subscription *mwi_subscription_alloc(struct ast_sip_endpoint *endpoint,
- enum ast_sip_subscription_role role, unsigned int is_solicited, pjsip_rx_data *rdata)
+ unsigned int is_solicited, struct ast_sip_subscription *sip_sub)
{
struct mwi_subscription *sub;
const char *endpoint_id = ast_sorcery_object_get_id(endpoint);
@@ -216,6 +208,7 @@
/* Safe strcpy */
strcpy(sub->id, endpoint_id);
+
/* Unsolicited MWI doesn't actually result in a SIP subscription being
* created. This is because a SIP subscription associates with a dialog.
* Most devices expect unsolicited MWI NOTIFYs to appear out of dialog. If
@@ -224,13 +217,7 @@
* state not being updated on the device
*/
if (is_solicited) {
- sub->sip_sub = ast_sip_create_subscription(&mwi_handler,
- role, endpoint, rdata);
- if (!sub->sip_sub) {
- ast_log(LOG_WARNING, "Unable to create MWI SIP subscription for endpoint %s\n", sub->id);
- ao2_cleanup(sub);
- return NULL;
- }
+ sub->sip_sub = ao2_bump(sip_sub);
}
sub->stasis_subs = ao2_container_alloc(STASIS_BUCKETS, stasis_sub_hash, stasis_sub_cmp);
@@ -314,7 +301,6 @@
struct mwi_subscription *sub;
struct ast_sip_endpoint *endpoint;
pjsip_evsub_state state;
- const char *reason;
const struct ast_sip_body *body;
};
@@ -324,7 +310,6 @@
struct mwi_subscription *sub = mwi_data->sub;
struct ast_sip_endpoint *endpoint = mwi_data->endpoint;
pjsip_evsub_state state = mwi_data->state;
- const char *reason = mwi_data->reason;
const struct ast_sip_body *body = mwi_data->body;
struct ast_sip_contact *contact = obj;
const char *state_name;
@@ -358,9 +343,6 @@
sub_state = pjsip_sub_state_hdr_create(tdata->pool);
pj_cstr(&sub_state->sub_state, state_name);
- if (reason) {
- pj_cstr(&sub_state->reason_param, reason);
- }
pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) sub_state);
event = pjsip_event_hdr_create(tdata->pool);
@@ -374,13 +356,15 @@
return 0;
}
-static void send_unsolicited_mwi_notify(struct mwi_subscription *sub, pjsip_evsub_state state, const char *reason,
- struct ast_sip_body *body)
+static void send_unsolicited_mwi_notify(struct mwi_subscription *sub,
+ struct ast_sip_message_accumulator *counter)
{
RAII_VAR(struct ast_sip_endpoint *, endpoint, ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(),
"endpoint", sub->id), ao2_cleanup);
char *endpoint_aors;
char *aor_name;
+ struct ast_sip_body body;
+ struct ast_str *body_text;
if (!endpoint) {
ast_log(LOG_WARNING, "Unable to send unsolicited MWI to %s because endpoint does not exist\n",
@@ -393,7 +377,27 @@
return;
}
+ body.type = MWI_TYPE;
+ body.subtype = MWI_SUBTYPE;
+
+ body_text = ast_str_create(64);
+
+ if (!body_text) {
+ return;
+ }
+
+ if (ast_sip_pubsub_generate_body_content(body.type, body.subtype, counter, &body_text)) {
+ ast_log(LOG_WARNING, "Unable to generate SIP MWI NOTIFY body.\n");
+ ast_free(body_text);
+ return;
+ }
+
+ body.body_text = ast_str_buffer(body_text);
+
endpoint_aors = ast_strdupa(endpoint->aors);
+
+ ast_debug(5, "Sending unsolicited MWI NOTIFY to endpoint %s, new messages: %d, old messages: %d\n",
+ sub->id, counter->new_msgs, counter->old_msgs);
while ((aor_name = strsep(&endpoint_aors, ","))) {
RAII_VAR(struct ast_sip_aor *, aor, ast_sip_location_retrieve_aor(aor_name), ao2_cleanup);
@@ -401,9 +405,7 @@
struct unsolicited_mwi_data mwi_data = {
.sub = sub,
.endpoint = endpoint,
- .state = state,
- .reason = reason,
- .body = body,
+ .body = &body,
};
if (!aor) {
@@ -419,63 +421,25 @@
ao2_callback(contacts, OBJ_NODATA, send_unsolicited_mwi_notify_to_contact, &mwi_data);
}
-}
-
-static void send_mwi_notify(struct mwi_subscription *sub, pjsip_evsub_state state, const char *reason)
-{
- const pj_str_t *reason_str_ptr = NULL;
+
+ ast_free(body_text);
+}
+
+static void send_mwi_notify(struct mwi_subscription *sub)
+{
struct ast_sip_message_accumulator counter = {
.old_msgs = 0,
.new_msgs = 0,
};
- RAII_VAR(struct ast_str *, body_text, ast_str_create(64), ast_free_ptr);
- pjsip_tx_data *tdata;
- pj_str_t reason_str;
- struct ast_sip_body body;
-
- body.type = sub->is_solicited ?
- ast_sip_subscription_get_body_type(sub->sip_sub) :
- MWI_TYPE;
-
- body.subtype = sub->is_solicited ?
- ast_sip_subscription_get_body_subtype(sub->sip_sub) :
- MWI_SUBTYPE;
ao2_callback(sub->stasis_subs, OBJ_NODATA, get_message_count, &counter);
- if (reason) {
- pj_cstr(&reason_str, reason);
- reason_str_ptr = &reason_str;
- }
-
- if (ast_sip_pubsub_generate_body_content(body.type, body.subtype, &counter, &body_text)) {
- ast_log(LOG_WARNING, "Unable to generate SIP MWI NOTIFY body.\n");
+ if (sub->is_solicited) {
+ ast_sip_subscription_notify(sub->sip_sub, &counter);
return;
}
- body.body_text = ast_str_buffer(body_text);
-
- ast_debug(5, "Sending %s MWI NOTIFY to endpoint %s, new messages: %d, old messages: %d\n",
- sub->is_solicited ? "solicited" : "unsolicited", sub->id, counter.new_msgs,
- counter.old_msgs);
-
- if (sub->is_solicited) {
- if (pjsip_evsub_notify(ast_sip_subscription_get_evsub(sub->sip_sub),
- state, NULL, reason_str_ptr, &tdata) != PJ_SUCCESS) {
- ast_log(LOG_WARNING, "Unable to create MWI NOTIFY request to %s.\n", sub->id);
- return;
- }
- if (ast_sip_add_body(tdata, &body)) {
- ast_log(LOG_WARNING, "Unable to add body to MWI NOTIFY request\n");
- return;
- }
- if (ast_sip_subscription_send_request(sub->sip_sub, tdata) != PJ_SUCCESS) {
- ast_log(LOG_WARNING, "Unable to send MWI NOTIFY request to %s\n", sub->id);
- return;
- }
- } else {
- send_unsolicited_mwi_notify(sub, state, reason, &body);
- }
+ send_unsolicited_mwi_notify(sub, &counter);
}
static int unsubscribe_stasis(void *obj, void *arg, int flags)
@@ -620,10 +584,9 @@
}
static struct mwi_subscription *mwi_create_subscription(
- struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
-{
- struct mwi_subscription *sub = mwi_subscription_alloc(
- endpoint, AST_SIP_NOTIFIER, 1, rdata);
+ struct ast_sip_endpoint *endpoint, struct ast_sip_subscription *sip_sub)
+{
+ struct mwi_subscription *sub = mwi_subscription_alloc(endpoint, 1, sip_sub);
if (!sub) {
return NULL;
@@ -640,7 +603,7 @@
}
static struct mwi_subscription *mwi_subscribe_single(
- struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, const char *name)
+ struct ast_sip_endpoint *endpoint, struct ast_sip_subscription *sip_sub, const char *name)
{
RAII_VAR(struct ast_sip_aor *, aor,
ast_sip_location_retrieve_aor(name), ao2_cleanup);
@@ -662,7 +625,7 @@
return NULL;
}
- if (!(sub = mwi_create_subscription(endpoint, rdata))) {
+ if (!(sub = mwi_create_subscription(endpoint, sip_sub))) {
return NULL;
}
@@ -671,7 +634,7 @@
}
static struct mwi_subscription *mwi_subscribe_all(
- struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
+ struct ast_sip_endpoint *endpoint, struct ast_sip_subscription *sip_sub)
{
struct mwi_subscription *sub;
@@ -679,7 +642,7 @@
return NULL;
}
- sub = mwi_create_subscription(endpoint, rdata);
+ sub = mwi_create_subscription(endpoint, sip_sub);
if (!sub) {
return NULL;
@@ -689,106 +652,67 @@
return sub;
}
-static struct ast_sip_subscription *mwi_new_subscribe(struct ast_sip_endpoint *endpoint,
- pjsip_rx_data *rdata)
+static int mwi_new_subscribe(struct ast_sip_endpoint *endpoint,
+ const char *resource)
+{
+ /* The MWI notifier does not care what resource is being subscribed to. We'll happily
+ * accept whatever resource is thrown our way.
+ */
+ return 200;
+}
+
+static int mwi_initial_subscription(struct ast_sip_subscription *sip_sub)
{
/* It's not obvious here, but the reference(s) to this subscription,
* once this function exits, is held by the stasis subscription(s)
* created in mwi_stasis_subscription_alloc()
*/
- RAII_VAR(struct mwi_subscription *, sub, NULL, ao2_cleanup);
- pjsip_uri *ruri = rdata->msg_info.msg->line.req.uri;
- pjsip_sip_uri *sip_ruri;
- char aor_name[80];
-
- if (!PJSIP_URI_SCHEME_IS_SIP(ruri) && !PJSIP_URI_SCHEME_IS_SIPS(ruri)) {
- ast_log(LOG_WARNING, "Attempt to SUBSCRIBE to a non-SIP URI\n");
- return NULL;
- }
- sip_ruri = pjsip_uri_get_uri(ruri);
- ast_copy_pj_str(aor_name, &sip_ruri->user, sizeof(aor_name));
+ const char *resource = ast_sip_subscription_get_resource_name(sip_sub);
+ struct mwi_subscription *sub;
+ struct ast_sip_endpoint *endpoint = ast_sip_subscription_get_endpoint(sip_sub);
/* no aor in uri? subscribe to all on endpoint */
- if (!(sub = ast_strlen_zero(aor_name) ? mwi_subscribe_all(endpoint, rdata) :
- mwi_subscribe_single(endpoint, rdata, aor_name))) {
- return NULL;
- }
-
- ast_sip_subscription_accept(sub->sip_sub, rdata, 200);
- send_mwi_notify(sub, PJSIP_EVSUB_STATE_ACTIVE, NULL);
-
- return sub->sip_sub;
-}
-
-static void mwi_resubscribe(struct ast_sip_subscription *sub,
- pjsip_rx_data *rdata, struct ast_sip_subscription_response_data *response_data)
+ if (ast_strlen_zero(resource)) {
+ sub = mwi_subscribe_all(endpoint, sip_sub);
+ } else {
+ sub = mwi_subscribe_single(endpoint, sip_sub, resource);
+ }
+
+ if (!sub) {
+ return -1;
+ }
+
+ send_mwi_notify(sub);
+ ao2_cleanup(sub);
+
+ return 0;
+}
+
+static int mwi_notify_required(struct ast_sip_subscription *sip_sub,
+ enum ast_sip_subscription_notify_reason reason)
{
struct mwi_subscription *mwi_sub;
- pjsip_evsub_state state;
- pjsip_evsub *evsub;
- RAII_VAR(struct ast_datastore *, mwi_datastore,
- ast_sip_subscription_get_datastore(sub, "MWI datastore"), ao2_cleanup);
-
- if (!mwi_datastore) {
- return;
- }
-
- mwi_sub = mwi_datastore->data;
- evsub = ast_sip_subscription_get_evsub(sub);
- state = pjsip_evsub_get_state(evsub);
-
- send_mwi_notify(mwi_sub, state, NULL);
-}
-
-static void mwi_subscription_timeout(struct ast_sip_subscription *sub)
-{
- struct mwi_subscription *mwi_sub;
- RAII_VAR(struct ast_datastore *, mwi_datastore,
- ast_sip_subscription_get_datastore(sub, "MWI datastore"), ao2_cleanup);
-
- if (!mwi_datastore) {
- return;
- }
-
-
- mwi_sub = mwi_datastore->data;
-
- ast_log(LOG_NOTICE, "MWI subscription for %s has timed out.\n", mwi_sub->id);
-
- send_mwi_notify(mwi_sub, PJSIP_EVSUB_STATE_TERMINATED, "timeout");
-}
-
-static void mwi_subscription_terminated(struct ast_sip_subscription *sub, pjsip_rx_data *rdata)
-{
- struct mwi_subscription *mwi_sub;
- RAII_VAR(struct ast_datastore *, mwi_datastore,
- ast_sip_subscription_get_datastore(sub, "MWI datastore"), ao2_cleanup);
-
- if (!mwi_datastore) {
- return;
- }
-
- mwi_sub = mwi_datastore->data;
-
- ast_log(LOG_NOTICE, "MWI subscription for %s has been terminated\n", mwi_sub->id);
-
- send_mwi_notify(mwi_sub, PJSIP_EVSUB_STATE_TERMINATED, NULL);
-}
-
-static void mwi_notify_response(struct ast_sip_subscription *sub, pjsip_rx_data *rdata)
-{
- /* We don't really care about NOTIFY responses for the moment */
-}
-
-static void mwi_notify_request(struct ast_sip_subscription *sub, pjsip_rx_data *rdata,
- struct ast_sip_subscription_response_data *response_data)
-{
- ast_log(LOG_WARNING, "Received an MWI NOTIFY request? This should not happen\n");
-}
-
-static int mwi_refresh_subscription(struct ast_sip_subscription *sub)
-{
- ast_log(LOG_WARNING, "Being told to refresh an MWI subscription? This should not happen\n");
+ struct ast_datastore *mwi_datastore;
+
+ switch (reason) {
+ case AST_SIP_SUBSCRIPTION_NOTIFY_REASON_STARTED:
+ return mwi_initial_subscription(sip_sub);
+ case AST_SIP_SUBSCRIPTION_NOTIFY_REASON_RENEWED:
+ case AST_SIP_SUBSCRIPTION_NOTIFY_REASON_TERMINATED:
+ case AST_SIP_SUBSCRIPTION_NOTIFY_REASON_OTHER:
+ mwi_datastore = ast_sip_subscription_get_datastore(sip_sub, "MWI datastore");
+
+ if (!mwi_datastore) {
+ return -1;
+ }
+
+ mwi_sub = mwi_datastore->data;
+
+ send_mwi_notify(mwi_sub);
+ ao2_cleanup(mwi_datastore);
+ break;
+ }
+
return 0;
}
@@ -834,7 +758,7 @@
{
struct mwi_subscription *mwi_sub = userdata;
- send_mwi_notify(mwi_sub, PJSIP_EVSUB_STATE_ACTIVE, NULL);
+ send_mwi_notify(mwi_sub);
ao2_ref(mwi_sub, -1);
return 0;
}
@@ -885,7 +809,7 @@
}
if (endpoint->subscription.mwi.aggregate) {
- aggregate_sub = mwi_subscription_alloc(endpoint, AST_SIP_NOTIFIER, 0, NULL);
+ aggregate_sub = mwi_subscription_alloc(endpoint, 0, NULL);
if (!aggregate_sub) {
return 0;
}
@@ -894,7 +818,7 @@
mailboxes = ast_strdupa(endpoint->subscription.mwi.mailboxes);
while ((mailbox = strsep(&mailboxes, ","))) {
struct mwi_subscription *sub = aggregate_sub ?:
- mwi_subscription_alloc(endpoint, AST_SIP_SUBSCRIBER, 0, NULL);
+ mwi_subscription_alloc(endpoint, 0, NULL);
RAII_VAR(struct mwi_stasis_subscription *, mwi_stasis_sub,
mwi_stasis_subscription_alloc(mailbox, sub), ao2_cleanup);
if (mwi_stasis_sub) {
Modified: team/mmichelson/subscription_abstraction/res/res_pjsip_pubsub.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/subscription_abstraction/res/res_pjsip_pubsub.c?view=diff&rev=416417&r1=416416&r2=416417
==============================================================================
--- team/mmichelson/subscription_abstraction/res/res_pjsip_pubsub.c (original)
+++ team/mmichelson/subscription_abstraction/res/res_pjsip_pubsub.c Mon Jun 16 13:31:19 2014
@@ -319,6 +319,16 @@
AST_RWLIST_HEAD_STATIC(body_generators, ast_sip_pubsub_body_generator);
AST_RWLIST_HEAD_STATIC(body_supplements, ast_sip_pubsub_body_supplement);
+static pjsip_evsub *sip_subscription_get_evsub(struct ast_sip_subscription *sub)
+{
+ return sub->pants.real->evsub;
+}
+
+static pjsip_dialog *sip_subscription_get_dlg(struct ast_sip_subscription *sub)
+{
+ return sub->pants.real->dlg;
+}
+
/*! \brief Destructor for subscription persistence */
static void subscription_persistence_destroy(void *obj)
{
@@ -345,12 +355,14 @@
struct subscription_persistence *persistence = ast_sorcery_alloc(ast_sip_get_sorcery(),
"subscription_persistence", NULL);
+ pjsip_dialog *dlg = sip_subscription_get_dlg(sub);
+
if (!persistence) {
return NULL;
}
persistence->endpoint = ast_strdup(ast_sorcery_object_get_id(sub->endpoint));
- ast_copy_pj_str(tag, &sub->dlg->local.info->tag, sizeof(tag));
+ ast_copy_pj_str(tag, &dlg->local.info->tag, sizeof(tag));
persistence->tag = ast_strdup(tag);
ast_sorcery_create(ast_sip_get_sorcery(), persistence);
@@ -361,11 +373,14 @@
static void subscription_persistence_update(struct ast_sip_subscription *sub,
pjsip_rx_data *rdata)
{
+ pjsip_dialog *dlg;
+
if (!sub->persistence) {
return;
}
- sub->persistence->cseq = sub->dlg->local.cseq;
+ dlg = sip_subscription_get_dlg(sub);
+ sub->persistence->cseq = dlg->local.cseq;
if (rdata) {
int expires;
@@ -445,12 +460,15 @@
/* If a SUBSCRIBE contains no Accept headers, then we must assume that
* the default accept type for the event package is to be used.
*/
- ast_copy_string(accept[0], handler->default_accept, sizeof(accept[0]));
+ ast_copy_string(accept[0], handler->notifier->default_accept, sizeof(accept[0]));
num_accept_headers = 1;
}
return find_body_generator(accept, num_accept_headers);
}
+
+static struct ast_sip_subscription *notifier_create_subscription(const struct ast_sip_subscription_handler *handler,
+ struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata);
/*! \brief Callback function to perform the actual recreation of a subscription */
static int subscription_persistence_recreate(void *obj, void *arg, int flags)
@@ -465,6 +483,8 @@
struct ast_sip_pubsub_body_generator *generator;
int resp;
char *resource;
+ size_t resource_size;
+ pjsip_sip_uri *request_uri;
/* If this subscription has already expired remove it */
if (ast_tvdiff_ms(persistence->expires, ast_tvnow()) <= 0) {
@@ -490,6 +510,11 @@
ast_sorcery_delete(ast_sip_get_sorcery(), persistence);
return 0;
}
+
+ request_uri = pjsip_uri_get_uri(rdata.msg_info.msg->line.req.uri);
+ resource_size = pj_strlen(&request_uri->user) + 1;
+ resource = alloca(resource_size);
+ ast_copy_pj_str(resource, &request_uri->user, resource_size);
/* Update the expiration header with the new expiration */
expires_header = pjsip_msg_find_hdr(rdata.msg_info.msg, PJSIP_H_EXPIRES, rdata.msg_info.msg->hdr.next);
@@ -520,8 +545,9 @@
ast_sip_mod_data_set(rdata.tp_info.pool, rdata.endpt_info.mod_data,
pubsub_module.id, MOD_DATA_PERSISTENCE, persistence);
- sub = handler->new_subscribe(endpoint, &rdata);
- if (sub) {
+ resp = handler->notifier->new_subscribe(endpoint, resource);
+ if (resp >= 200 && resp < 300) {
+ sub = notifier_create_subscription(handler, endpoint, &rdata);
sub->persistence = ao2_bump(persistence);
subscription_persistence_update(sub, &rdata);
} else {
@@ -633,11 +659,11 @@
ast_str_append(buf, 0, "Endpoint: %s\r\n",
ast_sorcery_object_get_id(sub->endpoint));
- ast_copy_pj_str(str, &sub->dlg->call_id->id, sizeof(str));
+ ast_copy_pj_str(str, &sip_subscription_get_dlg(sub)->call_id->id, sizeof(str));
ast_str_append(buf, 0, "Callid: %s\r\n", str);
ast_str_append(buf, 0, "State: %s\r\n", pjsip_evsub_get_state_name(
- ast_sip_subscription_get_evsub(sub)));
+ sip_subscription_get_evsub(sub)));
ast_callerid_merge(str, sizeof(str),
S_COR(id->self.name.valid, id->self.name.str, NULL),
@@ -690,8 +716,8 @@
* subscription is destroyed so that we can guarantee that our attempt to
* remove the serializer will be successful.
*/
- ast_sip_dialog_set_serializer(sub->dlg, NULL);
- pjsip_dlg_dec_session(sub->dlg, &pubsub_module);
+ ast_sip_dialog_set_serializer(sip_subscription_get_dlg(sub), NULL);
+ pjsip_dlg_dec_session(sip_subscription_get_dlg(sub), &pubsub_module);
return 0;
}
@@ -709,11 +735,12 @@
ao2_cleanup(sub->datastores);
ao2_cleanup(sub->endpoint);
- if (sub->dlg) {
+ if (sip_subscription_get_dlg(sub)) {
ast_sip_push_task_synchronous(NULL, subscription_remove_serializer, sub);
}
ast_taskprocessor_unreference(sub->serializer);
}
+
static void pubsub_on_evsub_state(pjsip_evsub *sub, pjsip_event *event);
static void pubsub_on_rx_refresh(pjsip_evsub *sub, pjsip_rx_data *rdata,
@@ -732,22 +759,9 @@
.on_server_timeout = pubsub_on_server_timeout,
};
-static pjsip_evsub *allocate_evsub(const char *event, enum ast_sip_subscription_role role,
- struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pjsip_dialog *dlg)
-{
- pjsip_evsub *evsub;
- if (role == AST_SIP_NOTIFIER) {
- } else {
- pj_str_t pj_event;
- pj_cstr(&pj_event, event);
- pjsip_evsub_create_uac(dlg, &pubsub_cb, &pj_event, 0, &evsub);
- }
- return evsub;
-}
-
/* XXX TODO There is a lot of repeated code between the two subscription creation functions. */
-struct ast_sip_subscription *notifier_create_subscription(const struct ast_sip_subscription_handler *handler,
+static struct ast_sip_subscription *notifier_create_subscription(const struct ast_sip_subscription_handler *handler,
struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
{
struct ast_sip_subscription *sub = ao2_alloc(sizeof(*sub), subscription_destructor);
@@ -770,6 +784,7 @@
sub->body_generator = ast_sip_mod_data_get(rdata->endpt_info.mod_data,
pubsub_module.id, MOD_DATA_BODY_GENERATOR);
sub->role = AST_SIP_NOTIFIER;
+ sub->type = SIP_SUBSCRIPTION_REAL;
dlg = ast_sip_create_dialog_uas(endpoint, rdata);
if (!dlg) {
ast_log(LOG_WARNING, "Unable to create dialog for SIP subscription\n");
@@ -789,14 +804,14 @@
dlg->remote.cseq = persistence->cseq;
}
- pjsip_evsub_create_uas(dlg, &pubsub_cb, rdata, 0, &sub->evsub);
+ pjsip_evsub_create_uas(dlg, &pubsub_cb, rdata, 0, &sub->pants.real->evsub);
/* We keep a reference to the dialog until our subscription is destroyed. See
* the subscription_destructor for more details
*/
pjsip_dlg_inc_session(dlg, &pubsub_module);
- sub->dlg = dlg;
+ sub->pants.real->dlg = dlg;
ast_sip_dialog_set_serializer(dlg, sub->serializer);
- pjsip_evsub_set_mod_data(sub->evsub, pubsub_module.id, sub);
+ pjsip_evsub_set_mod_data(sip_subscription_get_evsub(sub), pubsub_module.id, sub);
sub->endpoint = ao2_bump(endpoint);
sub->handler = handler;
@@ -826,6 +841,7 @@
return NULL;
}
sub->role = AST_SIP_SUBSCRIBER;
+ sub->type = SIP_SUBSCRIPTION_REAL;
contact = ast_sip_location_retrieve_contact_from_aor_list(endpoint->aors);
if (!contact || ast_strlen_zero(contact->uri)) {
ast_log(LOG_WARNING, "No contacts configured for endpoint %s. Unable to create SIP subsription\n",
@@ -843,14 +859,14 @@
}
pj_cstr(&event, handler->event_name);
- pjsip_evsub_create_uac(dlg, &pubsub_cb, &event, 0, &sub->evsub);
+ pjsip_evsub_create_uac(dlg, &pubsub_cb, &event, 0, &sub->pants.real->evsub);
/* We keep a reference to the dialog until our subscription is destroyed. See
* the subscription_destructor for more details
*/
pjsip_dlg_inc_session(dlg, &pubsub_module);
- sub->dlg = dlg;
+ sub->pants.real->dlg = dlg;
ast_sip_dialog_set_serializer(dlg, sub->serializer);
- pjsip_evsub_set_mod_data(sub->evsub, pubsub_module.id, sub);
+ pjsip_evsub_set_mod_data(sip_subscription_get_evsub(sub), pubsub_module.id, sub);
ao2_ref(endpoint, +1);
sub->endpoint = endpoint;
sub->handler = handler;
@@ -874,14 +890,26 @@
return sub->serializer;
}
-pjsip_evsub *ast_sip_subscription_get_evsub(struct ast_sip_subscription *sub)
-{
- return sub->evsub;
-}
-
-pjsip_dialog *ast_sip_subscription_get_dlg(struct ast_sip_subscription *sub)
-{
- return sub->dlg;
+int ast_sip_subscription_notify(struct ast_sip_subscription *sub, void *notify_data)
+{
+ /* XXX STUB */
+ return 0;
+}
+
+void ast_sip_subscription_get_local_uri(struct ast_sip_subscription *sub, char *buf, size_t size)
+{
+ /* XXX STUB */
+}
+
+void ast_sip_subscription_get_remote_uri(struct ast_sip_subscription *sub, char *buf, size_t size)
+{
+ /* XXX STUB */
+}
+
+const char *ast_sip_subscription_get_resource_name(struct ast_sip_subscription *sub)
+{
+ /* XXX STUB */
+ return NULL;
}
int ast_sip_subscription_accept(struct ast_sip_subscription *sub, pjsip_rx_data *rdata, int response)
@@ -891,7 +919,7 @@
return 0;
}
- return pjsip_evsub_accept(ast_sip_subscription_get_evsub(sub), rdata, response, NULL) == PJ_SUCCESS ? 0 : -1;
+ return pjsip_evsub_accept(sip_subscription_get_evsub(sub), rdata, response, NULL) == PJ_SUCCESS ? 0 : -1;
}
int ast_sip_subscription_send_request(struct ast_sip_subscription *sub, pjsip_tx_data *tdata)
@@ -900,7 +928,7 @@
int res;
ao2_ref(sub, +1);
- res = pjsip_evsub_send_request(ast_sip_subscription_get_evsub(sub),
+ res = pjsip_evsub_send_request(sip_subscription_get_evsub(sub),
tdata) == PJ_SUCCESS ? 0 : -1;
subscription_persistence_update(sub, NULL);
@@ -908,7 +936,7 @@
ast_test_suite_event_notify("SUBSCRIPTION_STATE_SET",
"StateText: %s\r\n"
"Endpoint: %s\r\n",
- pjsip_evsub_get_state_name(ast_sip_subscription_get_evsub(sub)),
+ pjsip_evsub_get_state_name(sip_subscription_get_evsub(sub)),
ast_sorcery_object_get_id(endpoint));
ao2_cleanup(sub);
ao2_cleanup(endpoint);
@@ -1199,6 +1227,7 @@
char *resource;
struct pjsip_sip_uri *request_uri;
size_t resource_size;
+ int resp;
endpoint = ast_pjsip_rdata_get_endpoint(rdata);
ast_assert(endpoint != NULL);
@@ -1256,7 +1285,7 @@
} else {
sub->persistence = subscription_persistence_create(sub);
subscription_persistence_update(sub, rdata);
- pjsip_evsub_accept(sub->evsub, rdata, resp, NULL);
+ pjsip_evsub_accept(sip_subscription_get_evsub(sub), rdata, resp, NULL);
handler->notifier->notify_required(sub, AST_SIP_SUBSCRIPTION_NOTIFY_REASON_STARTED);
}
@@ -1310,10 +1339,102 @@
return SIP_PUBLISH_UNKNOWN;
}
+/*! \brief Internal destructor for publications */
+static void publication_destroy_fn(void *obj)
+{
+ struct ast_sip_publication *publication = obj;
+
+ ast_debug(3, "Destroying SIP publication\n");
+
+ ao2_cleanup(publication->datastores);
+ ao2_cleanup(publication->endpoint);
+}
+
+static struct ast_sip_publication *sip_create_publication(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
+{
+ struct ast_sip_publication *publication;
+ pjsip_expires_hdr *expires_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, NULL);
+
+ ast_assert(endpoint != NULL);
+
+ if (!(publication = ao2_alloc(sizeof(*publication), publication_destroy_fn))) {
+ return NULL;
+ }
+
+ if (!(publication->datastores = ao2_container_alloc(DATASTORE_BUCKETS, datastore_hash, datastore_cmp))) {
+ ao2_ref(publication, -1);
+ return NULL;
+ }
+
+ publication->entity_tag = ast_atomic_fetchadd_int(&esc_etag_counter, +1);
+ ao2_ref(endpoint, +1);
+ publication->endpoint = endpoint;
+ publication->expires = expires_hdr ? expires_hdr->ivalue : DEFAULT_PUBLISH_EXPIRES;
+ publication->sched_id = -1;
+
+ return publication;
+}
+
+static int sip_publication_respond(struct ast_sip_publication *pub, int status_code,
+ pjsip_rx_data *rdata)
+{
+ pj_status_t status;
+ pjsip_tx_data *tdata;
+ pjsip_transaction *tsx;
+
+ if (pjsip_endpt_create_response(ast_sip_get_pjsip_endpoint(), rdata, status_code, NULL, &tdata) != PJ_SUCCESS) {
+ return -1;
+ }
+
+ if (PJSIP_IS_STATUS_IN_CLASS(status_code, 200)) {
+ RAII_VAR(char *, entity_tag, NULL, ast_free_ptr);
+ RAII_VAR(char *, expires, NULL, ast_free_ptr);
+
+ if ((ast_asprintf(&entity_tag, "%d", pub->entity_tag) < 0) ||
+ (ast_asprintf(&expires, "%d", pub->expires) < 0)) {
+ pjsip_tx_data_dec_ref(tdata);
+ return -1;
+ }
+
+ ast_sip_add_header(tdata, "SIP-ETag", entity_tag);
+ ast_sip_add_header(tdata, "Expires", expires);
+ }
+
+ if ((status = pjsip_tsx_create_uas(&pubsub_module, rdata, &tsx)) != PJ_SUCCESS) {
+ return -1;
+ }
+
+ pjsip_tsx_recv_msg(tsx, rdata);
+
+ if (pjsip_tsx_send_msg(tsx, tdata) != PJ_SUCCESS) {
+ return -1;
+ }
+
+ return 0;
+}
+
static struct ast_sip_publication *publish_request_initial(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata,
struct ast_sip_publish_handler *handler)
{
- struct ast_sip_publication *publication = handler->new_publication(endpoint, rdata);
+ struct ast_sip_publication *publication;
+ char *resource;
+ size_t resource_size;
+ pjsip_sip_uri *request_uri;
+ int resp;
+
+ request_uri = pjsip_uri_get_uri(rdata->msg_info.msg->line.req.uri);
+ resource_size = pj_strlen(&request_uri->user) + 1;
+ resource = alloca(resource_size);
+ ast_copy_pj_str(resource, &request_uri->user, resource_size);
+
+ resp = handler->new_publication(endpoint, resource);
+
+ if (PJSIP_IS_STATUS_IN_CLASS(resp, 200)) {
+ pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, resp, NULL, NULL, NULL);
+ return NULL;
+ }
+
+ publication = sip_create_publication(endpoint, rdata);
if (!publication) {
pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 503, NULL, NULL, NULL);
@@ -1321,6 +1442,14 @@
}
publication->handler = handler;
+ if (publication->handler->publication_state_change(publication, rdata->msg_info.msg->body,
+ AST_SIP_PUBLISH_STATE_INITIALIZED)) {
+ pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
+ ao2_cleanup(publication);
+ return NULL;
+ }
+
+ sip_publication_respond(publication, resp, rdata);
return publication;
}
@@ -1402,14 +1531,19 @@
publication = publish_request_initial(endpoint, rdata, handler);
break;
case SIP_PUBLISH_REFRESH:
+ sip_publication_respond(publication, 200, rdata);
case SIP_PUBLISH_MODIFY:
- if (handler->publish_refresh(publication, rdata)) {
+ if (handler->publication_state_change(publication, rdata->msg_info.msg->body,
+ AST_SIP_PUBLISH_STATE_ACTIVE)) {
/* If an error occurs we want to terminate the publication */
expires = 0;
}
+ sip_publication_respond(publication, 200, rdata);
break;
case SIP_PUBLISH_REMOVE:
- handler->publish_termination(publication, rdata);
+ handler->publication_state_change(publication, rdata->msg_info.msg->body,
+ AST_SIP_PUBLISH_STATE_TERMINATED);
+ sip_publication_respond(publication, 200, rdata);
break;
case SIP_PUBLISH_UNKNOWN:
default:
[... 212 lines stripped ...]
More information about the asterisk-commits
mailing list