forked from meetecho/janus-gateway
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mainpage.dox
1982 lines (1967 loc) · 85 KB
/
mainpage.dox
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*!
* \mainpage Janus - General purpose WebRTC Gateway
*
* \par Developer Documentation for the Janus WebRTC Gateway
* This is the main developer documentation for the Janus WebRTC
* Gateway, 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 the gateway,
* checkout the \ref README information. A \ref FAQ page is also available.
*
* \par A general purpose gateway
* The Janus WebRTC Gateway has been conceived as a <tt>general purpose</tt>
* gateway. 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 gateway 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
* gateway on the cloud, or a small nettop/box to handle a specific use case.
*
* \par Architecture and APIs
* The core of the gateway is specified in the \ref core section. The protocols
* implemented in the gateway are listed in the \ref protocols group
* instead. A list of plugins made available out of the box by Meetecho
* are available in the \ref plugins group: 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 HTTP/WebSocket/RabbitMQ
* tranports and the HTTP/WebSocket JavaScript API to use the
* gateway and the plugins it makes available in your web application
* can be found in the \ref JS and \ref rest pages. If you're interested
* in monitoring Janus resources, you can refer to the \ref admin page.
* 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.
*
* This is only the first version of the gateway, and as such it is a bit
* rough at the edges: there is definitely room for improvement, there are
* bugs, limitations, and things that need to be done. For a quick glance
* on the most relevant pending stuff check our \ref todo (and, if you're
* willing to help on any of those, get in touch with us!)
*
* \section copyright Copyright and author
*
* Janus WebRTC Gateway © 2014 <a href="http://www.meetecho.com/">Meetecho</a> (http://www.meetecho.com/)
*
* \author Lorenzo Miniero <[email protected]> ( \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 gengetopt: http://www.gnu.org/software/gengetopt/ (command line)
* - \b libmicrohttpd: http://www.gnu.org/software/libmicrohttpd/ (Web server)
* - \b libini-config: https://fedorahosted.org/sssd/ (INI configurations)
* - \b Jansson: http://www.digip.org/jansson/ (JSON)
* - \b libnice: http://nice.freedesktop.org/wiki/ (ICE/STUN/TURN)
* - \b OpenSSL: http://www.openssl.org/ (DTLS, at least v1.0.1e)
* - \b libsrtp: http://srtp.sourceforge.net/srtp.html (SRTP)
* - \b Sofia-SIP: http://sofia-sip.sourceforge.net/ (SDP parsing, SIP handling in the SIP plugin)
* - \b usrsctp: http://code.google.com/p/sctp-refimpl/ (\c optional, Data Channels)
* - \b libwebsock: https://github.com/payden/libwebsock/ (\c optional, v1.0.4, WebSockets)
* - \b rabbitmq-c: https://github.com/alanxz/rabbitmq-c (\c optional, v1.0.4, WebSockets)
* - \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)
*
*/
/*! \page JS JavaScript API
* The gateway exposes both a pseudo-RESTful interface, and optionally a
* WebSocket interface as well, both of which based on JSON messages. These
* interfaces are described in more detail in the \ref plainhttp and
* \ref WS documentation respectively, and both allow web applications to
* take advantage of the features provided by Janus and the functionality
* made available by its plugins. 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 gateway, 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.
*
* \note The current \c janus.js library makes use of jQuery (http://jquery.com/)
* as a support. We're considering preparing versions that make use of
* different libraries as well (e.g., Prototype, Dojo, Script.aculo.us, etc.)
* in case your web application us based on something that cannot make use
* of jQuery. Of course, if you happen to prepare one yourself in the
* meanwhile don't hesitate and let us know! :-)
*
* In general, when using the gateway features, you would normally do the following:
*
* -# include the Janus JavaScript library in your web page;
* -# initialize the Janus JavaScript library;
* -# connect to the gateway 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 gateway 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 <video> 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! :-)
*
* <hr>
*
* As a first step, you should include the \c janus.js library in your project:
*
\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 (true/false, default=false)
* - \c callback: a user provided function that is invoked when the initialization is complete.
*
* Here's an example:
*
*
\verbatim
Janus.init({
debug: true,
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 gateway: in
* fact, each gateway 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
* gateway session. That said, you're free to set up different gateway
* 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
* gateway. 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 gateway 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);
* - 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 tipically 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 gateway.
* 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 gateway;
* - \c isConnected(): returns \c true if the Janus instance is connected
* to the gateway, \c false otherwise;
* - \c getSessionId(): returns the unique gateway session identifier;
* - \c attach(parameters): attaches the session to a plugin, creating an handle;
* more handles to the same or different plugins can be created at the same time;
* - \c destroy(parameters): destroys the session with the gateway, 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 );
* will be used if you skip this property)
* - 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 onmessage: a message/event has been received from the plugin;
* - \c onlocalstream: a local \c MediaStream is available and ready to be displayed;
* - \c onremotestream: a remote \c MediaStream 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
},
onlocalstream: function(stream) {
// We have a local stream (getUserMedia worked!) to display
},
onremotestream: function(stream) {
// We have a remote stream (working PeerConnection!) to display
},
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 dtmf(parameters): sends a DTMF tone on the PeerConnection;
* - \c data(parameters): sends data through the Data Channel, if available;
* - \c getBitrate(): gets a verbose description of the currently received stream bitrate (only available on Chrome, for now);
* - \c hangup(): tells the library to close the PeerConnection;
* - \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 ( \c send(msg) ), negotiate
* a PeerConnection with the plugin right away ( \c createOffer followed
* by a \c send(msg, jsep) ) 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
* \c send(msg, jsep) 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 onlocalstream and/or the \c onremotestream callbacks will provide
* you with a stream you can display 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.
*
* - \c createOffer takes a single parameter, that can contain any of the
* following properties and callbacks:
* - \c media: 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
* audio and video are enabled in both directions, while the Data Channels are disabled;
* this option is an object that can take any of the following properties:
* - \c audioSend: \c true/false (do or do not send audio);
* - \c audioRecv: \c true/false (do or do not receive audio);
* - \c audio: \c true/false (do or do not send \b and receive audio, takes precedence on the above);
* - \c videoSend: \c true/false (do or do not send video);
* - \c videoRecv: \c true/false (do or do not receive video);
* - \c video: \c true/false (do or do not send \b and receive video, takes precedence on the above);
* - \c video: \c "hires"/"lowres" (send a 1280x720 or a 320x240 video, takes precedence on the above);
* this property will affect the resulting getUserMedia that the library will issue;
* - \c video: \c "screen" (use screensharing for video, disables audio, takes precedence on both audio and video);
* - \c data: \c true/false (do or do not use Data Channels, default is false)
* - \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 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 the gateway 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;
var body = { "audio": true, "video": true };
echotest.send({"message": body});
echotest.createOffer(
{
// No media property provided: by default,
// it's sendrecv for audio and video
success: function(jsep) {
// Got our SDP! Send our OFFER to the plugin
echotest.send({"message": body, "jsep": jsep});
},
error: function(error) {
// An error occurred...
}
});
},
[..]
onmessage: function(msg, jsep) {
// Handle msg, if needed, and check jsep
if(jsep !== undefined && jsep !== null) {
// We have the ANSWER from the plugin
echotest.handleRemoteJsep({jsep: jsep});
}
},
[..]
onlocalstream: function(stream) {
// Invoked after createOffer
// This is our video
},
onremotestream: function(stream) {
// Invoked after handleRemoteJsep has got us a PeerConnection
// This is the remote video
},
[..]
\endverbatim
*
* This, instead, is an example of how to use \c createAnswer, taken from the Streaming demo page:
*
\verbatim
// Attach to echo test 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 !== undefined && jsep !== null) {
// We have an OFFER from the plugin
streaming.createAnswer(
{
// We attach the remote OFFER
jsep: jsep,
// We want recvonly audio/video
media: { audioSend: false, videoSend: false },
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...
}
});
}
},
[..]
onlocalstream: function(stream) {
// This will NOT be invoked, we chose recvonly
},
onremotestream: function(stream) {
// Invoked after send has got us a PeerConnection
// This is the remote video
},
[..]
\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 Video Call plugin)
* 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.
*
* <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 rest RESTful, WebSockets and RabbitMQ API
*
* Since version \c 0.0.6, there are three different ways to interact with a
* Janus instance: a \ref plainhttp (the default), a \ref WS and a \ref rabbit
* (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 interfaces as well.
* As it will be explained later in the \ref WS and \ref rabbit sections
* below, the only differences come when addressing specific sessions/handles
* and in part in how you handle notifications using WebSockets: in fact,
* since with WebSockets and RabbitMQ there's no REST-based path involved,
* you'll need a couple of additional identifiers to bridge the gap.
*
* \section plainhttp Plain HTTP REST Interface
* As anticipated in the \ref JS documentation, the gateway 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 gateway
* your own way), this page described the interface and the protocol
* the API exposes and uses. Some details are also provided in case you're
* interested in \ref secret when wrapping requests in your application.
*
* 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 gateway 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 gateway (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 (Data Channels and WebSockets) are supported or not,
* and which 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
{
"version_string": "0.0.6",
"author": "Meetecho s.r.l.",
"name": "Janus WebRTC Gateway",
"version": 4,
"websockets": 1, // WebSockets are supported
"data_channels": 1, // Data Channels are supported
"rabbitmq": 1, // RabbitMQ is supported
"plugins": {
"janus.plugin.sip": { // The SIP plugin is available
"version_string": "0.0.2",
"description": "This is a simple SIP plugin for Janus, allowing WebRTC peers to register at a SIP server and call SIP user agents through the gateway.",
"author": "Meetecho s.r.l.",
"name": "JANUS SIP plugin",
"version": 2
},
"janus.plugin.videoroom": { // The Video MCU plugin is available
"version_string": "0.0.3",
"description": "This is a plugin implementing a videoconferencing MCU for Janus, something like Licode.",
"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 gateway root
* The gateway root is \c /janus by default but, as anticipated, it is
* configurable, either via command line or in the \c janus.cfg configuration.
*
* You can only contact the gateway root when you want to create a new
* session with the gateway. To do so, you need to \b POST the a \c janus "create"
* JSON message to the gateway:
*
\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 gateway 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 gateway. Specifically, the new endpoint is constructed by
* concatenating the gateway 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 max_events
* query string parameter to the GET, e.g.:
*
\verbatim
GET http://host:port/janus/<sessionid>?max_events=5
\endverbatim
*
\verbatim
[
{
// Event #1
"janus" : "event",
[..]
},
{
// Event #2
"janus" : "event",
[..]
},
[..]
]
\endverbatim
*
* This request will instruct the gateway 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 max_events 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 gateway; 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
*
* 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 gateway.
*
* 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 gateway 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.
*
* \section handles The plugin handle endpoint
* Once you've created a plugin handle, a new endpoint you can use is created
* in the gateway. Specifically, the new endpoint is constructed by
* concatenating the gateway 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
*
* If you're going to \c trickle candidates rather than including them
* all in an SDP OFFER or ANSWER, 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",
"candidate" : [
{
"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 the gateway 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 gateway 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 gateway core should do this
* automatically, but implementing the right behaviour in clients would
* help avoid potential issues nonetheless.
*
* \section secret Securing the API
* Several deployers showed an interested 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. To allow for that, Janus 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.cfg configuration (\c apisecret value in the \c general section).
* When enabled, all requests addressed to that Janus instance \b MUST