I'm having issues with using some sockets in C++ code with Android NDK. Two sockets are created, and one reads from the other. This works with a network connection on Android, both with and without a network connection on another machine, but NOT on Android without a network connection.
Here is a netstat output before the socket closes. The line of interest is
tcp 0 0 127.0.0.1:32993 127.0.0.1:46810 ESTABLISHED
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:32993 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:45549 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:5037 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:5555 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:46811 127.0.0.1:32993 ESTABLISHED
tcp 0 0 127.0.0.1:32993 127.0.0.1:46811 ESTABLISHED
tcp 0 0 127.0.0.1:46810 127.0.0.1:32993 ESTABLISHED
tcp 0 0 127.0.0.1:32993 127.0.0.1:46810 ESTABLISHED
tcp 0 0 10.0.2.15:5555 10.0.2.2:34217 ESTABLISHED
udp 0 0 10.0.2.15:49667 10.0.2.3:53
udp 0 0 0.0.0.0:60262 0.0.0.0:*
I then attempt to read 10 bytes from the socket 127.0.0.1:46810 (header_length - filled = 10):
bytes = read(fd, header, header_length - filled);
However, 0 bytes are read. TCP_NODELAY has been set on the socket. This is the netstat output after the read.
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:32993 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:5037 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:5555 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:46811 127.0.0.1:32993 FIN_WAIT2
tcp 0 1 127.0.0.1:32993 127.0.0.1:46811 CLOSE_WAIT
tcp 0 0 127.0.0.1:46810 127.0.0.1:32993 FIN_WAIT2
tcp 0 0 127.0.0.1:32993 127.0.0.1:46810 CLOSE_WAIT
tcp 0 0 10.0.2.15:5555 10.0.2.2:34217 ESTABLISHED
udp 0 0 0.0.0.0:60262 0.0.0.0:*
There are no problems when there is a network connection, and the addresses used are still 127.0.0.1. Why would it fail to read any bytes on localhost when there is no network connection?
Turns out that this was being caused by another issue. Some time after resolving the IP address into a char array, delete[] was being called on the array. When there was no network connection, the pointer was being reassigned directly to 127.0.0.1, so the program was crashing on the delete[]. Copying the IP into the array using
strcpy(ip, "127.0.0.1");
means that the pointer still points at the array, and the program does not crash when calling delete[].
Related
We have the following setup for webrtc two-way video and audio streaming:
Mobile
Android application using Google WebRTC implementation java wrapper. Tested these two libs:
implementation 'org.webrtc:google-webrtc:1.0.+'
implementation 'com.github.webrtc-sdk:android:92.4515.03' // https://github.com/webrtc-sdk/android
RPi
Gstreamer with WebRTC plugin based on gst-examples with a few modifications.
Browser
Also slightly modified gst-examples Javascript implementation. It is based on native browser WebRTC support.
TURN
Coturn server working in Docker (coturn/coturn).
The problem
When calling from RPi to browser or mobile to browser everything works fine both in local network and via Internet (through TURN server). However when trying to connect RPi and Android device via Internet it gets stuck (local network works as well). The devices communicate with each other, negotiate SDPs and ICE candidates and the TURN server opens the connections properly, but there is no audio/video.
When looking at Android logs, the first difference is that there is no ICE connection change triggered:
PeerConnectionObserver: onStandardizedIceConnectionChange: CHECKING
nor
PeerConnectionObserver: onConnectionChange: CONNECTING
which happens before ICE candidates exchange. After ICE candidates have been sent there is no further communication with the other device and no status changes are being fired. Like for example these in the working case:
PeerConnectionObserver: onSelectedCandidatePairChanged: org.webrtc.CandidatePairChangeEvent#a856333
PeerConnectionObserver: onStandardizedIceConnectionChange: CONNECTED
PeerConnectionObserver: onConnectionChange: CONNECTED
PeerConnectionObserver: onIceConnectionChange CONNECTED
[Internal data channel]: onStateChange
PeerConnectionObserver: onDataChannel org.webrtc.DataChannel#b76f6f0
[External data channel]: onStateChange
The coturn logs don't show anything suspicious at all.
Would appreciate any tips or help of any kind in further investigating this issue.
EDIT:
With #RSATom suggestion we've looked more closely to ICE and SDP messages being sent and found no discrapancies there. The SDPs are identical for mobile-RPi communication through Internet and locally. The only difference are ids generated randomly. The ICEs also do not differ much. It's identical for the first sender (offerer) and slightly different for answerer because it contains the TURN details:
via Internet
video0:0:candidate:228040959 1 udp 2122260223 10.111.215.156 53556 typ host generation 0 ufrag 3SNh network-id 3 network-cost 900::UNKNOWN
video0:0:candidate:559267639 1 udp 2122202367 ::1 48566 typ host generation 0 ufrag 3SNh network-id 2::UNKNOWN
video0:0:candidate:1510613869 1 udp 2122129151 127.0.0.1 41279 typ host generation 0 ufrag 3SNh network-id 1::UNKNOWN
video0:0:candidate:1876313031 1 tcp 1518222591 ::1 46051 typ host tcptype passive generation 0 ufrag 3SNh network-id 2::UNKNOWN
video0:0:candidate:344579997 1 tcp 1518149375 127.0.0.1 60259 typ host tcptype passive generation 0 ufrag 3SNh network-id 1::UNKNOWN
video0:0:candidate:842163049 1 udp 1686052607 31.0.91.196 6742 typ srflx raddr 10.111.215.156 rport 53556 generation 0 ufrag 3SNh network-id 3 network-cost 900:stun:3.70.23.20:3478:UNKNOWN
video0:0:candidate:593469510 1 udp 41885439 172.31.0.169 14307 typ relay raddr 31.0.91.196 rport 6742 generation 0 ufrag 3SNh network-id 3 network-cost 900:turn:3.70.23.20:3478?transport=udp:UNKNOWN
via local WiFi
video0:0:candidate:2858526953 1 udp 2122260223 192.168.0.21 38123 typ host generation 0 ufrag rwx/ network-id 3 network-cost 10::UNKNOWN
video0:0:candidate:559267639 1 udp 2122202367 ::1 52058 typ host generation 0 ufrag rwx/ network-id 2::UNKNOWN
video0:0:candidate:1510613869 1 udp 2122129151 127.0.0.1 39469 typ host generation 0 ufrag rwx/ network-id 1::UNKNOWN
video0:0:candidate:842163049 1 udp 1686052607 178.235.191.135 13607 typ srflx raddr 192.168.0.21 rport 38123 generation 0 ufrag rwx/ network-id 3 network-cost 10:stun:3.70.23.20:3478:UNKNOWN
video0:0:candidate:1876313031 1 tcp 1518222591 ::1 51551 typ host tcptype passive generation 0 ufrag rwx/ network-id 2::UNKNOWN
video0:0:candidate:344579997 1 tcp 1518149375 127.0.0.1 41007 typ host tcptype passive generation 0 ufrag rwx/ network-id 1::UNKNOWN
video0:0:candidate:593469510 1 udp 41885439 172.31.0.169 13744 typ relay raddr 178.235.191.135 rport 13607 generation 0 ufrag rwx/ network-id 3 network-cost 10:turn:3.70.23.20:3478?transport=udp:UNKNOWN
The order of ICE messages seems not to be persisted.
A diff of full logs (Internet left, local right): https://www.diffchecker.com/elEA6rkJ
ICE messages diff: https://www.diffchecker.com/C1TzPcMm
EDIT 2:
I missed that some of the logs were not present. Full log diff for connectivity via Internet (working vs not-working) available here. There are a few differences:
Invalid connection misses a lot of logs informing of connection creation and keepalive and still displays this instead:
tag: basic_ice_controller.cc
message: (line 541): Sorting 0 available connections
For the invalid connection RTP SSRC transport_cc is turned off
Gstreamer uses stream aliases (like video0 and audio0) which then cause ICE candidate errors like this:
ReadyToUseRemoteCandidate: Invalid candidate. Mid 0 specified but no media section with that mid found.
There are failed TCP requests to TURN:
LS_INFO
tag: turn_port.cc
message: (line 375): Port[31f33800:video0:1:0:relay:Net[lo:127.0.0.x/8:Loopback:id=1]]: Trying to connect to TURN server via tcp # sicdev-turn.ddns.net:3478
LS_INFO
tag: android_network_monitor.cc
message: (line 422): Find network handle.
LS_WARNING
tag: android_network_monitor.cc
message: (line 307): BindSocketToNetwork unable to find network handle for addr: 127.0.0.x ifname: lo
LS_VERBOSE
tag: physical_socket_server.cc
message: (line 207): Binding socket to loopback address failed; result: -3
LS_ERROR
tag: basic_packet_socket_factory.cc
message: (line 186): TCP connect failed with error 22
LS_ERROR
tag: turn_port.cc
message: (line 379): Failed to create TURN client socket
What I would do in your case:
Add logs for create-offer/create-answer/set-offer/set-answer requests
Add logs for every incoming/outgoing Ice Candidate and end-of-candidates
Then look to logs and check:
All Ice Candidates are really delivering to other party.
end-of-candidates delivering after all other Ice Candidates.
Ice Candidates coming after set-offer/set-answer
Your STUN/TURN server is really accessible by both parties (with https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/)
You have IPv6 configured on your STUN/TURN server (some GSM providers could not use IPv4 at all)
Upd 1
According to logs your Android device has IPv4. So there is no need to worry about IPv6 right now.
About end-of-candidates - you can look how I generate it with webrtcbin here.
The similar code for Android:
private val connectionObserver = object: PeerConnection.Observer {
// ... some overrides skipped ...
override fun onIceCandidate(candidate: IceCandidate) {
Log.d(TAG, "onIceCandidate \"$candidate\"")
}
override fun onIceGatheringChange(state: PeerConnection.IceGatheringState) {
Log.d(TAG, "IceGathering state: $state")
if(state == PeerConnection.IceGatheringState.COMPLETE) {
Log.d(TAG, "onIceCandidate \"a=end-of-candidates\"")
}
}
// ... some overrides skipped ...
}
Also please check following:
On Android
You are really call org.webrtc.PeerConnection.addIceCandidate for every incoming Ice Candidate
You do it after org.webrtc.PeerConnection.setRemoteDescription call
On RPi
You are really call g_signal_emit_by_name with add-ice-candidate for every incoming Ice Candidate
Upd 2
I've noticed your relay Ice Candidate points to private network IP (172.31.0.169). This can mean you have wrong config for your TURN
server.
Upd 3
Please check with https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/ you get relay Ice Candidate with valid IP on both sides.
I have created AndroidWebServer on my android phone.
When I try to access 192.168.1.150:8000 (phone address) I have good response from the server. But when I try to access the same url from the pc (connected via WiFi on the same network) nothing happens.
When the server is active if I run this
adb shell netstat -at
tcp 0 0 ::ffff:127.0.0.1:8000 :::* LISTEN
That is weird because other services got foreign address
tcp 0 0 ::ffff:192.168.1.150:54 ::ffff:173.194.76.188:5 ESTABLISHED
tcp 0 0 ::ffff:192.168.1.150:36 ::ffff:31.13.92.33:http ESTABLISHED
for my service the foring address is :::*
I am not sure what I do wrong
https://github.com/lopspower/AndroidWebServer
AndroidWebServer androidWebServer = new AndroidWebServer(8000);
androidWebServer.start();
What should I change in order my phone to be accessible from my pc connected to the same WiFi network?
Thanks
Looks like your server is listening on localhost. That means it will only accept connections that originate on the local machine. Try listening on 0.0.0.0 instead; that means you accept connections from all origins.
EDIT
Change this line:
AndroidWebServer androidWebServer = new AndroidWebServer("0.0.0.0", 8000);
My application is scanning available ports where I'm interested in open/established session on a remote IP address.
My code below returns 22 (ssh) and 902 (Vmware) where a netstat -an returns:
tcp 0 0 192.168.1.160:60376 216.58.208.238:443 (google) ESTABLISHED
How can I retrieve the established session for a remote device?
My code for available ports (I do a loop on ports):
Socket socket = new Socket();
socket.connect(new InetSocketAddress(ip, port), timeout);
socket.close();
I hooked into the /system/bin/netd binary to log all of the commands that are sent by the Android framework when it puts up a hotspot via clicking buttons in the system settings menu. (I needed to be able to bring up the hotspot up from shell & ADB without bringing up the settings menu.)
This returned all of the commands that are used to put up the hotspot.
interface clearaddrs wlan0
interface ipv6 wlan0 disable
resolver flushif wlan0
bandwidth setglobalalert 2097152
bandwidth setglobalalert 2097152
softap fwreload wlan0 AP
softap set wlan0 asdfa wpa2-psk 12345678
softap startap
interface getcfg wlan0
interface setcfg wlan0 192.168.43.1 24 running multicast broadcast up
tether interface add wlan0
ipfwd enable
tether start 192.168.42.2 192.168.42.254 192.168.43.2 192.168.43.254 192.168.44.2 192.168.44.254 192.168.45.2 192.168.45.254 192.168.46.2 192.168.46.254 192.168.47.2 192.168.47.254 192.168.48.2 192.168.48.254
tether dns set 8.8.8.8 8.8.4.4
Seems OK.
When I issue those commands through /system/bin/ndc from shell, nothing returns an error and claims that it succeeded. Great. Fantastic. Wonderful.
200 0 Interface IP addresses cleared
200 0 IPv6 state changed
200 0 Resolver command succeeded
200 0 Bandwidth command succeeeded
200 0 Bandwidth command succeeeded
200 0 Softap operation succeeded
200 0 Softap operation succeeded
600 Iface linkstate wlan0 down
600 Iface linkstate wlan0 down
200 0 Softap operation succeeded
213 0 44:33:4c:3d:98:dc 0.0.0.0 0 down broadcast multicast
200 0 Interface configuration set
200 0 Tether operation succeeded
200 0 ipfwd operation succeeded
200 0 Tether operation succeeded
200 0 Tether operation succeeded
Super! Except for the little trivial fact that the hotspot cannot be seen afterwards and it doesn't even kick me off the wireless connection, so obviously I am missing something.
It might be useful to note that in Android 4.1.1 the following works (as expected), but in 4.2.2 it does not; I have tried endless combinations of the logged commands and the 4.1.1 commands to very little avail.
softap stopap
softap stop wlan0
softap fwreload ap0 AP
softap start wlan0
softap set wlan0 ap0 SSID wpa2-psk 12345678 11 0 8
softap startap
interface setcfg ap0 192.168.2.254 255.255.255.0 up
Here is what happens when the hotspot is taken down via the system settings menu, maybe it will be helpful:
interface getcfg wlan0
interface setcfg wlan0 0.0.0.0 0 running multicast broadcast up
tether interface remove wlan0
tether stop
ipfwd disable
softap stopap
softap fwreload wlan0 STA
softap fwreload wlan0 STA
interface getcfg wlan0
interface setcfg wlan0 0.0.0.0 0 multicast broadcast down
interface ipv6privacyextensions wlan0 enable
interface getcfg p2p0
interface setcfg p2p0 0.0.0.0 0 multicast broadcast up
interface ipv6 wlan0 enable
interface route add wlan0 default 192.168.2.254 32 0.0.0.0
interface route add wlan0 default 0.0.0.0 0 192.168.2.254
resolver flushif wlan0
interface route add wlan0 default 192.168.2.254 32 0.0.0.0
bandwidth setglobalalert 2097152
interface route add wlan0 default 0.0.0.0 0 192.168.2.254
bandwidth setglobalalert 2097152
This is what is logged during system startup before any user input is possible:
interface list
interface getcfg eth0
interface ipv6 wlan0 disable
interface list
bandwidth enable
softap fwreload wlan0 STA
firewall disable
interface getcfg wlan0
interface setcfg wlan0 0.0.0.0 0 multicast broadcast down
interface ipv6privacyextensions wlan0 enable
bandwidth setglobalalert 2097152
firewall disable
interface setthrottle rmnet0 -1 -1
interface getcfg p2p0
interface setcfg p2p0 0.0.0.0 0 multicast broadcast up
interface ipv6 wlan0 enable
resolver setifdns wlan0 192.168.2.254
resolver setdefaultif wlan0
interface route add wlan0 default 192.168.2.254 32 0.0.0.0
interface route add wlan0 default 0.0.0.0 0 192.168.2.254
resolver flushif wlan0
interface route add wlan0 default 192.168.2.254 32 0.0.0.0
interface route add wlan0 default 0.0.0.0 0 192.168.2.254
The only thing I do know for sure is that I can trigger the hotspot to come up in 4.4.3 when I issue commands to netd prior to the bootanimation completion.
Where did I go wrong?
Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 9 years ago.
Improve this question
I notice that my Android phone has the https port (443) opened.
This is the nmap report:
PORT STATE SERVICE VERSION
443/tcp open http Mongoose httpd
|_http-methods: No Allow or Public header in OPTIONS response (status code 400)
|_http-title: Index of /
The port is not accessible, if I try to access from browser to this page: https://PHONE_IP I get this error: ERR_SSL_PROTOCOL_ERROR
I tried to connect using adb shell and the port is actually opened, this is the netstat report:
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.1:7777 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:7203 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:5037 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:80 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN
But I can't understand which process bind the 433 port.
Any suggestions?
UPDATE:
Android netstat has no options, not even the -h option.
I don't recall if Android's netstat has the -p option but if it does, that would be the easiest way to learn the process id that has the port open.
Failing that, you can either walk through /proc/ directories looking at the file descriptors open by each process until you find the offending one.