Package: gajim
Severity: wishlist
Tags: patch

Hi there,

please enable IPv6 support in Gajim through the attached patch (taken
from the Gajim bug tracker). IPv6 support is a release goal for Etch, so
it would be nice to see it included. The patch worked well for me for a
few weeks now, with both IPv4 and IPv6 Jabber servers.

Thank you for your work! If you need your upload sponsored, just let me
know.

Kind regards,
Philipp Kern
--- gajim-0.10.1.orig/debian/patches/00_ipv6.patch
+++ gajim-0.10.1/debian/patches/00_ipv6.patch
@@ -0,0 +1,266 @@
+diff -Nru gajim-20060727/src/common/xmpp/transports_nb.py gajim-20060727-ipv6/src/common/xmpp/transports_nb.py
+--- gajim-20060727/src/common/xmpp/transports_nb.py	2006-07-26 14:49:11.000000000 +0200
++++ gajim-20060727-ipv6/src/common/xmpp/transports_nb.py	2006-07-27 22:48:24.000000000 +0200
+@@ -60,6 +60,11 @@
+ 		# -2 - disconnected
+ 		self.state = 0
+ 		
++		# server information (IPv6 or IPv4 addresses to try connect to)
++		self._addrinfo = None
++		# socket address information used to connect to server
++		self._serveraddr = None
++		
+ 		# queue with messages to be send 
+ 		self.sendqueue = []
+ 		
+@@ -90,9 +95,16 @@
+ 		
+ 	def read_timeout(self):
+ 		if self.state == 0:
+-			self.idlequeue.unplug_idle(self.fd)
+-			if self.on_connect_failure:
+-				self.on_connect_failure()
++			# connect with this server address failed
++			self.DEBUG("Failed to connect to %s:%d with address [%s]:%d (timeout)"%(self._server[0],self._server[1],self._serveraddr[0],self._serveraddr[1]),'info')
++			self._addrinfo.pop(0)
++			# try another server address if possible, otherwise failure
++			if len(self._addrinfo) > 0:
++				self.connect()
++			else:
++				self.idlequeue.unplug_idle(self.fd)
++				if self.on_connect_failure:
++					self.on_connect_failure()
+ 		else:
+ 			if self.on_timeout:
+ 				self.on_timeout()
+@@ -105,14 +117,39 @@
+ 		else: 
+ 			self._server = server
+ 		self.state = 0
+-		try:
+-			self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+-			self._sock.setblocking(False)
+-		except:
++		
++		# get server addresses (either IPv6 or IPv4) if not already done
++		if self._addrinfo is None:
++			self._addrinfo = socket.getaddrinfo(server[0], server[1], socket.AF_UNSPEC, socket.SOCK_STREAM)
++		
++		# try to connect to server with one of its addresses
++		self._sock = None
++		for res in self._addrinfo:
++			af, socktype, proto, canonname, sa = res
++		
++			self.DEBUG("Connect to %s:%d with address [%s]:%d"%(server[0],server[1],sa[0],sa[1]),'info')
++			try:
++				self._sock = socket.socket(af, socktype, proto)
++				self._sock.setblocking(False)
++			except socket.error, msg:
++				self._sock = None
++				self._addrinfo.pop(0)
++				self.DEBUG("Failed to connect to %s:%d with address [%s]:%d (socket() failed)"%(server[0],server[1],sa[0],sa[1]),'info')
++				continue
++
++			self._serveraddr = sa
++			break
++
++		# if socket creation failed and no more addresses are available,
++		# failure
++		if self._sock is None:
+ 			sys.exc_clear()
+ 			if self.on_connect_failure:
+ 				self.on_connect_failure()
+ 			return False
++
++		# if socket creation with one server address is successful,
++		# try to connect
+ 		self.fd = self._sock.fileno()
+ 		self.idlequeue.plug_idle(self, True, False)
+ 		self.set_timeout(CONNECT_TIMEOUT_SECONDS)
+@@ -285,7 +322,7 @@
+ 		self._sock.setblocking(False)
+ 		errnum = 0
+ 		try:
+-			self._sock.connect(self._server)
++			self._sock.connect(self._serveraddr)
+ 		except socket.error, e:
+ 			errnum = e[0]
+ 			sys.exc_clear()
+@@ -295,10 +332,18 @@
+ 		# 10056  - already connected, only on win32
+ 		# code 'WS*' is not available on GNU, so we use its numeric value
+ 		elif errnum not in (0, 10056, errno.EISCONN): 
++			self.DEBUG("Failed to connect to %s:%d with address [%s]:%d (connect() failed with error %d)"%(self._server[0],self._server[1],self._serveraddr[0],self._serveraddr[1],errnum),'info')
+ 			self.remove_timeout()
+-			if self.on_connect_failure:
+-				self.on_connect_failure()
++			self._sock.close()
++			self._addrinfo.pop(0)
++			# try another server address if possible, otherwise failure
++			if len(self._addrinfo) > 0:
++				self.connect()
++			else:
++				if self.on_connect_failure:
++					self.on_connect_failure()
+ 			return
++		
+ 		self.remove_timeout()
+ 		self._owner.Connection=self
+ 		self.state = 1
+diff -Nru gajim-20060727/src/common/xmpp/transports.py gajim-20060727-ipv6/src/common/xmpp/transports.py
+--- gajim-20060727/src/common/xmpp/transports.py	2006-01-20 14:23:38.000000000 +0100
++++ gajim-20060727-ipv6/src/common/xmpp/transports.py	2006-07-27 22:53:14.000000000 +0200
+@@ -94,15 +94,30 @@
+ 
+     def connect(self,server=None):
+         """ Try to connect. Returns non-empty string on success. """
+-        try:
+-            if not server: server=self._server
+-            self._sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+-            self._sock.connect(server)
+-            self._send=self._sock.sendall
+-            self._recv=self._sock.recv
+-            self.DEBUG("Successfully connected to remote host %s"%`server`,'start')
+-            return 'ok'
+-        except: pass
++        if not server: server=self._server
++        s = None
++        for res in socket.getaddrinfo(server[0], server[1], socket.AF_UNSPEC, socket.SOCK_STREAM):
++            af, socktype, proto, canonname, sa = res
++            self.DEBUG("Connect to %s:%d with address [%s]:%d"%(server[0],server[1],sa[0],sa[1]),'info')
++            try:
++                s = socket.socket(af, socktype, proto)
++            except socket.error, msg:
++                self.DEBUG("Failed to connect to %s:%d with address [%s]:%d (socket() failed)"%(server[0],server[1],sa[0],sa[1]),'info')
++                s = None
++                continue
++            try:
++                s.connect(sa)
++            except socket.error, msg:
++                self.DEBUG("Failed to connect to %s:%d with address [%s]:%d (connect() failed)"%(server[0],server[1],sa[0],sa[1]),'info')
++                s.close()
++                s = None
++                continue
++            self.DEBUG("Successfully connected to remote host %s:%d with address [%s]:%d"%(server[0],server[1],sa[0],sa[1]),'info')
++            break
++        if s is None:
++            self.DEBUG("Failed to connect to remote host %s:%s"%(server[0],server[1]),'info')
++            pass
++        return 'ok'
+ 
+     def plugout(self):
+         """ Disconnect from the remote server and unregister self.disconnected method from
+diff -Nru gajim-20060727/THANKS gajim-20060727-ipv6/THANKS
+--- gajim-20060727/THANKS	2006-07-04 00:08:50.000000000 +0200
++++ gajim-20060727-ipv6/THANKS	2006-07-27 22:51:41.000000000 +0200
+@@ -10,6 +10,7 @@
+ Christoph Neuroth
+ David Campey
+ Dennis Craven
++Didier Barvaux (IPv6 support)
+ Fabian Neumann
+ Filippos Papadopoulos
+ Francisco Alburquerque Parra (Membris Khan)
+diff -uNr gajim-0.10.1/src/common/connection_handlers.py gajim-0.10.1-new/src/common/connection_handlers.py
+- --- gajim-0.10.1/src/common/connection_handlers.py	2006-06-05 14:03:08.000000000 +0200
++++ gajim-0.10.1-new/src/common/connection_handlers.py	2006-06-30 05:08:18.000000000 +0200
+@@ -33,6 +33,7 @@
+ from common import helpers
+ from common import gajim
+ from common import i18n
++from ipv6addr import ipv6addrlist
+ _ = i18n._
+ 
+ STATUS_LIST = ['offline', 'connecting', 'online', 'chat', 'away', 'xa', 'dnd',
+@@ -187,7 +188,16 @@
+ 		query.setNamespace(common.xmpp.NS_BYTESTREAM)
+ 		query.setAttr('mode', 'tcp')
+ 		query.setAttr('sid', file_props['sid'])
+- -		streamhost = query.setTag('streamhost')
++		# IPv6 go first
++		if socket.has_ipv6:
++			for ipv6addr in ipv6addrlist():
++				streamhost = common.xmpp.Node(tag = 'streamhost')
++				query.addChild(node=streamhost)
++				streamhost.setAttr('port', unicode(port))
++				streamhost.setAttr('host', ipv6addr)
++				streamhost.setAttr('jid', sender)
++		streamhost = common.xmpp.Node(tag = 'streamhost')
++		query.addChild(node=streamhost)
+ 		streamhost.setAttr('port', unicode(port))
+ 		streamhost.setAttr('host', ft_override_host_to_send)
+ 		streamhost.setAttr('jid', sender)
+diff -uNr gajim-0.10.1/src/common/socks5.py gajim-0.10.1-new/src/common/socks5.py
+- --- gajim-0.10.1/src/common/socks5.py	2006-06-05 14:03:08.000000000 +0200
++++ gajim-0.10.1-new/src/common/socks5.py	2006-06-30 05:14:10.000000000 +0200
+@@ -803,13 +803,21 @@
+ 		self.fd = -1
+ 		
+ 	def bind(self):
+- -		self._serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
++		if socket.has_ipv6:
++			family = socket.AF_INET6
++			addr_any = '::'
++		else:
++			family = socket.AF_INET
++			addr_any = '0.0.0.0'
++		self._serv = socket.socket(family, socket.SOCK_STREAM)
+ 		self._serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ 		self._serv.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
+ 		self._serv.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
++		if socket.has_ipv6:
++			self._serv.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
+ 		# will fail when port as busy, or we don't have rights to bind
+ 		try:
+- -			self._serv.bind(('0.0.0.0', self.port))
++			self._serv.bind((addr_any, self.port))
+ 		except Exception, e:
+ 			# unable to bind, show error dialog
+ 			return None
+diff -uNr gajim-0.10.1/src/ipv6addr.py gajim-0.10.1-new/src/ipv6addr.py
+- --- gajim-0.10.1/src/ipv6addr.py	1970-01-01 01:00:00.000000000 +0100
++++ gajim-0.10.1-new/src/ipv6addr.py	2006-06-30 05:15:24.000000000 +0200
+@@ -0,0 +1,43 @@
++import struct,sys
++
++ADDRFILE = '/proc/net/if_inet6'
++
++class ipv6addrlist(list):
++	def __init__(self):
++		if   sys.platform[:-1] == 'linux'  : self.getLinux()
++		elif sys.platform[:-1] == 'freebsd': self.getFreeBSD()
++		elif sys.platform == 'win32': self.getWindows()
++
++	def getFreeBSD(self):
++		return
++
++	def getWindows(self):
++		return
++
++	def getLinux(self):
++		try:
++			f = open(ADDRFILE, 'r')
++
++			l = f.readline()
++			while l:
++				addr = l.split()
++
++				# global scope addresses only
++				if addr[3] != '00':
++					l = f.readline()
++					continue
++
++				# split by four characters
++				addr=struct.unpack('4s4s4s4s4s4s4s4s', addr[0])
++				self.append(':'.join(addr))
++				
++				l = f.readline()
++		except IOError, e:
++			self[:] = []
++			return None
++	
++
++if __name__ == '__main__':
++	A =  ipv6addrlist()
++	for a in A:
++		print a

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to