GNOME Bugzilla – Bug 797059
rtspserver: Not possible to have more than 1 multicast stream with the same ports (non-shared media case)
Last modified: 2018-09-28 17:58:54 UTC
The problem is that the multicast sockets are bound to INADDR_ANY (0.0.0.0) and they should be bound to the multicast address. I have a solution to this problem (still working on the unittests).
It's not allowed to bind to the multicast address on Windows, and it also does not work on Linux with IPv6 IIRC. We did this before, check the GIT logs for some more details.
So this implies that we have an undocumented multicast limitation in gst-rtsp-server meaning that in a non-shared media case it's not possible to request RTP data from different multicast groups and the same ports. Is this problem solvable on the whole?
I don't know, it needs some research for the different platforms
(In reply to Sebastian Dröge (slomo) from comment #1) > It's not allowed to bind to the multicast address on Windows, and it also > does not work on Linux with IPv6 IIRC. We have tested the case with IPv6 without any problems. So it works. I guess that if bind() to the multicast addresses is not allowed on Windows, we should only have this limitation for this platform without putting any constraints on other platforms.
Platform-specific behaviour is something I would've liked to prevent but if there's no other way... This is also a problem in multiudpsink and udpsrc btw. Did you research how it behaves on e.g. the BSDs?
(In reply to Sebastian Dröge (slomo) from comment #5) > Platform-specific behaviour is something I would've liked to prevent but if > there's no other way... Ok, I understand. An alternative solution, in order to avoid platform specific behavior, would be to make alloc_ports () function a virtuall one. What do you think? > This is also a problem in multiudpsink and udpsrc > btw. What problem is it? > > Did you research how it behaves on e.g. the BSDs? No.
(In reply to Patricia Muscalu from comment #6) > (In reply to Sebastian Dröge (slomo) from comment #5) > > Platform-specific behaviour is something I would've liked to prevent but if > > there's no other way... > > Ok, I understand. An alternative solution, in order to avoid platform > specific behavior, would be to make alloc_ports () function a virtuall one. > What do you think? I think that's only working around the problem :) > > This is also a problem in multiudpsink and udpsrc > > btw. > > What problem is it? They also bind to ANY instead of the multicast group > > > > Did you research how it behaves on e.g. the BSDs? > > No. If we want to add code that is conditional on G_OS_WIN32 then we need to make sure that the other part works fine not only on Linux but also the BSDs (including macOS).
(In reply to Sebastian Dröge (slomo) from comment #7) > (In reply to Patricia Muscalu from comment #6) > > (In reply to Sebastian Dröge (slomo) from comment #5) > > > Platform-specific behaviour is something I would've liked to prevent but if > > > there's no other way... > > > > Ok, I understand. An alternative solution, in order to avoid platform > > specific behavior, would be to make alloc_ports () function a virtuall one. > > What do you think? > > I think that's only working around the problem :) > > > > This is also a problem in multiudpsink and udpsrc > > > btw. > > > > What problem is it? > > They also bind to ANY instead of the multicast group > Ok, but this in the case when the socket is created internally by the element itself. > > > > > > Did you research how it behaves on e.g. the BSDs? > > > > No. > > If we want to add code that is conditional on G_OS_WIN32 then we need to > make sure that the other part works fine not only on Linux but also the BSDs > (including macOS). What do you think about introducing a new property, bind-mcast-address (in rtsp-stream), that decides what type of address the mcast socket should be bound to? So the default behavior would be to bind to ANY unless bind-mcast-address=true. Setting bind-mcast-address=true restricts the mcast socket to multicast traffic only.
(In reply to Patricia Muscalu from comment #8) > > If we want to add code that is conditional on G_OS_WIN32 then we need to > > make sure that the other part works fine not only on Linux but also the BSDs > > (including macOS). > > What do you think about introducing a new property, bind-mcast-address (in > rtsp-stream), that decides what type of address the mcast socket should be > bound to? > So the default behavior would be to bind to ANY unless > bind-mcast-address=true. Probably the best we can do, same property on the UDP elements for the internal sockets would make sense then too. > Setting bind-mcast-address=true restricts the mcast socket to multicast > traffic only. Only for IPv4 on Linux. Try it with IPv6, it does not filter the packets then :) There's filtering code inside udpsrc though.
(In reply to Sebastian Dröge (slomo) from comment #9) > (In reply to Patricia Muscalu from comment #8) > > > > If we want to add code that is conditional on G_OS_WIN32 then we need to > > > make sure that the other part works fine not only on Linux but also the BSDs > > > (including macOS). > > > > What do you think about introducing a new property, bind-mcast-address (in > > rtsp-stream), that decides what type of address the mcast socket should be > > bound to? > > So the default behavior would be to bind to ANY unless > > bind-mcast-address=true. > > Probably the best we can do, same property on the UDP elements for the > internal sockets would make sense then too. Great! I'll provide a patch. > > > Setting bind-mcast-address=true restricts the mcast socket to multicast > > traffic only. > > Only for IPv4 on Linux. Try it with IPv6, it does not filter the packets > then :) There's filtering code inside udpsrc though. Ok. But it sounds like a bug actually. I'll check. Thanks!
Created attachment 373744 [details] [review] New property for socket binding to mcast addresses
The following commit introduces a problem when using only ipv6 and multicast: commit 12f8abb549e71053a49eb3c4a7bfd6d1d3e5318e Author: Mathieu Duponchelle <mathieu@centricular.com> Date: Wed Jul 25 19:54:55 2018 +0200 rtsp-client: always allocate both IPV4 and IPV6 sockets The problem is caused by the fact that the sockets (ipv4 and ipv6) are bound to ANY.
(In reply to Patricia Muscalu from comment #12) > The following commit introduces a problem when using only ipv6 and multicast: > > commit 12f8abb549e71053a49eb3c4a7bfd6d1d3e5318e > Author: Mathieu Duponchelle <mathieu@centricular.com> > Date: Wed Jul 25 19:54:55 2018 +0200 > > rtsp-client: always allocate both IPV4 and IPV6 sockets > > The problem is caused by the fact that the sockets (ipv4 and ipv6) are bound > to ANY. That's not very descriptive, can you elaborate? How does the problem manifest itself, what are the steps to reproduce it with master, etc.?
Hi Mathieu, sorry for too short description. The problem is triggered when requesting ipv6 multicast with client settings. alloc_ports() will be called twice: first for ipv4 (bind() to ANY is performed) and later for ipv6 (bind() fails because we have already bound the ipv4 socket to the same port).
Can you have look at the suggested patch? This patch solves 2 problems: requesting mcast streams with the same ports (non-shared media case) and ipv6 multicast request with client settings. Thanks!
Do I understand you correctly that your patch also fixes the problem you discussed with Mathieu?
Review of attachment 373744 [details] [review]: ::: gst/rtsp-server/rtsp-stream.c @@ +1454,1 @@ inetaddr = g_inet_address_new_from_string (addr->address); Doesn't this now go into the ANY case below for !multicast?
(In reply to Sebastian Dröge (slomo) from comment #16) > Do I understand you correctly that your patch also fixes the problem you > discussed with Mathieu? Yes. This patch solves the ipv6-client-settings-mcast problem (introduced in 12f8a) and when the same ports are requested in the mcast case (non-shared media case), assuming that the new property - bind-mcast-address - is set on the media factory. Note, that the problem is still persistent in Windows, as it's not possible to bind sockets to multicast addresses.
(In reply to Sebastian Dröge (slomo) from comment #17) > Review of attachment 373744 [details] [review] [review]: > > ::: gst/rtsp-server/rtsp-stream.c > @@ +1454,1 @@ > inetaddr = g_inet_address_new_from_string (addr->address); > > Doesn't this now go into the ANY case below for !multicast? You are right, the condition is not correct and should be changed to: if (priv->bind_mcast_address || !multicast) inetaddr = g_inet_address_new_from_string (addr->address); else inetaddr = g_inet_address_new_any (family);
Created attachment 373768 [details] [review] New property for socket binding to mcast addresses
Comment on attachment 373768 [details] [review] New property for socket binding to mcast addresses This does not apply cleanly to git master. I think it would also make sense to add the same property to udpsrc/multiudpsink (and a property to disable the control message based filtering in udpsrc). If you don't want to work on that, can you create a bug?
(In reply to Sebastian Dröge (slomo) from comment #21) > Comment on attachment 373768 [details] [review] [review] > New property for socket binding to mcast addresses > > This does not apply cleanly to git master. I'll fix. I'm not able to compile gst-rtps-server with the latest commit ...
Created attachment 373770 [details] [review] New property for socket binding to mcast addresses
(In reply to Sebastian Dröge (slomo) from comment #21) > Comment on attachment 373768 [details] [review] [review] > New property for socket binding to mcast addresses > > This does not apply cleanly to git master. > > I think it would also make sense to add the same property to > udpsrc/multiudpsink (and a property to disable the control message based > filtering in udpsrc). If you don't want to work on that, can you create a > bug? Yes, of course. I can work on adding property to udpsrc/multiudpsink. In order to solve the problem with the control message, I need to understand the issue. Can you explain it? Thanks.
(In reply to Patricia Muscalu from comment #24) > In order to solve the problem with the control message, I need to understand > the issue. Can you explain it? Thanks. We currently use control messages for getting the destination address of the packets in udpsrc, and then filtering out everything that is not for our multicast address. That's expensive and should probably be possible to disable
Comment on attachment 373770 [details] [review] New property for socket binding to mcast addresses The tests fail for for, but only if I do "make check" (every time!). Doing "make gst/client.check" always succeeds. Without your patch it also always succeeds. gst/client.c:509:F:general:test_client_multicast_transport_specific_no_address_in_pool:0: 'code' (461) is not equal to 'GST_RTSP_STS_OK' (200)
(In reply to Sebastian Dröge (slomo) from comment #26) > Comment on attachment 373770 [details] [review] [review] > New property for socket binding to mcast addresses > > The tests fail for for, but only if I do "make check" (every time!). Doing > "make gst/client.check" always succeeds. Without your patch it also always > succeeds. > > gst/client.c:509:F:general: > test_client_multicast_transport_specific_no_address_in_pool:0: 'code' (461) > is not equal to 'GST_RTSP_STS_OK' (200) I cannot reproduce the problem. "make check" works fine with or without my patch.
Ah also: rtsp-media.c:1930: Warning: GstRtspServer: gst_rtsp_media_set_bind_mcast_address: unknown parameter 'bind_mcast' in documentation comment, should be 'bind_mcast_addr' rtsp-media-factory.c:1565: Warning: GstRtspServer: gst_rtsp_media_factory_set_bind_mcast_address: unknown parameter 'bind_mcast' in documentation comment, should be 'bind_mcast_address'
Created attachment 373771 [details] client.log.xz Here's a GST_DEBUG=6 log. Search for (has two occurrences) > code: '461' The error is: gst/client.c:509:F:general:test_client_multicast_transport_specific_no_address_in_pool:0: 'code' (461) is not equal to 'GST_RTSP_STS_OK' (200)
Ok. Thanks. I've found the issue: bind() failure in your case: 0:00:01.502251314 4335 0x562165de3c00 DEBUG rtspstream rtsp-stream.c:1770:gst_rtsp_stream_allocate_udp_sockets:<GstRTSPStream@0x562165fb02f0> GST_RTSP_LOWER_TRANS_MCAST_UDP, ipv4 87 0:00:01.502265844 4335 0x562165de3c00 DEBUG rtspstream rtsp-stream.c:1401:alloc_ports_one_family:<GstRTSPStream@0x562165fb02f0> use transport settings 88 0:00:01.502369902 4335 0x562165de3c00 DEBUG rtspstream rtsp-stream.c:1474:alloc_ports_one_family:<GstRTSPStream@0x562165fb02f0> rtp bind() failed, will try again 89 0:00:01.502376005 4335 0x562165de3c00 ERROR rtspstream rtsp-stream.c:1596:alloc_ports_one_family:<GstRTSPStream@0x562165fb02f0> failed to allocate UDP ports with requested transport settings 90 0:00:01.502387868 4335 0x562165de3c00 ERROR rtspclient rtsp-client.c:2113:default_configure_client_transport:<GstRTSPClient@0x562165e860e0> Failed to allocate UDP ports 91 0:00:01.502392027 4335 0x562165de3c00 ERROR rtspclient rtsp-client.c:2675:handle_setup_request: client 0x562165e860e0: unsupported client transport 92 RTSP response message 0x7ffdae645060 93 status line: 94 code: '461' 95 reason: 'Unsupported transport' 96 version: '1.0' 97 headers: 98 key: 'CSeq', value: '0' 99 key: 'Server', value: 'GStreamer RTSP server' 100 body: length 0
So I guess that port 6000 is used in your system.
I can reproduce the problem by changing the requested port number portnum to the one already used by the system (0.0.0.0:<portnum>) It's a general problem for all our tests I guess.
Steps to reproduce the test failure: 1. netcat -u -l 6000 2. run the test The test (and all other tests, there bind() is involved) has to be modified to make sure that free ports are used. (Having this scenario: netcat -u -l 127.0.0.1 6000, requires a call to gst_rtsp_media_factory_set_bind_mcast_address (factory, TRUE) from the test code in order to avoid bind() failure).
(In reply to Patricia Muscalu from comment #33) > Steps to reproduce the test failure: > > 1. netcat -u -l 6000 > > 2. run the test > > The test (and all other tests, there bind() is involved) has to be modified > to make sure that free ports are used. > Another solution is to introduce a property allow-reuse (that would be set from the tests) deciding the behavior of bind(). What do you think?
It's not something listening on port 6000 on my system (or otherwise the test would fail if run individually too). The problem, I guess, is that the *other* tests use port 6000 and then the client test tries to use it too early before the OS allows to reuse it. Maybe we can configure the tests to all use a different port at least? :)
(In reply to Sebastian Dröge (slomo) from comment #35) > It's not something listening on port 6000 on my system (or otherwise the > test would fail if run individually too). The problem, I guess, is that the > *other* tests use port 6000 and then the client test tries to use it too > early before the OS allows to reuse it. > Ok, I see, rtspserver tests use port 6000. > Maybe we can configure the tests to all use a different port at least? :) Yes. I can do it.
Created attachment 373797 [details] [review] New property for socket binding to mcast addresses
Created attachment 373798 [details] [review] tests: client: Avoid bind() failures in tests
Attachment 373797 [details] pushed as c394de2 - New property for socket binding to mcast addresses Attachment 373798 [details] pushed as 982efec - tests: client: Avoid bind() failures in tests
Hello, you filed this one https://bugzilla.gnome.org/show_bug.cgi?id=797224 , unless I'm reading it wrong these patches are fixing exactly that no ?
Ah, I see, rtsp server creates it's own socket.