vstirbu / ZeroConf

ZeroConf plugin for Cordova/Phonegap 3.0
MIT License
38 stars 21 forks source link

ZeroConf finds no services #6

Closed y-lohse closed 9 years ago

y-lohse commented 10 years ago

Hi, I'm trying to use this plugin but I can't get it to discover any service. The console shows the Watch _calbr-wsgui._tcp.local. message but the callback is never fired. I can see the services using another app from the same device. My app has ACCESS_WIFI_STATE & CHANGE_WIFI_MULTICAST_STATE permissions. Any idea of what could cause thee problem?

vstirbu commented 10 years ago

I have experienced this situation but could not find the source of the problem.

So, in my case this behaviour is depended on the device. Some devices find the service from the start while on other I have to restart the application and then it works ok. (In my scenario I can afford to do that , but I'm well aware that this is not ideal).

The issue might be caused by switching the device WiFi to multicast mode. This might be quite slow (depending on WiFi chipset or processor?) and the Cordova callback gets somehow lost.

Do you have the same experience?

y-lohse commented 10 years ago

Thanks for the fast answer :)

The issues I have are with a Samung Galaxy tab 2. Sadly restarting the app doesn't help; however, a while ago, I accidentally left the discovery running without a timeout and it did find services. It's just extremely hard to reproduce so i didn't mention it, but that might indeed point to some slowlyness.

I also just tried it on my HTC One and it discovers the service right out of the box, and quickly.

FWIW the app I use on the galaxy tab which successfully discover services is ZeroConf Browser but it doesn't appear to be open source.

vstirbu commented 10 years ago

The zeroconf library outputs to the console the services found. Are you able to see anything in the log in Eclipse? There should be a json object containing the service details.

vstirbu commented 10 years ago

can you check this branch. Is is better?

y-lohse commented 9 years ago

Hi, unfortunately no, no change with that branch.

I'm using adb logcat for the logs but I assume it's the same than eclipse. There are no logs about service,s but there are DNS logs, not sure if they are related though:

D/ZeroConf( 8707): Watch _calbr-wsgui._tcp.local.
D/ZeroConf( 8707): Name: fe80::64b3:10ff:fe9d:3c52%p2p0.local. host: fe80::64b3:
10ff:fe9d:3c52%p2p0.local.

W/DNSIncoming( 8707): There was a problem reading the service name of the answer
 for domain:_printer._tcp.local.
E/DNSRecordType( 8707): Could not find record type for index: 49195
E/DNSIncoming( 8707): Could not find record type. domain: _printer._tcp.local.
E/DNSIncoming( 8707): dns[response,192.168.5.20:5353, length=295, id=0x0, flags=
0x8400:r:aa]
E/DNSIncoming( 8707):    0: 0000840000000001 00000003085f7072 696e746572045f74 6
370056c6f63616c     ........ ....._pr inter._t cp.local
E/DNSIncoming( 8707):   20: 00000c000100001c 20000300c00cc02b 0021800100001c20 0
01c003200000203     ........ .......+ .!...... ...2....
E/DNSIncoming( 8707):   40: 134e422d31384742 3243394546433030 30313533c01ac02b 0
010800100001c20     .NB-18GB 2C9EFC00 0153...+ ........
E/DNSIncoming( 8707):   60: 00b5097478747665 72733d310572703d 6c70056e6f74653d 0
871746f74616c3d     ...txtve rs=1.rp= lp.note= .qtotal=
E/DNSIncoming( 8707):   80: 310b7072696f7269 74793d35300a7479 3d69504636343530 1
770726f64756374     1.priori ty=50.ty =iPF6450 .product
E/DNSIncoming( 8707):   a0: 3d2843616e6f6e20 6950463634353029 1370646c3d617070 6
c69636174696f6e     =(Canon. iPF6450) .pdl=app lication
E/DNSIncoming( 8707):   c0: 2f7064662a61646d 696e75726c3d6874 74703a2f2f4e422d 3
138474232433945     /pdf*adm inurl=ht tp://NB- 18GB2C9E
E/DNSIncoming( 8707):   e0: 4643303030313533 2e6c6f63616c2e07 436f6c6f723d540d 5
061706572437573     FC000153 .local.. Color=T. PaperCus
E/DNSIncoming( 8707):  100: 746f6d3d54115061 7065724d61783d3e 69736f432d4132c0 4
00001800100001c     tom=T.Pa perMax=> isoC-A2. @.......
E/DNSIncoming( 8707):  120: 200004c0a80514
                    .......
W/DNSRecordClass( 8707): Could not find record class for index: 33
E/DNSIncoming( 8707): Could not find record class. domain: _printer._tcp.local.
type: TYPE_IGNORE index 0
E/DNSIncoming( 8707): dns[response,192.168.5.20:5353, length=295, id=0x0, flags=
0x8400:r:aa]
                    .......
E/ming$MessageInputStream( 8707): bad domain name: possible circular name detect
ed. Bad offset: 0xffffffff at 0x125
E/DNSRecordType( 8707): Could not find record type for index: -1
E/DNSIncoming( 8707): Could not find record type. domain:
E/DNSIncoming( 8707): dns[response,192.168.5.20:5353, length=295, id=0x0, flags=
0x8400:r:aa]
                    .......
W/DNSRecordClass( 8707): Could not find record class for index: -1
E/DNSIncoming( 8707): Could not find record class. domain:  type: TYPE_IGNORE in
dex 0
E/DNSIncoming( 8707): dns[response,192.168.5.20:5353, length=295, id=0x0, flags=
0x8400:r:aa]
                    .......
E/ming$MessageInputStream( 8707): bad domain name: possible circular name detect
ed. Bad offset: 0xffffffff at 0x125
E/DNSRecordType( 8707): Could not find record type for index: -1
E/DNSIncoming( 8707): Could not find record type. domain:
E/DNSIncoming( 8707): dns[response,192.168.5.20:5353, length=295, id=0x0, flags=
0x8400:r:aa]
                    .......
W/DNSRecordClass( 8707): Could not find record class for index: -1
E/DNSIncoming( 8707): Could not find record class. domain:  type: TYPE_IGNORE in
dex 0
E/DNSIncoming( 8707): dns[response,192.168.5.20:5353, length=295, id=0x0, flags=
0x8400:r:aa]

I left out some logs for clarity. They also don't show every time but I can't figure out when they do or don't.

vstirbu commented 9 years ago

I have not seen this kind of things in my logs.

vstirbu commented 9 years ago

I just noticed in your log that the ZeroConf watch registers with a link local IPv6 address (fe80:...) then the mDNS advertisements have IPv4 addresses.

Have you tried in another network configuration if it works?

y-lohse commented 9 years ago

No, I haven't. I'll see if I can work something out with our sysadmin :-)

Protoss78 commented 9 years ago

I experienced a similar behavior when I first tried this plugin a few days ago. I observed the following error behavior:

  1. I started my server application that uses jmdns to register a service (_http._tcp.local.)
  2. Then I started my android application where I use the zerconf plugin to watch for _http._tcp.local.
  3. No service was found, no event fired

Then I changed the scenario a little bit:

  1. I started my android app
  2. Then I started my server application
  3. Suddenly the 'added' event fired and my android app discovers the service

After some investigation I found a few articles on stackoverflow, that suggested to pass the InetAdress of the device to the jmdns constructor.

Therefore I added this method to ZeroConf.java class:

/**
     * Returns the first found IP address.
     * @return
     */
    public static InetAddress getIPAddress() {
        try {
            List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
            for (NetworkInterface intf : interfaces) {
                List<InetAddress> addrs = Collections.list(intf.getInetAddresses());
                for (InetAddress addr : addrs) {
                    if (!addr.isLoopbackAddress()) {
                        String sAddr = addr.getHostAddress().toUpperCase();
                        if (InetAddressUtils.isIPv4Address(sAddr)) {
                            return addr;
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

and changed this line in the setupWatcher() method:

jmdns = JmDNS.create(getIPAddress(), "ZeroConf");

After these changes I was able to discover my service in both scenarios. Hope this helps. :-)

vstirbu commented 9 years ago

This is great info! :)

It definitely fills the gap described by this issue but it locks the discovery to a specific IP address. If the address changes (e.g. move to another network), the setup watcher procedure has to be re-run to create a ZeroConf experience for the application.

This needs to be further investigated, although as always pull requests are welcome! :)

y-lohse commented 9 years ago

:+1: That worked, thanks!

In my use case the address change is rather unlikely so I'll probably use this. For the record, only the original device (running android 4.2) had this issue. A bunch of other devices running 4.4.X had no such problem.

Also for the record, the following packages need to be imported for @Protoss78 's solution:

import java.net.InetAddress;
import java.util.List;
import java.net.NetworkInterface;
import java.util.Collections;
import org.apache.http.conn.util.InetAddressUtils;

Thanks again for the help ;)

vstirbu commented 9 years ago

For the record, the response of ZeroConf Browsers on this issue: http://stackoverflow.com/a/23854825/1977815

Protoss78 commented 9 years ago

You're welcome guys. Sorry I can't contribute anymore at the moment, since I'm quite busy with a few projects. However, I had a few thoughts about the IP change problem and I'm currently also not sure how to approach that scenario. For my app it would be quite easy to solve, because in my use case the app is always running in a local Wifi network and has no online functionality. So probably the simplest approach would be to listen for connectivity changes. I've found a few examples for that: http://www.grokkingandroid.com/android-getting-notified-of-connectivity-changes/ http://android-er.blogspot.in/2011/01/check-rssi-by-monitoring-of.html

When I thought a little bit more about that, I stumbled upon one more question I was not able to answer myself: Does it even make sense to use ZeroConf in a non Wifi scenario? Are there any service providers out there who offer mDNS services via a cellular network?

vstirbu commented 9 years ago

There might be Android devices that have wired Ethernet, but most likely mDNS will not work over cellular or any connection that has a router.

@Protoss78 can you make a pull request if you have time. I've already implemented this, but it would be nice the solution to come from you :).

On a side note, this does not work on Android 4.0.3. I have to kill and restart the app and then the discovery works.

vstirbu commented 9 years ago

@Protoss78 Thanks for sending the pull request.

There is problem on Android 4.0.3 with using JmDNS.create with two arguments. It works very well if I provide only the IP address using only one argument. I have tried this also on Android 4.2.2 but can you try it also and confirm that works in your cases.

Protoss78 commented 9 years ago

I've tested the latest commit (where just the IP is passed to JmDNS.create) on two 4.0.3 tablets and a Nexus 5 on 4.4.4. Worked on all devices.

cleverplatypus commented 3 years ago

Hi, I had the same problem with the plugin not being able to list services advertised by another device using the same plugin. A bit of logging revealed that the getIPAddress function was always returning null because no IPv4 address was ever found.

I changed the method to the following and it now works.

//Additional imports
import java.net.Inet4Address;
import java.util.Enumeration;

public static InetAddress getIPAddress() {
    try { 
        for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) { 
            NetworkInterface intf = en.nextElement();
            for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) { 
                InetAddress inetAddress = enumIpAddr.nextElement(); 
                if (!inetAddress.isLoopbackAddress()) { 
                    if (inetAddress instanceof Inet4Address) {
                       return inetAddress;
                    } 
                } 
            } 
        } 
    } catch (Exception ex) { 
        Log.e("ZeroConf", "getIPAddress()", ex); 
    } 
    return null; 
}

There is still the caveat that the method always returns the first useful IP it finds, which might not be the right one for the use case, but there you go...