6
6
# This program is partly derived from an example program for an Avahi
7
7
# service publisher, downloaded from
8
8
# <http://avahi.org/wiki/PythonPublishExample>. This includes the
9
# methods "add" and "remove" in the "AvahiService" class, the
10
# "server_state_changed" and "entry_group_state_changed" functions,
11
# and some lines in "main".
9
# methods "add", "remove", "server_state_changed",
10
# "entry_group_state_changed", "cleanup", and "activate" in the
11
# "AvahiService" class, and some lines in "main".
13
13
# Everything else is
14
14
# Copyright © 2008,2009 Teddy Hogeborn
146
150
u" after %i retries, exiting.",
147
151
self.rename_count)
148
152
raise AvahiServiceError(u"Too many renames")
149
self.name = server.GetAlternativeServiceName(self.name)
153
self.name = self.server.GetAlternativeServiceName(self.name)
150
154
logger.info(u"Changing Zeroconf service name to %r ...",
152
156
syslogger.setFormatter(logging.Formatter
153
157
(u'Mandos (%s) [%%(process)d]:'
154
158
u' %%(levelname)s: %%(message)s'
158
162
self.rename_count += 1
159
163
def remove(self):
160
164
"""Derived from the Avahi example code"""
161
if group is not None:
165
if self.group is not None:
164
168
"""Derived from the Avahi example code"""
167
group = dbus.Interface(bus.get_object
169
server.EntryGroupNew()),
170
avahi.DBUS_INTERFACE_ENTRY_GROUP)
171
group.connect_to_signal('StateChanged',
172
entry_group_state_changed)
169
if self.group is None:
170
self.group = dbus.Interface(
171
bus.get_object(avahi.DBUS_NAME,
172
self.server.EntryGroupNew()),
173
avahi.DBUS_INTERFACE_ENTRY_GROUP)
174
self.group.connect_to_signal('StateChanged',
175
self.entry_group_state_changed)
173
176
logger.debug(u"Adding Zeroconf service '%s' of type '%s' ...",
174
service.name, service.type)
176
self.interface, # interface
177
self.protocol, # protocol
178
dbus.UInt32(0), # flags
179
self.name, self.type,
180
self.domain, self.host,
181
dbus.UInt16(self.port),
182
avahi.string_array_to_txt_array(self.TXT))
185
# From the Avahi example code:
186
group = None # our entry group
187
# End of Avahi example code
190
def _datetime_to_dbus(dt, variant_level=0):
191
"""Convert a UTC datetime.datetime() to a D-Bus type."""
192
return dbus.String(dt.isoformat(), variant_level=variant_level)
177
self.name, self.type)
178
self.group.AddService(
181
dbus.UInt32(0), # flags
182
self.name, self.type,
183
self.domain, self.host,
184
dbus.UInt16(self.port),
185
avahi.string_array_to_txt_array(self.TXT))
187
def entry_group_state_changed(self, state, error):
188
"""Derived from the Avahi example code"""
189
logger.debug(u"Avahi state change: %i", state)
191
if state == avahi.ENTRY_GROUP_ESTABLISHED:
192
logger.debug(u"Zeroconf service established.")
193
elif state == avahi.ENTRY_GROUP_COLLISION:
194
logger.warning(u"Zeroconf service name collision.")
196
elif state == avahi.ENTRY_GROUP_FAILURE:
197
logger.critical(u"Avahi: Error in group state changed %s",
199
raise AvahiGroupError(u"State changed: %s"
202
"""Derived from the Avahi example code"""
203
if self.group is not None:
206
def server_state_changed(self, state):
207
"""Derived from the Avahi example code"""
208
if state == avahi.SERVER_COLLISION:
209
logger.error(u"Zeroconf server name collision")
211
elif state == avahi.SERVER_RUNNING:
214
"""Derived from the Avahi example code"""
215
if self.server is None:
216
self.server = dbus.Interface(
217
bus.get_object(avahi.DBUS_NAME,
218
avahi.DBUS_PATH_SERVER),
219
avahi.DBUS_INTERFACE_SERVER)
220
self.server.connect_to_signal(u"StateChanged",
221
self.server_state_changed)
222
self.server_state_changed(self.server.GetState())
195
225
class Client(object):
459
489
+ self.name.replace(u".", u"_")))
460
490
dbus.service.Object.__init__(self, bus,
461
491
self.dbus_object_path)
494
def _datetime_to_dbus(dt, variant_level=0):
495
"""Convert a UTC datetime.datetime() to a D-Bus type."""
496
return dbus.String(dt.isoformat(),
497
variant_level=variant_level)
462
499
def enable(self):
463
500
oldstate = getattr(self, u"enabled", False)
464
501
r = Client.enable(self)
466
503
# Emit D-Bus signals
467
504
self.PropertyChanged(dbus.String(u"enabled"),
468
505
dbus.Boolean(True, variant_level=1))
469
self.PropertyChanged(dbus.String(u"last_enabled"),
470
(_datetime_to_dbus(self.last_enabled,
506
self.PropertyChanged(
507
dbus.String(u"last_enabled"),
508
self._datetime_to_dbus(self.last_enabled,
474
512
def disable(self, signal = True):
578
616
dbus.String(u"host"):
579
617
dbus.String(self.host, variant_level=1),
580
618
dbus.String(u"created"):
581
_datetime_to_dbus(self.created, variant_level=1),
619
self._datetime_to_dbus(self.created,
582
621
dbus.String(u"last_enabled"):
583
(_datetime_to_dbus(self.last_enabled,
622
(self._datetime_to_dbus(self.last_enabled,
585
624
if self.last_enabled is not None
586
625
else dbus.Boolean(False, variant_level=1)),
587
626
dbus.String(u"enabled"):
588
627
dbus.Boolean(self.enabled, variant_level=1),
589
628
dbus.String(u"last_checked_ok"):
590
(_datetime_to_dbus(self.last_checked_ok,
629
(self._datetime_to_dbus(self.last_checked_ok,
592
631
if self.last_checked_ok is not None
593
632
else dbus.Boolean (False, variant_level=1)),
594
633
dbus.String(u"timeout"):
1049
1088
return timevalue
1052
def server_state_changed(state):
1053
"""Derived from the Avahi example code"""
1054
if state == avahi.SERVER_COLLISION:
1055
logger.error(u"Zeroconf server name collision")
1057
elif state == avahi.SERVER_RUNNING:
1061
def entry_group_state_changed(state, error):
1062
"""Derived from the Avahi example code"""
1063
logger.debug(u"Avahi state change: %i", state)
1065
if state == avahi.ENTRY_GROUP_ESTABLISHED:
1066
logger.debug(u"Zeroconf service established.")
1067
elif state == avahi.ENTRY_GROUP_COLLISION:
1068
logger.warning(u"Zeroconf service name collision.")
1070
elif state == avahi.ENTRY_GROUP_FAILURE:
1071
logger.critical(u"Avahi: Error in group state changed %s",
1073
raise AvahiGroupError(u"State changed: %s" % unicode(error))
1075
1091
def if_nametoindex(interface):
1076
1092
"""Call the C function if_nametoindex(), or equivalent