Slides for the 60 minutes workshop I presented at the virtual edition of ClueCon 2020 (ClueCon Deconstructed). The many slides cover different aspects in Janus, ranging from configuration, to plugins, how to write your own plugin, core features, recording, monitoring, and so on. Unfortunately I didn't have enough time to talk about everything, but slides should be easy to follow anyway.
How to Troubleshoot Apps for the Modern Connected Worker
Janus Workshop @ ClueCon 2020
1. 60 Minutes: An hour with Janus
Lorenzo Miniero
ClueCon – Chicago, IL, USA (kinda!)
August 4th 2020
2. Who am I?
Lorenzo Miniero
• Ph.D @ UniNA
• Chairman @ Meetecho
• Main author of Janus®
Contacts and info
• lorenzo@meetecho.com
• https://twitter.com/elminiero
• https://www.slideshare.net/LorenzoMiniero
• https://soundcloud.com/lminiero
3. Just a few words on Meetecho
• Co-founded in 2009 as an academic spin-off
• University research efforts brought to the market
• Completely independent from the University
• Focus on real-time multimedia applications
• Strong perspective on standardization and open source
• Several activities
• Consulting services
• Commercial support and Janus licenses
• Streaming of live events (IETF, ACM, etc.)
• Proudly brewed in sunny Napoli, Italy
14. What’s Janus?
Janus
General purpose, open source WebRTC server
• https://github.com/meetecho/janus-gateway
• Demos and documentation: https://janus.conf.meetecho.com
• Community: https://groups.google.com/forum/#!forum/meetecho-janus
17. Modular architecture
• The core only implements the WebRTC stack
• JSEP/SDP, ICE, DTLS-SRTP, Data Channels, Simulcast, VP9-SVC, ...
• Plugins expose Janus API over different “transports”
• Currently HTTP / WebSockets / RabbitMQ / Unix Sockets / MQTT / Nanomsg
• “Application” logic implemented in plugins too
• Users attach to plugins via the Janus core
• The core handles the WebRTC stuff
• Plugins route/manipulate the media/data
• Plugins can be combined on client side as “bricks”
• Video SFU, Audio MCU, SIP gatewaying, broadcasting, etc.
18. Modular architecture
• The core only implements the WebRTC stack
• JSEP/SDP, ICE, DTLS-SRTP, Data Channels, Simulcast, VP9-SVC, ...
• Plugins expose Janus API over different “transports”
• Currently HTTP / WebSockets / RabbitMQ / Unix Sockets / MQTT / Nanomsg
• “Application” logic implemented in plugins too
• Users attach to plugins via the Janus core
• The core handles the WebRTC stuff
• Plugins route/manipulate the media/data
• Plugins can be combined on client side as “bricks”
• Video SFU, Audio MCU, SIP gatewaying, broadcasting, etc.
19. Modular architecture
• The core only implements the WebRTC stack
• JSEP/SDP, ICE, DTLS-SRTP, Data Channels, Simulcast, VP9-SVC, ...
• Plugins expose Janus API over different “transports”
• Currently HTTP / WebSockets / RabbitMQ / Unix Sockets / MQTT / Nanomsg
• “Application” logic implemented in plugins too
• Users attach to plugins via the Janus core
• The core handles the WebRTC stuff
• Plugins route/manipulate the media/data
• Plugins can be combined on client side as “bricks”
• Video SFU, Audio MCU, SIP gatewaying, broadcasting, etc.
20. Modular architecture
• The core only implements the WebRTC stack
• JSEP/SDP, ICE, DTLS-SRTP, Data Channels, Simulcast, VP9-SVC, ...
• Plugins expose Janus API over different “transports”
• Currently HTTP / WebSockets / RabbitMQ / Unix Sockets / MQTT / Nanomsg
• “Application” logic implemented in plugins too
• Users attach to plugins via the Janus core
• The core handles the WebRTC stuff
• Plugins route/manipulate the media/data
• Plugins can be combined on client side as “bricks”
• Video SFU, Audio MCU, SIP gatewaying, broadcasting, etc.
21. Installing Janus
• Should be straightforward (not that different from other projects)
• Natively available in some repos (e.g., Debian, OpenSuse)
• We still recommend installing manually, though
• The repo README.md describes steps, for dependencies too, e.g.
# Install some dependencies from repo
apt-get install <dependencies>
# Install other dependencies manually (e.g., libnice, libsrtp, usrsctp)
# Configure and install Janus
./autogen
./configure --prefix=/opt/janus --enable-post-processing ...
make
make install
# If you need sample configuration files
make configs
22. Installing Janus
• Should be straightforward (not that different from other projects)
• Natively available in some repos (e.g., Debian, OpenSuse)
• We still recommend installing manually, though
• The repo README.md describes steps, for dependencies too, e.g.
# Install some dependencies from repo
apt-get install <dependencies>
# Install other dependencies manually (e.g., libnice, libsrtp, usrsctp)
# Configure and install Janus
./autogen
./configure --prefix=/opt/janus --enable-post-processing ...
make
make install
# If you need sample configuration files
make configs
23. Installing Janus
• Should be straightforward (not that different from other projects)
• Natively available in some repos (e.g., Debian, OpenSuse)
• We still recommend installing manually, though
• The repo README.md describes steps, for dependencies too, e.g.
# Install some dependencies from repo
apt-get install <dependencies>
# Install other dependencies manually (e.g., libnice, libsrtp, usrsctp)
# Configure and install Janus
./autogen
./configure --prefix=/opt/janus --enable-post-processing ...
make
make install
# If you need sample configuration files
make configs
24. Configuring Janus
• Janus and plugins can be configured via .jcfg files (libconfig format)
• Old INI format (.cfg) still supported, but it’s deprecated
• Some (core-only) properties can be set via command-line as well
• Format of libconfig files is quite simple to understand and use
# This is a comment
name0 = value0
category1: {
name1 = number
name2 = "string"
name3 = boolean
...
}
category2: {
name2 = [ array ]
...
}
25. Configuring Janus
• Janus and plugins can be configured via .jcfg files (libconfig format)
• Old INI format (.cfg) still supported, but it’s deprecated
• Some (core-only) properties can be set via command-line as well
• Format of libconfig files is quite simple to understand and use
# This is a comment
name0 = value0
category1: {
name1 = number
name2 = "string"
name3 = boolean
...
}
category2: {
name2 = [ array ]
...
}
26. Configuring Janus
• Janus and plugins can be configured via .jcfg files (libconfig format)
• Old INI format (.cfg) still supported, but it’s deprecated
• Some (core-only) properties can be set via command-line as well
• Format of libconfig files is quite simple to understand and use
# This is a comment
name0 = value0
category1: {
name1 = number
name2 = "string"
name3 = boolean
...
}
category2: {
name2 = [ array ]
...
}
28. A ton of scenarios done today with Janus!
• SIP and RTSP gatewaying
• WebRTC-based call/contact centers
• Conferencing & collaboration
• E-learning & webinars
• Cloud platforms
• Media production
• Broadcasting & Gaming
• Identity verification
• Internet of Things
• Augmented/Virtual Reality
• ...and more!
29. How do you talk to Janus?
https://janus.conf.meetecho.com/docs/rest
30. How do you talk to Janus?
https://janus.conf.meetecho.com/docs/rest
72. We just used it A LOT for Virtual IETF 108!
https://commcon.xyz/session/turning-live-events-to-virtual-with-janus
73. Anything wrong? Check the Admin API first!
• One option is the requests/response API to interrogate Janus
• Query server capabilities
• Control some aspects (e.g., enable/disable debugging)
• Inspect handles and WebRTC “internals”
https://www.meetecho.com/blog/understanding-the-janus-admin-api/
78. Admin API features: capturing traffic
https://www.meetecho.com/blog/capturing-webrtc-traffic-in-janus/
79. An asynchronous approach
• Admin API is cool, but is request/response...
• Needs constant polling, and data is unavailable after the session ends
• What about an asynchronous approach?
• A new mechanism: Event Handlers
• Core and plugins generate events
• Custom modules can subscribe to and handle them
• e.g., save to DB, send to external service, CDR, etc.
• Multiple handlers available out of the box
• HTTP, WebSockets, RabbitMQ, MQTT, Nanomsg
80. An asynchronous approach
• Admin API is cool, but is request/response...
• Needs constant polling, and data is unavailable after the session ends
• What about an asynchronous approach?
• A new mechanism: Event Handlers
• Core and plugins generate events
• Custom modules can subscribe to and handle them
• e.g., save to DB, send to external service, CDR, etc.
• Multiple handlers available out of the box
• HTTP, WebSockets, RabbitMQ, MQTT, Nanomsg
81. An asynchronous approach
• Admin API is cool, but is request/response...
• Needs constant polling, and data is unavailable after the session ends
• What about an asynchronous approach?
• A new mechanism: Event Handlers
• Core and plugins generate events
• Custom modules can subscribe to and handle them
• e.g., save to DB, send to external service, CDR, etc.
• Multiple handlers available out of the box
• HTTP, WebSockets, RabbitMQ, MQTT, Nanomsg
83. Type of events
• Different events handlers can subscribe to
• Core events (e.g., startup/shutdown)
• Session related events (e.g., session created/destroyed)
• Handle related events (e.g., handle attached/detached)
• JSEP related events (e.g., got/sent offer/answer)
• WebRTC related events (e.g., ICE/DTLS state changes)
• Media related events (e.g., stats on packets/bytes)
• Plugin-originated events (specific to the application)
• Transport-originated (specific to the transport)
• External events (originated via Admin API)
• Correlation possible on different identifiers
• Transport instances that originate specific session
• Opaque ID applications can set on handles of same “user”
• Plugin-specific identifiers (e.g., in VideoRoom)
84. Type of events
• Different events handlers can subscribe to
• Core events (e.g., startup/shutdown)
• Session related events (e.g., session created/destroyed)
• Handle related events (e.g., handle attached/detached)
• JSEP related events (e.g., got/sent offer/answer)
• WebRTC related events (e.g., ICE/DTLS state changes)
• Media related events (e.g., stats on packets/bytes)
• Plugin-originated events (specific to the application)
• Transport-originated (specific to the transport)
• External events (originated via Admin API)
• Correlation possible on different identifiers
• Transport instances that originate specific session
• Opaque ID applications can set on handles of same “user”
• Plugin-specific identifiers (e.g., in VideoRoom)
88. “Sample Event Handler”: HTTP as a notifier
• Simply forwards all events as JSON to an HTTP backend
• Supports basic authentication
• Can group events (i.e., JSON array vs. multiple JSON objects)
• Implements basic retransmissions (exponential back-off)
• Does nothing more than that: logic needs to be elsewhere
• HTTP backend decides what to do with events, if anything
• Behaviour can be tweaked via Admin API calls
Need something else? Check the alternatives or write your own!
A few other event handlers also available
• Other transports (in repo), SQLite (by Mozilla)
89. “Sample Event Handler”: HTTP as a notifier
• Simply forwards all events as JSON to an HTTP backend
• Supports basic authentication
• Can group events (i.e., JSON array vs. multiple JSON objects)
• Implements basic retransmissions (exponential back-off)
• Does nothing more than that: logic needs to be elsewhere
• HTTP backend decides what to do with events, if anything
• Behaviour can be tweaked via Admin API calls
Need something else? Check the alternatives or write your own!
A few other event handlers also available
• Other transports (in repo), SQLite (by Mozilla)
90. “Sample Event Handler”: HTTP as a notifier
• Simply forwards all events as JSON to an HTTP backend
• Supports basic authentication
• Can group events (i.e., JSON array vs. multiple JSON objects)
• Implements basic retransmissions (exponential back-off)
• Does nothing more than that: logic needs to be elsewhere
• HTTP backend decides what to do with events, if anything
• Behaviour can be tweaked via Admin API calls
Need something else? Check the alternatives or write your own!
A few other event handlers also available
• Other transports (in repo), SQLite (by Mozilla)
93. How can you handle events?
• Generating events is easy, evaluating them is another matter...
• Event Handlers typically just relay events, and don’t do processing themselves
• Analyzing and correlating tons of events is complicated
• A few different approaches, from easiest to trickiest
1 https://github.com/stirlab/janus-event-server (dumping events to file)
2 https://github.com/mozilla/janus-eventhandler-sqlite (dumping events to SQLite)
3 Write your own backend, e.g.,
https://www.meetecho.com/blog/event-handlers-a-practical-example/
https://www.meetecho.com/blog/correlating-janus-event-handlers/
• A much better approach: trust the smart guys!
• https://github.com/sipcapture/homer
• https://hepic.tel/
94. How can you handle events?
• Generating events is easy, evaluating them is another matter...
• Event Handlers typically just relay events, and don’t do processing themselves
• Analyzing and correlating tons of events is complicated
• A few different approaches, from easiest to trickiest
1 https://github.com/stirlab/janus-event-server (dumping events to file)
2 https://github.com/mozilla/janus-eventhandler-sqlite (dumping events to SQLite)
3 Write your own backend, e.g.,
https://www.meetecho.com/blog/event-handlers-a-practical-example/
https://www.meetecho.com/blog/correlating-janus-event-handlers/
• A much better approach: trust the smart guys!
• https://github.com/sipcapture/homer
• https://hepic.tel/
95. How can you handle events?
• Generating events is easy, evaluating them is another matter...
• Event Handlers typically just relay events, and don’t do processing themselves
• Analyzing and correlating tons of events is complicated
• A few different approaches, from easiest to trickiest
1 https://github.com/stirlab/janus-event-server (dumping events to file)
2 https://github.com/mozilla/janus-eventhandler-sqlite (dumping events to SQLite)
3 Write your own backend, e.g.,
https://www.meetecho.com/blog/event-handlers-a-practical-example/
https://www.meetecho.com/blog/correlating-janus-event-handlers/
• A much better approach: trust the smart guys!
• https://github.com/sipcapture/homer
• https://hepic.tel/
99. Writing your own plugin in C (1)
• Plugin initialization and information
• init(): called when plugin is loaded
• destroy(): called when Janus is shutting down
• get_api_compatibility(): must return JANUS_PLUGIN_API_VERSION
• get_version(): numeric version identifier (e.g., 3)
• get_version_string(): verbose version identifier (e.g., “v1.0.1”)
• get_description(): verbose description of the plugin (e.g., “This is my awesome plugin
that does this and that”)
• get_name(): short display name for your plugin (e.g., “My Awesome Plugin”)
• get_author(): author of the plugin (e.g., “Meetecho s.r.l.”)
• get_package(): unique package identifier for your plugin (e.g., “janus.plugin.myplugin”)
100. Writing your own plugin in C (2)
• Sessions management (callbacks invoked by the core)
• create_session(): a user (session+handle) just attached to the plugin
• handle_message(): incoming message/request (with or without a JSEP/SDP)
• handle_admin_message(): incoming message/request from Admin API
• setup_media(): PeerConnection is now ready to be used
• incoming_rtp(): incoming RTP packet
• incoming_rtcp(): incoming RTCP message
• incoming_data(): incoming DataChannel message
• slow_link(): notification of problems on media path
• hangup_media(): PeerConnection has been closed (e.g., DTLS alert)
• query_session(): called to get plugin-specific info on a user session
• destroy_session(): existing user gone (handle detached)
101. Writing your own plugin in C (3)
• Interaction with the core (methods invoked by the plugin)
• push_event(): send the user a JSON message/event (with or without a JSEP/SDP)
• relay_rtp(): send/relay the user an RTP packet
• relay_rtcp(): send/relay the user an RTCP message
• relay_data(): send/relay the user a DataChannel message
• close_pc(): close the user’s PeerConnection
• end_session(): close a user session (force-detach core handle)
• events_is_enabled(): check whether the event handlers mechanism is enabled
• notify_event(): notify an event to the registered and subscribed event handlers
102. Beyond C: plugins in Lua or JavaScript
https://janus.conf.meetecho.com/docs/lua
https://janus.conf.meetecho.com/docs/duktape
107. Writing your own event handler in C (1)
• Plugin initialization and information
• init(): called when event handler is loaded
• destroy(): called when Janus is shutting down
• get_api_compatibility(): must return JANUS_EVENTHANDLER_API_VERSION
• get_version(): numeric version identifier (e.g., 3)
• get_version_string(): verbose version identifier (e.g., “v1.0.1”)
• get_description(): verbose description of the plugin (e.g., “This is my awesome event
handler that does this and that”)
• get_name(): short display name for your plugin (e.g., “My Awesome Event Handler”)
• get_author(): author of the plugin (e.g., “Meetecho s.r.l.”)
• get_package(): unique package identifier for your plugin (e.g.,
“janus.eventhandler.myhandler”)
108. Writing your own event handler in C (2)
• Events management (callbacks invoked by the core)
• incoming_event(): incoming event to manage (queue and process in your thread)
• handle_request(): incoming request from Admin API to tweak the plugin
109. Thanks! Questions? Comments?
Get in touch!
• https://twitter.com/elminiero
• https://twitter.com/meetecho
• https://www.meetecho.com