1 /*! \file   plugin.h
2  * \author Lorenzo Miniero <lorenzo@meetecho.com>
3  * \copyright GNU General Public License v3
4  * \brief  Plugin-Core communication
5  * \details  This header contains the definition of the callbacks both
6  * the Janus core and all the plugins need to implement to interact with
7  * each other. The structures to make the communication possible are
8  * defined here as well.
9  *
10  * In particular, the Janus core implements the \c janus_callbacks interface.
11  * This means that, as a plugin, you can use the methods it exposes to
12  * contact the core, e.g., in order to have it relay a message, event
13  * or RTP/RTCP packet to the peer you're handling. In particular, the
14  * methods the core exposes to plugins are:
15  *
16  * - \c push_event(): to send a JSON message/event to the peer (with or without
17  * an attached JSEP formatted SDP to negotiate a WebRTC PeerConnection);
18  * the syntax of the message/event is completely up to you, the only
19  * important thing is that it MUST be a JSON object, as it will be included
20  * as such within the Janus session/handle protocol;
21  * - \c relay_rtp(): to send/relay the peer an RTP packet;
22  * - \c relay_rtcp(): to send/relay the peer an RTCP message.
23  * - \c relay_data(): to send/relay the peer a SCTP DataChannel message.
24  *
25  * On the other hand, a plugin that wants to register at the Janus core
26  * needs to implement the \c janus_plugin interface. Besides, as a
27  * plugin is a shared object, and as such external to the core itself,
28  * in order to be dynamically loaded at startup it needs to implement
29  * the \c create_p() hook as well, that should return a pointer to the
30  * plugin instance. This is an example of such a step:
31  *
32 \verbatim
33 static janus_plugin myplugin = {
34 	[..]
35 };
36 
37 janus_plugin *create(void) {
38 	JANUS_LOG(LOG_VERB, , "%s created!\n", MY_PLUGIN_NAME);
39 	return &myplugin;
40 }
41 \endverbatim
42  *
43  * This will make sure that your plugin is loaded at startup by the Janus core,
44  * if it is deployed in the proper folder.
45  *
46  * As anticipated and described in the above example, a plugin must basically
47  * be an instance of the \c janus_plugin type. As such, it must implement
48  * the following methods and callbacks for the core:
49  *
50  * - \c init(): this is called by the Janus core as soon as your plugin is started;
51  * this is where you should setup your plugin (e.g., static stuff and reading
52  * the configuration file);
53  * - \c destroy(): on the other hand, this is called by the core when it
54  * is shutting down, and your plugin should too;
55  * - \c get_api_compatibility(): this method MUST return JANUS_PLUGIN_API_VERSION;
56  * - \c get_version(): this method should return a numeric version identifier (e.g., 3);
57  * - \c get_version_string(): this method should return a verbose version identifier (e.g., "v1.0.1");
58  * - \c get_description(): this method should return a verbose description of your plugin (e.g., "This is my awesome plugin that does this and that");
59  * - \c get_name(): this method should return a short display name for your plugin (e.g., "My Awesome Plugin");
60  * - \c get_package(): this method should return a unique package identifier for your plugin (e.g., "janus.plugin.myplugin");
61  * - \c create_session(): this method is called by the core to create a session between you and a peer;
62  * - \c handle_message(): a callback to notify you the peer sent you a message/request;
63  * - \c handle_admin_message(): a callback to notify you a message/request came from the Admin API;
64  * - \c setup_media(): a callback to notify you the peer PeerConnection is now ready to be used;
65  * - \c incoming_rtp(): a callback to notify you a peer has sent you a RTP packet;
66  * - \c incoming_rtcp(): a callback to notify you a peer has sent you a RTCP message;
67  * - \c incoming_data(): a callback to notify you a peer has sent you a message on a SCTP DataChannel;
68  * - \c data_ready(): a callback to notify you data can be sent on the SCTP DataChannel;
69  * - \c slow_link(): a callback to notify you a peer has sent a lot of NACKs recently, and the media path may be slow;
70  * - \c hangup_media(): a callback to notify you the peer PeerConnection has been closed (e.g., after a DTLS alert);
71  * - \c query_session(): this method is called by the core to get plugin-specific info on a session between you and a peer;
72  * - \c destroy_session(): this method is called by the core to destroy a session between you and a peer.
73  *
74  * All the above methods and callbacks, except for \c incoming_rtp ,
75  * \c incoming_rtcp , \c incoming_data and \c slow_link , are mandatory:
76  * the Janus core will reject a plugin that doesn't implement any of the
77  * mandatory callbacks. The previously mentioned ones, instead, are
78  * optional, so you're free to implement only those you care about. If
79  * your plugin will not handle any data channel, for instance, it makes
80  * sense to not implement the \c incoming_data callback at all. At the
81  * same time, if your plugin is ONLY going to use data channels and
82  * can't care less about RTP or RTCP, \c incoming_rtp and \c incoming_rtcp
83  * can be left out. Finally, \c slow_link is just there as a helper, some
84  * additional information you may be interested about, but you're not
85  * forced to receive it if you don't care.
86  *
87  * The Janus core \c janus_callbacks interface is provided to a plugin, together
88  * with the path to the configurations files folder, in the \c init() method.
89  * This path can be used to read and parse a configuration file for the
90  * plugin: the plugins we made available out of the box use the package
91  * name as a name for the file (e.g., \c janus.plugin.echotest.cfg for
92  * the Echo Test plugin), but you're free to use a different one, as long
93  * as it doesn't collide with existing ones. Besides, the existing plugins
94  * use the same INI format for configuration files the core uses (relying
95  * on the \c janus_config helpers for the purpose) but again, if you prefer
96  * a different format (XML, JSON, etc.) that's up to you.
97  *
98  * Both the the Janus core and a plugin can have several different sessions
99  * with the same and/or different peers: to match a specific session,
100  * a plugin can rely on a mapping called janus_plugin_session that
101  * is what all the communication between the plugins and the core
102  * (that is, both methods invoked by the core and callbacks invoked by
103  * the plugins) will make use of. See the janus_videoroom.c plugin for
104  * an example of multiple handles associated to the same peer.
105  *
106  * All messages/requests/events sent to and received from a plugin are
107  * asynchronous, meaning there's no way to immediately reply to a message
108  * sent by a browser, for instance. Messages/requests coming from browsers
109  * in a \c handle_message() callback, though, have a transaction
110  * identifier, which you can use in a \c push_event() reply to allow the
111  * browser to match it to the original request, if needed.
112  *
113  * As anticipated, both \c handle_message() and \c push_event() can attach
114  * a JSEP/SDP payload. This means that a browser, for instance, can attach
115  * a JSEP/SDP offer to negotiate a WebRTC PeerConnection with a plugin: the plugin
116  * would then need to provide, immediately or not, a JSEP/SDP answer to
117  * do so. At the same time, a plugin may want to originate the call instead:
118  * in that case, the plugin would attach a JSEP/SDP offer in a \c push_event()
119  * call, to which the browser would then need to reply with a JSEP/SDP answer,
120  * as described in \ref JS. Renegotiating a session can be done using the
121  * same mechanism above: in case plugins want to force an ICE restart,
122  * though, they must add a boolean property called \c restart to the JSEP
123  * object before passing it to the core. Notice that the core adds a property
124  * called \c update whenever the remote user is requesting a renegotiation,
125  * whether it's for ICE restarts or just for some media related change.
126  * \note It's important to notice that, while the Janus core would indeed
127  * take care of the WebRTC PeerConnection setup itself in terms of
128  * ICE/DTLS/RT(C)P on your behalf, plugins are what will actually manipulate
129  * the media flowing around, and as such it's them who are responsible for
130  * what concerns the codec negotiation in a JSEP/SDP offer/answer. This
131  * normally is not something you need to worry about, especially if you're
132  * just moving SDP around (e.g., janus_echotest.c or janus_videocall.c).
133  * If your plugin is going to generate media frames (e.g., as janus_audiobridge.c),
134  * you only support some codecs (e.g., Opus in janus_audiobridge.c) or you
135  * want to use the same SDP offer for several different sessions (e.g., a webinar),
136  * you need to make sure that your offer/answer does not contain anything
137  * you don't support. Besides, you also need to make sure that you use
138  * SDP-provided information (e.g., payload types, increasing versions in
139  * case of renegotiations) coherently.
140  *
141  * \todo Right now plugins can only interact with peers through the Janus core.
142  * Besides, a single PeerConnection can at the moment be used by only one
143  * plugin, as that plugin is actually the "owner" of the PeerConnection itself.
144  *
145  * \ingroup pluginapi
146  * \ref pluginapi
147  */
148 
149 #ifndef JANUS_PLUGIN_H
150 #define JANUS_PLUGIN_H
151 
152 #include <stdlib.h>
153 #include <stdint.h>
154 #include <stdio.h>
155 #include <string.h>
156 #include <ctype.h>
157 #include <unistd.h>
158 #include <inttypes.h>
159 
160 #include <glib.h>
161 
162 #include "refcount.h"
163 
164 
165 /*! \brief Version of the API, to match the one plugins were compiled against
166  *
167  * \note This was added in version 0.0.7 of Janus, to address changes
168  * to the API that might break existing plugin or the core itself. All
169  * plugins MUST implement the get_api_compatibility() method to make
170  * this work. Do NOT try to launch a pre 0.0.7 plugin on a >= 0.0.7
171  * Janus instance or it will crash.
172  *
173  */
174 #define JANUS_PLUGIN_API_VERSION	16
175 
176 /*! \brief Initialization of all plugin properties to NULL
177  *
178  * \note This was added in version 0.0.8 of Janus, to address changes
179  * to the API that might break existing plugin or the core itself. All
180  * plugins MUST add this as the FIRST line when initializing their
181  * plugin structure, e.g.:
182  *
183 \verbatim
184 static janus_plugin janus_echotest_plugin =
185 	{
186 		JANUS_PLUGIN_INIT,
187 
188 		.init = janus_echotest_init,
189 		[..]
190 \endverbatim
191  * */
192 #define JANUS_PLUGIN_INIT(...) {		\
193 		.init = NULL,					\
194 		.destroy = NULL,				\
195 		.get_api_compatibility = NULL,	\
196 		.get_version = NULL,			\
197 		.get_version_string = NULL,		\
198 		.get_description = NULL,		\
199 		.get_name = NULL,				\
200 		.get_author = NULL,				\
201 		.get_package = NULL,			\
202 		.create_session = NULL,			\
203 		.handle_message = NULL,			\
204 		.handle_admin_message = NULL,	\
205 		.setup_media = NULL,			\
206 		.incoming_rtp = NULL,			\
207 		.incoming_rtcp = NULL,			\
208 		.incoming_data = NULL,			\
209 		.data_ready = NULL,				\
210 		.slow_link = NULL,				\
211 		.hangup_media = NULL,			\
212 		.destroy_session = NULL,		\
213 		.query_session = NULL, 			\
214 		## __VA_ARGS__ }
215 
216 
217 /*! \brief Callbacks to contact the Janus core */
218 typedef struct janus_callbacks janus_callbacks;
219 /*! \brief The plugin session and callbacks interface */
220 typedef struct janus_plugin janus_plugin;
221 /*! \brief Plugin-Gateway session mapping */
222 typedef struct janus_plugin_session janus_plugin_session;
223 /*! \brief Result of individual requests passed to plugins */
224 typedef struct janus_plugin_result janus_plugin_result;
225 
226 /*! \brief RTP packet exchanged with the core */
227 typedef struct janus_plugin_rtp janus_plugin_rtp;
228 /*! \brief RTP extensions parsed in an RTP packet */
229 typedef struct janus_plugin_rtp_extensions janus_plugin_rtp_extensions;
230 /*! \brief RTCP message exchanged with the core */
231 typedef struct janus_plugin_rtcp janus_plugin_rtcp;
232 /*! \brief Data message exchanged with the core */
233 typedef struct janus_plugin_data janus_plugin_data;
234 
235 /* Use forward declaration to avoid including jansson.h */
236 typedef struct json_t json_t;
237 
238 /*! \brief Plugin-Gateway session mapping */
239 struct janus_plugin_session {
240 	/*! \brief Opaque pointer to the Janus core-level handle */
241 	void *gateway_handle;
242 	/*! \brief Opaque pointer to the plugin session */
243 	void *plugin_handle;
244 	/*! \brief Whether this mapping has been stopped definitely or not: if so,
245 	 * the plugin shouldn't make use of it anymore */
246 	volatile gint stopped;
247 	/*! \brief Reference counter for this instance */
248 	janus_refcount ref;
249 };
250 
251 /*! \brief The plugin session and callbacks interface */
252 struct janus_plugin {
253 	/*! \brief Plugin initialization/constructor
254 	 * @param[in] callback The callback instance the plugin can use to contact the Janus core
255 	 * @param[in] config_path Path of the folder where the configuration for this plugin can be found
256 	 * @returns 0 in case of success, a negative integer in case of error */
257 	int (* const init)(janus_callbacks *callback, const char *config_path);
258 	/*! \brief Plugin deinitialization/destructor */
259 	void (* const destroy)(void);
260 
261 	/*! \brief Informative method to request the API version this plugin was compiled against
262 	 *  \note This was added in version 0.0.7 of Janus, to address changes
263 	 * to the API that might break existing plugin or the core itself. All
264 	 * plugins MUST implement this method and return JANUS_PLUGIN_API_VERSION
265 	 * to make this work, or they will be rejected by the core. Do NOT try
266 	 * to launch a <= 0.0.7 plugin on a >= 0.0.7 Janus or it will crash. */
267 	int (* const get_api_compatibility)(void);
268 	/*! \brief Informative method to request the numeric version of the plugin */
269 	int (* const get_version)(void);
270 	/*! \brief Informative method to request the string version of the plugin */
271 	const char *(* const get_version_string)(void);
272 	/*! \brief Informative method to request a description of the plugin */
273 	const char *(* const get_description)(void);
274 	/*! \brief Informative method to request the name of the plugin */
275 	const char *(* const get_name)(void);
276 	/*! \brief Informative method to request the author of the plugin */
277 	const char *(* const get_author)(void);
278 	/*! \brief Informative method to request the package name of the plugin (what will be used in web applications to refer to it) */
279 	const char *(* const get_package)(void);
280 
281 	/*! \brief Method to create a new session/handle for a peer
282 	 * @param[in] handle The plugin/gateway session that will be used for this peer
283 	 * @param[out] error An integer that may contain information about any error */
284 	void (* const create_session)(janus_plugin_session *handle, int *error);
285 	/*! \brief Method to handle an incoming message/request from a peer
286 	 * @param[in] handle The plugin/gateway session used for this peer
287 	 * @param[in] transaction The transaction identifier for this message/request
288 	 * @param[in] message The json_t object containing the message/request JSON
289 	 * @param[in] jsep The json_t object containing the JSEP type/SDP, if available
290 	 * @returns A janus_plugin_result instance that may contain a response (for immediate/synchronous replies), an ack
291 	 * (for asynchronously managed requests) or an error */
292 	struct janus_plugin_result * (* const handle_message)(janus_plugin_session *handle, char *transaction, json_t *message, json_t *jsep);
293 	/*! \brief Method to handle an incoming Admin API message/request
294 	 * @param[in] message The json_t object containing the message/request JSON
295 	 * @returns A json_t instance containing the response */
296 	struct json_t * (* const handle_admin_message)(json_t *message);
297 	/*! \brief Callback to be notified when the associated PeerConnection is up and ready to be used
298 	 * @param[in] handle The plugin/gateway session used for this peer */
299 	void (* const setup_media)(janus_plugin_session *handle);
300 	/*! \brief Method to handle an incoming RTP packet from a peer
301 	 * @param[in] handle The plugin/gateway session used for this peer
302 	 * @param[in] packet The RTP packet and related data */
303 	void (* const incoming_rtp)(janus_plugin_session *handle, janus_plugin_rtp *packet);
304 	/*! \brief Method to handle an incoming RTCP packet from a peer
305 	 * @param[in] handle The plugin/gateway session used for this peer
306 	 * @param[in] packet The RTP packet and related data */
307 	void (* const incoming_rtcp)(janus_plugin_session *handle, janus_plugin_rtcp *packet);
308 	/*! \brief Method to handle incoming SCTP/DataChannel data from a peer (text only, for the moment)
309 	 * \note We currently only support text data, binary data will follow... please also notice that
310 	 * DataChannels send unterminated strings, so you'll have to terminate them with a \0 yourself to
311 	 * use them.
312 	 * @param[in] handle The plugin/gateway session used for this peer
313 	 * @param[in] packet The message data and related info */
314 	void (* const incoming_data)(janus_plugin_session *handle, janus_plugin_data *packet);
315 	/*! \brief Method to be notified about the fact that the datachannel is ready to be written
316 	 * \note This is not only called when the PeerConnection first becomes available, but also
317 	 * when the SCTP socket becomes writable again, e.g., because the internal buffer is empty.
318 	 * @param[in] handle The plugin/gateway session used for this peer */
319 	void (* const data_ready)(janus_plugin_session *handle);
320 	/*! \brief Method to be notified by the core when too many NACKs have
321 	 * been received or sent by Janus, and so a slow or potentially
322 	 * unreliable network is to be expected for this peer
323 	 * \note Beware that this callback may be called more than once in a row,
324 	 * (even though never more than once per second), until things go better for that
325 	 * PeerConnection. You may or may not want to handle this callback and
326 	 * act on it, considering you can get bandwidth information from REMB
327 	 * feedback sent by the peer if the browser supports it. Besides, your
328 	 * plugin may not have access to encoder related settings to slow down
329 	 * or decreae the bitrate if required after the callback is called.
330 	 * Nevertheless, it can be useful for debugging, or for informing your
331 	 * users about potential issues that may be happening media-wise.
332 	 * @param[in] handle The plugin/gateway session used for this peer
333 	 * @param[in] uplink Whether this is related to the uplink (Janus to peer)
334 	 * or downlink (peer to Janus)
335 	 * @param[in] video Whether this is related to an audio or a video stream */
336 	void (* const slow_link)(janus_plugin_session *handle, gboolean uplink, gboolean video);
337 	/*! \brief Callback to be notified about DTLS alerts from a peer (i.e., the PeerConnection is not valid any more)
338 	 * @param[in] handle The plugin/gateway session used for this peer */
339 	void (* const hangup_media)(janus_plugin_session *handle);
340 	/*! \brief Method to destroy a session/handle for a peer
341 	 * @param[in] handle The plugin/gateway session used for this peer
342 	 * @param[out] error An integer that may contain information about any error */
343 	void (* const destroy_session)(janus_plugin_session *handle, int *error);
344 	/*! \brief Method to get plugin-specific info of a session/handle
345 	 *  \note This was added in version 0.0.7 of Janus. Janus assumes
346 	 * the string is always allocated, so don't return constants here
347 	 * @param[in] handle The plugin/gateway session used for this peer
348 	 * @returns A json_t object with the requested info */
349 	json_t *(* const query_session)(janus_plugin_session *handle);
350 
351 };
352 
353 /*! \brief Callbacks to contact the Janus core */
354 struct janus_callbacks {
355 	/*! \brief Callback to push events/messages to a peer
356 	 * @note The Janus core increases the references to both the message and jsep
357 	 * json_t objects. This means that you'll have to decrease your own
358 	 * reference yourself with a \c json_decref after calling push_event.
359 	 * @param[in] handle The plugin/gateway session used for this peer
360 	 * @param[in] plugin The plugin instance that is sending the message/event
361 	 * @param[in] transaction The transaction identifier this message refers to
362 	 * @param[in] message The json_t object containing the JSON message
363 	 * @param[in] jsep The json_t object containing the JSEP type, the SDP attached to the message/event, if any (offer/answer), and whether this is an update */
364 	int (* const push_event)(janus_plugin_session *handle, janus_plugin *plugin, const char *transaction, json_t *message, json_t *jsep);
365 
366 	/*! \brief Callback to relay RTP packets to a peer
367 	 * @param[in] handle The plugin/gateway session used for this peer
368 	 * @param[in] packet The RTP packet and related data */
369 	void (* const relay_rtp)(janus_plugin_session *handle, janus_plugin_rtp *packet);
370 	/*! \brief Callback to relay RTCP messages to a peer
371 	 * @param[in] handle The plugin/gateway session that will be used for this peer
372 	 * @param[in] packet The RTCP packet and related data */
373 	void (* const relay_rtcp)(janus_plugin_session *handle, janus_plugin_rtcp *packet);
374 	/*! \brief Callback to relay SCTP/DataChannel messages to a peer
375 	 * @note The protocol is only used for the first message sent on a new data
376 	 * channel, as it will be used to create it; it will be ignored for following
377 	 * messages on the same label, so you can set NULL after that
378 	 * @param[in] handle The plugin/gateway session that will be used for this peer
379 	 * @param[in] packet The message data and related info */
380 	void (* const relay_data)(janus_plugin_session *handle, janus_plugin_data *packet);
381 
382 	/*! \brief Helper to ask for a keyframe via a RTCP PLI
383 	 * @note This is a shortcut, as it is also possible to do the same by crafting
384 	 * an RTCP PLI message manually, and passing it to the core via relay_rtcp
385 	 * @param[in] handle The plugin/gateway session that will be used for this peer */
386 	void (* const send_pli)(janus_plugin_session *handle);
387 	/*! \brief Helper to ask for a keyframe via a RTCP PLI
388 	 * @note This is a shortcut, as it is also possible to do the same by crafting
389 	 * an RTCP REMB message manually, and passing it to the core via relay_rtcp
390 	 * @param[in] handle The plugin/gateway session that will be used for this peer
391 	 * @param[in] bitrate The bitrate value to send in the REMB message */
392 	void (* const send_remb)(janus_plugin_session *handle, guint32 bitrate);
393 
394 	/*! \brief Callback to ask the core to close a WebRTC PeerConnection
395 	 * \note A call to this method will result in the core invoking the hangup_media
396 	 * callback on this plugin when done
397 	 * @param[in] handle The plugin/gateway session that the PeerConnection is related to */
398 	void (* const close_pc)(janus_plugin_session *handle);
399 	/*! \brief Callback to ask the core to get rid of a plugin/gateway session
400 	 * \note A call to this method will result in the core invoking the destroy_session
401 	 * callback on this plugin when done
402 	 * @param[in] handle The plugin/gateway session to get rid of */
403 	void (* const end_session)(janus_plugin_session *handle);
404 
405 	/*! \brief Callback to check whether the event handlers mechanism is enabled
406 	 * @returns TRUE if it is, FALSE if it isn't (which means notify_event should NOT be called) */
407 	gboolean (* const events_is_enabled)(void);
408 	/*! \brief Callback to notify an event to the registered and subscribed event handlers
409 	 * \note Don't unref the event object, the core will do that for you
410 	 * @param[in] plugin The plugin originating the event
411 	 * @param[in] handle The plugin/gateway session originating the event, if any
412 	 * @param[in] event The event to notify as a Jansson json_t object */
413 	void (* const notify_event)(janus_plugin *plugin, janus_plugin_session *handle, json_t *event);
414 
415 	/*! \brief Method to check whether the core is using signed tokens
416 	 * @returns TRUE if signed tokens are in use, FALSE otherwise */
417 	gboolean (* const auth_is_signed)(void);
418 	/*! \brief Method to check whether a signed token is valid
419 	 * \note accepts only tokens with the plugin identifier as realm
420 	 * @param[in] token The token to validate
421 	 * @returns TRUE if the signature is valid and not expired, FALSE otherwise */
422 	gboolean (* const auth_is_signature_valid)(janus_plugin *plugin, const char *token);
423 	/*! \brief Method to verify a signed token grants access to a descriptor
424 	 * \note accepts only tokens with the plugin identifier as realm
425 	 * @param[in] token The token to validate
426 	 * @param[in] desc The descriptor to search for
427 	 * @returns TRUE if the token is valid, not expired and contains the descriptor, FALSE otherwise */
428 	gboolean (* const auth_signature_contains)(janus_plugin *plugin, const char *token, const char *descriptor);
429 };
430 
431 /*! \brief The hook that plugins need to implement to be created from the Janus core */
432 typedef janus_plugin* create_p(void);
433 
434 
435 /** @name Janus plugin results
436  * @brief When a client sends a message to a plugin (e.g., a request or a
437  * command) this is notified to the plugin through a handle_message()
438  * callback. The plugin can then either handle the request immediately
439  * and provide a response (synchronous approach) or decide to queue it
440  * and process it later (asynchronous approach). In both cases the plugin
441  * must return a janus_plugin_result instance to the core, that will allow
442  * the client to: 1. know whether a response is immediately available or
443  * it will be later on through notifications, and 2. what the actual content
444  * of the result might be. Of course, notifications related to the
445  * transaction may occur later on even for synchronous requests, if the
446  * plugin was implemented with use cases that envisage this approach.
447  * @note An error may be returned as well, but this would cause a core-level
448  * error to be returned to the client. If you want to provide indications
449  * about a failed operation for application-level reason, the correct
450  * approach is to return a success with a plugin-specific payload describing
451  * the error.
452  */
453 ///@{
454 /*! \brief Result types */
455 typedef enum janus_plugin_result_type {
456 	/*! \brief A severe error happened (not an application level error) */
457 	JANUS_PLUGIN_ERROR = -1,
458 	/*! \brief The request was correctly handled and a response is provided (synchronous) */
459 	JANUS_PLUGIN_OK,
460 	/*! \brief The request was correctly handled and notifications will follow with more info (asynchronous) */
461 	JANUS_PLUGIN_OK_WAIT,
462 } janus_plugin_result_type;
463 
464 /*! \brief Janus plugin result */
465 struct janus_plugin_result {
466 	/*! \brief Result type */
467 	janus_plugin_result_type type;
468 	/*! \brief Text associated with this plugin result.
469 	 * @note This is ONLY used for JANUS_PLUGIN_OK_WAIT (to provide hints on
470 	 * why a request is being handled asynchronously) and JANUS_PLUGIN_ERROR
471 	 * (to provide a reason for the error). It is ignored for JANUS_PLUGIN_OK.
472 	 * Besides, it is NOT freed when destroying the janus_plugin_result instance,
473 	 * so if you allocated a string for that, you'll have to free it yourself. */
474 	const char *text;
475 	/*! \brief Result content
476 	 * @note This is ONLY used for JANUS_PLUGIN_OK, and is ignored otherwise.
477 	 * It MUST be a valid JSON payload (even when returning application
478 	 * level errors). Its reference is decremented automatically when destroying
479 	 * the janus_plugin_result instance, so if your plugin wants to re-use the
480 	 * same object for multiple responses, you jave to \c json_incref the object before
481 	 * passing it to the core, and \c json_decref it when you're done with it. */
482 	json_t *content;
483 };
484 
485 /*! \brief Helper to quickly create a janus_plugin_result instance
486  * @param[in] type The type of result
487  * @param[in] text String to add to the result (for JANUS_PLUGIN_OK_WAIT or JANUS_PLUGIN_ERROR), if any
488  * @param[in] content The json_t object with the content of the result, if any
489  * @returns A valid janus_plugin_result instance, if successful, or NULL otherwise */
490 janus_plugin_result *janus_plugin_result_new(janus_plugin_result_type type, const char *text, json_t *content);
491 
492 /*! \brief Helper to quickly destroy a janus_plugin_result instance
493  * @param[in] result The janus_plugin_result instance to destroy
494  * @returns A valid janus_plugin_result instance, if successful, or NULL otherwise */
495 void janus_plugin_result_destroy(janus_plugin_result *result);
496 ///@}
497 
498 
499 /** @name Janus plugin media packets
500  * @brief The Janus core and plugins exchange different kind of media
501  * packets, specifically RTP packets, RTCP messages and datachannel data.
502  * While previously these were exchanged between core and plugins using
503  * generic pointers and their length, Janus now uses a dedicated structure
504  * for each of them: this allows metadata and other info to be carried
505  * along the media data itself, making the exchange process extensible
506  * as a result (the signature remains the same, the data contained in
507  * the struct can change).
508  *
509  * The janus_plugin_rtp structure represents an RTP packet. When creating
510  * a new packet, it should be initialized with janus_plugin_rtp_init. Besides
511  * the data and its length, it also contains info on whether the packet is
512  * audio or video, and a list of the parsed RTP extensions provided in
513  * an instance of the janus_plugin_rtp_extensions structure. Notice that,
514  * while this list of extensions is mostly a commodity when receiving a
515  * packet, making it easier to access their values (the RTP extensions
516  * will still be part of the incoming RTP packet, so plugins are still free
517  * to parse them manually), they're very important when it comes to
518  * outgoing packets instead: in fact, since the Janus core may needs to
519  * terminate its own extensions with the peer, all RTP extensions that
520  * are in an RTP packet sent by a plugin are stripped when relay_rtp is
521  * called. This means that any attempt to inject an RTP extension in an
522  * outgoing packet will fail if the RTP extension is added to the payload
523  * manually, and will need to be set in the janus_plugin_rtp_extensions
524  * structure instead. It's also important to initialize the extensions
525  * structure before passing the packet to the core, as for each extension
526  * there may be a different way of telling the core whether the extension
527  * needs to be added or not (e.f., \c -1 instead of \c 0 or \c NULL ) .
528  * If the RTP extension management you need is not supported, it must be
529  * added to the core to get it working.
530  *
531  * The janus_plugin_rtcp, instead, represents an RTCP packet, which may
532  * contain one or more RTCP compound messages. The only info it contains
533  * are whether it's related to the audio or video stream, and a pointer
534  * to the data itself and its length. When creating a new packet, it should
535  * be initialized with janus_plugin_rtcp_init. To make the generation of
536  * some of the most common RTCP messages easier, a few helper core
537  * callbacks are provided: this means that, while you can craft RTCP
538  * messages yourself using the methods available in rtcp.h, it might be
539  * easier to send, e.g., a keyframe request using the dedicated method,
540  * which will leave the RTCP crafting process up tp the core.
541  *
542  * Finally, the janus_plugin_data represents a datachannel message. The
543  * only info it contains are the label the message came from, a pointer
544  * to the data itself and its length. When creating a new packet, it MUST
545  * be initialized with janus_plugin_data_init.
546  *
547  */
548 ///@{
549 /*! \brief Janus plugin RTP extensions */
550 struct janus_plugin_rtp_extensions {
551 	/*! \brief Audio level, in DB (0-127, 127=silence); -1 means no extension */
552 	int8_t audio_level;
553 	/*! \brief Whether the encoder detected voice activity (part of audio-level extension)
554 	 * @note Browsers apparently always set this to 1, so it's unreliable and should be ignored */
555 	gboolean audio_level_vad;
556 	/*! \brief Video orientation rotation (0, 90, 180, 270); -1 means no extension */
557 	int16_t video_rotation;
558 	/*! \brief Whether the video orientation extension says this is the back camera
559 	 * @note Will be ignored if no rotation value is set */
560 	gboolean video_back_camera;
561 	/*! \brief Whether the video orientation extension says it's flipped horizontally
562 	 * @note Will be ignored if no rotation value is set */
563 	gboolean video_flipped;
564 };
565 /*! \brief Helper method to initialise/reset the RTP extensions field
566  * @note This is important because each of the supported extensions may
567  * use a different value to specify an "extension missing" state, which
568  * may be different from a 0 or a NULL (e.g., a -1 instead)
569  * @param[in] extensions Pointer to the janus_plugin_rtp_extensions instance to reset
570 */
571 void janus_plugin_rtp_extensions_reset(janus_plugin_rtp_extensions *extensions);
572 
573 /*! \brief Janus plugin RTP packet */
574 struct janus_plugin_rtp {
575 	/*! \brief Whether this is an audio or video RTP packet */
576 	gboolean video;
577 	/*! \brief The packet data */
578 	char *buffer;
579 	/*! \brief The packet length */
580 	uint16_t length;
581 	/*! \brief RTP extensions */
582 	janus_plugin_rtp_extensions extensions;
583 };
584 /*! \brief Helper method to initialise/reset the RTP packet
585  * @note The main motivation for this method comes from the presence of the
586  * extensions as a janus_plugin_rtp_extensions instance.
587  * @param[in] packet Pointer to the janus_plugin_rtp packet to reset
588 */
589 void janus_plugin_rtp_reset(janus_plugin_rtp *packet);
590 
591 /*! \brief Janus plugin RTCP packet */
592 struct janus_plugin_rtcp {
593 	/*! \brief Whether this is an audio or video RTCP packet */
594 	gboolean video;
595 	/*! \brief The packet data */
596 	char *buffer;
597 	/*! \brief The packet length */
598 	uint16_t length;
599 };
600 /*! \brief Helper method to initialise/reset the RTCP packet
601  * @param[in] packet Pointer to the janus_plugin_rtcp packet to reset
602 */
603 void janus_plugin_rtcp_reset(janus_plugin_rtcp *packet);
604 
605 /*! \brief Janus plugin data message
606  * @note At the moment, we only support text based datachannels. In the
607  * future, once we add support for binary data, this structure may be
608  * extended to include info on the nature of the data itself */
609 struct janus_plugin_data {
610 	/*! \brief The label this message belongs to */
611 	char *label;
612 	/*! \brief The subprotocol this message refers to */
613 	char *protocol;
614 	/*! \brief Whether the message data is text (default=FALSE) or binary */
615 	gboolean binary;
616 	/*! \brief The message data */
617 	char *buffer;
618 	/*! \brief The message length */
619 	uint16_t length;
620 };
621 /*! \brief Helper method to initialise/reset the data message
622  * @param[in] packet Pointer to the janus_plugin_data message to reset
623 */
624 void janus_plugin_data_reset(janus_plugin_data *packet);
625 ///@}
626 
627 
628 #endif
629