link-local: track multiple service resolved infos (currently one for each browsing protocol)
This commit is contained in:
		
							parent
							
								
									b58a76d8ee
								
							
						
					
					
						commit
						0dcbe70635
					
				
					 3 changed files with 46 additions and 13 deletions
				
			
		| 
						 | 
					@ -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…
	
	Add table
		
		Reference in a new issue