d46cbae30d38896c5e5d73dda7ee7c16296a2279
[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 /*!
38  * \brief Callbacks that publication handlers will define
39  */
40 struct ast_sip_publish_handler {
41         /*! \brief The name of the event this handler deals with */
42         const char *event_name;
43
44         /*! \brief Publications */
45         struct ao2_container *publications;
46
47         /*!
48          * \brief Called when a PUBLISH to establish a new publication arrives.
49          *
50          * \param endpoint The endpoint from whom the PUBLISH arrived
51          * \param rdata The PUBLISH request
52          * \retval NULL PUBLISH was not accepted
53          * \retval non-NULL New publication
54          *
55          * \note The callback is expected to send a response for the PUBLISH in success cases.
56          */
57         struct ast_sip_publication *(*new_publication)(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata);
58
59         /*!
60          * \brief Called when a PUBLISH for an existing publication arrives.
61          *
62          * This PUBLISH may be intending to change state or it may be simply renewing
63          * the publication since the publication is nearing expiration. The callback
64          * is expected to send a response to the PUBLISH.
65          *
66          * \param pub The publication on which the PUBLISH arrived
67          * \param rdata The PUBLISH request
68          * \retval 0 Publication was accepted
69          * \retval non-zero Publication was denied
70          *
71          * \note The callback is expected to send a response for the PUBLISH.
72          */
73         int (*publish_refresh)(struct ast_sip_publication *pub, pjsip_rx_data *rdata);
74
75         /*!
76          * \brief Called when a publication has reached its expiration.
77          */
78         void (*publish_expire)(struct ast_sip_publication *pub);
79
80         /*!
81          * \brief Called when a PUBLISH arrives to terminate a publication.
82          *
83          * \param pub The publication that is terminating
84          * \param rdata The PUBLISH request terminating the publication
85          *
86          * \note The callback is expected to send a response for the PUBLISH.
87          */
88         void (*publish_termination)(struct ast_sip_publication *pub, pjsip_rx_data *rdata);
89
90         AST_LIST_ENTRY(ast_sip_publish_handler) next;
91 };
92
93 /*!
94  * \brief Create a new publication
95  *
96  * Publication handlers should call this when a PUBLISH arrives to establish a new publication.
97  *
98  * \param endpoint The endpoint from whom the PUBLISHes arrive
99  * \param rdata The PUBLISH that established the publication
100  * \retval NULL Failed to create a publication
101  * \retval non-NULL The newly-created publication
102  */
103 struct ast_sip_publication *ast_sip_create_publication(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata);
104
105 /*!
106  * \brief Given a publication, get the associated endpoint
107  *
108  * \param pub The publication
109  * \retval NULL Failure
110  * \retval non-NULL The associated endpoint
111  */
112 struct ast_sip_endpoint *ast_sip_publication_get_endpoint(struct ast_sip_publication *pub);
113
114 /*!
115  * \brief Create a response to an inbound PUBLISH
116  *
117  * The created response must be sent using ast_sip_publication_send_response
118  *
119  * \param pub The publication
120  * \param status code The status code to place in the response
121  * \param rdata The request to which the response is being made
122  * \param[out] tdata The created response
123  */
124 int ast_sip_publication_create_response(struct ast_sip_publication *pub, int status_code, pjsip_rx_data *rdata,
125         pjsip_tx_data **tdata);
126
127 /*!
128  * \brief Send a response for an inbound PUBLISH
129  *
130  * \param pub The publication
131  * \param rdata The request to which the response was made
132  * \param tdata The response to the request
133  */
134 pj_status_t ast_sip_publication_send_response(struct ast_sip_publication *pub, pjsip_rx_data *rdata,
135         pjsip_tx_data *tdata);
136
137 /*!
138  * \brief Register a publish handler
139  *
140  * \retval 0 Handler was registered successfully
141  * \retval non-zero Handler was not registered successfully
142  */
143 int ast_sip_register_publish_handler(struct ast_sip_publish_handler *handler);
144
145 /*!
146  * \brief Unregister a publish handler
147  */
148 void ast_sip_unregister_publish_handler(struct ast_sip_publish_handler *handler);
149
150 /*!
151  * \brief Add a datastore to a SIP publication
152  *
153  * Note that SIP uses reference counted datastores. The datastore passed into this function
154  * must have been allocated using ao2_alloc() or there will be serious problems.
155  *
156  * \param publication The publication to add the datastore to
157  * \param datastore The datastore to be added to the subscription
158  * \retval 0 Success
159  * \retval -1 Failure
160  */
161 int ast_sip_publication_add_datastore(struct ast_sip_publication *publication, struct ast_datastore *datastore);
162
163 /*!
164  * \brief Retrieve a publication datastore
165  *
166  * The datastore retrieved will have its reference count incremented. When the caller is done
167  * with the datastore, the reference counted needs to be decremented using ao2_ref().
168  *
169  * \param publication The publication from which to retrieve the datastore
170  * \param name The name of the datastore to retrieve
171  * \retval NULL Failed to find the specified datastore
172  * \retval non-NULL The specified datastore
173  */
174 struct ast_datastore *ast_sip_publication_get_datastore(struct ast_sip_publication *publication, const char *name);
175
176 /*!
177  * \brief Remove a publication datastore from the publication
178  *
179  * This operation may cause the datastore's free() callback to be called if the reference
180  * count reaches zero.
181  *
182  * \param publication The publication to remove the datastore from
183  * \param name The name of the datastore to remove
184  */
185 void ast_sip_publication_remove_datastore(struct ast_sip_publication *publication, const char *name);
186
187 /*!
188  * \brief Opaque structure representing an RFC 3265 SIP subscription
189  */
190 struct ast_sip_subscription;
191
192 /*!
193  * \brief Role for the subscription that is being created
194  */
195 enum ast_sip_subscription_role {
196         /* Sending SUBSCRIBEs, receiving NOTIFYs */
197         AST_SIP_SUBSCRIBER,
198         /* Sending NOTIFYs, receiving SUBSCRIBEs */
199         AST_SIP_NOTIFIER,
200 };
201
202 /*!
203  * \brief Data for responses to SUBSCRIBEs and NOTIFIEs
204  *
205  * Some of PJSIP's evsub callbacks expect us to provide them
206  * with data so that they can craft a response rather than have
207  * us create our own response.
208  *
209  * Filling in the structure is optional, since the framework
210  * will automatically respond with a 200 OK response if we do
211  * not provide it with any additional data.
212  */
213 struct ast_sip_subscription_response_data {
214         /*! Status code of the response */
215         int status_code;
216         /*! Optional status text */
217         const char *status_text;
218         /*! Optional additional headers to add to the response */
219         struct ast_variable *headers;
220         /*! Optional body to add to the response */
221         struct ast_sip_body *body;
222 };
223
224 #define AST_SIP_MAX_ACCEPT 32
225
226 struct ast_sip_subscription_handler {
227         /*! The name of the event this handler deals with */
228         const char *event_name;
229         /*! The types of body this handler accepts.
230          *
231          * \note This option has no bearing when the handler is used in the
232          * notifier role. When in a subscriber role, this header is used to
233          * populate the Accept: header of an outbound SUBSCRIBE request
234          */
235         const char *accept[AST_SIP_MAX_ACCEPT];
236         /*!
237          * \brief Default body type defined for the event package this handler handles.
238          *
239          * Typically, a SUBSCRIBE request will contain one or more Accept headers that tell
240          * what format they expect the body of NOTIFY requests to use. However, every event
241          * package is required to define a default body format type to be used if a SUBSCRIBE
242          * request for the event contains no Accept header.
243          */
244         const char *default_accept;
245         /*!
246          * \brief Called when a subscription is to be destroyed
247          *
248          * This is a subscriber and notifier callback.
249          *
250          * The handler is not expected to send any sort of requests or responses
251          * during this callback. The handler MUST, however, begin the destruction
252          * process for the subscription during this callback.
253          */
254         void (*subscription_shutdown)(struct ast_sip_subscription *subscription);
255
256         /*!
257          * \brief Called when a SUBSCRIBE arrives in order to create a new subscription
258          *
259          * This is a notifier callback.
260          *
261          * If the notifier wishes to accept the subscription, then it can create
262          * a new ast_sip_subscription to do so.
263          *
264          * If the notifier chooses to create a new subscription, then it must accept
265          * the incoming subscription using pjsip_evsub_accept() and it must also
266          * send an initial NOTIFY with the current subscription state.
267          *
268          * \param endpoint The endpoint from which we received the SUBSCRIBE
269          * \param rdata The SUBSCRIBE request
270          * \retval NULL The SUBSCRIBE has not been accepted
271          * \retval non-NULL The newly-created subscription
272          */
273         struct ast_sip_subscription *(*new_subscribe)(struct ast_sip_endpoint *endpoint,
274                         pjsip_rx_data *rdata);
275
276         /*!
277          * \brief Called when an endpoint renews a subscription.
278          *
279          * This is a notifier callback.
280          *
281          * Because of the way that the PJSIP evsub framework works, it will automatically
282          * send a response to the SUBSCRIBE. However, the subscription handler must send
283          * a NOTIFY with the current subscription state when this callback is called.
284          *
285          * The response_data that is passed into this callback is used to craft what should
286          * be in the response to the incoming SUBSCRIBE. It is initialized with a 200 status
287          * code and all other parameters are empty.
288          *
289          * \param sub The subscription that is being renewed
290          * \param rdata The SUBSCRIBE request in question
291          * \param[out] response_data Data pertaining to the SIP response that should be
292          * sent to the SUBSCRIBE
293          */
294         void (*resubscribe)(struct ast_sip_subscription *sub,
295                         pjsip_rx_data *rdata, struct ast_sip_subscription_response_data *response_data);
296
297         /*!
298          * \brief Called when a subscription times out.
299          *
300          * This is a notifier callback
301          *
302          * This indicates that the subscription has timed out. The subscription handler is
303          * expected to send a NOTIFY that terminates the subscription.
304          *
305          * \param sub The subscription that has timed out
306          */
307         void (*subscription_timeout)(struct ast_sip_subscription *sub);
308
309         /*!
310          * \brief Called when a subscription is terminated via a SUBSCRIBE or NOTIFY request
311          *
312          * This is a notifier and subscriber callback.
313          *
314          * The PJSIP subscription framework will automatically send the response to the
315          * request. If a notifier receives this callback, then the subscription handler
316          * is expected to send a final NOTIFY to terminate the subscription.
317          *
318          * \param sub The subscription being terminated
319          * \param rdata The request that terminated the subscription
320          */
321         void (*subscription_terminated)(struct ast_sip_subscription *sub, pjsip_rx_data *rdata);
322
323         /*!
324          * \brief Called when a subscription handler's outbound NOTIFY receives a response
325          *
326          * This is a notifier callback.
327          *
328          * \param sub The subscription
329          * \param rdata The NOTIFY response
330          */
331         void (*notify_response)(struct ast_sip_subscription *sub, pjsip_rx_data *rdata);
332
333         /*!
334          * \brief Called when a subscription handler receives an inbound NOTIFY
335          *
336          * This is a subscriber callback.
337          *
338          * Because of the way that the PJSIP evsub framework works, it will automatically
339          * send a response to the NOTIFY. By default this will be a 200 OK response, but
340          * this callback can change details of the response by returning response data
341          * to use.
342          *
343          * The response_data that is passed into this callback is used to craft what should
344          * be in the response to the incoming SUBSCRIBE. It is initialized with a 200 status
345          * code and all other parameters are empty.
346          *
347          * \param sub The subscription
348          * \param rdata The NOTIFY request
349          * \param[out] response_data Data pertaining to the SIP response that should be
350          * sent to the SUBSCRIBE
351          */
352         void (*notify_request)(struct ast_sip_subscription *sub,
353                         pjsip_rx_data *rdata, struct ast_sip_subscription_response_data *response_data);
354
355         /*!
356          * \brief Called when it is time for a subscriber to resubscribe
357          *
358          * This is a subscriber callback.
359          *
360          * The subscriber can reresh the subscription using the pjsip_evsub_initiate()
361          * function.
362          *
363          * \param sub The subscription to refresh
364          * \retval 0 Success
365          * \retval non-zero Failure
366          */
367         int (*refresh_subscription)(struct ast_sip_subscription *sub);
368
369         /*!
370          * \brief Converts the subscriber to AMI
371          *
372          * This is a subscriber callback.
373          *
374          * \param sub The subscription
375          * \param buf The string to write AMI data
376          */
377         void (*to_ami)(struct ast_sip_subscription *sub, struct ast_str **buf);
378         AST_LIST_ENTRY(ast_sip_subscription_handler) next;
379 };
380
381 /*!
382  * \brief Create a new ast_sip_subscription structure
383  *
384  * In most cases the pubsub core will create a general purpose subscription
385  * within PJSIP. However, PJSIP provides enhanced support for the following
386  * event packages:
387  *
388  * presence
389  * message-summary
390  *
391  * If either of these events are handled by the subscription handler, then
392  * the special-purpose event subscriptions will be created within PJSIP,
393  * and it will be expected that your subscription handler make use of the
394  * special PJSIP APIs.
395  *
396  * \param handler The subsription handler for this subscription
397  * \param role Whether we are acting as subscriber or notifier for this subscription
398  * \param endpoint The endpoint involved in this subscription
399  * \param rdata If acting as a notifier, the SUBSCRIBE request that triggered subscription creation
400  */
401 struct ast_sip_subscription *ast_sip_create_subscription(const struct ast_sip_subscription_handler *handler,
402                 enum ast_sip_subscription_role role, struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata);
403
404
405 /*!
406  * \brief Get the endpoint that is associated with this subscription
407  *
408  * This function will increase the reference count of the endpoint. Be sure to
409  * release the reference to it when you are finished with the endpoint.
410  *
411  * \retval NULL Could not get endpoint
412  * \retval non-NULL The endpoint
413  */
414 struct ast_sip_endpoint *ast_sip_subscription_get_endpoint(struct ast_sip_subscription *sub);
415
416 /*!
417  * \brief Get the serializer for the subscription
418  *
419  * Tasks that originate outside of a SIP servant thread should get the serializer
420  * and push the task to the serializer.
421  *
422  * \param sub The subscription
423  * \retval NULL Failure
424  * \retval non-NULL The subscription's serializer
425  */
426 struct ast_taskprocessor *ast_sip_subscription_get_serializer(struct ast_sip_subscription *sub);
427
428 /*!
429  * \brief Get the underlying PJSIP evsub structure
430  *
431  * This is useful when wishing to call PJSIP's API calls in order to
432  * create SUBSCRIBEs, NOTIFIES, etc. as well as get subscription state
433  *
434  * This function, as well as all methods called on the pjsip_evsub should
435  * be done in a SIP servant thread.
436  *
437  * \param sub The subscription
438  * \retval NULL Failure
439  * \retval non-NULL The underlying pjsip_evsub
440  */
441 pjsip_evsub *ast_sip_subscription_get_evsub(struct ast_sip_subscription *sub);
442
443 /*!
444  * \brief Get the underlying PJSIP dialog structure
445  *
446  * Call this function when information needs to be retrieved from the
447  * underlying pjsip dialog.
448  *
449  * This function, as well as all methods called on the pjsip_evsub should
450  * be done in a SIP servant thread.
451  *
452  * \param sub The subscription
453  * \retval NULL Failure
454  * \retval non-NULL The underlying pjsip_dialog
455  */
456 pjsip_dialog *ast_sip_subscription_get_dlg(struct ast_sip_subscription *sub);
457
458 /*!
459  * \brief Accept a subscription request
460  *
461  * \param sub The subscription to be accepted
462  * \param rdata The received subscription request
463  * \param response The response code to send
464  *
465  * \retval 0 Success
466  * \retval non-zero Failure
467  */
468 int ast_sip_subscription_accept(struct ast_sip_subscription *sub, pjsip_rx_data *rdata, int response);
469
470 /*!
471  * \brief Send a request created via a PJSIP evsub method
472  *
473  * Callers of this function should take care to do so within a SIP servant
474  * thread.
475  *
476  * \param sub The subscription on which to send the request
477  * \param tdata The request to send
478  * \retval 0 Success
479  * \retval non-zero Failure
480  */
481 int ast_sip_subscription_send_request(struct ast_sip_subscription *sub, pjsip_tx_data *tdata);
482
483 /*!
484  * \brief Alternative for ast_datastore_alloc()
485  *
486  * There are two major differences between this and ast_datastore_alloc()
487  * 1) This allocates a refcounted object
488  * 2) This will fill in a uid if one is not provided
489  *
490  * DO NOT call ast_datastore_free() on a datastore allocated in this
491  * way since that function will attempt to free the datastore rather
492  * than play nicely with its refcount.
493  *
494  * \param info Callbacks for datastore
495  * \param uid Identifier for datastore
496  * \retval NULL Failed to allocate datastore
497  * \retval non-NULL Newly allocated datastore
498  */
499 struct ast_datastore *ast_sip_subscription_alloc_datastore(const struct ast_datastore_info *info, const char *uid);
500
501 /*!
502  * \brief Add a datastore to a SIP subscription
503  *
504  * Note that SIP uses reference counted datastores. The datastore passed into this function
505  * must have been allocated using ao2_alloc() or there will be serious problems.
506  *
507  * \param subscription The ssubscription to add the datastore to
508  * \param datastore The datastore to be added to the subscription
509  * \retval 0 Success
510  * \retval -1 Failure
511  */
512 int ast_sip_subscription_add_datastore(struct ast_sip_subscription *subscription, struct ast_datastore *datastore);
513
514 /*!
515  * \brief Retrieve a subscription datastore
516  *
517  * The datastore retrieved will have its reference count incremented. When the caller is done
518  * with the datastore, the reference counted needs to be decremented using ao2_ref().
519  *
520  * \param subscription The subscription from which to retrieve the datastore
521  * \param name The name of the datastore to retrieve
522  * \retval NULL Failed to find the specified datastore
523  * \retval non-NULL The specified datastore
524  */
525 struct ast_datastore *ast_sip_subscription_get_datastore(struct ast_sip_subscription *subscription, const char *name);
526
527 /*!
528  * \brief Remove a subscription datastore from the subscription
529  *
530  * This operation may cause the datastore's free() callback to be called if the reference
531  * count reaches zero.
532  *
533  * \param subscription The subscription to remove the datastore from
534  * \param name The name of the datastore to remove
535  */
536 void ast_sip_subscription_remove_datastore(struct ast_sip_subscription *subscription, const char *name);
537
538 /*!
539  * \brief Register a subscription handler
540  *
541  * \retval 0 Handler was registered successfully
542  * \retval non-zero Handler was not registered successfully
543  */
544 int ast_sip_register_subscription_handler(struct ast_sip_subscription_handler *handler);
545
546 /*!
547  * \brief Unregister a subscription handler
548  */
549 void ast_sip_unregister_subscription_handler(struct ast_sip_subscription_handler *handler);
550
551 /*!
552  * \brief Pubsub body generator
553  *
554  * A body generator is responsible for taking Asterisk content
555  * and converting it into a body format to be placed in an outbound
556  * SIP NOTIFY or PUBLISH request.
557  */
558 struct ast_sip_pubsub_body_generator {
559         /*!
560          * \brief Content type
561          * In "plain/text", "plain" is the type
562          */
563         const char *type;
564         /*!
565          * \brief Content subtype
566          * In "plain/text", "text" is the subtype
567          */
568         const char *subtype;
569         /*!
570          * \brief allocate body structure.
571          *
572          * Body generators will have this method called when a NOTIFY
573          * or PUBLISH body needs to be created. The type returned depends on
574          * the type of content being produced for the body. The data parameter
575          * is provided by the subscription handler and will vary between different
576          * event types.
577          *
578          * \param data The subscription data provided by the event handler
579          * \retval non-NULL The allocated body
580          * \retval NULL Failure
581          */
582         void *(*allocate_body)(void *data);
583         /*!
584          * \brief Add content to the body of a SIP request
585          *
586          * The body of the request has already been allocated by the body generator's
587          * allocate_body callback.
588          *
589          * \param body The body of the SIP request. The type is determined by the
590          * content type.
591          * \param data The subscription data used to populate the body. The type is
592          * determined by the content type.
593          */
594         int (*generate_body_content)(void *body, void *data);
595         /*!
596          * \brief Convert the body to a string.
597          *
598          * \param body The request body.
599          * \param str The converted string form of the request body
600          */
601         void (*to_string)(void *body, struct ast_str **str);
602         /*!
603          * \brief Deallocate resources created for the body
604          *
605          * Optional callback to destroy resources allocated for the
606          * message body.
607          *
608          * \param body Body to be destroyed
609          */
610         void (*destroy_body)(void *body);
611         AST_LIST_ENTRY(ast_sip_pubsub_body_generator) list;
612 };
613
614 /*!
615  * \brief Body supplement
616  *
617  * Body supplements provide additions to bodies not already
618  * provided by body generators. This may include proprietary
619  * extensions, optional content, or other nonstandard fare.
620  */
621 struct ast_sip_pubsub_body_supplement {
622         /*!
623          * \brief Content type
624          * In "plain/text", "plain" is the type
625          */
626         const char *type;
627         /*!
628          * \brief Content subtype
629          * In "plain/text", "text" is the subtype
630          */
631         const char *subtype;
632         /*!
633          * \brief Add additional content to a SIP request body.
634          *
635          * A body generator will have already allocated a body and populated
636          * it with base data for the event. The supplement's duty is, if desired,
637          * to extend the body to have optional data beyond what a base RFC specifies.
638          *
639          * \param body The body of the SIP request. The type is determined by the
640          * body generator that allocated the body.
641          * \param data The subscription data used to populate the body. The type is
642          * determined by the content type.
643          */
644         int (*supplement_body)(void *body, void *data);
645         AST_LIST_ENTRY(ast_sip_pubsub_body_supplement) list;
646 };
647
648 /*!
649  * \since 13.0.0
650  * \brief Generate body content for a PUBLISH or NOTIFY
651  *
652  * This function takes a pre-allocated body and calls into registered body
653  * generators in order to fill in the body with appropriate details.
654  * The primary body generator will be called first, followed by the
655  * supplementary body generators
656  *
657  * \param content_type The content type of the body
658  * \param content_subtype The content subtype of the body
659  * \param data The data associated with body generation.
660  * \param[out] str The string representation of the generated body
661  * \retval 0 Success
662  * \retval non-zero Failure
663  */
664 int ast_sip_pubsub_generate_body_content(const char *content_type,
665                 const char *content_subtype, void *data, struct ast_str **str);
666
667 /*!
668  * \since 13.0.0
669  * \brief Register a body generator with the pubsub core.
670  *
671  * This may fail if an attempt is made to register a primary body supplement
672  * for a given content type if a primary body supplement for that content type
673  * has already been registered.
674  *
675  * \param generator Body generator to register
676  * \retval 0 Success
677  * \retval -1 Failure
678  */
679 int ast_sip_pubsub_register_body_generator(struct ast_sip_pubsub_body_generator *generator);
680
681 /*!
682  * \since 13.0.0
683  * \brief Unregister a body generator with the pubsub core.
684  *
685  * \param generator Body generator to unregister
686  */
687 void ast_sip_pubsub_unregister_body_generator(struct ast_sip_pubsub_body_generator *generator);
688
689 /*!
690  * \since 13.0.0
691  * \brief Register a body generator with the pubsub core.
692  *
693  * This may fail if an attempt is made to register a primary body supplement
694  * for a given content type if a primary body supplement for that content type
695  * has already been registered.
696  *
697  * \param generator Body generator to register
698  * \retval 0 Success
699  * \retval -1 Failure
700  */
701 int ast_sip_pubsub_register_body_supplement(struct ast_sip_pubsub_body_supplement *supplement);
702
703 /*!
704  * \since 13.0.0
705  * \brief Unregister a body generator with the pubsub core.
706  *
707  * \param generator Body generator to unregister
708  */
709 void ast_sip_pubsub_unregister_body_supplement(struct ast_sip_pubsub_body_supplement *supplement);
710
711 /*!
712  * \since 13.0.0
713  * \brief Get the body type used for this subscription
714  */
715 const char *ast_sip_subscription_get_body_type(struct ast_sip_subscription *sub);
716
717 /*!
718  * \since 13.0.0
719  * \brief Get the body subtype used for this subscription
720  */
721 const char *ast_sip_subscription_get_body_subtype(struct ast_sip_subscription *sub);
722
723 #endif /* RES_PJSIP_PUBSUB_H */