res_pjsip_pubsub: Solidify lifetime and ownership of objects.
[asterisk/asterisk.git] / include / asterisk / res_pjsip_pubsub.h
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * Mark Michelson <mmichelson@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 #ifndef _RES_PJSIP_PUBSUB_H
20 #define _RES_PJSIP_PUBSUB_H
21
22 #include "asterisk/linkedlists.h"
23
24 /* Forward declarations */
25 struct pjsip_rx_data;
26 struct pjsip_tx_data;
27 struct pjsip_evsub;
28 struct ast_sip_endpoint;
29 struct ast_datastore;
30 struct ast_datastore_info;
31
32 /*!
33  * \brief Opaque structure representing a publication
34  */
35 struct ast_sip_publication;
36
37 enum ast_sip_publish_state {
38     /*! Publication has just been initialized */
39     AST_SIP_PUBLISH_STATE_INITIALIZED,
40     /*! Publication is currently active */
41     AST_SIP_PUBLISH_STATE_ACTIVE,
42     /*! Publication has been terminated */
43     AST_SIP_PUBLISH_STATE_TERMINATED,
44 };
45
46 /*!
47  * \brief Callbacks that publication handlers will define
48  */
49 struct ast_sip_publish_handler {
50         /*! \brief The name of the event this handler deals with */
51         const char *event_name;
52
53         /*! \brief Publications */
54         struct ao2_container *publications;
55
56         /*!
57          * \brief Called when a PUBLISH to establish a new publication arrives.
58          *
59          * \param endpoint The endpoint from whom the PUBLISH arrived.
60          * \param resource The resource whose state is being published.
61          * \param event_configuration The name of the event type configuration to use for this resource.
62          * \return Response code for the incoming PUBLISH
63          */
64         int (*new_publication)(struct ast_sip_endpoint *endpoint, const char *resource, const char *event_configuration);
65         /*!
66          * \brief Called when a publication has reached its expiration.
67          */
68         void (*publish_expire)(struct ast_sip_publication *pub);
69         /*!
70          * \brief Published resource has changed states.
71          *
72          * The state parameter can be used to take further action. For instance,
73          * if the state is AST_SIP_PUBLISH_STATE_INITIALIZED, then this is the initial
74          * PUBLISH request. This is a good time to set up datastores on the publication
75          * or any other initial needs.
76          *
77          * AST_SIP_PUBLISH_STATE_TERMINATED is used when the remote end is terminating
78          * its publication. This is a good opportunity to free any resources associated with
79          * the publication.
80          *
81          * AST_SIP_PUBLISH_STATE_ACTIVE is used when a publication that modifies state
82          * arrives.
83          *
84          * \param pub The publication whose state has changed
85          * \param body The body of the inbound PUBLISH
86          * \param state The state of the publication
87          */
88         int (*publication_state_change)(struct ast_sip_publication *pub, pjsip_msg_body *body,
89                         enum ast_sip_publish_state state);
90         AST_LIST_ENTRY(ast_sip_publish_handler) next;
91 };
92
93 /*!
94  * \brief Given a publication, get the associated endpoint
95  *
96  * \param pub The publication
97  * \retval NULL Failure
98  * \retval non-NULL The associated endpoint
99  */
100 struct ast_sip_endpoint *ast_sip_publication_get_endpoint(struct ast_sip_publication *pub);
101
102 /*!
103  * \brief Given a publication, get the resource the publication is to
104  *
105  * \param pub The publication
106  * \return The resource
107  */
108 const char *ast_sip_publication_get_resource(const struct ast_sip_publication *pub);
109
110 /*!
111  * \brief Given a publication, get the configuration name for the event type in use
112  *
113  * \param pub The publication
114  * \return The configuration name
115  */
116 const char *ast_sip_publication_get_event_configuration(const struct ast_sip_publication *pub);
117
118 /*!
119  * \brief Register a publish handler
120  *
121  * \retval 0 Handler was registered successfully
122  * \retval non-zero Handler was not registered successfully
123  */
124 int ast_sip_register_publish_handler(struct ast_sip_publish_handler *handler);
125
126 /*!
127  * \brief Unregister a publish handler
128  */
129 void ast_sip_unregister_publish_handler(struct ast_sip_publish_handler *handler);
130
131 /*!
132  * \brief Add a datastore to a SIP publication
133  *
134  * Note that SIP uses reference counted datastores. The datastore passed into this function
135  * must have been allocated using ao2_alloc() or there will be serious problems.
136  *
137  * \param publication The publication to add the datastore to
138  * \param datastore The datastore to be added to the subscription
139  * \retval 0 Success
140  * \retval -1 Failure
141  */
142 int ast_sip_publication_add_datastore(struct ast_sip_publication *publication, struct ast_datastore *datastore);
143
144 /*!
145  * \brief Retrieve a publication datastore
146  *
147  * The datastore retrieved will have its reference count incremented. When the caller is done
148  * with the datastore, the reference counted needs to be decremented using ao2_ref().
149  *
150  * \param publication The publication from which to retrieve the datastore
151  * \param name The name of the datastore to retrieve
152  * \retval NULL Failed to find the specified datastore
153  * \retval non-NULL The specified datastore
154  */
155 struct ast_datastore *ast_sip_publication_get_datastore(struct ast_sip_publication *publication, const char *name);
156
157 /*!
158  * \brief Remove a publication datastore from the publication
159  *
160  * This operation may cause the datastore's free() callback to be called if the reference
161  * count reaches zero.
162  *
163  * \param publication The publication to remove the datastore from
164  * \param name The name of the datastore to remove
165  */
166 void ast_sip_publication_remove_datastore(struct ast_sip_publication *publication, const char *name);
167
168 /*!
169  * \brief Opaque structure representing an RFC 3265 SIP subscription
170  */
171 struct ast_sip_subscription;
172
173 /*!
174  * \brief Role for the subscription that is being created
175  */
176 enum ast_sip_subscription_role {
177         /* Sending SUBSCRIBEs, receiving NOTIFYs */
178         AST_SIP_SUBSCRIBER,
179         /* Sending NOTIFYs, receiving SUBSCRIBEs */
180         AST_SIP_NOTIFIER,
181 };
182
183 /*!
184  * \brief Data for responses to SUBSCRIBEs and NOTIFIEs
185  *
186  * Some of PJSIP's evsub callbacks expect us to provide them
187  * with data so that they can craft a response rather than have
188  * us create our own response.
189  *
190  * Filling in the structure is optional, since the framework
191  * will automatically respond with a 200 OK response if we do
192  * not provide it with any additional data.
193  */
194 struct ast_sip_subscription_response_data {
195         /*! Status code of the response */
196         int status_code;
197         /*! Optional status text */
198         const char *status_text;
199         /*! Optional additional headers to add to the response */
200         struct ast_variable *headers;
201         /*! Optional body to add to the response */
202         struct ast_sip_body *body;
203 };
204
205 #define AST_SIP_MAX_ACCEPT 32
206 enum ast_sip_subscription_notify_reason {
207         /*! Initial NOTIFY for subscription */
208         AST_SIP_SUBSCRIPTION_NOTIFY_REASON_STARTED,
209         /*! Subscription has been renewed */
210         AST_SIP_SUBSCRIPTION_NOTIFY_REASON_RENEWED,
211         /*! Subscription is being terminated */
212         AST_SIP_SUBSCRIPTION_NOTIFY_REASON_TERMINATED,
213         /*! Other unspecified reason */
214         AST_SIP_SUBSCRIPTION_NOTIFY_REASON_OTHER
215 };
216
217 /*! Type used for conveying mailbox state */
218 #define AST_SIP_EXTEN_STATE_DATA "ast_sip_exten_state_data"
219 /*! Type used for extension state/presence */
220 #define AST_SIP_MESSAGE_ACCUMULATOR "ast_sip_message_accumulator"
221
222 /*!
223  * \brief Data used to create bodies for NOTIFY/PUBLISH requests.
224  */
225 struct ast_sip_body_data {
226         /*! The type of the data */
227         const char *body_type;
228         /*! The actual data from which the body is generated */
229         void *body_data;
230 };
231
232 struct ast_sip_notifier {
233         /*!
234          * \brief Default body type defined for the event package this notifier handles.
235          *
236          * Typically, a SUBSCRIBE request will contain one or more Accept headers that tell
237          * what format they expect the body of NOTIFY requests to use. However, every event
238          * package is required to define a default body format type to be used if a SUBSCRIBE
239          * request for the event contains no Accept header.
240          */
241         const char *default_accept;
242         /*!
243          * \brief Called when a SUBSCRIBE arrives attempting to establish a new subscription.
244          *
245          * The notifier is expected to return the response that should be sent to the
246          * SUBSCRIBE request.
247          *
248          * If a 200-class response is returned, then the notifier's notify_required
249          * callback will immediately be called into with a reason of
250          * AST_SIP_SUBSCRIPTION_NOTIFY_REASON_STARTED.
251          *
252          * \param endpoint The endpoint from which we received the SUBSCRIBE
253          * \param resource The name of the resource to which the subscription is being made
254          * \return The response code to send to the SUBSCRIBE.
255          */
256         int (*new_subscribe)(struct ast_sip_endpoint *endpoint, const char *resource);
257         /*!
258          * \brief Called when an inbound subscription has been accepted.
259          *
260          * This is a prime opportunity for notifiers to add any notifier-specific
261          * data to the subscription (such as datastores) that it needs to.
262          *
263          * \note There is no need to send a NOTIFY request when this callback
264          * is called
265          *
266          * \param sub The new subscription
267          * \retval 0 Success
268          * \retval -1 Failure
269          */
270         int (*subscription_established)(struct ast_sip_subscription *sub);
271         /*!
272          * \brief Supply data needed to create a NOTIFY body.
273          *
274          * The returned data must be an ao2 object. The caller of this function
275          * will be responsible for decrementing the refcount of the returned object
276          *
277          * \param sub The subscription
278          * \return An ao2 object that can be used to create a NOTIFY body.
279          */
280         void *(*get_notify_data)(struct ast_sip_subscription *sub);
281 };
282
283 struct ast_sip_subscriber {
284         /*!
285          * \brief A NOTIFY has been received.
286          *
287          * The body of the NOTIFY is provided so that it may be parsed and appropriate
288          * internal state change may be generated.
289          *
290          * The state can be used to determine if the subscription has been terminated
291          * by the far end or if this is just a typical resource state change.
292          *
293          * \param sub The subscription on which the NOTIFY arrived
294          * \param body The body of the NOTIFY
295          * \param state The subscription state
296          */
297         void (*state_change)(struct ast_sip_subscription *sub, pjsip_msg_body *body, enum pjsip_evsub_state state);
298 };
299
300 struct ast_sip_subscription_handler {
301         /*! The name of the event this subscriber deals with */
302         const char *event_name;
303         /*! Type of data used to generate NOTIFY bodies */
304         const char *body_type;
305         /*! The types of body this subscriber accepts. */
306         const char *accept[AST_SIP_MAX_ACCEPT];
307         /*!
308          * \brief Called when a subscription is to be destroyed
309          *
310          * The handler is not expected to send any sort of requests or responses
311          * during this callback. The handler MUST, however, begin the destruction
312          * process for the subscription during this callback.
313          */
314         void (*subscription_shutdown)(struct ast_sip_subscription *subscription);
315         /*!
316          * \brief Converts the subscriber to AMI
317          *
318          * \param sub The subscription
319          * \param buf The string to write AMI data
320          */
321         void (*to_ami)(struct ast_sip_subscription *sub, struct ast_str **buf);
322         /*! Subscriber callbacks for this handler */
323         struct ast_sip_subscriber *subscriber;
324         /*! Notifier callbacks for this handler */
325         struct ast_sip_notifier *notifier;
326         AST_LIST_ENTRY(ast_sip_subscription_handler) next;
327 };
328
329 /*!
330  * \brief Create a new ast_sip_subscription structure
331  *
332  * When a subscriber wishes to create a subscription, it may call this function
333  * to allocate resources and to send the initial SUBSCRIBE out.
334  *
335  * \param subscriber The subscriber that is making the request.
336  * \param endpoint The endpoint to whome the SUBSCRIBE will be sent.
337  * \param resource The resource to place in the SUBSCRIBE's Request-URI.
338  */
339 struct ast_sip_subscription *ast_sip_create_subscription(const struct ast_sip_subscription_handler *handler,
340                 struct ast_sip_endpoint *endpoint, const char *resource);
341
342
343 /*!
344  * \brief Get the endpoint that is associated with this subscription
345  *
346  * This function will increase the reference count of the endpoint. Be sure to
347  * release the reference to it when you are finished with the endpoint.
348  *
349  * \retval NULL Could not get endpoint
350  * \retval non-NULL The endpoint
351  */
352 struct ast_sip_endpoint *ast_sip_subscription_get_endpoint(struct ast_sip_subscription *sub);
353
354 /*!
355  * \brief Get the serializer for the subscription
356  *
357  * Tasks that originate outside of a SIP servant thread should get the serializer
358  * and push the task to the serializer.
359  *
360  * \param sub The subscription
361  * \retval NULL Failure
362  * \retval non-NULL The subscription's serializer
363  */
364 struct ast_taskprocessor *ast_sip_subscription_get_serializer(struct ast_sip_subscription *sub);
365
366 /*!
367  * \brief Notify a SIP subscription of a state change.
368  *
369  * This tells the pubsub core that the state of a subscribed resource has changed.
370  * The pubsub core will generate an appropriate NOTIFY request to send to the
371  * subscriber.
372  *
373  * \param sub The subscription on which a state change is occurring.
374  * \param notify_data Event package-specific data used to create the NOTIFY body.
375  * \param terminate True if this NOTIFY is intended to terminate the subscription.
376  * \retval 0 Success
377  * \retval non-zero Failure
378  */
379 int ast_sip_subscription_notify(struct ast_sip_subscription *sub, struct ast_sip_body_data *notify_data, int terminate);
380
381 /*!
382  * \brief Retrieve the local URI for this subscription
383  *
384  * This is the local URI of the subscribed resource.
385  *
386  * \param sub The subscription
387  * \param[out] buf The buffer into which to store the URI.
388  * \param size The size of the buffer.
389  */
390 void ast_sip_subscription_get_local_uri(struct ast_sip_subscription *sub, char *buf, size_t size);
391
392 /*!
393  * \brief Retrive the remote URI for this subscription
394  *
395  * This is the remote URI as determined by the underlying SIP dialog.
396  *
397  * \param sub The subscription
398  * \param[out] buf The buffer into which to store the URI.
399  * \param size The size of the buffer.
400  */
401 void ast_sip_subscription_get_remote_uri(struct ast_sip_subscription *sub, char *buf, size_t size);
402
403 /*!
404  * \brief Get the name of the subscribed resource.
405  */
406 const char *ast_sip_subscription_get_resource_name(struct ast_sip_subscription *sub);
407
408 /*!
409  * \brief Get whether the subscription has been terminated or not.
410  *
411  * \param sub The subscription.
412  * \retval 0 not terminated.
413  * \retval 1 terminated.
414  * \since 13.4.0
415  */
416 int ast_sip_subscription_is_terminated(const struct ast_sip_subscription *sub);
417
418 /*!
419  * \brief Get a header value for a subscription.
420  *
421  * For notifiers, the headers of the inbound SUBSCRIBE that started the dialog
422  * are stored on the subscription. This method allows access to the header. The
423  * return is the same as pjsip_msg_find_hdr_by_name(), meaning that it is dependent
424  * on the header being searched for.
425  *
426  * \param sub The subscription to search in.
427  * \param header The name of the header to search for.
428  * \return The discovered header, or NULL if the header cannot be found.
429  */
430 void *ast_sip_subscription_get_header(const struct ast_sip_subscription *sub, const char *header);
431
432 /*!
433  * \brief Send a request created via a PJSIP evsub method
434  *
435  * Callers of this function should take care to do so within a SIP servant
436  * thread.
437  *
438  * \param sub The subscription on which to send the request
439  * \param tdata The request to send
440  * \retval 0 Success
441  * \retval non-zero Failure
442  */
443 int ast_sip_subscription_send_request(struct ast_sip_subscription *sub, pjsip_tx_data *tdata);
444
445 /*!
446  * \brief Alternative for ast_datastore_alloc()
447  *
448  * There are two major differences between this and ast_datastore_alloc()
449  * 1) This allocates a refcounted object
450  * 2) This will fill in a uid if one is not provided
451  *
452  * DO NOT call ast_datastore_free() on a datastore allocated in this
453  * way since that function will attempt to free the datastore rather
454  * than play nicely with its refcount.
455  *
456  * \param info Callbacks for datastore
457  * \param uid Identifier for datastore
458  * \retval NULL Failed to allocate datastore
459  * \retval non-NULL Newly allocated datastore
460  */
461 struct ast_datastore *ast_sip_subscription_alloc_datastore(const struct ast_datastore_info *info, const char *uid);
462
463 /*!
464  * \brief Add a datastore to a SIP subscription
465  *
466  * Note that SIP uses reference counted datastores. The datastore passed into this function
467  * must have been allocated using ao2_alloc() or there will be serious problems.
468  *
469  * \param subscription The ssubscription to add the datastore to
470  * \param datastore The datastore to be added to the subscription
471  * \retval 0 Success
472  * \retval -1 Failure
473  */
474 int ast_sip_subscription_add_datastore(struct ast_sip_subscription *subscription, struct ast_datastore *datastore);
475
476 /*!
477  * \brief Retrieve a subscription datastore
478  *
479  * The datastore retrieved will have its reference count incremented. When the caller is done
480  * with the datastore, the reference counted needs to be decremented using ao2_ref().
481  *
482  * \param subscription The subscription from which to retrieve the datastore
483  * \param name The name of the datastore to retrieve
484  * \retval NULL Failed to find the specified datastore
485  * \retval non-NULL The specified datastore
486  */
487 struct ast_datastore *ast_sip_subscription_get_datastore(struct ast_sip_subscription *subscription, const char *name);
488
489 /*!
490  * \brief Remove a subscription datastore from the subscription
491  *
492  * This operation may cause the datastore's free() callback to be called if the reference
493  * count reaches zero.
494  *
495  * \param subscription The subscription to remove the datastore from
496  * \param name The name of the datastore to remove
497  */
498 void ast_sip_subscription_remove_datastore(struct ast_sip_subscription *subscription, const char *name);
499
500 /*!
501  * \brief Register a subscription handler
502  *
503  * \retval 0 Handler was registered successfully
504  * \retval non-zero Handler was not registered successfully
505  */
506 int ast_sip_register_subscription_handler(struct ast_sip_subscription_handler *handler);
507
508 /*!
509  * \brief Unregister a subscription handler
510  */
511 void ast_sip_unregister_subscription_handler(struct ast_sip_subscription_handler *handler);
512
513 /*!
514  * \brief Pubsub body generator
515  *
516  * A body generator is responsible for taking Asterisk content
517  * and converting it into a body format to be placed in an outbound
518  * SIP NOTIFY or PUBLISH request.
519  */
520 struct ast_sip_pubsub_body_generator {
521         /*!
522          * \brief Content type
523          * In "plain/text", "plain" is the type
524          */
525         const char *type;
526         /*!
527          * \brief Content subtype
528          * In "plain/text", "text" is the subtype
529          */
530         const char *subtype;
531         /*! Type of data the body generator takes as input */
532         const char *body_type;
533         /*!
534          * \brief allocate body structure.
535          *
536          * Body generators will have this method called when a NOTIFY
537          * or PUBLISH body needs to be created. The type returned depends on
538          * the type of content being produced for the body. The data parameter
539          * is provided by the subscription handler and will vary between different
540          * event types.
541          *
542          * \param data The subscription data provided by the event handler
543          * \retval non-NULL The allocated body
544          * \retval NULL Failure
545          */
546         void *(*allocate_body)(void *data);
547         /*!
548          * \brief Add content to the body of a SIP request
549          *
550          * The body of the request has already been allocated by the body generator's
551          * allocate_body callback.
552          *
553          * \param body The body of the SIP request. The type is determined by the
554          * content type.
555          * \param data The subscription data used to populate the body. The type is
556          * determined by the content type.
557          */
558         int (*generate_body_content)(void *body, void *data);
559         /*!
560          * \brief Convert the body to a string.
561          *
562          * \param body The request body.
563          * \param str The converted string form of the request body
564          */
565         void (*to_string)(void *body, struct ast_str **str);
566         /*!
567          * \brief Deallocate resources created for the body
568          *
569          * Optional callback to destroy resources allocated for the
570          * message body.
571          *
572          * \param body Body to be destroyed
573          */
574         void (*destroy_body)(void *body);
575         AST_LIST_ENTRY(ast_sip_pubsub_body_generator) list;
576 };
577
578 /*!
579  * \brief Body supplement
580  *
581  * Body supplements provide additions to bodies not already
582  * provided by body generators. This may include proprietary
583  * extensions, optional content, or other nonstandard fare.
584  */
585 struct ast_sip_pubsub_body_supplement {
586         /*!
587          * \brief Content type
588          * In "plain/text", "plain" is the type
589          */
590         const char *type;
591         /*!
592          * \brief Content subtype
593          * In "plain/text", "text" is the subtype
594          */
595         const char *subtype;
596         /*!
597          * \brief Add additional content to a SIP request body.
598          *
599          * A body generator will have already allocated a body and populated
600          * it with base data for the event. The supplement's duty is, if desired,
601          * to extend the body to have optional data beyond what a base RFC specifies.
602          *
603          * \param body The body of the SIP request. The type is determined by the
604          * body generator that allocated the body.
605          * \param data The subscription data used to populate the body. The type is
606          * determined by the content type.
607          */
608         int (*supplement_body)(void *body, void *data);
609         AST_LIST_ENTRY(ast_sip_pubsub_body_supplement) list;
610 };
611
612 /*!
613  * \since 13.0.0
614  * \brief Generate body content for a PUBLISH or NOTIFY
615  *
616  * This function takes a pre-allocated body and calls into registered body
617  * generators in order to fill in the body with appropriate details.
618  * The primary body generator will be called first, followed by the
619  * supplementary body generators
620  *
621  * \param content_type The content type of the body
622  * \param content_subtype The content subtype of the body
623  * \param data The data associated with body generation.
624  * \param[out] str The string representation of the generated body
625  * \retval 0 Success
626  * \retval non-zero Failure
627  */
628 int ast_sip_pubsub_generate_body_content(const char *content_type,
629                 const char *content_subtype, struct ast_sip_body_data *data, struct ast_str **str);
630
631 /*!
632  * \since 13.0.0
633  * \brief Register a body generator with the pubsub core.
634  *
635  * This may fail if an attempt is made to register a primary body supplement
636  * for a given content type if a primary body supplement for that content type
637  * has already been registered.
638  *
639  * \param generator Body generator to register
640  * \retval 0 Success
641  * \retval -1 Failure
642  */
643 int ast_sip_pubsub_register_body_generator(struct ast_sip_pubsub_body_generator *generator);
644
645 /*!
646  * \since 13.0.0
647  * \brief Unregister a body generator with the pubsub core.
648  *
649  * \param generator Body generator to unregister
650  */
651 void ast_sip_pubsub_unregister_body_generator(struct ast_sip_pubsub_body_generator *generator);
652
653 /*!
654  * \since 13.0.0
655  * \brief Register a body generator with the pubsub core.
656  *
657  * This may fail if an attempt is made to register a primary body supplement
658  * for a given content type if a primary body supplement for that content type
659  * has already been registered.
660  *
661  * \param generator Body generator to register
662  * \retval 0 Success
663  * \retval -1 Failure
664  */
665 int ast_sip_pubsub_register_body_supplement(struct ast_sip_pubsub_body_supplement *supplement);
666
667 /*!
668  * \since 13.0.0
669  * \brief Unregister a body generator with the pubsub core.
670  *
671  * \param generator Body generator to unregister
672  */
673 void ast_sip_pubsub_unregister_body_supplement(struct ast_sip_pubsub_body_supplement *supplement);
674
675 /*!
676  * \since 13.0.0
677  * \brief Get the body type used for this subscription
678  */
679 const char *ast_sip_subscription_get_body_type(struct ast_sip_subscription *sub);
680
681 /*!
682  * \since 13.0.0
683  * \brief Get the body subtype used for this subscription
684  */
685 const char *ast_sip_subscription_get_body_subtype(struct ast_sip_subscription *sub);
686
687 /*!
688  * \since 13.6.0
689  * \brief Alert the pubsub core that the subscription is ready for destruction
690  *
691  * \param sub The subscription that is complete
692  * \return Nothing
693  */
694 void ast_sip_subscription_destroy(struct ast_sip_subscription *sub);
695
696 /*! \brief Determines whether the res_pjsip_pubsub module is loaded */
697 #define CHECK_PJSIP_PUBSUB_MODULE_LOADED()                      \
698         do {                                                    \
699                 CHECK_PJSIP_MODULE_LOADED();                    \
700                 if (!ast_module_check("res_pjsip_pubsub.so")) { \
701                         return AST_MODULE_LOAD_DECLINE;         \
702                 }                                               \
703         } while(0)
704
705 #endif /* RES_PJSIP_PUBSUB_H */