Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Service discovery example #6

Open
fhunleth opened this issue Dec 18, 2018 · 10 comments
Open

Service discovery example #6

fhunleth opened this issue Dec 18, 2018 · 10 comments

Comments

@fhunleth
Copy link
Contributor

I'd like to advertise an ssh service so that a laptop running on the same LAN can discover the device. I've tried avahi-browse _ssh._tcp on my Linux laptop and made several attempts with registering a service. Is there an example somewhere on how to do this? or something similar that I could modify? I saw that you could register PTR and TXT records in the readme, but my attempts to use those have failed.

@entone
Copy link
Contributor

entone commented Dec 18, 2018

I haven't specifically tested SSH advertising, but in general the TXT advertising has worked. Can you post your registration code for the SSH service?

@fhunleth
Copy link
Contributor Author

I tried a few things, but I definitely have the feeling of not knowing enough about mDNS to make good guesses. Here's one iteration:

    domain = "nerves.local"
    Mdns.Server.add_service(%Mdns.Server.Service{
      domain: domain,
      data: :ip,
      ttl: 120,
      type: :a
    })  
    Mdns.Server.add_service(%Mdns.Server.Service{
      domain: domain,
      data: "_ssh._tcp.local",
      ttl: 120,                                                                                                                                                                              
      type: :txt
    })       

@entone
Copy link
Contributor

entone commented Dec 18, 2018

can you try making :txt -> :ptr

@fhunleth
Copy link
Contributor Author

That was my first try.

@entone
Copy link
Contributor

entone commented Dec 18, 2018

hmm, did you try using the built-in client?

Mdns.Client.query("_ssh._tcp.local")

anything with that?

@entone
Copy link
Contributor

entone commented Dec 18, 2018

also, you are starting the server as well?

ping nerves.local works fine?

@entone
Copy link
Contributor

entone commented Dec 18, 2018

after looking at the code, it may be necessary to pass the domain.

avahi-browse -d nerves.local _ssh._tcp

@entone
Copy link
Contributor

entone commented Dec 18, 2018

Specifically, this line https://github.com/rosetta-home/mdns/blob/master/lib/mdns/server.ex#L106

I'm not sure that is at all necessary.

@fazibear
Copy link
Contributor

fazibear commented May 13, 2019

This is what I've figured out today. Just an ssh service discovery.

[
  # create domain for an ip
  %Mdns.Server.Service{domain: "somedomain.local", data: :ip, ttl: 450, type: :a},

  # make service discoverable
  %Mdns.Server.Service{domain: "_services._dns-sd._udp.local",data: "_ssh._tcp.local",ttl: 4500, type: :ptr},

  # register ssh service
  %Mdns.Server.Service{domain: "_ssh._tcp.local",data: "SOME NAME._ssh._tcp.local",ttl: 4500, type: :ptr},


  # point service to our domain and port (22)
  %Mdns.Server.Service{domain: "SOME NAME._ssh._tcp.local",data: {0,0,22, 'somedomain.local'},ttl: 4500,type: :srv},

  # empty txt service (some tools expext that)
  %Mdns.Server.Service{domain: "SOME NAME._ssh._tcp.local",data: [],ttl: 4500,type: :txt})
] |> Enum.each(&Mdns.Server.add_service/1)

Also, there is pending PR with a working example: nerves-project-attic/nerves_init_gadget#62

Move the domain problem here: #7

@jackyz
Copy link

jackyz commented Nov 27, 2019

I had dig this problem for a while, and here is a example of service record.

service = "_nerves._tcp"
host = "hello"
domain = "local"

Mdns.Server.start(interface: ip_tuple)
Mdns.Server.set_ip(ip_tuple)
[
  # public the host :a
  %Mdns.Server.Service{domain: "#{host}.#{domain}", type: :a, ttl: 120, data: :ip},
  # public the service :ptr
  %Mdns.Server.Service{domain: "_services._dns-sd._udp.#{domain}", type: :ptr, ttl: 120, data: "#{service}.#{domain}"},
  # public the instance of the service :ptr
  %Mdns.Server.Service{domain: "#{service}.#{domain}", type: :ptr, ttl: 120, data: "#{host}.#{service}.#{domain}"},
  # public the info to connect the instance :srv
  # !!! you must use list instead of string when add srv recode due to the inet:dns just use list
  %Mdns.Server.Service{domain: String.to_charlist("#{host}.#{service}.#{domain}"), type: :srv, ttl: 120, data: {0, 0, 8080, String.to_charlist("#{host}.#{domain}")}},
  # public the extra info to connect the instance :txt
  %Mdns.Server.Service{domain: "#{host}.#{service}.#{domain}", type: :txt, ttl: 120, data: ["info=12341234"]}
] |> Enum.each(&Mdns.Server.add_service/1)

Logger.debug("Restarted Mdns server for service...")

Note the String.to_charlist usage when adding a :srv record, it's an ugly work around. there is a bug in somewhere, the inner inet:dns module only use list (instead of string). You can reproduce this bug easily.

the list will work well

DNS.Record.encode(%DNS.Record{header: %DNS.Header{aa: true, qr: true, opcode: 0, rcode: 0}, anlist: [%DNS.Resource{bm: [], class: :in, cnt: 0, type: :srv, ttl: 120, data: {0, 0, 8080, 'abc.local'}, domain: 'abc._nerves._tcp.local'}]})

but the string will throw an exception

DNS.Record.encode(%DNS.Record{header: %DNS.Header{aa: true, qr: true, opcode: 0, rcode: 0}, anlist: [%DNS.Resource{bm: [], class: :in, cnt: 0, type: :srv, ttl: 120, data: {0, 0, 8080, "abc.local"}, domain: "abc._nerves._tcp.local"}]})

There is still a problem in the L106. When the domain was set to a list, it's doesn't match the right side to_string(q.domain), I use to_sting(service.domain) as well, a careful improve was needed. maybe I will commit a pull request.

Then you can use dns-sd -L hello _nerves._tcp to test the result.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants