Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow SIP plugin to bind media to a specific address (see #3248) #3263

Merged
merged 6 commits into from
Nov 16, 2023

Conversation

pawnnail
Copy link
Contributor

The multi-stream version of the SIP plugin no longer binds RTP/RTCP sockets to a specific address just like the single-stream version used to. Instead, the multi-stream SIP plugin binds to "any" address for IPv4 and IPv6 (if supported). This highlights a potential security risk if deployed on a multihomed host in a hostile environment. Perhaps, is also wasteful as UDP ports are allocated on multiple addresses and a change of behaviour when migrating from a single-stream to multi. The change was added by PR #3159.

I would like the SIP plugin to use a specific address, IPv4 or IPV6, for media (RTP/RTCP) while preserving the option of binding to any interface (PR #3159). The binding address changes driven by the value of configuration parameter local_media_ip are summarized below.

local_media_ip single-stream multi-stream multi-stream proposed
<empty string> not supported not supported any (IPv4 and IPv6)
<unspecified> local_ip (IPv4) any (IPv4 and IPv6) any (IPv4 and IPv6)
"0.0.0.0" any (IPv4) any (IPv4 and IPv6) any (IPv4 and IPv6)
"::" not supported any (IPv4 and IPv6) any (IPv4 and IPv6)
IPv4, e.g. "192.168.171.8" 192.168.171.8 any (IPv4 and IPv6) 192.168.171.8
IPv4-mapped IPv6, e.g. "::ffff:192.168.171.8" not supported any (IPv4 and IPv6) 192.168.171.8
IPVv6, e.g. "2406:da1c:aa9:9401:2825:674b:3e05:fca2" not supported any (IPv4 and IPv6) 2406:da1c:aa9:9401:2825:674b:3e05:fca2

So there is an impact on PR #3159: if local_media_ip happens to be specified then RTP/RTCP sockets will bind to that address only rather than to all. There is nothing I can do about it other than to warn. I hope the proposal is flexible enough to address most desired configuration scenarios going forward.

Have tested the above scenarios on Linux and Windows WSL.

Have made sdp_ip used for the SDP connection address header (c=) to fallback to a valid value of either local_media_ip or local_ip.

Also fixed an issue where bind() intermittently fails due to audio_rtp_address and audio_rtcp_address not initialized to 0.

Copy link
Member

@lminiero lminiero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some notes inline.

/*
Since we might have to derive SDP connection address from local_media_ip make sure it has a meaningful value
for the prupose of using it in the SDP c= header.
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't use this format for comments. Align to what we use in other parts of the code, so something the lines of

/* Since ...
 * for the ... */

As a side notem there's a typo in "purpose".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point taken.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The format of the comment is still incorrect.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry about that. Fixed.

/* Determine the address family to use */
if(ipv6_disabled &&
!janus_network_address_is_null(&janus_network_local_media_ip) &&
janus_network_local_media_ip.family == AF_INET6) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code style: you need another tab of indent for the two additional checks above, otherwise it ends up lined with the action below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Point taken. The condition is removed as redundant.

if(ipv6_disabled &&
!janus_network_address_is_null(&janus_network_local_media_ip) &&
janus_network_local_media_ip.family == AF_INET6) {
JANUS_LOG(LOG_ERR, "Error setting address for media sockets, IPv6 is disabled and local media address is IPv6...\n");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this action failing at runtime. It looks like a check that can be done when thew plugin is loaded, that is after the janus_network_local_media_ip property is filled in and we know if ipv6_disabled is FALSE. Better to have the plugin not load at all, if we already know it will never allocate sockets for media.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. Moved the failure to the config loading time.

struct sockaddr_storage audio_rtp_address, audio_rtcp_address;
while(session->media.local_audio_rtp_port == 0 || session->media.local_audio_rtcp_port == 0) {
if(attempts == 0) /* Too many failures */
return -1;
memset(&audio_rtp_address, 0, sizeof(audio_rtp_address));
memset(&audio_rtcp_address, 0, sizeof(audio_rtcp_address));
if(session->media.audio_rtp_fd == -1) {
session->media.audio_rtp_fd = socket(!ipv6_disabled ? AF_INET6 : AF_INET, SOCK_DGRAM, 0);
Copy link
Member

@lminiero lminiero Aug 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you forget to switch to use_ipv6_address_family here? (and when creating the RTCP socket too, a few lines below). There's other checks that now use use_ipv6_address_family in this code block that should probably move to the other boolean, since it's that one that now dictates the addrlen.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Essentially !ipv6_disabled and use_ipv6_address_family have the same effect, replaced one with the other for clarity.

src/plugins/janus_sip.c Outdated Show resolved Hide resolved
@pawnnail
Copy link
Contributor Author

Thanks for the review, Lorenzo. Will get it sorted within the next few days.

@pawnnail
Copy link
Contributor Author

pawnnail commented Sep 6, 2023

There are few more things I would like to do to tidy up port binding but not in the same PR. Arbitrary int attempts = 100 tends to fail often on a busy system, especially in a limited port range especially considering RTCP port needs to be adjacent to RTP port. And then it only makes sense to retry bind() on transient errors like hitting a busy port. But one thing at a time.

Retested again. Haven't done the rebase yet, will do once all the changes are approved.
Thanks.

@lminiero
Copy link
Member

lminiero commented Sep 7, 2023

Thanks, looks good now! I just added a tiny note on the comment format.

@lminiero lminiero added the multistream Related to Janus 1.x label Oct 2, 2023
@lminiero
Copy link
Member

lminiero commented Oct 2, 2023

Apologies for the lack of feedback, I've been pretty busy lately and this is an effort I need to study well, especially considering that, if it works, I'll need to port it to the NoSIP plugin as well, besides backporting it to 0.x for both plugins. I'll try to reserve some time later this week to have a deeper look and make some tests. Scream at me if it doesn't happen 😆

@pawnnail
Copy link
Contributor Author

pawnnail commented Oct 4, 2023

No problems and thanks. I am not in a hurry. Let me know if I can help.

@lminiero
Copy link
Member

I'm adapting the patch to 0.x, and then I'll port the changes to NoSIP too. If all goes well, I'll try to merge later today. Apologies again for the delay!

Copy link
Member

@lminiero lminiero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pawnnail while updating other branches and plugins, I stumbled upon these two things. One is a bug and needs to be fixed (it will cause a crash), the other is simply a code style nit. Thanks!

src/plugins/janus_sip.c Show resolved Hide resolved
session->media.local_audio_rtp_port = rtp_port;
session->media.local_audio_rtcp_port = rtcp_port;
}
}
if(session->media.has_video) {
JANUS_LOG(LOG_VERB, "Allocating video ports:\n");
JANUS_LOG(LOG_VERB, "Allocating video ports using address [%s]\n",
janus_network_address_is_null(&janus_network_local_media_ip ) ?"any" : local_media_ip);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some weird spaces in here. Per the code style, it should be

janus_network_address_is_null(&janus_network_local_media_ip) ? "any" : local_media_ip);

@lminiero
Copy link
Member

I'll merge and fix the remaining nits myself, since this has been open quite some time. Thanks again for the contribution and the patience!

@lminiero lminiero merged commit d9a5853 into meetecho:master Nov 16, 2023
8 checks passed
@pawnnail
Copy link
Contributor Author

Thanks!

@pawnnail pawnnail deleted the sip-local-media-address branch November 17, 2023 03:52
mwalbeck pushed a commit to mwalbeck/docker-janus-gateway that referenced this pull request Dec 8, 2023
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [meetecho/janus-gateway](https://github.com/meetecho/janus-gateway) | minor | `v1.1.4` -> `v1.2.1` |

---

### Release Notes

<details>
<summary>meetecho/janus-gateway (meetecho/janus-gateway)</summary>

### [`v1.2.1`](https://github.com/meetecho/janus-gateway/blob/HEAD/CHANGELOG.md#v121---2023-12-06)

[Compare Source](meetecho/janus-gateway@v1.2.0...v1.2.1)

-   Added support for abs-capture-time RTP extension \[[PR-3161](meetecho/janus-gateway#3161)]
-   Fixed truncated label in datachannels (thanks [@&#8203;veeting](https://github.com/veeting)!) \[[PR-3265](meetecho/janus-gateway#3265)]
-   Support larger values for SDP attributes (thanks [@&#8203;petarminchev](https://github.com/petarminchev)!) \[[PR-3282](meetecho/janus-gateway#3282)]
-   Fixed rare crash in VideoRoom plugin (thanks [@&#8203;tmatth](https://github.com/tmatth)!) \[[PR-3259](meetecho/janus-gateway#3259)]
-   Don't create VideoRoom subscriptions to publisher streams with no associated codecs
-   Added suspend/resume participant API to AudioBridge \[[PR-3301](meetecho/janus-gateway#3301)]
-   Fixed rare crash in AudioBridge
-   Fixed rare crash in Streaming plugin when doing ICE restarts \[[Issue-3288](meetecho/janus-gateway#3288)]
-   Allow SIP and NoSIP plugins to bind media to a specific address (thanks [@&#8203;pawnnail](https://github.com/pawnnail)!) \[[PR-3263](meetecho/janus-gateway#3263)]
-   Removed advertised support for SIP UPDATE in SIP plugin
-   Parse RFC2833 DTMF to custom events in SIP plugin (thanks [@&#8203;ywmoyue](https://github.com/ywmoyue)!) \[[PR-3280](meetecho/janus-gateway#3280)]
-   Fixed missing Contact header in some dialogs in SIP plugin (thanks [@&#8203;ycherniavskyi](https://github.com/ycherniavskyi)!) \[[PR-3286](meetecho/janus-gateway#3286)]
-   Properly set mid when notifying about ended tracks in janus.js
-   Fixed broken restamping in janus-pp-rec
-   Other smaller fixes and improvements (thanks to all who contributed pull requests and reported issues!)

### [`v1.2.0`](https://github.com/meetecho/janus-gateway/blob/HEAD/CHANGELOG.md#v120---2023-08-09)

[Compare Source](meetecho/janus-gateway@v1.1.4...v1.2.0)

-   Added support for VP9/AV1 simulcast, and fixed broken AV1/SVC support \[[PR-3218](meetecho/janus-gateway#3218)]
-   Fixed RTCP out quality stats \[[PR-3228](meetecho/janus-gateway#3228)]
-   Default link quality stats to 100
-   Added support for ICE consent freshness \[[PR-3234](meetecho/janus-gateway#3234)]
-   Fixed rare race condition in VideoRoom \[[PR-3219](meetecho/janus-gateway#3219)] \[[PR-3247](meetecho/janus-gateway#3247)]
-   Use speexdsp's jitter buffer in the AudioBridge \[[PR-3233](meetecho/janus-gateway#3233)]
-   Fixed crash in Streaming plugin on mountpoints with too many streams \[[Issue-3225](meetecho/janus-gateway#3225)]
-   Support for batched configure requests in Streaming plugin (thanks [@&#8203;petarminchev](https://github.com/petarminchev)!) \[[PR-3239](meetecho/janus-gateway#3239)]
-   Fixed rare deadlock in Streamin plugin \[[PR-3250](meetecho/janus-gateway#3250)]
-   Fix simulated leave message for longer string ID rooms in TextRoom (thanks [@&#8203;adnanel](https://github.com/adnanel)!) [PR-3243](meetecho/janus-gateway#3243)]
-   Notify about count of sessions, handles and PeerConnections on a regular basis, when event handlers are enabled \[[PR-3221](meetecho/janus-gateway#3221)]
-   Fixed broken Insertable Streams for recvonly streams when answering in janus.js
-   Added background selector and blur support to Virtual Background demo
-   Other smaller fixes and improvements (thanks to all who contributed pull requests and reported issues!)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNi4zNC4wIiwidXBkYXRlZEluVmVyIjoiMzcuODEuNCIsInRhcmdldEJyYW5jaCI6Im1hc3RlciJ9-->

Reviewed-on: https://git.walbeck.it/walbeck-it/docker-janus-gateway/pulls/122
Co-authored-by: renovate-bot <bot@walbeck.it>
Co-committed-by: renovate-bot <bot@walbeck.it>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
multistream Related to Janus 1.x
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants