Index: src/test/java/net/sourceforge/peers/sip/transaction/TransactionManagerTestNG.java
===================================================================
--- src/test/java/net/sourceforge/peers/sip/transaction/TransactionManagerTestNG.java	(revision 200)
+++ src/test/java/net/sourceforge/peers/sip/transaction/TransactionManagerTestNG.java	(working copy)
@@ -23,6 +23,7 @@
 import java.io.IOException;
 import java.net.DatagramSocket;
 import java.net.InetAddress;
+import java.net.Inet4Address;
 import java.net.UnknownHostException;
 import java.util.Random;
 
@@ -50,7 +51,7 @@
         Logger logger = new Logger(null);
         transactionManager = new TransactionManager(logger);
         Config config = new JavaConfig();
-        config.setLocalInetAddress(InetAddress.getLocalHost());
+        config.setLocalInet4Address((Inet4Address) InetAddress.getLocalHost());
         transportManager = new TransportManager(
                 transactionManager, config, logger);
         transactionManager.setTransportManager(transportManager);
Index: src/test/java/net/sourceforge/peers/sip/core/useragent/UacHangupTestNG.java
===================================================================
--- src/test/java/net/sourceforge/peers/sip/core/useragent/UacHangupTestNG.java	(revision 200)
+++ src/test/java/net/sourceforge/peers/sip/core/useragent/UacHangupTestNG.java	(working copy)
@@ -20,6 +20,7 @@
 package net.sourceforge.peers.sip.core.useragent;
 
 import java.net.InetAddress;
+import java.net.Inet4Address;
 import java.net.SocketException;
 import java.net.UnknownHostException;
 
@@ -51,13 +52,13 @@
             UnknownHostException{
 
         Config config = new JavaConfig();
-        config.setLocalInetAddress(InetAddress.getLocalHost());
+        config.setLocalInet4Address((Inet4Address) InetAddress.getLocalHost());
         config.setMediaMode(MediaMode.captureAndPlayback);
         user1SipListener = new UserSipListener();
         testUser1 = new UserAgent(user1SipListener, config, null);
 
         config = new JavaConfig();
-        config.setLocalInetAddress(InetAddress.getLocalHost());
+        config.setLocalInet4Address((Inet4Address) InetAddress.getLocalHost());
         config.setMediaMode(MediaMode.echo);
         user2SipListener = new UserSipListener();
         testUser2 = new UserAgent(user2SipListener, config, null);
@@ -67,7 +68,7 @@
     @Test(timeOut = 3000)
     public void uacHangup() throws SipUriSyntaxException, InterruptedException {
         Config config = testUser2.getConfig();
-        InetAddress inetAddress = config.getLocalInetAddress();
+        InetAddress inetAddress = config.getLocalInet4Address();
         String host = inetAddress.getHostAddress();
         int port = testUser2.getTransportManager().getSipPort();
         UAC uac1 = testUser1.getUac();
Index: src/test/java/net/sourceforge/peers/sip/core/useragent/UACTestUasHangupMain.java
===================================================================
--- src/test/java/net/sourceforge/peers/sip/core/useragent/UACTestUasHangupMain.java	(revision 200)
+++ src/test/java/net/sourceforge/peers/sip/core/useragent/UACTestUasHangupMain.java	(working copy)
@@ -32,10 +32,10 @@
         try {
             UserAgent userAgent = new UserAgent(null, (String)null, new Logger(null));
             requestUri = "sip:bob@" + userAgent.getConfig()
-                .getLocalInetAddress().getHostAddress() + ":6060";
+                .getLocalInet4Address().getHostAddress() + ":6060";
             userAgent.getUac().invite(requestUri,
                     Utils.generateCallID(userAgent.getConfig()
-                            .getLocalInetAddress()));
+                            .getLocalInet4Address(),null));
         } catch (SipUriSyntaxException e) {
             e.printStackTrace();
         } catch (SocketException e) {
Index: src/test/java/net/sourceforge/peers/sip/core/useragent/CancelTestNG.java
===================================================================
--- src/test/java/net/sourceforge/peers/sip/core/useragent/CancelTestNG.java	(revision 200)
+++ src/test/java/net/sourceforge/peers/sip/core/useragent/CancelTestNG.java	(working copy)
@@ -20,6 +20,7 @@
 package net.sourceforge.peers.sip.core.useragent;
 
 import java.net.InetAddress;
+import java.net.Inet4Address;
 import java.net.SocketException;
 import java.net.UnknownHostException;
 
@@ -48,13 +49,13 @@
             UnknownHostException{
 
         Config config = new JavaConfig();
-        config.setLocalInetAddress(InetAddress.getLocalHost());
+        config.setLocalInet4Address((Inet4Address) InetAddress.getLocalHost());
         config.setMediaMode(MediaMode.none);
         user1SipListener = new UserSipListener();
         testUser1 = new UserAgent(user1SipListener, config, null);
 
         config = new JavaConfig();
-        config.setLocalInetAddress(InetAddress.getLocalHost());
+        config.setLocalInet4Address((Inet4Address) InetAddress.getLocalHost());
         config.setMediaMode(MediaMode.none);
         user2SipListener = new UserSipListener();
         testUser2 = new UserAgent(user2SipListener, config, null);
@@ -64,8 +65,8 @@
     @Test(timeOut = 3000)
     public void uacCancel() throws SipUriSyntaxException, InterruptedException {
         Config config = testUser2.getConfig();
-        InetAddress inetAddress = config.getLocalInetAddress();
-        String host = inetAddress.getHostAddress();
+        Inet4Address inet4Address = config.getLocalInet4Address();
+        String host = inet4Address.getHostAddress();
         int port = testUser2.getTransportManager().getSipPort();
         UAC uac1 = testUser1.getUac();
         SipRequest invite = uac1.invite("sip:" + host + ":" + port,
Index: src/test/java/net/sourceforge/peers/sip/core/useragent/UACTestMain.java
===================================================================
--- src/test/java/net/sourceforge/peers/sip/core/useragent/UACTestMain.java	(revision 200)
+++ src/test/java/net/sourceforge/peers/sip/core/useragent/UACTestMain.java	(working copy)
@@ -34,10 +34,10 @@
         try {
             userAgent = new UserAgent(null, (String)null, new Logger(null));
             requestUri = "sip:bob@" + userAgent.getConfig()
-                .getLocalInetAddress().getHostAddress() + ":6060";
+                .getLocalInet4Address().getHostAddress() + ":6060";
             sipRequest = userAgent.getUac().invite(requestUri,
                     userAgent.getConfig()
-                        .getLocalInetAddress().getHostName());
+                        .getLocalInet4Address().getHostName());
         } catch (SipUriSyntaxException e) {
             e.printStackTrace();
             return;
Index: src/test/java/net/sourceforge/peers/sip/transport/UdpMessageSenderTestMain.java
===================================================================
--- src/test/java/net/sourceforge/peers/sip/transport/UdpMessageSenderTestMain.java	(revision 200)
+++ src/test/java/net/sourceforge/peers/sip/transport/UdpMessageSenderTestMain.java	(working copy)
@@ -22,6 +22,7 @@
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.net.InetAddress;
+import java.net.Inet4Address;
 import java.net.UnknownHostException;
 
 import net.sourceforge.peers.Config;
@@ -55,7 +56,7 @@
         } catch (UnknownHostException e) {
             e.printStackTrace();
         }
-        config.setLocalInetAddress(localhost);
+        config.setLocalInet4Address((Inet4Address) localhost);
         TransportManager transportManager = new TransportManager(
                 null, config, new Logger(null));
         try {
Index: src/test/java/net/sourceforge/peers/sip/transport/UdpMessageReceiverTestMain.java
===================================================================
--- src/test/java/net/sourceforge/peers/sip/transport/UdpMessageReceiverTestMain.java	(revision 200)
+++ src/test/java/net/sourceforge/peers/sip/transport/UdpMessageReceiverTestMain.java	(working copy)
@@ -21,6 +21,7 @@
 
 import java.io.IOException;
 import java.net.InetAddress;
+import java.net.Inet4Address;
 
 import net.sourceforge.peers.Config;
 import net.sourceforge.peers.JavaConfig;
@@ -33,7 +34,7 @@
     public void run() {
         try {
             Config config = new JavaConfig();
-            config.setLocalInetAddress(InetAddress.getLocalHost());
+            config.setLocalInet4Address((Inet4Address) InetAddress.getLocalHost());
             TransportManager transportManager = new TransportManager(null,
                     config, new Logger(null));
             transportManager.createServerTransport("UDP", RFC3261.TRANSPORT_DEFAULT_PORT);
Index: src/test/java/net/sourceforge/peers/sip/transport/MessageSenderTestNG.java
===================================================================
--- src/test/java/net/sourceforge/peers/sip/transport/MessageSenderTestNG.java	(revision 200)
+++ src/test/java/net/sourceforge/peers/sip/transport/MessageSenderTestNG.java	(working copy)
@@ -24,6 +24,7 @@
 import java.net.DatagramPacket;
 import java.net.DatagramSocket;
 import java.net.InetAddress;
+import java.net.Inet4Address;
 import java.net.SocketException;
 import java.net.UnknownHostException;
 import java.util.Random;
@@ -54,7 +55,7 @@
         final int localPort = datagramSocket.getLocalPort();
         Config config = new JavaConfig();
         config.setSipPort(localPort);
-        config.setLocalInetAddress(InetAddress.getLocalHost());
+        config.setLocalInet4Address((Inet4Address) InetAddress.getLocalHost());
         SipServerTransportUser sipServerTransportUser =
             new SipServerTransportUser() {
             @Override public void messageReceived(SipMessage sipMessage) {}
Index: src/test/java/net/sourceforge/peers/sip/transport/TransportManagerTestNG.java
===================================================================
--- src/test/java/net/sourceforge/peers/sip/transport/TransportManagerTestNG.java	(revision 200)
+++ src/test/java/net/sourceforge/peers/sip/transport/TransportManagerTestNG.java	(working copy)
@@ -23,6 +23,7 @@
 import java.io.IOException;
 import java.net.DatagramSocket;
 import java.net.InetAddress;
+import java.net.Inet4Address;
 import java.net.SocketException;
 import java.net.UnknownHostException;
 
@@ -48,7 +49,7 @@
         //TODO interface between transport manager and transaction manager
         Config config = new JavaConfig();
         config.setSipPort(port);
-        config.setLocalInetAddress(InetAddress.getLocalHost());
+        config.setLocalInet4Address((Inet4Address) InetAddress.getLocalHost());
         Logger logger = new Logger(null);
         transportManager = new TransportManager(
                 new TransactionManager(logger),
Index: src/test/java/net/sourceforge/peers/XmlConfigTestNG.java
===================================================================
--- src/test/java/net/sourceforge/peers/XmlConfigTestNG.java	(revision 200)
+++ src/test/java/net/sourceforge/peers/XmlConfigTestNG.java	(working copy)
@@ -20,6 +20,7 @@
 package net.sourceforge.peers;
 
 import java.net.InetAddress;
+import java.net.Inet4Address;
 import java.net.UnknownHostException;
 
 import net.sourceforge.peers.media.MediaMode;
@@ -44,7 +45,7 @@
         MediaMode mediaMode = MediaMode.echo;
         boolean mediaDebug = true;
         int rtpPort = 8002;
-        config.setLocalInetAddress(localHost);
+        config.setLocalInet4Address((Inet4Address) localHost);
         config.setUserPart(userPart);
         config.setDomain(domain);
         config.setPassword(password);
@@ -55,7 +56,7 @@
         config.setRtpPort(rtpPort);
         config.save();
         config = new XmlConfig(fileName, logger);
-        assert localHost.equals(config.getLocalInetAddress());
+        assert localHost.equals(config.getLocalInet4Address());
         assert userPart.equals(config.getUserPart());
         assert domain.equals(config.getDomain());
         assert password.equals(config.getPassword());
Index: src/main/java/net/sourceforge/peers/media/MediaManager.java
===================================================================
--- src/main/java/net/sourceforge/peers/media/MediaManager.java	(revision 200)
+++ src/main/java/net/sourceforge/peers/media/MediaManager.java	(working copy)
@@ -167,8 +167,9 @@
 
     private void startNewRtpSession(String destAddress, int destPort,
             Codec codec, SoundSource soundSource) {
+        //TODO Assume that datagramScket.getInetAddress() will always deliver
         rtpSession = new RtpSession(
-                userAgent.getConfig().getLocalInetAddress(),
+                userAgent.getConfig().getMatchingLocalInetAddress(datagramSocket.getInetAddress()),
                 datagramSocket, userAgent.isMediaDebug(), logger,
                 userAgent.getPeersHome());
         
@@ -228,8 +229,9 @@
                 echo = new Echo(datagramSocket, destAddress, destPort, logger);
             } catch (UnknownHostException e) {
                 logger.error("unknown host amongst "
-                        + userAgent.getConfig().getLocalInetAddress()
-                            .getHostAddress() + " or " + destAddress);
+                		+ userAgent.getConfig().getLocalInet4Address().getHostAddress()
+                        + userAgent.getConfig().getPublicInet6Address().getHostAddress()
+                        + " or " + destAddress);
                 return;
             }
             userAgent.setEcho(echo);
Index: src/main/java/net/sourceforge/peers/media/SoundManager.java
===================================================================
--- src/main/java/net/sourceforge/peers/media/SoundManager.java	(revision 200)
+++ src/main/java/net/sourceforge/peers/media/SoundManager.java	(working copy)
@@ -54,7 +54,7 @@
         this.mediaDebug = mediaDebug;
         this.logger = logger;
         this.peersHome = peersHome;
-        // linear PCM 8kHz, 16 bits signed, mono-channel, little endian
+        // linear PCM 8kHz, 16 bits, mono-channel, signed, little endian
         audioFormat = new AudioFormat(8000, 16, 1, true, false);
         targetInfo = new DataLine.Info(TargetDataLine.class, audioFormat);
         sourceInfo = new DataLine.Info(SourceDataLine.class, audioFormat);
Index: src/main/java/net/sourceforge/peers/Logger.java
===================================================================
--- src/main/java/net/sourceforge/peers/Logger.java	(revision 200)
+++ src/main/java/net/sourceforge/peers/Logger.java	(working copy)
@@ -43,6 +43,16 @@
     private SimpleDateFormat logFormatter;
     private SimpleDateFormat networkFormatter;
 
+    public Logger(PrintWriter logWriter, PrintWriter networkWriter) {
+    	this.logWriter = logWriter;
+    	this.networkWriter = networkWriter;
+        logMutex = new Object();
+        networkMutex = new Object();
+        logFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS");
+        networkFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS");
+    	
+    }
+    
     public Logger(String peersHome) {
         if (peersHome == null) {
             peersHome = Utils.DEFAULT_PEERS_HOME;
Index: src/main/java/net/sourceforge/peers/Config.java
===================================================================
--- src/main/java/net/sourceforge/peers/Config.java	(revision 200)
+++ src/main/java/net/sourceforge/peers/Config.java	(working copy)
@@ -20,6 +20,8 @@
 package net.sourceforge.peers;
 
 import java.net.InetAddress;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
 
 import net.sourceforge.peers.media.MediaMode;
 import net.sourceforge.peers.sip.syntaxencoding.SipURI;
@@ -27,8 +29,10 @@
 public interface Config {
 
     public void save();
-    public InetAddress getLocalInetAddress();
-    public InetAddress getPublicInetAddress();
+    public Inet4Address getLocalInet4Address();
+    public Inet4Address getPublicInet4Address();
+    public Inet6Address getPublicInet6Address();
+    public InetAddress getMatchingLocalInetAddress(InetAddress matchMyFamily);
     public String getUserPart();
     public String getDomain();
     public String getPassword();
@@ -38,8 +42,9 @@
     public boolean isMediaDebug();
     public String getMediaFile();
     public int getRtpPort();
-    public void setLocalInetAddress(InetAddress inetAddress);
-    public void setPublicInetAddress(InetAddress inetAddress);
+    public void setLocalInet4Address(Inet4Address inetAddress);
+    public void setPublicInet4Address(Inet4Address inetAddress);
+    public void setPublicInet6Address(Inet6Address inetAddress);
     public void setUserPart(String userPart);
     public void setDomain(String domain);
     public void setPassword(String password);
Index: src/main/java/net/sourceforge/peers/sdp/SDPManager.java
===================================================================
--- src/main/java/net/sourceforge/peers/sdp/SDPManager.java	(revision 200)
+++ src/main/java/net/sourceforge/peers/sdp/SDPManager.java	(working copy)
@@ -21,6 +21,7 @@
 
 import java.io.IOException;
 import java.net.InetAddress;
+import java.net.Inet6Address;
 import java.util.ArrayList;
 import java.util.Hashtable;
 import java.util.List;
@@ -103,6 +104,7 @@
     }
 
     public SessionDescription createSessionDescription(SessionDescription offer,
+    		InetAddress matchMyAddressFamilyByDefault,
             int localRtpPort)
             throws IOException {
         SessionDescription sessionDescription = new SessionDescription();
@@ -110,10 +112,21 @@
         sessionDescription.setId(random.nextInt(Integer.MAX_VALUE));
         sessionDescription.setVersion(random.nextInt(Integer.MAX_VALUE));
         Config config = userAgent.getConfig();
-        InetAddress inetAddress = config.getPublicInetAddress();
-        if (inetAddress == null) {
-            inetAddress = config.getLocalInetAddress();
+        boolean useIPv6;
+        InetAddress inetAddress;
+        if (offer != null) {
+        	useIPv6 = (offer.getIpAddress() instanceof Inet6Address);
+        } else {
+        	useIPv6 = (matchMyAddressFamilyByDefault instanceof Inet6Address);
         }
+        if (useIPv6) {
+        	inetAddress = config.getPublicInet6Address ();
+        } else {
+        	inetAddress = config.getPublicInet4Address ();
+        	if (inetAddress == null) {
+        		inetAddress = config.getLocalInet4Address ();
+        	}
+        }
         sessionDescription.setIpAddress(inetAddress);
         sessionDescription.setName("-");
         sessionDescription.setAttributes(new Hashtable<String, String>());
Index: src/main/java/net/sourceforge/peers/XmlConfig.java
===================================================================
--- src/main/java/net/sourceforge/peers/XmlConfig.java	(revision 200)
+++ src/main/java/net/sourceforge/peers/XmlConfig.java	(working copy)
@@ -23,6 +23,8 @@
 import java.io.FileWriter;
 import java.io.IOException;
 import java.net.InetAddress;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
 import java.net.UnknownHostException;
 
 import javax.xml.parsers.DocumentBuilder;
@@ -58,7 +60,7 @@
 
     // persistent variables
 
-    private InetAddress localInetAddress;
+    private Inet4Address localInet4Address;
     private String userPart;
     private String domain;
     private String password;
@@ -84,7 +86,8 @@
 
     // non-persistent variables
 
-    private InetAddress publicInetAddress;
+    private Inet4Address publicInet4Address;
+    private Inet6Address publicInet6Address;
 
     //private InetAddress
     public XmlConfig(String fileName, Logger logger) {
@@ -114,15 +117,39 @@
         }
         Element documentElement = document.getDocumentElement();
         ipAddressNode = getFirstChild(documentElement, "ipAddress");
-        String address = ipAddressNode.getTextContent();
-        try {
-            if (isNullOrEmpty(ipAddressNode)) {
-                localInetAddress = InetAddress.getLocalHost();
-            } else {
-                localInetAddress = InetAddress.getByName(address);
-            }
-        } catch (UnknownHostException e) {
-            logger.error("unknown host: " + address, e);
+        while ((ipAddressNode != null) && (ipAddressNode.getNodeName() == "ipAddress")) {
+	        String address = ipAddressNode.getTextContent();
+        	InetAddress inaddrs[];
+	        try {
+	            if (isNullOrEmpty(ipAddressNode)) {
+	                inaddrs = new InetAddress [1]; 
+	                inaddrs [0] = InetAddress.getLocalHost();
+	            } else {
+	                inaddrs = InetAddress.getAllByName(address);
+	            }
+	            for (int i=0; i<inaddrs.length; i++) {
+		            if (inaddrs[i] instanceof Inet6Address) {
+		            	if (publicInet6Address == null) {
+		            		publicInet6Address = (Inet6Address) inaddrs[i];
+		            	} else {
+		            		logger.error("ignoring additional IPv6 address " + address);
+		            	}
+		            } else if (inaddrs[i] instanceof Inet4Address) {
+		            	if (localInet4Address == null) {
+		            		localInet4Address = (Inet4Address) inaddrs[i];
+		            	} else {
+		            		logger.error("ignoring additional IPv4 address " + address);
+		            	}
+		            } else {
+		            	logger.info("Ignoring unrecognisable address " + address);
+		            }
+	            }
+	        } catch (UnknownHostException e) {
+	            logger.error("unknown host: " + address, e);
+	        }
+	        do {
+	        	ipAddressNode = ipAddressNode.getNextSibling();
+	        } while ((ipAddressNode != null) && (ipAddressNode.getNodeName().charAt(0) == '#'));
         }
         userPartNode = getFirstChild(documentElement, "userPart");
         if (isNullOrEmpty(userPartNode)) {
@@ -231,16 +258,30 @@
     }
 
     @Override
-    public InetAddress getLocalInetAddress() {
-        return localInetAddress;
+    public Inet4Address getLocalInet4Address() {
+        return localInet4Address;
     }
 
     @Override
-    public InetAddress getPublicInetAddress() {
-        return publicInetAddress;
+    public Inet4Address getPublicInet4Address() {
+        return publicInet4Address;
     }
 
     @Override
+    public Inet6Address getPublicInet6Address() {
+        return publicInet6Address;
+    }
+    
+    @Override
+    public InetAddress getMatchingLocalInetAddress(InetAddress matchMyFamily) {
+    	if (matchMyFamily instanceof Inet6Address) {
+    		return getPublicInet6Address();
+    	} else {
+    		return getLocalInet4Address();
+    	}
+    }
+    
+    @Override
     public String getUserPart() {
         return userPart;
     }
@@ -281,17 +322,25 @@
     }
 
     @Override
-    public void setLocalInetAddress(InetAddress inetAddress) {
-        this.localInetAddress = inetAddress;
-        ipAddressNode.setTextContent(inetAddress.getHostAddress());
+    public void setLocalInet4Address(Inet4Address inet4Address) {
+        this.localInet4Address = inet4Address;
+        if (ipAddressNode != null) {
+        	ipAddressNode.setTextContent(inet4Address.getHostAddress());
+        }
     }
 
     @Override
-    public void setPublicInetAddress(InetAddress inetAddress) {
-        this.publicInetAddress = inetAddress;
+    public void setPublicInet4Address(Inet4Address inet4Address) {
+        this.publicInet4Address = inet4Address;
     }
 
     @Override
+    public void setPublicInet6Address(Inet6Address inet6Address) {
+        this.publicInet6Address = inet6Address;
+        //TODO// ipAddressNode, but IPv6-based
+    }
+
+    @Override
     public void setUserPart(String userPart) {
         this.userPart = userPart;
         userPartNode.setTextContent(userPart);
@@ -329,7 +378,9 @@
     @Override
     public void setMediaMode(MediaMode mediaMode) {
         this.mediaMode = mediaMode;
-        mediaModeNode.setTextContent(mediaMode.toString());
+        if (mediaModeNode != null) {
+        	mediaModeNode.setTextContent(mediaMode.toString());
+        }
     }
 
     @Override
Index: src/main/java/net/sourceforge/peers/JavaConfig.java
===================================================================
--- src/main/java/net/sourceforge/peers/JavaConfig.java	(revision 200)
+++ src/main/java/net/sourceforge/peers/JavaConfig.java	(working copy)
@@ -20,14 +20,17 @@
 package net.sourceforge.peers;
 
 import java.net.InetAddress;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
 
 import net.sourceforge.peers.media.MediaMode;
 import net.sourceforge.peers.sip.syntaxencoding.SipURI;
 
 public class JavaConfig implements Config {
 
-    private InetAddress localInetAddress;
-    private InetAddress publicInetAddress;
+    private Inet4Address localInet4Address;
+    private Inet4Address publicInet4Address;
+    private Inet6Address publicInet6Address;
     private String userPart;
     private String domain;
     private String password;
@@ -44,16 +47,30 @@
     }
 
     @Override
-    public InetAddress getLocalInetAddress() {
-        return localInetAddress;
+    public Inet4Address getLocalInet4Address() {
+        return localInet4Address;
     }
 
     @Override
-    public InetAddress getPublicInetAddress() {
-        return publicInetAddress;
+    public Inet4Address getPublicInet4Address() {
+        return publicInet4Address;
     }
 
     @Override
+    public Inet6Address getPublicInet6Address() {
+        return publicInet6Address;
+    }
+
+    @Override
+    public InetAddress getMatchingLocalInetAddress(InetAddress matchMyFamily) {
+    	if (matchMyFamily instanceof Inet6Address) {
+    		return getPublicInet6Address();
+    	} else {
+    		return getLocalInet4Address();
+    	}
+    }
+    
+    @Override
     public String getUserPart() {
         return userPart;
     }
@@ -94,16 +111,21 @@
     }
 
     @Override
-    public void setLocalInetAddress(InetAddress inetAddress) {
-        localInetAddress = inetAddress;
+    public void setLocalInet4Address(Inet4Address inet4Address) {
+        localInet4Address = inet4Address;
     }
 
     @Override
-    public void setPublicInetAddress(InetAddress inetAddress) {
-        publicInetAddress = inetAddress;
+    public void setPublicInet4Address(Inet4Address inet4Address) {
+        publicInet4Address = inet4Address;
     }
 
     @Override
+    public void setPublicInet6Address(Inet6Address inet6Address) {
+        publicInet6Address = inet6Address;
+    }
+
+    @Override
     public void setUserPart(String userPart) {
         this.userPart = userPart;
     }
Index: src/main/java/net/sourceforge/peers/sip/Utils.java
===================================================================
--- src/main/java/net/sourceforge/peers/sip/Utils.java	(revision 200)
+++ src/main/java/net/sourceforge/peers/sip/Utils.java	(working copy)
@@ -21,6 +21,10 @@
 
 
 import java.net.InetAddress;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.UnknownHostException;
+import java.util.List;
 
 import net.sourceforge.peers.sip.core.useragent.UAS;
 import net.sourceforge.peers.sip.syntaxencoding.SipHeaderFieldMultiValue;
@@ -44,19 +48,74 @@
         }
         return via;
     }
+
+    /** Retrieve the SIP address that initiated a transaction.  This can be used as a
+     * utility to determine the address family of a remote peer, for instance when
+     * constructing a response that holds SDP to an INVITE that had none.  If no SDP
+     * offer is available, looking at the remote peer's SIP address offers the best
+     * opportunity of constructing a decent response.
+     */
+    public final static InetAddress getInitiatingSipAddress(SipMessage sipMessage) {
+        SipHeaders sipHeaders = sipMessage.getSipHeaders();
+        SipHeaderFieldName viaName = new SipHeaderFieldName(RFC3261.HDR_VIA);
+        SipHeaderFieldValue via = sipHeaders.get(viaName);
+        if (via instanceof SipHeaderFieldMultiValue) {
+        	List<SipHeaderFieldValue> vias = ((SipHeaderFieldMultiValue)via).getValues();
+            via = vias.get(vias.size()-1);
+        }
+        if (via == null) {
+        	return null;
+        }
+        String viastr = via.toString ();
+        int starthost = 1 + viastr.indexOf (' ');
+        if (starthost == 0) {
+        	return null;
+        }
+        int endhost = viastr.indexOf (';', starthost);
+        if (endhost == -1) {
+        	return null;
+        }
+        if (viastr.charAt (starthost) == '[') {
+        	starthost++;
+        	endhost = viastr.lastIndexOf (']', endhost);
+        } else {
+        	int colon = viastr.lastIndexOf (':', endhost);
+        	if ((colon > -1) && (colon < endhost)) {
+        		endhost = colon;
+        	}
+        }
+        if (starthost >= endhost) {
+        	return null;
+        }
+        try {
+        	return InetAddress.getByName (viastr.substring (starthost, endhost));
+        } catch (UnknownHostException uhe) {
+        	return null;
+        }
+        //TODO// Parse via, retrieve host, convert to InetAddress
+    }
+
     
     public final static String generateTag() {
         return randomString(8);
     }
     
-    public final static String generateCallID(InetAddress inetAddress) {
+    public final static String generateCallID(Inet4Address inet4Address, Inet6Address inet6Address) {
         //TODO make a hash using current time millis, public ip @, private @, and a random string
         StringBuffer buf = new StringBuffer();
         buf.append(randomString(8));
         buf.append('-');
         buf.append(String.valueOf(System.currentTimeMillis()));
         buf.append('@');
-        buf.append(inetAddress.getHostName());
+        if (inet4Address != null) {
+        	buf.append(inet4Address.getHostName());
+		if (inet6Address != null) {
+			buf.append('.');
+		}
+        }
+        if (inet6Address != null) {
+        	buf.append(inet6Address.getHostName());
+        }
         return buf.toString();
     }
     
Index: src/main/java/net/sourceforge/peers/sip/core/useragent/handlers/RegisterHandler.java
===================================================================
--- src/main/java/net/sourceforge/peers/sip/core/useragent/handlers/RegisterHandler.java	(revision 200)
+++ src/main/java/net/sourceforge/peers/sip/core/useragent/handlers/RegisterHandler.java	(working copy)
@@ -20,6 +20,8 @@
 package net.sourceforge.peers.sip.core.useragent.handlers;
 
 import java.net.InetAddress;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
 import java.net.UnknownHostException;
 import java.util.Hashtable;
 import java.util.Timer;
@@ -96,9 +98,27 @@
         if (sipUri == null) {
             sipUri = destinationUri;
         }
-        InetAddress inetAddress;
+        InetAddress inetAddress = null;
         try {
-            inetAddress = InetAddress.getByName(sipUri.getHost());
+        	InetAddress addrs[] = InetAddress.getAllByName(sipUri.getHost());
+        	if (addrs.length == 0) {
+        		throw new UnknownHostException ("No IP found for the host");
+        	}
+        	boolean gotIPv6 = userAgent.getConfig().getPublicInet6Address() != null;
+        	boolean gotIPv4 = userAgent.getConfig().getLocalInet4Address()  != null;
+        	for (int i = 0; i<addrs.length; i++) {
+        		if (gotIPv6 && (addrs[i] instanceof Inet6Address)) {
+        			inetAddress = addrs[i];
+        			break; // Prefer IPv6, bail out immediately
+        		}
+        		if (gotIPv4 && (addrs[i] instanceof Inet4Address)) {
+        			inetAddress = addrs [i];
+        			// Continue trying, perhaps an IPv6 address overwrites what was found here
+        		}
+        	}
+            if (inetAddress == null) {
+            	throw new UnknownHostException ("Cannot connect between IPv4-only and IPv6-only");
+            }
         } catch (UnknownHostException e) {
             throw new SipUriSyntaxException("unknown host: "
                     + sipUri.getHost(), e);
@@ -178,7 +198,11 @@
                             InetAddress receivedInetAddress =
                                 InetAddress.getByName(received);
                             Config config = userAgent.getConfig();
-                            config.setPublicInetAddress(receivedInetAddress);
+                            if (receivedInetAddress instanceof Inet6Address) {
+                            	config.setPublicInet6Address((Inet6Address) receivedInetAddress);
+                            } else {
+                            	config.setPublicInet4Address((Inet4Address) receivedInetAddress);
+                            }
                             userAgent.getUac().register();
                         } catch (UnknownHostException e) {
                             notifyListener(sipResponse);
Index: src/main/java/net/sourceforge/peers/sip/core/useragent/handlers/OptionsHandler.java
===================================================================
--- src/main/java/net/sourceforge/peers/sip/core/useragent/handlers/OptionsHandler.java	(revision 200)
+++ src/main/java/net/sourceforge/peers/sip/core/useragent/handlers/OptionsHandler.java	(working copy)
@@ -54,7 +54,9 @@
         int localPort = new Random().nextInt(MAX_PORTS);
         try {
             SessionDescription sessionDescription =
-                sdpManager.createSessionDescription(null, localPort);
+                sdpManager.createSessionDescription(null,
+                		Utils.getInitiatingSipAddress (sipRequest),
+                		localPort);
             sipResponse.setBody(sessionDescription.toString().getBytes());
         } catch (IOException e) {
             logger.error(e.getMessage(), e);
Index: src/main/java/net/sourceforge/peers/sip/core/useragent/handlers/InviteHandler.java
===================================================================
--- src/main/java/net/sourceforge/peers/sip/core/useragent/handlers/InviteHandler.java	(revision 200)
+++ src/main/java/net/sourceforge/peers/sip/core/useragent/handlers/InviteHandler.java	(working copy)
@@ -22,12 +22,17 @@
 import java.io.IOException;
 import java.net.DatagramSocket;
 import java.net.InetAddress;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
 import java.net.SocketException;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Hashtable;
 import java.util.List;
 
+import nl.openfortress.socket6bed4.DatagramSocket6bed4;
+import nl.openfortress.socket6bed4.Inet6bed4Address;
+
 import net.sourceforge.peers.Logger;
 import net.sourceforge.peers.sdp.Codec;
 import net.sourceforge.peers.sdp.MediaDestination;
@@ -172,38 +177,58 @@
         
         // TODO 486 or 600
         
+        SessionDescription offer, answer;
         byte[] offerBytes = sipRequest.getBody();
-        SessionDescription answer;
+        InetAddress matchThisAddressFamilyInSdp;
+        if (offerBytes != null && contentType != null &&
+                RFC3261.CONTENT_TYPE_SDP.equals(contentType.getValue())) {
+            // create response in 200
+            offer = sdpManager.parse(offerBytes);
+            matchThisAddressFamilyInSdp = offer.getIpAddress ();
+        } else {
+        	// create offer in 200 (never tested...)
+        	offer = null;
+        	matchThisAddressFamilyInSdp = Utils.getInitiatingSipAddress (sipRequest);
+        }
         try {
             int rtpPort = userAgent.getConfig().getRtpPort();
             DatagramSocket datagramSocket;
             try {
-                if (rtpPort == 0) {
-                    datagramSocket = new DatagramSocket();
-                } else {
-                    datagramSocket = new DatagramSocket(rtpPort);
-                }
+				if ((matchThisAddressFamilyInSdp instanceof Inet6Address) && Inet6bed4Address.is6bed4Address ((Inet6Address) matchThisAddressFamilyInSdp)) {
+				    if (rtpPort == 0) {
+					datagramSocket = new DatagramSocket6bed4 ();
+				    } else {
+					datagramSocket = new DatagramSocket6bed4 (rtpPort);
+				    }
+				} else {
+                    if (rtpPort == 0) {
+                        datagramSocket = new DatagramSocket();
+                    } else {
+                        datagramSocket = new DatagramSocket(rtpPort);
+                    }
+				}
                 datagramSocket.setSoTimeout(TIMEOUT);
             } catch (SocketException e) {
                 logger.error("cannot create datagram socket ", e);
                 return;
             }
             userAgent.getMediaManager().setDatagramSocket(datagramSocket);
-            if (offerBytes != null && contentType != null &&
-                    RFC3261.CONTENT_TYPE_SDP.equals(contentType.getValue())) {
+            if (offer != null) {
                 // create response in 200
                 try {
-                    SessionDescription offer = sdpManager.parse(offerBytes);
                     answer = sdpManager.createSessionDescription(offer,
+                    		null,
                             datagramSocket.getLocalPort());
                     mediaDestination = sdpManager.getMediaDestination(offer);
                 } catch (NoCodecException e) {
-                    answer = sdpManager.createSessionDescription(null,
+						answer = sdpManager.createSessionDescription(null,
+							Utils.getInitiatingSipAddress (sipRequest),
                             datagramSocket.getLocalPort());
                 }
             } else {
                 // create offer in 200 (never tested...)
                 answer = sdpManager.createSessionDescription(null,
+                		Utils.getInitiatingSipAddress(sipRequest),
                         datagramSocket.getLocalPort());
             }
             sipResponse.setBody(answer.toString().getBytes());
@@ -324,9 +349,27 @@
         if (sipUri == null) {
             sipUri = destinationUri;
         }
-        InetAddress inetAddress;
+        InetAddress inetAddress = null;
         try {
-            inetAddress = InetAddress.getByName(sipUri.getHost());
+        	InetAddress addrs[] = InetAddress.getAllByName(sipUri.getHost());
+        	if (addrs.length == 0) {
+        		throw new UnknownHostException ("No IP found for the host");
+        	}
+        	boolean gotIPv6 = userAgent.getConfig().getPublicInet6Address() != null;
+        	boolean gotIPv4 = userAgent.getConfig().getLocalInet4Address()  != null;
+        	for (int i = 0; i<addrs.length; i++) {
+        		if (gotIPv6 && (addrs[i] instanceof Inet6Address)) {
+        			inetAddress = addrs[i];
+        			break; // Prefer IPv6, bail out immediately
+        		}
+        		if (gotIPv4 && (addrs[i] instanceof Inet4Address)) {
+        			inetAddress = addrs [i];
+        			// Continue trying, perhaps an IPv6 address overwrites what was found here
+        		}
+        	}
+            if (inetAddress == null) {
+            	throw new UnknownHostException ("Cannot connect between IPv4-only and IPv6-only");
+            }
         } catch (UnknownHostException e) {
             throw new SipUriSyntaxException("unknown host: "
                     + sipUri.getHost(), e);
@@ -337,11 +380,19 @@
         int rtpPort = userAgent.getConfig().getRtpPort();
         DatagramSocket datagramSocket;
         try {
-            if (rtpPort == 0) {
-                datagramSocket = new DatagramSocket();
-            } else {
-                datagramSocket = new DatagramSocket(rtpPort);
-            }
+	    if ((inetAddress instanceof Inet6Address) && Inet6bed4Address.is6bed4Address ((Inet6Address) inetAddress)) {
+		if (rtpPort == 0) {
+		    datagramSocket = new DatagramSocket6bed4 ();
+		} else {
+		    datagramSocket = new DatagramSocket6bed4 (rtpPort);
+		}
+	    } else {
+		if (rtpPort == 0) {
+		    datagramSocket = new DatagramSocket();
+		} else {
+		    datagramSocket = new DatagramSocket(rtpPort);
+		}
+	    }
             datagramSocket.setSoTimeout(TIMEOUT);
         } catch (SocketException e) {
             logger.error("cannot create datagram socket ", e);
@@ -351,6 +402,7 @@
         try {
             SessionDescription sessionDescription =
                 sdpManager.createSessionDescription(null,
+                		inetAddress,
                         datagramSocket.getLocalPort());
             sipRequest.setBody(sessionDescription.toString().getBytes());
         } catch (IOException e) {
@@ -509,8 +561,15 @@
         String remoteAddress = mediaDestination.getDestination();
         int remotePort = mediaDestination.getPort();
         Codec codec = mediaDestination.getCodec();
-        String localAddress = userAgent.getConfig()
-            .getLocalInetAddress().getHostAddress();
+        String localAddress = null;
+		try {
+			localAddress = userAgent.getConfig()
+			    .getMatchingLocalInetAddress(InetAddress.getByName(remoteAddress)).getHostAddress();
+		} catch (NullPointerException npe) {
+			logger.error("No matching address in requested address family");
+		} catch (UnknownHostException uhe) {
+			logger.error("Media address did not lead to an IP address");
+		}
 
         userAgent.getMediaManager().successResponseReceived(localAddress,
                 remoteAddress, remotePort, codec);
@@ -519,7 +578,7 @@
         dialog.receivedOrSent2xx();
         
         //generate ack
-        //p. 82 §3
+        //p. 82 ��3
         SipRequest ack = dialog.buildSubsequentRequest(RFC3261.METHOD_ACK);
         
         
@@ -574,9 +633,27 @@
         if (sipUri == null) {
             sipUri = destinationUri;
         }
-        InetAddress inetAddress;
+        InetAddress inetAddress = null;
         try {
-            inetAddress = InetAddress.getByName(sipUri.getHost());
+        	InetAddress addrs[] = InetAddress.getAllByName(sipUri.getHost());
+        	if (addrs.length == 0) {
+        		throw new UnknownHostException ("No IP found for the host");
+        	}
+        	boolean gotIPv6 = userAgent.getConfig().getPublicInet6Address() != null;
+        	boolean gotIPv4 = userAgent.getConfig().getLocalInet4Address()  != null;
+        	for (int i = 0; i<addrs.length; i++) {
+        		if (gotIPv6 && (addrs[i] instanceof Inet6Address)) {
+        			inetAddress = addrs[i];
+        			break; // Prefer IPv6, bail out immediately
+        		}
+        		if (gotIPv4 && (addrs[i] instanceof Inet4Address)) {
+        			inetAddress = addrs [i];
+        			// Continue trying, perhaps an IPv6 address overwrites what was found here
+        		}
+        	}
+            if (inetAddress == null) {
+            	throw new UnknownHostException ("Cannot connect between IPv4-only and IPv6-only");
+            }
         } catch (UnknownHostException e) {
             logger.error("unknown host: " + sipUri.getHost(), e);
             return;
Index: src/main/java/net/sourceforge/peers/sip/core/useragent/UAC.java
===================================================================
--- src/main/java/net/sourceforge/peers/sip/core/useragent/UAC.java	(revision 200)
+++ src/main/java/net/sourceforge/peers/sip/core/useragent/UAC.java	(working copy)
@@ -93,7 +93,8 @@
         profileUri = RFC3261.SIP_SCHEME + RFC3261.SCHEME_SEPARATOR
         	+ userAgent.getUserpart() + RFC3261.AT + domain;
         registerCallID = Utils.generateCallID(
-                userAgent.getConfig().getLocalInetAddress());
+                userAgent.getConfig().getLocalInet4Address(),
+                userAgent.getConfig().getPublicInet6Address());
         SipRequest sipRequest = initialRequestManager.createInitialRequest(
                 requestUri, RFC3261.METHOD_REGISTER, profileUri,
                 registerCallID);
Index: src/main/java/net/sourceforge/peers/sip/core/useragent/InitialRequestManager.java
===================================================================
--- src/main/java/net/sourceforge/peers/sip/core/useragent/InitialRequestManager.java	(revision 200)
+++ src/main/java/net/sourceforge/peers/sip/core/useragent/InitialRequestManager.java	(working copy)
@@ -129,7 +129,8 @@
             localCallId = callId;
         } else {
             localCallId = Utils.generateCallID(
-                    userAgent.getConfig().getLocalInetAddress());
+                    userAgent.getConfig().getLocalInet4Address(),
+                    userAgent.getConfig().getPublicInet6Address());
         }
         headers.add(callIdName, new SipHeaderFieldValue(localCallId));
         
Index: src/main/java/net/sourceforge/peers/sip/core/useragent/MidDialogRequestManager.java
===================================================================
--- src/main/java/net/sourceforge/peers/sip/core/useragent/MidDialogRequestManager.java	(revision 200)
+++ src/main/java/net/sourceforge/peers/sip/core/useragent/MidDialogRequestManager.java	(working copy)
@@ -19,6 +19,8 @@
 
 package net.sourceforge.peers.sip.core.useragent;
 
+import java.net.Inet4Address;
+import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.Hashtable;
@@ -129,9 +131,28 @@
         if (sipUri == null) {
             sipUri = destinationUri;
         }
-        InetAddress inetAddress;
+        
+        InetAddress inetAddress = null;
         try {
-            inetAddress = InetAddress.getByName(sipUri.getHost());
+        	InetAddress addrs[] = InetAddress.getAllByName(sipUri.getHost());
+        	if (addrs.length == 0) {
+        		throw new UnknownHostException ("No IP found for the host");
+        	}
+        	boolean gotIPv6 = userAgent.getConfig().getPublicInet6Address() != null;
+        	boolean gotIPv4 = userAgent.getConfig().getLocalInet4Address()  != null;
+        	for (int i = 0; i<addrs.length; i++) {
+        		if (gotIPv6 && (addrs[i] instanceof Inet6Address)) {
+        			inetAddress = addrs[i];
+        			break; // Prefer IPv6, bail out immediately
+        		}
+        		if (gotIPv4 && (addrs[i] instanceof Inet4Address)) {
+        			inetAddress = addrs [i];
+        			// Continue trying, perhaps an IPv6 address overwrites what was found here
+        		}
+        	}
+            if (inetAddress == null) {
+            	throw new UnknownHostException ("Cannot connect between IPv4-only and IPv6-only");
+            }
         } catch (UnknownHostException e) {
             logger.error("unknown host: " + sipUri.getHost(), e);
             return null;
Index: src/main/java/net/sourceforge/peers/sip/core/useragent/UserAgent.java
===================================================================
--- src/main/java/net/sourceforge/peers/sip/core/useragent/UserAgent.java	(revision 200)
+++ src/main/java/net/sourceforge/peers/sip/core/useragent/UserAgent.java	(working copy)
@@ -20,10 +20,18 @@
 package net.sourceforge.peers.sip.core.useragent;
 
 import java.io.File;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
 import java.net.SocketException;
 import java.util.ArrayList;
+import java.util.Enumeration;
 import java.util.List;
 
+import nl.openfortress.socket6bed4.ConnectionPool;
+import nl.openfortress.socket6bed4.ServerNode;
+
 import net.sourceforge.peers.Config;
 import net.sourceforge.peers.Logger;
 import net.sourceforge.peers.XmlConfig;
@@ -89,6 +97,97 @@
         this(sipListener, config, null, logger);
     }
 
+    /* A bit of cleverness to enable Peers to function even without
+     * a configuration file, or with options not set.  It will only
+     * change configuration options that were not previously set.
+     */
+    private void autofillConfigDefaults () {
+    	//
+    	// 1. Autofill MediaMode to 
+    	if (config.getMediaMode () == null) {
+    		config.setMediaMode (MediaMode.captureAndPlayback);
+    	}
+    	//
+    	// 2. Autofill IPv4 and IPv6 addresses
+		Inet4Address in4local = null, in4public = null;
+		Inet6Address in6public = null;
+		Enumeration<NetworkInterface> ifs;
+		try {
+			ifs = NetworkInterface.getNetworkInterfaces ();
+		} catch (SocketException se) {
+			throw new RuntimeException (se.toString ());
+		}
+		if (ifs == null) {
+			return;
+		}
+		while (ifs.hasMoreElements ()) {
+			NetworkInterface iff = ifs.nextElement ();
+			if (iff == null) {
+				continue;
+			}
+			try {
+				if (!iff.isUp ()) {
+					continue;
+				}
+			} catch (SocketException se) {
+				continue;
+			}
+			Enumeration<InetAddress> lia = iff.getInetAddresses ();
+			if (lia == null) {
+				continue;
+			}
+			while (lia.hasMoreElements ()) {
+				InetAddress ia = lia.nextElement ();
+				if (ia == null) {
+					continue;
+				}
+				if (ia.isAnyLocalAddress ()) {
+					continue;
+				}
+				if (ia.isLinkLocalAddress ()) {
+					continue;
+				}
+				if (ia.isLoopbackAddress ()) {
+					continue;
+				}
+				if (ia.isMulticastAddress ()) {
+					continue;
+				}
+				boolean sitelocal = ia.isSiteLocalAddress ();
+				boolean is_ipv6 = (ia instanceof Inet6Address);
+				if (is_ipv6) {
+					if (!sitelocal) {
+						in6public = (Inet6Address) ia;
+					}
+				} else {
+					if (sitelocal && (in4public == null)) {
+						in4local = (Inet4Address) ia;
+						in4public = null;
+					}
+					if (!sitelocal) {
+						in4local = in4public = (Inet4Address) ia;
+					}
+				}
+				if ((config.getLocalInet4Address () == null) && (config.getPublicInet4Address () == null)) {
+					config.setLocalInet4Address (in4local);
+					config.setPublicInet4Address (in4public);
+				}
+				if (config.getPublicInet6Address () == null) {
+					if (in6public != null) {
+						config.setPublicInet6Address ((Inet6Address) in6public);
+					} else {
+						ConnectionPool cp = ConnectionPool.getSharedConnectionPool ();
+						nl.openfortress.socket6bed4.ServerNode sn = cp.getDefaultServerNode ();
+						Inet6Address i6a = sn.getShared6bed4Address ();
+						config.setPublicInet6Address (i6a);
+					}
+				}
+			}
+		}
+    }
+
+
+    
     private UserAgent(SipListener sipListener, Config config, String peersHome,
             Logger logger) throws SocketException {
         this.sipListener = sipListener;
@@ -105,13 +204,23 @@
                     + CONFIG_FILE, this.logger);
         }
         this.config = config;
+        autofillConfigDefaults ();
 
         cseqCounter = 1;
         
         StringBuffer buf = new StringBuffer();
         buf.append("starting user agent [");
-        buf.append("myAddress: ");
-        buf.append(config.getLocalInetAddress().getHostAddress()).append(", ");
+        InetAddress inaddr;
+        inaddr = config.getLocalInet4Address();
+        if (inaddr != null) {
+	        buf.append("myIPv4Address: ");
+	        buf.append(inaddr.getHostAddress()).append(", ");
+        }
+        inaddr = config.getPublicInet6Address();
+        if (inaddr != null) {
+	        buf.append("myIPv6Address: ");
+	        buf.append(inaddr.getHostAddress()).append(", ");
+        }
         buf.append("sipPort: ");
         buf.append(config.getSipPort()).append(", ");
         buf.append("userpart: ");
@@ -223,7 +332,8 @@
 
     public void close() {
         transportManager.closeTransports();
-        config.setPublicInetAddress(null);
+        config.setPublicInet4Address(null);
+        config.setPublicInet6Address(null);
     }
 
     /**
Index: src/main/java/net/sourceforge/peers/sip/transport/MessageSender.java
===================================================================
--- src/main/java/net/sourceforge/peers/sip/transport/MessageSender.java	(revision 200)
+++ src/main/java/net/sourceforge/peers/sip/transport/MessageSender.java	(working copy)
@@ -20,6 +20,7 @@
 package net.sourceforge.peers.sip.transport;
 
 import java.io.IOException;
+import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.util.Timer;
 import java.util.TimerTask;
@@ -47,6 +48,7 @@
         super();
         this.localPort = localPort;
         this.inetAddress = inetAddress;
+logger.debug ("TODO: Setting up inetAddress with " + inetAddress.toString());
         this.port = port;
         this.config = config;
         this.transportName = transportName;
@@ -62,11 +64,22 @@
 
     public String getContact() {
         StringBuffer buf = new StringBuffer();
-        InetAddress myAddress = config.getPublicInetAddress();
+        InetAddress myAddress;
+        if (inetAddress instanceof Inet6Address) {
+        	myAddress = config.getPublicInet6Address();
+        } else { 
+        	myAddress = config.getPublicInet4Address();
+    	}
         if (myAddress == null) {
-            myAddress = config.getLocalInetAddress();
+            myAddress = config.getLocalInet4Address();
         }
-        buf.append(myAddress.getHostAddress());
+        if (myAddress instanceof Inet6Address) {
+        	buf.append ("[");
+            buf.append(myAddress.getHostAddress());
+        	buf.append ("]");
+        } else {
+            buf.append(myAddress.getHostAddress());
+        }
         buf.append(RFC3261.TRANSPORT_PORT_SEP);
         //buf.append(config.getSipPort());
         buf.append(localPort);
Index: src/main/java/net/sourceforge/peers/sip/transport/TransportManager.java
===================================================================
--- src/main/java/net/sourceforge/peers/sip/transport/TransportManager.java	(revision 200)
+++ src/main/java/net/sourceforge/peers/sip/transport/TransportManager.java	(working copy)
@@ -36,11 +36,15 @@
 import java.io.IOException;
 import java.net.DatagramSocket;
 import java.net.Inet4Address;
+import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.net.SocketException;
 import java.net.UnknownHostException;
 import java.util.Hashtable;
 
+import nl.openfortress.socket6bed4.DatagramSocket6bed4;
+import nl.openfortress.socket6bed4.Inet6bed4Address;
+
 import net.sourceforge.peers.Config;
 import net.sourceforge.peers.Logger;
 import net.sourceforge.peers.sip.RFC3261;
@@ -108,7 +112,7 @@
         buf.append(transport);
         if (inetAddress.isMulticastAddress()) {
             SipHeaderParamName maddrName = new SipHeaderParamName(PARAM_MADDR);
-            via.addParam(maddrName, inetAddress.getHostAddress());
+            via.addParam(maddrName, inetAddress.getHostAddress()); //TODO Brackets needed for IPv6?
             if (inetAddress instanceof Inet4Address) {
                 SipHeaderParamName ttlName = new SipHeaderParamName(PARAM_TTL);
                 via.addParam(ttlName, IPV4_TTL);
@@ -122,12 +126,23 @@
         
         //TODO user server connection
         
-        InetAddress myAddress = config.getPublicInetAddress();
+        InetAddress myAddress;
+        if (inetAddress instanceof Inet6Address) {
+        	myAddress = config.getPublicInet6Address();
+        } else {
+        	myAddress = config.getPublicInet4Address();
+        }
         if (myAddress == null) {
-            myAddress = config.getLocalInetAddress();
+            myAddress = config.getLocalInet4Address();
         }
 
-        buf.append(myAddress.getHostAddress()); //TODO use getHostName if real DNS
+        if (myAddress instanceof Inet6Address) {
+        	buf.append ("[");
+            buf.append(myAddress.getHostAddress()); //TODO use getHostName if real DNS
+            buf.append ("]");
+        } else {
+        	buf.append(myAddress.getHostAddress()); //TODO use getHostName if real DNS
+        }
         buf.append(TRANSPORT_PORT_SEP);
         
 
@@ -148,7 +163,7 @@
         via.setValue(buf.toString());
         
         SipTransportConnection connection = new SipTransportConnection(
-                config.getLocalInetAddress(), sipPort, inetAddress, port,
+                config.getMatchingLocalInetAddress(inetAddress), sipPort, inetAddress, port,
                 transport);
 
         MessageSender messageSender = messageSenders.get(connection);
@@ -161,18 +176,31 @@
     
     public void createServerTransport(String transportType, int port)
             throws SocketException {
-        SipTransportConnection conn = new SipTransportConnection(
-                    config.getLocalInetAddress(), port, null,
-                    SipTransportConnection.EMPTY_PORT, transportType);
-        
-        MessageReceiver messageReceiver = messageReceivers.get(conn);
-        if (messageReceiver == null) {
-            messageReceiver = createMessageReceiver(conn);
-            new Thread(messageReceiver).start();
-        }
-        if (!messageReceiver.isListening()) {
-            new Thread(messageReceiver).start();
-        }
+    	for (int fam=4; fam <= 6; fam +=2 ) {
+    		InetAddress localEndPoint;
+    		if (fam == 4) {
+    			localEndPoint = config.getLocalInet4Address();
+    		} else {
+    			localEndPoint = config.getPublicInet6Address();
+    		}
+    		if (localEndPoint != null) {
+    	        SipTransportConnection conn = new SipTransportConnection(
+                        localEndPoint, port, null,
+                        SipTransportConnection.EMPTY_PORT, transportType);
+	            MessageReceiver messageReceiver = messageReceivers.get(conn);
+	            if (messageReceiver == null) {
+	                messageReceiver = createMessageReceiver(conn);
+	                Thread rcvr = new Thread(messageReceiver);
+	                rcvr.setDaemon (true);
+	                rcvr.start ();
+	            }
+	            if (!messageReceiver.isListening()) {
+	                Thread rcvr = new Thread(messageReceiver);
+	                rcvr.setDaemon (true);
+	                rcvr.start ();
+	            }
+    		}
+    	}
     }
     
     public void sendResponse(SipResponse sipResponse) throws IOException {
@@ -195,13 +223,19 @@
         }
         String host;
         int port;
-        int colonPos = hostport.indexOf(RFC3261.TRANSPORT_PORT_SEP);
+        int bra_ket = 0, endhost = 0;
+        if (hostport.charAt (0) == '[') {
+        	bra_ket = 1;
+        	endhost = hostport.indexOf(']');
+        }
+    	int colonPos = hostport.indexOf(RFC3261.TRANSPORT_PORT_SEP, endhost);
+        
         if (colonPos > -1) {
-            host = hostport.substring(0, colonPos);
+            host = hostport.substring(bra_ket, colonPos - bra_ket);
             port = Integer.parseInt(
                     hostport.substring(colonPos + 1, hostport.length()));
         } else {
-            host = hostport;
+            host = hostport.substring(bra_ket, hostport.length() - bra_ket);
             port = RFC3261.TRANSPORT_DEFAULT_PORT;
         }
         
@@ -230,8 +264,10 @@
         }
         SipTransportConnection connection;
         try {
-            connection = new SipTransportConnection(config.getLocalInetAddress(),
-                    sipPort, InetAddress.getByName(host),
+        	InetAddress inetAddress = InetAddress.getByName (host); 
+            connection = new SipTransportConnection(
+            		config.getMatchingLocalInetAddress(inetAddress),
+                    sipPort, inetAddress,
                     port, transport);
         } catch (UnknownHostException e) {
             logger.error("unknwon host", e);
@@ -298,11 +334,19 @@
             //TODO use Utils.getMyAddress to create socket on appropriate NIC
             DatagramSocket datagramSocket = datagramSockets.get(conn);
             if (datagramSocket == null) {
-                logger.debug("new DatagramSocket(" + conn.getLocalPort()
-                        + ", " + conn.getLocalInetAddress());
-                datagramSocket = new DatagramSocket(conn.getLocalPort(),
-                        conn.getLocalInetAddress());
-                datagramSocket.setSoTimeout(SOCKET_TIMEOUT);
+   	    if ((conn.getLocalInetAddress () instanceof Inet6Address) && Inet6bed4Address.is6bed4Address ((Inet6Address) conn.getLocalInetAddress ())) {
+                   logger.debug("new DatagramSocket6bed4(" + conn.getLocalPort()
+                           + ", " + conn.getLocalInetAddress());
+                   datagramSocket = new DatagramSocket6bed4(conn.getLocalPort(),
+                           (Inet6Address) conn.getLocalInetAddress());
+                   datagramSocket.setSoTimeout(SOCKET_TIMEOUT);
+		} else {
+                   logger.debug("new DatagramSocket(" + conn.getLocalPort()
+                           + ", " + conn.getLocalInetAddress());
+                   datagramSocket = new DatagramSocket(conn.getLocalPort(),
+                           conn.getLocalInetAddress());
+                   datagramSocket.setSoTimeout(SOCKET_TIMEOUT);
+		}
                 datagramSockets.put(conn, datagramSocket);
                 logger.info("added datagram socket " + conn);
             }
@@ -322,7 +366,9 @@
         MessageReceiver messageReceiver = messageReceivers.get(conn);
         if (messageReceiver == null) {
         	messageReceiver = createMessageReceiver(conn, socket);
-        	new Thread(messageReceiver).start();
+        	Thread rcvr = new Thread(messageReceiver);
+        	rcvr.setDaemon (true);
+        	rcvr.start();
         }
 //        if (RFC3261.TRANSPORT_UDP.equalsIgnoreCase(conn.getTransport())) {
 //            messageSender = new UdpMessageSender(conn.getRemoteInetAddress(),
@@ -352,11 +398,19 @@
         if (RFC3261.TRANSPORT_UDP.equals(conn.getTransport())) {
             DatagramSocket datagramSocket = datagramSockets.get(conn);
             if (datagramSocket == null) {
-                logger.debug("new DatagramSocket(" + conn.getLocalPort()
-                        + ", " + conn.getLocalInetAddress());
-                datagramSocket = new DatagramSocket(conn.getLocalPort(),
-                        conn.getLocalInetAddress());
-                datagramSocket.setSoTimeout(SOCKET_TIMEOUT);
+		if ((conn.getLocalInetAddress () instanceof Inet6Address) && Inet6bed4Address.is6bed4Address ((Inet6Address) conn.getLocalInetAddress ())) {
+                   logger.debug("new DatagramSocket6bed4(" + conn.getLocalPort()
+                           + ", " + conn.getLocalInetAddress());
+                   datagramSocket = new DatagramSocket6bed4(conn.getLocalPort(),
+                           (Inet6Address) conn.getLocalInetAddress());
+                   datagramSocket.setSoTimeout(SOCKET_TIMEOUT);
+		} else {
+                   logger.debug("new DatagramSocket(" + conn.getLocalPort()
+                           + ", " + conn.getLocalInetAddress());
+                   datagramSocket = new DatagramSocket(conn.getLocalPort(),
+                           conn.getLocalInetAddress());
+                   datagramSocket.setSoTimeout(SOCKET_TIMEOUT);
+		}
                 if (conn.getLocalPort() == 0) {
                     sipTransportConnection = new SipTransportConnection(
                             conn.getLocalInetAddress(),
@@ -405,6 +459,7 @@
 			return;
 		}
 		for (DatagramSocket datagramSocket: datagramSockets.values()) {
+logger.debug ("TODO: Closing datagramSocket " + datagramSocket.toString ());
 			datagramSocket.close();
 		}
 		datagramSockets.clear();
Index: src/main/java/net/sourceforge/peers/sip/transport/MessageReceiver.java
===================================================================
--- src/main/java/net/sourceforge/peers/sip/transport/MessageReceiver.java	(revision 200)
+++ src/main/java/net/sourceforge/peers/sip/transport/MessageReceiver.java	(working copy)
@@ -106,7 +106,7 @@
         if (!startLine.contains(RFC3261.DEFAULT_SIP_VERSION)) {
             // keep-alive, send back to sender
             SipTransportConnection sipTransportConnection =
-                new SipTransportConnection(config.getLocalInetAddress(),
+                new SipTransportConnection(config.getMatchingLocalInetAddress(sourceIp),
                         port, sourceIp, sourcePort, transport);
             MessageSender messageSender = transportManager.getMessageSender(
                     sipTransportConnection);
Index: src/main/java/net/sourceforge/peers/sip/transport/UdpMessageSender.java
===================================================================
--- src/main/java/net/sourceforge/peers/sip/transport/UdpMessageSender.java	(revision 200)
+++ src/main/java/net/sourceforge/peers/sip/transport/UdpMessageSender.java	(working copy)
@@ -40,6 +40,8 @@
         super(datagramSocket.getLocalPort(), inetAddress, port,
                 config, RFC3261.TRANSPORT_UDP, logger);
         this.datagramSocket = datagramSocket;
+logger.debug ("TODO: Setup datagramSocket with " + datagramSocket.toString());
+logger.debug ("TODO: Setup datagramSocket has inetAddress " + datagramSocket.getLocalAddress().toString());
     }
 
     @Override
@@ -63,7 +65,8 @@
                 inetAddress, port);
         logger.debug("UdpMessageSender.sendBytes " + bytes.length
                 + " " + inetAddress + ":" + port);
-        logger.debug(datagramSocket.getLocalAddress().toString());
+logger.debug ("TODO: Sending to datagramSocket " + datagramSocket.toString());
+        //TODO:NOT_ALWAYS_SET// logger.debug(datagramSocket.getLocalAddress().toString());
         try {
             datagramSocket.send(packet);
         } catch (Throwable t) {
Index: src/main/java/net/sourceforge/peers/sip/syntaxencoding/SipURI.java
===================================================================
--- src/main/java/net/sourceforge/peers/sip/syntaxencoding/SipURI.java	(revision 200)
+++ src/main/java/net/sourceforge/peers/sip/syntaxencoding/SipURI.java	(working copy)
@@ -20,11 +20,14 @@
 package net.sourceforge.peers.sip.syntaxencoding;
 
 import java.util.Hashtable;
+import java.util.Random;
 
 import net.sourceforge.peers.sip.RFC3261;
 
+import org.xbill.DNS.*;
 
 
+
 public class SipURI {
 
     public final static int DEFAULT_PORT = -1;
@@ -42,7 +45,11 @@
     private Hashtable<String, String> uriParameters;
     //headers not implemented
     //private Hashtable<String, String> headers;
-
+    /**
+     * Random number generation is needed to handle SRV records well
+     */
+    static private Random rng = new Random ();
+    
     public SipURI(String sipUri)
             throws SipUriSyntaxException {
         stringRepresentation = sipUri;
@@ -69,16 +76,77 @@
         }
         String hostport = buf.substring(0, endHostport);
         buf.delete(0, endHostport);
-        int colonPos = hostport.indexOf(':');
-        if (colonPos > -1) {
-            if (colonPos == hostport.length() - 1) {
+        int colonPos;
+        if (hostport.charAt (0) == '[') {
+        	int endHost = hostport.indexOf (']');
+        	if (endHost == -1) {
+        		throw new SipUriSyntaxException("brackets '[' and ']' around host are not matched");
+        	}
+        	if (endHostport == endHost) {
+        		colonPos = -1;
+        	} else {
+        		colonPos = endHost + 1; 
+        		if (hostport.charAt (colonPos) != ':') {
+        			throw new SipUriSyntaxException("non-port garbage following host");
+        		}
+        	}
+        	if (colonPos > -1) {
+        		host = hostport.substring (1, colonPos - 1);
+        	} else {
+        		host = hostport.substring (1, hostport.length() - 1);
+        	}
+        } else {
+        	colonPos = hostport.indexOf(':');
+        	if (colonPos > -1) {
+        		host = hostport.substring (0, colonPos);
+        	} else {
+        		host = hostport;
+        	}
+        }
+        if (host.length() == 0) {
+        	throw new SipUriSyntaxException("host cannot be empty");
+        }
+    	if (colonPos > -1) {
+    		if (colonPos == hostport.length() - 1) {
                 throw new SipUriSyntaxException("hostport cannot terminate with a ':'");
-            }
+    		}
             port = Integer.parseInt(hostport.substring(colonPos + 1));
-        } else {
-            colonPos = hostport.length();
+    	} else {
+            // Attempt SRV resolution if ":port" is not present in the URI
+        	try {
+        		Record [] records = new Lookup ("_sip._udp." + host, Type.SRV).run ();
+    			int minpri = 65538;
+    			int priwgt = 0;
+        		if (records != null) {
+	        		for (int i = 0; i < records.length; i++) {
+	        			SRVRecord srv = (SRVRecord) records [i];
+	        			int curpri = srv.getPriority ();
+	        			if (curpri < minpri) {
+	        				minpri = curpri;
+	        				priwgt = 0;
+	        			}
+	        			if (curpri == minpri) {
+	        				priwgt += srv.getWeight () + 1; 
+	        			}
+	        		}
+	        		if (priwgt > 0) {
+	        			int wgtsel = rng.nextInt (priwgt);
+	        			int i = 0;
+	        			SRVRecord srv = null;
+	        			while (wgtsel >= 0) {
+	        				srv = (SRVRecord) records [i++];
+	        				wgtsel -= srv.getWeight () + 1;
+	        			}
+						// Overwrite host and port with one SRV-entry
+						host = srv.getTarget ().toString ();
+						port = srv.getPort ();
+						// SIP Peers is currently designed to handle a single host:port and a single IP:port
+	        		}
+        		}
+        	} catch (TextParseException tpe) {
+        		throw new SipUriSyntaxException("hostname did not parse according to DNS");
+        	}
         }
-        host = hostport.substring(0, colonPos);
         if (buf.length() == 1) {
             //if there is only one ';' at the end of the uri => do not
             //parse uri-parameters and headers
Index: pom.xml
===================================================================
--- pom.xml	(revision 200)
+++ pom.xml	(working copy)
@@ -12,12 +12,26 @@
   </properties>
 
   <dependencies>
+
     <dependency>
       <groupId>org.testng</groupId>
       <artifactId>testng</artifactId>
       <version>6.1.1</version>
       <scope>test</scope>
     </dependency>
+
+    <dependency>
+      <groupId>dnsjava</groupId>
+      <artifactId>dnsjava</artifactId>
+      <version>2.1.1</version>
+    </dependency>
+
+    <dependency>
+      <groupId>socket6bed4</groupId>
+      <artifactId>nl.openfortress.socket6bed4</artifactId>
+      <version>0.2.1</version>
+    </dependency>
+
   </dependencies>
 
   <build>
@@ -33,6 +47,16 @@
         </configuration>
       </plugin>
 
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>2.3.2</version>
+        <configuration>
+          <source>1.6</source>
+          <target>1.6</target>
+        </configuration>
+      </plugin>
+
     </plugins>
   </build>
 
