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