Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package janus-gateway for openSUSE:Factory checked in at 2023-03-22 22:32:03 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/janus-gateway (Old) and /work/SRC/openSUSE:Factory/.janus-gateway.new.31432 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "janus-gateway" Wed Mar 22 22:32:03 2023 rev:15 rq:1073849 version:1.1.1 Changes: -------- --- /work/SRC/openSUSE:Factory/janus-gateway/janus-gateway.changes 2022-10-06 07:41:44.472625474 +0200 +++ /work/SRC/openSUSE:Factory/.janus-gateway.new.31432/janus-gateway.changes 2023-03-22 22:32:56.586887939 +0100 @@ -1,0 +2,20 @@ +Wed Dec 07 17:24:59 UTC 2022 - mich...@stroeder.com + +- Update to version 1.1.1: + * Added timing info on ICE starting and gathering done to Admin API + * Fixed rare crash when generating SDP to send [Issue-3081] + * Fixed rare crash when checking payload types (thanks @zevarito!) [PR-3086] + * Fixed double a=ssrc attribute in SDP for inactive m-line + * Replaced non-portable strcasestr() with strncasecmp() (thanks @iskraman!) [PR-3076] + * Fixed parameters not being URL-encoded when using TURN REST API [Issue-3112] + * Fixed renegotiation sent to VideoRoom subscribers when a room is destroyed [Issue-3083] + * Added option to prevent automatic SDP offer updates to VideoRoom subscribers when a publisher leaves + * Fixed "send" property not being automatically reset to "true" in the VideoRoom for new subscriptions + * Fixed small memory leak in AudioBridge (thanks @RSATom!) [PR-3088] + * Minor fixes to the Streaming plugin + * Enforced media direction policies when SIP call is on hold PR-3087] + * Added code to send PLI to SIP peer when recording [PR-3093] + * Fixed renegotiations in VideoCall not updating session properties + * Other smaller fixes and improvements + +------------------------------------------------------------------- Old: ---- janus-gateway-1.1.0.tar.xz New: ---- janus-gateway-1.1.1.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ janus-gateway.spec ++++++ --- /var/tmp/diff_new_pack.tbXorG/_old 2023-03-22 22:32:57.058890314 +0100 +++ /var/tmp/diff_new_pack.tbXorG/_new 2023-03-22 22:32:57.082890435 +0100 @@ -21,7 +21,7 @@ %endif Name: janus-gateway -Version: 1.1.0 +Version: 1.1.1 Release: 0 License: GPL-3.0-only Summary: Janus WebRTC Gateway ++++++ _service ++++++ --- /var/tmp/diff_new_pack.tbXorG/_old 2023-03-22 22:32:57.414892105 +0100 +++ /var/tmp/diff_new_pack.tbXorG/_new 2023-03-22 22:32:57.454892306 +0100 @@ -1,9 +1,9 @@ <services> <service name="tar_scm" mode="disabled"> <param name="url">https://github.com/meetecho/janus-gateway.git</param> - <param name="versionformat">1.1.0</param> + <param name="versionformat">1.1.1</param> <param name="scm">git</param> - <param name="revision">v1.1.0</param> + <param name="revision">v1.1.1</param> <param name="changesgenerate">enable</param> </service> <service name="recompress" mode="disabled"> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.tbXorG/_old 2023-03-22 22:32:57.634893212 +0100 +++ /var/tmp/diff_new_pack.tbXorG/_new 2023-03-22 22:32:57.666893373 +0100 @@ -3,6 +3,6 @@ <param name="url">git://github.com/meetecho/janus-gateway.git</param> <param name="changesrevision">21a5fc91d2c508481b9173e474a8688d615fd580</param></service><service name="tar_scm"> <param name="url">https://github.com/meetecho/janus-gateway.git</param> - <param name="changesrevision">0b5ea050d7bc5330de657e8939580f86348f4e68</param></service></servicedata> + <param name="changesrevision">0a6bd68926dae0a115e05c9e0ceddd428938396a</param></service></servicedata> (No newline at EOF) ++++++ janus-gateway-1.1.0.tar.xz -> janus-gateway-1.1.1.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/CHANGELOG.md new/janus-gateway-1.1.1/CHANGELOG.md --- old/janus-gateway-1.1.0/CHANGELOG.md 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/CHANGELOG.md 2022-12-07 17:04:11.000000000 +0100 @@ -3,6 +3,24 @@ All notable changes to this project will be documented in this file. +## [v1.1.1] - 2022-12-07 + +- Added timing info on ICE starting and gathering done to Admin API +- Fixed rare crash when generating SDP to send [[Issue-3081](https://github.com/meetecho/janus-gateway/issues/3081)] +- Fixed rare crash when checking payload types (thanks @zevarito!) [[PR-3086](3086)] +- Fixed double a=ssrc attribute in SDP for inactive m-line +- Replaced non-portable strcasestr() with strncasecmp() (thanks @iskraman!) [[PR-3076](https://github.com/meetecho/janus-gateway/pull/3076)] +- Fixed parameters not being URL-encoded when using TURN REST API [[Issue-3112](https://github.com/meetecho/janus-gateway/issues/3112)] +- Fixed renegotiation sent to VideoRoom subscribers when a room is destroyed [[Issue-3083](https://github.com/meetecho/janus-gateway/issues/3083)] +- Added option to prevent automatic SDP offer updates to VideoRoom subscribers when a publisher leaves +- Fixed "send" property not being automatically reset to "true" in the VideoRoom for new subscriptions +- Fixed small memory leak in AudioBridge (thanks @RSATom!) [[PR-3088](https://github.com/meetecho/janus-gateway/pull/3088)] +- Minor fixes to the Streaming plugin +- Enforced media direction policies when SIP call is on hold [PR-3087](https://github.com/meetecho/janus-gateway/pull/3087)] +- Added code to send PLI to SIP peer when recording [[PR-3093](https://github.com/meetecho/janus-gateway/pull/3093)] +- Fixed renegotiations in VideoCall not updating session properties +- Other smaller fixes and improvements (thanks to all who contributed pull requests and reported issues!) + ## [v1.1.0] - 2022-10-03 - Added versioning to .so files [[PR-3075](https://github.com/meetecho/janus-gateway/pull/3075)] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/bower.json new/janus-gateway-1.1.1/bower.json --- old/janus-gateway-1.1.0/bower.json 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/bower.json 2022-12-07 17:04:11.000000000 +0100 @@ -1,6 +1,6 @@ { "name": "janus-gateway", - "version": "1.1.0", + "version": "1.1.1", "homepage": "https://github.com/meetecho/janus-gateway", "authors": [ "Lorenzo Miniero <lore...@meetecho.com>", @@ -33,6 +33,6 @@ "tests" ], "dependencies": { - "webrtc-adapter": "8.1.1" + "webrtc-adapter": "8.2.0" } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/configure.ac new/janus-gateway-1.1.1/configure.ac --- old/janus-gateway-1.1.0/configure.ac 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/configure.ac 2022-12-07 17:04:11.000000000 +0100 @@ -1,4 +1,4 @@ -AC_INIT([Janus WebRTC Server],[1.1.0],[https://github.com/meetecho/janus-gateway],[janus-gateway],[https://janus.conf.meetecho.com]) +AC_INIT([Janus WebRTC Server],[1.1.1],[https://github.com/meetecho/janus-gateway],[janus-gateway],[https://janus.conf.meetecho.com]) AC_LANG(C) AC_CONFIG_AUX_DIR([.]) AC_CONFIG_MACRO_DIR([m4]) @@ -70,11 +70,11 @@ -Wunused-but-set-variable" esac -JANUS_VERSION=1100 +JANUS_VERSION=1101 AC_SUBST(JANUS_VERSION) -JANUS_VERSION_STRING="1.1.0" +JANUS_VERSION_STRING="1.1.1" AC_SUBST(JANUS_VERSION_STRING) -JANUS_VERSION_SO="1:1:0" +JANUS_VERSION_SO="1:1:1" AC_SUBST(JANUS_VERSION_SO) case "$host_os" in diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/docs/janus-doxygen.cfg new/janus-gateway-1.1.1/docs/janus-doxygen.cfg --- old/janus-gateway-1.1.0/docs/janus-doxygen.cfg 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/docs/janus-doxygen.cfg 2022-12-07 17:04:11.000000000 +0100 @@ -38,7 +38,7 @@ # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.1.0 +PROJECT_NUMBER = 1.1.1 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/html/audiobridgetest.html new/janus-gateway-1.1.1/html/audiobridgetest.html --- old/janus-gateway-1.1.0/html/audiobridgetest.html 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/html/audiobridgetest.html 2022-12-07 17:04:11.000000000 +0100 @@ -5,7 +5,7 @@ <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Janus WebRTC Server (multistream): Audio Bridge Demo</title> -<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.1.1/adapter.min.js" ></script> +<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.2.0/adapter.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/html/canvas.html new/janus-gateway-1.1.1/html/canvas.html --- old/janus-gateway-1.1.0/html/canvas.html 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/html/canvas.html 2022-12-07 17:04:11.000000000 +0100 @@ -5,7 +5,7 @@ <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Janus WebRTC Server (multistream): Canvas Capture</title> -<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.1.1/adapter.min.js" ></script> +<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.2.0/adapter.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/html/devicetest.html new/janus-gateway-1.1.1/html/devicetest.html --- old/janus-gateway-1.1.0/html/devicetest.html 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/html/devicetest.html 2022-12-07 17:04:11.000000000 +0100 @@ -5,7 +5,7 @@ <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Janus WebRTC Server (multistream): Device Selection Test</title> -<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.1.1/adapter.min.js" ></script> +<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.2.0/adapter.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/html/e2etest.html new/janus-gateway-1.1.1/html/e2etest.html --- old/janus-gateway-1.1.0/html/e2etest.html 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/html/e2etest.html 2022-12-07 17:04:11.000000000 +0100 @@ -5,7 +5,7 @@ <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Janus WebRTC Server (multistream): End-to-end Encryption Test</title> -<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.1.1/adapter.min.js" ></script> +<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.2.0/adapter.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/html/echotest.html new/janus-gateway-1.1.1/html/echotest.html --- old/janus-gateway-1.1.0/html/echotest.html 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/html/echotest.html 2022-12-07 17:04:11.000000000 +0100 @@ -5,7 +5,7 @@ <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Janus WebRTC Server (multistream): Echo Test</title> -<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.1.1/adapter.min.js" ></script> +<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.2.0/adapter.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/html/index.html new/janus-gateway-1.1.1/html/index.html --- old/janus-gateway-1.1.0/html/index.html 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/html/index.html 2022-12-07 17:04:11.000000000 +0100 @@ -34,7 +34,7 @@ <h3>Janus: the general purpose WebRTC server</h3> <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 current version of + 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> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/html/janus.js new/janus-gateway-1.1.1/html/janus.js --- old/janus-gateway-1.1.0/html/janus.js 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/html/janus.js 2022-12-07 17:04:11.000000000 +0100 @@ -1915,7 +1915,7 @@ try { pluginHandle.onremotetrack(event.track, mid, true); } catch(e) { - Janus.error(e); + Janus.error("Error calling onremotetrack", e); } if(event.track.onended) return; @@ -1925,13 +1925,14 @@ Janus.log('Remote track removed:', ev); clearTimeout(trackMutedTimeoutId); // Notify the application - let transceiver = config.pc.getTransceivers().find( - t => t.receiver.track === ev.target); + let transceivers = config.pc ? config.pc.getTransceivers() : null; + let transceiver = transceivers ? transceivers.find( + t => t.receiver.track === ev.target) : null; let mid = transceiver ? transceiver.mid : ev.target.id; try { pluginHandle.onremotetrack(ev.target, mid, false); } catch(e) { - Janus.error(e); + Janus.error("Error calling onremotetrack on removal", e); } }; event.track.onmute = function(ev) { @@ -1940,13 +1941,14 @@ trackMutedTimeoutId = setTimeout(function() { Janus.log('Removing remote track'); // Notify the application the track is gone - let transceiver = config.pc.getTransceivers().find( - t => t.receiver.track === ev.target); + let transceivers = config.pc ? config.pc.getTransceivers() : null; + let transceiver = transceivers ? transceivers.find( + t => t.receiver.track === ev.target) : null; let mid = transceiver ? transceiver.mid : ev.target.id; try { pluginHandle.onremotetrack(ev.target, mid, false); } catch(e) { - Janus.error(e); + Janus.error("Error calling onremotetrack on mute", e); } trackMutedTimeoutId = null; // Chrome seems to raise mute events only at multiples of 834ms; @@ -1962,12 +1964,13 @@ } else { try { // Notify the application the track is back - let transceiver = config.pc.getTransceivers().find( - t => t.receiver.track === ev.target); + let transceivers = config.pc ? config.pc.getTransceivers() : null; + let transceiver = transceivers ? transceivers.find( + t => t.receiver.track === ev.target) : null; let mid = transceiver ? transceiver.mid : ev.target.id; pluginHandle.onremotetrack(ev.target, mid, true); } catch(e) { - Janus.error(e); + Janus.error("Error calling onremotetrack on unmute", e); } } }; @@ -2615,7 +2618,7 @@ config.myStream.removeTrack(rt); pluginHandle.onlocaltrack(rt, false); } catch(e) { - Janus.error(e); + Janus.error("Error calling onlocaltrack on removal for renegotiation", e); } // Close the old track (unless we've been asked not to) if(rt.dontStop !== true) { @@ -2634,13 +2637,13 @@ try { pluginHandle.onlocaltrack(ev.target, false); } catch(e) { - Janus.error(e); + Janus.error("Error calling onlocaltrack following end", e); } } try { pluginHandle.onlocaltrack(nt, true); } catch(e) { - Janus.error(e); + Janus.error("Error calling onlocaltrack for track add", e); } } // Update the direction of the transceiver @@ -2737,7 +2740,7 @@ config.volume[stream] = { value: 0 }; // Start getting the volume, if audioLevel in getStats is supported (apparently // they're only available in Chrome/Safari right now: https://webrtc-stats.callstats.io/) - if(config.pc.getStats && (Janus.webRTCAdapter.browserDetails.browser === "chrome" || + if(config.pc && config.pc.getStats && (Janus.webRTCAdapter.browserDetails.browser === "chrome" || Janus.webRTCAdapter.browserDetails.browser === "safari")) { // Are we interested in a mid in particular? let query = config.pc; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/html/multiopus.html new/janus-gateway-1.1.1/html/multiopus.html --- old/janus-gateway-1.1.0/html/multiopus.html 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/html/multiopus.html 2022-12-07 17:04:11.000000000 +0100 @@ -5,7 +5,7 @@ <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Janus WebRTC Server (multistream): Multichannel Opus (surround)</title> -<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.1.1/adapter.min.js" ></script> +<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.2.0/adapter.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/html/mvideoroomtest.html new/janus-gateway-1.1.1/html/mvideoroomtest.html --- old/janus-gateway-1.1.0/html/mvideoroomtest.html 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/html/mvideoroomtest.html 2022-12-07 17:04:11.000000000 +0100 @@ -5,7 +5,7 @@ <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Janus WebRTC Server (multistream): Video Room Demo (multistream)</title> -<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.1.1/adapter.min.js" ></script> +<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.2.0/adapter.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/html/nosiptest.html new/janus-gateway-1.1.1/html/nosiptest.html --- old/janus-gateway-1.1.0/html/nosiptest.html 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/html/nosiptest.html 2022-12-07 17:04:11.000000000 +0100 @@ -5,7 +5,7 @@ <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Janus WebRTC Server (multistream): NoSIP (SDP/RTP)</title> -<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.1.1/adapter.min.js" ></script> +<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.2.0/adapter.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/html/recordplaytest.html new/janus-gateway-1.1.1/html/recordplaytest.html --- old/janus-gateway-1.1.0/html/recordplaytest.html 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/html/recordplaytest.html 2022-12-07 17:04:11.000000000 +0100 @@ -5,7 +5,7 @@ <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Janus WebRTC Server (multistream): Recorder/Playout Demo</title> -<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.1.1/adapter.min.js" ></script> +<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.2.0/adapter.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/html/screensharingtest.html new/janus-gateway-1.1.1/html/screensharingtest.html --- old/janus-gateway-1.1.0/html/screensharingtest.html 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/html/screensharingtest.html 2022-12-07 17:04:11.000000000 +0100 @@ -5,7 +5,7 @@ <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Janus WebRTC Server (multistream): Screen Sharing Demo</title> -<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.1.1/adapter.min.js" ></script> +<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.2.0/adapter.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/html/siptest.html new/janus-gateway-1.1.1/html/siptest.html --- old/janus-gateway-1.1.0/html/siptest.html 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/html/siptest.html 2022-12-07 17:04:11.000000000 +0100 @@ -5,7 +5,7 @@ <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Janus WebRTC Server (multistream): SIP Gateway Demo</title> -<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.1.1/adapter.min.js" ></script> +<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.2.0/adapter.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/html/streamingtest.html new/janus-gateway-1.1.1/html/streamingtest.html --- old/janus-gateway-1.1.0/html/streamingtest.html 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/html/streamingtest.html 2022-12-07 17:04:11.000000000 +0100 @@ -5,7 +5,7 @@ <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Janus WebRTC Server (multistream): Streaming Demo</title> -<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.1.1/adapter.min.js" ></script> +<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.2.0/adapter.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/5.4.0/bootbox.min.js"></script> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/html/streamingtest.js new/janus-gateway-1.1.1/html/streamingtest.js --- old/janus-gateway-1.1.0/html/streamingtest.js 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/html/streamingtest.js 2022-12-07 17:04:11.000000000 +0100 @@ -176,6 +176,8 @@ delete remoteTracks[mid]; return; } + if($('#remotevideo' + mid).length > 0) + return; // If we're here, a new track was added var stream = null; if(track.kind === "audio") { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/html/textroomtest.html new/janus-gateway-1.1.1/html/textroomtest.html --- old/janus-gateway-1.1.0/html/textroomtest.html 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/html/textroomtest.html 2022-12-07 17:04:11.000000000 +0100 @@ -5,7 +5,7 @@ <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Janus WebRTC Server (multistream): Text Room</title> -<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.1.1/adapter.min.js" ></script> +<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.2.0/adapter.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/html/videocalltest.html new/janus-gateway-1.1.1/html/videocalltest.html --- old/janus-gateway-1.1.0/html/videocalltest.html 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/html/videocalltest.html 2022-12-07 17:04:11.000000000 +0100 @@ -5,7 +5,7 @@ <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Janus WebRTC Server (multistream): Video Call Demo</title> -<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.1.1/adapter.min.js" ></script> +<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.2.0/adapter.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/html/videoroomtest.html new/janus-gateway-1.1.1/html/videoroomtest.html --- old/janus-gateway-1.1.0/html/videoroomtest.html 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/html/videoroomtest.html 2022-12-07 17:04:11.000000000 +0100 @@ -5,7 +5,7 @@ <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Janus WebRTC Server (multistream): Video Room Demo</title> -<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.1.1/adapter.min.js" ></script> +<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.2.0/adapter.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/html/videoroomtest.js new/janus-gateway-1.1.1/html/videoroomtest.js --- old/janus-gateway-1.1.0/html/videoroomtest.js 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/html/videoroomtest.js 2022-12-07 17:04:11.000000000 +0100 @@ -148,6 +148,7 @@ continue; var id = list[f]["id"]; var streams = list[f]["streams"]; + var display = list[f]["display"]; for(var i in streams) { var stream = streams[i]; stream["id"] = id; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/html/virtualbg.html new/janus-gateway-1.1.1/html/virtualbg.html --- old/janus-gateway-1.1.0/html/virtualbg.html 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/html/virtualbg.html 2022-12-07 17:04:11.000000000 +0100 @@ -5,7 +5,7 @@ <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Janus WebRTC Server (multistream): Virtual Background</title> -<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.1.1/adapter.min.js" ></script> +<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.2.0/adapter.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/html/voicemailtest.html new/janus-gateway-1.1.1/html/voicemailtest.html --- old/janus-gateway-1.1.0/html/voicemailtest.html 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/html/voicemailtest.html 2022-12-07 17:04:11.000000000 +0100 @@ -5,7 +5,7 @@ <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Janus WebRTC Server (multistream): Voice Mail Demo</title> -<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.1.1/adapter.min.js" ></script> +<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.2.0/adapter.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/html/vp9svctest.html new/janus-gateway-1.1.1/html/vp9svctest.html --- old/janus-gateway-1.1.0/html/vp9svctest.html 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/html/vp9svctest.html 2022-12-07 17:04:11.000000000 +0100 @@ -5,7 +5,7 @@ <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Janus WebRTC Server (multistream): VP9-SVC Video Room Demo</title> -<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.1.1/adapter.min.js" ></script> +<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.2.0/adapter.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/html/webaudio.html new/janus-gateway-1.1.1/html/webaudio.html --- old/janus-gateway-1.1.0/html/webaudio.html 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/html/webaudio.html 2022-12-07 17:04:11.000000000 +0100 @@ -5,7 +5,7 @@ <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Janus WebRTC Server (multistream): Web Audio Processing</title> -<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.1.1/adapter.min.js" ></script> +<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/8.2.0/adapter.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/package.json new/janus-gateway-1.1.1/package.json --- old/janus-gateway-1.1.0/package.json 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/package.json 2022-12-07 17:04:11.000000000 +0100 @@ -1,6 +1,6 @@ { "name": "janus-gateway", - "version": "1.1.0", + "version": "1.1.1", "description": "A javascript library for interacting with the C based Janus WebRTC Server", "main": "html/janus.js", "types": "npm/janus.d.ts", @@ -15,7 +15,7 @@ }, "homepage": "https://github.com/meetecho/janus-gateway#readme", "dependencies": { - "webrtc-adapter": "8.1.1" + "webrtc-adapter": "8.2.0" }, "devDependencies": { "eslint": "5.0.1" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/src/ice.c new/janus-gateway-1.1.1/src/ice.c --- old/janus-gateway-1.1.0/src/ice.c 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/src/ice.c 2022-12-07 17:04:11.000000000 +0100 @@ -1617,6 +1617,7 @@ return; } handle->agent_created = 0; + handle->agent_started = 0; if(handle->pc != NULL) { janus_ice_peerconnection_destroy(handle->pc); handle->pc = NULL; @@ -2027,6 +2028,7 @@ JANUS_LOG(LOG_ERR, "[%"SCNu64"] No stream %d??\n", handle->handle_id, stream_id); return; } + pc->gathered = janus_get_monotonic_time(); pc->cdone = 1; /* If we're doing full-trickle, send an event to the user too */ if(janus_full_trickle_enabled) { @@ -3946,7 +3948,10 @@ } } else { size_t midlen = strlen(mid); - if(extbufsize < (midlen + 2)) { + if(midlen > 16) { + JANUS_LOG(LOG_WARN, "[%"SCNu64"] mid too large, capping to first 16 characters...\n", handle->handle_id); + midlen = 16; + } else if(extbufsize < (midlen + 2)) { JANUS_LOG(LOG_WARN, "[%"SCNu64"] Not enough room for mid extension, skipping it...\n", handle->handle_id); } else { *index = handle->pc->mid_ext_id; @@ -4371,6 +4376,8 @@ } guint count = g_slist_length(candidates); if(pc != NULL && count > 0) { + if(handle->agent_started == 0) + handle->agent_started = janus_get_monotonic_time(); int added = nice_agent_set_remote_candidates(handle->agent, pc->stream_id, pc->component_id, candidates); if(added < 0 || (guint)added != count) { JANUS_LOG(LOG_WARN, "[%"SCNu64"] Failed to add some remote candidates (added %u, expected %u)\n", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/src/ice.h new/janus-gateway-1.1.1/src/ice.h --- old/janus-gateway-1.1.0/src/ice.h 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/src/ice.h 2022-12-07 17:04:11.000000000 +0100 @@ -362,6 +362,8 @@ NiceAgent *agent; /*! \brief Monotonic time of when the ICE agent has been created */ gint64 agent_created; + /*! \brief Monotonic time of when the ICE agent has been started (remote credentials set) */ + gint64 agent_started; /*! \brief ICE role (controlling or controlled) */ gboolean controlling; /*! \brief Main mid */ @@ -416,6 +418,8 @@ gint cdone:1; /*! \brief libnice ICE component state */ guint state; + /*! \brief Monotonic time of when gathering has completed */ + gint64 gathered; /*! \brief Monotonic time of when ICE has successfully connected */ gint64 connected; /*! \brief GLib list of libnice remote candidates for this component */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/src/janus.c new/janus-gateway-1.1.1/src/janus.c --- old/janus-gateway-1.1.0/src/janus.c 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/src/janus.c 2022-12-07 17:04:11.000000000 +0100 @@ -2992,6 +2992,8 @@ json_object_set_new(info, "flags", flags); if(handle->agent) { json_object_set_new(info, "agent-created", json_integer(handle->agent_created)); + if(handle->agent_started > 0) + json_object_set_new(info, "agent-started", json_integer(handle->agent_started)); json_object_set_new(info, "ice-mode", json_string(janus_ice_is_ice_lite_enabled() ? "lite" : "full")); json_object_set_new(info, "ice-role", json_string(handle->controlling ? "controlling" : "controlled")); } @@ -3099,6 +3101,8 @@ json_object_set_new(i, "failed-detected", json_integer(pc->icefailed_detected)); json_object_set_new(i, "icetimer-started", pc->icestate_source ? json_true() : json_false()); } + if(pc->gathered > 0) + json_object_set_new(i, "gathered", json_integer(pc->gathered)); if(pc->connected > 0) json_object_set_new(i, "connected", json_integer(pc->connected)); if(pc->local_candidates) { @@ -3830,12 +3834,12 @@ janus_sdp_destroy(parsed_sdp); return NULL; } - if(medium->msid == NULL || strcasecmp(medium->msid, msid)) { + if(medium != NULL && (medium->msid == NULL || strcasecmp(medium->msid, msid))) { char *old_msid = medium->msid; medium->msid = g_strdup(msid); g_free(old_msid); } - if(medium->mstid == NULL || strcasecmp(medium->mstid, mstid)) { + if(medium != NULL && (medium->mstid == NULL || strcasecmp(medium->mstid, mstid))) { char *old_mstid = medium->mstid; medium->mstid = g_strdup(mstid); g_free(old_mstid); @@ -3868,7 +3872,7 @@ /* If the user offered RED but the plugin rejected it, disable it */ if(opusred_pt < 0 && medium != NULL && medium->opusred_pt > 0) medium->opusred_pt = 0; - if(!have_msid) { + if(!have_msid && medium != NULL) { g_free(medium->msid); medium->msid = NULL; g_free(medium->mstid); @@ -3971,10 +3975,12 @@ medium = g_hash_table_lookup(pc->media, GUINT_TO_POINTER(mi)); if(medium && medium->type != JANUS_MEDIA_DATA) { janus_sdp_mline *m = janus_sdp_mline_find_by_index(parsed_sdp, medium->mindex); - GList *tpt = m->ptypes; - while(tpt) { - g_hash_table_insert(pc->payload_types, tpt->data, tpt->data); - tpt = tpt->next; + if(m && m->ptypes) { + GList *tpt = m->ptypes; + while(tpt) { + g_hash_table_insert(pc->payload_types, tpt->data, tpt->data); + tpt = tpt->next; + } } } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/src/mainpage.dox new/janus-gateway-1.1.1/src/mainpage.dox --- old/janus-gateway-1.1.0/src/mainpage.dox 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/src/mainpage.dox 2022-12-07 17:04:11.000000000 +0100 @@ -3,7 +3,7 @@ * * <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 current version of + * 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> @@ -4058,7 +4058,9 @@ * - 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>. \n\n + * - 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. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/src/plugins/janus_audiobridge.c new/janus-gateway-1.1.1/src/plugins/janus_audiobridge.c --- old/janus-gateway-1.1.0/src/plugins/janus_audiobridge.c 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/src/plugins/janus_audiobridge.c 2022-12-07 17:04:11.000000000 +0100 @@ -2718,14 +2718,14 @@ /* Finally, let's check if IPv6 is disabled, as we may need to know for forwarders */ int fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); - if(fd <= 0) { + if(fd < 0) { ipv6_disabled = TRUE; } else { int v6only = 0; if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only)) != 0) ipv6_disabled = TRUE; } - if(fd > 0) + if(fd >= 0) close(fd); if(ipv6_disabled) { JANUS_LOG(LOG_WARN, "IPv6 disabled, will only create VideoRoom forwarders to IPv4 addresses\n"); @@ -8617,6 +8617,8 @@ janus_audiobridge_relay_rtp_packet(participant->session, outpkt); } } + } + if(mixedpkt) { g_free(mixedpkt->data); g_free(mixedpkt); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/src/plugins/janus_sip.c new/janus-gateway-1.1.1/src/plugins/janus_sip.c --- old/janus-gateway-1.1.0/src/plugins/janus_sip.c 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/src/plugins/janus_sip.c 2022-12-07 17:04:11.000000000 +0100 @@ -531,6 +531,7 @@ "video" : <true|false; whether or not our video should be recorded>, "peer_audio" : <true|false; whether or not our peer's audio should be recorded>, "peer_video" : <true|false; whether or not our peer's video should be recorded>, + "send_peer_pli" : <true|false; whether or not send PLI to request keyframe from peer>, "filename" : "<base path/filename to use for all the recordings>" } \endverbatim @@ -825,6 +826,7 @@ {"video", JANUS_JSON_BOOL, 0}, {"peer_audio", JANUS_JSON_BOOL, 0}, {"peer_video", JANUS_JSON_BOOL, 0}, + {"send_peer_pli", JANUS_JSON_BOOL, 0}, {"filename", JSON_STRING, 0} }; static struct janus_json_parameter dtmf_info_parameters[] = { @@ -1020,8 +1022,8 @@ srtp_t audio_srtp_in, audio_srtp_out; srtp_policy_t audio_remote_policy, audio_local_policy; char *audio_srtp_local_profile, *audio_srtp_local_crypto; - gboolean audio_send; - janus_sdp_mdirection pre_hold_audio_dir; + gboolean audio_send, audio_recv; + janus_sdp_mdirection hold_audio_dir, pre_hold_audio_dir; gboolean has_video; int video_rtp_fd, video_rtcp_fd; int local_video_rtp_port, remote_video_rtp_port; @@ -1034,8 +1036,9 @@ srtp_t video_srtp_in, video_srtp_out; srtp_policy_t video_remote_policy, video_local_policy; char *video_srtp_local_profile, *video_srtp_local_crypto; - gboolean video_send; - janus_sdp_mdirection pre_hold_video_dir; + gboolean video_send, video_recv; + gboolean video_pli_supported; + janus_sdp_mdirection hold_video_dir, pre_hold_video_dir; janus_rtp_switching_context acontext, vcontext; int pipefd[2]; gboolean updated; @@ -1086,6 +1089,7 @@ static void janus_sip_srtp_cleanup(janus_sip_session *session); static void janus_sip_media_reset(janus_sip_session *session); +static void janus_sip_rtcp_pli_send(janus_sip_session *session); static void janus_sip_call_update_status(janus_sip_session *session, janus_sip_call_status new_status) { if(session->status != new_status) { @@ -1477,11 +1481,16 @@ session->media.opusred_pt = -1; session->media.audio_pt_name = NULL; /* Immutable string, no need to free*/ session->media.audio_send = TRUE; + session->media.audio_recv = TRUE; + session->media.hold_audio_dir = JANUS_SDP_SENDONLY; session->media.pre_hold_audio_dir = JANUS_SDP_DEFAULT; session->media.has_video = FALSE; session->media.video_pt = -1; session->media.video_pt_name = NULL; /* Immutable string, no need to free*/ session->media.video_send = TRUE; + session->media.video_recv = TRUE; + session->media.video_pli_supported = FALSE; + session->media.hold_video_dir = JANUS_SDP_SENDONLY; session->media.pre_hold_video_dir = JANUS_SDP_DEFAULT; session->media.video_orientation_extension_id = -1; session->media.audio_level_extension_id = -1; @@ -2164,6 +2173,8 @@ session->media.opusred_pt = -1; session->media.audio_pt_name = NULL; session->media.audio_send = TRUE; + session->media.audio_recv = TRUE; + session->media.hold_audio_dir = JANUS_SDP_SENDONLY; session->media.pre_hold_audio_dir = JANUS_SDP_DEFAULT; session->media.has_video = FALSE; session->media.video_rtp_fd = -1; @@ -2177,7 +2188,9 @@ session->media.simulcast_ssrc = 0; session->media.video_pt = -1; session->media.video_pt_name = NULL; - session->media.video_send = TRUE; + session->media.video_recv = TRUE; + session->media.video_pli_supported = FALSE; + session->media.hold_video_dir = JANUS_SDP_SENDONLY; session->media.pre_hold_video_dir = JANUS_SDP_DEFAULT; session->media.video_orientation_extension_id = -1; session->media.audio_level_extension_id = -1; @@ -2409,6 +2422,10 @@ /* Dropping video packet, peer doesn't want to receive it */ return; } + if(session->media.on_hold && session->media.hold_video_dir != JANUS_SDP_SENDONLY) { + /* Dropping video packet, the call is on hold and we're not sending anything */ + return; + } if(session->media.simulcast_ssrc) { /* The user is simulcasting: drop everything except the base layer */ janus_rtp_header *header = (janus_rtp_header *)buf; @@ -2464,6 +2481,10 @@ /* Dropping audio packet, peer doesn't want to receive it */ return; } + if(session->media.on_hold && session->media.hold_audio_dir != JANUS_SDP_SENDONLY) { + /* Dropping audio packet, the call is on hold and we're not sending anything */ + return; + } if(session->media.audio_ssrc == 0) { janus_rtp_header *header = (janus_rtp_header *)buf; session->media.audio_ssrc = ntohl(header->ssrc); @@ -4359,6 +4380,7 @@ if(m) { if(hold) { /* Take note of the original media direction */ + session->media.hold_audio_dir = hold_dir; session->media.pre_hold_audio_dir = m->direction; if(m->direction != hold_dir) { /* Update the media direction */ @@ -4380,6 +4402,7 @@ if(m) { if(hold) { /* Take note of the original media direction */ + session->media.hold_video_dir = hold_dir; session->media.pre_hold_video_dir = m->direction; if(m->direction != hold_dir) { /* Update the media direction */ @@ -4480,7 +4503,7 @@ goto error; } gboolean record_audio = FALSE, record_video = FALSE, /* No media is recorded by default */ - record_peer_audio = FALSE, record_peer_video = FALSE; + record_peer_audio = FALSE, record_peer_video = FALSE, send_peer_pli = FALSE; json_t *audio = json_object_get(root, "audio"); record_audio = audio ? json_is_true(audio) : FALSE; json_t *video = json_object_get(root, "video"); @@ -4489,6 +4512,8 @@ record_peer_audio = peer_audio ? json_is_true(peer_audio) : FALSE; json_t *peer_video = json_object_get(root, "peer_video"); record_peer_video = peer_video ? json_is_true(peer_video) : FALSE; + json_t *peer_pli = json_object_get(root, "send_peer_pli"); + send_peer_pli = peer_pli ? json_is_true(peer_pli) : FALSE; if(!record_audio && !record_video && !record_peer_audio && !record_peer_video) { JANUS_LOG(LOG_ERR, "Invalid request (at least one of audio, video, peer_audio and peer_video should be true)\n"); error_code = JANUS_SIP_ERROR_RECORDING_ERROR; @@ -4553,7 +4578,9 @@ /* If the video-orientation extension has been negotiated, mark it in the recording */ if(session->media.video_orientation_extension_id > 0) janus_recorder_add_extmap(session->vrc_peer, session->media.video_orientation_extension_id, JANUS_RTP_EXTMAP_VIDEO_ORIENTATION); - /* TODO We should send a FIR/PLI to this peer... */ + /* If we detected PLI support in the remote SDP, craft and send a PLI to the peer */ + if(session->media.video_pli_supported || send_peer_pli) + janus_sip_rtcp_pli_send(session); if(rc == NULL) { /* FIXME We should notify the fact the recorder could not be created */ JANUS_LOG(LOG_ERR, "Couldn't open an video recording file for this peer!\n"); @@ -6228,7 +6255,8 @@ JANUS_LOG(LOG_WARN, "[%s] SUBSCRIBE failed: %d %s\n", session->account.username, status, phrase ? phrase : ""); json_t *event = json_object(); json_object_set_new(event, "sip", json_string("event")); - json_object_set_new(event, "call_id", json_string(sip->sip_call_id->i_id)); + if(sip->sip_call_id) + json_object_set_new(event, "call_id", json_string(sip->sip_call_id->i_id)); json_t *result = json_object(); json_object_set_new(result, "event", json_string("subscribe_failed")); json_object_set_new(result, "code", json_integer(status)); @@ -6298,8 +6326,13 @@ session->media.audio_send = FALSE; else session->media.audio_send = TRUE; + if(m->direction == JANUS_SDP_RECVONLY || m->direction == JANUS_SDP_INACTIVE) + session->media.audio_recv = FALSE; + else + session->media.audio_recv = TRUE; } else { session->media.audio_send = FALSE; + session->media.audio_recv = FALSE; } } else if(m->type == JANUS_SDP_VIDEO) { if(m->port) { @@ -6315,8 +6348,13 @@ session->media.video_send = FALSE; else session->media.video_send = TRUE; + if(m->direction == JANUS_SDP_RECVONLY || m->direction == JANUS_SDP_INACTIVE) + session->media.video_recv = FALSE; + else + session->media.video_recv = TRUE; } else { session->media.video_send = FALSE; + session->media.video_recv = FALSE; } } else { JANUS_LOG(LOG_WARN, "Unsupported media line (not audio/video)\n"); @@ -6380,6 +6418,9 @@ } } } + } else if(m->type == JANUS_SDP_VIDEO && !strcasecmp(a->name, "rtcp-fb") && a->value) { + if(strstr(a->value, " pli")) + session->media.video_pli_supported = TRUE; } } tempA = tempA->next; @@ -6870,10 +6911,14 @@ } /* In case we're on hold (remote address is 0.0.0.0) set the send properties to FALSE */ - if(have_audio_server_ip && !strcmp(session->media.remote_audio_ip, "0.0.0.0")) + if(have_audio_server_ip && !strcmp(session->media.remote_audio_ip, "0.0.0.0")) { session->media.audio_send = FALSE; - if(have_video_server_ip && !strcmp(session->media.remote_video_ip, "0.0.0.0")) + session->media.audio_recv = FALSE; + } + if(have_video_server_ip && !strcmp(session->media.remote_video_ip, "0.0.0.0")) { session->media.video_send = FALSE; + session->media.video_recv = FALSE; + } } /* Prepare poll */ @@ -6991,6 +7036,14 @@ continue; } pollerrs = 0; + if(!session->media.audio_recv) { + /* Dropping audio packet, we weren't expecting anything */ + continue; + } + if(session->media.on_hold && session->media.hold_audio_dir != JANUS_SDP_RECVONLY) { + /* Dropping video packet, the call is on hold and we're not receiving anything */ + continue; + } janus_rtp_header *header = (janus_rtp_header *)buffer; if(session->media.audio_ssrc_peer == 0) { session->media.audio_ssrc_peer = ntohl(header->ssrc); @@ -7038,6 +7091,14 @@ continue; } pollerrs = 0; + if(!session->media.video_recv) { + /* Dropping video packet, we weren't expecting anything */ + continue; + } + if(session->media.on_hold && session->media.hold_video_dir != JANUS_SDP_RECVONLY) { + /* Dropping video packet, the call is on hold and we're not receiving anything */ + continue; + } /* Is this SRTCP? */ if(session->media.has_srtp_remote_audio) { int buflen = bytes; @@ -7235,3 +7296,46 @@ g_thread_unref(g_thread_self()); return NULL; } + +/* Helper method to send an RTCP PLI to the SIP peer */ +static void janus_sip_rtcp_pli_send(janus_sip_session *session) { + if(!session || g_atomic_int_get(&session->destroyed)) { + JANUS_LOG(LOG_ERR, "No session associated with this handle...\n"); + return; + } + if(!janus_sip_call_is_established(session)) + return; + if(!session->media.has_video || session->media.video_rtcp_fd == -1) + return; + /* Generate a PLI */ + char rtcp_buf[12]; + int rtcp_len = 12; + janus_rtcp_pli((char *)&rtcp_buf, rtcp_len); + /* Fix SSRCs as the Janus core does */ + JANUS_LOG(LOG_HUGE, "[SIP] Fixing SSRCs (local %u, peer %u)\n", + session->media.video_ssrc, session->media.video_ssrc_peer); + janus_rtcp_fix_ssrc(NULL, (char *)rtcp_buf, rtcp_len, 1, session->media.video_ssrc, session->media.video_ssrc_peer); + /* Is SRTP involved? */ + if(session->media.has_srtp_local_video) { + char sbuf[50]; + memcpy(&sbuf, rtcp_buf, rtcp_len); + int protected = rtcp_len; + int res = srtp_protect_rtcp(session->media.video_srtp_out, &sbuf, &protected); + if(res != srtp_err_status_ok) { + JANUS_LOG(LOG_ERR, "[SIP-%s] Video SRTCP protect error... %s (len=%d-->%d)...\n", + session->account.username, janus_srtp_error_str(res), rtcp_len, protected); + } else { + /* Forward the message to the peer */ + if(send(session->media.video_rtcp_fd, sbuf, protected, 0) < 0) { + JANUS_LOG(LOG_HUGE, "[SIP-%s] Error sending SRTCP video packet... %s (len=%d)...\n", + session->account.username, g_strerror(errno), protected); + } + } + } else { + /* Forward the message to the peer */ + if(send(session->media.video_rtcp_fd, rtcp_buf, rtcp_len, 0) < 0) { + JANUS_LOG(LOG_HUGE, "[SIP-%s] Error sending RTCP video packet... %s (len=%d)...\n", + session->account.username, g_strerror(errno), rtcp_len); + } + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/src/plugins/janus_streaming.c new/janus-gateway-1.1.1/src/plugins/janus_streaming.c --- old/janus-gateway-1.1.0/src/plugins/janus_streaming.c 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/src/plugins/janus_streaming.c 2022-12-07 17:04:11.000000000 +0100 @@ -5820,11 +5820,11 @@ } /* New viewer: we send an offer ourselves */ JANUS_LOG(LOG_VERB, "Request to watch mountpoint/stream %s\n", id_value_str); - if(session->mountpoint != NULL || g_list_find(mp->viewers, session) != NULL) { + if(g_list_find(mp->viewers, session) != NULL) { janus_mutex_unlock(&session->mutex); janus_mutex_unlock(&mp->mutex); janus_refcount_decrease(&mp->ref); - JANUS_LOG(LOG_ERR, "Already watching a stream...\n"); + JANUS_LOG(LOG_ERR, "Already watching a stream (found %p in %s's viewers)...\n", session, id_value_str); error_code = JANUS_STREAMING_ERROR_UNKNOWN_ERROR; g_snprintf(error_cause, 512, "Already watching a stream"); goto error; @@ -7488,13 +7488,15 @@ /* Possibly a quirk in the RTSP server, where the DESCRIBE request expects a path only. */ CURLU *curl_u = curl_url(); char *path = NULL; - if(!(curl_url_set(curl_u, CURLUPART_URL, source->rtsp_url, 0))) { + if(curl_u && !(curl_url_set(curl_u, CURLUPART_URL, source->rtsp_url, 0))) { if(!(curl_url_get(curl_u, CURLUPART_PATH, &path, 0))) { curl_easy_setopt(curl, CURLOPT_RTSP_STREAM_URI, path); - curl_easy_perform(curl); - res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); - if((res == CURLE_OK) && (code != 404)) { - source->rtsp_stream_uri = g_strdup(path); + res = curl_easy_perform(curl); + if(res == CURLE_OK) { + res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); + if((res == CURLE_OK) && (code != 404)) { + source->rtsp_stream_uri = g_strdup(path); + } } curl_free(path); } @@ -9737,6 +9739,9 @@ copy->ssrc[2] = packet->ssrc[2]; copy->codec = packet->codec; copy->substream = packet->substream; + copy->svc = packet->svc; + if(copy->svc) + copy->svc_info = packet->svc_info; copy->ptype = packet->ptype; copy->timestamp = packet->timestamp; copy->seq_number = packet->seq_number; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/src/plugins/janus_videocall.c new/janus-gateway-1.1.1/src/plugins/janus_videocall.c --- old/janus-gateway-1.1.0/src/plugins/janus_videocall.c 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/src/plugins/janus_videocall.c 2022-12-07 17:04:11.000000000 +0100 @@ -1386,8 +1386,14 @@ janus_sdp_find_first_codec(answer, JANUS_SDP_VIDEO, -1, &vcodec); session->vcodec = janus_videocodec_from_name(vcodec); session->opusred_pt = janus_sdp_get_opusred_pt(answer, -1); - if(peer) + if(peer) { + peer->has_audio = session->has_audio; + peer->has_video = session->has_video; + peer->has_data = session->has_data; + peer->acodec = session->acodec; + peer->vcodec = session->vcodec; peer->opusred_pt = session->opusred_pt; + } if(session->acodec == JANUS_AUDIOCODEC_NONE) { session->has_audio = FALSE; if(peer) @@ -1491,6 +1497,8 @@ gateway->send_remb(session->handle, session->bitrate ? session->bitrate : 10000000); } janus_videocall_session *peer = session->peer; + if(peer) + janus_refcount_increase(&peer->ref); if(fallback) { JANUS_LOG(LOG_VERB, "Setting fallback timer (simulcast): %lld (was %"SCNu32")\n", json_integer_value(fallback) ? json_integer_value(fallback) : 250000, @@ -1543,12 +1551,62 @@ gateway->send_pli(peer->handle); } } - if(record) { - if(msg_sdp) { - session->has_audio = (strstr(msg_sdp, "m=audio") != NULL); - session->has_video = (strstr(msg_sdp, "m=video") != NULL); - session->has_data = (strstr(msg_sdp, "DTLS/SCTP") != NULL); + if(msg_sdp && msg_sdp_type && !strcasecmp(msg_sdp_type, "answer")) { + /* Process the answer to see if there were any changes */ + char error_str[512]; + janus_sdp *answer = janus_sdp_parse(msg_sdp, error_str, sizeof(error_str)); + if(answer == NULL) { + if(peer) + janus_refcount_decrease(&peer->ref); + JANUS_LOG(LOG_ERR, "Error parsing answer: %s\n", error_str); + error_code = JANUS_VIDEOCALL_ERROR_INVALID_SDP; + g_snprintf(error_cause, 512, "Error parsing answer: %s", error_str); + goto error; + } + JANUS_LOG(LOG_VERB, "%s is accepting an update from %s\n", session->username, peer->username); + session->has_audio = (strstr(msg_sdp, "m=audio") != NULL); + session->has_video = (strstr(msg_sdp, "m=video") != NULL); + session->has_data = (strstr(msg_sdp, "DTLS/SCTP") != NULL); + /* Check if this user will simulcast */ + json_t *msg_simulcast = json_object_get(msg->jsep, "simulcast"); + if(msg_simulcast && janus_get_codec_pt(msg_sdp, "vp8") > 0) { + JANUS_LOG(LOG_VERB, "VideoCall callee (%s) cannot do simulcast.\n", session->username); + } else { + janus_rtp_simulcasting_cleanup(NULL, session->ssrc, session->rid, &session->rid_mutex); + } + /* Check which codecs we ended up using */ + const char *acodec = NULL, *vcodec = NULL; + janus_sdp_find_first_codec(answer, JANUS_SDP_AUDIO, -1, &acodec); + session->acodec = janus_audiocodec_from_name(acodec); + janus_sdp_find_first_codec(answer, JANUS_SDP_VIDEO, -1, &vcodec); + session->vcodec = janus_videocodec_from_name(vcodec); + session->opusred_pt = janus_sdp_get_opusred_pt(answer, -1); + janus_videocall_session *peer = session->peer; + if(peer) { + peer->has_audio = session->has_audio; + peer->has_video = session->has_video; + peer->has_data = session->has_data; + peer->acodec = session->acodec; + peer->vcodec = session->vcodec; + peer->opusred_pt = session->opusred_pt; + } + if(session->acodec == JANUS_AUDIOCODEC_NONE) { + session->has_audio = FALSE; + if(peer) + peer->has_audio = FALSE; + } else if(peer) { + peer->acodec = session->acodec; + } + if(session->vcodec == JANUS_VIDEOCODEC_NONE) { + session->has_video = FALSE; + if(peer) + peer->has_video = FALSE; + } else if(peer) { + peer->vcodec = session->vcodec; } + janus_sdp_destroy(answer); + } + if(record) { gboolean recording = json_is_true(record); const char *recording_base = json_string_value(recfile); JANUS_LOG(LOG_VERB, "Recording %s (base filename: %s)\n", recording ? "enabled" : "disabled", recording_base ? recording_base : "not provided"); @@ -1694,6 +1752,8 @@ json_decref(event); json_decref(jsep); } + if(peer) + janus_refcount_decrease(&peer->ref); } else if(!strcasecmp(request_text, "hangup")) { json_t *hangup = json_object_get(root, "reason"); if(hangup && !json_is_string(hangup)) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/src/plugins/janus_videoroom.c new/janus-gateway-1.1.1/src/plugins/janus_videoroom.c --- old/janus-gateway-1.1.0/src/plugins/janus_videoroom.c 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/src/plugins/janus_videoroom.c 2022-12-07 17:04:11.000000000 +0100 @@ -1048,6 +1048,7 @@ "ptype" : "subscriber", "room" : <unique ID of the room to subscribe in>, "use_msid" : <whether subscriptions should include an msid that references the publisher; false by default>, + "autoupdate" : <whether a new SDP offer is sent automatically when a subscribed publisher leaves; true by default>, "private_id" : <unique ID of the publisher that originated this request; optional, unless mandated by the room configuration>, "streams" : [ { @@ -1178,7 +1179,7 @@ "feed" : <unique ID of publisher owning the new stream to subscribe to>, "mid" : "<unique mid of the publisher stream to subscribe to; optional>" "crossrefid" : "<id to map this subscription with entries in streams list; optional>" - // Optionally, simulcast or SVC targets (defaults if missing) + // Optionally, send, simulcast or SVC targets (defaults if missing) }, // Other new streams to subscribe to ] @@ -1282,7 +1283,7 @@ "feed" : <unique ID of publisher owning the new stream to subscribe to>, "mid" : "<unique mid of the publisher stream to subscribe to; optional>" "crossrefid" : "<id to map this subscription with entries in streams list; optional>" - // Optionally, simulcast or SVC targets (defaults if missing) + // Optionally, send, simulcast or SVC targets (defaults if missing) }, // Other new streams to subscribe to ], @@ -1827,7 +1828,7 @@ static struct janus_json_parameter subscriber_parameters[] = { {"streams", JANUS_JSON_ARRAY, 0}, {"private_id", JSON_INTEGER, JANUS_JSON_PARAM_POSITIVE}, - {"close_pc", JANUS_JSON_BOOL, 0}, + {"autoupdate", JANUS_JSON_BOOL, 0}, /* All the following parameters are deprecated: use streams instead */ {"audio", JANUS_JSON_BOOL, 0}, {"video", JANUS_JSON_BOOL, 0}, @@ -1846,6 +1847,7 @@ static struct janus_json_parameter subscriber_stream_parameters[] = { {"mid", JANUS_JSON_STRING, 0}, {"crossrefid", JANUS_JSON_STRING, 0}, + {"send", JANUS_JSON_BOOL, 0}, /* For VP8 (or H.264) simulcast */ {"substream", JSON_INTEGER, JANUS_JSON_PARAM_POSITIVE}, {"temporal", JSON_INTEGER, JANUS_JSON_PARAM_POSITIVE}, @@ -2283,12 +2285,12 @@ GHashTable *streams_bymid; /* As above, indexed by mid */ janus_mutex streams_mutex; gboolean use_msid; /* Whether we should add custom msid attributes to offers, to match publishers and streams */ - gboolean close_pc; /* Whether we should automatically close the PeerConnection when the publisher goes away */ + gboolean autoupdate; /* Whether we should trigger a renegotiation automatically when a subscribed publisher goes away */ guint32 pvt_id; /* Private ID of the participant that is subscribing (if available/provided) */ gboolean paused; gboolean kicked; /* Whether this subscription belongs to a participant that has been kicked */ gboolean e2ee; /* If media for this subscriber is end-to-end encrypted */ - volatile gint answered, pending_offer, pending_restart; + volatile gint answered, pending_offer, pending_restart, skipped_autoupdate; volatile gint destroyed; janus_refcount ref; } janus_videoroom_subscriber; @@ -3265,6 +3267,7 @@ stream->msid = g_strdup(ps->publisher->user_id_str); g_free(msid); } + stream->send = TRUE; janus_rtp_simulcasting_context_reset(&stream->sim_context); if(ps->simulcast) { stream->sim_context.rid_ext_id = ps->rid_extmap_id; @@ -3923,14 +3926,14 @@ /* Finally, let's check if IPv6 is disabled, as we may need to know for forwarders */ int fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); - if(fd <= 0) { + if(fd < 0) { ipv6_disabled = TRUE; } else { int v6only = 0; if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only)) != 0) ipv6_disabled = TRUE; } - if(fd > 0) + if(fd >= 0) close(fd); if(ipv6_disabled) { JANUS_LOG(LOG_WARN, "IPv6 disabled, will only create VideoRoom forwarders to IPv4 addresses\n"); @@ -6808,10 +6811,10 @@ janus_mutex_unlock(&rooms_mutex); janus_mutex_lock(&videoroom->mutex); /* Set recording status */ - gboolean room_prev_recording_active = recording_active; - if (room_prev_recording_active != videoroom->record) { + gboolean room_new_recording_active = recording_active; + if (room_new_recording_active != videoroom->record) { /* Room recording state has changed */ - videoroom->record = room_prev_recording_active; + videoroom->record = room_new_recording_active; /* Iterate over all participants */ gpointer value; GHashTableIter iter; @@ -8922,12 +8925,22 @@ temp = temp->next; } /* Any subscriber session to update? */ + janus_videoroom *room = participant->room; if(subscribers != NULL) { temp = subscribers; while(temp) { janus_videoroom_subscriber *subscriber = (janus_videoroom_subscriber *)temp->data; /* Send (or schedule) a new offer */ janus_mutex_lock(&subscriber->streams_mutex); + if(!subscriber->autoupdate || room == NULL || g_atomic_int_get(&room->destroyed)) { + /* ... unless we've been asked not to, or there's no room (anymore) */ + g_atomic_int_set(&subscriber->skipped_autoupdate, 1); + janus_mutex_unlock(&subscriber->streams_mutex); + janus_refcount_decrease(&subscriber->session->ref); + janus_refcount_decrease(&subscriber->ref); + temp = temp->next; + continue; + } if(!g_atomic_int_get(&subscriber->answered)) { /* We're still waiting for an answer to a previous offer, postpone this */ g_atomic_int_set(&subscriber->pending_offer, 1); @@ -9608,8 +9621,8 @@ } json_t *msid = json_object_get(root, "use_msid"); gboolean use_msid = json_is_true(msid); - json_t *cpc = json_object_get(root, "close_pc"); - gboolean close_pc = cpc ? json_is_true(cpc) : TRUE; + json_t *au = json_object_get(root, "autoupdate"); + gboolean autoupdate = au ? json_is_true(au) : TRUE; /* Make sure all the feeds we're subscribing to exist */ GList *publishers = NULL; size_t i = 0; @@ -9777,7 +9790,7 @@ videoroom = NULL; subscriber->pvt_id = pvt_id; subscriber->use_msid = use_msid; - subscriber->close_pc = close_pc; + subscriber->autoupdate = autoupdate; subscriber->paused = TRUE; /* We need an explicit start from the stream */ subscriber->streams_byid = g_hash_table_new_full(NULL, NULL, NULL, (GDestroyNotify)janus_videoroom_subscriber_stream_destroy); @@ -10818,6 +10831,7 @@ /* Are we subscribing to this publisher as a whole or only to a single stream? */ const char *mid = json_string_value(json_object_get(s, "mid")); const char *crossrefid = json_string_value(json_object_get(s, "crossrefid")); + json_t *send = json_object_get(s, "send"); json_t *spatial = json_object_get(s, "spatial_layer"); json_t *sc_substream = json_object_get(s, "substream"); json_t *temporal = json_object_get(s, "temporal_layer"); @@ -10840,6 +10854,15 @@ janus_videoroom_subscriber_stream *stream = janus_videoroom_subscriber_stream_add_or_replace(subscriber, ps, crossrefid); if(stream) { changes++; + if(send) { + gboolean oldsend = stream->send; + gboolean newsend = json_is_true(send); + if(!oldsend && newsend) { + /* Medium just resumed, reset the RTP sequence numbers */ + stream->context.seq_reset = TRUE; + } + stream->send = json_is_true(send); + } if(ps->type == JANUS_VIDEOROOM_MEDIA_VIDEO && (spatial || sc_substream || temporal || sc_temporal)) { /* Override the default spatial/substream/temporal targets */ @@ -10942,6 +10965,8 @@ } } /* We're done: check if this resulted in any actual change */ + if(g_atomic_int_compare_and_exchange(&subscriber->skipped_autoupdate, 1, 0)) + changes++; if(changes == 0) { janus_mutex_unlock(&subscriber->streams_mutex); /* Nothing changed, just ack and don't do anything else */ @@ -11658,6 +11683,7 @@ janus_mutex_lock(&ps->rid_mutex); stream->sim_context.rid_ext_id = ps->rid_extmap_id; janus_mutex_unlock(&ps->rid_mutex); + stream->send = TRUE; stream->sim_context.substream_target = 2; stream->sim_context.templayer_target = 2; janus_vp8_simulcast_context_reset(&stream->vp8_context); @@ -12798,6 +12824,8 @@ /* Look for the right publisher stream instance */ char *remote_id = forward->remote_id; janus_videoroom_publisher_stream *ps = (janus_videoroom_publisher_stream *)forward->source; + if(ps == NULL) + return; janus_videoroom_publisher *p = ps->publisher; if(p == NULL || g_atomic_int_get(&p->destroyed)) return; @@ -12834,7 +12862,7 @@ temp = temp->next; } janus_mutex_unlock(&p->rtp_forwarders_mutex); - if(found && ps) + if(found) janus_videoroom_reqpli(ps, "RTCP from remotized forwarder"); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/src/postprocessing/janus-pp-rec.c new/janus-gateway-1.1.1/src/postprocessing/janus-pp-rec.c --- old/janus-gateway-1.1.0/src/postprocessing/janus-pp-rec.c 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/src/postprocessing/janus-pp-rec.c 2022-12-07 17:04:11.000000000 +0100 @@ -1105,6 +1105,7 @@ if(p->drop) { /* We don't need this */ g_free(p); + p = NULL; } else if(!added) { /* We reached the start */ p->next = list; @@ -1113,7 +1114,7 @@ } } /* Add to the extended header, if that's what we're doing */ - if(extjson_only && p->rotation != -1 && p->rotation != last_rotation) { + if(extjson_only && p && p->rotation != -1 && p->rotation != last_rotation) { last_rotation = p->rotation; if(rotations == NULL) rotations = json_array(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/src/rtcp.h new/janus-gateway-1.1.1/src/rtcp.h --- old/janus-gateway-1.1.0/src/rtcp.h 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/src/rtcp.h 2022-12-07 17:04:11.000000000 +0100 @@ -430,16 +430,6 @@ * @returns 0 in case of success, -1 on errors */ int janus_rtcp_report_block(janus_rtcp_context *ctx, janus_report_block *rb); -/*! \brief Method to quickly fetch the lost packets info from an RR packet, if present - * \note This is just means as a simple way for plugins to extract this information from - * a packet, without the need to setup a dedicated RTCP context for tracking the stats flow - * @param[in] packet The message data - * @param[in] len The message data length in bytes - * @param[out] lost The number of lost packets as a whole - * @param[out] fraction The fraction of lost packets since the last RR/SR - * @returns TRUE in case of success, FALSE otherwise */ -gboolean janus_rtcp_parse_lost_info(char *packet, int len, uint32_t *lost, int *fraction); - /*! \brief Method to check whether an RTCP message contains a BYE message * @param[in] packet The message data * @param[in] len The message data length in bytes diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/src/rtp.c new/janus-gateway-1.1.1/src/rtp.c --- old/janus-gateway-1.1.0/src/rtp.c 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/src/rtp.c 2022-12-07 17:04:11.000000000 +0100 @@ -1132,6 +1132,7 @@ /* Check what we need to do with the packet */ if(context->substream == -1) { if((vcodec == JANUS_VIDEOCODEC_VP8 && janus_vp8_is_keyframe(payload, plen)) || + (vcodec == JANUS_VIDEOCODEC_VP9 && janus_vp9_is_keyframe(payload, plen)) || (vcodec == JANUS_VIDEOCODEC_H264 && janus_h264_is_keyframe(payload, plen))) { context->substream = substream; /* Notify the caller that the substream changed */ @@ -1146,6 +1147,7 @@ if(((context->substream < target && substream > context->substream) || (context->substream > target && substream < context->substream)) && ((vcodec == JANUS_VIDEOCODEC_VP8 && janus_vp8_is_keyframe(payload, plen)) || + (vcodec == JANUS_VIDEOCODEC_VP9 && janus_vp9_is_keyframe(payload, plen)) || (vcodec == JANUS_VIDEOCODEC_H264 && janus_h264_is_keyframe(payload, plen)))) { JANUS_LOG(LOG_VERB, "Received keyframe on #%d (SSRC %"SCNu32"), switching (was #%d/%"SCNu32")\n", substream, ssrc, context->substream, *(ssrcs + context->substream)); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/src/sdp.c new/janus-gateway-1.1.1/src/sdp.c --- old/janus-gateway-1.1.0/src/sdp.c 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/src/sdp.c 2022-12-07 17:04:11.000000000 +0100 @@ -161,10 +161,10 @@ if(a && a->name && a->value) { if(!strcasecmp(a->name, "fingerprint")) { JANUS_LOG(LOG_VERB, "[%"SCNu64"] Fingerprint (global) : %s\n", handle->handle_id, a->value); - if(strcasestr(a->value, "sha-256 ") == a->value) { + if(!strncasecmp(a->value, "sha-256 ", strlen("sha-256 "))) { rhashing = g_strdup("sha-256"); rfingerprint = g_strdup(a->value + strlen("sha-256 ")); - } else if(strcasestr(a->value, "sha-1 ") == a->value) { + } else if(!strncasecmp(a->value, "sha-1 ", strlen("sha-1 "))) { JANUS_LOG(LOG_WARN, "[%"SCNu64"] Hashing algorithm not the one we expected (sha-1 instead of sha-256), but that's ok\n", handle->handle_id); rhashing = g_strdup("sha-1"); rfingerprint = g_strdup(a->value + strlen("sha-1 ")); @@ -349,12 +349,12 @@ } } else if(!strcasecmp(a->name, "fingerprint")) { JANUS_LOG(LOG_VERB, "[%"SCNu64"] Fingerprint (local) : %s\n", handle->handle_id, a->value); - if(strcasestr(a->value, "sha-256 ") == a->value) { + if(!strncasecmp(a->value, "sha-256 ", strlen("sha-256 "))) { g_free(rhashing); /* FIXME We're overwriting the global one, if any */ rhashing = g_strdup("sha-256"); g_free(rfingerprint); /* FIXME We're overwriting the global one, if any */ rfingerprint = g_strdup(a->value + strlen("sha-256 ")); - } else if(strcasestr(a->value, "sha-1 ") == a->value) { + } else if(!strncasecmp(a->value, "sha-1 ", strlen("sha-1 "))) { JANUS_LOG(LOG_WARN, "[%"SCNu64"] Hashing algorithm not the one we expected (sha-1 instead of sha-256), but that's ok\n", handle->handle_id); g_free(rhashing); /* FIXME We're overwriting the global one, if any */ rhashing = g_strdup("sha-1"); @@ -1688,7 +1688,8 @@ a = janus_sdp_attribute_create("ssrc", "%"SCNu32" cname:janus", medium->ssrc); m->attributes = g_list_append(m->attributes, a); if(medium->ssrc_rtx > 0 && m->type == JANUS_SDP_VIDEO && - janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_RFC4588_RTX)) { + janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_RFC4588_RTX) && + (m->direction == JANUS_SDP_DEFAULT || m->direction == JANUS_SDP_SENDRECV || m->direction == JANUS_SDP_SENDONLY)) { /* Add rtx SSRC group to negotiate the RFC4588 stuff */ a = janus_sdp_attribute_create("ssrc", "%"SCNu32" cname:janus", medium->ssrc_rtx); m->attributes = g_list_append(m->attributes, a); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/src/turnrest.c new/janus-gateway-1.1.1/src/turnrest.c --- old/janus-gateway-1.1.0/src/turnrest.c 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/src/turnrest.c 2022-12-07 17:04:11.000000000 +0100 @@ -126,6 +126,13 @@ janus_mutex_unlock(&api_mutex); return NULL; } + /* Prepare the libcurl context */ + CURLcode res; + CURL *curl = curl_easy_init(); + if(curl == NULL) { + JANUS_LOG(LOG_ERR, "libcurl error\n"); + return NULL; + } /* Prepare the request URI */ char query_string[512]; g_snprintf(query_string, 512, "service=turn"); @@ -135,10 +142,12 @@ * suggested 'key' instead: as such, we send them both * See https://github.com/meetecho/janus-gateway/issues/1416 */ char buffer[256]; - g_snprintf(buffer, 256, "&api=%s", api_key); + char *encoded_key = curl_easy_escape(curl, api_key, 0); + g_snprintf(buffer, 256, "&api=%s", encoded_key); janus_strlcat(query_string, buffer, 512); - g_snprintf(buffer, 256, "&key=%s", api_key); + g_snprintf(buffer, 256, "&key=%s", encoded_key); janus_strlcat(query_string, buffer, 512); + curl_free(encoded_key); } if(user != NULL) { /* Note: 'username' is supposedly optional, but a commonly used @@ -146,20 +155,15 @@ * now send that too, letting the Janus core tell us what to use * See https://github.com/meetecho/janus-gateway/issues/2199 */ char buffer[256]; - g_snprintf(buffer, 256, "&username=%s", user); + char *encoded_user = curl_easy_escape(curl, user, 0); + g_snprintf(buffer, 256, "&username=%s", encoded_user); janus_strlcat(query_string, buffer, 512); + curl_free(encoded_user); } char request_uri[1024]; g_snprintf(request_uri, 1024, "%s?%s", api_server, query_string); JANUS_LOG(LOG_VERB, "Sending request: %s\n", request_uri); janus_mutex_unlock(&api_mutex); - /* Prepare the libcurl context */ - CURLcode res; - CURL *curl = curl_easy_init(); - if(curl == NULL) { - JANUS_LOG(LOG_ERR, "libcurl error\n"); - return NULL; - } curl_easy_setopt(curl, CURLOPT_URL, request_uri); curl_easy_setopt(curl, api_http_get ? CURLOPT_HTTPGET : CURLOPT_POST, 1); if(!api_http_get) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/janus-gateway-1.1.0/src/utils.h new/janus-gateway-1.1.1/src/utils.h --- old/janus-gateway-1.1.0/src/utils.h 2022-10-03 15:10:00.000000000 +0200 +++ new/janus-gateway-1.1.1/src/utils.h 2022-12-07 17:04:11.000000000 +0100 @@ -332,14 +332,12 @@ gboolean janus_h264_is_keyframe(const char *buffer, int len); /*! \brief Helper method to check if an AV1 frame is a keyframe or not - * @note Currently only a placeholder, always returns FALSE * @param[in] buffer The RTP payload to process * @param[in] len The length of the RTP payload * @returns TRUE if it's a keyframe, FALSE otherwise */ gboolean janus_av1_is_keyframe(const char *buffer, int len); /*! \brief Helper method to check if an H.265 frame is a keyframe or not - * @note Currently only a placeholder, always returns FALSE * @param[in] buffer The RTP payload to process * @param[in] len The length of the RTP payload * @returns TRUE if it's a keyframe, FALSE otherwise */