/*!
 * \mainpage Janus - General purpose WebRTC server
 *
 * <div class="alert alert-warning">
 *		<b>Note Well:</b> these are the demos and documentation for the <code>multistream</code> version
 *		of Janus, which is a new version. If you want to check the previous version of
 *		Janus instead (i.e., <code>0.x</code>, a.k.a. "legacy") click
 *		<a href="https://janus-legacy.conf.meetecho.com">here</a> instead.
 * </div>
 *
 * \par Developer Documentation for the Janus WebRTC server
 * This is the main developer documentation for the Janus WebRTC
 * Server, generated with the help of
 * <a href="http://www.doxygen.org">Doxygen</a>. Make sure you
 * check the \ref DEPS before attempting a compilation. If you are
 * interested in how to compile, install and use Janus,
 * checkout the \ref README information. A \ref FAQ page is also available,
 * as well as an overview on \ref CHANGELOG.
 *
 * \par A general purpose WebRTC server
 * The Janus WebRTC Server has been conceived as a <tt>general purpose</tt>
 * server. As such, it doesn't provide any functionality per se
 * other than implementing the means to set up a WebRTC media communication
 * with a browser, exchanging JSON messages with it, and relaying RTP/RTCP
 * and messages between browsers and the server-side application logic they're attached to. Any specific
 * feature/application needs to be implemented in server side plugins,
 * that browsers can then contact via the Janus core to take advantage of
 * the functionality they provide. Example of such plugins can be
 * implementations of applications like echo tests, conference bridges,
 * media recorders, SIP gateways and the like.
 *
 * The reason for this is simple: we wanted something that would have a
 * <tt>small footprint</tt> (hence a C implementation) and that we could only
 * equip with what was <tt>really needed</tt> (hence pluggable modules). That is,
 * something that would allow us to deploy either a full-fledged WebRTC
 * server on the cloud, or a small nettop/box to handle a specific use case.
 *
 * \par Architecture and APIs
 * The core of the server is specified in the \ref core section. The protocols
 * implemented in the Janus core are listed in the \ref protocols group
 * instead. A list of plugins provided out of the box by Meetecho are
 * documented in the \ref pluginslist page: these plugins can be changed
 * or extended to match your requirements, or just used as a simple
 * reference should you be interested in writing a new plugin from
 * scratch (and you're definitely welcome to!). A \ref pluginapi to
 * create new plugins, or understand how they're conceived, is documented
 * as well. A documentation on the available API tranports and the
 * HTTP/WebSocket JavaScript API to use Janus and the plugins it
 * makes available in your web application can be found in the \ref JS
 * and \ref rest pages. New API transports can be created referring to
 * the \ref transportapi page. If you're interested in monitoring Janus
 * resources, you can refer to the \ref admin page. Event handler
 * plugins can also be used for the purpose: refer to the \ref eventhandlers
 * and, for more developer oriented info, to the \ref eventhandlerapi
 * page if you're interested in creating your own. For what concerns logging,
 * out of the box Janus supports printing the output to \c stdout and saving
 * to a local file, but logging can also be extended via additional plugins:
 * refer to the \ref loggerapi for more details, and to learn how to write
 * your own. You can check the \ref ide page for some details about how
 * to setup your local development environment for Janus..
 *
 * Janus also supports \ref recordings out of the box, so check the
 * related documentation to know more about how that works.
 *
 * Finally, some information on how to deploy Janus and your web
 * applications that want to make use of it are provided in the \ref deploy
 * page. If you're interested in starting Janus as a service/daemon rather
 * than launching it normally, check the information provided in the
 * \ref service page. Some additional \ref resources are also listed in
 * case you're interested in talking to Janus from different languages
 * and platforms.
 *
 * To conclude, the \ref debug page contains info on how you can help us
 * fixing issues you might encounter along the road.
 *
 * \section copyright Copyright and author
 *
 * Janus WebRTC Server © 2014-2023 <a href="https://www.meetecho.com/">Meetecho</a> (https://www.meetecho.com/)
 *
 * \author Lorenzo Miniero <lorenzo@meetecho.com> ( \ref CREDITS )
 *
 * \section license License
 * This program is free software, distributed under the terms of
 * the GNU General Public License Version 3. For more details and licensing
 * options, including a commercial license, see the \ref COPYING page.
 *
*/

/*! \page DEPS Dependencies
 *
 * The application and the plugins depend on the following open source
 * software and libraries, so make sure you install the related development
 * versions before attempting a compilation:
 *
 * - \b GLib: http://library.gnome.org/devel/glib/
 * - \b pkg-config: http://www.freedesktop.org/wiki/Software/pkg-config/
 * - \b Jansson: http://www.digip.org/jansson/ (JSON)
 * - \b libconfig: https://hyperrealm.github.io/libconfig/ (configuration files)
 * - \b libnice: https://libnice.freedesktop.org/ (ICE/STUN/TURN, at least v0.1.16 suggested, v0.1.18 recommended)
 * - \b OpenSSL: http://www.openssl.org/ (DTLS, at least v1.0.1e)
 * - \b libsrtp: https://github.com/cisco/libsrtp (SRTP, at least v2.x suggested)
 * - \b usrsctp: https://github.com/sctplab/usrsctp (\c optional, Data Channels)
 * - \b libmicrohttpd: http://www.gnu.org/software/libmicrohttpd/ (\c optional, v0.9.59, Web server)
 * - \b libwebsockets: https://libwebsockets.org/ (\c optional, WebSockets)
 * - \b rabbitmq-c: https://github.com/alanxz/rabbitmq-c (\c optional, v1.0.4, RabbitMQ)
 * - \b paho.mqtt.c: https://eclipse.org/paho/clients/c (\c optional, v1.1.0 for MQTT v3.1 & v3.1.1 or v1.3.0 for MQTT v5)
 * - \b nanomsg: https://nanomsg.org/ (\c optional, Nanomsg)
 * - \b Sofia-SIP: https://github.com/freeswitch/sofia-sip (\c optional, only needed for the SIP plugin)
 * - \b libopus: http://opus-codec.org/ (\c optional, only needed for the bridge plugin)
 * - \b libogg: http://xiph.org/ogg/ (\c optional, only needed for the voicemail plugin)
 * - \b libcurl: https://curl.haxx.se/libcurl/ (\c optional, only needed for the TURN REST API,
 * RTSP support in the Streaming plugin and the sample Event Handler plugin)
 * - \b zlib: https://zlib.net/ (gzip compression utility)
 * - \b Lua: https://www.lua.org/download.html (\c optional, only needed for the Lua plugin)
 * - \b Duktape: https://duktape.org/ (\c optional, only needed for the Duktape plugin)
 * - \b npm: https://docs.npmjs.com/ (\c optional, used during build for generating JavaScript modules)
 *
 */

/*! \page JS JavaScript API
 * Janus exposes, assuming the HTTP transport has been compiled, a
 * pseudo-RESTful interface, and optionally also WebSocket/RabbitMQ/MQTT/Nanomsg/UnixSockets
 * interfaces as well, all of which based on JSON messages. These
 * interfaces are described in more detail in the \ref plainhttp \ref WS
 * \ref rabbit \ref apimqtt \ref apinanomsg and \ref unix documentation respectively, and all allow clients to
 * take advantage of the features provided by Janus and the functionality
 * made available by its plugins. Considering most clients will be web browsers,
 * a common choice will be to rely on either the REST or the WebSockets
 * interface for the purpose. To make things easier for web
 * developers, a JavaScript library (\c janus.js) is available that can
 * make use of both interfaces using exactly the same API. This library
 * eases the task of creating sessions with the Janus core, attaching WebRTC
 * users to plugins, send and receive requests and events to the plugins
 * themselves and so on. For real examples of how this library can be
 * used, check the demos in the \b html folder of this package. Notice
 * that the \c janus.js library makes use of the features made available
 * by the <a href="https://github.com/webrtc/adapter">webrtc-adapter</a>
 * shim, which means that your web application should always include it
 * as a dependency. For instance, all the demos link to it externally via
 * <a href="https://cdnjs.com/">cdnjs.com</a>.
 *
 * \note The current \c janus.js library allows you to provide custom implementations of
 * certain dependencies, in order to make it easier to integrate with other JavaScript
 * libraries and frameworks. Using this feature you can ensure \c janus.js does not (implicitly)
 * depend on certain global variables. Two implementations are included in \c janus.js itself:
 *
 *  -# \ref js-default-deps which relies on native browser APIs,
 *     which in turn require somewhat more modern browsers
 *  -# \ref js-old-deps which uses jQuery (http://jquery.com/) instead,
 *     and should provide equivalent behaviour to previous versions of \c janus.js
 *
 * By default \ref js-default-deps will be used, but you can override this
 * when initialising the Janus library and pass a custom dependencies object instead.
 * For details, refer to: \ref js-dependencies
 *
 * In general, when using the Janus features, you would normally do the following:
 *
 * -# include the Janus JavaScript library in your web page;
 * -# initialize the Janus JavaScript library and (optionally) passing its dependencies;
 * -# connect to the server and create a session;
 * -# create one or more handles to attach to a plugin (e.g., echo test and/or streaming);
 * -# interact with the plugin (sending/receiving messages, negotiating a PeerConnection);
 * -# eventually, close all the handles and shutdown the related PeerConnections;
 * -# destroy the session.
 *
 * The above steps will be presented in order, describing how you can use
 * the low level API to accomplish them. Consider that in the future we might
 * provide higher level wrappers to this API to address specific needs, e.g.,
 * a higher level API for each plugin: this would make it even easier to use
 * the server features, as a high level API for the streaming plugin, for
 * instance, may just ask you to provide the server address and the ID of
 * the \c &lt;video&gt; element to display the stream in, and would take care of all the
 * above mentioned steps on your behalf. Needless to say, you're very welcome
 * to provide wrapper APIs yourself, if you feel a sudden urge to do so! :-)
 *
 * \section janusjs Using janus.js
 *
 * As a first step, you should include the Janus library in your project.
 * Depending on your needs you can either use \c janus.js or one of the generated
 * JavaScript module variants of it. For available module syntaxes and how to build the
 * corresponding variants, see: \ref js-modules
 *
\verbatim
<script type="text/javascript" src="janus.js" ></script>
\endverbatim
 *
 * The core of the JavaScript API is the \c Janus object. This object needs
 * to be initialized the first time it is used in a page. This can be done
 * using the static \c init method of the object, which accepts the
 * following options:
 *
 * - \c debug: whether debug should be enabled on the JavaScript console, and what levels
 *   - \c true or \c "all": all debuggers enabled (Janus.trace, Janus.debug, Janus.log, Janus.warn, Janus.error)
 *   - array (e.g., <code>["trace", "warn"]</code>): only enable selected debuggers (allowed tokens: trace, debug, log, warn, error)
 *   - \c false: disable all debuggers
 * - \c callback: a user provided function that is invoked when the initialization is complete
 * - \c dependencies: a user provided implementation of Janus library dependencies
 *
 * Here's an example:
 *
 *
 \verbatim
Janus.init({
   debug: true,
   dependencies: Janus.useDefaultDependencies(), // or: Janus.useOldDependencies() to get the behaviour of previous Janus versions
   callback: function() {
	   // Done!
   }
});
 \endverbatim
 *
 * \note When using one of the JavaScript module variants of \c janus.js, you
 * will need to import the \c Janus symbol from the module first. See also: \ref js-modules
 * For example, using the ECMAScript module variant, the above example should be altered to:
 *
 *
 \verbatim
import * as Janus from './janus.es.js'

Janus.init({
   debug: true,
   dependencies: Janus.useDefaultDependencies(), // or: Janus.useOldDependencies() to get the behaviour of previous Janus versions
   callback: function() {
	   // Done!
   }
});
 \endverbatim
 *
 * Once the library has been initialized, you can start creating sessions.
 * Normally, each browser tab will need a single session with the server: in
 * fact, each Janus session can contain several different plugin handles
 * at the same time, meaning you can start several different WebRTC sessions
 * with the same or different plugins for the same user using the same
 * Janus session. That said, you're free to set up different Janus
 * sessions in the same page, should you prefer so.
 *
 * Creating a session is quite easy. You just need to use the \c new constructor
 * to create a new \c Janus object that will handle your interaction with the
 * server. Considering the dynamic and asynchronous nature of Janus sessions
 * (events may occur at any time), there are several properties and callbacks you
 * can configure when creating a session:
 *
 * - \c server: the address of the server as a specific address (e.g.,
 * http://yourserver:8088/janus to use the plain HTTP API or ws://yourserver:8188/
 * for WebSockets) or as an array of addresses to try sequentially to allow
 * automatic for fallback/failover during setup;
 * - \c iceServers: a list of STUN/TURN servers to use (a default STUN server
 * will be used if you skip this property);
 * - \c withCredentials: whether the \c withCredentials property of XHR requests
 * should be enabled or not (false by default, and only valid when using HTTP
 * as a transport, ignored for WebSockets);
 * - \c max_poll_events: the number of events that should be returned when polling;
 * the default is 1 (polling returns an object), passing a higher number will
 * have the backend return an array of objects instead (again, only valid for
 HTTP usage as this is strictly related to long polling, ignored for WebSockets);
 * - \c destroyOnUnload: whether we should destroy automatically try and
 * destroy this session via Janus API when \c onbeforeunload is called (true by default);
 * - \c token , \c apisecret: optional parameters only needed in case you're \ref auth ;
 * - a set of callbacks to be notified about events, namely:
 * 		- \c success: the session was successfully created and is ready to be used;
 * 		- \c error: the session was NOT successfully created;
 * 		- \c destroyed: the session was destroyed and can't be used any more.
 *
 * These properties and callbacks are passed to the method as properties
 * of a single parameter object: that is, the \c Janus constructor takes a
 * single parameter, which although acts as a container for all the available
 * options. The \c success callback is where you typically start your application
 * logic, e.g., attaching the peer to a plugin and start a media session.
 *
 * Here's an example:
 *
 \verbatim
var janus = new Janus(
    {
        server: 'http://yourserver:8088/janus',
        success: function() {
            // Done! attach to plugin XYZ
        },
        error: function(cause) {
            // Error, can't go on...
        },
        destroyed: function() {
            // I should get rid of this
        }
    });
 \endverbatim
 *
 * As anticipated, the server may be a specific address, e.g.:
 *
 \verbatim
var janus = new Janus(
    {
        server: 'http://yourserver:8088/janus',
                // or
        server: 'ws://yourserver:8188/',
        [..]
 \endverbatim
 *
 * or an array of addresses. Such an array can be especially useful if
 * you want the library to first check if the WebSockets server is
 * reachable and, if not, fallback to plain HTTP, or just to provide
 * a link multiple instances to try for failover. This is an example of
 * how to pass a 'try websockets and fallback to HTTP' array:
 *
 \verbatim
var janus = new Janus(
    {
        server: ['ws://yourserver:8188/','http://yourserver:8088/janus'],
        [..]
 \endverbatim
 *
 * Once created, this object represents your session with the server.
 * you can interact with a \c Janus object in several different ways.
 * In particular, the following properties and methods are defined:
 *
 * - \c getServer(): returns the address of the server;
 * - \c isConnected(): returns \c true if the Janus instance is connected
 * to the server, \c false otherwise;
 * - \c getSessionId(): returns the unique Janus session identifier;
 * - \c attach(parameters): attaches the session to a plugin, creating a handle;
 * more handles to the same or different plugins can be created at the same time;
 * - \c destroy(parameters): destroys the session with the server, and closes
 * all the handles (and related PeerConnections) the session may have with any plugin as well.
 *
 * The most important property is obviously the \c attach() method, as
 * it's what will allow you to exploit the features of a plugin to manipulate
 * the media sent and/or received by a PeerConnection in your web page.
 * This method will create a plugin handle you can use for the purpose,
 * for which you can configure properties and callbacks when calling the
 * \c attach() method itself. As for the \c Janus constructor, the \c attach()
 * method takes a single parameter that can contain any of the following
 * properties and callbacks:
 *
 * - \c plugin: the unique package name of the plugin (e.g., \c janus.plugin.echotest );
 * - \c opaqueId: an optional opaque string meaningful to your application (e.g., to map all the handles of the same user);
 * - a set of callbacks to be notified about events, namely:
 * 		- \c success: the handle was successfully created and is ready to be used;
 * 		- \c error: the handle was NOT successfully created;
 * 		- \c consentDialog: this callback is triggered just before \c getUserMedia is called
 * (parameter=<b>true</b>) and after it is completed (parameter=<b>false</b>); this means it can
 * be used to modify the UI accordingly, e.g., to prompt the user about the need to accept the device access consent requests;
 * 		- \c webrtcState: this callback is triggered with a <b>true</b> value
 * when the PeerConnection associated to a handle becomes active (so ICE, DTLS and
 * everything else succeeded) from the Janus perspective, while <b>false</b> is
 * triggered when the PeerConnection goes down instead; useful to figure out
 * when WebRTC is actually up and running between you and Janus (e.g., to notify
 * a user they're actually now active in a conference); notice that in case
 * of <b>false</b> a reason string may be present as an optional parameter;
 * 		- \c iceState: this callback is triggered when the ICE state for the
 * PeerConnection associated to the handle changes: the argument of the callback
 * is the new state as a string (e.g., "connected" or "failed");
 * 		- \c mediaState: this callback is triggered when Janus starts or stops
 * receiving your media: for instance, a \c mediaState with mid=<b>0</b>, type=<b>audio</b>
 * and on=<b>true</b> means Janus started receiving the audio stream identified
 * by mid \c b in the offer/answer exchange and transceivers (or started
 * getting them again after a pause of more than a second); a \c mediaState with
 * type=<b>video</b> and on=<b>false</b> means Janus hasn't received any video
 * from you in the last second, after a start was detected before; useful to
 * figure out when Janus actually started handling your media, or to detect
 * problems on the media path (e.g., media never started, or stopped at some time);
 * 		- \c slowLink: this callback is triggered when Janus reports trouble
 * either sending or receiving media on the specified PeerConnection, typically
 * as a consequence of too many NACKs received from/sent to the user in the
 * last second: for instance, a \c slowLink with uplink=<b>true</b> means
 * you notified several missing packets from Janus, while uplink=<b>false</b>
 * means Janus is not receiving all your packets; useful to figure out when
 * there are problems on the media path (e.g., excessive loss), in order to
 * possibly react accordingly (e.g., decrease the bitrate if most of our
 * packets are getting lost);
 * 		- \c onmessage: a message/event has been received from the plugin;
 * 		- \c onlocaltrack: a local \c MediaStreamTrack is available and ready to be displayed;
 * 		- \c onremotetrack: a remote \c MediaStreamTrack is available and ready to be displayed;
 * 		- \c ondataopen: a Data Channel is available and ready to be used;
 * 		- \c ondata: data has been received through the Data Channel;
 * 		- \c oncleanup: the WebRTC PeerConnection with the plugin was closed;
 * 		- \c detached: the plugin handle has been detached by the plugin itself,
 * and so should not be used anymore.
 *
 * Here's an example:
 *
 \verbatim
// Attach to echo test plugin, using the previously created janus instance
janus.attach(
    {
        plugin: "janus.plugin.echotest",
        success: function(pluginHandle) {
            // Plugin attached! 'pluginHandle' is our handle
        },
        error: function(cause) {
            // Couldn't attach to the plugin
        },
        consentDialog: function(on) {
            // e.g., Darken the screen if on=true (getUserMedia incoming), restore it otherwise
        },
        onmessage: function(msg, jsep) {
            // We got a message/event (msg) from the plugin
            // If jsep is not null, this involves a WebRTC negotiation
        },
        onlocaltrack: function(track, added) {
            // A local track to display has just been added (getUserMedia worked!) or removed
        },
        onremotetrack: function(track, mid, added) {
            // A remote track (working PeerConnection!) with a specific mid has just been added or removed
        },
        oncleanup: function() {
            // PeerConnection with the plugin closed, clean the UI
            // The plugin handle is still valid so we can create a new one
        },
        detached: function() {
            // Connection with the plugin closed, get rid of its features
            // The plugin handle is not valid anymore
        }
    });
 \endverbatim
 *
 * So the \c attach() method allows you to attach to a plugin, and specify
 * the callbacks to invoke when anything relevant happens in this interaction.
 * To actively interact with the plugin, you can use the \c Handle object
 * that is returned by the \c success callback (pluginHandle in the example).
 *
 * This \c Handle object has several methods you can use to interact with
 * the plugin or check the state of the session handle:
 *
 * - \c getId(): returns the unique handle identifier;
 * - \c getPlugin(): returns the unique package name of the attached plugin;
 * - \c send(parameters): sends a message (with or without a jsep to
 * negotiate a PeerConnection) to the plugin;
 * - \c createOffer(callbacks): asks the library to create a WebRTC compliant OFFER;
 * - \c createAnswer(callbacks): asks the library to create a WebRTC compliant ANSWER;
 * - \c handleRemoteJsep(callbacks): asks the library to handle an incoming WebRTC compliant session description;
 * - \c replaceTracks(tracks, callbacks): asks the library to replace local tracks without renegotiating (no other offer/answer);
 * - \c dtmf(parameters): sends a DTMF tone on the PeerConnection;
 * - \c data(parameters): sends data through the Data Channel, if available;
 * - \c getBitrate(mid): gets a verbose description of the currently received
 * video stream bitrate (optional mid to specify the stream, first video stream if missing);
 * - \c getLocalTracks(): returns an array of the tracks that are currently being sent
 * on this PeerConnection, as basic objects including, e.g., type, \c mid and \c label of the track;
 * - \c getRemoteTracks(): returns an array of the tracks that are currently being received
 * on this PeerConnection, as basic objects including, e.g., type, \c mid and \c label of the track;
 * - \c muteAudio , \c unmuteAudio , \c isAudioMuted , \c muteVideo , \c unmuteVideo , \c isVideoMuted: a
 set of helper functions to mute, unmute or check the muted status of a specific audio or video track
 * that is currently being sent (optional mid to specify the stream, first audio/video stream if missing);
 * - \c getLocalVolume , \c getRemoteVolume: a couple of helper functions to get the current volume of
 * the local or remote track; notice that this isn't supported on Firefox at the moment
 * (optional mid to specify the stream, first audio stream if missing);
 * - \c hangup(sendRequest): tells the library to close the PeerConnection; if the optional \c sendRequest argument is
 * set to \c true, then a \c hangup Janus API request is sent to Janus as well (disabled by default, Janus can usually
 * figure this out via DTLS alerts and the like but it may be useful to enable it sometimes);
 * - \c detach(parameters): detaches from the plugin and destroys the handle, tearing
 * down the related PeerConnection if it exists.
 *
 * While the \c Handle API may look complex, it's actually quite straightforward
 * once you get the concept. The only step that may require a little more
 * effort to understand is the PeerConnection negotiation, but again, if
 * you're familiar with the WebRTC API, the \c Handle actually makes it
 * a lot easier.
 *
 * The idea behind it's usage is the following:
 *
 * -# you use \c attach() to create a \c Handle object;
 * -# in the \c success callback, your application logic can kick in: you may
 * want to send a message to the plugin (<code>send({msg})</code>), negotiate
 * a PeerConnection with the plugin right away ( \c createOffer followed
 * by a <code>send({msg, jsep})</code>) or wait for something to happen to do anything;
 * -# the \c onmessage callback tells you when you've got messages from the plugin;
 * if the \c jsep parameter is not null, just pass it to the library, which will take
 * care of it for you; if it's an \b OFFER use \c createAnswer (followed by a
 * <code>send({msg, jsep})</code> to close the loop with the plugin), otherwise use
 * \c handleRemoteJsep ;
 * -# whether you took the initiative to set up a PeerConnection or the plugin did,
 * the \c onlocaltrack and/or the \c onremotetrack callbacks will provide
 * you with info on media tracks you can display or play in your page;
 * -# each plugin may allow you to manipulate what should flow through the
 * PeerConnection channel: the \c send method and \c onmessage callback
 * will allow you to handle this interaction (e.g., to tell the plugin
 * to mute your stream, or to be notified about someone joining a virtual room),
 * while the \c ondata callback is triggered whenever data is received
 * on the Data Channel, if available (and the \c ondataopen callback
 * will tell you when a Data Channel is actually available).
 *
 * The following paragraphs will delve a bit deeper in the negotiation
 * mechanism provided by the \c Handle API, in particular describing
 * the properties and callbacks that may be involved. To follow the approach
 * outlined by the W3C WebRTC API, this negotiation mechanism is heavily
 * based on asynchronous methods as well. Notice that the following paragraphs
 * address the first negotiation step, that is the one to create a new
 * PeerConnection from scratch: to know how to originate or handle a
 * renegotiation instead (e.g., to add/remove/replace a media source, or
 * force an ICE restart) check the \ref renegotiation section instead.
 *
 * - \c createOffer takes a single parameter, that can contain any of the
 * following properties and callbacks:
 *   - \c tracks: you can use this property to tell the library which media (audio/video/data)
 * you're interested in, and whether you're going to send and/or receive any of them; by default
 * no device is captured, and Data Channels are disabled as well; incoming audio and video
 * is instead autoaccepted unless you tell the library otherwose; the same property can also
 * be used to update sessions (e.g., to add/remove/replace tracks); this option is an array of
 * objects, where each object can take any of the following properties:
 *     - \c type: mandatory, must be one of "audio", "video", "screen" and "data";
 *     - \c mid: to address existing tracks (e.g., when answering or updating sessions),
 * the \c mid property specifies that the info in the related track object
 * are specific to that target; notice that this is ignored in a first \c createOffer ,
 * as mid values are created by the browser automatically and cannot be forced;
 *     - \c capture: in case something must be captured (e.g., a microphone for
 * "audio" or a "webcam" for video), the \c capture property can be used to
 * dictate what and how; passing \c true asks for the default device, but
 * \c getUserMedia (for audio/video) or \c getDisplayMedia (for screen sharing)
 * constraints can be passed as well as objects, and in case those will be
 * used instead; passing a \c MediaStreamTrack instance will tell the library
 * not to capture anything, but use the provided track as a source instead;
 *     - \c simulcast: \c true/false, for video, whether simulcast should be used for this track;
 *     - \c svc: for video, the scalability mode to enable, in case SVC needs to be
 * used for this track; notice that SVC support is experimental in Janus, and not
 * fully supported in all browsers either;
 *     - \c recv: \c true/false , whether audio or video should be received
 * as well; in case \c capture is set but \c recv is false, then this means
 * you're asking for a "sendonly" track;
 *     - \c add: \c true/false , whether a new track should be added (default is true for offers);
 *     - \c replace: \c true/false , whether a provided \c capture should replace what
 * is being captured for the specified track;
 *     - \c remove: \c true/false , whether the local track that's currently captured
 * should be removed, meaning nothing will be sent for that specific stream;
 *     - \c dontStop: \c true/false , whether a track that is being added right
 * now should \b NOT be stopped when the track is removed; this is helpful whenever,
 * for instance, an external track is being provided to \c capture , and the application
 * wants to keep control on the life cycle of the \c MediaStreamTrack instance;
 *     - \c transforms: in case Insertable Streams need to be used (e.g., for end-to-end
 * encryption), the \c sender and/or \c receiver transform functions for this track can
 * be provided in the \c transforms property;
 *   - \c trickle: \c true/false, to tell the library whether you want
 * Trickle ICE to be used (true, the default) or not (false);
 *   - a set of callbacks to be notified about the result, namely:
 *     - \c success: the session description was created (attached as a parameter) and is ready to be sent to the plugin;
 *     - \c error: the session description was NOT successfully created;
 *     - \c customizeSdp: you can modify the sdp generated by the webrtc engine if you need;
 * - \c createAnswer takes the same options as createOffer, but requires
 * an additional one as part of the single parameter argument:
 *   - \c jsep: the session description sent by the plugin (e.g., as received
 * in an \c onmessage callback) as its OFFER.
 *
 * Whether you use \c createOffer or \c createAnswer depending on the scenario,
 * you should end up with a valid \c jsep object returned in the \c success
 * callback. You can attach this \c jsep object to a message in a \c send request
 * to pass it to the plugin, and have Janus negotiate a PeerConnection
 * with your application.
 *
 * Here's an example of how to use \c createOffer, taken from the Echo Test demo page:
 *
 \verbatim
// Attach to echo test plugin
janus.attach(
    {
        plugin: "janus.plugin.echotest",
        success: function(pluginHandle) {
            // Negotiate WebRTC
            echotest = pluginHandle;
            echotest.createOffer(
                {
                    // We want bidirectional audio and video, plus data channels
                    tracks: [
                        { type: 'audio', capture: true, recv: true },
                        { type: 'video', capture: true, recv: true },
                        { type: 'data' },
                    ],
                    success: function(jsep) {
                        // Got our SDP! Send our OFFER to the plugin
                        echotest.send({ message: body, jsep: jsep });
                    },
                    error: function(error) {
                        // An error occurred...
                    },
                    customizeSdp: function(jsep) {
                        // if you want to modify the original sdp, do as the following
                        // oldSdp = jsep.sdp;
                        // jsep.sdp = yourNewSdp;
                    }
                });
        },
        [..]
        onmessage: function(msg, jsep) {
            // Handle msg, if needed, and check jsep
            if(jsep) {
                // We have the ANSWER from the plugin
                echotest.handleRemoteJsep({jsep: jsep});
            }
        },
        [..]
        onlocaltrack: function(track, added) {
            // Invoked after createOffer
            // This is info on a local track: when added, we can choose to render
        },
        onremotetrack: function(track, mid, added) {
            // Invoked after handleRemoteJsep has got us a PeerConnection
            // This is info on a remote track: when added, we can choose to render
        },
        [..]
  \endverbatim
 *
 * This, instead, is an example of how to use \c createAnswer, taken from the Streaming demo page:
 *
 \verbatim
// Attach to the Streaming plugin
janus.attach(
    {
        plugin: "janus.plugin.streaming",
        success: function(pluginHandle) {
            // Handle created
            streaming = pluginHandle;
            [..]
        },
        [..]
        onmessage: function(msg, jsep) {
            // Handle msg, if needed, and check jsep
            if(jsep) {
                // We have an OFFER from the plugin
                streaming.createAnswer(
                    {
                        // We attach the remote OFFER
                        jsep: jsep,
                        // We only specify data channels here, as this way in
                        // case they were offered we'll enable them. Since we
                        // don't mention audio or video tracks, we autoaccept them
                        // as recvonly (since we won't capture anything ourselves)
                        tracks: [
                            { type: 'data' }
                        ],
                        success: function(ourjsep) {
                            // Got our SDP! Send our ANSWER to the plugin
                            var body = { request: "start" };
                            streaming.send({ message: body, jsep: ourjsep });
                        },
                        error: function(error) {
                            // An error occurred...
                        }
                    });
            }
        },
        [..]
        onlocaltrack: function(track, added) {
            // This will NOT be invoked, we chose recvonly
        },
        onremotetrack: function(track, mid, added) {
            // Invoked after send has got us a PeerConnection
            // This is info on a remote track: when added, we can choose to render
        },
        [..]
  \endverbatim
 *
 * Of course, these are just a couple of examples where the scenarios
 * assumed that one plugin would only receive (Echo Test) or generate
 * (Streaming) offers. A more complex example (e.g., a call using the
 * Video Call, SIP or NoSIP plugin, or a videoconfecence using the Video Room)
 * would involve both, allowing you to either send offers to a plugin,
 * or receive some from them. Handling this is just a matter of checking
 * the \c type of the \c jsep object and reacting accordingly.
 *
 * \section renegotiation Updating an existing PeerConnection (with or without renegotiations)
 * While the JavaScript APIs described above will suffice for most of the
 * common scenarios, there are cases when updates on a PeerConnection may
 * be needed. This can happen whenever, for instance, you want to add a
 * new media source (e.g., add video to an audio only call), replace an
 * existing one (e.g., switch from capturing the camera to sharing your
 * screen), or trigger an ICE restart because of a network change. While
 * adding or removing tracks requires a renegotiation, which means a new SDP
 * offer/answer round to update the existing PeerConnection, just replacing
 * a track can be done without any further SDP exchange. In both cases,
 * the \c tracks property introduced before can be used to update a session.
 *
 * To just replace an existing track (e.g., changing the camera used to
 * capture the video we're sending) the \c replaceTracks handle method can
 * be used. Using it is quite trivial, since you simply need to provide a
 * list of tracks you want to update, identify them somehow (e.g., via
 * their \c mid ), and provide the new \c capture property. A simple
 * example that shows how to replace a video track with a specific camera
 * identified by its \c deviceId is the following:
 *
 \verbatim
echotest.replaceTracks([
    {
        type: 'video',
        mid: '1',    // We assume mid 1 is video
        capture: { deviceId: { exact: videoDeviceId } }
    }
]);
 \endverbatim
 *
 * In case a new track needs to be added to a session, or an existing
 * track be removed, instead, a renegotiation is indeed needed, because
 * it requires changes to be signalled to the other party. In that case,
 * a renegotiation happens exactly as new sessions do, meaning that you
 * either perform a new \c createOffer followed by a \c handleRemoteJsep
 * with the updated answer, or you handle an incoming updated offer and
 * provide an updated answer via \c createAnswer : the library will
 * automatically understand from context if you're creating a new session
 * or updating an existing one.
 *
 * When updating a session to add or remove tracks, you need to provide
 * an updated \c tracks property as well. It's important to only include
 * in this \c tracks property a list of tracks you want to change: omitting
 * existing tracks will result in the library not making any change to
 * them. This means that a \c createOffer without a \c tracks property,
 * for instance, will simply generate a new offer without applying any
 * change (which, as we'll see later, can be useful in some cases, e.g.,
 * ICE restarts).
 *
 * Depending on what you want to update, you'll need to set one of the
 * following properties to \c true in the related track object:
 *
 * - \c add: adds a new track to the session;
 * - \c replace: replaces an existing track in the session (similar to
 * what \c replaceTracks does, but within the context of a renegotiation);
 * - \c remove: removes an existing track from a session (the direction of
 * the related m-line will be changed to either "recvonly" or "inactive",
 * depending on whether there's incoming media as well or not).
 *
 * Notice that these properties are only processed when you're trying a
 * renegotiation, and will be ignored when creating a new PeerConnection.
 * These properties don't replace the existing \c track properties, but go
 * along with them. For instance, when adding a new video stream, or
 * replacing an existing one, you can still use the video related properties
 * as before, e.g., to pass a specific device ID or asking for a screenshare
 * instead of a camera. As anticipated, omitting info on existing tracks
 * will leave them untouched.
 *
 * It's important to point out that, as for negotiations that result in
 * the creation of a new PeerConnection in the first place, how to perform
 * a renegotiation in practice will typically vary depending on the plugin
 * that you're trying to do it for. Some plugins may allow you to offer
 * a renegotiation, others may require you to send a different request
 * instead in order to trigger a renegotiation from the plugin. As it
 * will be clearer later, this is especially true for ICE restarts. As
 * such, apart from the generic and core-related definitions introduced
 * in this section, please refer to the documentation for each individual
 * plugin for more information about how to perform renegotiations in
 * specific use cases.
 *
 * Here's a simple example of how you can remove the local video capture
 * in a session, e.g., in the EchoTest demo:
 *
 \verbatim
// Remove local video
echotest.createOffer(
    {
        tracks: [{ type: 'video', mid: '1', remove: true }],
        success: function(jsep) {
            echotest.send({ message: { video: true }, jsep: jsep })
        }
        error: function(error) {
            bootbox.alert('WebRTC error... ' + error.message);
        }
    });
 \endverbatim
 *
 * This other example shows how you can add a new video stream, e.g.,
 * a screen share, to an existing PeerConnection instead:
 *
 \verbatim
// Add local video
echotest.createOffer(
    {
        tracks: [{ type: 'screen', add: true, capture: true }],
        success: function(jsep) {
            echotest.send({ message: { video: true }, jsep: jsep })
        }
        error: function(error) {
            bootbox.alert('WebRTC error... ' + error.message);
        }
    });
 \endverbatim
 *
 * Notice that renegotiations involving media changes (both local and remote)
 * will likely result in new calls to the \c onlocaltrack and \c onremotetrack
 * application callbacks: as such, be prepared to see those callbacks called
 * for the same PeerConnection more than once during the course of a media session.
 *
 * \section restarts ICE restarts
 * While ICE restarts can be achieved with a renegotiation, they're complex
 * enough to deserve a specific subsection. In fact, ICE restarts don't
 * address changes in the media, but in the underlying transport itself.
 * They're used, for instance, when there's a network change (e.g., the
 * IP address changed, or the user switched from WiFi to 4G). In order for
 * this to work, new candidates must be exchanged, and connectivity checks
 * must be restarted in order to find the new optimal path.
 *
 * With \c janus.js, you can only force an ICE restart when sending a new
 * offer. In order to do so, all you need to do is add `iceRestart :true`
 * to your `createOffer` call, and an ICE restart will be requested. The
 * following example shows how this can be done with the EchoTest:
 *
 \verbatim
echotest.createOffer(
    {
        iceRestart: true,
        success: function(jsep) {
            echotest.send({ message: { audio: true, video: true }, jsep: jsep});
        }
    });
 \endverbatim
 *
 * Notice how, in this particular example, we're not asking for any change
 * on the media streams, but just an ICE restart, which is why we don't
 * provide a \c tracks property at all: as a consequence, the library won't
 * make any changes to the existing streams, but only generate a new offer.
 * If successful, as soon as the answer is received, the client and Janus
 * will restart the ICE process and find a new path for the media packets.
 *
 * Notice that, with Janus and its plugins, you won't always be able to
 * force an ICE restart by sending a new SDP offer yourself: some plugins,
 * like the Streaming plugin for instance, will want to always send an
 * offer themselves, which means they'll be the ones actually forcing the
 * ICE restart from a negotiation perspective. In order to still allow
 * users to actually originate the process, all the stock Janus plugins
 * that assume they'll be sending offers for some or all of their media
 * streams also expose APIs to force an ICE restart from the server side.
 * You can learn more about this on a plugin level basis
 * <a target="_blank" href="https://github.com/meetecho/janus-gateway/pull/753">here</a> and
 * <a target="_blank" href="https://github.com/meetecho/janus-gateway/pull/1099">here</a>.
 * Besides, make sure you read the documentation for each of the plugins
 * you're interested in using ICE restarts for, as the details for how
 * to perform it properly are typically provided there.
 *
 * <hr>
 *
 * This is it! For more information about the API, have a look at the
 * demo pages that are available in the \b html folder in this package.
 *
 */

/*!\page js-modules Using janus.js as JavaScript module
 *
 * To facilitate integration of \c janus.js within modular JavaScript code bases,
 * you can instruct the build system(s) to generate a modular variants of \c janus.js.
 * Generated modules may then be copied to your own JavaScript projects and seamlessly integrated with your own project's build system.
 *
 * Building the modules can be done in two ways:
 *
 * -# As part of a regular build of the Janus WebRTC Server, using \c make, by enabling the integrated support via \c configure
 * -# By running NPM commands manually. This may be useful if you are looking to build just the JavaScript modules without
 *    incurring the overhead of a full build of Janus.
 *
 * As an alternative to generating the module and copying it to your project, you can also tweak
 * your module bundler to use \c janus.js directly from the official Janus repository. See more
 * details (including concrete instructions for Webpack): \ref js-webpack
 *
 * \section auto-build-js-modules Building modules using make
 * Each supported variant may be enabled by passing a corresponding \c --enable-javascript-*-module flag
 * (with or without a \c =yes directive) to \c configure before invoking \c make to build Janus.
 * Please note: if you do not pass any such flag, by default no modules will be built.
 *
 * The following table provides a summary of available module formats and their corresponding \c configure options:
 *
 * <table class="table table-striped">
 * <tr><th>Module format (syntax)</th><th>File name</th><th>configure flag to pass</th></tr>
 * <tr><td>ECMAScript</td><td>janus.es.js</td><td>\c --enable-javascript-es-module</td></tr>
 * <tr><td>Universal Module Definition (UMD)</td><td>janus.umd.js</td><td>\c --enable-javascript-umd-module</td></tr>
 * <tr><td>CommonJS</td><td>janus.cjs.js</td><td>\c --enable-javascript-common-js-module</td></tr>
 * <tr><td>Immediately Invoked Function Expression (IIFE)</td><td>janus.iife.js</td><td>\c --enable-javascript-iffe-module</td></tr>
 * </table>
 *
 * The \c --enable-all-js-modules shortcut is available, in case you want to enable and build them all.
 *
 * When built and installed, these module variants may be found in the \c $PREFIX/share/janus/javascript
 * folder, alongside the \c janus.js file itself (assuming \c $PREFIX the installation directory passed to \c configure).
 *
 * \note Building the JavaScript modules still requires NPM and may involve an \c install which means \c npm must be able
 * to download dependencies. By default \c configure will attempt to auto-detect available \c npm on your PATH, but
 * if you have installed NPM outside the PATH you can override this by passing the (full) path to your \c npm executable, e.g.:
 *
 \verbatim
 ./configure NPM=/path/to/my/custom/npm --enable-javascript-es-module=yes
 \endverbatim
 *
 * \section manual-build-modules Building modules manually with NPM
 * You can also opt to build modules by invoking \c npm manually. The \c npm subdirectory contains the necessary
 * configuration files to get you started:
 *
 \verbatim
 cd ./npm
 npm install
 npm run rollup -- --o /path/to/desired/output/file-name.js --f cjs # or es, iffe, umd, amd, ...
 \endverbatim
 *
 * Using \c npm directly is useful if you want to build the JavaScript modules only, without building Janus itself
 * or if you are looking for advanced customisation options or alternative formats which are not integrated in \c configure yet.
 * As you may have surmised from the example command, the actual build consists mostly of invoking \c rollup with the
 * correct parameters. For more information on available parameters, please refer to the \c rollup documentation:
 *
 * -# https://rollupjs.org/#command-line-flags
 * -# https://rollupjs.org/#configuration-files
 *
 * \section js-webpack Using janus.js directly with Webpack and other bundlers
 *
 * Generating a converted version of \c janus.js and copying it to your project is not always the best
 * solution. In many situations it may be prefered to let your JavaScript module bundler (e.g.
 * <a href="https://webpack.js.org">Webpack</a>) grab the file directly from the official Janus repository.
 * Doing that you can manage \c janus.js just like any other dependency coming from Github or the npm Registry,
 * getting rid of the manual copy step and letting the bundler take care of version management, updates
 * and downloads.
 *
 * Of course, the first step is to include the official Janus repository as a dependency in your
 * project by adding it to your \c packages.json file.
 *
 \verbatim
 {
   "dependencies": {
     "janus-gateway": "git://github.com/meetecho/janus-gateway.git"
   }
 }
 \endverbatim
 *
 * That will automatically drag in the dependency on the appropriate version of the
 * <a href="https://www.npmjs.com/package/webrtc-adapter">WebRTC Adapter</a> from the npm Registry.
 * But \c janus.js expects such adapter to be available as a global variable.
 * So we have to make that happen for it to work properly. In the case of Webpack, is as easy as
 * adding this to your \c webpack.config.js file.
 \verbatim
 const webpack = require('webpack');

 module.exports = {
   plugins: [
     // janus.js does not use 'import' to access to the functionality of webrtc-adapter,
     // instead it expects a global object called 'adapter' for that.
     // Let's make that object available.
     new webpack.ProvidePlugin({ adapter: ['webrtc-adapter', 'default'] })
   ]
 };
 \endverbatim
 *
 * On the other hand, \c janus.js defines the \c Janus object globally. So a small tweak is also
 * needed to serve such object via \c export. That can be done using
 * <a href="https://webpack.js.org/loaders/exports-loader/">exports-loader</a> and adding this to
 * \c webpack.config.js
 \verbatim
 module.exports = {
   module: {
     rules: [
       // janus.js does not use 'export' to provide its functionality to others, instead
       // it creates a global variable called 'Janus' and expects consumers to use it.
       // Let's use 'exports-loader' to simulate it uses 'export'.
       {
         test: require.resolve('janus-gateway'),
         loader: 'exports-loader',
          options: {
            exports: 'Janus',
          },
       }
     ]
   }
 };
 \endverbatim
 *
 * With that extra configuration, the official \c janus.js can be used directly in any modular
 * JavaScript code base without any previous transformation of the file. That means you can simply
 * do this to access to the Janus API from your modular code.
 \verbatim
 import { Janus } from 'janus-gateway';
 \endverbatim

 * For more detailed or updated documentation check the
 * <a href="https://webpack.js.org/guides/shimming/">Webpack shimming guide</a> or the equivalent
 * documentation for your bundler of choice.
 */

/*!\page js-dependencies Working with custom janus.js dependencies
 *
 * Certain dependencies of \c janus.js may be passed during library initialization as
 * a property list containing the following keys:
 *
 * -# \c newWebSocket: a function which given WebSockets server and protocol arguments
 * should return a new WebSocket (or something that acts like it)
 * -# \c webRTCAdapter: an \c adapter object such as provided by the
 * <a href="https://github.com/webrtc/adapter">webrtc-adapter</a> library
 * -# \c isArray: a function which tests if a given argument is a JavaScript array
 * -# \c checkJanusExtension: a function which tests if the Janus Screensharing extension
 * for Chrome is installed/available. This can be done by testing whether or not an element
 * with an \c id attribute value of \c janus-extension-installed is present.
 * -# \c httpAPICall: a function which given an url and options argument performs an
 * HTTP API request to Janus. This function is not as straightforward to implement,
 * see the section on \ref js-http-apicall below for details.
 *
 * Depending on your needs you do not have to provide all these dependencies, e.g.
 * you do not need to implement the \c httpAPICall function if your application relies
 * exclusively on WebSockets to access the Janus API.
 *
 * Two implementations of the dependencies object are provided by \c janus.js:
 *
 * -# \c Janus.useDefaultDependencies
 * -# \c Janus.useOldDependencies
 *
 * In turn, each of these implementations accept their dependencies as arguments or fallback on
 * certain global variables. Below follows an overview:
 *
 * \section js-default-deps Janus.useDefaultDependencies
 * The \c Janus.useDefaultDependencies method relies on the following native browser APIs:
 *
 * -# \c Promise: support for \c Promises as standardised in ES 6 (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises)
 * -# \c fetch: support for the \c fetch API (https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)
 * -# \c WebSocket: support for the \c WebSocket API (https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)
 * -# \c document.querySelector: support for the \c document.querySelector API (https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector)
 *
 * Additionally the \c adapter object from the <a href="https://github.com/webrtc/adapter">webrtc-adapter</a> library is also required.
 * These dependencies may either be passed explicitly to the function as a property list with keys of the same name, or
 * if omitted the function will fallback to relying on global variables of that name instead.
 *
 * Example:
\verbatim
	var customDependencies = Janus.useDefaultDependencies({
		fetch: myCustomFetchImplementation // myCustomFetchImplementation should provide a compatible fetch() API
	});

	var relyingOnGlobalsEntirely = Janus.useDefaultDependencies();
\endverbatim
 *
 * Being able to passe dependencies like this is especially useful in the context of modern ES modules:
 *
\verbatim
import adapter from 'webrtc-adapter';
//  other imports elided

const setupDeps = () => Janus.useDefaultDependencies({
	adapter,
	// other dependencies elided
});

export const initialiseJanusLibrary = () => Janus.init({dependencies: setupDeps()});
\endverbatim
 *
 * \section js-old-deps Janus.useOldDependencies
 * The \c Janus.useOldDependencies method relies on:
 *
 * -# \c jQuery: the JQuery library (http://jquery.com/)
 * -# \c WebSocket: support for the \c WebSocket API (https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)
 * -# \c adapter: the \c adapter object from the <a href="https://github.com/webrtc/adapter">webrtc-adapter</a> library
 *
 * This function provides a simple upgrade path for existing applications which are heavily
 * tied to jQuery (especially since previous versions of \c janus.js depended on it).
 *
 * \section js-http-apicall httpAPICall
 * The \c httpAPICall function is used to issue API calls to the Janus HTTP(S) interfaces.
 * It will be passed two arguments:
 *
 * -# \c url: a string which refers to the (server) URL of the API endpoint to contact
 * -# \c options a property list (see below)
 *
 * Any return values from the \c httpAPICall function will be ignored.
 *
 * When working with HTTP request or response bodies, the \c httpAPICall is responsible for
 * serialisation to, and deserialisation from the 'wire format' (JSON).
 * That is: the \c httpAPICall must transform objects to JSON or parse JSON as and when required.
 * Similarly, the \c httpAPICall is also responsible for setting appropriate HTTP
 * \c Content-Type (application/json) and/or \c Accept headers.
 *
 * The \c options argument may contain the following keys:
 *
 * -# \c timeout: a timeout in miliseconds which should be imposed on the request.
 *    The \c httpAPICall implementation is required to implement support for imposing timeouts
 *    on HTTP API requests.
 * -# \c body: payload to include as body of the outgoing HTTP request.
      The \c httpAPICall must encode it in the 'wire format' (JSON).
 * -# \c withCredentials: a boolean indicating whether or not HTTP credentials should be sent
 * -# \c success: a callback which should be dispatched when an API request was successful.
 * -# \c error: a callback which should be dispatched when an API request was unsuccessful, or timed out
 * -# \c async: a boolean hint which indicates whether or not asynchronous requests are desirable.
 *    This hint is a primarily a remnant for backwards compatible behaviour when working with jQuery.
 *
 * The \c success callback should be passed the deserialised API response body.
 * The \c error callback accepts two arguments: a descriptive status text string and the raw error object
 * which caused the \c error callback to be invoked.
 *
 * \note The \c httpAPICall represents the primary way to intercept HTTP(S) API calls issued from within the
 * \c janus.js library. You can use this mechanism to augment outgoing requests with additional headers
 * or to intercept responses. For example:
 *
 * -# You can support authentication schemes based on the HTTP \c Authorization header by
 * injecting it into outgoing API requests and routing them through a proxy.
 * -# You can intercept incoming responses and extract data from custom header values generated by a proxy.
 * -# You can combine both to implement a robust defence against <a href="https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)">CSRF</a>
 * -# You can reroute the control flow entirely, and e.g. use \c httpAPICall as an action creator in your
 * <a href="http://redux.js.org/">Redux</a> application.
 *
 * \section js-extension Custom Screensharing Extension for Chrome
 * To use a different extension for screensharing permissions in Chrome you can pass a \c extension object
 * to \c Janus.useDefaultDependencies and \c Janus.useOldDependencies.
 * The object should provide the following methods:
 *
 * -# \c init(): Do any setup work here. Will be called once when the dependencies are loaded.
 * -# \c isInstalled(): should return a boolean indicating whether the Extension was detected and is ready to use.
 * -# \c getScreen(callback): make a call to the extension to get a \c streamId here. The streamId can be obtained
 *    from chrome using <a href="https://developer.chrome.com/extensions/desktopCapture">chrome.desktopCapture.chooseDesktopMedia()</a>.
 *    When the request is successful pass the \c streamId back using <tt>callback(null, streamId)</tt>,
 *    otherwise pass an \c Error object like \c callback(error)
 */

/*! \page rest RESTful, WebSockets, RabbitMQ, MQTT, Nanomsg and UnixSockets API
 *
 * Since version \c 0.0.6, there are different ways to interact with a
 * Janus instance: a \ref plainhttp (the default), a \ref WS, a \ref rabbit, \ref apimqtt, \ref apinanomsg
 * and a \ref unix (both optional, need an external library to be available). All of
 * the interfaces use the same messages (in terms of requests, responses
 * and notifications), so almost all the concepts described in the
 * \ref plainhttp section apply to the WebSocket/RabbitMQ/MQTT/Nanomsg/UnixSockets interfaces as well.
 * Besides, since version \c 0.1.0 the transport mechanism for the Janus API
 * has been made modular, which means other protocols for transporting
 * Janus API messages might become available in the future: considering the
 * Janus protocol is supposed to be mostly agnostic to the protocol it is
 * transported on, the concepts explained in the following sections should
 * apply to those as well.
 *
 * As it will be explained later in the \ref WS, \ref rabbit, \ref apimqtt, \ref apinanomsg and \ref unix sections
 * below, the only differences come when addressing specific sessions/handles
 * and in part in how you handle notifications using something different than
 * the REST interface: in fact, since with WebSockets, RabbitMQ, MQTT, Nanomsg and UnixSockets
 * (and, as anticipated, with other protocols that may be added in the future too)
 * there's no REST-based path involved, you'll need a couple of additional
 * identifiers to bridge the gap.
 * Some details are also provided in case you're interested in \ref auth.
 *
 * \section plainhttp Plain HTTP REST Interface
 * As anticipated in the \ref JS documentation, the server deploys a
 * RESTful interface that clients can exploit. The \c janus.js library
 * makes use of it in a transparent way, but if you're interested in
 * more details about it (e.g., because you want to talk to the server
 * your own way), this page described the interface and the protocol
 * the API exposes and uses.
 *
 * There are basically three types/levels of endpoints you can meet:
 *
 * -# \ref root (\c /janus by default, but configurable), which
 * you only \b POST to in order to create a Janus session;
 * -# \ref sessions (e.g., \c /janus/12345678, using the
 * identifier retrieved with a previous create), which you either send
 * a \b GET to (long poll for events and messages from plugins) or a \b POST
 * (to create plugin handles or manipulate the session);
 * -# \ref handles (e.g., \c /janus/12345678/98765432, appending
 * the handle identifier to the session one) which you only send \b POST
 * messages to (messages/negotiations for a plugin, handle manipulation),
 * as all events related to this handle would be received in the session
 * endpoint \b GET (the \c janus.js library would redirect the incoming
 * messages to the right handle internally).
 *
 * Messages and requests you can send to and receive from any of the
 * above mentioned endpoints are described in the following chapters.
 * In general, all messages share at least two fields:
 *
 * - \c janus: the request/event (e.g., "create", "attach", "message", etc.);
 * - \c transaction: a random string that the client can use to match incoming
 * messages from the server (since, as explained in the \ref plugins
 * documentation, all messages are asynchronous).
 *
 * Different messages will of course add different information to this
 * base syntax. Error message, instead, usually have these fields:
 *
 * - \c janus: this would be "error";
 * - \c transaction: this would be the transaction identifier of the request
 * that failed;
 * - \c error: a JSON object containing two fields:
 *   - \c code: a numeric error code, as defined in apierror.h;
 *   - \c reason: a verbose string describing the cause of the failure.
 *
 * An example of an error is presented here:
 *
\verbatim
{
	"janus" : "error",
	"transaction" : "a1b2c3d4"
	"error" : {
		"code" : 458
		"reason" : "Could not find session 12345678"
	}
}
\endverbatim
 *
 *
 * \section info Getting info about the Janus instance
 * The API exposes an \c info endpoint you can query to get information
 * about the Janus instance you're talking to. Specifically, it returns
 * information about the version of the Janus server, whether some of the
 * optional features (e.g., Data Channels or IPv6) are supported or not,
 * and which transports and plugins are available.
 *
 * To get this information, just send an HTTP \b GET message to the \c info
 * endpoint (e.g., http://yourserver:8088/janus/info), which will return
 * something like this:
 *
\verbatim
{
	"janus": "server_info",
	"transaction": "i1bzIL341Kl2",
	"name": "Janus WebRTC Server",
	"version": 73,
	"version_string": "0.7.3",
	"author": "Meetecho s.r.l.",
	"data_channels": "true",	// Data channels are supported
	"ipv6": "false",			// IPv6 is not configured
	"ice-tcp": "false",			// ICE-TCP support is disabled,
	[..]
	"transports": {
		"janus.transport.http": {
			"name": "JANUS REST (HTTP/HTTPS) transport plugin",
			"author": "Meetecho s.r.l.",
			"description": "This transport plugin adds REST (HTTP/HTTPS) support to the Janus API via libmicrohttpd.",
			"version_string": "0.0.2",
			"version": 2
		},
		[..]	// Other transport plugins
	},
	"plugins": {
		"janus.plugin.sip": {		// The SIP plugin is available
			"version_string": "0.0.7",
			"description": "This is a simple SIP plugin for Janus, allowing WebRTC peers to register at a SIP server and call SIP user agents through Janus.",
			"author": "Meetecho s.r.l.",
			"name": "JANUS SIP plugin",
			"version": 7
		},
		"janus.plugin.videoroom": {	// The Video SFU plugin is available
			"version_string": "0.0.3",
			"description": "This is a plugin implementing a videoconferencing SFU (Selective Forwarding Unit) for Janus, that is an audio/video router.",
			"author": "Meetecho s.r.l.",
			"name": "JANUS VideoRoom plugin",
			"version": 3
		},
		[..]	// Other plugins
	}
\endverbatim
 *
 * You can use this information to selectively enable or disable features
 * in your application according to what's available in the Janus instance
 * you're trying to contact.
 *
 *
 * \section root The server root
 * The server root is \c /janus by default but, as anticipated, it is
 * configurable, either via command line or in the \c janus.jcfg configuration.
 *
 * You can only contact the server root when you want to create a new
 * session with the server. To do so, you need to \b POST the a \c janus "create"
 * JSON message to the server:
 *
\verbatim
{
	"janus" : "create",
	"transaction" : "<random alphanumeric string>"
}
\endverbatim
 *
 * If the request is successful, you'll receive the unique session identifier
 * in a response formatted like this:
 *
\verbatim
{
	"janus" : "success",
	"transaction" : "<same as the request>",
	"data" : {
		"id" : <unique integer session ID>
	}
}
\endverbatim
 *
 * In case of an error, you'll receive an error message as the one introduced
 * before. This request, if issued with a POST to the server root, can only
 * fail if you miss any of the required fields in the request.
 *
 *
 * \section sessions The session endpoint
 * Once you've created a session, a new endpoint you can use is created
 * in the server. Specifically, the new endpoint is constructed by
 * concatenating the server root and the session identifier you've been
 * returned (\c e.g., \c /janus/12345678).
 *
 * This endpoint can be used in two different ways:
 *
 * -# using a parameter-less \b GET request to the endpoint, you'll
 * issue a long-poll request to be notified about events and incoming
 * messages from this session;
 * -# using a \b POST request to send JSON messages, you'll interact
 * with the session itself.
 *
 * <hr>
 *
 * \par Long-poll requests
 * The long-poll will only trigger events related to messages you're
 * being sent from plugins, and as such will be clearer to understand
 * once you read the \ref handles section. That said, the events are formatted
 * this way:
 *
 * - \c janus: this would be "event";
 * - \c sender: this would be the unique numeric plugin handle identifier;
 * - \c transaction: this is optional: it is either related to a request
 * you sent to a plugin before, or it may be missing in case this is an
 * event the plugin sent on its own account;
 * - \c plugindata: a JSON object containing the info coming from the plugin itself:
 *   - \c plugin: the plugin's unique package name (e.g., \c janus.plugin.echotest);
 *   - \c data: an opaque JSON object that is plugin specific.
 * - \c jsep: an optional JSON object containing the JSEP SDP (offer or
 * answer) the plugin may send to negotiate a WebRTC PeerConnection with
 * the client (check the \ref handles section for more details).
 *
 * An example of such an event (in this case, sent by the janus_echotest.c
 * plugin in response to a request) is presented here:
 *
\verbatim
{
	"janus" : "event",
	"sender" : 1815153248,
	"transaction" : "sBJNyUhH6Vc6",
	"plugindata" : {
		"plugin": "janus.plugin.echotest",
		"data" : {
			"echotest" : "event",
			"result" : "ok"
		}
	}
}
\endverbatim
 *
 * The long-poll request has a 30 seconds timeout. If it has no event to
 * report, a simple \em keep-alive message will be triggered:
 *
\verbatim
{
	"janus" : "keepalive",
}
\endverbatim
 *
 * As with all long-poll based approaches, it's up to your application
 * to send a new polling request as soon as an event or a keep-alive
 * has been received.
 *
 * Notice that, by default, the long poll returns a single event: that is,
 * as soon as a message becomes available in the session queue, that event
 * is returned and the long poll closes. If you want to receive more events
 * within the context of the same long poll, you can pass the \c maxev
 * query string parameter to the GET, e.g.:
 *
\verbatim
GET http://host:port/janus/<sessionid>?maxev=5
\endverbatim
 *
\verbatim
[
	{
		// Event #1
		"janus" : "event",
		[..]
	},
	{
		// Event #2
		"janus" : "event",
		[..]
	},
	[..]
]
\endverbatim
 *
 * This request will instruct the server to return at maximum 5 events
 * within the context of the same long poll, formatted as a JSON array
 * of events. Please beware that this does \b NOT mean that you'll
 * always get 5 events this way: it only means that, if a message becomes
 * available in the queue and more events are present as well, Janus will
 * return more than one without needing you to send multiple long polls
 * immediately thereafter to get them. For this reason, don't be surprised
 * if even with a \c maxev parameter set, you'll still get a single
 * event being notified as the sole object in the returned array.
 *
 * <hr>
 *
 * \par Interacting with the session
 * To interact with the session, e.g., to create a new handle to attach
 * to a plugin or destroy the current session, you need to send a \b POST
 * JSON message to the session endpoint.
 *
 * To attach to a plugin in order to exploit its features, you need to
 * \b POST a \c janus "attach" JSON message to the server; you'll need
 * of course to provide information on the plugin you want to attach to,
 * which can be done using the \c plugin field:
 *
\verbatim
{
	"janus" : "attach",
	"plugin" : "<the plugin's unique package name>",
	"transaction" : "<random string>"
}
\endverbatim
 *
 * Notice that you can also provide an optional \c opaque_id string
 * identifier (for more details on why this might be useful, read more
 * <a href="https://github.com/meetecho/janus-gateway/pull/748">here</a>).
 * If the request is successful, you'll receive the unique plugin handle
 * identifier in a response formatted the same way as the session create
 * one, that is like this:
 *
\verbatim
{
	"janus" : "success",
	"transaction" : "<same as the request>",
	"data" : {
		"id" : <unique integer plugin handle ID>
	}
}
\endverbatim
 *
 * In case of an error, you'll receive an error message as the one introduced
 * before. This request, if issued with a POST to a valid session endpoint, can only
 * fail if you miss any of the required fields in the request or if the
 * plugin you requested is not available in the server.
 *
 * To destroy the current session, instead, just send a "destroy" \c janus
 * request:
 *
\verbatim
{
	"janus" : "destroy",
	"transaction" : "<random string>"
}
\endverbatim
 *
 * This will also destroy the endpoint created for this session.
 * If your session is currently managing one or more plugin handles,
 * make sure you destroy them first (as explained in the next section).
 * The server tries to do this automatically when receiving a session
 * destroy request, but a cleaner approach on the client side would help
 * nonetheless avoid potential issues.
 *
 * Notice that a session may also be destroyed automatically in case of
 * inactivity. If Janus doesn't receive any activity (requests, long polls)
 * for a session for a time longer than the \c session_timeout value
 * configured in \c janus.jcfg then the session will timeout, and a
 * \c timeout event will be fired. If a \c reclaim_session_timeout value
 * is configured, you can still reclaim the session from the same or
 * a different transport using the \c claim request, within a limited
 * amount of time. An unreclaimed session that has timed out will be
 * permanently destroyed, and will destroy all its handles as well.
 *
 * \section handles The plugin handle endpoint
 * Once you've created a plugin handle, a new endpoint you can use is created
 * in the server. Specifically, the new endpoint is constructed by
 * concatenating the server root, the session identifier and the new
 * plugin handle identifier you've been returned (\c e.g.,
 * \c /janus/12345678/98765432).
 *
 * You can use this plugin handle for everything that is related to the
 * communication with a plugin, that is, send the plugin a message,
 * negotiate a WebRTC connection to attach to the plugin, and so on.
 *
 * To send a plugin a message/request, you need to \b POST the handle
 * endpoint a \c janus "message" JSON payload. The \c body field will
 * have to contain a plugin-specific JSON payload. In case the message
 * also needs to convey WebRTC-related negotiation information, a \c jsep
 * field containing the JSON-ified version of the JSEP object can be
 * attached as well.
 *
 * \note If you attach a \c jsep object, whether it's an offer or an answer,
 * you're stating your will to negotiate a PeerConnection. This means that
 * an empty or invalid \c jsep object will trigger a validation and will
 * cause the whole request to fail, so make sure you exclude the field
 * completely from your request if all you're interested into is sending
 * a message to a plugin.
 *
 * Here's an example of a message you may send the janus_echotest.c plugin
 * to mute your audio:
 *
\verbatim
{
	"janus" : "message",
	"transaction" : "sBJNyUhH6Vc6",
	"body" : {
		"audio" : false
	}
}
\endverbatim
 *
 * The same message containing negotiation information as well, instead,
 * (an OFFER, in this example), is presented here:
 *
\verbatim
{
	"janus" : "message",
	"transaction" : "sBJNyUhH6Vc6",
	"body" : {
		"audio" : false
	},
	"jsep" : {
		"type" : "offer",
		"sdp" : "v=0\r\no=[..more sdp stuff..]"
	}
}
\endverbatim
 *
 * Please notice that, if for any reason you don't want to use the
 * trickling of ICE candidates from your application (which means you'll
 * include them all in the SDP OFFER or ANSWER, which is usually not
 * recommended), you'll have to add an additional <code>"trickle" : false</code>
 * attribute to the "jsep" object, to explicitly tell Janus you won't
 * send any \c trickle candidate (by default Janus will always assume
 * support for trickle).
 *
 * If you're going to \c trickle candidates, instead, there is an ad-hoc
 * message you can use to do so which is called, unsurprisingly, \c trickle
 * and which you can use to send one or more trickle candidates to Janus.
 * Since such a message is related to a specific PeerConnection, it will
 * need to be addressed to the right Handle just as the \c message introduced
 * previously. A \c trickle message can contain three different kind of
 * information:
 *
 *  - a single trickle candidate;
 *  - an array of trickle candidates;
 *  - a null candidate or a \c completed JSON object to notify the end of the
 * candidates.
 *
 * This is an example of a single candidate being trickled:
 *
\verbatim
{
	"janus" : "trickle",
	"transaction" : "hehe83hd8dw12e",
	"candidate" : {
		"sdpMid" : "video",
		"sdpMLineIndex" : 1,
		"candidate" : "..."
	}
}
\endverbatim
 *
 * This, instead, is an example of how to group more trickle candidates
 * in a single request (particularly useful if you're wrapping Janus in
 * your server and want to reduce the number of transactions):
 *
\verbatim
{
	"janus" : "trickle",
	"transaction" : "hehe83hd8dw12e",
	"candidates" : [
		{
			"sdpMid" : "video",
			"sdpMLineIndex" : 1,
			"candidate" : "..."
		},
		{
			"sdpMid" : "video",
			"sdpMLineIndex" : 1,
			"candidate" : "..."
		},
		[..]
	]
}
\endverbatim
 *
 * Finally, this is how you can tell Janus that you sent all the trickle
 * candidates that were gathered:
 *
\verbatim
{
	"janus" : "trickle",
	"transaction" : "hehe83hd8dw12e",
	"candidate" : {
		"completed" : true
	}
}
\endverbatim
 *
 * Plugins may handle this requests synchronously or asynchronously. In
 * the former, plugins would return a response to the request itself
 * immediately; in the latter, instead, the plugin would only notify a
 * successful reception of the request, which it would process later.
 * Considering the asynchronous nature of the Janus API, a successful
 * management of such messages within Janus would in such case result in
 * a \c janus "ack" messages being sent back to the client. A logical response
 * to those messages, if needed, would be provided as an event in the
 * long-poll interface described previously, and clients would be able
 * to match it to the original request by means of the transaction
 * identifiers. It is worth noting, though, that should a WebRTC negotiation
 * be involved you don't have to expect an ANSWER to your OFFER to be
 * sent back in the same transaction. A plugin may decide, in its
 * application logic, to not provide you with an ANSWER right away, but
 * only after some internal state changes occur. It's up to your application
 * to handle the negotiation state accordingly.
 *
 * An example of an "ack" being sent back to the client, using the previous
 * sample request as a reference, is presented here:
 *
\verbatim
{
	"janus" : "ack",
	"transaction" : "sBJNyUhH6Vc6"
}
\endverbatim
 *
 * If you receive this ack instead of a "success" response, you can be
 * sure the plugin has received the message, and is going to process it soon.
 *
 * In case of an error, instead, you'll receive an error message as the one
 * introduced before. This request, if issued with a POST to a valid plugin
 * handle endpoint, can only fail if you miss any of the required fields
 * in the request, if the plugin you tried to contact is not available in
 * the server anymore, if an error occurred in the plugin when trying to
 * receive the message or if the \c jsep SDP you may have provided is
 * invalid.
 *
 * To destroy the plugin handle, instead, just send a "detach" \c janus
 * request:
 *
\verbatim
{
	"janus" : "detach",
	"transaction" : "<random string>"
}
\endverbatim
 *
 * This will also destroy the endpoint created for this plugin handle.
 * If your plugin handle is also managing an ongoing WebRTC connection
 * with the plugin, make sure it is torn down as part of this process.
 * The plugin implementation and the Janus core should do this
 * automatically, but implementing the right behaviour in clients would
 * help avoid potential issues nonetheless. Notice that you may receive
 * \c detached event after a handle has been detached, whether this was
 * done in response to a request or automatically, in response to an event.
 *
 * If you're interested in keeping the handle alive but want to hang up
 * the associated PeerConnection, if available, just send a "hangup" \c janus
 * request:
 *
\verbatim
{
	"janus" : "hangup",
	"transaction" : "<random string>"
}
\endverbatim
 *
 * This is usually not required, as you can typically just hangup your
 * WebRTC PeerConnection normally and Janus will figure out it's gone
 * by itself. Anyway, there are cases where this might be useful (e.g.,
 * the connection was stuck in some weird ICE/DTLS state) as it can be
 * used to reset the connection state for the handle.
 *
 * \section events WebRTC-related events
 *
 * As anticipated in the previous sections, Janus can send events and
 * notifications at any time through the long poll channel (or, as it
 * will be explained later, through the related push mechanisms made
 * available by other transport protocols ). While this channel is
 * mostly used to convey asynchronous notifications originated by
 * plugins as part of the messaging they may have with the application
 * using it, the same channel is actually used by Janus to trigger
 * events related to different aspects pertaining a specific handle.
 *
 * In particular, for each handle involving a PeerConnection Janus
 * provides notifications about its current state. To do so, the
 * following events may be received as well:
 *
 *  - \c webrtcup: ICE and DTLS succeeded, and so Janus correctly
 * established a PeerConnection with the user/application;
 *  - \c media: whether Janus is receiving (\c receiving: \c true/false)
 * audio/video (\c type: \c "audio/video") on this PeerConnection;
 *  - \c slowlink: whether Janus is reporting trouble sending/receiving
 * (\c uplink: \c true/false) media on this PeerConnection;
 *  - \c hangup: the PeerConnection was closed, either by Janus or by
 * the user/application, and as such cannot be used anymore.
 *
 * As such, to monitor the status of a PeerConnection as seen from
 * Janus you can make use of these events to track what's going on. A
 * correct flow for an active PeerConnection would be one that, after a
 * WebRTC negotiation and setup, results in a \c webrtcup event followed
 * by two \c media events (in case both audio and video have been
 * negotiated) specifying that the first audio/video packets have been
 * received. A \c hangup event would inform the user/application that
 * no media is being exchanged with Janus anymore.
 *
 * Here are a few examples of how these events may look like.
 *
 * A PeerConnection becoming ready:
 *
\verbatim
{
	"janus" : "webrtcup",
	session_id: <the session identifier>,
	sender: <the handle identifier>
}
\endverbatim
 *
 * First audio bytes being received by Janus:
 *
\verbatim
{
	"janus" : "media",
	session_id: <the session identifier>,
	sender: <the handle identifier>,
	"type" : "audio",
	"receiving" : true
}
\endverbatim
 *
 * Audio not getting to Janus anymore for some reason:
 *
\verbatim
{
	"janus" : "media",
	"session_id" : <the session identifier>,
	"sender" : <the handle identifier>
	"type" : "audio",
	"receiving" : false
}
\endverbatim
 *
 * Audio getting to Janus again (same message as first audio):
 *
\verbatim
{
	"janus" : "media",
	"session_id" : <the session identifier>,
	"sender" : <the handle identifier>
	"type" : "audio",
	"receiving" : true
}
\endverbatim
 *
 * Janus reporting problems sending media to a user (user sent many NACKs
 * in the last second; uplink=true is from Janus' perspective):
 *
\verbatim
{
	"janus" : "slowlink",
	"session_id" : <the session identifier>,
	"sender" : <the handle identifier>
	"uplink" : true,
	"nacks" : <number of NACKs in the last second>
}
\endverbatim
 *
 * PeerConnection closed for a DTLS alert (normal shutdown):
 *
\verbatim
{
	"janus" : "hangup",
	"session_id" : <the session identifier>,
	"sender" : <the handle identifier>,
	"reason" : "DTLS alert"
}
\endverbatim
 *
 * It is important to point out that the \c media event notifications
 * only apply if your PeerConnection is going to actually send media to
 * Janus. A \c recvonly PeerConnection, for instance (e.g., as the
 * Streaming plugin would create) would never trigger any \c media
 * event, as Janus would never be receiving media, but only send it.
 *
 * \section WS WebSockets Interface
 * WebSockets provide a more efficient means for implementing a bidirectional communication.
 * This is especially useful if you're wrapping the Janus API on your
 * servers, as it allows you to avoid all the noise and overhead introduced
 * by several concurrent HTTP transactions and long polls by relying on
 * what may be seen as a single "control channel".
 *
 * To interact with Janus using WebSockets you MUST specify a specific
 * subprotocol, named \c janus-protocol, e.g.,
 *
\verbatim
var websocket = new WebSocket('ws://1.2.3.4:8188', 'janus-protocol');
\endverbatim
 *
 * The \c janus.js library does this automatically.
 *
 * As anticipated at the beginning of this section, the actual messages
 * being exchanged are exactly the same. This means that all the concepts
 * introduced before still apply: you still create a session, attach to
 * a plugin and interact with it exactly the same way. What is different
 * is, of course, the REST path approach that becomes unavailable when
 * using a WebSocket as a control channel. To address the idenfitiers
 * that become missing using WebSockets, you'll need to add additional
 * fields to the requests when necessary.
 *
 * So, when you want to create a session using the REST API, you send a
 * POST to the server base path:
 *
\verbatim
{
	"janus" : "create",
	"transaction" : "<random alphanumeric string>"
}
\endverbatim
 *
 * The same applies if you're interested in getting generic info from the
 * Janus instance. Since there's no \b GET you can use, a specific \c janus
 * request type called \c info is available:
 *
\verbatim
{
	"janus" : "info",
	"transaction" : "<random alphanumeric string>"
}
\endverbatim
 *
 * Since you'd contact the base path for both requests, you don't need to add any identifier
 * for this scenario. But if instead you want to attach to a plugin within
 * the context of a specific session, using the REST API you'd send a
 * post to the \c /janus/<session-id> endpoint:
 *
\verbatim
{
	"janus" : "attach",
	"plugin" : "<the plugin's unique package name>",
	"transaction" : "<random string>"
}
\endverbatim
 *
 * To make this work with WebSockets as well, you need to add a further
 * field called \c session_id in the request:
 *
\verbatim
{
	"janus" : "attach",
	"session_id" : <the session identifier>,		// NEW!
	"plugin" : "<the plugin's unique package name>",
	"transaction" : "<random string>"
}
\endverbatim
 *
 * which will allow the WebSocket server to understand which session this
 * request pertains to. At the same time, when you need to address a
 * specific handle (e.g., to send a message to a plugin, or negotiate a
 * WebRTC PeerConnection) you'll need to add a \c handle_id field to the
 * request as well, or the request will be rejected:
 *
\verbatim
{
	"janus" : "message",
	"session_id" : <the session identifier>,		// NEW!
	"handle_id" : <the handle identifier>,		// NEW!
	"transaction" : "sBJNyUhH6Vc6",
	"body" : {
		"audio" : false
	}
}
\endverbatim
 *
 * Considering the bidirectional nature of WebSockets and the fact that
 * the channel will be shared for different requests, you'll need to pay
 * extra attention to the \c transaction identifier, which will allow you
 * to map incoming responses and events to the request you sent that
 * originated them.
 *
 * An \b important aspect to point out is related to keep-alive messages
 * for WebSockets Janus channels. As explained above, a Janus session is
 * kept alive as long as there's no inactivity for \c session_timeout seconds:
 * if no messages have been received in that time frame, the session is
 * marked as timed-out and, unless reclaimed, will be torn down by the server.
 * A normal activity on a session is usually enough to prevent that;
 * for a more prolonged inactivity with respect to messaging, on plain
 * HTTP the session is usually kept alive through the regular long poll
 * requests, which act as activity as long as the session is concerned.
 * This aid is obviously not possible when using WebSockets, where a single channel is
 * used both for sending requests and receiving events and responses. For
 * this reason, an ad-hoc message for keeping alive a Janus session should
 * to be triggered on a regular basis:
 *
\verbatim
{
	"janus" : "keepalive",
	"session_id" : <the session identifier>,
	"transaction" : "sBJNyUhH6Vc6"
}
\endverbatim
 *
 * This will make sure that the server detects activity on the session
 * even when no actual messages are being exchanged with handles.
 *
 * As a last point, another slight difference with WebSockets comes from
 * how push notifications are implemented. In the \ref plainhttp this is
 * done via long polls: that is, you explicitly subscribe to notifications,
 * and have to do that again as soon as an event has been received. With
 * WebSockets, this is not needed: as soon as you create a session on a
 * WebSocket, that channel becomes automatically subscribed for events
 * related to that sessions, and you'll receive them on the same WebSocket.
 * For the same reason, as soon as the WebSocket is closed, all the sessions
 * created within its context are considered closed as well, and so their
 * resources (including all the handles and PeerConnections) will be
 * released as well.
 *
 * \note The same \c janus.js JavaScript library can be used both with the
 * REST and the WebSockets API: all you need to do is provide the right
 * Janus server address during the initialization and the library will
 * use one or the other according to the protocol prefix.
 *
 * \section rabbit RabbitMQ interface
 * The semantics of how the requests have to be built, when compared to
 * the usage of plain HTTP, is exactly the same as for WebSockets, so
 * refer to the \ref WS documentation for details about that.
 *
 * Of course, there are other aspects that differ when making use of
 * RabbitMQ messaging to talk to Janus, rather than using HTTP messages
 * or WebSockets. Specifically, RabbitMQ just basically forwards messages
 * on queues, and as such implementing a pseudo-bidirectional channel
 * as the Janus API requires some precaution.
 *
 * In particular, when configuring Janus to use RabbitMQ you'll have to
 * specify \b two \b queues:
 *
 * - a queue for \b incoming messages (application -> Janus);
 * - a queue for \b outgoing messages (Janus -> application).
 *
 * The proper usage of these queues will allow you to implement the kind
 * of bidirectional channel Janus needs.
 *
 * Another aspect to point out is that Janus requires all requests to
 * have a random \c correlation_id identifier. In fact, as pointed out
 * in the previous sections, the Janus API is conceived as a request/response
 * protocol that can involve asynchronous notifications as well. In order
 * to make sure that an application can match a received response to one
 * of the requests made earlier, Janus copies the \c correlation_id
 * identifier from the original request in the response to it: this is
 * compliant with the
 * <a href="https://www.rabbitmq.com/tutorials/tutorial-six-python.html">RPC pattern</a>
 * as specified in the RabbitMQ documentation. Notifications originated by
 * Janus, instead, will not include a \c correlation_id identifier, and as
 * such applications shouldn't expect any: applications will still be able
 * to match a notification to a request, if the involved plugin was
 * implemented to do so, by looking at the Janus-level \c transaction
 * identifier.
 *
 * \section apimqtt MQTT interface
 * The semantics of how the requests have to be built, when compared to
 * the usage of plain HTTP, is exactly the same as for WebSockets, so
 * refer to the \ref WS documentation for details about that.
 *
 * Of course, there are other aspects that differ when making use of
 * MQTT messaging to talk to Janus, rather than using HTTP messages
 * or WebSockets. Similar to RabbitMQ, MQTT just basically forwards messages
 * on queues, and as such implementing a pseudo-bidirectional channel
 * as the Janus API requires some precaution.
 *
 * In particular, when configuring Janus to use MQTT you'll have to
 * specify \b two \b queues:
 *
 * - a queue for \b incoming messages (application -> Janus);
 * - a queue for \b outgoing messages (Janus -> application).
 *
 * The proper usage of these queues will allow you to implement the kind
 * of bidirectional channel Janus needs.
 *
 * \section apinanomsg Nanomsg interface
 * The semantics of how the requests have to be built, when compared to
 * the usage of plain HTTP, is exactly the same as for WebSockets, RabbitMQ
 * and MQTT, so refer to the \ref WS documentation for details about that.
 *
 * Apart from that, the only configuration needed is related to the Nanomsg
 * address to use, and whether it should be used to bind locally or to
 * connect to a remote endpoint. Notice that only the \c NN_PAIR pattern
 * is supported by the plugin, so no Pub/Sub or other variations.
 *
 * \section unix UnixSockets interface
 * The semantics of how the requests have to be built, when compared to
 * the usage of plain HTTP, is exactly the same as for WebSockets, RabbitMQ
 * MQTT and Nanomsg, so refer to the \ref WS documentation for details about that.
 *
 * Apart from that, the only configuration needed is related to the path
 * the client and server will be sharing, and the socket type. Notice that only the
 * \c SOCK_SEQPACKET and \c SOCK_DGRAM types are supported in the plugin.
 *
 */

/*! \page auth Authenticating the Janus API
 * By default no authentication is involved when using the Janus API.
 * This means that the API is completely open, and that everybody can
 * talk to Janus and its plugins and set up media connections. There are
 * times, though, where limiting access to Janus may be desirable, e.g.,
 * when you want to prevent unauthorized users to join a service you
 * created, or when you wrap the Janus API in your server and you want
 * your application to be the only one to be able to interact with
 * Janus from a messaging perspective.
 *
 * There are a couple of ways to authenticate requests in Janus:
 *
 * - using a \ref token (useful for web users);
 * - using a \ref signed (useful for web users);
 * - using a \ref secret (useful when wrapping the Janus API).
 *
 * \section token Stored token based authentication mechanism
 * The token based authentication mechanism expects all users to provide,
 * in each request, a \c token string attribute: if this token is
 * known to Janus, the request will be accepted, otherwise it will be
 * rejected as an \c unauthorized response. Configuring the token based
 * authentication mechanism is easy enough: you can do that either via
 * the command line (\c -A or \c --token-auth ) or in the \c janus.jcfg
 * configuration (\c token_auth value in the \c general section).
 *
 * These tokens are completely opaque to Janus, meaning they can be
 * pretty much anything that you want. Janus does not do any form of
 * authorization/authentication itself: it's up to you to provide it
 * with valid tokens users can use, e.g., as part of your server-side
 * application handling users. You can add and remove tokens
 * dynamically using the \ref admin, which means you will need to enable
 * it if you want to use tokens, or otherwise all requests will fail
 * (Janus will never have a valid token, so all requests will be rejected).
 *
 * You add tokens using the \c add_token admin request, while you
 * remove them using \c remove_token. You can also limit the scope of tokens
 * to specific plugins, by passing a list of plugins to \c add_token or
 * modifying the token properties via \c allow_token and \c disallow_token.
 * By default (\c add_token without any plugin specified) Janus assumes
 * a new token is allowed to access all plugins. A list of all the
 * existing tokens can be retrieved with a \c list_tokens request.
 *
 * Here are a couple of examples of how you can use the requests:
 *
\verbatim
{
	"janus" : "add_token",
	"token": "a1b2c3d4",
	"transaction" : "sBJNyUhH6Vc6",
	"admin_secret": "adminpassword"
}
\endverbatim
 *
 * This adds a new token (a1b2c3d4) that is allowed to access all the
 * plugins in Janus (no limitation provided in \c add_token ). To create
 * a new token and limit the scope to a few selected plugins, you can
 * use this other syntax instead (notice the extra \c plugins array):
 *
\verbatim
{
	"janus" : "add_token",
	"token": "a1b2c3d4",
	"plugins": [
		"janus.plugin.streaming",
		"janus.plugin.videoroom"
	],
	"transaction" : "sBJNyUhH6Vc6",
	"admin_secret": "adminpassword"
}
\endverbatim
 *
 * In this other example, we're creating a new token, and also telling
 * Janus that the only plugins a user with this token can access are
 * the Streaming and Videoroom plugins. An attempt to attach to a
 * different plugin (e.g., EchoTest) will result in an error.
 *
 * You can change the permissions a token has with respect to plugin
 * access at any time. In the following example, we add a new plugin
 * to the permissions for an existing token:
 *
\verbatim
{
	"janus" : "allow_token",
	"token": "a1b2c3d4",
	"plugins": [
		"janus.plugin.echotest"
	],
	"transaction" : "sBJNyUhH6Vc6",
	"admin_secret": "adminpassword"
}
\endverbatim
 *
 * This way, the provided token is now also allowed to access the EchoTest
 * plugin. To remove a permission, the syntax is this one instead:
 *
\verbatim
{
	"janus" : "disallow_token",
	"token": "a1b2c3d4",
	"plugins": [
		"janus.plugin.videoroom"
	],
	"transaction" : "sBJNyUhH6Vc6",
	"admin_secret": "adminpassword"
}
\endverbatim
 *
 * To retrieve a list of all the valid tokens Janus is aware of, together
 * with the plugins each of them is allowed to access, a \c list_tokens
 * request can be used:
 *
\verbatim
{
	"janus" : "list_tokens",
	"transaction" : "sBJNyUhH6Vc6",
	"admin_secret": "adminpassword"
}
\endverbatim
 *
 * Finally, you can get rid of a token using a \c remove_token request:
 *
\verbatim
{
	"janus" : "remove_token",
	"token": "a1b2c3d4",
	"transaction" : "sBJNyUhH6Vc6",
	"admin_secret": "adminpassword"
}
\endverbatim
 *
 * As anticipated, with the token based mechanism enabled, all users
 * will need to provide a valid token as part of their requests. This is
 * done by adding a \c token attribute to the request root, e.g.:
 *
\verbatim
{
	"janus" : "create",
	"transaction" : "sBJNyUhH6Vc6",
	"token": "usertoken"
}
\endverbatim
 *
 * The same applies for the long poll GET messages as well, which will
 * need to contain the \c token as a query string parameter.
 *
 * A valid token will mean the request will be accepted and processed
 * normally. A missing or invalid token, instead, will result in an
 * error being returned:
 *
\verbatim
{
	"janus" : "error",
	"transaction" : "sBJNyUhH6Vc6",
	"error" : {
		"code" : 403,
		"reason" : "Unauthorized request (wrong or missing secret/token)"
	}
}
\endverbatim
 *
 * An attempt to use a valid token to attach to a plugin it is not
 * allowed to access, instead, will result in a different error:
 *
\verbatim
{
	"janus" : "error",
	"transaction" : "sBJNyUhH6Vc6",
	"error" : {
		"code" : 405,
		"reason" : "Provided token can't access plugin 'janus.plugin.echotest'"
	}
}
\endverbatim
 *
 * \section signed HMAC-Signed token authentication
 *
 * <div class="well"><b>NOTE WELL:</b> At the time of writing, HMAC-Signed
 * tokens are ONLY available for the VideoRoom plugin. If you need authentication
 * for other plugins, you should use the \ref token instead.</div>
 *
 * Simple token based authentication requires the application host to
 * continuously update the Janus instance on permission changes.
 * Since Janus stores the tokens in memory, it can be problematic to guarantee
 * the permissions of a dynamic application stay in sync with Janus.
 *
 * This problem can be solved by using a type of nonce / lease system to
 * let the application server generate automatically expiring tokens without
 * requiring direct communication with or any data storage in Janus.
 *
 * You can use the HMAC signed token mechanism by enabling token authentication
 * in general, as above (\c -A or \c --token-auth) and specifying an encryption
 * secret using \c --token-auth-secret. The same can be accomplished using
 * \c token_auth and \c token_auth_secret in the \c general section of
 * \c janus.jcfg.
 *
 * With Signed token support enabled, dynamic token creation via the \ref admin
 * is not supported. Instead, Janus will look for tokens with a format like:
 *
\verbatim
<timestamp>,janus,<plugin1>[,plugin2...]:<signature>
\endverbatim
 *
 * Where \c timestamp is a UNIX timestamp (seconds since 0:00 UTC, 1.1.1970)
 * that marks the point in time at which the token expires;
 * \c plugin1 etc. are the \c bundle names of plugins (such as \c janus.plugin.videoroom);
 * and \c signature is the base64-encoded HMAC-SHA1 signature of the expiry
 * timestamp in ASCII format, hashed using the \c --token-auth-secret as a key.
 *
 * The following function can be used to sign tokens using the node.js crypto library:
 *
\verbatim
const crypto = require('crypto');
function getJanusToken(realm, data = [], timeout = 24 * 60 * 60) {
  const expiry = Math.floor(Date.now() / 1000) + timeout;

  const strdata = [expiry.toString(), realm, ...data].join(',');
  const hmac = crypto.createHmac('sha1', secret);
  hmac.setEncoding('base64');
  hmac.write(strdata);
  hmac.end();

  return [strdata, hmac.read()].join(':');
};

const token = getJanusToken('janus', ['janus.plugin.videoroom']);
\endverbatim
 *
 * The \c janus parameter here is the \c realm of the token. For authenticating the
 * Janus API it should always be set to \c janus.
 *
 * When Janus encounters a token, it will:
 *
 * - verify that the timestamp has not passed
 * - verify that the signature matches the timestamp
 * - if the request requires access to a plugin, verify that the signature allows access
 *
 * Since the auth secret should never leave the application side, a signature
 * like this can only be generated by the application server, which needs to
 * be configured using the same secret.
 *
 * Please note that tokens of this sort cannot be revoked after being signed
 * and passed to the client. Instead of signing tokens with late expirys,
 * it is recommended to use tokens with shorter durations and generate and
 * transition to a new token within the expiry time of every last token when
 * the lease time is unknown and security is critical.
 *
 * \section secret Shared static secret
 * Several deployers showed an interest in wrapping the Janus API on
 * their server side: this allows them to keep the interaction with their
 * users the way it was before, while still benefiting from the features
 * Janus provides. This is an easy enough step, as it just needs developers
 * to relay the involved SDP, and implementing the Janus API messages to
 * handle the logic.
 *
 * That said, since in this case Janus would be contacted, through the API,
 * just by a limited number of applications (e.g., application servers
 * made in node.js, Ruby, Java Servlets or whatever) and not random
 * browsers, it is reasonable to involve a mechanism to control who is
 * allowed to contact and control it. The previous section described
 * how you can exploit a token based mechanism for authenticating
 * requests, but since in this case you only need a single application,
 * or a limited set of them,
 * to be able to talk to Janus, it's worthwhile to resort to something
 * simpler and more static. To allow for that, Janus also exposes a
 * shared API secret mechanism: that is, you configure Janus with a string
 * applications need to present when sending requests, and if they don't,
 * Janus rejects them with an \c unauthorized message.
 *
 * Configuring the API secret mechanism is easy enough: you can do that
 * either via the command line (\c -a or \c --apisecret ) or in the
 * \c janus.jcfg configuration (\c api_secret value in the \c general section).
 * When enabled, all requests addressed to that Janus instance \b MUST
 * also contain an \c apisecret field in the Janus message headers. For
 * instance, this message presented above would fail:
 *
\verbatim
{
	"janus" : "create",
	"transaction" : "<random alphanumeric string>"
}
\endverbatim
 *
\verbatim
{
	"janus" : "error",
	"transaction" : "<same as request>"
	"error" : {
		"code" : 403,
		"reason" : "Unauthorized request (wrong or missing secret/token)"
	}
}
\endverbatim
 *
 * For a successful transaction, the message would have to look like this:
 *
\verbatim
{
	"janus" : "create",
	"apisecret" : "<API secret configured in Janus>",
	"transaction" : "<random alphanumeric string>"
}
\endverbatim
 *
 * The same applies for the long poll GET messages as well, which will
 * need to contain the \c apisecret as a query string parameter.
 *
 */

/*! \page admin Admin/Monitor API
 * Recent versions of Janus introduced a new feature: an Admin/Monitor
 * API that can be used to ask Janus for more specific information
 * related to sessions and handles. This is especially useful when you
 * want to debug issues at the media level.
 *
 * \note Right now, this new API mostly allows you to retrieve information,
 * but only act on part of it: for more interaction (e.g., to force a
 * session removal), you can rely on the existing \ref rest for the purpose.
 * Besides, notice that this is a pull-based API. If you're interested in
 * asynchronous notifications about the internal state of core and plugins,
 * check the recently added janus_eventhandler mechanism instead.
 *
 * The API, for security reasons, is typically not enabled by default in any of the
 * transport plugins: that's definitely the case for the stock transport
 * plugins, for instance, while additional, third party plugins may choose
 * to expose the functionality without requiring any tweaking. As to the
 * existing transport, you can enable the admin API by editing the \c [ \c admin \c ]
 * section in the related transport configuration file (e.g., \c janus.transport.http.jcfg
 * for the REST interface, to use the admin API over HTTP). The configuration
 * is pretty much the same as the one for the Janus API. In addition, you
 * can configure restrictions in the form of a password/secret that clients
 * need to provide or other transport-specific ones.
 *
 * For what concerns the syntax, it's very similar to the \ref rest and
 * so this page will briefly discuss the differences. Notice that, when
 * using WebSockets, you'll have to use <code>janus-admin-protocol</code>
 * as the subprotocol, instead of the <code>janus-protocol</code> of the
 * regular Janus API.
 *
 * \section adminreq Admin API requests
 * There are several different requests that this API implementents, so,
 * to make this documentation easier to read and the functionality easier
 * to identify, we can group requests depending on what they provide.
 *
 * \subsection adminreqg Generic requests
 * - \c info: get the generic on the Janus instance; this returns exactly
 * the same information that a Janus API \c info request would return,
 * and doesn't require any secret;
 * - \c ping: a simple ping/pong mechanism for the Admin API, that returns
 * a \c pong back that the client can use as a healthcheck or to measure
 * the protocol round-trip time; together with the \c info request introduced
 * above, it's the only one that doesn't require a secret;
 * - \c loops_info: returns a summary of how many handles each static
 * event loop is currently responsible for, in case static event loops
 * are in use (returns an empty array otherwise).
 *
 * \subsection adminreqc Configuration-related requests
 * - \c get_status: returns the current value for the settings that can be
 * modified at runtime via the Admin API (see below);
 * - \c set_session_timeout: change global session timeout value in Janus;
 * - \c set_log_level: change the log level in Janus;
 * - \c set_log_timestamps: selectively enable/disable adding a timestamp
 * to all log lines Janus writes on the console and/or to file;
 * - \c set_log_colors: selectively enable/disable using colors in all
 * log lines Janus writes on the console and/or to file;
 * - \c set_locking_debug: selectively enable/disable a live debugging of
 * the locks in Janus on the fly (useful if you're experiencing deadlocks
 * and want to investigate them);
 * - \c set_refcount_debug: selectively enable/disable a live debugging of
 * the reference counters in Janus on the fly (useful if you're experiencing
 * memory leaks in the Janus structures and want to investigate them);
 * - \c set_libnice_debug: selectively enable/disable libnice debugging;
 * - \c set_min_nack_queue: change the value of the min NACK queue window;
 * - \c set_no_media_timer: change the value of the no-media timer property;
 * - \c set_slowlink_threshold: change the value of the slowlink-threshold property.
 *
 * \subsection adminreqk Token-related requests
 * - \c add_token: add a valid token (only available if you enabled the \ref token);
 * - \c allow_token: give a token access to a plugin (only available if you enabled the \ref token);
 * - \c disallow_token: remove a token access from a plugin (only available if you enabled the \ref token);
 * - \c list_tokens: list the existing tokens (only available if you enabled the \ref token);
 * - \c remove_token: remove a token (only available if you enabled the \ref token).
 *
 * \subsection adminreqs Session-related requests
 * - \c accept_new_sessions: configure whether Janus should accept new
 * incoming sessions or not; this can be particularly useful whenever, e.g.,
 * you want to stop accepting new sessions because you're draining this instance;
 * - \c list_sessions: list all the sessions currently active in Janus
 * (returns an array of session identifiers);
 * - \c set_session_timeout: change session timeout value in Janus;
 * - \c destroy_session: destroy a specific session; this behaves exactly
 * as the \c destroy request does in the Janus API.
 *
 * \subsection adminreqh Handle- and WebRTC-related requests
 * - \c list_handles: list all the ICE handles currently active in a Janus
 * session (returns an array of handle identifiers);
 * - \c handle_info: list all the available info on a specific ICE handle;
 * if a \c plugin_only property is set to \c true then only the plugin-specific
 * information is returned, excluding the more verbose WebRTC info and stats;
 * - \c start_pcap: start dumping incoming and outgoing RTP/RTCP packets
 * of a handle to a pcap file (e.g., for ex-post analysis via Wireshark);
 * - \c stop_pcap: stop the pcap dump;
 * - \c start_text2pcap: same as above, but saves to a text file instead,
 * to be fed to \c text2pcap in order to generate a \c .pcap or \c .pcapng file;
 * - \c stop_text2pcap: stop the text2pcap dump;
 * - \c message_plugin: send a synchronous request to a plugin and return a
 * response; implemented by most plugins to facilitate and streamline the
 * management of plugin resources (e.g., creating rooms in a conference plugin);
 * - \c hangup_webrtc: hangups the PeerConnection associated with a specific
 * handle; this behaves exactly as the \c hangup request does in the Janus API.
 * - \c detach_handle: detached a specific handle; this behaves exactly
 * as the \c detach request does in the Janus API.
 *
 * \subsection adminreqt Transport-related requests
 * - \c query_transport: send a synchronous request to a transport plugin and
 * return a response; whether this is implemented, and what functionality is
 * provided, can vary from transport to transport, but in general this feature
 * is available to tweak some setting dynamically and/or query some internal
 * transport-specific information (e.g., the number of served connections).
 *
 * \subsection adminreqe Event handlers-related requests
 * - \c query_eventhandler: send a synchronous request to an event handler and
 * return a response; implemented by most event handlers to dynamically
 * configure some of their properties;
 * - \c custom_event: push a custom "external" event to notify via event handlers;
 * this can be useful whenever info from a third-party application needs to be
 * easily correlated to events originated by Janus, or to push information
 * Janus doesn't have available (e.g., a script polling CPU usage regularly).
 *
 * \subsection adminreql Custom logging-related requests
 * - \c custom_logline: push a custom "external" string to print on the logs;
 * this can be useful whenever info from a third-party application needs to be
 * injected in the Janus logs for whatever reason. The log level can be chosen.
 *
 * \subsection adminreqz Helper requests
 * - \c resolve_address: helper request to evaluate whether this Janus instance
 * can resolve an address via DNS, and how long it takes;
 * - \c test_stun: helper request to evaluate whether this Janus instance
 * can contact a STUN server, what is returned, and how long it takes.
 *
 * \section adminsyntax Admin API syntax
 * Following the same spirit of the \ref rest these methods need to be
 * invoked on the right path and/or providing the right \c session_id and
 * \c handle_id identifiers. Specifically, the following requests must be invoked
 * without any session/handle information, as they're global requests:
 *
 * - \c info , \c ping , \c get_status , all the configuration setters, all
 * the token requests, all the event-handler related requests, all the
 * helper requests, \c accept_new_sessions and \c list_sessions
 *
 * Here's an example of how such a request and its related response might look like:
 *
\verbatim
POST /admin
{
	"janus" : "list_sessions",
	"transaction" : "<random alphanumeric string>",
	"admin_secret" : "<password specified in janus.jcfg, if any>"
}
\endverbatim
 *
 *
\verbatim
{
	"janus" : "success",
	"transaction" : "<same as the request>",
	"sessions" : [
		<session ID #1>,
		<session ID #2>,
		[..]
		<session ID #n>
	]
}
\endverbatim
 *
 * On the other hand, some requests may be targeting a specific session,
 * in which case a \c session_id property must be provided. Specifically,
 * these are the requests that do need a valid session identifier:
 *
 * - \c destroy_session , \c list_handles
 *
 * Using the REST API, this can be done by appending the session identifier
 (e.g., one of the ID returned by a \c list_sessions call) to the API root,
 * but a more generic approach that works for all transports is to just
 * specify a \c session_id property in the request, e.g.:
 *
\verbatim
POST /admin/12345678
{
	"janus" : "list_handles",
	"session_id" : 12345678,
	"transaction" : "<random alphanumeric string>",
	"admin_secret" : "<password specified in janus.jcfg, if any>"
}
\endverbatim
 *
 *
\verbatim
{
	"janus" : "success",
	"transaction" : "<same as the request>",
	"session_id" : 12345678,
	"handles" : [
		<handle ID #1>,
		<handle ID #2>,
		[..]
		<handle ID #n>
	]
}
\endverbatim
 *
 * Finally, some requests need not only a valid session identifier, but
 * a handle identifier as well, as they may address a specific handle
 * that the Janus instance is serving. It is the case for all requests
 * that address a specific handle and/or the related PeerConnection,
 * namely:
 *
 * - \c handle_info , all the pcap-related requests, \c message_plugin ,
 * \c hangup_webrtc and \c detach_handle
 *
 * The following is an example of how a \c handle_info call addressing
 * a specific handle might look like. Since this is a handle-specific
 * request, the correct handle identifier must be
 * referenced, e.g., by appending the ID to the session it belongs to
 * or adding a \c handle_id attribute besides the \c session_id parent:
 *
\verbatim
POST /admin/12345678/98765432
{
	"janus" : "handle_info",
	"session_id" : 12345678,
	"handle_id" : 98765432,
	"transaction" : "<random alphanumeric string>",
	"admin_secret" : "<password specified in janus.jcfg, if any>"
}
\endverbatim
 *
 *
\verbatim
{
	"janus" : "success",
	"transaction" : "<same as the request>",
	"session_id" : 12345678,
	"handle_id" : 98765432,
	"info" : {
		"session_id" : 12345678,
		"session_last_activity": 7927759122,
		"session_transport": "janus.transport.websockets",
		"handle_id" : 98765432,
		"opaque_id": "echotest-YZcsLRCI4uSV",
		"loop-running": true,
		"created": 18695669309,
		"current_time": 18706199704,
		"plugin": "janus.plugin.echotest",
		"plugin_specific": {
			// plugin specific (e.g., EchoTest internals)
		},
		"flags": {
			// flags
		},
		"agent-created": 18696092523,
		"ice-mode": "full",
		"ice-role": "controlled",
		"sdps": {
			"profile": "UDP/TLS/RTP/SAVPF",
			"local": "v=0[..]",
			"remote": "v=0[..]"
		},
		"queued-packets": 0,
		"streams": [
			// WebRTC info, including SSRCs, codecs, ICE and DTLS states, RTCP stats, etc.
		]
	}
}
\endverbatim
 *
 * With respect to the \c handle_info request we used as an example, here,
 * the actual content of the last response is omitted for brevity, but
 * you're welcome to experiment with it in order to check whether more
 * information (of a different nature, maybe) may be useful to have. In
 * particular, you may want to play with the plugin-specific details, as
 * different plugins will return different information according to what
 * they provide: for instance, the VideoRoom plugin might clarify whether
 * a handle is being used for publishing media or for receiving it, and
 * what are the involved IDs, the current status of the delivery, and so on.
 * At the same time, the \c streams object will contain invaluable details
 * related to the WebRTC PeerConnection associated with the handle, as
 * in input/output statistics statistics (bytes, bytes per seconds, NACKs,
 * etc.) or the SDP/ICE/DTLS states. Notice that the information as
 * returned by the Admin API here is just a snapshot: if you're more
 * interested in how this information evolves in a more dynamic way, you
 * may want to start using the Event Handlers instead, which return pretty
 * much the same information, but conveying it as dynamic events pushed
 * to an application you control.
 *
 * \section adminpcap Capturing unencrypted WebRTC traffic
 * As anticipated, you can also enable/disable the dumping of the RTP/RTCP
 * packets a handle is sending and receiving to a pcap or text2pcap file. This is
 * especially useful for debugging reasons, e.g., to check whether or not
 * there are issues in a specific packet Janus is sending or receiving
 * with tools like Wireshark. Notice that this is not supposed to be used
 * for recording Janus streams: while it can be used for that, the
 * janus_recorder utility is much more suited for the task, and is what
 * all plugins make use of when they're interested in \ref recordings .
 *
 * The syntax for the \c start_pcap and \c start_text2pcap commands is
 * trivial, and apart from the command name pretty much the same: all you
 * need to specify are information on the handle to dump, information
 * on the target file (target folder and filename), and whether to truncate
 * packets or not before dumping them:
 *
\verbatim
POST /admin/12345678/98765432
{
	"janus" : "start_pcap",		// Use start_text2pcap for a text file instead
	"folder" : "<folder to save the dump to; optional, current folder if missing>",
	"filename" : "<filename of the dump; optional, random filename if missing>",
	"truncate" : "<number of bytes to truncate packet at; optional, truncate=0 (don't truncate) if missing>",
	"transaction" : "<random alphanumeric string>",
	"admin_secret" : "<password specified in janus.jcfg, if any>"
}
\endverbatim
 *
 * If successful, the full path of the dump file can be obtained by doing
 * a \c handle_info request. A \c stop_pcap or \c start_text2pcap command
 * is even easier to generate, as it doesn't need any parameter:
 *
\verbatim
POST /admin/12345678/98765432
{
	"janus" : "stop_pcap",		// Use stop_text2pcap if you started a text-based capture
	"transaction" : "<random alphanumeric string>",
	"admin_secret" : "<password specified in janus.jcfg, if any>"
}
\endverbatim
 *
 */

/*! \page deploy Deploying Janus
 *
 * When you're going to deploy Janus (e.g., to try the demos we made
 * available out-of-the-box), there's one thing that is important to point
 * out: while Janus does indeed provide an HTTP RESTful interface (documented
 * in \ref rest), it does \b NOT also act as a webserver for static files.
 * This means you'll need a different webserver to host static files, including
 * HTML/PHP/JSP/etc. pages, JavaScript files, images and whatever is part
 * of your web application.
 *
 * That said, deploying Janus is, in principle, quite simple: just start Janus on a
 * machine, put the HTML and JavaScript that will make use of it on a webserver
 * somewhere, make sure the JavaScript code is configured with the right
 * address for the server and you're done!
 *
 * Let's assume, for the sake of simplicity, that your webserver is serving
 * files on port \c 80. By default, Janus binds on the \c 8088 port for HTTP.
 * So, if Janus and the webserver hosting the are co-located, all you need to get your
 * application working is configure the web application to point to the right
 * address for the server. In the demos provided with these packages, this
 * is done by means of the \c server variable:
 *
 \verbatim
var server = "http://" + window.location.hostname + ":8088/janus";
 \endverbatim
 *
 * which basically tells the JavaScript application that the Janus API can be
 * contacted at the same host as the website but at a different port (8088) and path (/janus).
 * In case you configured the server differently, e.g., 7000 as the port
 * for HTTP and /my/custom/path as the API endpoint, the \c server variable
 * could be built this way:
 *
 \verbatim
var server = "http://" + window.location.hostname + ":7000/my/custom/path";
 \endverbatim
 *
 * In case the webserver and Janus are <b>NOT</b> colocated, instead, just
 * replace the \c window.location.hostname part with the right address of
 * the server, e.g.:
 *
 \verbatim
var server = "http://www.example.com:8088/janus";
 \endverbatim
 *
 * It's important to point out, though, that this more "static" approach
 * only works if the webserver is serving files via HTTP. As soon as you
 * start involving \b HTTPS, things start to get more complicated: in fact,
 * for security reasons you cannot contact an HTTP backend if the page is
 * made available via HTTPS. This means that if you're interested in serving
 * your web application via HTTPS, you'll need to enable the HTTPS embedded
 * webserver in Janus as well, and configure the JavaScript code to refer to
 * that itself, e.g.:
 *
 \verbatim
var server = "https://" + window.location.hostname + ":8089/janus";
 \endverbatim
 *
 * assuming \c 8089 is the port you configured Janus to use for HTTPS.
 * To make this more "dynamic", e.g., allow both HTTP and HTTPS instead of
 * just sticking to one, you might make use of something like this:
 *
 \verbatim
var server = null;
if(window.location.protocol === 'http:')
	server = "http://" + window.location.hostname + ":8088/janus";
else
	server = "https://" + window.location.hostname + ":8089/janus";
 \endverbatim
 *
 * that is evaulate the right address to use at runtime.
 *
 * Anyway, there's a much easier way to address these scenarios, which
 * is explained in the next section.
 *
 * \section apache Deploying Janus behind a web frontend
 *
 * To avoid most of the issues explained above, an easy approach can be
 * deploying Janus behind a frontend (e.g., Apache HTTPD, nginx, lighttpd
 * or others) that would act as a reverse proxy for incoming requests.
 * This would allow you to make the Janus API available as a relative path
 * of your web application, rather than a service reachable at a different
 * port and/or domain.
 *
 * Configuring the web application, as a consequence, would be even easier,
 * as all you'd need to do would be to provide a relative path for the API,
 * e.g.:
 *
 \verbatim
var server = "/janus";
 \endverbatim
 *
 * which would automatically work whether the page is served via HTTP or
 * HTTPS. In fact, all the HTTPS requests would be terminated at the webserver,
 * which would then always send simple HTTP messages to the server itself.
 *
 * An easy way to do so in Apache HTTPD is by means of the following directives:
 *
 \verbatim
ProxyRequests Off
ProxyVia Off
ProxyPass /janus http://127.0.0.1:8088/janus retry=0
ProxyPassReverse /janus http://127.0.0.1:8088/janus
 \endverbatim
 *
 * Different versions of HTTPD or different webservers may require a
 * different syntax, but the principle is usually always the same: you instruct
 * the webserver to act as a proxy for a local endpoint, in this case a
 * Janus instance colocated at the webserver and configured with the
 * default settings.
 *
 * A way to do the same with nginx, as explained by some Janus users
 * <a href="https://groups.google.com/forum/#!topic/meetecho-janus/dIv-4s0HOdw">here</a>,
 * is the following directive:
 *
 \verbatim
location /janus {
	proxy_pass http://127.0.0.1:8088/janus;
}
 \endverbatim
 *
 * \section webserver A quick and easy web server
 * While opening WebRTC-powered web applications by just opening the
 * application HTML files from file system works with some browsers, it
 * doesn't in others. Specifically, this works in Firefox but not in Chrome
 * (see <a href="https://github.com/meetecho/janus-gateway/issues/291">issue #291</a>).
 * Anyway, considering that you will eventually want other people besides
 * you to use your Janus services, this means that to test and use Janus
 * you'll want/need to host your applications on a webserver.
 *
 * If you're not interested in configuring a full-fledged webserver, but
 * are only interested in a quick and easy way to test the demos, you can
 * make use of the embedded webservers some frameworks like PHP and Python
 * provide. To start a webserver for the demos, for instance, just open a
 * terminal in the \c html folder of the project, and type:
 *
 *\verbatim
php -S 0.0.0.0:8000
 \endverbatim
 *
 * or:
 *
 *\verbatim
python -m SimpleHTTPServer 8000
 \endverbatim
 *
 * This will setup a webserver on port \c 8000 for you to use, meaning you'll
 * just need to have your browser open a local connection to that port to
 * try the demos:
 *
 *\verbatim
http://yourlocaliphere:8000
 \endverbatim
 *
 * You can do the same on a different port to also access the HTML version of the Doxygen generated
 * documentation, starting the embedded webservers from the \c docs/html
 * folder instead:
 *
 *\verbatim
php -S 0.0.0.0:9000
 \endverbatim
 *
 * or:
 *
 *\verbatim
python -m SimpleHTTPServer 9000
 \endverbatim
 *
 * \section deplyws Using Janus with WebSockets
 *
 * Configuring the use of WebSockets rather than the REST API in the JavaScript
 * library is quite trivial, as it's a matter of passing a \c ws:// address
 * instead of an \c http:// one to the constructor. That said, most of the same
 * considerations provided for the REST API apply here as well, e.g.,
 * to just use \c window.location.hostname if the webserver and Janus are
 * colocated:
 *
 \verbatim
var server = "ws://" + window.location.hostname + ":8188/";
 \endverbatim
 *
 * to specify the port if you change it:
 *
 \verbatim
var server = "ws://" + window.location.hostname + ":7000/";
 \endverbatim
 *
 * and/or the right address of the server in case the webserver and Janus
 * are <b>NOT</b> colocated:
 *
 \verbatim
var server = "ws://www.example.com:8188/";
 \endverbatim
 *
 * Notice how the path (\c /janus by default for HTTP) is not provided
 * for WebSockets, as it is ignored by the server.
 *
 * The considerations for deploying Janus behind a proxy/webserver, though,
 * differ if you use WebSockets, as most webservers don't provide an easy
 * way to proxy WebSocket requests, and usually require custom modifications
 * for the purpose. Recent versions of HTTPD (>= 2.4.5), with the right
 * module (proxy_wstunnel), do allow you to also proxy WebSockets requests the
 * same way you do with HTTP, which can be useful to do the same
 * WSS-to-WS proxying in a frontend. Here's a sample configuration:
 *
 \verbatim
<IfModule mod_proxy_wstunnel.c>
	ProxyPass /janus-ws ws://127.0.0.1:8188 retry=0
	ProxyPassReverse /janus-ws ws://127.0.0.1:8188
</IfModule>
 \endverbatim
 *
 * that will allow you to expose a <code>wss://myserver/janus-ws</code>
 * or <code>ws://myserver/janus-ws</code> address, and have all communication
 * forwarded to and from Janus at <code>ws://127.0.0.1:8188</code>.
 *
 * Similar configurations are probably available for other systems as well,
 * so in case this is something you're interested in, we recommend you
 * follow the best practices related to that made available by the web server developers.
 *
 * \section both Using fallback addresses
 * As anticipated in the \ref JS section, you can also pass an array of servers
 * to the Janus library initialization. This allows you, for instance, to
 * pass a link to both the WebSockets and REST interfaces, and have the
 * library try them both to see which one is reachable, e.g.:
 *
 \verbatim
var ws_server = "ws://" + window.location.hostname + ":8188/";
var http_server = "http://" + window.location.hostname + ":8088/janus";
var servers = [ws_server, http_server];
 \endverbatim
 *
 * which is especially useful if you're not sure whether or not WebSockets
 * will work in some specific networks. Please notice that, for the individual
 * servers listed in the array, the same considerations given above (e.g.,
 * in terms of relative vs. absolute linking) still apply.
 *
 * Such an approach can also be used when you've deployed several different
 * instances of Janus, and you want the library to try some and fallback
 * to others if any of them is not reachable for any reason.
 *
 */

/*! \page service Janus as a daemon/service
 *
 * By default, Janus starts in foreground, and as such works as a server
 * application that you start normally and displays output on the console.
 * That said, there are several reasons why you may not want to keep
 * Janus in the foreground, while still being interested in checking
 * the console to see what's happening.
 *
 * There are different ways to "daemonize" it and have it run as a service,
 * though. This page tries to summarize a few ways to do so, starting
 * from "dumb" approaches like sending to background and/or using screen/tmux,
 * to more sophisticated approaches involving \c systemd, \c upstart
 * and others.
 *
 * \section daemon Running Janus as a daemon
 * Since version \c 0.1.0, you can run Janus as a daemon application. To
 * do so, just pass either \c -b or \c --daemon as a command line
 * argument, and Janus will be daemonized. Just beware, though, that
 * since this results in stdout/stdin/stderr being closed, you MUST
 * specify a log file for Janus to use, either via command line (\c -L
 * or \c --log-file ) or in \c janus.jcfg.
 *
 * \section bg Running in background
 * Another simple way to run Janus in the background is to just append the
 * \c & character to the command line. Anyway, this will still "flood" the console
 * with output from Janus. While there are ways to handle it (e.g., as
 * explained <a href="http://www.thegeekstuff.com/2010/05/unix-background-job/">here</a>),
 * a nice and easy way to handle this is redirecting the output to a
 * separate file, e.g., a dedicated log:
 *
 \verbatim
/opt/janus/bin/janus -d 5 -6 >/path/to/mylogfile 2>&1 &
 \endverbatim
 *
 * This is especially useful in case you want to keep a log of what
 * happened when Janus was running, and can also be used as a simple and
 * effective way to watch the console "live" using \c tail:
 \verbatim
tail -f /path/to/mylogfile
 \endverbatim
 *
 * \section screen Terminal multiplexers
 * Another easy way to run Janus in the background is using terminal
 * multiplexers like \c screen or \c tmux. If you're not familiar with
 * such applications, you can find a quick overview
 * <a href="https://en.wikipedia.org/wiki/Terminal_multiplexer">here</a>.
 *
 * The following is a simple example with \c screen:
 *
 \verbatim
screen -S janus -d -m
screen -r janus -X stuff $'/opt/janus/bin/janus -d 5 -6\n'
 \endverbatim
 *
 * This will create a session called "janus" and launch Janus in it with
 * a few command line options (in this case, just the option to enable
 * IPv6 support and set the debug to verbose). Janus will then be running
 * in the background: accessing the console is just a matter of attaching
 * to the "janus" screen:
 *
 \verbatim
screen -r janus
[CTRL+A+D to detach again]
 \endverbatim
 *
 * Terminal multiplexers usually allow for logging the output to file
 * as well, if you want to keep an history of what happened during the
 * Janus lifetime.
 *
 * \section systemd systemd
 * This section shows how you can add Janus as a service to
 * <a href="https://en.wikipedia.org/wiki/Systemd">systemd</a>.
 *
 \verbatim
[Unit]
Description=Janus WebRTC Server
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=/opt/janus/bin/janus -o
Restart=on-abnormal
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
 \endverbatim
 *
 * \note Remember to adjust the path in ExecStart to match the Janus binary path.
 *
 * \warning Please beware that, per the default \c RateLimitInterval and
 * and \c RateLimitBurst values in the default sytemd configuration, logger
 * messages are dropped if they arrive faster than ~33 per second. You
 * may want to configure them accordingly, or otherwise Janus log messages
 * may be missing. To fix this, setting <code>RateLimitInterval=1s</code>
 * and <code>RateLimitBurst=2000</code> in
 * <code>/etc/systemd/journald.conf</code> is usually enough.
 *
 * \note systemd example provided by
 * <a href="https://github.com/meetecho/janus-gateway/pull/306">\@saghul</a>
 *
 * \section upstart upstart
 * This section shows how you can add Janus as a daemon to
 * <a href="http://upstart.ubuntu.com/">upstart</a>, which is
 * typically available on Ubuntu systems.
 *
 \verbatim
description "janus"

start on filesystem or runlevel [2345]
stop on runlevel [!2345]
limit nofile 50000 50000
limit core unlimited unlimited

respawn
respawn limit 10 5

exec /opt/janus/bin/janus
 \endverbatim
 *
 * \note upstart example provided by
 * <a href="https://github.com/meetecho/janus-gateway/pull/306">\@ploxiln</a>
 *
 * \warning In case starting Janus depends on some external conditions, you
 * may need to modify the \c start and \c stop lines accordingly. Here you can
 * find an <a href="https://github.com/meetecho/janus-gateway/pull/455">example</a>,
 * provided by <a href="https://github.com/meetecho/janus-gateway/pull/455">\@stormbkk87</a>,
 * showing how you can wait, for instance, for RabbitMQ to start before starting Janus too.
 *
 * \section sysvinit sysvinit
 * This section shows how you can add Janus as a daemon to
 * SysVinit based systems.
 *
 \verbatim
#!/bin/sh

### BEGIN INIT INFO
# Provides:          Janus
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Janus WebRTC Server
# Description:       Janus WebRTC Server
### END INIT INFO

DAEMON=/usr/bin/janus
DAEMON_NAME=janus

# Add any command line options for your daemon here
DAEMON_OPTS="-D -o"

# This next line determines what user the script runs as.
# Root generally not recommended but necessary if you are using the Raspberry Pi GPIO from Python.
DAEMON_USER=root

# The process ID of the script when it runs is stored here:
PIDFILE=/var/run/$DAEMON_NAME.pid

. /lib/lsb/init-functions

do_start () {
    log_daemon_msg "Starting system $DAEMON_NAME daemon"
    start-stop-daemon --start --background --no-close --pidfile $PIDFILE --make-pidfile --user $DAEMON_USER --chuid $DAEMON_USER --startas $DAEMON -- $DAEMON_OPTS >> /var/log/$DAEMON_NAME.log 2>&1
    log_end_msg $?
}
do_stop () {
    log_daemon_msg "Stopping system $DAEMON_NAME daemon"
    start-stop-daemon --stop --pidfile $PIDFILE --retry 10
    log_end_msg $?
}

case "$1" in

    start|stop)
        do_${1}
        ;;

    restart|reload|force-reload)
        do_stop
        do_start
        ;;

    status)
        status_of_proc "$DAEMON_NAME" "$DAEMON" && exit 0 || exit $?
        ;;

    *)
        echo "Usage: /etc/init.d/$DAEMON_NAME {start|stop|restart|status}"
        exit 1
        ;;

esac
exit 0
 \endverbatim
 *
 * \note sysvinit example provided by
 * <a href="https://github.com/saghul">\@saghul</a>
 *
 * \section supervisor supervisor
 * This section shows how you can add Janus to
 * <a href="http://supervisord.org/">supervisor</a>, which is
 * typically available on Ubuntu systems.
 *
 \verbatim
[program:janus]
command=/opt/janus/bin/janus
user=root
autostart=true
autorestart=true
stderr_logfile=/var/log/janus.err.log
stdout_logfile=/var/log/janus.out.log
 \endverbatim
 *
 * \note The above configuration file should be added to
 * <code>/etc/supervisor/conf.d/janus.conf</code>. Then the following commands
 * should be run:
 *
 \verbatim
sudo supervisorctl reread
sudo supervisorctl update
 \endverbatim
 *
 * \section Others
 * TODO.
 *
 */

/*! \page debug Debugging Janus
 *
 * In the magical world of fairies and unicorns, the sun always shines
 * and everything always works smoothly and without issues. Unfortunately,
 * this is not the world we live in, and so you might still encounter
 * issues using Janus, e.g., unexpected crashes and the like. We always
 * try and tackle bugs as soon as we spot them, but some issues may be
 * always lingering in the background.
 *
 * Should you encounter a bug or a crash, open a new
 * <a href="https://github.com/meetecho/janus-gateway/issues/new">issue</a>
 * on GitHub. Make sure you carefully read the
 * <a href="https://github.com/meetecho/janus-gateway/blob/master/.github/CONTRIBUTING.md">guidelines</a>
 * for contributing, or otherwise we may decide to close the issue and
 * not even look at it.
 *
 * What's important for us to look into issues and bugs definitely is
 * having enough information to do so. As such, whenever possible try to
 * provide as many details and data as possible. Quite useful to us are
 * GDB stacktraces and/or AddressSanitizer output. The following sections
 * give a quick overview on how you can collect this information after
 * a crash, but for a more detailed description of the tools you should
 * refer to the related documentation pages and tutorials.
 *
 * \section gdb GDB
 * GDB is the <a href="http://www.gnu.org/software/gdb/">GNU Project Debugger</a>
 * and is an effective tool for looking at what has happened (or is
 * happening) inside an application. As such, it's quite useful to spot
 * bugs and the like, as it can provide information about the values of
 * variables when they were used and the application crashed.
 *
 * When Janus crashes, you should get a core dump file somewhere. This is
 * a recorded state of the application memory at the time of crashing, and
 * so a backtrace of what lead to an issue can help. You can open such
 * a core dump file via gdb this way:
 *
 \verbatim
gdb /path/to/bin/janus /path/to/coredump
gdb bt
 \endverbatim
 *
 * The \c bt command retrieves the backtrace, and is what you should provide
 * as part of your new issue.
 *
 * \note Please \c DON'T paste this backtrace in the issue text. Use a
 * service like <a href="https://gist.github.com/">Gist</a> or
 * <a href="http://pastebin.com/">Pastebin</a> and pass the generated
 * link instead.
 *
 * \section sanitizer Address Sanitizer
 * An even better tool for spotting issues is
 * <a href="https://code.google.com/p/address-sanitizer/">Address Sanitizer</a>,
 * a fast memory error detector. Since it can spot memory errors, it's
 * very useful to find out about hidden race conditions and the like.
 *
 * Unlike GDB which can be used as is, though, to use Address Sanitizer
 * you'll first need to recompile Janus with some new settings, as it
 * requires a specific dependency on a library, libasan, which you'll need
 * to install through your repository manager if needed. Besides, you'll
 * need at least gcc 4.8 for this to work: older versions of gcc won't
 * work.
 *
 * Once you've installed libasan, reconfigure Janus like this:
 *
 \verbatim
CFLAGS="-O1 -g3 -ggdb3 -fno-omit-frame-pointer -fsanitize=address -fno-sanitize-recover=all -fsanitize-address-use-after-scope" LDFLAGS="-fsanitize=address" ./configure --prefix=/opt/janus
 \endverbatim
 *
 * Of course you're free to add whatever additional configuration parameter
 * you were using before: the important parts are the environment variables
 * before that. Once done configuring, do a \c make \c clean (to make sure
 * everything is recompiled from scratch) and then a \c make and \c make \c install
 * as usual.
 *
 * At this point, your Janus version should be Address Sanitizer compliant.
 * To make sure, try using \c ldd to check whether libasan is indeed a
 * dependency or not:
 *
 \verbatim
ldd janus | grep asan
 \endverbatim
 *
 * If it is, you're done: whenever Janus crashes for any reason, you'll
 * get additional output from Address Sanitizer automatically with details
 * on what went wrong, and that's what you should provide as part of the
 * issue content. Just as a side note, please beware that using Address
 * Sanitizer Janus will run just a bit slower, even though not to the
 * point of being unusable (as when using, e.g., valgrind).
 *
 * \note Please \c DON'T paste Address Sanitizer output in the issue text.
 * Use a service like <a href="https://gist.github.com/">Gist</a> or
 * <a href="http://pastebin.com/">Pastebin</a> and pass the generated
 * link instead.
 *
 */

/*! \page pluginslist Plugins documentation
 * Out of the box, Janus comes with a set of different and heterogeneous
 * media manipulation plugins. These can be used individually or composed
 * together at an application level for building complex WebRTC-based
 * media applications.
 *
 * The list of plugins currently available is the following. Since new
 * plugins may become available available in the future, make sure you
 * come back to this page for more information.
 *
 * - \ref echotest
 * - \ref streaming
 * - \ref videocall
 * - \ref sip
 * - \ref nosip
 * - \ref audiobridge
 * - \ref videoroom
 * - \ref textroom
 * - \ref recordplay
 * - \ref voicemail
 * - \ref lua
 * - \ref duktape
 */

/*! \page eventhandlers Event handlers documentation
 * Controlling and monitoring a Janus instance can be done using the
 * \ref admin which includes ways to query information related to the
 * state of ongoing PeerConnections (ICE/DTLS state, stats, etc.).
 * That said, while powerful and useful the Admin API is a poll-based
 * protocol: this means that you have to query for information yourself,
 * and if you want to keep up-to-date with what is happening, you have
 * to do that on a regular basis. As such, things can get problematic
 * when dealing with many sessions and handles running in your application,
 * as you may not be immediately aware of which session/handle corresponds
 * to what, or which of them belong to the same scenario (e.g., all
 * PeerConnections established in the context of the same VideoRoom).
 *
 * This is where Event Handlers can help. Just like media and transport
 * plugins, Event Handlers plugins in Janus themselves, meaning their
 * modular nature allows for extensibility. When enabling Event handlers,
 * Janus and other plugins generate real-time events related to several
 * different aspects that may be happening during its lifetime: these
 * events are then passed to all the available event handler plugins,
 * plugins that can then decide to do with these events whatever they want.
 * They might choose to store these events somehow, aggregate, dump or
 * process them, format and send them to an external application, and so
 * on. This really depends on what these events should be used for.
 *
 * Janus will generate events related to:
 * - session related events (e.g., session created/destroyed, etc.);
 * - handle related events (e.g., handle attached/detached, etc.);
 * - JSEP related events (e.g., got/sent offer/answer);
 * - WebRTC related events (e.g., PeerConnection up/down, ICE updates, DTLS updates, etc.);
 * - media related events (e.g., media started/stopped flowing, stats on packets/bytes, etc.);
 * - generic events originated by the Janus core (e.g., Janus started/stopped);
 * - events originated by plugins (content specific plugins themselves);
 * - events originated by transports (see above);
 * - events originated by external applications via the Admin API (content specific to source).
 *
 * \section evhsyntax Events format
 * All events generated by Janus are JSON object, which have a shared
 * header and a custom body that will depend on the type (and in some
 * cases subtype) of the event itself.
 *
 * The header of the event will contain some information that is usually
 * common to all events: this includes \c type and (when needed) \c subtype
 * of the event, a timestamp in microseconds (so that you can know exactly
 * when the event was generated in the first place from the server's perspective,
 * no matter it was received), and various IDs. These IDs include the
 * session identifier (Janus session the event refers to), the handle
 * identifier (Janus handle the event refers to) and an opaque ID (set
 * by whoever controls the Janus API): as we'll see, all these IDs are
 * optional, as there are events that are not related to a session in
 * particular (e.g., a server shutdown event), but can be very important
 * for correlation purposes when they're used.
 *
 * The generic format of events is the following:
\verbatim
    {
        "emitter" : "<string identifying the source of the event, if configured (optional)>",
        "type" : <numeric event type identifier>,
        "subtype" : <numeric event subtype identifier (specific to the event type; optional)>,
        "timestamp" : <time of when the event was generated>,
        "session_id" : <unique session identifier, if provided/available (optional)>,
        "handle_id" : <unique handle identifier, if provided/available (optional)>,
        "opaque_id" : "<user-provided opaque identifier, if provided/available (optional)>",
        "event" : {
             <event body, custom depending on event type>
        }
    }
\endverbatim
 *
 * For instance, this is what an event related to a new session being created
 * would look like:
 *
\verbatim
    {
        "emitter": "MyJanusInstance",
        "type": 1,
        "timestamp": 1582211094846980,
        "session_id": 3439056127855429,
        "event": {
            "name": "created",
            "transport": {
                "transport": "janus.transport.http",
                "id": "0x60400002c2d0"
            }
        }
    }
\endverbatim
 *
 * Since \c type \c 1 is related to session events, this event basically
 * tells us that a new session with ID \c 3439056127855429 was created
 * (we know this from the \c name property in the event body) on the Janus
 * instance called \c MyJanusInstance at the timestamp \c 1582211094846980 .
 * There are no \c subtype , \c handle_id or \c opaque_id properties as
 * they were unneeded or not applicable here.
 *
 * \section evhtypes Event types
 * As we've seen from the previous example, event types are numeric. In
 * order to figure out what you're receiving, you can refer to the
 * following table as a reference:
 *
 * <table class="table table-striped">
 * <tr><th>Type</th><th>Category of event</th></tr>
 * <tr><td>1</td><td>Session related event</td></tr>
 * <tr><td>2</td><td>Handle related event</td></tr>
 * <tr><td>4</td><td>External event (injected via Admin API)</td></tr>
 * <tr><td>8</td><td>JSEP event (SDP offer/answer)</td></tr>
 * <tr><td>16</td><td>WebRTC state event (ICE/DTLS states, candidates, etc.)</td></tr>
 * <tr><td>32</td><td>Media event (media state, reports, etc.)</td></tr>
 * <tr><td>64</td><td>Plugin-originated event (e.g., event coming from VideoRoom)</td></tr>
 * <tr><td>128</td><td>Transport-originated event (e.g., WebSocket connection state)</td></tr>
 * <tr><td>256</td><td>Core event (server startup/shutdown)</td></tr>
 * </table>
 *
 * The types of events are not monotonically increasing as, internally,
 * they're represented as a mask: this allows event handler plugins to
 * only subscribe to a subset of them, rather than them all, when needed.
 *
 * The event \c type property dictates the syntax of the \c event body ,
 * meaning that the body for a JSEP event (type \c 8 ) will for instance
 * be very different from a media event (type \c 32 ). That said, the
 * format of some events can change even within the same type: for instance,
 * a WebRTC state event includes a lot of different notifications, including
 * ICE states, DTLS states, local and remote candidates, selected pair, etc.
 * In order to allow event handler recipients written in strongly typed
 * languages to be able to use different classes for the different events,
 * a different property called \c subtype can help further discriminate
 * an event of a specified \c type. At the time of writing, a \c subtype
 * attribute will only be present if the event is of type \c 256 (core),
 * \c 16 (WebRTC) and \c 32 (media): all other event types have a consistent
 * format, and so don't need this differentiation (e.g., type \c 8 includes
 * both SDP offers and answers, but the nature of the SDP is indicated
 * in an attribute that has the same name in both cases).
 *
 * The available subtypes are the following:
 *
 * <table class="table table-striped">
 * <tr><th colspan=2>Core subtype</th></tr>
 * <tr><td>1</td><td>Server startup</td></tr>
 * <tr><td>2</td><td>Server shutdown</td></tr>
 * <tr><th colspan=2>WebRTC subtype</th></tr>
 * <tr><td>1</td><td>ICE state</td></tr>
 * <tr><td>2</td><td>Local candidate</td></tr>
 * <tr><td>3</td><td>Remote candidate</td></tr>
 * <tr><td>4</td><td>Selected pair</td></tr>
 * <tr><td>5</td><td>DTLS state</td></tr>
 * <tr><td>6</td><td>PeerConnection state</td></tr>
 * <tr><th colspan=2>Media subtype</th></tr>
 * <tr><td>1</td><td>Medium state</td></tr>
 * <tr><td>2</td><td>Slow link</td></tr>
 * <tr><td>3</td><td>Report/stats</td></tr>
 * </table>
 *
 */

/*! \page recordings Recordings
 * Janus supports recordings of WebRTC sessions out of the box, assuming
 * plugins take advantage of the feature. Specifically, recording as a
 * functionality is implemented in the Janus core, specifically using the
 * janus_recorder structure and the related methods. When enabled, media
 * streams are recorded to a custom format (that we introduce below):
 * as such, it's then up to individual plugins to expose ways for users
 * to configure/start/stop recordings, and using the core functionality
 * to actually implementing the recording part. At the time of writing,
 * most plugins do implement it.
 *
 * \note This section covers recordings for the purpose of storage,
 * archiving or further manipulation. If you're interested in recording
 * for the purpose of debugging media sessions, you may want to refer to
 * the \ref adminpcap documentation instead, as that would allow you
 * to capture unencrypted RTP/RTCP packets sent/received to/from Janus
 * in a format tools like Wireshark and tcpdump support.
 *
 * \section mjr Meetecho Janus Recordings
 * As anticipated, the janus_recorder core functionality saves media
 * streams to a custom format that we call the "Meetecho Janus Recordings"
 * format. When saved to file, the custom \c mjr extension is used.
 *
 * Each \c mjr file contains a single media stream. This means that if
 * if you want to record, for instance, an audio/video stream, you'll need
 * two separate \c mjr files: one just for audio, and the other just for
 * video. Each \c mjr file then basically just contains a structured
 * dump of the RTP packets exactly as they arrived: after a short header
 * that describes the data contained in the recording (i.e., type of
 * media, the codec, when it was created, when the first packet was written),
 * each RTP packet is saved together with info on its length. A partial
 * timestamp of when the packet was received is also stored, as this
 * allows for more realistic conversions to \c pcap format when needed.
 *
 *\verbatim
+-----------------------------------------------+
|               MJR00002 (8 bytes)              |
+-----------------------------------------------+
| LEN (2 bytes) | JSON header (variable length) |
+-----------------------------------------------+
|    MEET (4 bytes)     |  Recvd Time (4 bytes) |
+-----------------------------------------------+
| LEN (2 bytes) | RTP packet (variable length)  |
+-----------------------------------------------+
|    MEET (4 bytes)     |  Recvd Time (4 bytes) |
+-----------------------------------------------+
| LEN (2 bytes) | RTP packet (variable length)  |
+-----------------------------------------------+
|    MEET (4 bytes)     |  Recvd Time (4 bytes) |
+-----------------------------------------------+
| LEN (2 bytes) | RTP packet (variable length)  |
+-----------------------------------------------+
|                     ...                       |
+-----------------------------------------------+
 \endverbatim
 *
 * This makes the recording process very lightweight, as Janus doesn't
 * need to do anything more that just saving the packets to file: no
 * CPU intensive operation like transcoding or frame manipulation is
 * done by the janus_recorder instances. RTP packets don't even need to
 * be saved in order, as the \c mjr files can be post-processed later
 * and, as we'll see, re-ordering of the stored packets is part of the
 * activities that our post-processor performs when doing so.
 *
 * \subsection mjrdata Saving data channels
 * While we've so far only mentioned RTP packets, and so audio and video,
 * Janus actually also natively supports the recording of datachannels.
 * In that case, the recording will be a structured dump not of RTP
 * packets, but of the individual messages that were received. Just as
 * we said for audio and video, since \c mjr files only cover individual
 * streams, data recordings will need their own instance as well.
 *
 * \section mjrproc Post-processing the recordings
 * Once a recording is available in the \c mjr format, it obviously needs
 * some transformation before it can be consumed by external tools, e.g.,
 * media players or third-party applications for further processing (like
 * muxing audio and video together, or mixing multiple video streams
 * together).

 * Out of the box, Janus comes with a simple post-processing tool whose
 * only job is re-ordering the available RTP packets, extracting the
 * media frames from the RTP packets (which for video might mean
 * extracting the same frame from multiple packets in sequence), and
 * saving the media frames to a well-known media format. To make this
 * simple, this tool can, for instance, convert an audio \c mjr recording
 * to an \c opus file, or a video \c mjr recording containing VP8 packets
 * to a \c webm file instead. Notice that no transcoding is done by this
 * postprocessor either: frames are extracted exactly as they were sent
 * originally, and just saved to a media container in a way that multimedia
 * applications can consume them. If further processing is needed (e.g.,
 * muxing, mixing, transcoding, or other), then this is up to third-party
 * applications that can work with existing media files.
 *
 * For more information on the Janus recordings post-processor, check
 * the documentation for the janus-pp-rec.c executable.
 *
 */

/*! \page resources Resources
 * This page contains pointers to some third-party resources, in particular
 * distro repos for an easier installation of Janus, where available,
 * applications, mobile/docker/Pi stuff, orchestration tools, client stacks,
 * libraries and bindings in other languages (that is tools that you find
 * helpful to interact with Janus outside of the context of the \c janus.js
 * JavaScript library we provide) and so on. It is not a complete list,
 * but just a summary of the material that has been shared so far on the
 * <a href="https://groups.google.com/forum/#!forum/meetecho-janus">meetecho-janus</a>
 * Google group.
 *
 * If you've developed anything related to Janus and you're willing to share
 * it with the community, or you know any such effort that is not listed
 * here, just let us know and we'll add it on this page.
 * <br/><br/>
 *
 * - <a href="#repos">Distro repositories</a>\n
 * - <a href="#stacks">Client-side stacks</a>\n
 * - <a href="#mobile">Mobile resources</a>\n
 * - <a href="#pi">Raspberry Pi resources</a>\n
 * - <a href="#docker">Docker resources</a>\n
 * - <a href="#config">Configuration management</a>\n
 * - <a href="#thirdplugins">Third-party plugins</a>\n
 * - <a href="#thirdtransports">Third-party transports</a>\n
 * - <a href="#evhandlers">Event handlers (monitoring/troubleshooting)</a>\n
 * - <a href="#orchestration">Orchestration</a>\n
 * - <a href="#applications">Complete applications</a>\n
 *
 * <hr/>
 *
 * \section repos Distro repositories
 *
 * <table class="table table-striped">
 * <tr><th>Distro</th><th>Author</th><th>Repo</th><th>Description</th></tr>
 * <tr>
 * 		<td>Debian</td>
 * 		<td>Debian VoIP Team</td>
 * 		<td><a href="https://packages.debian.org/source/sid/janus">Janus packages (sid)</a></td>
 *		<td>Debian Sid</td>
 * </tr>
 * <tr>
 * 		<td>Debian/Ubuntu</td>
 * 		<td><a href="https://github.com/saghul">Saúl Ibarra Corretgé</a></td>
 * 		<td><a href="http://projects.ag-projects.com/projects/documentation/wiki/Repositories">AG Projects Repo</a></td>
 *		<td>Debian Jessie, Ubuntu Trusty and Ubuntu Xenial</td>
 * </tr>
 * <tr>
 * 		<td>Snap</td>
 * 		<td><a href="https://github.com/RSATom">Sergey Radionov</a></td>
 * 		<td><a href="https://github.com/RSATom/janus-gateway-snap">janus-gateway-snap</a></td>
 *		<td>Helper repo for build Janus WebRTC Server on build.snapcraft.io</td>
 * </tr>
 * <tr>
 * 		<td>openSUSE/SUSE</td>
 * 		<td><a href="https://github.com/ancorgs">Ancor Gonzalez Sosa</a></td>
 * 		<td><a href="https://build.opensuse.org/project/show/network:jangouts">Janus packages</a></td>
 *		<td>Repositories for several versions of SUSE and openSUSE</td>
 * </tr>
 * </table>
 * <br/>
 *
 * \section stacks Client-side stacks
 *
 * <table class="table table-striped">
 * <tr><th>Language</th><th>Author</th><th>Project</th><th>Description</th></tr>
 * <tr>
 * 		<td>JavaScript/node</td>
 * 		<td><a href="https://github.com/meetecho">Meetecho</a></td>
 * 		<td><a href="https://github.com/meetecho/janode">janode</a></td>
 *		<td>A Node.js adapter for the Janus WebRTC server</td>
 * </tr>
  * <tr>
 * 		<td>TypeScript/node</td>
 * 		<td><a href="https://github.com/smyrgeorge">smyrgeorge</a></td>
 * 		<td><a href="https://github.com/smyrgeorge/janus-gateway-tsdx">/janus-gateway-tsdx</a></td>
 *		<td>Modern typescript client for janus gateway. Based on websockets</td>
 * </tr>
 * <tr>
 * 		<td>JavaScript/node</td>
 * 		<td><a href="https://github.com/ndarilek">Nolan Darilek</a></td>
 * 		<td><a href="https://github.com/ndarilek/node-janus">node-janus</a></td>
 *		<td>node and browserify compatible integration layer for the Janus WebRTC server</td>
 * </tr>
 * <tr>
 * 		<td>JavaScript/node</td>
 * 		<td><a href="https://github.com/DamonOehlman">Damon Oehlman</a></td>
 * 		<td><a href="https://github.com/rtc-io/rtc-janus">rtc-janus</a></td>
 *		<td>node and browserify compatible integration layer for the Janus WebRTC server:
 * experimental and incomplete as per the author words, but a good starting point</td>
 * </tr>
 * <tr>
 * 		<td>JavaScript/node</td>
 * 		<td><a href="https://github.com/sjkummer">Sebastian Schmid</a></td>
 * 		<td><a href="https://github.com/sjkummer/janus-gateway-js">janus-gateway-js</a></td>
 * 		<td>Simple JavaScript client for janus-gateway that runs in the browser as well as in Node.js</td>
 * </tr>
 * <tr>
 * 		<td>JavaScript/node</td>
 * 		<td><a href="https://www.sipwise.com/">sip:wise</a></td>
 * 		<td><a href="https://www.npmjs.com/~sipwise">admin/videoroom client</a></td>
 * 		<td>Node.js clients that implement the Admin API and VideoRoom functionality</td>
 * </tr>
 * <tr>
 * 		<td>JavaScript/node</td>
 * 		<td><a href="https://github.com/mquander">Marshall Quander</a></td>
 * 		<td><a href="https://github.com/mquander/minijanus.js">minijanus.js</a></td>
 * 		<td>A super-simplistic and -minimal wrapper for talking to the Janus signalling API</td>
 * </tr>
 * <tr>
 * 		<td>JavaScript/node</td>
 * 		<td><a href="https://github.com/TechTeamer">TechTeamer</a></td>
 * 		<td><a href="https://github.com/TechTeamer/janus-api">janus-api</a></td>
 * 		<td>Javascript (node and browser side) API for Janus WebRTC server</td>
 * </tr>
 * <tr>
 * 		<td>JavaScript/node</td>
 * 		<td><a href="https://github.com/uwejan">Saddam Uwejan</a></td>
 * 		<td><a href="https://github.com/uwejan/janus-api-mqtt">janus-api-mqtt</a></td>
 * 		<td>Javascript (node and browser side) API for Janus WebRTC Gateway, Using MQTT</td>
 * </tr>
 * <tr>
 * 		<td>JavaScript/Angular</td>
 * 		<td><a href="https://github.com/kevin29a">Kevin Thompson</a></td>
 * 		<td><a href="https://kevin29a.github.io/angular-janus">janus-angular</a></td>
 * 		<td>Angular Component for implementing a videoroom</td>
 * </tr>
 * <tr>
 * 		<td>ruby</td>
 * 		<td><a href="https://github.com/cargomedia">Cargo Media</a></td>
 * 		<td><a href="https://github.com/cargomedia/janus-gateway-ruby">janus-gateway-ruby</a></td>
 * 		<td>ruby client side API wrapper for the Janus API (websocket only at the moment)</td>
 * </tr>
 * <tr>
 * 		<td>C#/.NET</td>
 * 		<td><a href="https://github.com/Computician">Benjamin Trent</a></td>
 * 		<td><a href="https://github.com/Computician/JanusSharp">JanusSharp</a></td>
 * 		<td>C#/.Net client side API wrapper for the Janus API</td>
 * </tr>
 * <tr>
 * 		<td>PHP</td>
 * 		<td><a href="https://github.com/BenJaziaSadok">Mohamed Sadok Ben Jazia</a></td>
 * 		<td><a href="https://github.com/BenJaziaSadok/janus-gateway-php">janus-gateway-php</a></td>
 * 		<td>Client-side PHP/javascript implementation of the Janus and Admin APIs</td>
 * </tr>
 * <tr>
 * 		<td>PHP</td>
 * 		<td><a href="https://github.com/mvnrsa">Marnus van Niekerk</a></td>
 * 		<td><a href="https://github.com/mvnrsa/JanusPHPclass">Janus PHP Class</a></td>
 * 		<td>Client-side PHP Class implementing the Janus Admin API</td>
 * </tr>
 * <tr>
 * 		<td>Golang</td>
 * 		<td><a href="https://github.com/nowylie">Nicholas Wylie</a></td>
 * 		<td><a href="https://github.com/nowylie/go-janus">go-janus</a></td>
 * 		<td>Golang library to the Janus API (Unix Sockets/SOCK_DGRAM only at the moment)</td>
 * </tr>
 * <tr>
 * 		<td>Elixir</td>
 * 		<td><a href="https://github.com/ndarilek">Nolan Darilek</a></td>
 * 		<td><a href="https://github.com/ndarilek/elixir-janus">elixir-janus</a></td>
 *		<td>Elixir client side API wrapper for the Janus WebRTC server</td>
 * </tr>
 * <tr>
 * 		<td>OBS</td>
 * 		<td><a href="https://github.com/CoSMoSoftware">CoSMo Software</a></td>
 * 		<td><a href="https://github.com/CoSMoSoftware/OBS-studio-webrtc">OBS-studio-webrtc</a></td>
 *		<td>This is a fork of obs-studio with support for webrtc in general, and Janus Video Room plugin in particular</td>
 * </tr>
 * <tr>
 * 		<td>OCaml</td>
 * 		<td><a href="https://github.com/monstasat">Alexander Yanin</a></td>
 * 		<td><a href="https://github.com/monstasat/janus-ocaml">Janus-ocaml</a></td>
 *		<td>Library for Janus WebRTC server handling written in OCaml (HTTP only)</td>
 * </tr>
 * <tr>
 * 		<td>Haskell</td>
 * 		<td><a href="https://github.com/oofp">oofp</a></td>
 * 		<td><a href="https://github.com/oofp/janus-connector">janus-connector</a></td>
 *		<td>Haskell binding of Janus client protocol using WebSocket transport with examples</td>
 * </tr>
 * </table>
 * <br/>
 *
 * \section mobile Mobile resources
 *
 * <table class="table table-striped">
 * <tr><th>OS</th><th>Author</th><th>Project</th><th>Description</th></tr>
 * <tr>
 * 		<td>Android/iOS</td>
 * 		<td><a href="https://github.com/meetecho">Meetecho</a></td>
 * 		<td><a href="https://github.com/meetecho/janus-mobile-sdk">janus-mobile-sdk</a></td>
 *		<td>Janus Client SDK [ABANDONED PROJECT]</td>
 * </tr>
 * <tr>
 * 		<td>Android</td>
 * 		<td><a href="https://github.com/Computician">Benjamin Trent</a></td>
 * 		<td><a href="https://github.com/Computician/janus-gateway-android">janus-gateway-android</a></td>
 *		<td>API wrapper that utilizes the native WebRTC build and is made to ease communication with Janus</td>
 * </tr>
 * <tr>
 * 		<td>iOS</td>
 * 		<td><a href="https://github.com/davibe">Davide Bertola</a></td>
 * 		<td><a href="https://github.com/davibe/cordova-webrtc-janus-gateway">cordova-webrtc-janus-gateway</a></td>
 * 		<td>cordova application that interfaces with Janus and is based on the PhoneRTC cordova plugin</td>
 * </tr>
 * <tr>
 * 		<td>Android/iOS</td>
 * 		<td><a href="https://github.com/atyenoria">Akinori Nakajima</a></td>
 * 		<td><a href="https://github.com/atyenoria/react-native-webrtc-janus-gateway">react-native-webrtc-janus-gateway</a></td>
 * 		<td>Video conference system for mobile application on react-native-webrtc + Janus WebRTC server</td>
 * </tr>
 * <tr>
 * 		<td>Android/iOS</td>
 * 		<td><a href="https://github.com/WorldViews">WorldViews</a></td>
 * 		<td><a href="https://github.com/WorldViews/JanusMobile">JanusMobile</a></td>
 * 		<td>react-native based Janus mobile client</td>
 * </tr>
 * </table>
 * <br/>
 *
 * \section pi Raspberry Pi resources
 *
 * <table class="table table-striped">
 * <tr><th>Author</th><th>Project</th><th>Description</th></tr>
 * <tr>
 * 		<td><a href="http://linux-projects.org">Linux Projects</a></td>
 * 		<td><a href="http://www.linux-projects.org/rpi-videoconference-demo-os/">Rpi VideoConference OS</a></td>
 *		<td>Ready-to-use OS for video conferences over the web from a Raspberry Pi</td>
 * </tr>
 * <tr>
 * 		<td><a href="http://linux-projects.org">Linux Projects</a></td>
 * 		<td><a href="http://www.linux-projects.org/uv4l/tutorials/janus-gateway/">UV4L, User Space Video Collection</a></td>
 * 		<td>Software modules providing solutions for encrypted live data, audio and video streaming, mirroring, conferencing</td>
 * </tr>
 * </table>
 * <br/>
 *
 * \section docker Docker resources
 *
 * <table class="table table-striped">
 * <tr><th>Author</th><th>Project</th><th>Description</th></tr>
 * <tr>
 * 		<td><a href="https://github.com/krull">Brendan Jocson</a></td>
 * 		<td><a href="https://github.com/krull/docker-janus">docker-janus</a></td>
 *		<td>Debian 8 based docker image for Meetecho's Janus Gateway</td>
 * </tr>
 * <tr>
 * 		<td><a href="https://github.com/atyenoria">Akinori Nakajima</a></td>
 * 		<td><a href="https://github.com/atyenoria/janus-gateway-docker">janus-gateway-docker</a></td>
 *		<td>Janus WebRTC server Docker Image for Media Streaming Expert User</td>
 * </tr>
 * <tr>
 * 		<td><a href="https://github.com/canyanio">Canyan.io</a></td>
 * 		<td><a href="https://github.com/canyanio/janus-gateway-docker">janus-gateway-docker</a></td>
 *		<td>Docker image for the Janus WebRTC Server</td>
 * </tr>
 * <tr>
 * 		<td><a href="https://github.com/bartbalaz">Bartosz Balazinski</a></td>
 * 		<td><a href="https://github.com/bartbalaz/janus-container">janus-container</a></td>
 *		<td>Janus container</td>
 * </tr>
 * </table>
 * <br/>
 *
 * \section config Configuration management
 *
 * <table class="table table-striped">
 * <tr><th>Author</th><th>Project</th><th>Description</th></tr>
 * <tr>
 * 		<td><a href="https://github.com/bitsy-ai">Leigh Johnson</a></td>
 * 		<td><a href="https://galaxy.ansible.com/bitsyai/janus_gateway">ansible-role-janus-gateway</a></td>
 *		<td>Ansible role to build and deploy Janus</td>
 * </tr>
 * </table>
 * <br/>
 *
 * \section thirdplugins Third-party plugins
 *
 * <table class="table table-striped">
 * <tr><th>Author</th><th>Project</th><th>Description</th></tr>
 * <tr>
 * 		<td><a href="https://github.com/cargomedia">Cargo Media</a></td>
 * 		<td><a href="https://github.com/cargomedia/janus-gateway-rtpbroadcast">janus-gateway-rtpbroadcast</a></td>
 * 		<td>Janus-gateway plugin to broadcast RTP video</td>
 * </tr>
 * <tr>
 * 		<td><a href="https://github.com/mquander">Marshall Quander</a></td>
 * 		<td><a href="https://github.com/mquander/janus-plugin-rs">janus-plugin-rs</a></td>
 * 		<td>Rust bindings and wrappers for creating Janus plugins in Rust</td>
 * </tr>
 * </table>
 * <br/>
 *
 * \section thirdtransports Third-party transports
 *
 * <table class="table table-striped">
 * <tr><th>Author</th><th>Project</th><th>Description</th></tr>
 * <tr>
 * 		<td><a href="https://github.com/nowylie">Nicholas Wylie</a></td>
 * 		<td><a href="https://github.com/nowylie/janus-ud-transport">janus-ud-transport</a></td>
 * 		<td>Janus transport plugin that adds support for Datagram messages over Unix Domain Sockets</td>
 * </tr>
 * </table>
 * <br/>
 *
 * \section evhandlers Event handlers (monitoring/troubleshooting)
 *
 * <table class="table table-striped">
 * <tr><th>Language</th><th>Author</th><th>Project</th><th>Description</th></tr>
 * <tr>
 * 		<td>node-js</td>
 * 		<td><a href="https://github.com/thehunmonkgroup">Chad Phillips</a></td>
 * 		<td><a href="https://github.com/thehunmonkgroup/janus-event-server">janus-event-server</a></td>
 * 		<td>Simple plugin-based server to receive/process events from Janus</td>
 * </tr>
 * <tr>
 * 		<td>Rust</td>
 * 		<td><a href="https://github.com/mozilla">Mozilla</a></td>
 * 		<td><a href="https://github.com/mozilla/janus-eventhandler-sqlite">janus-eventhandler-sqlite</a></td>
 * 		<td>A Janus event handler plugin that writes events to a SQLite database</td>
 * </tr>
 * </table>
 * <br/>
 *
 * \section orchestration Orchestration
 *
 * <table class="table table-striped">
 * <tr><th>Author</th><th>Project</th><th>Description</th></tr>
 * <tr>
 * 		<td><a href="https://github.com/OpenSight">OpenSight</a></td>
 * 		<td><a href="https://github.com/OpenSight/janus-cloud">janus-cloud</a></td>
 * 		<td>An API proxy for Janus WebRTC server cluster</td>
 * </tr>
 * </table>
 * <br/>
 *
 * \section applications Complete applications
 *
 * <table class="table table-striped">
 * <tr><th>Author</th><th>Project</th><th>Description</th></tr>
 * <tr>
 * 		<td><a href="https://github.com/jangouts">jangouts</a></td>
 * 		<td><a href="https://github.com/jangouts/jangouts">jangouts</a></td>
 * 		<td>Videoconferencing based on WebRTC and Janus Gateway with an UI inspired by Google Hangouts</td>
 * </tr>
 * <tr>
 * 		<td><a href="https://github.com/gjovanov">Goran Jovanov</a></td>
 * 		<td><a href="https://github.com/gjovanov/roomler">roomler</a></td>
 * 		<td>Roomler - Video collaboration tool using WebRTC (Janus Gateway)</td>
 * </tr>
 * </table>
 * <br/>
 *
 */

/*! \page ide Writing code for Janus
 *
 * Janus is open source, which means the whole source code is available for
 * both its core internals and all plugins. As such, it's easy to write code
 * to fix issues, add new features, implement new modules and so on.
 *
 * You don't really need any integrated development environment (IDE) to
 * write code for Janus, but in case you do want to make use of one, you
 * may need to tweak your development environment accordingly. The Janus
 * codebase makes use of many macros defined at <code>configure</code> time
 * to figure out what's available and what should be compiled, for instance,
 * and the IDE you're using may need to be aware of those to do its job.
 *
 * The following snippet is an example of how you can configure, for instance,
 * Visual Studio Code on Ubuntu 20.04:
 *
\verbatim
{
    "configurations": [
        {
            "name": "Linux",
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "gnu17",
            "includePath": [
                "${workspaceFolder}/**",
                "/usr/lib/x86_64-linux-gnu/glib-2.0/include",
                "/usr/include/**"
            ],
            "intelliSenseMode": "linux-gcc-x64",
            "defines": [
                "CONFDIR=\"\"",
                "EVENTDIR=\"\"",
                "HAVE_CLOSE_ASYNC=1",
                "HAS_DTLS_WINDOW_SIZE=1",
                "HAVE_ICE_NOMINATION=1",
                "HAVE_LIBCURL=1",
                "HAVE_LIBNICE_TCP=1",
                "HAVE_LIBOGG=1",
                "HAVE_LIBOPUS=1",
                "HAVE_LIBWEBSOCKETS_PEER_SIMPLE=1",
                "HAVE_PORTRANGE=1",
                "HAVE_SCTP=1",
                "HAVE_SRTP_2=1",
                "LOGGERDIR=\"\"",
                "PLUGINDIR=\"\"",
                "TRANSPORTDIR=\"\""
            ]
        }
    ],
    "version": 4
}
\endverbatim
 *
 */

/*! \page README README
 *  \verbinclude README.md
 */

/*! \page CREDITS Credits
 *
 * Janus WebRTC Server © 2014-2023 <a href="https://www.meetecho.com/">Meetecho</a> (https://www.meetecho.com/)
 *
 * \b Author:
 *         Lorenzo Miniero <lorenzo@meetecho.com>
 *
 * Several open source components have been used to implement this software:
 *
 * - \b GLib: http://library.gnome.org/devel/glib/
 * - \b pkg-config: http://www.freedesktop.org/wiki/Software/pkg-config/
 * - \b Jansson: http://www.digip.org/jansson/ (JSON)
 * - \b libconfig: https://hyperrealm.github.io/libconfig/ (configuration files)
 * - \b libnice: https://libnice.freedesktop.org/ (ICE/STUN/TURN, at least v0.1.16 suggested, v0.1.18 recommended)
 * - \b OpenSSL: http://www.openssl.org/ (DTLS, at least v1.0.1e)
 * - \b libsrtp: https://github.com/cisco/libsrtp (SRTP, at least v2.x suggested)
 * - \b usrsctp: https://github.com/sctplab/usrsctp (\c optional, Data Channels)
 * - \b libmicrohttpd: http://www.gnu.org/software/libmicrohttpd/ (\c optional, Web server, at least v0.9.59)
 * - \b libwebsockets: https://libwebsockets.org/ (\c optional, WebSockets)
 * - \b rabbitmq-c: https://github.com/alanxz/rabbitmq-c (\c optional, v1.0.4, RabbitMQ)
 * - \b paho.mqtt.c: https://eclipse.org/paho/clients/c (\c optional, v1.1.0 for MQTT v3.1 & v3.1.1 or v1.3.0 for MQTT v5)
 * - \b nanomsg: https://nanomsg.org/ (\c optional, Nanomsg)
 * - \b Sofia-SIP: https://github.com/freeswitch/sofia-sip (\c optional, only needed for the SIP plugin)
 * - \b libopus: http://opus-codec.org/ (\c optional, only needed for the bridge plugin)
 * - \b libogg: http://xiph.org/ogg/ (\c optional, only needed for the voicemail plugin)
 * - \b libcurl: https://curl.haxx.se/libcurl/ (\c optional, only needed for the TURN REST API,
 * RTSP support in the Streaming plugin and the sample Event Handler plugin)
 * - \b zlib: https://zlib.net/ (gzip compression utility)
 * - \b Lua: https://www.lua.org/download.html (\c optional, only needed for the Lua plugin)
 * - \b Duktape: https://duktape.org/ (\c optional, only needed for the Duktape plugin)
 * - \b npm: https://docs.npmjs.com/ (\c optional, used during build for generating JavaScript modules)
 *
 */

/*! \page COPYING License
 * This program is free software, distributed under the terms of the GNU
 * General Public License Version 3.
 *
 * If you're interested in a commercial license (e.g., because GPLv3 is
 * not suited for what you need, you're interested in technical support
 * or want to sponsor the development of new features), feel free to
 * <a href="https://janus.conf.meetecho.com/support">contact us</a>.
 *
 *  \verbinclude COPYING
 */

/*! \page CHANGELOG Tagged versions and Changelog
 * There are different tagged versions on the Janus repository. We usually
 * tag a new version any time a breaking change and/or a set of comprehensive
 * changes and fixes is going to be merged/applied to Janus, and so the
 * Changelog below can act as a simple and quick summary of which changes
 * are available in each version.
 *
 * It's very important to point out, though, that tagged version are \b NOT
 * to be considered \b stable versions. This is a common misunderstanding.
 * The only version we consider \b stable is \b master as it's the only
 * branch where we continuously provide fixes and enhancements: this is
 * particularly important in the WebRTC world, where it's not uncommon to
 * see features breaking overnight due to changes in how browsers and other
 * WebRTC devices implement things. As such, again, a tagged version is
 * \b only a way to take a snapshot of where Janus was at a specific point
 * in time, and before a more or less major change occurred. While you're
 * free to stick to tagged versions for your deployments (e.g., because
 * that's how provisioning is usually done in your company), please notice
 * we will ignore issues and reports addressing any other branch that is
 * not master: due to lack of time and resources, we simply cannot go and
 * investigate issues we may have fixed already, so if you're experiencing
 * issues, make sure you can replicate them on master as well first.
 *
 *  \verbinclude CHANGELOG.md
 */

/*! \page FAQ Frequently Asked Questions
 * This page contains a list of FAQ as gathered on the
 * <a href="https://groups.google.com/forum/?pli=1#!forum/meetecho-janus">meetecho-janus</a>
 * Google group and the
 * <a href="https://github.com/meetecho/janus-gateway/issues">Issues</a>
 * page on GitHub. It obviously also includes things we're being asked all the
 * time in general! If your question is not listed here or not available
 * anywhere in this documentation, feel free to refer to the group for
 * generic help, or to the Issues page for bugs in the implementation.\n\n
 *
 * <hr>
 *
 * -# <a href="#janus">What is Janus?</a>\n
 * -# <a href="#meetecho">What is Meetecho?</a>\n
 * -# <a href="#pronounce">Now that we're at it, how is Meetecho pronounced??</a>\n
 * -# <a href="#videos">I just started with Janus and am overwhelmed by the amount of info, documentation, etc... any easy way to dive in?</a>\n
 * -# <a href="#origin">Why is Janus called like that?</a>\n
 * -# <a href="#license">Is the license AGPLv3 or GPLv3? Do you provide alternative license mechanisms as well?</a>\n
 * -# <a href="#OS">On what OS can I install Janus?</a>\n
 * -# <a href="#datachans">Are Data Channels supported?</a>\n
 * -# <a href="#usrsctp">I don't care about Data Channels, do I have to compile usrsctp anyway?</a>\n
 * -# <a href="#usrsctperr">I can't install usrsctp, I'm getting errors about dereferencing pointers?</a>\n
 * -# <a href="#gateway">Can I use Janus as a gateway to my Freeswitch/Kamailio/Asterisk/other SIP infrastructure?</a>\n
 * -# <a href="#jssip">Can I use existing SIP stacks (e.g., JsSIP) with Janus?</a>\n
 * -# <a href="#transcoding">Does Janus support transcoding?</a>\n
 * -# <a href="#recording">Does Janus support recording?</a>\n
 * -# <a href="#websockets">Can I use WebSockets instead of plain HTTP to interact with Janus?</a>\n
 * -# <a href="#rabbitmq">Can I use RabbitMQ instead of HTTP/WebSockets to interact with Janus?</a>\n
 * -# <a href="#unixsockets">Can I use Unix Sockets instead of HTTP/WebSockets/RabbitMQ to interact with Janus?</a>\n
 * -# <a href="#mqtt">Can I use MQTT instead of HTTP/WebSockets/RabbitMQ/Unix Sockets to interact with Janus?</a>\n
 * -# <a href="#nanomsg">Can I use Nanomsg instead of HTTP/WebSockets/RabbitMQ/MQTT/Unix Sockets to interact with Janus?</a>\n
 * -# <a href="#transports">What about \<my favourite control protocol\> instead?</a>\n
 * -# <a href="#demos">I've launched Janus, how do I try the demos?</a>\n
 * -# <a href="#certificates">I'm trying the demos, but I get "Janus down" or certificate errors!</a>\n
 * -# <a href="#nodejs">Can I use Janus with node.js or other frameworks?</a>\n
 * -# <a href="#monitoring">How do I monitor/manage my Janus instance?</a>\n
 * -# <a href="#writeplugin">I want to write my own plugin, where do I start?</a>\n
 * -# <a href="#ulimit">I'm using the VideoRoom plugin and, when several users are handled, I get
 *    a "Too many open files" errors and Janus crashes</a>\n
 * -# <a href="#aesgcm">I get an undefined reference to <code>srtp_crypto_policy_set_aes_gcm_256_16_auth</code>
 *    when building Janus</a>\n
 * -# <a href="#https">When I enable the HTTPS web server in Janus, the CPU goes crazy</a>\n
 * -# <a href="#turn">I enabled TURN in the Janus configuration, but my clients behind a firewall can't connect</a>\n
 * -# <a href="#benchmark">Is there any benchmark on Janus performances?</a>\n
 * -# <a href="#scaling">How do I scale Janus?</a>\n
 * -# <a href="#requests">Can you implement a feature/plugin/application I want?</a>\n
 * -# <a href="#learning">I want to learn more on Janus!</a>\n
 *
 * <hr>
 *
 * \anchor janus
 * -# <b>What is Janus?</b>\n
 *    .
 *    Janus is an open source WebRTC server written by <a href="https://www.meetecho.com">Meetecho</a>,
 *    conceived as modular and, as much as possible,
 *    general purpose. It acts as a WebRTC endpoint browsers can interact
 *    with, and different modules can determine what should be done with
 *    the media. This means that you can do SIP, videoconferencing, streaming
 *    and tons of other stuff using the same box! And if what you need is
 *    not there, you can always write your own module and expand Janus.\n\n
 *    .
 * \anchor meetecho
 * -# <b>What is Meetecho?</b>\n
 *    .
 *    Meetecho is a company founded by a few researchers, post-docs and
 *    Ph.Ds coming from the Universty of Napoli Federico II. We've been
 *    working on real-time multimedia applications over the Internet for
 *    years, and at one point we decided to try and make products out
 *    of our research efforts. Our web conferencing platform and Janus
 *    are part of those efforts.\n\n
 *    .
 * \anchor pronounce
 * -# <b>Now that we're at it, how is Meetecho pronounced??</b>\n
 *    .
 *    We're being asked that a lot! We've heard so many variants and different
 *    pronounciations of the name that we could make a book out of it!
 *    When we chose the name, we wanted it to sound like
 *    <a href="https://www.youtube.com/watch?v=TkgDOMSv9PE">this</a>,
 *    which means \a awesome! in Italian. The extra H was a mistake on our
 *    side, as obviously \a echo is pronouced differently than \a eco! Long
 *    story short, it doesn't really matter how you pronounce it: just
 *    do it and help us be famous! :-)\n\n
 *    .
 * \anchor videos
 * -# <b>I just started with Janus and am overwhelmed by the amount of info, documentation, etc... any easy way to dive in?</b>\n
 *    .
 *    Fair point! Janus and its concepts/APIs can be a lot to digest in a short time...
 *    An easy way to start is watching one of the several presentations we've done
 *    on Janus these last months. Most if not all of them try to provide a
 *    complete introduction to the context Janus was built in, how it was
 *    born, the architecture we chose for it and so on. As such, it should
 *    be a useful starting point for whoever is interested in learning
 *    what Janus can do and how to use it.\n\n
 *    There are several videos available that you can find online (most of the slides
 *    available on <a href="https://www.slideshare.net/LorenzoMiniero/">SlideShare</a>),
 *    here are some of them as quick pointers:
 *    - Presentations at <a href="https://www.youtube.com/watch?v=u0PyXgAC8m4">vuc485</a>,
 *    <a href="https://www.youtube.com/watch?v=VnflQF7oCLA">vuc584</a>
 *    and <a href="https://www.youtube.com/watch?v=XnQ7ECOpRIU">vuc640</a> (last one more focused on IETF remote participation);
 *    - Presentation at <a href="https://www.youtube.com/watch?v=SFeWYewoL7Q">OpenSIPS summit 2016</a>;
 *    - Presentation at <a href="https://www.youtube.com/watch?v=yvt-vMHW83c">Kamailio World 2016</a>;
 *    - Presentation at <a href="https://www.youtube.com/watch?v=WfNciKbsP80">WebRTC Meetup Tokyo #12</a>;
 *    - Presentation at <a href="https://www.youtube.com/watch?v=gArqopeNQY0">DevDay Napoli</a> (in Italian);
 *    - Presentation on Event Handlers at <a href="https://www.youtube.com/watch?v=UT9CDhoHL_Q">FOSDEM 2017</a>;
 *    - Presentation on different SIP options in Janus at <a href="https://www.youtube.com/watch?v=anmyMC6Ovl8&t=25112s">OpenSIPS 2017</a>;
 *    - Presentation on WebRTC load testing at <a href="https://www.youtube.com/watch?v=SnvTAsYtZ5s">Kamailio World 2017</a>;
 *    - Presentation on SIP, WebRTC and Asterisk at <a href="https://www.youtube.com/watch?v=IaPDufOzVek">Astricon 2017</a>;
 *    - Presentation at <a href="https://www.youtube.com/watch?v=cSV0X1JgcKY">WebRTC Rockstars Tour (Singapore)</a>;
 *    - Presentation at <a href="https://youtu.be/dsVDzh9sS1A?t=51m00s">WebRTC Meetup Tokyo #17</a> (in Japanese);
 *    - Interview on the origins of Janus, at <a href="http://www.allthingsrtc.org/2017/10/30/lorenzo-miniero-creator-janus/">AllThingRTC.org</a>;
 *    - Presentation on the Janus Lua plugin, at <a href="https://www.youtube.com/watch?v=NVLdbbnmUAA">FOSDEM 2018</a>;
 *    - Presentation on how to integrate Janus and HOMER/HEPIC, at <a href="https://www.youtube.com/watch?v=YUZqhu2-tbM">OpenSIPS 2018</a>;
 *    - Presentation on Security, Authentication and Privacy in WebRTC, at <a href="https://www.youtube.com/watch?v=ewNJMci62rs">Kamailio World 2018</a>;
 *    - Presentation on Janus and Scalability, at <a href="https://www.youtube.com/watch?v=zxRwELmyWU0">CommCon 2018</a>;
 *    - Interview on Janus, at <a href="https://www.youtube.com/watch?v=dzQhyw1jiaA">ClueCon Weekly</a>;
 *    - Presentation at <a href="https://vimeo.com/303014581">Voip2day 2018</a> (here for the <a href="https://vimeo.com/302814764">Spanish version</a>);
 *    - Presentation on Janus and SIP at <a href="https://www.youtube.com/watch?v=beHHL0Ew5xY">OpenSIPS 2019</a>;
 *    - Presentation on RTC fuzzing in Janus at <a href="https://www.youtube.com/watch?v=YTN88fUiGoI">Kamailio World 2019</a>;
 *    - Presentation on Multistream support in Janus (Unified Plan) at <a href="https://www.youtube.com/watch?v=xbsHYvBjsdY">CommCon 2019</a>;
 *    - Presentation on Janus at <a href="https://www.youtube.com/watch?v=2LHto3iufzU">ClueCon 2019</a>;
 *    - Presentation on Simulcast and SVC at <a href="https://www.youtube.com/watch?v=6COV44AORlo">IIT RTC 2019</a>;
 *    - Presentation on RTP forwarders at <a href="https://fosdem.org/2020/schedule/event/janus/">FOSDEM 2020</a>;
 *    - Presentation on using Janus for Virtual Events at <a href="https://2020.commcon.xyz/session/turning-live-events-to-virtual-with-janus/">CommCon 2020</a>;
 *    - Workshop on Janus (lesson/tutorial) at <a href="https://www.youtube.com/watch?v=Ga_7lukslxw">ClueCon 2020</a>;
 *    - Presentation on E2EE (end-to-end encryption) and Insertable Streams at <a href="https://youtu.be/SmN8-6ZFuOo?t=2004">ClueCon 2020</a>;
 *    - Workshop on Janus and SIP (lesson/tutorial) at <a href="https://youtu.be/fv9KwrguR-4?t=3544">OpenSIPS 2020</a>;
 *    - Presentation on SFUs and MCUs at <a href="https://www.youtube.com/watch?v=0ldgX_0w5QU">IIT RTC 2020</a>;
 *    - Presentation on using Janus for IETF Virtual Participation at the <a href="https://youtu.be/WeoKtWfmxnU?t=286">MOPS WG session (IETF109)</a>;
 *    - Presentation on WebRTC (and Janus) as a way to help musicians at <a href="https://fosdem.org/2021/schedule/event/webrtc_musicians/">FOSDEM 2021</a>;
 *    - Workshop on Janus RTP forwarders (lesson/tutorial) at <a href="https://www.youtube.com/watch?v=uW8ztFCkxVk">ClueCon TGI2021</a>;
 *    - Presentation on Janus and NDI at <a href="https://youtu.be/RZ58vapWfUw?t=1755">ClueCon TGI2021</a>;
 *    - Presentation on Janus and multicast at the <a href="https://youtu.be/cT_74CRBsQs?t=5910">MBONED WG session (IETF 110)</a>;
 *    - Presentation on how to use WHIP and Janus for broadcasting at <a href="https://www.youtube.com/watch?v=b_QBd3WnGgY">IIT RTC 2021</a>;
 *    - Presentation on the efforts to integrate audio redundancy via RED in Janus at <a href="https://www.youtube.com/watch?v=NWEYv6OILZI">ClueCon 2021</a>;
 *    - Presentation on how to use WHIP, NDI and Janus together at <a href="https://2021.commcon.xyz/talks/whip-ndi-and-janus-genesis-of-a-broadcasting-demo">CommCon 2021</a>;
 *    - Presentation on Janode, the official Janus nodejs SDK, at <a href="https://2021.commcon.xyz/talks/janode-the-janus-node-js-sdk">CommCon 2021</a>;
 *    - Presentation on WebRTC broadcasting with WHIP and how to scale at <a href="https://fosdem.org/2022/schedule/event/rtc_whip/">FOSDEM 2022</a>;
 *    - Presentation on SIP call transfers and multiple calls at <a href="https://youtu.be/vSFZe8SsTbM?t=6379">OpenSIPS 2022</a>;
 *    - Presentation on SFU/VideoRoom cascading at <a href="https://www.youtube.com/watch?v=z7SvEQcDEgM">IIT RTC 2022</a>. \n\n
 *    Apart from these presentations, make sure you also check the slides
 *    and presentations from <a href="https://januscon.it/2019">JanusCon</a>,
 *    the Janus conference we hosted here in Napoli.
 *    \n\n
 *    .
 * \anchor origin
 * -# <b>Why is Janus called like that?</b>\n
 *    .
 *    Quoting <a href="http://en.wikipedia.org/wiki/Janus">Wikipedia</a>:
 *    "<i>In ancient Roman religion and myth, Janus (Latin: Ianus, pronounced
 *    [ˈiaː.nus]) is the god of beginnings and transitions, and thereby of
 *    gates, doors, passages, endings and time. He is usually depicted as
 *    having two faces, since he looks to the future and to the past.</i>"
 *    Considering the general purpose nature of our server, where one face always looks
 *    at the future (WebRTC) and the other at the past (whatever the modules
 *    allows you to do, be it legacy stuff or not), Janus looked like the
 *    perfect name for it! And besides, we're Italian, Ancient Rome was
 *    awesome and mythology rules... ;-)
 *    \n\n
 *    .
 * \anchor januslicense
 * -# <b>Is the license AGPLv3 or GPLv3? Do you provide alternative license mechanisms as well?</b>\n
 *    .
 *    Janus is licensend under the GPLv3 licence. At the very beginning
 *    we chose AGPLv3 for a simple reason: we wanted our work to be open source,
 *    and we wanted interested people to play with it and contribute back
 *    whatever improvement they could provide to the core. This is not always
 *    the case with open source software, which is sometimes just seen as
 *    free stuff you can exploit without helping back, and AGPLv3 looked like
 *    the easiest way to do that. That said, we were almost immediately
 *    made aware that this license mechanism is
 *    <a href="https://groups.google.com/forum/?pli=1#!searchin/discuss-webrtc/janus/discuss-webrtc/LJHXkIsAaEU/fHgJ2z0sxfoJ">not very appreciated</a>
 *    around, especially because of some
 *    interpretations about it that could affect the way proprietary stuff
 *    is deployed. We obviously cared about these concerns, and that's what
 *    eventually lead us to pick GPLv3 as a license, which should make it
 *    easier for Janus to be integrated in heterogeneous scenarios.\n\n
 *    Anyway, if for some reason you're not comfortable with GPLv3 for your
 *    needs, we have a <a href="https://janus.conf.meetecho.com/support">commercial license</a>
 *    offering as well.\n\n
 *    .
 * \anchor OS
 * -# <b>On what OS can I install Janus?</b>\n
 *    .
 *    At the moment only Linux is officially supported. Anyway, Janus does
 *    compile on Mac OS as well, thanks to contributions from the community,
 *    and so should work fine there as well. Windows support is also provided
 *    as a <a href="https://github.com/meetecho/janus-gateway/pull/597">pull request</a>
 *    by a Janus contributor: anyway, please beware that Windows support is behind the current
 *    version of development.\n\n
 *    .
 * \anchor datachans
 * -# <b>Are Data Channels supported?</b>\n
 *    .
 *    Yes they are! Starting from version \c 0.0.3 of Janus, we added a first
 *    experimental support to Data Channels, that can as such be used in
 *    plugins that choose to support them. Right now, they are handled in
 *    several plugins like the Echo Test, VideoCall, VideoRoom and TextRoom plugins.\n\n
 *    Please notice that right now we only support text data: hopefully support
 *    for binary streams will be available soon as well. Until that happens,
 *    you'll have to resort to text-based encodings like Base64 to share
 *    binary data through Janus.\n\n
 *    .
 * \anchor usrsctp
 * -# <b>I don't care about Data Channels, do I have to compile usrsctp anyway?</b>\n
 *    .
 *    Support for Data Channels is optional, so if you didn't install the library
 *    the configure script will go around them and compile Janus without Data Channels
 *    support. If you did install the library and don't care about Data Channels,
 *    but only about audio and/or video, pass the \c --disable-data-channels
 *    option to the configure script to explicitly disable them. If you're updating
 *    an existing install, issue a \c make \c clean before compiling again, or
 *    you might encounter issues with pre-existing symbols.\n\n
 *    .
 * \anchor usrsctperr
 * -# <b>I can't install usrsctp, I'm getting errors about dereferencing pointers?</b>\n
 *    .
 *    Apparently recent compilers are stricter with respect to some code
 *    syntaxes, and this seems to be affecting the way \c usrsctp is written
 *    as of now. Some users managed to fix this issue by passing an export
 *    before the \c bootstrap and \c configure steps in the \c usrsctp
 *    compilation:\n\n
 *\verbatim
   export CFLAGS="-fno-strict-aliasing" ./boostrap
   export CFLAGS="-fno-strict-aliasing" ./configure --prefix=/usr
   make && make install
 \endverbatim
 *    Another solution seems to be removing all the \c -O2 occurrences
 *    in the generated \c configure script.\n\n
 *    .
 * \anchor gateway
 * -# <b>Can I use Janus as a gateway to my Freeswitch/Kamailio/Asterisk/other SIP infrastructure?</b>\n
 *    .
 *    Of course! One of the modules we provide out of the box is a SIP
 *    gateway plugin based on the <a href="https://github.com/freeswitch/sofia-sip">Sofia-SIP</a>
 *    library stack. These plugin allows a web user to register at a SIP
 *    proxy/server either as an authenticated user or as a guest, and
 *    start or receive calls from other SIP users, including other web users
 *    exploiting the same plugin. Janus will take care of all the WebRTC-related
 *    stuff (ICE, DTLS, SRTP), which means that on the SIP side it will
 *    be plain RTP only, much easier and lighter to handle for legacy
 *    implementations. SDES-SRTP is also supported on the SIP side in case
 *    it is required.\n\n
 *    .
 * \anchor jssip
 * -# <b>Can I use existing SIP stacks (e.g., JsSIP) with Janus?</b>\n
 *    .
 *    Janus uses a custom JSON-based protocol for all the communication
 *    between web users and plugins in the server, so no, that's not
 *    possible right now. While there are some controls that give you access
 *    to some of the SIP details (e.g., requesting SRTP negotiation or injecting
 *    custom headers), the SIP plugin in Janus only exposes some very
 *    high level information to web users (e.g., registration failed/succeeded,
 *    incoming call, decline, hangup, etc.), without delving in any SIP-related
 *    detail, which is instead completely demanded to the server-side plugin
 *    itself. This ensures that web users can take advantage of SIP functionality
 *    in an easy way, without having to worry about the details and complexity
 *    of SIP within JavaScript.\n\n
 *    .
 * \anchor transcoding
 * -# <b>Does Janus support transcoding?</b>\n
 *    .
 *    Janus is a simple intermediary between WebRTC users and server-side
 *    plugins providing application logic, so no, it doesn't provide any
 *    transcoding functionality per-se. If transcoding is needed, this is
 *    supposed to be implemented within plugins themselves. That said,
 *    apart from the AudioBridge plugin which acts as an audio MCU,
 *    none of the plugins we provide out-of the box does transcoding,
 *    since we wanted the implementation to be lightweight and besides
 *    there are several existing tools and third-party implementations that
 *    could be leveraged for the purpose.\n\n
 *    .
 * \anchor recording
 * -# <b>Does Janus support recording?</b>\n
 *    .
 *    Yep! The Janus core provides an integrated way of recording all
 *    the media streams that go through it, whether it's audio, video or
 *    data, and almost all stock plugins do exploit it one way or another.
 *    Recording is implemented as a structured dump of all RTP and data
 *    files exactly as they were transmitted or sent: as such, no manipulation
 *    is done while recording, and all post-processing is demanded to
 *    an external tool. For more information on this, check the
 *    <a href="https://janus.conf.meetecho.com/docs/janus-pp-rec_8c.html#details">documentation</a>.\n\n
 *    .
 * \anchor websockets
 * -# <b>Can I use WebSockets instead of plain HTTP to interact with Janus?</b>\n
 *    .
 *    Since version \c 0.0.4, you can! At first we chose a REST-based plain HTTP communication
 *    for a simple reason: we noticed that there were some scenarios (e.g.,
 *    client firewalls) where websockets wouldn't work, even though WebRTC
 *    did. To improve the chances of success in the communication, we
 *    then chose this simpler approach with respect to signalling. Besides,
 *    plain HTTP is much easier to proxy and/or place behind frontends
 *    like Apache HTTPD or nginx than WebSockets, another aspect that
 *    played a decisive role in our decision, as we were also very interested
 *    in making the integration of Janus in heterogeneous environments
 *    as easy as possible. That said, WebSockets also provide substantial
 *    benefits when compared to plain HTTP, and definitely make life easier to
 *    server side integrators as well, e.g., in terms of overhead and use of
 *    resources. For more information, check the \ref WS page. \n\n
 *    .
 * \anchor rabbitmq
 * -# <b>Can I use RabbitMQ instead of HTTP/WebSockets to interact with Janus?</b>\n
 *    .
 *    Since version \c 0.0.6, you can! This is a feature that several
 *    developers asked for, especially those that are interested in wrapping
 *    the Janus API on the server side, and implement the communication
 *    on the client side their own way. Specificaly, Janus now supports
 *    RabbitMQ based messaging as an alternative "transport" for API
 *    requests, responses and notifications, meaning it can be used with
 *    or without HTTP and WebSockets, depending on your requirements.
 *    For more information, check the \ref rabbit page. \n\n
 *    .
 * \anchor unixsockets
 * -# <b>Can I use Unix Sockets instead of HTTP/WebSockets/RabbitMQ to interact with Janus?</b>\n
 *    .
 *    Since version \c 0.2.1, you can! More specifically, you can use a
 *    \c SOCK_SEQPACKET or a \c SOCK_DGRAM socket to control a Janus instance.
 *    Notice that this feature is only available when installing Janus on a Linux machine.
 *    For more information, check the \ref unix page. \n\n
 *    .
 * \anchor mqtt
 * -# <b>Can I use MQTT instead of HTTP/WebSockets/RabbitMQ/Unix Sockets to interact with Janus?</b>\n
 *    .
 *    Since version \c 0.2.1, you can! This was a very welcome contribution by
 *    a Janus user, as it makes it even easier to have Janus interact with IoT deployments.
 *    For more information, check the \ref apimqtt page. \n\n
 *    .
 * \anchor nanomsg
 * -# <b>Can I use Nanomsg instead of HTTP/WebSockets/RabbitMQ/MQTT/Unix Sockets to interact with Janus?</b>\n
 *    .
 *    Since version \c 0.4.2, you can! For more information, check the \ref apinanomsg page. \n\n
 *    .
 * \anchor transports
 * -# <b>What about \<my favourite control protocol\> instead?</b>\n
 *    .
 *    Since version \c 0.1.0, the transports for the Janus API have been made
 *    modular. This means that, assuming a transport plugin implementing
 *    support for your favourite protocol has been made available, you
 *    can just add it to the Janus transport modules folder and it should
 *    work. If no plugin has been implemented, you may even want to do so
 *    yourself, or ask for ours or others help.\n\n
 *    .
 * \anchor demos
 * -# <b>I've launched Janus, how do I try the demos?</b>\n
 *    .
 *    The demos are available in the \c html folder in the project. That
 *    said, the integrated web server in Janus does not serve static files
 *    as well, so you'll have to make them available using a different
 *    webserver. Details about how to deploy Janus are provided in
 *    \ref deploy.\n\n
 *    .
 * \anchor certificates
 * -# <b>I'm trying the demos, but I get "Janus down" or certificate errors!</b>\n
 *    .
 *    Again, make sure you've read and are following the instructions on how to
 *    effectively deploy Janus in \ref deploy. Most likely you're either trying
 *    to open the WebRTC demos using HTTP instead of HTTPS (something that
 *    browsers will not allow, if not on localhost for testing), trying
 *    to contact Janus via an insecure protocol through a secure page, or
 *    using an insecure certificate for Janus itself. All of these problems
 *    are explained and solved easily in the \ref deploy documentation.\n\n
 *    .
 * \anchor nodejs
 * -# <b>Can I use Janus with node.js or other frameworks?</b>\n
 *    .
 *    Not natively, but since interaction with Janus is demanded to
 *    a JSON based communication transported on a network protocol (HTTP,
 *    WebSockets, RabbitMQ and others), this can be abstracted quite easily
 *    in several different ways. A common approach is implementing the Janus
 *    API in a server-side application, so that you handle users your own way
 *    and with your own API, while controlling Janus as a media server yourself
 *    by wrapping its API. Check the \ref resources documentation page
 *    for a list of Janus API wrappers in different programming languages
 *    that ou can use within your application
 *    to control a Janus instance from there instead of the browser. Should
 *    you decide to write your own Janus API wrapper, don't hesitate to let
 *    us know so that we can advertise yours there too!\n\n
 *    .
 * \anchor monitoring
 * -# <b>How do I monitor/manage my Janus instance?</b>\n
 *    .
 *    Since version \c 0.2.2 there are a couple of different ways you can do
 *    that. The first and most immediate one is making use of the Admin API,
 *    which you can find documented in the \ref admin page. It is a request/response
 *    protocol that can be used to poll information on existing sessions and
 *    handles, and which also provides a lot of useful WebRTC-related information
 *    on PeerConnections Janus is managing. You can also find a very useful
 *    <a href="https://www.meetecho.com/blog/understanding-the-janus-admin-api">blog post</a>
 *    where we describe in detail how the Admin API can be used to investigate issues. \n\n
 *    A more recent, and potentially much more powerful, addition to Janus
 *    are the Event Handlers. Unlike the Admin API, which is query-based,
 *    Event Handlers provide a mechanism to dynamically feed you with real-time
 *    and live data on whatever is happening within Janus, whether it's the
 *    core or any of the plugins. You can find more information, along with
 *    an example of how to receive such events, in the
 *    <a href="https://github.com/meetecho/janus-gateway/pull/536">pull request</a>
 *    page from where this effort was merged. More guidelines and implementations
 *    will definitely follow. \n\n
 *    .
 * \anchor writeplugin
 * -# <b>I want to write my own plugin, where do I start?</b>\n
 *    .
 *    Great! Depending on the kind of plugin you want to implement (application plugin,
 *    transport plugin, event handler plugin), some of the details may change,
 *    but the concept is typically the same. There are APIs you can refer to,
 *    documented in \ref pluginapi , \ref transportapi and \ref eventhandlerapi.
 *    The existing plugins are also an excellent way to start to get
 *    comfortable with the API: a good starting point may be the Echo Test
 *    plugin, which is a very simple and barebone implementation that
 *    simply bounces back whatever it is sent, and also involves some
 *    rough application logic to determine its behaviour (e.g., messages
 *    coming from web users that selectively enable or disable video).
 *    You may want to check third-party plugins as well in the \ref resources
 *    as well, as they'll give you an idea of how other users did the same.
 *    If you need any help with this, feel free to ask for help on the Google group:
 *    we're always excited whenever new Janus plugins are realized!\n\n
 *    .
 * \anchor ulimit
 * -# <b>I'm using the VideoRoom plugin and, when several users are handled, I get
 *    a "Too many open files" errors and Janus crashes</b>\n
 *    .
 *    As all applications on Linux environments, Janus is bound to the
 *    constraints imposed by the OS and/or the user. One of these constraints
 *    is related to how many file descriptors the application, or all the
 *    applications, can open. On several distributions this number is, by
 *    default, quite low, which can cause the issue you experienced. This
 *    value, together with others, can be modified, per-user or for all users,
 *    using the \c ulimit application. For a simple and quick way to handle
 *    this refer to the guide provided by the MongoDB developers:
 *    http://docs.mongodb.org/manual/reference/ulimit/ \n\n
 *    .
 * \anchor aesgcm
 * -# <b>I get an undefined reference to <code>srtp_crypto_policy_set_aes_gcm_256_16_auth</code>
 *    when building Janus</b>\n
 *    .
 *    As explained in the README, you have to build libsrtp or libsrtp2 with
 *    the <code>--enable-openssl</code> or <code>--enable-nss</code> flags,
 *    since they're needed to support AES-GCM in our SRTP streams. If you
 *    don't want AES-GCM support, pass the <code>--disable-aes-gcm</code>
 *    option when configuring Janus instead: remember to do a
 *    <code>make clean</code> before recompiling Janus after the change. \n\n
 *    .
 * \anchor https
 * -# <b>When I enable the HTTPS web server in Janus, the CPU goes crazy</b>\n
 *    .
 *    As discussed in a recent <a href="https://groups.google.com/forum/?pli=1#!topic/meetecho-janus/lD8A0VqXsNs">post</a>
 *    on our Google group, this is caused by an occasional problem within
 *    libmicrohttpd, the library we use to implement an embedded web server
 *    in Janus. This is not deterministic, as the high CPU usage does happen
 *    on some distributions (e.g., Ubuntu 12.04), while it doesn't on
 *    others (e.g., Ubuntu 14.04). Anyway, this only can happen if you enable
 *    HTTPS support within Janus itself: you can still have a safe HTTPS
 *    usage with Janus if you deploy it behind a frontend (e.g., Apache HTTPD)
 *    that takes care of this on its behalf. Refer to the \ref deploy section
 *    for more details about this.\n\n
 *    .
 * \anchor turn
 * -# <b>I enabled TURN in the Janus configuration, but my clients behind a firewall can't connect</b>\n
 *    .
 *    As explained in the \c janus.jcfg documentation, the TURN settings you
 *    configure there refer to Janus \b itself, \b not the clients that make use
 *    of its services. This means that, whether you configure a static TURN
 *    server and the related credentials, or the REST API client stack to
 *    retrieve them dynamically, you're asking Janus to gather relay candidates
 *    for ITSELF. This is only useful if you know that your Janus instance
 *    will not be deployed on a public address (as it usually will) but will
 *    instead potentially sit behind a restrictive component like a firewall,
 *    or if you simply want to limit the number of open ports and so force
 *    all media traffic to go through the TURN server port alone.\n\n
 *    If you want your clients to gather relay candidates, instead, this
 *    needs to be done on the client side (e.g., in JavaScript, if your
 *    clients are web applications). If you're using our \ref JS check
 *    the \c echotest.js code, which has a commented portion that explains
 *    how to provide one or more TURN servers to make use of. If you're
 *    handling the WebRTC-related stuff on your own and are contacting
 *    Janus some other way, please refer to the related way of specifying
 *    STUN and TURN servers instead.\n\n
 *    .
 * \anchor benchmark
 * -# <b>Is there any benchmark on Janus performances?</b>\n
 *    .
 *    Benchmarking Janus is not an easy task, especially if we consider
 *    its general purpose nature. In fact, Janus by itself does not much
 *    more than negotiating WebRTC PeerConnections and relaying frames
 *    around, while most of the application login is in the modules. As
 *    you can imagine, different modules may have very different requirements
 *    and impact on the performances. For instance, the Echo Test is probably
 *    much lighter than the Video SFU, even if they're handling the same
 *    number of users. This means that such a benchmarking does not have
 *    much sense unless you contextualise the scenarios.\n\n
 *    You can find some results on tests we made ourselves in a couple of
 *    publications we wrote and available
 *    <a href="https://janus.conf.meetecho.com/citeus">here</a>. One of those
 *    introduces a WebRTC stress testing tool we implemented called Jattack,
 *    for which a <a href="https://www.youtube.com/watch?v=UwNq8p0m1js">video of the presentation</a>
 *    is available. You can find some more details and considerations in an older
 *    <a href="https://groups.google.com/forum/?pli=1#!topic/meetecho-janus/ydGcbMt7IX0">post</a>
 *    on our Google group too.\n\n
 *    .
 * \anchor scaling
 * -# <b>How do I scale Janus?</b>\n
 *    .
 *    This question is way too generic to answer here. As explained in the previous
 *    point, Janus is not an easily measurable entity, as it very much depends
 *    on which of the plugins you're involving in the scenarios that interest you
 *    and how. The same considerations also apply to scaling the scenario you
 *    implemented, as different plugins may require different approaches to
 *    do that. \n\n
 *    In general, Janus does not have any built-in multi-tenant support. Each
 *    Janus instance is conceived to be standalone, and works by itself. That
 *    said, there are different ways in which you can implement scalability in
 *    your service. One of them is implementing a wrapper/controller application
 *    that is in charge of multiple Janus instances, so that it can distribute
 *    the load depending on the requests. If the scenario allows for it,
 *    you can also mix concepts from different plugins on different Janus
 *    instances (e.g., use the RTP forwardiing feature of the VideoRoom plugin
 *    to make the same VideoRoom publisher available as a Streaming mountpoint
 *    on other Janus machines). Anyway, as explained each application may have
 *    very different requirements when it comes to scalability. \n\n
 *    Should you be interested in implementing scalability in your application and
 *    need help, <a href="https://janus.conf.meetecho.com/support">contact us</a>.\n\n
 *    .
 * \anchor requests
 * -# <b>Can you implement a feature/plugin/application I want?</b>\n
 *    .
 *    We're constantly working on new features and on improving what's
 *    already there, and we do love feedback from users. That said, we're
 *    a small team and we do have to pay our bills, so we always have to
 *    reserve our resources wisely. If there's a feature you'd like to
 *    see implemented, tell us on our Google group, and discuss it with
 *    other users: it may be on our schedule, or someone else may be
 *    already working on it to contribute it back to the project. You
 *    may even want to try and build it yourself and help us make Janus
 *    even better! \n\n
 *    If you really need something that isn't there, you may also want to consider
 *    <a href="https://janus.conf.meetecho.com/support">contacting us</a>
 *    for a sponsored development or consulting.\n\n
 *    .
 * \anchor learning
 * -# <b>I want to learn more on Janus!</b>\n
 *    .
 *    That's great! The first obvious suggestion is of course to carefully
 *    read the documentation here: we worked hard on it and are constantly
 *    expanding it, so it should always be the first source of information
 *    whenever in doubt. We have a great Google group as well where the
 *    <a href="https://groups.google.com/forum/#!forum/meetecho-janus">community</a>
 *    shares questions, data and more everyday, so make sure you join too! \n\n
 *    We also provide training on Janus and WebRTC in general, so if interested
 *    just <a href="https://janus.conf.meetecho.com/support">contact us</a>.\n\n
 *    .
 */

/*! \defgroup core Core
 * \brief Core implementation of the server
 * \details The Janus WebRTC Server is founded on a core that glues the
 * involved parts together. The main code is janus.c that implements
 * the logic behind the server itself: it implements the web server that
 * interacts with browsers, and handles sessions with them. This includes
 * taking care of media signalling and negotiation, and bridging peers
 * with available plugins.
 */

/*! \defgroup protocols Protocols
 * \brief Implementations of the WebRTC protocols
 * \details The WebRTC specification (WEBRTC/RTCWEB) currently mandates
 * the usage of a few protocols and techniques. The code in this group
 * takes care of them all (SDP, ICE, DTLS-SRTP, RTP/RTCP).
 * \ingroup core
 */

/*! \defgroup plugins Plugins
 * \brief Janus plugins available out of the box
 * \details In order to showcase how different plugins can implement
 * completely different applications on top of the Janus core, a few
 * plugin implementations are provided out of the box. The API for
 * writing a new plugin is specified in the \ref pluginapi section.
 */

/*! \defgroup pluginapi Plugin API
 * \brief Plugin API (aka, how to write your own plugin)
 * \details The plugin.h header specifies the API a plugin needs to
 * implement and make available in order to be used by the server and
 * exposed to browsers.
 * \ingroup plugins
 */

/*! \defgroup luapapi Lua plugin API
 * \brief Lua plugin (aka, how to write your own plugin in Lua)
 * \details The Janus Lua plugin allows you to write your application
 * logic in Lua, instead of creating a new plugin in C: check the
 * documentation in janus_lua.c for info on the APIs. Some additional
 * hooks in C may be required, which is what the janus_lua_data.h and
 * janus_lua_extra.c code is for.
 * \ingroup plugins
 */

/*! \defgroup jspapi Duktape plugin API
 * \brief Duktape plugin (aka, how to write your own plugin in JavaScript)
 * \details The Janus Duktape plugin allows you to write your application
 * logic in JavaScript, instead of creating a new plugin in C: check the
 * documentation in janus_duktape.c for info on the APIs. Some additional
 * hooks in C may be required, which is what the janus_duktape_data.h and
 * janus_duktape_extra.c code is for.
 * \ingroup plugins
 */

/*! \defgroup transports Transports
 * \brief Transport plugins available out of the box
 * \details In order to showcase how different transport plugins can implement
 * support for the Janus API over different transport protocols, a few
 * plugin implementations are provided out of the box. The API for
 * writing a new plugin is specified in the \ref transportapi section.
 */

/*! \defgroup transportapi Transport API
 * \brief Transport API (aka, how to write your own transport plugin)
 * \details The transport.h header specifies the API a plugin needs to
 * implement and make available in order to expose a new transport protocol
 * that can be used by the server for talking the Janus API.
 * \ingroup transports
 */

/*! \defgroup eventhandlers Event Handlers
 * \brief Event handler plugins available out of the box
 * \details In order to showcase how different plugins can handle events
 * originated by the Janus core or any of its plugins, a sample plugin
 * implementation is provided out of the box. The API for writing a new
 * event handler plugin is specified in the \ref eventhandlerapi section.
 */

/*! \defgroup eventhandlerapi Event Handler API
 * \brief Event Handler API (aka, how to write your own event handler plugin)
 * \details The eventhandler.h header specifies the API a plugin needs to
 * implement and make available in order to receive events from Janus.
 * \ingroup eventhandlers
 */

/*! \defgroup loggers Loggers
 * \brief Logger plugins available out of the box
 * \details In order to showcase how different plugins can handle log lines
 * originated by the Janus core or any of its plugins, a sample plugin
 * implementation is provided out of the box. The API for writing a new
 * logger plugin is specified in the \ref loggerapi section.
 */

/*! \defgroup loggerapi Logger API
 * \brief Logger API (aka, how to write your own logger plugin)
 * \details The logger.h header specifies the API a plugin needs to
 * implement and make available in order to receive log lines from Janus.
 * \ingroup loggers
 */

/*! \defgroup tools Tools and utilities
 * \brief Tools and utilities
 * \details Set of simple tools and utilities that may be of help when
 * used in conjunction with Janus.
 */

/*! \defgroup postprocessing Recordings post-processing utility
 * \brief \ref recordings post-processing utility
 * \details This simple utility (janus-pp-rec.c) allows you to
 * post-process \ref recordings generated by the janus_recorder helper (e.g.,
 * in the Video SFU plugin).
 * \ingroup tools
 */
