• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src/router/avahi-0.6.31/avahi-python/avahi-discover/
1#!@PYTHON@
2# -*-python-*-
3# This file is part of avahi.
4#
5# avahi is free software; you can redistribute it and/or modify it
6# under the terms of the GNU Lesser General Public License as
7# published by the Free Software Foundation; either version 2 of the
8# License, or (at your option) any later version.
9#
10# avahi is distributed in the hope that it will be useful, but WITHOUT
11# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
13# License for more details.
14#
15# You should have received a copy of the GNU Lesser General Public
16# License along with avahi; if not, write to the Free Software
17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18# USA.
19
20import os, sys
21
22try:
23    import avahi, gettext, gtk, gobject, dbus, avahi.ServiceTypeDatabase
24    gettext.bindtextdomain(@GETTEXT_PACKAGE@, @LOCALEDIR@)
25    gettext.textdomain(@GETTEXT_PACKAGE@)
26    _ = gettext.gettext
27except ImportError, e:
28    print "Sorry, to use this tool you need to install Avahi, pygtk and python-dbus.\n Error: %s" % e
29    sys.exit(1)
30except Exception, e:
31    print "Failed to initialize: %s" % e
32    sys.exit(1)
33
34
35## !!NOTE!! ##
36# It's really important to do this, else you won't see any events
37##
38try:
39    from dbus import DBusException
40    import dbus.glib
41except ImportError, e:
42    pass
43
44service_type_browsers = {}
45service_browsers = {}
46
47def error_msg(msg):
48    d = gtk.MessageDialog(parent=None, flags=gtk.DIALOG_MODAL,
49                          type=gtk.MESSAGE_ERROR, buttons=gtk.BUTTONS_OK)
50    d.set_markup(msg)
51    d.show_all()
52    d.run()
53    d.destroy()
54
55ui_dir = "@interfacesdir@"
56
57service_type_db = avahi.ServiceTypeDatabase.ServiceTypeDatabase()
58
59class Main_window:
60    def __init__(self, path="avahi-discover.ui", root="main_window", domain=None, **kwargs):
61        path = os.path.join(ui_dir, path)
62        gtk.window_set_default_icon_name("network-wired")
63        self.ui = gtk.Builder()
64        self.ui.add_from_file(path)
65        self.ui.connect_signals(self)
66        self.tree_view = self.ui.get_object("tree_view")
67        self.info_label = self.ui.get_object("info_label")
68        self.new()
69
70    def on_tree_view_cursor_changed(self, widget, *args):
71        (model, iter) = widget.get_selection().get_selected()
72        stype = None
73        if iter is not None:
74            (name,interface,protocol,stype,domain) = self.treemodel.get(iter,1,2,3,4,5)
75        if stype == None:
76            self.info_label.set_markup(_("<i>No service currently selected.</i>"))
77            return
78        #Asynchronous resolving
79        self.server.ResolveService( int(interface), int(protocol), name, stype, domain, avahi.PROTO_UNSPEC, dbus.UInt32(0), reply_handler=self.service_resolved, error_handler=self.print_error)
80
81    def protoname(self,protocol):
82        if protocol == avahi.PROTO_INET:
83            return "IPv4"
84        if protocol == avahi.PROTO_INET6:
85            return "IPv6"
86        return "n/a"
87
88    def siocgifname(self, interface):
89        if interface <= 0:
90            return "n/a"
91        else:
92            return self.server.GetNetworkInterfaceNameByIndex(interface)
93
94    def get_interface_name(self, interface, protocol):
95        if interface == avahi.IF_UNSPEC and protocol == avahi.PROTO_UNSPEC:
96            return "Wide Area"
97        else:
98            return str(self.siocgifname(interface)) + " " + str(self.protoname(protocol))
99
100    def service_resolved(self, interface, protocol, name, stype, domain, host, aprotocol, address, port, txt, flags):
101        print "Service data for service '%s' of type '%s' in domain '%s' on %i.%i:" % (name, stype, domain, interface, protocol)
102
103        print "\tHost %s (%s), port %i, TXT data: %s" % (host, address, port, str(avahi.txt_array_to_string_array(txt)))
104
105        self.update_label(interface, protocol, name, stype, domain, host, aprotocol, address, port, avahi.txt_array_to_string_array(txt))
106
107    def print_error(self, err):
108        error_label = "<b>Error:</b> %s" % (err)
109        self.info_label.set_markup(error_label)
110        print "Error:", str(err)
111
112    def lookup_type(self, stype):
113        global service_type_db
114
115        try:
116            return service_type_db[stype]
117        except KeyError:
118            return stype
119
120    def new_service(self, interface, protocol, name, stype, domain, flags):
121        print "Found service '%s' of type '%s' in domain '%s' on %i.%i." % (name, stype, domain, interface, protocol)
122        if self.zc_ifaces.has_key((interface,protocol)) == False:
123
124            ifn = self.get_interface_name(interface, protocol)
125
126            self.zc_ifaces[(interface,protocol)] = self.insert_row(self.treemodel, None, ifn, None,interface,protocol,None,domain)
127        if self.zc_domains.has_key((interface,protocol,domain)) == False:
128            self.zc_domains[(interface,protocol,domain)] = self.insert_row(self.treemodel, self.zc_ifaces[(interface,protocol)], domain,None,interface,protocol,None,domain)
129        if self.zc_types.has_key((interface,protocol,stype,domain)) == False:
130            thisDomain = self.zc_domains[(interface,protocol,domain)]
131            self.zc_types[(interface,protocol,stype,domain)] = self.insert_row(self.treemodel, thisDomain, self.lookup_type(stype), name, interface,None,None,None)
132        treeiter = self.insert_row(self.treemodel,self.zc_types[(interface,protocol,stype,domain)], name, name, interface,protocol,stype,domain)
133        self.services_browsed[(interface, protocol, name, stype, domain)] = treeiter
134        # expand the tree of this path
135        self.tree_view.expand_to_path(self.treemodel.get_path(treeiter))
136
137    def remove_service(self, interface, protocol, name, stype, domain, flags):
138        print "Service '%s' of type '%s' in domain '%s' on %i.%i disappeared." % (name, stype, domain, interface, protocol)
139        self.info_label.set_markup("")
140        treeiter=self.services_browsed[(interface, protocol, name, stype, domain)]
141        parent = self.treemodel.iter_parent(treeiter)
142        self.treemodel.remove(treeiter)
143        del self.services_browsed[(interface, protocol, name, stype, domain)]
144        if self.treemodel.iter_has_child(parent) == False:
145            treeiter=self.zc_types[(interface,protocol,stype,domain)]
146            parent = self.treemodel.iter_parent(treeiter)
147            self.treemodel.remove(treeiter)
148            del self.zc_types[(interface,protocol,stype,domain)]
149            if self.treemodel.iter_has_child(parent) == False:
150                treeiter=self.zc_domains[(interface,protocol,domain)]
151                parent = self.treemodel.iter_parent(treeiter)
152                self.treemodel.remove(treeiter)
153                del self.zc_domains[(interface,protocol,domain)]
154                if self.treemodel.iter_has_child(parent) == False:
155                    treeiter=self.zc_ifaces[(interface,protocol)]
156                    parent = self.treemodel.iter_parent(treeiter)
157                    self.treemodel.remove(treeiter)
158                    del self.zc_ifaces[(interface,protocol)]
159
160    def new_service_type(self, interface, protocol, stype, domain, flags):
161        global service_browsers
162
163        # Are we already browsing this domain for this type?
164        if service_browsers.has_key((interface, protocol, stype, domain)):
165            return
166
167        print "Browsing for services of type '%s' in domain '%s' on %i.%i ..." % (stype, domain, interface, protocol)
168
169        b = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, self.server.ServiceBrowserNew(interface, protocol, stype, domain, dbus.UInt32(0))),  avahi.DBUS_INTERFACE_SERVICE_BROWSER)
170        b.connect_to_signal('ItemNew', self.new_service)
171        b.connect_to_signal('ItemRemove', self.remove_service)
172
173        service_browsers[(interface, protocol, stype, domain)] = b
174
175    def browse_domain(self, interface, protocol, domain):
176        global service_type_browsers
177
178        # Are we already browsing this domain?
179        if service_type_browsers.has_key((interface, protocol, domain)):
180            return
181
182        if self.stype is None:
183            print "Browsing domain '%s' on %i.%i ..." % (domain, interface, protocol)
184
185            try:
186                b = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, self.server.ServiceTypeBrowserNew(interface, protocol, domain, dbus.UInt32(0))),  avahi.DBUS_INTERFACE_SERVICE_TYPE_BROWSER)
187            except DBusException, e:
188                print e
189                error_msg("You should check that the avahi daemon is running.\n\nError : %s" % e)
190                sys.exit(0)
191
192            b.connect_to_signal('ItemNew', self.new_service_type)
193
194            service_type_browsers[(interface, protocol, domain)] = b
195        else:
196            new_service_type(interface, protocol, stype, domain)
197
198    def new_domain(self,interface, protocol, domain, flags):
199        if self.zc_ifaces.has_key((interface,protocol)) == False:
200            ifn = self.get_interface_name(interface, protocol)
201            self.zc_ifaces[(interface,protocol)] = self.insert_row(self.treemodel, None, ifn,None,interface,protocol,None,domain)
202        if self.zc_domains.has_key((interface,protocol,domain)) == False:
203            self.zc_domains[(interface,protocol,domain)] = self.insert_row(self.treemodel, self.zc_ifaces[(interface,protocol)], domain,None,interface,protocol,None,domain)
204        if domain != "local":
205            self.browse_domain(interface, protocol, domain)
206
207    def pair_to_dict(self, l):
208        res = dict()
209        for el in l:
210            if "=" not in el:
211                res[el]=''
212            else:
213                tmp = el.split('=',1)
214                if len(tmp[0]) > 0:
215                    res[tmp[0]] = tmp[1]
216        return res
217
218
219    def update_label(self,interface, protocol, name, stype, domain, host, aprotocol, address, port, txt):
220        if len(txt) != 0:
221            txts = ""
222            txtd = self.pair_to_dict(txt)
223            for k,v in txtd.items():
224                txts+="<b>" + _("TXT") + " <i>%s</i></b> = %s\n" % (k,v)
225        else:
226            txts = "<b>" + _("TXT Data:") + "</b> <i>" + _("empty") + "</i>"
227
228        infos = "<b>" + _("Service Type:") + "</b> %s\n"
229        infos += "<b>" + _("Service Name:") + "</b> %s\n"
230        infos += "<b>" + _("Domain Name:") + "</b> %s\n"
231        infos += "<b>" + _("Interface:") + "</b> %s %s\n"
232        infos += "<b>" + _("Address:") + "</b> %s/%s:%i\n%s"
233        infos = infos % (stype, name, domain, self.siocgifname(interface), self.protoname(protocol), host, address, port, txts.strip())
234        self.info_label.set_markup(infos)
235
236    def insert_row(self, model,parent,
237                   content, name, interface,protocol,stype,domain):
238        myiter=model.insert_after(parent,None)
239        model.set(myiter,0,content,1,name,2,str(interface),3,str(protocol),4,stype,5,domain)
240        return myiter
241
242    def new(self):
243        self.treemodel=gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING)
244        self.tree_view.set_model(self.treemodel)
245
246        #creating the columns headers
247        self.tree_view.set_headers_visible(False)
248        renderer=gtk.CellRendererText()
249        column=gtk.TreeViewColumn("",renderer, text=0)
250        column.set_resizable(True)
251        column.set_sizing("GTK_TREE_VIEW_COLUMN_GROW_ONLY");
252        column.set_expand(True);
253        self.tree_view.append_column(column)
254
255        self.domain = None
256        self.stype = None
257        self.zc_ifaces = {}
258        self.zc_domains = {}
259        self.zc_types = {}
260        self.services_browsed = {}
261
262        try:
263            self.bus = dbus.SystemBus()
264            self.server = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, avahi.DBUS_PATH_SERVER), avahi.DBUS_INTERFACE_SERVER)
265        except Exception, e:
266            print "Failed to connect to Avahi Server (Is it running?): %s" % e
267            sys.exit(1)
268
269        if self.domain is None:
270            # Explicitly browse .local
271            self.browse_domain(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, "local")
272
273            # Browse for other browsable domains
274            db = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, self.server.DomainBrowserNew(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, "", avahi.DOMAIN_BROWSER_BROWSE, dbus.UInt32(0))), avahi.DBUS_INTERFACE_DOMAIN_BROWSER)
275            db.connect_to_signal('ItemNew', self.new_domain)
276        else:
277            # Just browse the domain the user wants us to browse
278            self.browse_domain(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, domain)
279
280    def gtk_main_quit(self, *args):
281        gtk.main_quit()
282
283def main():
284    main_window = Main_window()
285    gtk.main()
286
287if __name__ == "__main__":
288    main()
289