Closed eslam-ahmed-khair closed 2 years ago
I don't see any srflx
Ice Candidate from 192.168.1.x network for ReStreamer in your logs. This can mean your STUN server is not working properly. I think the problem is it is on the same docker network as ReStreamer and provides only Ice Candidates from docker private network. It's possible coturn can be configured better for that case, but I didn't do something like this myself yet.
Would it help to use google's STUN server? also do you think that coturn
should be placed directly on the Host X? but I am sure that coturn
doesn't mind being behind NAT itself.
let's go back to the basic setup:
ReStreamer
running natively on 192.168.1.108 with no STUN/TURN server. A local client 192.168.1.106 is able to connect without issues. yet the client's IP doesn't show in the ice candidates here
ReStreamer
running natively on 192.168.1.108 with just google's STUN server. A local client 192.168.1.106 is able to connect without issues. again, the client's IP doesn't show in the ice candidates here. Now you can see that more cadidates are available that uses the public IP 197.58.221.59 to the local IP 192.168.1.108
ReStreamer
and coturn (STUN) running natively on 192.168.1.108. A local client 192.168.1.106 is able to connect without issues. again, the client's IP doesn't show in the ice candidates here.
Why is it that some clients are able to send their local IPs and work and when others don't send their local IPs, such as Machine Z, they don't work. Yet here all the trials mentioned above, the client never sent its IP and it still worked!
Is there a way to figure out what ice candidate did the webrtcbin
of gstreamer pick up?
What do you make of this?
it's from your log for first try:
[2021-12-30 12:52:57.919] [WsServer] [trace] WsServer -> : SETUP 1 WEBRTSP/0.2
CSeq: 34
Session: 1
content-type: application/x-ice-candidate
0/a=candidate:34 1 UDP 2013266420 192.168.1.108 55775 typ host
[2021-12-30 12:52:57.919] [WsServer] [trace] WsServer -> : SETUP 1 WEBRTSP/0.2
CSeq: 35
Session: 1
content-type: application/x-ice-candidate
0/a=candidate:35 1 TCP 1015024639 192.168.1.108 9 typ host tcptype active
[2021-12-30 12:52:57.919] [WsServer] [trace] WsServer -> : SETUP 1 WEBRTSP/0.2
CSeq: 36
Session: 1
content-type: application/x-ice-candidate
0/a=candidate:36 1 TCP 1010830335 192.168.1.108 59467 typ host tcptype passive
STUN server should run outside NAT, or at least it should know about it's external IP in case of 1:1 NAT (for example on AWS EC2)
Google STUN (or any other STUN running on public internet) is not the best option if you want run WebRTC over local network, since it will give your provider's IP.
it's from your log for first try:
[2021-12-30 12:52:57.919] [WsServer] [trace] WsServer -> : SETUP 1 WEBRTSP/0.2 CSeq: 34 Session: 1 content-type: application/x-ice-candidate 0/a=candidate:34 1 UDP 2013266420 192.168.1.108 55775 typ host [2021-12-30 12:52:57.919] [WsServer] [trace] WsServer -> : SETUP 1 WEBRTSP/0.2 CSeq: 35 Session: 1 content-type: application/x-ice-candidate 0/a=candidate:35 1 TCP 1015024639 192.168.1.108 9 typ host tcptype active [2021-12-30 12:52:57.919] [WsServer] [trace] WsServer -> : SETUP 1 WEBRTSP/0.2 CSeq: 36 Session: 1 content-type: application/x-ice-candidate 0/a=candidate:36 1 TCP 1010830335 192.168.1.108 59467 typ host tcptype passive
That's the IP of the of ReStreamer, not the web client
STUN server should run outside NAT, or at least it should know about it's external IP in case of 1:1 NAT (for example on AWS EC2)
Except that I am using docker as my NAT, I really don't need to go out to the router for this. In this case, the Local IP is the external IP. Hence coturn is run as ./turnserver -X 192.168.1.108/172.16.238.2 -a -f -r north.gov -v
STUN server should run outside NAT, or at least it should know about it's external IP in case of 1:1 NAT (for example on AWS EC2)
Sorry, it was about TURN. STUN server should be able get incoming connection from IP not behind NAT.
@eslam-ahmed-khair browser give its own IP here:
[2021-12-30 12:53:00.368] [WsServer] [trace] -> WsServer: SETUP 1 WEBRTSP/0.2
CSeq: 1
Session: 1
Content-Type: application/x-ice-candidate
0/candidate:2530088836 1 udp 2113937151 bd189776-4476-45da-b1bc-a7acfed2174b.local 56353 typ host generation 0 ufrag Ap0U network-cost 999
It's so called mDns Ice Candidates. And ReStreamer is able (at some conditions) to resolve it to real IP.
That's good to know. Can we know what it was resolved to?
Also, Is there a way to figure out which ice candidate was selected by the protocol?
That's good to know. Can we know what it was resolved to?
You can add some logging here: https://github.com/WebRTSP/RtStreaming/blob/master/GstRtStreaming/Helpers.cpp#L138 (but it will be called only if IsMDNSResolveRequired returns true
)
Also, Is there a way to figure out which ice candidate was selected by the protocol?
It's possible but requires some changes to code. It can be done with https://gstreamer.freedesktop.org/documentation/webrtc/index.html?gi-language=c#webrtcbin::get-stats
I can't help but wonder why it works with same LAN clients and others don't?
Only full list of Ice Candidates from both sides can explain this (+ info about used IPs and networks).... All I can say right now - something is still different, and I would recommend you find what exactly.
It's possible but requires some changes to code. It can be done with https://gstreamer.freedesktop.org/documentation/webrtc/index.html?gi-language=c#webrtcbin::get-stats
So I invoked the webrtcbin action get-stats
when the connection state is GST_WEBRTC_PEER_CONNECTION_STATE_NEW
. here's the code snippet
GstPromise* p = gst_promise_new_with_change_func(promise_changed, nullptr, nullptr);
g_signal_emit_by_name(rtcbin, "get-stats", nullptr, p);
and here are the functions printing the struct, since I am using Gstreamer 1.16.2, I can't use gst_structure_serialize
or gst_structure_to_string
gboolean print_struct(GQuark field, const GValue* value, gpointer pfx) {
if (GST_VALUE_HOLDS_STRUCTURE(value)) {
const GstStructure* nested_struct = gst_value_get_structure(value);
g_print("printing nested struct: %s\n", gst_structure_get_name(nested_struct));
gst_structure_foreach(nested_struct, print_struct, (gpointer) " ");
} else {
gchar* str = gst_value_serialize(value);
g_print("%s %s: %s\n", (gchar*)pfx, g_quark_to_string(field), str);
g_free(str);
}
return TRUE;
}
void promise_changed(GstPromise* promise, gpointer user_data) {
if (gst_promise_wait(promise) == GST_PROMISE_RESULT_REPLIED) {
const GstStructure* reply = gst_promise_get_reply(promise);
g_print("printing struct: %s\n", gst_structure_get_name(reply));
gst_structure_foreach(reply, print_struct, (gpointer) " ");
}
gst_promise_unref(promise);
}
Yet the results are pointless at this point, as I was hoping to find the exact ice candidate pair used (unless I am really not printing all the stats properly).
printing struct: application/x-webrtc-stats
printing nested struct: peer-connection
data-channels-opened: 0
data-channels-closed: 0
data-channels-requested: 0
data-channels-accepted: 0
type: GST_WEBRTC_STATS_PEER_CONNECTION
timestamp: 11098421.231000001
id: peer-connection-stats
printing nested struct: codec
type: GST_WEBRTC_STATS_CODEC
timestamp: 11098421.231000001
id: codec-stats-sink_0
payload-type: 96
clock-rate: 90000
ssrc: 3404116983
printing nested struct: transport
type: GST_WEBRTC_STATS_TRANSPORT
timestamp: 11098421.231000001
id: transport-stats_webrtcdtlstransport0
printing nested struct: transport
type: GST_WEBRTC_STATS_TRANSPORT
timestamp: 11098421.231000001
id: ice-candidate-pair_webrtcnicetransport0
I didn't use get-stats
from webrtcbin
myself yet, but I've used getStats
from WebRTC.org
library. And there it was possible to get selected Ice Candidates pair... So again, I would recommend you to try newer GStreamer version. Maybe stats was extended there already....
Other possible solution can be enable logs for libnice
...
I didn't use
get-stats
fromwebrtcbin
myself yet, but I've usedgetStats
fromWebRTC.org
library. And there it was possible to get selected Ice Candidates pair... So again, I would recommend you to try newer GStreamer version. Maybe stats was extended there already....
Okay, can you elaborate on which Ubuntu version and Gstreamer version I should be using?
At least 20.10
Right, so I went back to the basics and started from the first post in this issue.
The fact that Machine Y is working yet Machine Z is not! if we inspect their ICE candidates, you'll find that Machine Y used its local IP address directly while Machine Z send its mDNS instead (.local)
Reading about mDNS has lead to stumble upon this helpful link. One funny thing mentioned is that you can disable mDNS from chrome browser and let it send its local IP naked, exposing user privacy bla bla bla, using this flag chrome://flags/#enable-webrtc-hide-local-ips-with-mdns
.
So I disabled it on machine Z, and it worked! Chrome sent the local IP of Machine Z this time.
Reading about how mDNS and how it works now makes sense, because ReStreaming
will never be able to resolve the mDNS address while residing in the container. There's even a daemon avahi
that might be needed in the container to be able to resolve such addresses which wasn't running in the first place.
That's good to know. Can we know what it was resolved to?
You can add some logging here: https://github.com/WebRTSP/RtStreaming/blob/master/GstRtStreaming/Helpers.cpp#L138 (but it will be called only if IsMDNSResolveRequired returns
true
)
Putting some extra logging here with an else
branch will tell use if the resolution was successful or not. When ReStreamer
is running natively, the resolution succeeds, yet when running in container it fails. This is a different problem that I need to address next.
So you just need get STUN working to override this issue....
So you just need get STUN working to override this issue....
I don't think it has something to do with the STUN server because I was using coturn
's. but I'll try Google's STUN server just in case.
@eslam-ahmed-khair I've added selected ICE Candidate pair logging. Please check if you still need it.
@eslam-ahmed-khair I've added selected ICE Candidate pair logging. Please check if you still need it.
Thank you! Yes, I'll need it. It's a really nice thing to have. it lets you know what happens under the curtain.
Hello,
Assume that Machine X is hosting a docker container that is running
ReStreamer
and coturn acting as the local stun/turn server (i.e. both are behind NAT). The container is exposing some ports needed forcoturn
to the host Machine X. For reference the ports are:ReStreamer
is configured with the following ICE servers:stun-server: "stun://192.168.1.108:3478"
turn-server : "turn://admin:admin@192.168.1.108:3478"
coturn
launch command:turnserver -X 192.168.1.108/172.16.238.2 -a -f -r north.gov -v --min-port 49152 --max-port 49200
Now I would like other machines on the same LAN as X, say machine Y and Z, to connect as webrtc clients. Problem is Machine Y can and Machine Z can't!
Refer to Machine Z ICE gathering trace here Refer to Machine Y ICE gathering trace here
The difference I found is that Machine Y sent the following ICE candidate which is its local IP in the LAN:
0/candidate:2222700650 1 udp 2113937151 192.168.1.105 37622 typ host generation 0 ufrag mIbA network-cost 999
Yet Machine Z sent this IPv6 IP ICE candidate and didn't even send an IPv4 candidate:0/candidate:2530088836 1 udp 2113937151 9af8f8fc-e12a-4b3c-b5b4-fb76a833e17c.local 58799 typ host generation 0 ufrag XwOb network-cost 999
What could cause such issue? any clues?