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
signature.asc
Description: OpenPGP digital signature

