svinota / mdns

mDNS library
GNU General Public License v3.0
21 stars 10 forks source link

How to browse services ? #8

Open titilambert opened 10 years ago

titilambert commented 10 years ago

Hello ! I'm trying to use your beautiful lib ! I succeed to register my service using issue #3 . Now I'm trying to use the Service Browser. Could you give me an example of it ? After I finish my tests, I could submit a pull request with some basic examples if you want.

svinota commented 10 years ago
# start mdns
In [1]: from mdns.zeroconf import *
In [2]: from socket import *
In [3]: r = Zeroconf(("127.0.0.1",))

# register own service, just as example
In [4]: desc = {'version':'0.10','a':'test value', 'b':'another value'}
In [5]: n = "vala._workstation._tcp.local."
In [6]: d = "_workstation._tcp.local."
In [7]: info = ServiceInfo(d, n, inet_aton("127.0.0.6"), 1234)
In [8]: r.register_service(info)

# browse own services
In [9]: r.services
Out[9]: {'vala._workstation._tcp.local.': service[vala._workstation._tcp.local.,['127.0.0.6']:1234,]}

# browse cache entries
In [10]: r.cache.entries()
Out[10]: 
[record[txt,in,iPhone._device-info._tcp.local.,4500/4481.0,'\x0bmodel=N53AP'],
 record[txt,in-unique,linux-4 [28:d2:44:3f:f6:58]._workstation._tcp.local.,4500/4461.0,'\x00'],
 record[srv,in-unique,linux-4 [28:d2:44:3f:f6:58]._workstation._tcp.local.,120/81.0,linux-4.local.:9],
 record[ptr,in,_workstation._tcp.local.,4500/4461.0,linux-4 [28:d2:44:3f:f6:58]._workstation._tcp.local.],
 record[ptr,in,_workstation._tcp.local.,4500/4461.0,linux [a0:48:1c:15:87:ab]._workstation._tcp.local.],
 record[ptr,in,_workstation._tcp.local.,3600/3562.0,vala._workstation._tcp.local.],
 fe:80:0:0:0:0:0:0:50:54:0:ff:fe:e4:ee:29 (reachable),
 fe:80:0:0:0:0:0:0:12:dd:b1:ff:fe:b9:5b:be (reachable),
 192.168.1.68 (reachable),
 fe:80:0:0:0:0:0:0:a2:48:1c:ff:fe:15:87:ab (reachable),
 192.168.1.178 (reachable),
 fe:80:0:0:0:0:0:0:2a:d2:44:ff:fe:3f:f6:58 (reachable),
 192.168.1.179 (reachable),
 fe:80:0:0:0:0:0:0:22:c9:d0:ff:fe:7b:2e:a3 (reachable),
 192.168.1.182 (reachable),
 record[srv,in-unique,linux [a0:48:1c:15:87:ab]._workstation._tcp.local.,120/81.0,linux.local.:9],
 record[srv,in,vala._workstation._tcp.local.,3600/3562.0,vala._workstation._tcp.local.:1234],
 record[txt,in,vala._workstation._tcp.local.,3600/3562.0,''],
 127.0.0.6 (reachable)]

# match by name
In [11]: r.cache.entries_with_name('vala._workstation._tcp.local.')
Out[11]: 
[record[srv,in,vala._workstation._tcp.local.,3600/3508.0,vala._workstation._tcp.local.:1234],
 record[txt,in,vala._workstation._tcp.local.,3600/3508.0,''],
 127.0.0.6 (reachable)]

You can also play around with structures in ipython.

And thanks for heads-up, this library needs some refactoring.

titilambert commented 10 years ago

Thanks ! Do you plan to support python3 ?

svinota commented 10 years ago

I have to :) So if it doesn't work with python3 now, it should be fixed soon. I didn't touch this package for too long, actually. Maybe, time to revive it.

titilambert commented 10 years ago

Oki, I will to try to do it ! One more question: In fact, I want to discovert all bonjour user inthe network. When I run your example, I have to launch my pidgin after I create the "r" object... Which function do I need to relaunch the discovering ?

Thanks !

svinota commented 10 years ago

If you have a service record in the cache, you can use request() method to update it. Beside of that, all updates are done asynchronously, so, when something changes, you'll see it in the cache.

titilambert commented 10 years ago

oki but at the beginning I don't have any services, and pidgin seems resend registration only on login ...

svinota commented 10 years ago

Ahha... Right now I can not check it -- but tomorrow for sure will provide you the code (and/or fix the library, depends)

titilambert commented 10 years ago

Your libs seems python 3.4 compatible :) I manage to remove the dependency to crypto

titilambert commented 10 years ago

Thanks !

svinota commented 10 years ago

Actually, crypto is required by DNSSEC extensions. So I have just to make this dependency optional.

titilambert commented 10 years ago

Not for python 3.4 :(, I get :

.... ..../mdns/zeroconf.py", line 829, in read_name len = ord(self.data[off]) TypeError: ord() expected string of length 1, but int found

I just opened an other issue for this subject...

svinota commented 10 years ago

Yep. Thanks a lot! Will fix it.

svinota commented 10 years ago

So, about pidgin records.

If you start pidgin, then mdns: you can use r.get_service_info('record.name', 'full.pidgin.record.name.') (just replace strings with what pidgin uses)

If you start mdns, then pidgin: pidgin on login will send a notification and you will get it in the cache automatically.

titilambert commented 10 years ago

Thanks ! I will try to test it to night (EST time)

svinota commented 10 years ago

There is a possibility, that the record can be short-term, and will be expired soon. For this short-term records one can use listeners as callbacks: https://github.com/svinota/mdns/blob/master/mdns/zeroconf.py#L1888

titilambert commented 10 years ago

Hello ! I just don't get the get_service_info function. I get this from cache.entries() from pidgin:

Out[46]: 
[record[ptr,in,_presence._tcp.local.,4500/4499.0,Me_on_my_computer@absol._presence._tcp.local.],
 fe:80:0:0:0:0:0:0:4a:5b:39:ff:fe:70:34:aa (reachable),
 192.168.2.11 (reachable),
 <repr(<mdns.zeroconf.DNSText at 0x7f0b773f18d0>) failed: TypeError: can't concat bytes to str>,
 record[srv,in-unique,Me_on_my_computer@absol._presence._tcp.local.,120/119.0,absol.local.:5298],
 record[ptr,in,_services._dns-sd._udp.local.,4500/4499.0,_presence._tcp.local.]]

I just fail to refetch pidgin informations. I tried: get_service_info('_presence._tcp.local.', '._presence._tcp.local.') get_service_info('_presence._tcp.local.', 'Me_on_my_computer@absol._presence._tcp.local.')

But nothing seems work...

Thanks !

svinota commented 10 years ago

Actually, it should return appropriate service record from cache after update. But, obviously, doesn't. Investigating.

svinota commented 10 years ago

No, it does :)

Look, it return services, not pointers:

$ avahi-browse -r -a -t
+ virbr0 IPv4 linux-4 [fe:54:00:91:f7:e6]                   Workstation          local
+ wlp3s0 IPv4 linux-4 [5c:51:4f:fa:9f:65]                   Workstation          local
= virbr0 IPv4 linux-4 [fe:54:00:91:f7:e6]                   Workstation          local
   hostname = [linux-4.local]
   address = [192.168.122.1]
   port = [9]
   txt = []
= wlp3s0 IPv4 linux-4 [5c:51:4f:fa:9f:65]                   Workstation          local
   hostname = [linux-4.local]
   address = [10.0.0.205]
   port = [9]
   txt = []
In [20]: r.get_service_info('local.', 'linux-4.local.')
Out[20]: service[linux-4.local.,['10.0.0.205', '192.168.122.1']:None,]

But in your case, probably, a record is required, not a service. So, looking, how to get it (working with services, never needed this before, so can be not implemented yet)

svinota commented 10 years ago

Could you pls tell how to set up pidgin to provide these mdns records? I have pidgin 2.10.9 on Fedora 20, but see no such «presence» records in avahi database.

titilambert commented 10 years ago

you have to add a "Bonjour" account in your configuration. Accounts -> Manage Accounts -> Add... -> Protocol: Bonjour

svinota commented 10 years ago

Great. What I did: started Pidgin with my name (svinota), after that launched mdns:

In [13]: r.get_service_info('local.', 'svinota@linux._presence._tcp.local.')

In [14]: r.cache.cache['svinota@linux._presence._tcp.local.']
Out[14]: 
[record[txt,in-unique,svinota@linux._presence._tcp.local.,4500/4010.0,'\x04vc=!\nver=2.10.9\x0enode=libpu...'],
 record[srv,in-unique,svinota@linux._presence._tcp.local.,120/105.0,linux.local.:5298]]

In [15]: p = r.cache.cache['svinota@linux._presence._tcp.local.'][0]

In [16]: p.properties
Out[16]: 
{'1st': 'svinota',
 'last': 0,
 'node': 'libpurple',
 'port.p2pj': '5298',
 'status': 'avail',
 'txtvers': '1',
 'vc': '!',
 'ver': '2.10.9'}

This is a bit weird way to get info, yep, but it is usable right now; more convenient way you wait or propose as a patchset.

gepd commented 7 years ago

I know this repository it's not updated since 2014, but maybe you may help me.

I'm developing a plugin for sublime text and I need to browse/discover Arduino/ESP devices. I was using zeroconf with _arduino._tcp.local. and it works fine. But zeroconf works with netifaces and I can't make run that package in the sublime text environment because it's written in C. So I'm looking for an alternative and this repository seems to work without the netifaces dependence.

I tried with the examples you wrote above but I didn't have luck, can you tell me how should I do it with the arduino service?

svinota commented 7 years ago

Actually I had a plan to write an implementation completely from scratch, possibly based on pyroute2, so didn't pay attention to this repo, sorry, it may be in a broken state. Give me some time to review the repo and possibly fix it enough to launch samples at least.

gepd commented 7 years ago

Thanks @svinota , I'll really appreciate your help, I'm a little lost with this subject and this it's an important feature to work with that kind of hardware.