link-local: track multiple service resolved infos (currently one for each browsing protocol)
This commit is contained in:
parent
b58a76d8ee
commit
0dcbe70635
|
@ -56,8 +56,9 @@ class Roster:
|
||||||
if not contact:
|
if not contact:
|
||||||
return
|
return
|
||||||
|
|
||||||
host, address, port = contact[4:7]
|
resolved_info = contact[zeroconf.C_RESOLVED_INFO]
|
||||||
txt = contact[8]
|
host, aprotocol, address, port = resolved_info[0][zeroconf.C_RI_HOST:zeroconf.C_RI_PORT+1]
|
||||||
|
txt = contact[zeroconf.C_TXT]
|
||||||
|
|
||||||
self._data[jid]={}
|
self._data[jid]={}
|
||||||
self._data[jid]['ask'] = 'none'
|
self._data[jid]['ask'] = 'none'
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
||||||
##
|
##
|
||||||
|
|
||||||
C_NAME, C_DOMAIN, C_INTERFACE, C_PROTOCOL, C_HOST, \
|
C_NAME, C_DOMAIN, C_RESOLVED_INFO, C_BARE_NAME, C_TXT = range(5)
|
||||||
C_ADDRESS, C_PORT, C_BARE_NAME, C_TXT = range(9)
|
C_RI_INTERFACE, C_RI_PROTOCOL, C_RI_HOST, C_RI_APROTOCOL, C_RI_ADDRESS, C_RI_PORT = range(6)
|
||||||
|
|
||||||
def test_avahi():
|
def test_avahi():
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -25,7 +25,8 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
from common.zeroconf.zeroconf import C_BARE_NAME, C_INTERFACE, C_PROTOCOL, C_DOMAIN
|
from common.zeroconf.zeroconf import C_BARE_NAME, C_RESOLVED_INFO, \
|
||||||
|
C_RI_INTERFACE, C_RI_PROTOCOL, C_RI_APROTOCOL, C_DOMAIN, C_TXT
|
||||||
|
|
||||||
class Zeroconf:
|
class Zeroconf:
|
||||||
def __init__(self, new_serviceCB, remove_serviceCB, name_conflictCB,
|
def __init__(self, new_serviceCB, remove_serviceCB, name_conflictCB,
|
||||||
|
@ -93,7 +94,16 @@ class Zeroconf:
|
||||||
return
|
return
|
||||||
if name != self.name:
|
if name != self.name:
|
||||||
for key in self.contacts.keys():
|
for key in self.contacts.keys():
|
||||||
if self.contacts[key][C_BARE_NAME] == name:
|
val = self.contacts[key]
|
||||||
|
if val[C_BARE_NAME] == name:
|
||||||
|
# try to reduce instead of delete first
|
||||||
|
resolved_info = val[C_RESOLVED_INFO]
|
||||||
|
if len(resolved_info) > 1:
|
||||||
|
for i in range(len(resolved_info)):
|
||||||
|
if resolved_info[i][C_RI_INTERFACE] == interface and resolved_info[i][C_RI_PROTOCOL] == protocol:
|
||||||
|
del self.contacts[key][C_RESOLVED_INFO][i]
|
||||||
|
# if still something left, don't remove
|
||||||
|
if len(self.contacts[key][C_RESOLVED_INFO]) > 1: return
|
||||||
del self.contacts[key]
|
del self.contacts[key]
|
||||||
self.remove_serviceCB(key)
|
self.remove_serviceCB(key)
|
||||||
return
|
return
|
||||||
|
@ -151,16 +161,34 @@ class Zeroconf:
|
||||||
|
|
||||||
# we don't want to see ourselves in the list
|
# we don't want to see ourselves in the list
|
||||||
if name != self.name:
|
if name != self.name:
|
||||||
self.contacts[name] = (name, domain, interface, protocol, host,
|
resolved_info = [(interface, protocol, host, aprotocol, address, port)]
|
||||||
address, port, bare_name, txt)
|
if name in self.contacts:
|
||||||
|
# Decide whether to try to merge with existing resolved info:
|
||||||
|
old_name, old_domain, old_resolved_info, old_bare_name, old_txt = self.contacts[name]
|
||||||
|
if name == old_name and domain == old_domain and bare_name == old_bare_name:
|
||||||
|
# Seems similar enough, try to merge resolved info:
|
||||||
|
for i in range(len(old_resolved_info)):
|
||||||
|
# for now, keep a single record for each (interface, protocol) pair
|
||||||
|
#
|
||||||
|
# Note that, theoretically, we could both get IPv4 and
|
||||||
|
# IPv6 aprotocol responses via the same protocol,
|
||||||
|
# so this probably needs to be revised again.
|
||||||
|
if old_resolved_info[i][0:2] == (interface, protocol):
|
||||||
|
log.debug('Deleting resolved info for interface %i, protocol %i, host %s, aprotocol %i, address %s, port %i' % old_resolved_info[i])
|
||||||
|
del cur_hosts[i]
|
||||||
|
break
|
||||||
|
resolved_info = resolved_info + old_resolved_info
|
||||||
|
log.debug('Collected resolved info is now: %s' % (resolved_info,))
|
||||||
|
self.contacts[name] = (name, domain, resolved_info, bare_name, txt)
|
||||||
self.new_serviceCB(name)
|
self.new_serviceCB(name)
|
||||||
else:
|
else:
|
||||||
# remember data
|
# remember data
|
||||||
# In case this is not our own record but of another
|
# In case this is not our own record but of another
|
||||||
# gajim instance on the same machine,
|
# gajim instance on the same machine,
|
||||||
# it will be used when we get a new name.
|
# it will be used when we get a new name.
|
||||||
self.invalid_self_contact[name] = (name, domain, interface, protocol,
|
self.invalid_self_contact[name] = (name, domain,
|
||||||
host, address, port, bare_name, txt)
|
(interface, protocol, host, aprotocol, address, port),
|
||||||
|
bare_name, txt)
|
||||||
|
|
||||||
|
|
||||||
# different handler when resolving all contacts
|
# different handler when resolving all contacts
|
||||||
|
@ -171,8 +199,9 @@ class Zeroconf:
|
||||||
bare_name = name
|
bare_name = name
|
||||||
if name.find('@') == -1:
|
if name.find('@') == -1:
|
||||||
name = name + '@' + name
|
name = name + '@' + name
|
||||||
self.contacts[name] = (name, domain, interface, protocol, host, address,
|
# update TXT data only, as intended according to resolve_all comment
|
||||||
port, bare_name, txt)
|
old_contact = self.contacts[name]
|
||||||
|
self.contacts[name] = old_contact[0:C_TXT] + (txt,) + old_contact[C_TXT+1:]
|
||||||
|
|
||||||
def service_added_callback(self):
|
def service_added_callback(self):
|
||||||
log.debug('Service successfully added')
|
log.debug('Service successfully added')
|
||||||
|
@ -419,7 +448,10 @@ class Zeroconf:
|
||||||
if not self.connected:
|
if not self.connected:
|
||||||
return
|
return
|
||||||
for val in self.contacts.values():
|
for val in self.contacts.values():
|
||||||
self.server.ResolveService(int(val[C_INTERFACE]), int(val[C_PROTOCOL]),
|
# get txt data from last recorded resolved info
|
||||||
|
# TODO: Better try to get it from last IPv6 mDNS, then last IPv4?
|
||||||
|
ri = val[C_RESOLVED_INFO][0]
|
||||||
|
self.server.ResolveService(int(ri[C_RI_INTERFACE]), int(ri[C_RI_PROTOCOL]),
|
||||||
val[C_BARE_NAME], self.stype, val[C_DOMAIN],
|
val[C_BARE_NAME], self.stype, val[C_DOMAIN],
|
||||||
self.avahi.PROTO_UNSPEC, dbus.UInt32(0),
|
self.avahi.PROTO_UNSPEC, dbus.UInt32(0),
|
||||||
reply_handler=self.service_resolved_all_callback,
|
reply_handler=self.service_resolved_all_callback,
|
||||||
|
|
Loading…
Reference in New Issue