youviewtv/tinydnssd

SocketTimeoutExceptions and log statements

ryanhubbell opened this issue · 9 comments

While it's not crashing, I'm seeing SocketTimeoutExceptions all over the place when scanning.

Also, there doesn't seem to be a way to shut off log statements. These are great when debugging, but in a production app, I'd rather it not print any log statements (or perhaps JUST critical errors).

MulticastSocket sock = new MulticastSocket(PORT); seems to do the trick with the Timeout Exception and resolving the DNS records.

@wnemay Where does this trick go to? In the current implementation, in resolve() and discover() methods in MDNSDiscover class, It's called as MulticastSocket sock = new MulticastSocket();

So setting the Port Number resolves the issue ? If it's is there any specific PORT Number to set ?

Thanks.

I figured out how to initialise the MulticastSocket with the predefined port number but unfortunately, it doesn't resolve the SocketTimeoutExceptions.

I've a weird behavior though, I guess it would be the reason for these exceptions. Whenever I start the discovery, my Wifi Connection drops and the device connects back to LTE network (I've Nexus 6P). So it finds the devices in my sub network but when trying to make a socket connection to retrieve the TXT Records, it fails and drops the Wifi Connection, so it fails with SocketTimeOutException.

I've used this library in a Beta version where I can send the build to test users and get some feedback, and I get the same logs from them. They all share the same failure. Any idea what is going on ? @wnemay @ryanidev @youview-android-team

Thanks,
Okan.

huycn commented

I get the same issue. However, it happens only with services advertised by Avahi on Linux only. It works well with for services advertised with command line dns-sd -P (from Bonjour for Windows package).

huycn commented

I think I found the source of the exception. In MDNSDiscover.resolve(), we try to get A record, which is not sent by Avahi, thus the condition result.a == null in the while loop is not satisfied and then we continue to receive() on the socket, which eventually causes the timeout.

I am currently getting this issue. @huycn were you able to resolve it with the A record? Can we address this and submit a merge request, or is it as simple as adding an A record in Avahi?

huycn commented

@kylemallory For my project, I ended up by modify the method MDNSDiscover.resolve() to remove result.a == null from the loop's condition, so it becomes:
while (result.srv == null || result.txt == null)
Even though, this change works for my project (as I don't use A record anyway), I don't consider it as a proper fix since it breaks method's contract. Thus, I didn't submit a merge request.

By looking at the method, it seems that it does the right thing: it asks for A record among other things, thus it's legitimate to expect for it. The reason why Avahi don't sent it is out of my knowledge.

Thanks @huycn. I'll dig into it more. I am creating the Avahi messages on the service side; maybe I can find a way to include the A records explicitly. If not, I guess I can fork...

Will this ever be solved? What would be the solution?
In my case "a" is not filled (null) so I will never receive the MDNSDiscover.Result.

I now altered the code myself but I don't really know if I'm doing the right thing because I don't have lowlevel knowledge about mDNS. I catched the SocketTimeoutException around the while loop and in the finaly part I still return the result even if it does not has a or srv data.

If you run the (crappy) NSdChat app example from Google and register its service and listen to it with another device using this library the a and the srv are not filled. If you could make it work with this example the library would be fixed I guess..

        // records could be returned in different packets, so we have to loop
        // timeout applies to the acquisition of ALL packets
        try {
            while (result.a == null || result.srv == null || result.txt == null) {
                if (timeout != 0) {
                    int remaining = (int) (endTime - System.currentTimeMillis());
                    if (remaining <= 0) {
                        break;
                    }
                    sock.setSoTimeout(remaining);
                }
                sock.receive(packet);
                if (DEBUG) System.out.println("\n\nIncoming packet:");
                if (DEBUG) hexdump(packet.getData(), 0, packet.getLength());
                decode(packet.getData(), packet.getLength(), result);
            }
        //NOTE RBR: added this catch so if some part is and it times out missing we still get the result
        }catch(SocketTimeoutException e){
            e.printStackTrace();
        }
        finally {
            return result;
        }

Update:
Found a great alternative that works:
https://github.com/andriydruk/RxDNSSD
and example application with all features implemented:
https://github.com/andriydruk/BonjourBrowser