Menu

service discovery failure

mtraut
2010-02-01
2013-01-24
  • mtraut

    mtraut - 2010-02-01

    i've worked on this for two days - i can't find the reason:

    i have two processes on the same machine, the service provider and the service client. both start JmDNS on the host adress in the WLAN interface. when i am starting the service provider first, the client does not find the services, starting the client first the services are discovered.

     
  • Pierre Frisch

    Pierre Frisch - 2010-03-09

    I have just merged the Service Listener fix to Top of Tree. I am a bit concerned about the second one. This would prevent jmDNS from finding itself which may be an issue for certain usage pattern.

     
  • Mike Power

    Mike Power - 2010-03-16

    I can not get to the source because the ports seem to be closed.  I was using this command
    cvs -d:pserver:anonymous@jmdns.cvs.sourceforge.net:/cvsroot/jmdns login

    I am running into a similar problem.  Where I have a program with one jmdns instance that registers some services and then looks for services of the same time.  I run the program twice and only the first program run is able to see all services registered.

     
  • Pierre Frisch

    Pierre Frisch - 2010-03-17

    I am just posted version 3.1.1 with a fix for this problem.

     
  • Mike Power

    Mike Power - 2010-03-17

    Hmm, now I am getting null pointer exceptions out of the ServiceInfoImpl

            at javax.jmdns.impl.ServiceInfoImpl.getPropertyString(ServiceInfoImpl.java:405)
            at javax.jmdns.impl.ServiceInfoImpl.getURL(ServiceInfoImpl.java:371)
            at javax.jmdns.impl.ServiceInfoImpl.getURL(ServiceInfoImpl.java:361)
            at com.intuit.mdnstest.App.outputService(App.java:50)
            at com.intuit.mdnstest.App.outputEvent(App.java:64)
            at com.intuit.mdnstest.App$OutputServiceListener.serviceAdded(App.java:72)
            at javax.jmdns.impl.JmDNSImpl.updateRecord(JmDNSImpl.java:953)

    With 3.1 I could get my own service out of the list call only when I had the avahi-daemon running (which is ood).  Now I can not get my own service at all. 

    I still can not run two instance and have them see each other's services via the list call on JmDNS.

     
  • Pierre Frisch

    Pierre Frisch - 2010-03-17

    Sorry this uncovered another bug.  It is fixed and I have tried your case and it works for me.
    In 2 terminal windows if you run
    1-$ java -jar jmdns.jar -rs toto coucou _tcp.local. 9999 txt=here
    2-$java -jar jmdns.jar
    The browser will see the service published by the first run.

    I will push a new version later today.

     
  • Pierre Frisch

    Pierre Frisch - 2010-03-17

    Posted 3.1.2 to replace 3.1.1 Please let me know if it fixes you issues.

     
  • Mike Power

    Mike Power - 2010-03-17

    Well I am still getting the null pointer. 
    The script you gave does not work for me.  The browser does not detect the addition of the service.  Looking at WireShark it looks like the JmDNS object with the registered service is not responding to queries.

    What system are you running?  Windows, Linux, 32bit, java 1.5, 1.6?  Is avahi-daemon on the system?  I keep seeing different behavior when avahi-daemon is running versus when it is not. 

    I also found that list does not produce the ServiceInfo if there is already a listener attached to that type.  Did not do any triage to figure out of the behaviour is more general.  Is that a bug?

    I started putting things into junit tests.  You want them?

     
  • Pierre Frisch

    Pierre Frisch - 2010-03-18

    junit tests would be great.

    I am bit surprised. Are you sure it is the same exception? There was case in which this could happen but I am quite sure I plugged that hole. For the discovery, are you sure there is not a firewall or some other process that prevent the connection to the machine.

    I am running on Snow Leopard on a very busy network so it is Java 1.6 only on 64bits.
    I am sorry but I do not have a Linux machine handy to test it.

     
  • Pierre Frisch

    Pierre Frisch - 2010-03-18

    I also found that list does not produce the ServiceInfo if there is already a listener attached to that type. Did not do any triage to figure out of the behaviour is more general. Is that a bug?

    This could very well be a timing issue. if you call list and there is no registered listener it will wait for 200ms for the service to appear. If you register a listener that tempo does not occurs so if you register a listener and immediately ask for the list you will probably have an empty list. if you wait a bit then you should see the result.

    Could you confirm the behavior?

     
  • Mike Power

    Mike Power - 2010-03-18

    I added the tests as patches to a bug/feature request:
    https://sourceforge.net/tracker/?func=detail&aid=2972843&group_id=93852&atid=605791

    If you look at my test you'll see I immediately call list after adding the listener and registering the service.

    I'll change the code to wait 400ms and try it again.

     
  • Mike Power

    Mike Power - 2010-03-20

    Hmm perhaps I do not understand something I verified that jmdns is getting the packets.  In fact it processes them creates a bunch of DNSAnswers but then it never seems to send them.

    In the Responder.run
    there is code like

                            DNSOutgoing out = null;
                            if (isUnicast)
                            {
                                out = new DNSOutgoing(DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA, false);
                            }
                            if (out != null)
                            {
                                for (DNSQuestion question : questions)
                                {
                                    out.addQuestion(question);
                                }
                                for (DNSRecord answer : answers)
                                {
                                    out = this._jmDNSImpl.addAnswer(_in, _addr, _port, out, answer);
                                }
                                this._jmDNSImpl.send(out);
                            }
    

    As far as I can tell this means jmdns will never respond to multicast requests?  Do I read that right?  Does the jmdns browser ever do unicast requests?  Does it simply default to the localhost?  Maybe jmdns does not support multicast responses yet?

     
  • Mike Power

    Mike Power - 2010-03-20

    Sorry it seems I some how copied and pasted the code twice in there.

     
  • Pierre Frisch

    Pierre Frisch - 2010-03-23

    I have just posted the 3.1.3 with fixes to make the test cases work correctly. Please look at the test case as I had to change some of them and this may help clarify how JmDNS works.

     
  • Mike Power

    Mike Power - 2010-03-25

    Well it seems I forgot to make the tests part of the ant release.  I'll get the code going and send another patch.  Meanwhile I am wrangling with another test cast

        @Test
        public void testRegisterAndListServiceOnOtherRegistry() throws IOException
        {
            JmDNS registry = null;
            JmDNS newServiceRegistry = null;
            try
            {
                registry = JmDNS.create();

                registry.registerService(service);

                newServiceRegistry = JmDNS.create();
                ServiceInfo fetchedServices = newServiceRegistry.list(service.getType());
                assertEquals("Did not get the expected services listed:", 1, fetchedServices.length);
                assertEquals("Did not get the expected service type:", service.getType(), fetchedServices.getType());
                assertEquals("Did not get the expected service name:", service.getName(), fetchedServices.getName());
                assertEquals("Did not get the expected service fully qualified name:", service.getQualifiedName(), fetchedServices.getQualifiedName());
                newServiceRegistry.getServiceInfo(service.getType(), service.getName());

                assertEquals("Did not get the expected service info: ", service, fetchedServices);
            }
            finally
            {
                if (registry != null)
                    registry.close();
                if (newServiceRegistry != null)
                    newServiceRegistry.close();
            }
        }

    The test fails, service count it zero.  Based on my current understanding I would think that this test case is correct.

     
  • Pierre Frisch

    Pierre Frisch - 2010-03-25

    This will not work because of the ports allocation. The 2 DNS conflict with each other.
    Inverting the DNS creation will make it work.

        @Test
        public void testRegisterAndListServiceOnOtherRegistry() throws IOException
        {
            JmDNS registry = null;
            JmDNS newServiceRegistry = null;
            try
            {
                newServiceRegistry = JmDNS.create();
                registry = JmDNS.create();

                registry.registerService(service);

                ServiceInfo fetchedServices = newServiceRegistry.list(service.getType());
                assertEquals("Did not get the expected services listed:", 1, fetchedServices.length);
                assertEquals("Did not get the expected service type:", service.getType(), fetchedServices.getType());
                assertEquals("Did not get the expected service name:", service.getName(), fetchedServices.getName());
                assertEquals("Did not get the expected service fully qualified name:", service.getQualifiedName(), fetchedServices.getQualifiedName());
                newServiceRegistry.getServiceInfo(service.getType(), service.getName());

                assertEquals("Did not get the expected service info: ", service, fetchedServices);
            }
            finally
            {
                if (registry != null)
                    registry.close();
                if (newServiceRegistry != null)
                    newServiceRegistry.close();
            }
        }

     
  • Mike Power

    Mike Power - 2010-03-26

    Hmm javadoc says "Multiple MulticastSocket's may subscribe to a multicast group and port concurrently, and they will all receive group datagrams. " but what java says and what java does can be two different things.

    So I created a test:
        @Test
        public void testTwoMulticastPortsAtOnce() throws UnknownHostException, IOException
        {
          String firstMessage = "ping";
          String secondMessage = "pong";
          InetAddress someInet = InetAddress.getByName("224.0.0.252");
          MulticastSocket firstSocket = new MulticastSocket(8053);
          MulticastSocket secondSocket = new MulticastSocket(8053);

          firstSocket.joinGroup(someInet);
          secondSocket.joinGroup(someInet);

          DatagramPacket data = new DatagramPacket(firstMessage.getBytes("UTF-8"), firstMessage.length(), someInet, 8053);
          firstSocket.send(data);

          secondSocket.receive(data);
          String fromFirst = new String(data.getData(), "UTF-8");
          assertEquals("Expected the second socket to recieve the same message the first socket sent", firstMessage, fromFirst);
          //Make sure the first socket had read its own message
          firstSocket.receive(data);

          data = new DatagramPacket(secondMessage.getBytes("UTF-8"), secondMessage.length(), someInet, 8053);
          secondSocket.send(data);

          firstSocket.receive(data);
          String fromSecond = new String(data.getData(), "UTF-8");
          assertEquals("Expected the first socket to recieve the same message the second socket sent", secondMessage, fromSecond);
        }

    The test passes.  This is great because it means that mDNS can be used by both a chat client and a web server running on the same computer.

    I have a use case with jmdns that I am trying to play with however I can not get it to work.  The basic idea is to use jmdns on tomcat to allow one apache web server to discover the tomcat servers and proxy/load balance all of them.  Since I do not want to dig my fingers into mod_jk at the moment I have written everything into two servlets.  One servlet launches when tomcat starts and uses jmdns to advertise itself.  Next I hit the browser on a jsp page to download a configuration file.  The jsp page starts another JmDNS instance and does a listing on the application type that was used to advertise the application.  It then enumerates over the result and spits the configuration into the jsp result. 

    However right now the jsp page comes back empty because the List request gives be back an empty list or null I forget which.  I have attached a debugger and watched traffic with WireShark.  The jsp successfully sends out the request for services, JmDNS takes in this request, does a whole bundle of processing on it and then decides not to respond.  It never sends a mDNS packet out with information about the type and instance that was registered to it. 

    Flipping around the creation of the registeries work because that means the listing registry is online when the advertising registry makes its initial publish.  When the advertising registery makes its initial publish the listing registry picks it up and when called populates list with the result. 

    However if with the advertising registry comes up first it does its initial publish which the listing registry does not get because it does not exist yet.  When the listing registry comes online and the list function is called on it.  The listing registry then sends out a mDNS query that the advertising registry does not respond to.

    Let me know if I am getting anything wrong, I am fairly new to this stuff and it is quite complicated. 

     
  • Pierre Frisch

    Pierre Frisch - 2010-03-29

    I think I nailed your problem. At least the test case is working. Thanks for pointing out the problem.
    I have posted revision 3.1.4

     
  • Mike Power

    Mike Power - 2010-03-30

    The test case does now work.  However the code for my use case does not.  I still see the requests flying across the wire.  So there seems to be something  wrong with the listing JmDNS.  I'll see if I have time to attach a debugger tomorrow and see what I can learn. 

    Thanks for all the bug fixes.  I am really excited about this project. 

     
  • Pierre Frisch

    Pierre Frisch - 2010-03-30

    Are you sure it does not respond? It may respond too late. I had to increase the timeout to get things to work and I have added a timeout param on the list API. On a busy network it can take 6 seconds or more for the services to be available to clients.

     
  • Pierre Frisch

    Pierre Frisch - 2010-03-31

    I have just posted 3.1.5 that should improve the response time let me know what you think.

     
  • Mike Power

    Mike Power - 2010-04-12

    Yeah that did it combined with my ajb versus ajp I have a working demo.  Thanks for all the bug fixes.

     

Log in to post a comment.