Google nearby connections - sending payload does not work after reconnecting a few times - google-nearby

I want to create offline multiplayer game for android, so I need reliable p2p communication between devices. Google nearby connections work quite ok, but I found one issue. Setup is standard - device A advertises, device D discovers and connects to A. Then D disconnects, discovers again and connects again. After one to ten iterations D can still connect to A and receive data from A, but it can no longer send data. I call sendPayload with Payload.fromBytes, I receive onSuccessCallback, but A does not receive this payload. Later on D receives onPayloadTransferUpdate with status code 2. Further reconnects does not solve the problem. Only thing that solves the problem reliably is reboot.
Some logs:
03-21 12:20:25.827 30317-30317/com.alienff.ntest I/Log: [21.03.2018 12:20:25.827] [main] MainActivity: sending payload -5864147190526311071
03-21 12:20:25.841 30317-30317/com.alienff.ntest I/Log: [21.03.2018 12:20:25.841] [main] MainActivity: payload cent
...
03-21 12:21:16.925 3066-3215/? D/WifiStateMachine: Current network is: "___mm___" , ID is: 0
03-21 12:21:16.926 3066-3215/? D/WifiStateMachine: Current network is still qualified due to heavy traffic, txSuccessRate=2.1973258256066233 rxSuccessRate=0.0
03-21 12:21:16.926 3066-3215/? D/WifiStateMachine: Current network is 5GHz, bail out...
03-21 12:21:17.408 4049-4049/? D/io_stats: !# 179,0 r 906136 23065676 w 370340 7270584 d 46705 2438912 f 147311 147270 iot 680350 657112 th 51200 0 0 pt 0 inp 0 0 55938.769
03-21 12:21:17.571 10176-30596/? W/NearbyConnections: Unexpected call to physicalConnectionClosed() for medium WIFI_LAN while NearbyRecorder has active medium BLUETOOTH -- metadata{ service_id: 0 }
03-21 12:21:17.576 10176-30596/? W/NearbyConnections: Unexpected call to physicalConnectionClosed() for medium WIFI_LAN with no corresponding EstablishedConnection that was previously opened. -- metadata{ service_id: 0 }
03-21 12:21:17.579 10176-30596/? W/NearbyConnections: NearbyRecorder expected no more active physical connections before logging this endpoint connection. -- metadata{ service_id: 0 }
03-21 12:21:17.585 3336-3929/? E/BluetoothRemoteDevices: setRfcommConnected false
03-21 12:21:17.586 30317-30317/com.alienff.ntest I/Log: [21.03.2018 12:21:17.586] [main] MainActivity: onPayloadTransferUpdate. endpointId: 7oRz payloadId: -5864147190526311071 bytesTransferred: 0 status: 2
03-21 12:21:17.597 30317-30317/com.alienff.ntest I/Log: [21.03.2018 12:21:17.596] [main] MainActivity: onDisconnected: 7oRz
Do you know how to make google nearby connections reconnect reliably?
Thank you!

I haven't seen this before, so I'm going to have you do some debugging for me.
Give me the model names of all the devices you can reproduce this on.
Tell me what type of Payload (BYTE, FILE, STREAM) you're sending.
Reproduce this bug while running logcat. Look for the log tags "NearbyConnections" and "NearbyMediums". Let me know if you see any errors/warnings.
Reproduce this bug, and then force kill your app. Wait 45 seconds. You should see Wifi/Bluetooth toggle off/on. Reopen the app and try to reproduce again.
Current thoughts:
Status Code 2 is "PayloadTransferUpdate.Status.FAILURE". Usually that's immediately followed by a disconnection because the socket is assumed broken. However, it doesn't look like the socket has gone bad. You're still receiving data and, internally, we send a flurry of control messages over the socket when connecting and those are all going through successfully or you wouldn't get onConnectionResult. That means something is going wrong with the Payload itself; either on your side, or ours. I suspect you're sending either FILE or STREAM payloads because I don't know of a way that BYTE payloads can fail. FILE payloads can fail if the file has moved or the ParcelFileDescriptor becomes invalid. STREAM payloads can fail if the socket/ParceFileDescriptor are closed or garbage collected.
Disclaimer: I work on Nearby Connections

Related

Bidirectional communication of Unix sockets

I'm trying to create a server that sets up a Unix socket and listens for clients which send/receive data. I've made a small repository to recreate the problem.
The server runs and it can receive data from the clients that connect, but I can't get the server response to be read from the client without an error on the server.
I have commented out the offending code on the client and server. Uncomment both to recreate the problem.
When the code to respond to the client is uncommented, I get this error on the server:
thread '' panicked at 'called Result::unwrap() on an Err value: Os { code: 11, kind: WouldBlock, message: "Resource temporarily unavailable" }', src/main.rs:77:42
MRE Link
Your code calls set_read_timeout to set the timeout on the socket. Its documentation states that on Unix it results in a WouldBlock error in case of timeout, which is precisely what happens to you.
As to why your client times out, the likely reason is that the server calls stream.read_to_string(&mut response), which reads the stream until end-of-file. On the other hand, your client calls write_all() followed by flush(), and (after uncommenting the offending code) attempts to read the response. But the attempt to read the response means that the stream is not closed, so the server will wait for EOF, and you have a deadlock on your hands. Note that none of this is specific to Rust; you would have the exact same issue in C++ or Python.
To fix the issue, you need to use a protocol in your communication. A very simple protocol could consist of first sending the message size (in a fixed format, perhaps 4 bytes in length) and only then the actual message. The code that reads from the stream would do the same: first read the message size and then the message itself. Even better than inventing your own protocol would be to use an existing one, e.g. to exchange messages using serde.

How Can I Manipulate Some/IP Message Content On Run Time?

I was trying to manipulate SOME/IP messages by falsifying their content(Payload) sent between 2 ECUs at run time.
After setting up the Hardware VN6510A MAC Bypassing and integrating it in the data traffic path between those 2 ECUs to monitor and control all Ethernet data streams.
ECU A ---> eth1 interface --VN6510A-- eth2 interface ---> ECU B
I successfully catch our target SOME/IP messages and I also succefully manipulate their paylod.
But at the end we got 2 SOME/IP messages: the real coming message and the falsified message forwarded at the same time.
How could we bound those 2 SOME/IP messages, the real message and the falsified message together, so that we could have just one falsified SOME/IP message, knowing that I am using the same SOME/IP message handle.
I used the callback function void OnEthPacket(LONG channel, LONG dir, LONG packet) to register a received Ethernet packet.
Probably by setting your VN.... to "Direct" and not "MAC Bypassing"
Well we could not manipulate Messages at run time using the vector box VN6510A Solution because simply their box doesn't support this feature.

Python socket.getdefaulttimeout() is None, but getting "timeout: timed out"

How can I determine what the numeric timeout value is that is causing the below stack trace?
...
File "/usr/lib/python2.7/httplib.py", line 548, in read
s = self._safe_read(self.length)
File "/usr/lib/python2.7/httplib.py", line 647, in _safe_read
chunk = self.fp.read(min(amt, MAXAMOUNT))
File "/usr/lib/python2.7/socket.py", line 380, in read
data = self._sock.recv(left)
timeout: timed out
After importing my modules, the result of socket.getdefaulttimeout() is None (note that this isn't the same situation as what produced the above, since getting those requires an 8-hour stress run on the system).
My code is not setting any timeout values (default or otherwise) AFAICT. I have not yet been able to find any hint that 3rd party libraries are doing so either.
Obviously there's some timeout somewhere in the system. I want to know the numeric value, so that I can have the system back off as it is approached.
This is python 2.7 under ubuntu 12.04.
Edit:
The connection is to localhost (talking to CouchDB listening on 127.0.0.1), so NAT shouldn't be an issue. The timeout only occurs when the DB is under heavy load, which implies to me that it's only when the DB is getting backed up and cannot respond quickly enough to requests, which is why I would like to know what the timeout is, so I can track response times and throttle incoming requests when the response time gets over something like 50% of the timeout.
Not knowing anything more my guess would be that NAT tracking expires due to long inactivity and unfortunately in most cases you won't be able to discover exact timeout value. Workaround would be to introduce some sort of keep alive packets to your protocol if there's such a possibility.

lwip - what's the reason tcp socket blocked in send()?

I am make a application base on lwip,the applcation just send data to the server;
When my app works for some times (about 5 hours),I found that the send thread hung in send() function,and after about 30min send() return 0,and my thread run agin;
In the server side ,have make a keepalive,its time is 5min,when my app hungs,5min later the server close the sockect,but my app have not get this,still hungs in send() until 30min get 0 return; why this happen?
1: the up speed is not enough to send data,it will hungs in send?
2: maybe the server have not read data on time,and it make send buff full and hungs?
how can i avoid these peoblems in my code ? I have try to set TCP_NODELAY,SO_SNDTIMEO and select before send,but also have this problem.
send() blocks when the receiver is too far behind the sender. recv() returns zero when the peer has closed the connection, which means you must close the socket and stop reading.

How can I test TCP socket status in Perl?

I've got a TCP socket which reads data. When an error occurs when reading the data, I return an undef (NULL) value. Errors can be caused by badly formatted messages or broken sockets. Can someone tell me if there is a specific function which returns the status of a socket?
There are three ways to detect whether the socket is open or closed, but neither of them are 100% full proof.
The first is to attempt a read on the socket as follows:
my $ret = recv($sockfd, $buff, 1, MSG_PEEK | MSG_NOWAIT);
If the socket has went through an orderly shutdown, i.e. the peer called shutdown for writing or called close AND the FIN packet has arrived then this call will result in a 0 length read indicating a closed socket. This also helps if your peer application crashed since the OS will close the connection and send a FIN. However, if your peer machine has crashed or your peer application has locked up this won't help you since each end of the connection maintains independent state.
A second way to detect a broken connection is by probing your peer. If you send a 0 length packet to your peer ( which is should be able to handle ) and the application has crashed then you send a second 0 length packet your application will get the SIG_PIPE signal indicating a broken pipe.
Another way to deal with this issue is to use an application level heartbeat in which the peers periodically send a heartbeat packet to each other indicating that they are alive and functioning properly.
One last option is to use the SO_KEEPALIVE socket option, although this is of limited use since it will only detect a broken socket after approximately 2 hours of inactivity.
If you really must know fairly quickly when a connection is broken, then the most reliable option is probably going to be the application level heartbeat.
doh!, the answer was obvious in retrospect, use the connected call.
$socket = IO::Socket::INET(localhost, 1000);
die "no connection" unless $socket -> connected();
$socket -> send("your face here for $20");
die "socket is dead" unless $socket -> connected();
$socket -> recv($data);