[asterisk-commits] mmichelson: branch mmichelson/subscription_abstraction r416236 - in /team/mmi...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Fri Jun 13 18:07:52 CDT 2014
Author: mmichelson
Date: Fri Jun 13 18:07:48 2014
New Revision: 416236
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=416236
Log:
Commit some progress towards this effort.
Unfortunately, I've simply run out of time for the day
so this is a big garbled mess at the moment. This does
not even come close to compiling right now.
I've made the necessary changes to res_pjsip_pubsub.h, and
I'm working on the pubsub core before I start adjusting
subscription handlers' calls to the API.
Modified:
team/mmichelson/subscription_abstraction/include/asterisk/res_pjsip_pubsub.h
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=416236&r1=416235&r2=416236
==============================================================================
--- team/mmichelson/subscription_abstraction/include/asterisk/res_pjsip_pubsub.h (original)
+++ team/mmichelson/subscription_abstraction/include/asterisk/res_pjsip_pubsub.h Fri Jun 13 18:07:48 2014
@@ -222,19 +222,20 @@
};
#define AST_SIP_MAX_ACCEPT 32
-
-struct ast_sip_subscription_handler {
- /*! The name of the event this handler deals with */
- const char *event_name;
- /*! The types of body this handler accepts.
- *
- * \note This option has no bearing when the handler is used in the
- * notifier role. When in a subscriber role, this header is used to
- * populate the Accept: header of an outbound SUBSCRIBE request
- */
- const char *accept[AST_SIP_MAX_ACCEPT];
- /*!
- * \brief Default body type defined for the event package this handler handles.
+enum ast_sip_subscription_notify_reason {
+ /*! Initial NOTIFY for subscription */
+ AST_SIP_SUBSCRIPTION_NOTIFY_REASON_STARTED,
+ /*! Subscription has been renewed */
+ AST_SIP_SUBSCRIPTION_NOTIFY_REASON_RENEWED,
+ /*! Subscription is being terminated */
+ AST_SIP_SUBSCRIPTION_NOTIFY_REASON_TERMINATED,
+ /*! Other unspecified reason */
+ AST_SIP_SUBSCRIPTION_NOTIFY_REASON_OTHER
+};
+
+struct ast_sip_notifier {
+ /*!
+ * \brief Default body type defined for the event package this notifier handles.
*
* Typically, a SUBSCRIBE request will contain one or more Accept headers that tell
* what format they expect the body of NOTIFY requests to use. However, every event
@@ -243,163 +244,95 @@
*/
const char *default_accept;
/*!
+ * \brief Called when a SUBSCRIBE arrives attempting to establish a new subscription.
+ *
+ * The notifier is expected to return the response that should be sent to the
+ * SUBSCRIBE request.
+ *
+ * If a 200-class response is returned, then the notifier's notify_required
+ * callback will immediately be called into with a reason of
+ * AST_SIP_SUBSCRIPTION_NOTIFY_REASON_STARTED.
+ *
+ * \param endpoint The endpoint from which we received the SUBSCRIBE
+ * \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);
+ /*!
+ * \brief The subscription is in need of a NOTIFY request.
+ *
+ * A reason of AST_SIP_SUBSCRIPTION_NOTIFY_REASON_STARTED is given immediately
+ * after a SUBSCRIBE is accepted. This is a good opportunity for the notifier to
+ * perform setup duties such as establishing Stasis subscriptions or adding
+ * datastores to the subscription.
+ *
+ * A reason of AST_SIP_SUBSCRIPTION_NOTIFY_REASON_TERMINATED is given when the
+ * subscriber has terminated the subscription. If there are any duties that the
+ *
+ *
+ * \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);
+};
+
+struct ast_sip_subscriber {
+ /*! The types of body this subscriber accepts. */
+ const char *accept[AST_SIP_MAX_ACCEPT];
+ /*!
+ * \brief A NOTIFY has been received.
+ *
+ * The body of the NOTIFY is provided so that it may be parsed and appropriate
+ * internal state change may be generated.
+ *
+ * The state can be used to determine if the subscription has been terminated
+ * by the far end or if this is just a typical resource state change.
+ *
+ * \param sub The subscription on which the NOTIFY arrived
+ * \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);
+};
+
+struct ast_sip_subscription_handler {
+ /*! The name of the event this subscriber deals with */
+ const char *event_name;
+ /*!
* \brief Called when a subscription is to be destroyed
- *
- * This is a subscriber and notifier callback.
*
* The handler is not expected to send any sort of requests or responses
* during this callback. The handler MUST, however, begin the destruction
* process for the subscription during this callback.
*/
void (*subscription_shutdown)(struct ast_sip_subscription *subscription);
-
- /*!
- * \brief Called when a SUBSCRIBE arrives in order to create a new subscription
- *
- * This is a notifier callback.
- *
- * If the notifier wishes to accept the subscription, then it can create
- * a new ast_sip_subscription to do so.
- *
- * If the notifier chooses to create a new subscription, then it must accept
- * the incoming subscription using pjsip_evsub_accept() and it must also
- * send an initial NOTIFY with the current subscription state.
- *
- * \param endpoint The endpoint from which we received the SUBSCRIBE
- * \param rdata The SUBSCRIBE request
- * \retval NULL The SUBSCRIBE has not been accepted
- * \retval non-NULL The newly-created subscription
- */
- struct ast_sip_subscription *(*new_subscribe)(struct ast_sip_endpoint *endpoint,
- pjsip_rx_data *rdata);
-
- /*!
- * \brief Called when an endpoint renews a subscription.
- *
- * This is a notifier callback.
- *
- * Because of the way that the PJSIP evsub framework works, it will automatically
- * send a response to the SUBSCRIBE. However, the subscription handler must send
- * a NOTIFY with the current subscription state when this callback is called.
- *
- * The response_data that is passed into this callback is used to craft what should
- * be in the response to the incoming SUBSCRIBE. It is initialized with a 200 status
- * code and all other parameters are empty.
- *
- * \param sub The subscription that is being renewed
- * \param rdata The SUBSCRIBE request in question
- * \param[out] response_data Data pertaining to the SIP response that should be
- * sent to the SUBSCRIBE
- */
- void (*resubscribe)(struct ast_sip_subscription *sub,
- pjsip_rx_data *rdata, struct ast_sip_subscription_response_data *response_data);
-
- /*!
- * \brief Called when a subscription times out.
- *
- * This is a notifier callback
- *
- * This indicates that the subscription has timed out. The subscription handler is
- * expected to send a NOTIFY that terminates the subscription.
- *
- * \param sub The subscription that has timed out
- */
- void (*subscription_timeout)(struct ast_sip_subscription *sub);
-
- /*!
- * \brief Called when a subscription is terminated via a SUBSCRIBE or NOTIFY request
- *
- * This is a notifier and subscriber callback.
- *
- * The PJSIP subscription framework will automatically send the response to the
- * request. If a notifier receives this callback, then the subscription handler
- * is expected to send a final NOTIFY to terminate the subscription.
- *
- * \param sub The subscription being terminated
- * \param rdata The request that terminated the subscription
- */
- void (*subscription_terminated)(struct ast_sip_subscription *sub, pjsip_rx_data *rdata);
-
- /*!
- * \brief Called when a subscription handler's outbound NOTIFY receives a response
- *
- * This is a notifier callback.
- *
- * \param sub The subscription
- * \param rdata The NOTIFY response
- */
- void (*notify_response)(struct ast_sip_subscription *sub, pjsip_rx_data *rdata);
-
- /*!
- * \brief Called when a subscription handler receives an inbound NOTIFY
- *
- * This is a subscriber callback.
- *
- * Because of the way that the PJSIP evsub framework works, it will automatically
- * send a response to the NOTIFY. By default this will be a 200 OK response, but
- * this callback can change details of the response by returning response data
- * to use.
- *
- * The response_data that is passed into this callback is used to craft what should
- * be in the response to the incoming SUBSCRIBE. It is initialized with a 200 status
- * code and all other parameters are empty.
- *
- * \param sub The subscription
- * \param rdata The NOTIFY request
- * \param[out] response_data Data pertaining to the SIP response that should be
- * sent to the SUBSCRIBE
- */
- void (*notify_request)(struct ast_sip_subscription *sub,
- pjsip_rx_data *rdata, struct ast_sip_subscription_response_data *response_data);
-
- /*!
- * \brief Called when it is time for a subscriber to resubscribe
- *
- * This is a subscriber callback.
- *
- * The subscriber can reresh the subscription using the pjsip_evsub_initiate()
- * function.
- *
- * \param sub The subscription to refresh
- * \retval 0 Success
- * \retval non-zero Failure
- */
- int (*refresh_subscription)(struct ast_sip_subscription *sub);
-
/*!
* \brief Converts the subscriber to AMI
- *
- * This is a subscriber callback.
*
* \param sub The subscription
* \param buf The string to write AMI data
*/
void (*to_ami)(struct ast_sip_subscription *sub, struct ast_str **buf);
+ /*! Subscriber callbacks for this handler */
+ struct ast_sip_subscriber *subscriber;
+ /*! Notifier callbacks for this handler */
+ struct ast_sip_subscriber *notifier;
AST_LIST_ENTRY(ast_sip_subscription_handler) next;
};
/*!
* \brief Create a new ast_sip_subscription structure
*
- * In most cases the pubsub core will create a general purpose subscription
- * within PJSIP. However, PJSIP provides enhanced support for the following
- * event packages:
- *
- * presence
- * message-summary
- *
- * If either of these events are handled by the subscription handler, then
- * the special-purpose event subscriptions will be created within PJSIP,
- * and it will be expected that your subscription handler make use of the
- * special PJSIP APIs.
- *
- * \param handler The subsription handler for this subscription
- * \param role Whether we are acting as subscriber or notifier for this subscription
- * \param endpoint The endpoint involved in this subscription
- * \param rdata If acting as a notifier, the SUBSCRIBE request that triggered subscription creation
+ * When a subscriber wishes to create a subscription, it may call this function
+ * to allocate resources and to send the initial SUBSCRIBE out.
+ *
+ * \param subscriber The subscriber that is making the request.
+ * \param endpoint The endpoint to whome the SUBSCRIBE will be sent.
+ * \param resource The resource to place in the SUBSCRIBE's Request-URI.
*/
struct ast_sip_subscription *ast_sip_create_subscription(const struct ast_sip_subscription_handler *handler,
- enum ast_sip_subscription_role role, struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata);
+ struct ast_sip_endpoint *endpoint, const char *resource);
/*!
@@ -426,34 +359,28 @@
struct ast_taskprocessor *ast_sip_subscription_get_serializer(struct ast_sip_subscription *sub);
/*!
- * \brief Get the underlying PJSIP evsub structure
- *
- * This is useful when wishing to call PJSIP's API calls in order to
- * create SUBSCRIBEs, NOTIFIES, etc. as well as get subscription state
- *
- * This function, as well as all methods called on the pjsip_evsub should
- * be done in a SIP servant thread.
- *
- * \param sub The subscription
- * \retval NULL Failure
- * \retval non-NULL The underlying pjsip_evsub
- */
-pjsip_evsub *ast_sip_subscription_get_evsub(struct ast_sip_subscription *sub);
-
-/*!
- * \brief Get the underlying PJSIP dialog structure
- *
- * Call this function when information needs to be retrieved from the
- * underlying pjsip dialog.
- *
- * This function, as well as all methods called on the pjsip_evsub should
- * be done in a SIP servant thread.
- *
- * \param sub The subscription
- * \retval NULL Failure
- * \retval non-NULL The underlying pjsip_dialog
- */
-pjsip_dialog *ast_sip_subscription_get_dlg(struct ast_sip_subscription *sub);
+ * \brief Notify a SIP subscription of a state change.
+ *
+ * This will create a NOTIFY body to be sent out for the subscribed resource.
+ * On real subscriptions, a NOTIFY request will be generated and sent.
+ * On virtual subscriptions, the NOTIFY is saved on the virtual subscription and the
+ * parent subscription is alerted.
+ *
+ * \param sub The subscription on which a state change is occurring.
+ * \param notify_data Event package-specific data used to create the NOTIFY body.
+ * \retval 0 Success
+ * \retval non-zero Failure
+ */
+int ast_sip_subscription_notify(struct ast_sip_subscription *sub, void *notify_data);
+
+/*! Retrieve the local URI for this subscription */
+void ast_sip_subscription_get_local_uri(struct ast_sip_subscription *sub, char *buf, size_t size);
+
+/*! Retrive the remote URI for this subscription */
+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);
/*!
* \brief Accept a subscription request
@@ -536,17 +463,30 @@
void ast_sip_subscription_remove_datastore(struct ast_sip_subscription *subscription, const char *name);
/*!
- * \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 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 Pubsub body generator
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=416236&r1=416235&r2=416236
==============================================================================
--- team/mmichelson/subscription_abstraction/res/res_pjsip_pubsub.c (original)
+++ team/mmichelson/subscription_abstraction/res/res_pjsip_pubsub.c Fri Jun 13 18:07:48 2014
@@ -249,6 +249,36 @@
};
/*!
+ * \brief Real subscription details
+ *
+ * A real subscription is one that has a direct link to a
+ * PJSIP subscription and dialog.
+ */
+struct ast_sip_real_subscription {
+ /*! The underlying PJSIP event subscription structure */
+ pjsip_evsub *evsub;
+ /*! The underlying PJSIP dialog */
+ pjsip_dialog *dlg;
+};
+
+/*!
+ * \brief Virtual subscription details
+ *
+ * A virtual subscription is one that does not have a direct
+ * link to a PJSIP subscription. Instead, it is a descendent
+ * of an ast_sip_subscription. Following the ancestry will
+ * eventually lead to a real subscription.
+ */
+struct ast_sip_virtual_subscription {
+ struct ast_sip_subscription *parent;
+};
+
+enum sip_subscription_type {
+ SIP_SUBSCRIPTION_REAL,
+ SIP_SUBSCRIPTION_VIRTUAL,
+};
+
+/*!
* \brief Structure representing a SIP subscription
*/
struct ast_sip_subscription {
@@ -262,16 +292,21 @@
const struct ast_sip_subscription_handler *handler;
/*! The role for this subscription */
enum ast_sip_subscription_role role;
- /*! The underlying PJSIP event subscription structure */
- pjsip_evsub *evsub;
- /*! The underlying PJSIP dialog */
- pjsip_dialog *dlg;
+ /*! Indicator of real or virtual subscription */
+ enum sip_subscription_type type;
+ /*! Real and virtual components of the subscription */
+ union {
+ struct ast_sip_real_subscription *real;
+ struct ast_sip_virtual_subscription *virtual;
+ } pants;
/*! Body generaator for NOTIFYs */
struct ast_sip_pubsub_body_generator *body_generator;
/*! Persistence information */
struct subscription_persistence *persistence;
/*! Next item in the list */
AST_LIST_ENTRY(ast_sip_subscription) next;
+ /*! List of child subscriptions */
+ AST_LIST_HEAD_NOLOCK(,ast_sip_subscription) children;
};
static const char *sip_subscription_roles_map[] = {
@@ -428,6 +463,8 @@
RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
struct ast_sip_subscription *sub;
struct ast_sip_pubsub_body_generator *generator;
+ int resp;
+ char *resource;
/* If this subscription has already expired remove it */
if (ast_tvdiff_ms(persistence->expires, ast_tvnow()) <= 0) {
@@ -467,7 +504,7 @@
expires_header->ivalue = (ast_tvdiff_ms(persistence->expires, ast_tvnow()) / 1000);
handler = subscription_get_handler_from_rdata(&rdata);
- if (!handler) {
+ if (!handler || !handler->notifier) {
ast_sorcery_delete(ast_sip_get_sorcery(), persistence);
return 0;
}
@@ -679,7 +716,6 @@
}
static void pubsub_on_evsub_state(pjsip_evsub *sub, pjsip_event *event);
-static void pubsub_on_tsx_state(pjsip_evsub *sub, pjsip_transaction *tsx, pjsip_event *event);
static void pubsub_on_rx_refresh(pjsip_evsub *sub, pjsip_rx_data *rdata,
int *p_st_code, pj_str_t **p_st_text, pjsip_hdr *res_hdr, pjsip_msg_body **p_body);
static void pubsub_on_rx_notify(pjsip_evsub *sub, pjsip_rx_data *rdata, int *p_st_code,
@@ -690,7 +726,6 @@
static pjsip_evsub_user pubsub_cb = {
.on_evsub_state = pubsub_on_evsub_state,
- .on_tsx_state = pubsub_on_tsx_state,
.on_rx_refresh = pubsub_on_rx_refresh,
.on_rx_notify = pubsub_on_rx_notify,
.on_client_refresh = pubsub_on_client_refresh,
@@ -701,12 +736,7 @@
struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pjsip_dialog *dlg)
{
pjsip_evsub *evsub;
- /* PJSIP is kind enough to have some built-in support for certain
- * events. We need to use the correct initialization function for the
- * built-in events
- */
if (role == AST_SIP_NOTIFIER) {
- pjsip_evsub_create_uas(dlg, &pubsub_cb, rdata, 0, &evsub);
} else {
pj_str_t pj_event;
pj_cstr(&pj_event, event);
@@ -715,8 +745,10 @@
return evsub;
}
-struct ast_sip_subscription *ast_sip_create_subscription(const struct ast_sip_subscription_handler *handler,
- enum ast_sip_subscription_role role, struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
+/* 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,
+ struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
{
struct ast_sip_subscription *sub = ao2_alloc(sizeof(*sub), subscription_destructor);
pjsip_dialog *dlg;
@@ -737,26 +769,14 @@
}
sub->body_generator = ast_sip_mod_data_get(rdata->endpt_info.mod_data,
pubsub_module.id, MOD_DATA_BODY_GENERATOR);
- sub->role = role;
- if (role == AST_SIP_NOTIFIER) {
- dlg = ast_sip_create_dialog_uas(endpoint, rdata);
- } else {
- RAII_VAR(struct ast_sip_contact *, contact, NULL, ao2_cleanup);
-
- 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",
- ast_sorcery_object_get_id(endpoint));
- ao2_ref(sub, -1);
- return NULL;
- }
- dlg = ast_sip_create_dialog_uac(endpoint, contact->uri, NULL);
- }
+ sub->role = AST_SIP_NOTIFIER;
+ dlg = ast_sip_create_dialog_uas(endpoint, rdata);
if (!dlg) {
ast_log(LOG_WARNING, "Unable to create dialog for SIP subscription\n");
ao2_ref(sub, -1);
return NULL;
}
+
persistence = ast_sip_mod_data_get(rdata->endpt_info.mod_data,
pubsub_module.id, MOD_DATA_PERSISTENCE);
if (persistence) {
@@ -768,7 +788,62 @@
dlg->local.cseq = persistence->cseq;
dlg->remote.cseq = persistence->cseq;
}
- sub->evsub = allocate_evsub(handler->event_name, role, endpoint, rdata, dlg);
+
+ pjsip_evsub_create_uas(dlg, &pubsub_cb, rdata, 0, &sub->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;
+ ast_sip_dialog_set_serializer(dlg, sub->serializer);
+ pjsip_evsub_set_mod_data(sub->evsub, pubsub_module.id, sub);
+ sub->endpoint = ao2_bump(endpoint);
+ sub->handler = handler;
+
+ add_subscription(sub);
+ return sub;
+}
+
+struct ast_sip_subscription *ast_sip_create_subscription(const struct ast_sip_subscription_handler *handler,
+ struct ast_sip_endpoint *endpoint, const char *resource)
+{
+ struct ast_sip_subscription *sub = ao2_alloc(sizeof(*sub), subscription_destructor);
+ pjsip_dialog *dlg;
+ struct ast_sip_contact *contact;
+ pj_str_t event;
+
+ if (!sub) {
+ return NULL;
+ }
+ sub->datastores = ao2_container_alloc(DATASTORE_BUCKETS, datastore_hash, datastore_cmp);
+ if (!sub->datastores) {
+ ao2_ref(sub, -1);
+ return NULL;
+ }
+ sub->serializer = ast_sip_create_serializer();
+ if (!sub->serializer) {
+ ao2_ref(sub, -1);
+ return NULL;
+ }
+ sub->role = AST_SIP_SUBSCRIBER;
+ 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",
+ ast_sorcery_object_get_id(endpoint));
+ ao2_ref(sub, -1);
+ ao2_cleanup(contact);
+ return NULL;
+ }
+ dlg = ast_sip_create_dialog_uac(endpoint, contact->uri, NULL);
+ ao2_cleanup(contact);
+ if (!dlg) {
+ ast_log(LOG_WARNING, "Unable to create dialog for SIP subscription\n");
+ ao2_ref(sub, -1);
+ return NULL;
+ }
+
+ pj_cstr(&event, handler->event_name);
+ pjsip_evsub_create_uac(dlg, &pubsub_cb, &event, 0, &sub->evsub);
/* We keep a reference to the dialog until our subscription is destroyed. See
* the subscription_destructor for more details
*/
@@ -781,6 +856,8 @@
sub->handler = handler;
add_subscription(sub);
+
+ /* XXX TODO We need to send our initial subscribe here */
return sub;
}
@@ -1019,9 +1096,9 @@
int ast_sip_register_subscription_handler(struct ast_sip_subscription_handler *handler)
{
pj_str_t event;
- pj_str_t accept[AST_SIP_MAX_ACCEPT];
+ pj_str_t accept[AST_SIP_MAX_ACCEPT] = { {0, }, };
struct ast_sip_subscription_handler *existing;
- int i;
+ int i = 0;
if (ast_strlen_zero(handler->event_name)) {
ast_log(LOG_ERROR, "No event package specified for subscription handler. Cannot register\n");
@@ -1035,8 +1112,10 @@
return -1;
}
- for (i = 0; i < AST_SIP_MAX_ACCEPT && !ast_strlen_zero(handler->accept[i]); ++i) {
- pj_cstr(&accept[i], handler->accept[i]);
+ if (handler->subscriber) {
+ for (i = 0; i < AST_SIP_MAX_ACCEPT && !ast_strlen_zero(handler->subscriber->accept[i]); ++i) {
+ pj_cstr(&accept[i], handler->subscriber->accept[i]);
+ }
}
pj_cstr(&event, handler->event_name);
@@ -1117,6 +1196,9 @@
RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
struct ast_sip_subscription *sub;
struct ast_sip_pubsub_body_generator *generator;
+ char *resource;
+ struct pjsip_sip_uri *request_uri;
+ size_t resource_size;
endpoint = ast_pjsip_rdata_get_endpoint(rdata);
ast_assert(endpoint != NULL);
@@ -1126,6 +1208,11 @@
pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 603, NULL, NULL, NULL);
return PJ_TRUE;
}
+
+ 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);
expires_header = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, rdata->msg_info.msg->hdr.next);
@@ -1142,7 +1229,7 @@
pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 423, NULL, NULL, NULL);
return PJ_TRUE;
}
- }
+ }
handler = subscription_get_handler_from_rdata(rdata);
if (!handler) {
@@ -1159,24 +1246,18 @@
ast_sip_mod_data_set(rdata->tp_info.pool, rdata->endpt_info.mod_data,
pubsub_module.id, MOD_DATA_BODY_GENERATOR, generator);
- sub = handler->new_subscribe(endpoint, rdata);
+ resp = handler->notifier->new_subscribe(endpoint, resource);
+ if (resp < 200 || resp >= 300) {
+ pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, resp, NULL, NULL, NULL);
+ }
+ sub = notifier_create_subscription(handler, endpoint, rdata);
if (!sub) {
- pjsip_transaction *trans = pjsip_rdata_get_tsx(rdata);
-
- if (trans) {
- pjsip_dialog *dlg = pjsip_rdata_get_dlg(rdata);
- pjsip_tx_data *tdata;
-
- if (pjsip_endpt_create_response(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, &tdata) != PJ_SUCCESS) {
- return PJ_TRUE;
- }
- pjsip_dlg_send_response(dlg, trans, tdata);
- } else {
- pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
- }
+ pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
} else {
sub->persistence = subscription_persistence_create(sub);
subscription_persistence_update(sub, rdata);
+ pjsip_evsub_accept(sub->evsub, rdata, resp, NULL);
+ handler->notifier->notify_required(sub, AST_SIP_SUBSCRIPTION_NOTIFY_REASON_STARTED);
}
return PJ_TRUE;
@@ -1590,20 +1671,6 @@
pjsip_evsub_set_mod_data(evsub, pubsub_module.id, NULL);
}
-static void pubsub_on_tsx_state(pjsip_evsub *evsub, pjsip_transaction *tsx, pjsip_event *event)
-{
- struct ast_sip_subscription *sub = pjsip_evsub_get_mod_data(evsub, pubsub_module.id);
-
- if (!sub) {
- return;
- }
-
- if (sub->handler->notify_response && tsx->role == PJSIP_ROLE_UAC &&
- event->body.tsx_state.type == PJSIP_EVENT_RX_MSG) {
- sub->handler->notify_response(sub, event->body.tsx_state.src.rdata);
- }
-}
-
static void set_parameters_from_response_data(pj_pool_t *pool, int *p_st_code,
pj_str_t **p_st_text, pjsip_hdr *res_hdr, pjsip_msg_body **p_body,
struct ast_sip_subscription_response_data *response_data)
@@ -1657,27 +1724,18 @@
int *p_st_code, pj_str_t **p_st_text, pjsip_hdr *res_hdr, pjsip_msg_body **p_body)
{
struct ast_sip_subscription *sub = pjsip_evsub_get_mod_data(evsub, pubsub_module.id);
- struct ast_sip_subscription_response_data response_data = {
- .status_code = 200,
- };
+ enum ast_sip_subscription_notify_reason reason;
if (!sub) {
return;
}
if (pjsip_evsub_get_state(sub->evsub) == PJSIP_EVSUB_STATE_TERMINATED) {
- sub->handler->subscription_terminated(sub, rdata);
- return;
- }
-
- sub->handler->resubscribe(sub, rdata, &response_data);
-
- if (!response_data_changed(&response_data)) {
- return;
- }
-
- set_parameters_from_response_data(rdata->tp_info.pool, p_st_code, p_st_text,
- res_hdr, p_body, &response_data);
+ reason = AST_SIP_SUBSCRIPTION_NOTIFY_REASON_TERMINATED;
+ } else {
+ reason = AST_SIP_SUBSCRIPTION_NOTIFY_REASON_RENEWED;
+ }
+ sub->handler->notify_required(sub, reason);
}
static void pubsub_on_rx_notify(pjsip_evsub *evsub, pjsip_rx_data *rdata, int *p_st_code,
More information about the asterisk-commits
mailing list