1
2
3
4 """
5 A mixin object for Service instances that announce the service over Zeroconf.
6 """
7
8 import avahi
9 import dbus
10
11 from twisted.python import log
12 from sparked import events
13
14
16 """
17 A globally defined object which interfaces with avahi.
18 """
19
21 self.published = {}
22 self.server = None
23 self.bus = None
24 self.subscribed = []
25
26
28 """
29 Publish a named service on the local zeroconf network.
30 """
31 if name in self.published:
32 return
33
34 if not self.bus:
35 self.bus = dbus.SystemBus()
36
37 server = dbus.Interface(
38 self.bus.get_object(
39 avahi.DBUS_NAME,
40 avahi.DBUS_PATH_SERVER),
41 avahi.DBUS_INTERFACE_SERVER)
42
43 g = dbus.Interface(
44 self.bus.get_object(avahi.DBUS_NAME,
45 server.EntryGroupNew()),
46 avahi.DBUS_INTERFACE_ENTRY_GROUP)
47
48 g.AddService(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC,dbus.UInt32(0),
49 name, stype, domain, host,
50 dbus.UInt16(port), "")
51
52 g.Commit()
53 self.published[name] = g
54
55
57 """
58 Revoke a previously published service.
59 """
60 self.published[name].Reset()
61 del self.published[name]
62
63
65 """
66 Revoke all published services.
67 """
68 for k in self.published.keys():
69 self.unpublishService(k)
70
71
72
74 """
75 Subscribe to a specific service.
76 """
77 if serviceType in self.subscribed:
78 return
79
80 if not self.bus:
81 self.bus = dbus.SystemBus()
82 if not self.server:
83 self.server = dbus.Interface( self.bus.get_object(avahi.DBUS_NAME, '/'), 'org.freedesktop.Avahi.Server')
84
85 sbrowser = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME,
86 self.server.ServiceBrowserNew(avahi.IF_UNSPEC,
87 avahi.PROTO_UNSPEC, serviceType, 'local', dbus.UInt32(0))),
88 avahi.DBUS_INTERFACE_SERVICE_BROWSER)
89 sbrowser.connect_to_signal("ItemNew", self._itemNew)
90 sbrowser.connect_to_signal("ItemRemove", self._itemRemove)
91 self.subscribed.append(serviceType)
92
93
94
95
96 - def _itemNew(self, iface, protocol, name, stype, domain, flags):
97
98 def resolveError(*a):
99 log.msg("RESOLVE ERROR:")
100 log.err(a)
101
102 def resolveSuccess(*args):
103 name = args[2]
104 hostname = args[5]
105 address = args[7]
106 port = args[8]
107 log.msg("** New service: %s (%s@%s)" % (name, hostname, port))
108 zeroconfEvents.dispatch("service-found", name, hostname=hostname, address=address, port=port, type=stype)
109
110 self.server.ResolveService(iface, protocol, name, stype,
111 domain, avahi.PROTO_UNSPEC, dbus.UInt32(0),
112 reply_handler=resolveSuccess, error_handler=resolveError)
113
114
115
116 - def _itemRemove(self, iface, protocol, name, stype, domain, flags):
119
120
121 try:
122 zeroconfService
123 except NameError:
124 zeroconfService = _ZeroconfService()
125 zeroconfEvents = events.EventDispatcher()
126
127
128 __all__ = ['zeroconfService', 'zeroconfEvents']
129