From 9329c4ede58fbe370574f3a3419ebb2e0efe349a Mon Sep 17 00:00:00 2001
From: jpbl <jpbl>
Date: Thu, 10 Nov 2005 21:40:30 +0000
Subject: [PATCH] reintegrated exosip2

---
 INSTALL                        |    1 -
 Makefile.am                    |    5 +-
 config.guess                   |  158 +--
 config.h.in                    |   50 +-
 config.sub                     |  139 +-
 configure.ac                   |   31 +-
 deps/Makefile.am               |    2 +-
 exosip2/Makefile.am            |   33 +
 exosip2/eXcall_api.c           | 1563 ++++++++++++++++++++++
 exosip2/eXconf.c               |  803 +++++++++++
 exosip2/eXinsubscription_api.c |  567 ++++++++
 exosip2/eXmessage_api.c        |  196 +++
 exosip2/eXoptions_api.c        |  200 +++
 exosip2/eXosip.c               |  760 +++++++++++
 exosip2/eXosip2.h              |  533 ++++++++
 exosip2/eXpublish_api.c        |  168 +++
 exosip2/eXrefer_api.c          |   74 +
 exosip2/eXregister_api.c       |  376 ++++++
 exosip2/eXsubscription_api.c   |  372 +++++
 exosip2/eXtransport.c          |  279 ++++
 exosip2/eXutils.c              |  694 ++++++++++
 exosip2/inet_ntop.c            |  217 +++
 exosip2/inet_ntop.h            |   21 +
 exosip2/jauth.c                |  489 +++++++
 exosip2/jcall.c                |  119 ++
 exosip2/jcallback.c            | 2053 ++++++++++++++++++++++++++++
 exosip2/jdialog.c              |  217 +++
 exosip2/jevents.c              |  511 +++++++
 exosip2/jnotify.c              |  202 +++
 exosip2/jpipe.c                |  230 ++++
 exosip2/jpipe.h                |  109 ++
 exosip2/jpublish.c             |  122 ++
 exosip2/jreg.c                 |  104 ++
 exosip2/jrequest.c             |  999 ++++++++++++++
 exosip2/jresponse.c            |  736 ++++++++++
 exosip2/jsubscribe.c           |  150 +++
 exosip2/misc.c                 |  239 ++++
 exosip2/sdp_offans.c           |  204 +++
 exosip2/udp.c                  | 2307 ++++++++++++++++++++++++++++++++
 include/Makefile.am            |    3 +
 include/eXosip2/Makefile.am    |    6 +
 include/eXosip2/eX_call.h      |  231 ++++
 include/eXosip2/eX_message.h   |  108 ++
 include/eXosip2/eX_options.h   |  100 ++
 include/eXosip2/eX_publish.h   |   92 ++
 include/eXosip2/eX_refer.h     |   84 ++
 include/eXosip2/eX_register.h  |   96 ++
 include/eXosip2/eX_setup.h     |  258 ++++
 include/eXosip2/eX_subscribe.h |  189 +++
 include/eXosip2/eXosip.h       |  301 +++++
 ltmain.sh                      |  594 ++++----
 m4/Makefile.am                 |    1 +
 m4/acx_pthread.m4              |  224 ++++
 m4/exosip.m4                   |   88 ++
 m4/ilbc.m4                     |   33 +
 m4/osip.m4                     |   32 +
 m4/speex.m4                    |   24 +
 m4/video.m4                    |   85 ++
 src/Makefile.am                |    4 +-
 src/audio/Makefile.am          |    2 +-
 60 files changed, 18089 insertions(+), 499 deletions(-)
 create mode 100644 exosip2/Makefile.am
 create mode 100644 exosip2/eXcall_api.c
 create mode 100644 exosip2/eXconf.c
 create mode 100644 exosip2/eXinsubscription_api.c
 create mode 100644 exosip2/eXmessage_api.c
 create mode 100644 exosip2/eXoptions_api.c
 create mode 100644 exosip2/eXosip.c
 create mode 100644 exosip2/eXosip2.h
 create mode 100644 exosip2/eXpublish_api.c
 create mode 100644 exosip2/eXrefer_api.c
 create mode 100644 exosip2/eXregister_api.c
 create mode 100644 exosip2/eXsubscription_api.c
 create mode 100644 exosip2/eXtransport.c
 create mode 100644 exosip2/eXutils.c
 create mode 100644 exosip2/inet_ntop.c
 create mode 100644 exosip2/inet_ntop.h
 create mode 100644 exosip2/jauth.c
 create mode 100644 exosip2/jcall.c
 create mode 100644 exosip2/jcallback.c
 create mode 100644 exosip2/jdialog.c
 create mode 100644 exosip2/jevents.c
 create mode 100644 exosip2/jnotify.c
 create mode 100644 exosip2/jpipe.c
 create mode 100644 exosip2/jpipe.h
 create mode 100644 exosip2/jpublish.c
 create mode 100644 exosip2/jreg.c
 create mode 100644 exosip2/jrequest.c
 create mode 100644 exosip2/jresponse.c
 create mode 100644 exosip2/jsubscribe.c
 create mode 100644 exosip2/misc.c
 create mode 100644 exosip2/sdp_offans.c
 create mode 100644 exosip2/udp.c
 create mode 100644 include/Makefile.am
 create mode 100644 include/eXosip2/Makefile.am
 create mode 100644 include/eXosip2/eX_call.h
 create mode 100644 include/eXosip2/eX_message.h
 create mode 100644 include/eXosip2/eX_options.h
 create mode 100644 include/eXosip2/eX_publish.h
 create mode 100644 include/eXosip2/eX_refer.h
 create mode 100644 include/eXosip2/eX_register.h
 create mode 100644 include/eXosip2/eX_setup.h
 create mode 100644 include/eXosip2/eX_subscribe.h
 create mode 100644 include/eXosip2/eXosip.h
 create mode 100644 m4/Makefile.am
 create mode 100644 m4/acx_pthread.m4
 create mode 100644 m4/exosip.m4
 create mode 100644 m4/ilbc.m4
 create mode 100644 m4/osip.m4
 create mode 100644 m4/speex.m4
 create mode 100644 m4/video.m4

diff --git a/INSTALL b/INSTALL
index c493b7b3cc..56b077d6a0 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,7 +1,6 @@
 Installation Instructions
 *************************
 
-
 Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free
 Software Foundation, Inc.
 
diff --git a/Makefile.am b/Makefile.am
index 58dc0abfaf..698adb4bd0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,2 +1,5 @@
-SUBDIRS = utilspp stund src ringtones 
+SUBDIRS = exosip2 utilspp stund src ringtones m4 
 EXTRA_DIST = tools/*.sh
+
+ACLOCAL_FLAGS=-I$(top_srcdir)/m4
+
diff --git a/config.guess b/config.guess
index 45bee13987..2fc3acce2e 100755
--- a/config.guess
+++ b/config.guess
@@ -1,9 +1,9 @@
 #! /bin/sh
 # Attempt to guess a canonical system name.
 #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+#   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
-timestamp='2005-04-22'
+timestamp='2003-06-17'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -53,7 +53,7 @@ version="\
 GNU config.guess ($timestamp)
 
 Originally written by Per Bothner.
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
@@ -136,6 +136,13 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
 UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
 UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
 
+## for Red Hat Linux
+if test -f /etc/redhat-release ; then
+    VENDOR=redhat ;
+else
+    VENDOR= ;
+fi
+
 # Note: order is significant - the case branches are not exclusive.
 
 case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
@@ -197,21 +204,15 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
 	echo "${machine}-${os}${release}"
 	exit 0 ;;
-    amd64:OpenBSD:*:*)
-	echo x86_64-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
     amiga:OpenBSD:*:*)
 	echo m68k-unknown-openbsd${UNAME_RELEASE}
 	exit 0 ;;
-    cats:OpenBSD:*:*)
-	echo arm-unknown-openbsd${UNAME_RELEASE}
+    arc:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
 	exit 0 ;;
     hp300:OpenBSD:*:*)
 	echo m68k-unknown-openbsd${UNAME_RELEASE}
 	exit 0 ;;
-    luna88k:OpenBSD:*:*)
-    	echo m88k-unknown-openbsd${UNAME_RELEASE}
-	exit 0 ;;
     mac68k:OpenBSD:*:*)
 	echo m68k-unknown-openbsd${UNAME_RELEASE}
 	exit 0 ;;
@@ -227,33 +228,25 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     mvmeppc:OpenBSD:*:*)
 	echo powerpc-unknown-openbsd${UNAME_RELEASE}
 	exit 0 ;;
+    pmax:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
     sgi:OpenBSD:*:*)
-	echo mips64-unknown-openbsd${UNAME_RELEASE}
+	echo mipseb-unknown-openbsd${UNAME_RELEASE}
 	exit 0 ;;
     sun3:OpenBSD:*:*)
 	echo m68k-unknown-openbsd${UNAME_RELEASE}
 	exit 0 ;;
+    wgrisc:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
     *:OpenBSD:*:*)
 	echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
 	exit 0 ;;
-    *:ekkoBSD:*:*)
-	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
-	exit 0 ;;
-    macppc:MirBSD:*:*)
-	echo powerppc-unknown-mirbsd${UNAME_RELEASE}
-	exit 0 ;;
-    *:MirBSD:*:*)
-	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
-	exit 0 ;;
     alpha:OSF1:*:*)
-	case $UNAME_RELEASE in
-	*4.0)
+	if test $UNAME_RELEASE = "V4.0"; then
 		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
-		;;
-	*5.*)
-	        UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
-		;;
-	esac
+	fi
 	# According to Compaq, /usr/sbin/psrinfo has been available on
 	# OSF/1 and Tru64 systems produced since 1995.  I hope that
 	# covers most systems running today.  This code pipes the CPU
@@ -291,12 +284,14 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 	    "EV7.9 (21364A)")
 		UNAME_MACHINE="alphaev79" ;;
 	esac
-	# A Pn.n version is a patched version.
 	# A Vn.n version is a released version.
 	# A Tn.n version is a released field test version.
 	# A Xn.n version is an unreleased experimental baselevel.
 	# 1.2 uses "1.2" for uname -r.
-	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	exit 0 ;;
+    Alpha*:OpenVMS:*:*)
+	echo alpha-hp-vms
 	exit 0 ;;
     Alpha\ *:Windows_NT*:*)
 	# How do we know it's Interix rather than the generic POSIX subsystem?
@@ -319,12 +314,6 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     *:OS/390:*:*)
 	echo i370-ibm-openedition
 	exit 0 ;;
-    *:z/VM:*:*)
-	echo s390-ibm-zvmoe
-	exit 0 ;;
-    *:OS400:*:*)
-        echo powerpc-ibm-os400
-	exit 0 ;;
     arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
 	echo arm-acorn-riscix${UNAME_RELEASE}
 	exit 0;;
@@ -345,7 +334,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     DRS?6000:unix:4.0:6*)
 	echo sparc-icl-nx6
 	exit 0 ;;
-    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+    DRS?6000:UNIX_SV:4.2*:7*)
 	case `/usr/bin/uname -p` in
 	    sparc) echo sparc-icl-nx7 && exit 0 ;;
 	esac ;;
@@ -417,9 +406,6 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
         echo m68k-unknown-mint${UNAME_RELEASE}
         exit 0 ;;
-    m68k:machten:*:*)
-	echo m68k-apple-machten${UNAME_RELEASE}
-	exit 0 ;;
     powerpc:machten:*:*)
 	echo powerpc-apple-machten${UNAME_RELEASE}
 	exit 0 ;;
@@ -755,7 +741,7 @@ EOF
 	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
 	exit 0 ;;
     *:UNICOS/mp:*:*)
-	echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' 
 	exit 0 ;;
     F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
 	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
@@ -763,11 +749,6 @@ EOF
         FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
         echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
         exit 0 ;;
-    5000:UNIX_System_V:4.*:*)
-        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
-        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
-        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
-	exit 0 ;;
     i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
 	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
 	exit 0 ;;
@@ -777,8 +758,19 @@ EOF
     *:BSD/OS:*:*)
 	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
 	exit 0 ;;
-    *:FreeBSD:*:*)
-	echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+    *:FreeBSD:*:*|*:GNU/FreeBSD:*:*)
+	# Determine whether the default compiler uses glibc.
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <features.h>
+	#if __GLIBC__ >= 2
+	LIBC=gnu
+	#else
+	LIBC=
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+	echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
 	exit 0 ;;
     i*:CYGWIN*:*)
 	echo ${UNAME_MACHINE}-pc-cygwin
@@ -804,9 +796,6 @@ EOF
     i*:UWIN*:*)
 	echo ${UNAME_MACHINE}-pc-uwin
 	exit 0 ;;
-    amd64:CYGWIN*:*:*)
-	echo x86_64-unknown-cygwin
-	exit 0 ;;
     p*:CYGWIN*:*)
 	echo powerpcle-unknown-cygwin
 	exit 0 ;;
@@ -814,13 +803,8 @@ EOF
 	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
 	exit 0 ;;
     *:GNU:*:*)
-	# the GNU system
 	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
 	exit 0 ;;
-    *:GNU/*:*:*)
-	# other systems with GNU libc and userland
-	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
-	exit 0 ;;
     i*86:Minix:*:*)
 	echo ${UNAME_MACHINE}-pc-minix
 	exit 0 ;;
@@ -830,17 +814,8 @@ EOF
     cris:Linux:*:*)
 	echo cris-axis-linux-gnu
 	exit 0 ;;
-    crisv32:Linux:*:*)
-	echo crisv32-axis-linux-gnu
-	exit 0 ;;
-    frv:Linux:*:*)
-    	echo frv-unknown-linux-gnu
-	exit 0 ;;
     ia64:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
-	exit 0 ;;
-    m32r*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-${VENDOR:-unknown}-linux-gnu
 	exit 0 ;;
     m68*:Linux:*:*)
 	echo ${UNAME_MACHINE}-unknown-linux-gnu
@@ -884,10 +859,10 @@ EOF
 	test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
 	;;
     ppc:Linux:*:*)
-	echo powerpc-unknown-linux-gnu
+	echo powerpc-${VENDOR:-unknown}-linux-gnu
 	exit 0 ;;
     ppc64:Linux:*:*)
-	echo powerpc64-unknown-linux-gnu
+	echo powerpc64-${VENDOR:-unknown}-linux-gnu
 	exit 0 ;;
     alpha:Linux:*:*)
 	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
@@ -915,7 +890,7 @@ EOF
 	echo hppa64-unknown-linux-gnu
 	exit 0 ;;
     s390:Linux:*:* | s390x:Linux:*:*)
-	echo ${UNAME_MACHINE}-ibm-linux
+	echo ${UNAME_MACHINE}-${VENDOR:-ibm}-linux-gnu
 	exit 0 ;;
     sh64*:Linux:*:*)
     	echo ${UNAME_MACHINE}-unknown-linux-gnu
@@ -927,7 +902,7 @@ EOF
 	echo ${UNAME_MACHINE}-unknown-linux-gnu
 	exit 0 ;;
     x86_64:Linux:*:*)
-	echo x86_64-unknown-linux-gnu
+	echo x86_64-${VENDOR:-unknown}-linux-gnu
 	exit 0 ;;
     i*86:Linux:*:*)
 	# The BFD linker knows what the default object file format is, so
@@ -977,12 +952,9 @@ EOF
 	LIBC=gnuaout
 	#endif
 	#endif
-	#ifdef __dietlibc__
-	LIBC=dietlibc
-	#endif
 EOF
 	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
-	test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
+	test x"${LIBC}" != x && echo "${UNAME_MACHINE}-${VENDOR:-pc}-linux-${LIBC}" && exit 0
 	test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
 	;;
     i*86:DYNIX/ptx:4*:*)
@@ -1010,9 +982,6 @@ EOF
     i*86:atheos:*:*)
 	echo ${UNAME_MACHINE}-unknown-atheos
 	exit 0 ;;
-	i*86:syllable:*:*)
-	echo ${UNAME_MACHINE}-pc-syllable
-	exit 0 ;;
     i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
 	echo i386-unknown-lynxos${UNAME_RELEASE}
 	exit 0 ;;
@@ -1082,9 +1051,9 @@ EOF
     M680?0:D-NIX:5.3:*)
 	echo m68k-diab-dnix
 	exit 0 ;;
-    M68*:*:R3V[5678]*:*)
+    M68*:*:R3V[567]*:*)
 	test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
-    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+    3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0)
 	OS_REL=''
 	test -r /etc/.relid \
 	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
@@ -1140,10 +1109,6 @@ EOF
 	# From seanf@swdc.stratus.com.
 	echo i860-stratus-sysv4
 	exit 0 ;;
-    i*86:VOS:*:*)
-	# From Paul.Green@stratus.com.
-	echo ${UNAME_MACHINE}-stratus-vos
-	exit 0 ;;
     *:VOS:*:*)
 	# From Paul.Green@stratus.com.
 	echo hppa1.1-stratus-vos
@@ -1186,10 +1151,9 @@ EOF
 	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
 	exit 0 ;;
     *:Darwin:*:*)
-	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
-	case $UNAME_PROCESSOR in
+	case `uname -p` in
 	    *86) UNAME_PROCESSOR=i686 ;;
-	    unknown) UNAME_PROCESSOR=powerpc ;;
+	    powerpc) UNAME_PROCESSOR=powerpc ;;
 	esac
 	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
 	exit 0 ;;
@@ -1204,10 +1168,7 @@ EOF
     *:QNX:*:4*)
 	echo i386-pc-qnx
 	exit 0 ;;
-    NSE-?:NONSTOP_KERNEL:*:*)
-	echo nse-tandem-nsk${UNAME_RELEASE}
-	exit 0 ;;
-    NSR-?:NONSTOP_KERNEL:*:*)
+    NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*)
 	echo nsr-tandem-nsk${UNAME_RELEASE}
 	exit 0 ;;
     *:NonStop-UX:*:*)
@@ -1251,19 +1212,6 @@ EOF
     SEI:*:*:SEIUX)
         echo mips-sei-seiux${UNAME_RELEASE}
 	exit 0 ;;
-    *:DragonFly:*:*)
-	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
-	exit 0 ;;
-    *:*VMS:*:*)
-    	UNAME_MACHINE=`(uname -p) 2>/dev/null`
-	case "${UNAME_MACHINE}" in
-	    A*) echo alpha-dec-vms && exit 0 ;;
-	    I*) echo ia64-dec-vms && exit 0 ;;
-	    V*) echo vax-dec-vms && exit 0 ;;
-	esac ;;
-    *:XENIX:*:SysV)
-	echo i386-pc-xenix
-	exit 0 ;;
 esac
 
 #echo '(No uname command or uname output not recognized.)' 1>&2
@@ -1423,9 +1371,7 @@ This script, last modified $timestamp, has failed to recognize
 the operating system you are using. It is advised that you
 download the most up to date version of the config scripts from
 
-  http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
-and
-  http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
+    ftp://ftp.gnu.org/pub/gnu/config/
 
 If the version you run ($0) is already up to date, please
 send the following data and any information you think might be
diff --git a/config.h.in b/config.h.in
index 0962968911..8af0e48264 100644
--- a/config.h.in
+++ b/config.h.in
@@ -1,17 +1,29 @@
 /* config.h.in.  Generated from configure.ac by autoheader.  */
 
+/* Define to 1 if you have the <assert.h> header file. */
+#undef HAVE_ASSERT_H
+
+/* Define to 1 if you have the <ctype.h> header file. */
+#undef HAVE_CTYPE_H
+
 /* Define to 1 if you have the <dlfcn.h> header file. */
 #undef HAVE_DLFCN_H
 
 /* Define if dns-sd is available */
 #undef HAVE_DNSSD
 
-/* Define to 1 if you have the <eXosip2/eXosip.h> header file. */
-#undef HAVE_EXOSIP2_EXOSIP_H
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
 
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
+/* Define to 1 if you have the `osipparser2' library (-losipparser2). */
+#undef HAVE_LIBOSIPPARSER2
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#undef HAVE_MALLOC_H
+
 /* Define to 1 if you have the <memory.h> header file. */
 #undef HAVE_MEMORY_H
 
@@ -21,9 +33,24 @@
 /* Define to 1 if you have the <portaudio.h> header file. */
 #undef HAVE_PORTAUDIO_H
 
+/* Define if you have POSIX threads libraries and header files. */
+#undef HAVE_PTHREAD
+
+/* Define to 1 if you have the <semaphore.h> header file. */
+#undef HAVE_SEMAPHORE_H
+
+/* Define to 1 if you have the <signal.h> header file. */
+#undef HAVE_SIGNAL_H
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#undef HAVE_STDARG_H
+
 /* Define to 1 if you have the <stdint.h> header file. */
 #undef HAVE_STDINT_H
 
+/* Define to 1 if you have the <stdio.h> header file. */
+#undef HAVE_STDIO_H
+
 /* Define to 1 if you have the <stdlib.h> header file. */
 #undef HAVE_STDLIB_H
 
@@ -33,15 +60,30 @@
 /* Define to 1 if you have the <string.h> header file. */
 #undef HAVE_STRING_H
 
+/* Define to 1 if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define to 1 if you have the <sys/sem.h> header file. */
+#undef HAVE_SYS_SEM_H
+
+/* Define to 1 if you have the <sys/signal.h> header file. */
+#undef HAVE_SYS_SIGNAL_H
+
 /* Define to 1 if you have the <sys/stat.h> header file. */
 #undef HAVE_SYS_STAT_H
 
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
 /* Define to 1 if you have the <sys/types.h> header file. */
 #undef HAVE_SYS_TYPES_H
 
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
+/* Define to 1 if you have the <varargs.h> header file. */
+#undef HAVE_VARARGS_H
+
 /* Name of package */
 #undef PACKAGE
 
@@ -60,6 +102,10 @@
 /* Define to the version of this package. */
 #undef PACKAGE_VERSION
 
+/* Define to the necessary symbol if this constant uses a non-standard name on
+   your system. */
+#undef PTHREAD_CREATE_JOINABLE
+
 /* Define to 1 if you have the ANSI C header files. */
 #undef STDC_HEADERS
 
diff --git a/config.sub b/config.sub
index 87a1ee49e6..6b2ff9f6a7 100755
--- a/config.sub
+++ b/config.sub
@@ -1,9 +1,9 @@
 #! /bin/sh
 # Configuration validation subroutine script.
 #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+#   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
-timestamp='2005-04-22'
+timestamp='2003-06-18'
 
 # This file is (in principle) common to ALL GNU software.
 # The presence of a machine in this file suggests that SOME GNU software
@@ -70,7 +70,7 @@ Report bugs and patches to <config-patches@gnu.org>."
 version="\
 GNU config.sub ($timestamp)
 
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
@@ -118,8 +118,7 @@ esac
 # Here we must recognize all the valid KERNEL-OS combinations.
 maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
 case $maybe_os in
-  nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
-  kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
+  nto-qnx* | linux-gnu* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
     os=-$maybe_os
     basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
     ;;
@@ -145,7 +144,7 @@ case $os in
 	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
 	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
 	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-	-apple | -axis | -knuth | -cray)
+	-apple | -axis)
 		os=
 		basic_machine=$1
 		;;
@@ -229,16 +228,14 @@ case $basic_machine in
 	| a29k \
 	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
 	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
-	| am33_2.0 \
 	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
-	| bfin \
 	| c4x | clipper \
 	| d10v | d30v | dlx | dsp16xx \
 	| fr30 | frv \
 	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
 	| i370 | i860 | i960 | ia64 \
-	| ip2k | iq2000 \
-	| m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \
+	| ip2k \
+	| m32r | m68000 | m68k | m88k | mcore \
 	| mips | mipsbe | mipseb | mipsel | mipsle \
 	| mips16 \
 	| mips64 | mips64el \
@@ -250,7 +247,6 @@ case $basic_machine in
 	| mipsisa32 | mipsisa32el \
 	| mipsisa32r2 | mipsisa32r2el \
 	| mipsisa64 | mipsisa64el \
-	| mipsisa64r2 | mipsisa64r2el \
 	| mipsisa64sb1 | mipsisa64sb1el \
 	| mipsisa64sr71k | mipsisa64sr71kel \
 	| mipstx39 | mipstx39el \
@@ -261,15 +257,15 @@ case $basic_machine in
 	| pdp10 | pdp11 | pj | pjl \
 	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
 	| pyramid \
+	| s390 | s390x \
 	| sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
 	| sh64 | sh64le \
-	| sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \
-	| sparcv8 | sparcv9 | sparcv9b \
+	| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv8 | sparcv9 | sparcv9b \
 	| strongarm \
 	| tahoe | thumb | tic4x | tic80 | tron \
 	| v850 | v850e \
 	| we32k \
-	| x86 | xscale | xscalee[bl] | xstormy16 | xtensa \
+	| x86 | xscale | xstormy16 | xtensa \
 	| z8k)
 		basic_machine=$basic_machine-unknown
 		;;
@@ -300,19 +296,19 @@ case $basic_machine in
 	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
 	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
 	| avr-* \
-	| bfin-* | bs2000-* \
+	| bs2000-* \
 	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
-	| clipper-* | craynv-* | cydra-* \
+	| clipper-* | cydra-* \
 	| d10v-* | d30v-* | dlx-* \
 	| elxsi-* \
 	| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
 	| h8300-* | h8500-* \
 	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
 	| i*86-* | i860-* | i960-* | ia64-* \
-	| ip2k-* | iq2000-* \
-	| m32r-* | m32rle-* \
+	| ip2k-* \
+	| m32r-* \
 	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
-	| m88110-* | m88k-* | maxq-* | mcore-* \
+	| m88110-* | m88k-* | mcore-* \
 	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
 	| mips16-* \
 	| mips64-* | mips64el-* \
@@ -324,30 +320,28 @@ case $basic_machine in
 	| mipsisa32-* | mipsisa32el-* \
 	| mipsisa32r2-* | mipsisa32r2el-* \
 	| mipsisa64-* | mipsisa64el-* \
-	| mipsisa64r2-* | mipsisa64r2el-* \
 	| mipsisa64sb1-* | mipsisa64sb1el-* \
 	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
 	| mipstx39-* | mipstx39el-* \
-	| mmix-* \
 	| msp430-* \
-	| none-* | np1-* | ns16k-* | ns32k-* \
+	| none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
 	| orion-* \
 	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
 	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
 	| pyramid-* \
 	| romp-* | rs6000-* \
+	| s390-* | s390x-* \
 	| sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
 	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
-	| sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \
-	| sparclite-* \
+	| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
 	| sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
 	| tahoe-* | thumb-* \
 	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
 	| tron-* \
 	| v850-* | v850e-* | vax-* \
 	| we32k-* \
-	| x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \
-	| xstormy16-* | xtensa-* \
+	| x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
+	| xtensa-* \
 	| ymp-* \
 	| z8k-*)
 		;;
@@ -367,9 +361,6 @@ case $basic_machine in
 		basic_machine=a29k-amd
 		os=-udi
 		;;
-    	abacus)
-		basic_machine=abacus-unknown
-		;;
 	adobe68k)
 		basic_machine=m68010-adobe
 		os=-scout
@@ -387,9 +378,6 @@ case $basic_machine in
 	amd64)
 		basic_machine=x86_64-pc
 		;;
-	amd64-*)
-		basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
-		;;
 	amdahl)
 		basic_machine=580-amdahl
 		os=-sysv
@@ -449,27 +437,12 @@ case $basic_machine in
 		basic_machine=j90-cray
 		os=-unicos
 		;;
-	craynv)
-		basic_machine=craynv-cray
-		os=-unicosmp
-		;;
-	cr16c)
-		basic_machine=cr16c-unknown
-		os=-elf
-		;;
 	crds | unos)
 		basic_machine=m68k-crds
 		;;
-	crisv32 | crisv32-* | etraxfs*)
-		basic_machine=crisv32-axis
-		;;
 	cris | cris-* | etrax*)
 		basic_machine=cris-axis
 		;;
-	crx)
-		basic_machine=crx-unknown
-		os=-elf
-		;;
 	da30 | da30-*)
 		basic_machine=m68k-da30
 		;;
@@ -492,10 +465,6 @@ case $basic_machine in
 		basic_machine=m88k-motorola
 		os=-sysv3
 		;;
-	djgpp)
-		basic_machine=i586-pc
-		os=-msdosdjgpp
-		;;
 	dpx20 | dpx20-*)
 		basic_machine=rs6000-bull
 		os=-bosx
@@ -674,6 +643,10 @@ case $basic_machine in
 	mips3*)
 		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
 		;;
+	mmix*)
+		basic_machine=mmix-knuth
+		os=-mmixware
+		;;
 	monitor)
 		basic_machine=m68k-rom68k
 		os=-coff
@@ -754,6 +727,10 @@ case $basic_machine in
 	np1)
 		basic_machine=np1-gould
 		;;
+	nv1)
+		basic_machine=nv1-cray
+		os=-unicosmp
+		;;
 	nsr-tandem)
 		basic_machine=nsr-tandem
 		;;
@@ -765,10 +742,6 @@ case $basic_machine in
 		basic_machine=or32-unknown
 		os=-coff
 		;;
-	os400)
-		basic_machine=powerpc-ibm
-		os=-os400
-		;;
 	OSE68000 | ose68000)
 		basic_machine=m68000-ericsson
 		os=-ose
@@ -860,12 +833,6 @@ case $basic_machine in
 	rtpc | rtpc-*)
 		basic_machine=romp-ibm
 		;;
-	s390 | s390-*)
-		basic_machine=s390-ibm
-		;;
-	s390x | s390x-*)
-		basic_machine=s390x-ibm
-		;;
 	sa29200)
 		basic_machine=a29k-amd
 		os=-udi
@@ -989,10 +956,6 @@ case $basic_machine in
 	tower | tower-32)
 		basic_machine=m68k-ncr
 		;;
-	tpf)
-		basic_machine=s390x-ibm
-		os=-tpf
-		;;
 	udi29k)
 		basic_machine=a29k-amd
 		os=-udi
@@ -1036,10 +999,6 @@ case $basic_machine in
 		basic_machine=hppa1.1-winbond
 		os=-proelf
 		;;
-	xbox)
-		basic_machine=i686-pc
-		os=-mingw32
-		;;
 	xps | xps100)
 		basic_machine=xps100-honeywell
 		;;
@@ -1070,9 +1029,6 @@ case $basic_machine in
 	romp)
 		basic_machine=romp-ibm
 		;;
-	mmix)
-		basic_machine=mmix-knuth
-		;;
 	rs6000)
 		basic_machine=rs6000-ibm
 		;;
@@ -1168,20 +1124,19 @@ case $os in
 	      | -aos* \
 	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
 	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
-	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
-	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
-	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+	      | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+	      | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
 	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
 	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
 	      | -chorusos* | -chorusrdb* \
 	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
-	      | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
 	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
 	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
 	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
 	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
 	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
-	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly*)
+	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei*)
 	# Remember, each alternative MUST END IN *, to match a version number.
 		;;
 	-qnx*)
@@ -1205,9 +1160,6 @@ case $os in
 	-mac*)
 		os=`echo $os | sed -e 's|mac|macos|'`
 		;;
-	-linux-dietlibc)
-		os=-linux-dietlibc
-		;;
 	-linux*)
 		os=`echo $os | sed -e 's|linux|linux-gnu|'`
 		;;
@@ -1220,9 +1172,6 @@ case $os in
 	-opened*)
 		os=-openedition
 		;;
-        -os400*)
-		os=-os400
-		;;
 	-wince*)
 		os=-wince
 		;;
@@ -1244,9 +1193,6 @@ case $os in
 	-atheos*)
 		os=-atheos
 		;;
-	-syllable*)
-		os=-syllable
-		;;
 	-386bsd)
 		os=-bsd
 		;;
@@ -1269,9 +1215,6 @@ case $os in
 	-sinix*)
 		os=-sysv4
 		;;
-        -tpf*)
-		os=-tpf
-		;;
 	-triton*)
 		os=-sysv3
 		;;
@@ -1308,9 +1251,6 @@ case $os in
 	-kaos*)
 		os=-kaos
 		;;
-	-zvmoe)
-		os=-zvmoe
-		;;
 	-none)
 		;;
 	*)
@@ -1342,9 +1282,9 @@ case $basic_machine in
 	arm*-semi)
 		os=-aout
 		;;
-    c4x-* | tic4x-*)
-        os=-coff
-        ;;
+	c4x-* | tic4x-*)
+		os=-coff
+		;;
 	# This must come before the *-dec entry.
 	pdp10-*)
 		os=-tops20
@@ -1391,9 +1331,6 @@ case $basic_machine in
 	*-ibm)
 		os=-aix
 		;;
-    	*-knuth)
-		os=-mmixware
-		;;
 	*-wec)
 		os=-proelf
 		;;
@@ -1526,15 +1463,9 @@ case $basic_machine in
 			-mvs* | -opened*)
 				vendor=ibm
 				;;
-			-os400*)
-				vendor=ibm
-				;;
 			-ptx*)
 				vendor=sequent
 				;;
-			-tpf*)
-				vendor=ibm
-				;;
 			-vxsim* | -vxworks* | -windiss*)
 				vendor=wrs
 				;;
diff --git a/configure.ac b/configure.ac
index 3ec02f6e80..4a09a029a4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT(acinclude.m4)
+AC_INIT(aclocal.m4)
 
 AM_CONFIG_HEADER(config.h)
 
@@ -31,9 +31,8 @@ dnl KDE_USE_QT(3.3)
 AC_CANONICAL_SYSTEM
 AC_ARG_PROGRAM
 AM_INIT_AUTOMAKE(sflphoned, $VERSION)
-AM_DISABLE_LIBRARIES
 AC_PROG_LIBTOOL
-AC_CHECK_COMPILERS
+dnl AC_CHECK_COMPILERS
 
 CXXFLAGS="$CXXFLAGS $USE_EXCEPTIONS"
 
@@ -54,7 +53,6 @@ dnl Checks for header files.
 AC_HEADER_STDC
 AC_CHECK_HEADERS( \
 ostream \
-eXosip2/eXosip.h \
 portaudio.h \
 )
 
@@ -73,22 +71,17 @@ PKG_CHECK_MODULES(libccrtp1, libccrtp1 >= ${LIBCCRT_MIN_VERSION})
 SFLPHONE_CXXFLAGS="$SFLPHONE_CXXFLAGS $libccrtp1_CFLAGS"
 SFLPHONE_LIBS="$SFLPHONE_LIBS $libccrtp1_LIBS"
 
-dnl 2.2.0 is buggy, header corruption
-LIBOSIP2_MIN_VERSION=2.2.1
-PKG_CHECK_MODULES(libosip2, libosip2 >= ${LIBOSIP2_MIN_VERSION})
-SFLPHONE_CXXFLAGS="$SFLPHONE_CXXFLAGS $libosip2_CFLAGS"
-SFLPHONE_LIBS="$SFLPHONE_LIBS $libosip2_LIBS"
+dnl check for osip2
+LP_CHECK_OSIP2
 
-if test $ac_cv_header_eXosip2_eXosip_h = no; then
-   AC_MSG_ERROR([*** missing eXosip2/eXosip.h. You need a working eXosip2 installation. See http://www.antisip.com/download/])
-fi
-
-AC_CHECK_LIB([eXosip2], [eXosip_init],[libexosip2_LIBS="-leXosip2 "],[
-   AC_MSG_ERROR([*** missing eXosip2 library. You need a working eXosip2 installation. See http://www.antisip.com/download/])])
+dnl setup flags for embedded exosip library
+LP_SETUP_EXOSIP
 
-SFLPHONE_LIBS="$SFLPHONE_LIBS $libexosip2_LIBS"
+SFLPHONE_CXXFLAGS="$SFLPHONE_CXXFLAGS $OSIP_CFLAGS"
+SFLPHONE_LIBS="$SFLPHONE_LIBS $OSIP_LIBS"
+SFLPHONE_CXXFLAGS="$SFLPHONE_CXXFLAGS $EXOSIP_CFLAGS"
+SFLPHONE_LIBS="$SFLPHONE_LIBS $EXOSIP_LIBS"
 
-dnl AC_SUBST(LIBQT)
 
 if test $ac_cv_header_portaudio_h = no; then
    AC_MSG_ERROR([*** missing portaudio.h. You need a working PortAudio installation. See http://www.portaudio.com])
@@ -142,13 +135,13 @@ fi
 AC_SUBST(LIB_DNSSD)
 AM_CONDITIONAL(USE_ZEROCONF, test "$have_libdns_sd" = "yes")	
 
-AC_CONFIG_SUBDIRS(src/gui/qt)
-
 dnl AC_CONFIG_FILES(
 AC_OUTPUT(
 sflphone.spec \
 sflphoned-fedora.spec \
 Makefile \
+m4/Makefile \
+exosip2/Makefile \
 src/Makefile \
 src/sflphone \
 src/audio/Makefile \
diff --git a/deps/Makefile.am b/deps/Makefile.am
index b9b47071d6..e6e60a9522 100644
--- a/deps/Makefile.am
+++ b/deps/Makefile.am
@@ -10,5 +10,5 @@ if COMPILE_PORTAUDIO
 PORTAUDIO = portaudio
 endif
 
-SUBDIRS = $(OSIP) $(EXOSIP) $(PORTAUDIO)
+SUBDIRS = $(PORTAUDIO)
 
diff --git a/exosip2/Makefile.am b/exosip2/Makefile.am
new file mode 100644
index 0000000000..a3ef5a35dc
--- /dev/null
+++ b/exosip2/Makefile.am
@@ -0,0 +1,33 @@
+
+
+lib_LTLIBRARIES = libeXosip2.la
+
+#
+# Other flags to add someday:
+#	-Wcast-qual
+#	-Wwrite-strings
+#	-Wstrict-prototypes
+#	-Werror
+#
+AM_CFLAGS = @EXOSIP_CFLAGS@ @CFLAGS@  
+
+libeXosip2_la_SOURCES =      \
+eXosip.c         eXconf.c    \
+eXregister_api.c eXsubscription_api.c    \
+eXcall_api.c     eXoptions_api.c         \
+eXrefer_api.c    eXmessage_api.c         \
+eXinsubscription_api.c  eXpublish_api.c     \
+eXtransport.c    \
+inet_ntop.c      inet_ntop.h   \
+jrequest.c       jresponse.c   \
+jcallback.c      jdialog.c               udp.c        \
+jcall.c          jreg.c                  eXutils.c    \
+jnotify.c        jsubscribe.c            jevents.c    \
+misc.c           eXosip2.h     \
+jpipe.c          jpipe.h                 jauth.c      \
+sdp_offans.c     jpublish.c
+
+libeXosip2_la_LDFLAGS = -L$(prefix)/lib -version-info $(LIBEXOSIP_SO_VERSION)
+libeXosip2_la_LIBADD = -losip2  @EXOSIP_LIBS@ 
+
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(includedir)
diff --git a/exosip2/eXcall_api.c b/exosip2/eXcall_api.c
new file mode 100644
index 0000000000..76dc9a8fc7
--- /dev/null
+++ b/exosip2/eXcall_api.c
@@ -0,0 +1,1563 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002,2003,2004,2005  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+
+#include "eXosip2.h"
+
+extern eXosip_t eXosip;
+
+static int eXosip_create_transaction (eXosip_call_t * jc,
+                                      eXosip_dialog_t * jd,
+                                      osip_message_t * request);
+static int eXosip_create_cancel_transaction (eXosip_call_t * jc,
+                                             eXosip_dialog_t * jd,
+                                             osip_message_t * request);
+static int _eXosip_call_transaction_find (int tid, eXosip_call_t ** jc,
+                                          eXosip_dialog_t ** jd,
+                                          osip_transaction_t ** tr);
+
+static int
+eXosip_create_transaction (eXosip_call_t * jc,
+                           eXosip_dialog_t * jd, osip_message_t * request)
+{
+  osip_event_t *sipevent;
+  osip_transaction_t *tr;
+  int i;
+
+  i = osip_transaction_init (&tr, NICT, eXosip.j_osip, request);
+  if (i != 0)
+    {
+      /* TODO: release the j_call.. */
+
+      osip_message_free (request);
+      return -1;
+    }
+
+  if (jd != NULL)
+    osip_list_add (jd->d_out_trs, tr, 0);
+
+  sipevent = osip_new_outgoing_sipmessage (request);
+  sipevent->transactionid = tr->transactionid;
+
+  osip_transaction_set_your_instance (tr, __eXosip_new_jinfo (jc, jd, NULL, NULL));
+  osip_transaction_add_event (tr, sipevent);
+  __eXosip_wakeup ();
+  return 0;
+}
+
+static int
+eXosip_create_cancel_transaction (eXosip_call_t * jc,
+                                  eXosip_dialog_t * jd, osip_message_t * request)
+{
+  osip_event_t *sipevent;
+  osip_transaction_t *tr;
+  int i;
+
+  i = osip_transaction_init (&tr, NICT, eXosip.j_osip, request);
+  if (i != 0)
+    {
+      /* TODO: release the j_call.. */
+
+      osip_message_free (request);
+      return -2;
+    }
+
+  osip_list_add (eXosip.j_transactions, tr, 0);
+
+  sipevent = osip_new_outgoing_sipmessage (request);
+  sipevent->transactionid = tr->transactionid;
+
+  osip_transaction_add_event (tr, sipevent);
+  __eXosip_wakeup ();
+  return 0;
+}
+
+static int
+_eXosip_call_transaction_find (int tid, eXosip_call_t ** jc,
+                               eXosip_dialog_t ** jd, osip_transaction_t ** tr)
+{
+  for (*jc = eXosip.j_calls; *jc != NULL; *jc = (*jc)->next)
+    {
+      if ((*jc)->c_inc_tr != NULL && (*jc)->c_inc_tr->transactionid == tid)
+        {
+          *tr = (*jc)->c_inc_tr;
+          *jd = (*jc)->c_dialogs;
+          return 0;
+        }
+      if ((*jc)->c_out_tr != NULL && (*jc)->c_out_tr->transactionid == tid)
+        {
+          *tr = (*jc)->c_out_tr;
+          *jd = (*jc)->c_dialogs;
+          return 0;
+        }
+      for (*jd = (*jc)->c_dialogs; *jd != NULL; *jd = (*jd)->next)
+        {
+          osip_transaction_t *transaction;
+          int pos = 0;
+
+          while (!osip_list_eol ((*jd)->d_inc_trs, pos))
+            {
+              transaction =
+                (osip_transaction_t *) osip_list_get ((*jd)->d_inc_trs, pos);
+              if (transaction != NULL && transaction->transactionid == tid)
+                {
+                  *tr = transaction;
+                  return 0;
+                }
+              pos++;
+            }
+
+          pos = 0;
+          while (!osip_list_eol ((*jd)->d_out_trs, pos))
+            {
+              transaction =
+                (osip_transaction_t *) osip_list_get ((*jd)->d_out_trs, pos);
+              if (transaction != NULL && transaction->transactionid == tid)
+                {
+                  *tr = transaction;
+                  return 0;
+                }
+              pos++;
+            }
+        }
+    }
+  *jd = NULL;
+  *jc = NULL;
+  return -1;
+}
+
+int
+eXosip_call_set_reference (int id, void *reference)
+{
+  eXosip_dialog_t *jd = NULL;
+  eXosip_call_t *jc = NULL;
+
+  if (id > 0)
+    {
+      eXosip_call_dialog_find (id, &jc, &jd);
+      if (jc == NULL)
+        {
+          eXosip_call_find (id, &jc);
+        }
+    }
+  if (jc == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: No call here?\n"));
+      return -1;
+    }
+  jc->external_reference = reference;
+  return 0;
+}
+
+/* this method can't be called unless the previous
+   INVITE transaction is over. */
+int
+eXosip_call_build_initial_invite (osip_message_t ** invite,
+                                  const char *to,
+                                  const char *from,
+                                  const char *route, const char *subject)
+{
+  int i;
+  osip_uri_param_t *uri_param = NULL;
+  osip_to_t *_to=NULL;
+
+  *invite = NULL;
+
+  if (to != NULL && *to == '\0')
+    return -1;
+  if (route != NULL && *route == '\0')
+    route = NULL;
+  if (subject != NULL && *subject == '\0')
+    subject = NULL;
+
+  i = osip_to_init(&_to);
+  if (i!=0)
+    return -1;
+  
+  i = osip_to_parse(_to, to);
+  if (i!=0)
+    {
+      osip_to_free(_to);
+      return -1;
+    }
+
+  osip_uri_uparam_get_byname(_to->url, "transport", &uri_param);
+  if (uri_param != NULL && uri_param->gvalue != NULL)
+    {
+      i = generating_request_out_of_dialog (invite, "INVITE", to, uri_param->gvalue, from, route);      
+    }
+  else
+    {
+      if (eXosip.net_interfaces[0].net_socket>0)
+	i = generating_request_out_of_dialog (invite, "INVITE", to, "UDP", from, route);
+      else if (eXosip.net_interfaces[1].net_socket>0)
+	i = generating_request_out_of_dialog (invite, "INVITE", to, "TCP", from, route);
+      else
+	i = generating_request_out_of_dialog (invite, "INVITE", to, "UDP", from, route);
+    }
+  osip_to_free(_to);
+  if (i != 0)
+    return -1;
+
+  if (subject != NULL)
+    osip_message_set_subject (*invite, subject);
+
+  /* after this delay, we should send a CANCEL */
+  osip_message_set_expires (*invite, "120");
+  return 0;
+}
+
+int
+eXosip_call_send_initial_invite (osip_message_t * invite)
+{
+  eXosip_call_t *jc;
+  osip_transaction_t *transaction;
+  osip_event_t *sipevent;
+  int i;
+
+  eXosip_call_init (&jc);
+
+  i = osip_transaction_init (&transaction, ICT, eXosip.j_osip, invite);
+  if (i != 0)
+    {
+      eXosip_call_free (jc);
+      osip_message_free (invite);
+      return -1;
+    }
+
+  jc->c_out_tr = transaction;
+
+  sipevent = osip_new_outgoing_sipmessage (invite);
+  sipevent->transactionid = transaction->transactionid;
+
+  osip_transaction_set_your_instance (transaction,
+                                      __eXosip_new_jinfo (jc, NULL, NULL, NULL));
+  osip_transaction_add_event (transaction, sipevent);
+
+  jc->external_reference = NULL;
+  ADD_ELEMENT (eXosip.j_calls, jc);
+
+  eXosip_update ();             /* fixed? */
+  __eXosip_wakeup ();
+  return jc->c_id;
+}
+
+int
+eXosip_call_build_ack (int did, osip_message_t ** _ack)
+{
+  eXosip_dialog_t *jd = NULL;
+  eXosip_call_t *jc = NULL;
+  osip_transaction_t *tr = NULL;
+
+  osip_message_t *ack;
+  char *transport;
+  int i;
+
+  *_ack = NULL;
+
+  if (did > 0)
+    {
+      eXosip_call_dialog_find (did, &jc, &jd);
+    }
+  if (jc == NULL || jd == NULL || jd->d_dialog == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: No call here?\n"));
+      return -1;
+    }
+
+  tr = eXosip_find_last_invite (jc, jd);
+
+  if (tr == NULL || tr->orig_request == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: No transaction for call?\n"));
+      return -1;
+    }
+
+  if (0 != osip_strcasecmp (tr->orig_request->sip_method, "INVITE"))
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: ACK are only sent for invite transactions\n"));
+      return -1;
+    }
+
+  transport = NULL;
+  transport = _eXosip_transport_protocol(tr->orig_request);
+  if (transport==NULL)
+    i = _eXosip_build_request_within_dialog (&ack, "ACK", jd->d_dialog, "UDP");
+  else
+    i = _eXosip_build_request_within_dialog (&ack, "ACK", jd->d_dialog, transport);
+
+  if (i != 0)
+    {
+      return -1;
+    }
+
+  /* Fix CSeq Number when request has been exchanged during INVITE transactions */
+  if (tr->orig_request->cseq!=NULL && tr->orig_request->cseq->number!=NULL)
+    {
+      if (ack!=NULL && ack->cseq!=NULL && ack->cseq->number!=NULL)
+	{
+	  osip_free(ack->cseq->number);
+	  ack->cseq->number = osip_strdup(tr->orig_request->cseq->number);
+	}
+    }
+
+  /* copy all credentials from INVITE! */
+  {
+    int pos = 0;
+    int i;
+    osip_proxy_authorization_t *pa = NULL;
+
+    i = osip_message_get_proxy_authorization (tr->orig_request, pos, &pa);
+    while (i == 0 && pa != NULL)
+      {
+        osip_proxy_authorization_t *pa2;
+
+        i = osip_proxy_authorization_clone (pa, &pa2);
+        if (i != 0)
+          {
+            OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                                    "Error in credential from INVITE\n"));
+            break;
+          }
+        osip_list_add (ack->proxy_authorizations, pa2, -1);
+        pa = NULL;
+        pos++;
+        i = osip_message_get_proxy_authorization (tr->orig_request, pos, &pa);
+      }
+  }
+
+  *_ack = ack;
+  return 0;
+}
+
+int
+eXosip_call_send_ack (int did, osip_message_t * ack)
+{
+  eXosip_dialog_t *jd = NULL;
+  eXosip_call_t *jc = NULL;
+
+  osip_route_t *route;
+  char *host;
+  int port;
+
+  if (did > 0)
+    {
+      eXosip_call_dialog_find (did, &jc, &jd);
+    }
+
+  if (jc == NULL || jd == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: No call here?\n"));
+      if (ack != NULL)
+	osip_message_free (ack);
+      return -1;
+    }
+
+  if (ack == NULL)
+    {
+      int i;
+
+      i = eXosip_call_build_ack (did, &ack);
+      if (i != 0)
+        {
+          return -1;
+        }
+    }
+
+  osip_message_get_route (ack, 0, &route);
+  if (route != NULL)
+    {
+      osip_uri_param_t *lr_param=NULL;
+      osip_uri_uparam_get_byname (route->url, "lr", &lr_param);
+      if (lr_param==NULL)
+	route=NULL;
+    }
+
+  if (route != NULL)
+    {
+      port = 5060;
+      if (route->url->port != NULL)
+        port = osip_atoi (route->url->port);
+      host = route->url->host;
+  } else
+    {
+      port = 5060;
+      if (ack->req_uri->port != NULL)
+        port = osip_atoi (ack->req_uri->port);
+      host = ack->req_uri->host;
+    }
+
+  cb_snd_message (NULL, ack, host, port, -1);
+
+  if (jd->d_ack != NULL)
+    osip_message_free (jd->d_ack);
+  jd->d_ack = ack;
+  return 0;
+}
+
+int
+eXosip_call_build_request (int jid, const char *method, osip_message_t ** request)
+{
+  eXosip_dialog_t *jd = NULL;
+  eXosip_call_t *jc = NULL;
+
+  osip_transaction_t *transaction;
+  char *transport;
+  int i;
+  
+  *request = NULL;
+  if (method == NULL || method[0] == '\0')
+    return -1;
+
+  if (jid > 0)
+    {
+      eXosip_call_dialog_find (jid, &jc, &jd);
+    }
+  if (jd == NULL || jd->d_dialog == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: No call here?\n"));
+      return -1;
+    }
+
+  transaction = NULL;
+  if (0 == osip_strcasecmp (method, "INVITE"))
+    {
+      transaction = eXosip_find_last_invite (jc, jd);
+  } else                        /* OPTIONS, UPDATE, INFO, REFER, ?... */
+    {
+      transaction = eXosip_find_last_transaction (jc, jd, method);
+    }
+
+  if (transaction != NULL)
+    {
+      if (0 != osip_strcasecmp (method, "INVITE"))
+        {
+          if (transaction->state != NICT_TERMINATED &&
+              transaction->state != NIST_TERMINATED &&
+              transaction->state != NICT_COMPLETED &&
+              transaction->state != NIST_COMPLETED)
+            return -1;
+      } else
+        {
+          if (transaction->state != ICT_TERMINATED &&
+              transaction->state != IST_TERMINATED &&
+              transaction->state != IST_CONFIRMED &&
+              transaction->state != ICT_COMPLETED)
+            return -1;
+        }
+    }
+
+  transport = NULL;
+  transaction = eXosip_find_last_invite (jc, jd);
+  if (transaction!=NULL && transaction->orig_request!=NULL)
+    transport = _eXosip_transport_protocol(transaction->orig_request);
+
+  transaction = NULL;
+
+  if (transport==NULL)
+    i = _eXosip_build_request_within_dialog (request, method, jd->d_dialog, "UDP");
+  else
+    i = _eXosip_build_request_within_dialog (request, method, jd->d_dialog, transport);
+  if (i != 0)
+    return -2;
+
+  if (jc->response_auth!=NULL)
+    eXosip_add_authentication_information (*request, jc->response_auth);
+
+  return 0;
+}
+
+int
+eXosip_call_send_request (int jid, osip_message_t * request)
+{
+  eXosip_dialog_t *jd = NULL;
+  eXosip_call_t *jc = NULL;
+
+  osip_transaction_t *transaction;
+  osip_event_t *sipevent;
+
+  int i;
+
+  if (request == NULL)
+    return -1;
+
+  if (request->sip_method == NULL)
+    {
+      osip_message_free (request);
+      return -1;
+    }
+
+  if (jid > 0)
+    {
+      eXosip_call_dialog_find (jid, &jc, &jd);
+    }
+  if (jd == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: No call here?\n"));
+      osip_message_free (request);
+      return -1;
+    }
+
+  transaction = NULL;
+  if (0 == osip_strcasecmp (request->sip_method, "INVITE"))
+    {
+      transaction = eXosip_find_last_invite (jc, jd);
+  } else                        /* OPTIONS, UPDATE, INFO, REFER, ?... */
+    {
+      transaction = eXosip_find_last_transaction (jc, jd, request->sip_method);
+    }
+
+  if (transaction != NULL)
+    {
+      if (0 != osip_strcasecmp (request->sip_method, "INVITE"))
+        {
+          if (transaction->state != NICT_TERMINATED &&
+              transaction->state != NIST_TERMINATED &&
+              transaction->state != NICT_COMPLETED &&
+              transaction->state != NIST_COMPLETED)
+	    {
+	      osip_message_free (request);
+	      return -1;
+	    }
+      } else
+        {
+          if (transaction->state != ICT_TERMINATED &&
+              transaction->state != IST_TERMINATED &&
+              transaction->state != IST_CONFIRMED &&
+              transaction->state != ICT_COMPLETED)
+	    {
+	      osip_message_free (request);
+	      return -1;
+	    }
+        }
+    }
+
+  transaction = NULL;
+  if (0 != osip_strcasecmp (request->sip_method, "INVITE"))
+    {
+      i = osip_transaction_init (&transaction, NICT, eXosip.j_osip, request);
+  } else
+    {
+      i = osip_transaction_init (&transaction, ICT, eXosip.j_osip, request);
+    }
+
+  if (i != 0)
+    {
+      osip_message_free (request);
+      return -2;
+    }
+
+  osip_list_add (jd->d_out_trs, transaction, 0);
+
+  sipevent = osip_new_outgoing_sipmessage (request);
+  sipevent->transactionid = transaction->transactionid;
+
+  osip_transaction_set_your_instance (transaction,
+                                      __eXosip_new_jinfo (jc, jd, NULL, NULL));
+  osip_transaction_add_event (transaction, sipevent);
+  __eXosip_wakeup ();
+  return 0;
+}
+
+int
+eXosip_call_build_refer (int did, const char *refer_to, osip_message_t ** request)
+{
+  int i;
+
+  *request = NULL;
+  i = eXosip_call_build_request (did, "REFER", request);
+  if (i != 0)
+    return -1;
+
+  if (refer_to == NULL || refer_to[0] == '\0')
+    return 0;
+
+  osip_message_set_header (*request, "Refer-to", refer_to);
+  return 0;
+}
+
+int
+eXosip_call_build_options (int did, osip_message_t ** request)
+{
+  int i;
+
+  *request = NULL;
+  i = eXosip_call_build_request (did, "OPTIONS", request);
+  if (i != 0)
+    return -1;
+
+  return 0;
+}
+
+int
+eXosip_call_build_info (int did, osip_message_t ** request)
+{
+  int i;
+
+  *request = NULL;
+  i = eXosip_call_build_request (did, "INFO", request);
+  if (i != 0)
+    return -1;
+
+  return 0;
+}
+
+int
+eXosip_call_build_update (int did, osip_message_t ** request)
+{
+  int i;
+
+  *request = NULL;
+  i = eXosip_call_build_request (did, "UPDATE", request);
+  if (i != 0)
+    return -1;
+
+  return 0;
+}
+
+int
+eXosip_call_build_notify (int did, int subscription_status,
+                          osip_message_t ** request)
+{
+  char subscription_state[50];
+  char *tmp;
+  int i;
+
+  *request = NULL;
+  i = eXosip_call_build_request (did, "NOTIFY", request);
+  if (i != 0)
+    return -1;
+
+  if (subscription_status == EXOSIP_SUBCRSTATE_PENDING)
+    osip_strncpy (subscription_state, "pending;expires=", 16);
+  else if (subscription_status == EXOSIP_SUBCRSTATE_ACTIVE)
+    osip_strncpy (subscription_state, "active;expires=", 15);
+  else if (subscription_status == EXOSIP_SUBCRSTATE_TERMINATED)
+    {
+      int reason = NORESOURCE;
+
+      if (reason == DEACTIVATED)
+        osip_strncpy (subscription_state, "terminated;reason=deactivated", 29);
+      else if (reason == PROBATION)
+        osip_strncpy (subscription_state, "terminated;reason=probation", 27);
+      else if (reason == REJECTED)
+        osip_strncpy (subscription_state, "terminated;reason=rejected", 26);
+      else if (reason == TIMEOUT)
+        osip_strncpy (subscription_state, "terminated;reason=timeout", 25);
+      else if (reason == GIVEUP)
+        osip_strncpy (subscription_state, "terminated;reason=giveup", 24);
+      else if (reason == NORESOURCE)
+        osip_strncpy (subscription_state, "terminated;reason=noresource", 29);
+    }
+  tmp = subscription_state + strlen (subscription_state);
+  if (subscription_status != EXOSIP_SUBCRSTATE_TERMINATED)
+    sprintf (tmp, "%i", 180);
+  osip_message_set_header (*request, "Subscription-State", subscription_state);
+
+  return 0;
+}
+
+int
+eXosip_call_build_answer (int tid, int status, osip_message_t ** answer)
+{
+  int i = -1;
+  eXosip_dialog_t *jd = NULL;
+  eXosip_call_t *jc = NULL;
+  osip_transaction_t *tr = NULL;
+
+  *answer = NULL;
+
+  if (tid > 0)
+    {
+      _eXosip_call_transaction_find (tid, &jc, &jd, &tr);
+    }
+  if (tr == NULL || jd == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: No call here?\n"));
+      return -1;
+    }
+
+  if (0 == osip_strcasecmp (tr->orig_request->sip_method, "INVITE"))
+    {
+      if (status > 100 && status < 200)
+        {
+          i = _eXosip_answer_invite_1xx (jc, jd, status, answer);
+      } else if (status > 199 && status < 300)
+        {
+          i = _eXosip_answer_invite_2xx (jc, jd, status, answer);
+      } else if (status > 300 && status < 699)
+        {
+          i = _eXosip_answer_invite_3456xx (jc, jd, status, answer);
+      } else
+        {
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                       "eXosip: wrong status code (101<status<699)\n"));
+          return -1;
+        }
+  } else
+    {
+      if (jd != NULL)
+        {
+          i =
+            _eXosip_build_response_default (answer, jd->d_dialog, status,
+                                            tr->orig_request);
+      } else
+        {
+          i =
+            _eXosip_build_response_default (answer, NULL, status,
+                                            tr->orig_request);
+        }
+      if (status>100 && status < 300 )
+	i = complete_answer_that_establish_a_dialog (*answer, tr->orig_request);
+    }
+
+  if (i != 0)
+    {
+      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                              "ERROR: Could not create response for %s\n",
+                              tr->orig_request->sip_method));
+      return -1;
+    }
+  return 0;
+}
+
+int
+eXosip_call_send_answer (int tid, int status, osip_message_t * answer)
+{
+  int i = -1;
+  eXosip_dialog_t *jd = NULL;
+  eXosip_call_t *jc = NULL;
+  osip_transaction_t *tr = NULL;
+  osip_event_t *evt_answer;
+
+  if (tid > 0)
+    {
+      _eXosip_call_transaction_find (tid, &jc, &jd, &tr);
+    }
+  if (jd == NULL || tr == NULL || tr->orig_request == NULL
+      || tr->orig_request->sip_method == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: No call here or no transaction for call\n"));
+      osip_message_free (answer);
+      return -1;
+    }
+
+  if (answer == NULL)
+    {
+      if (0 == osip_strcasecmp (tr->orig_request->sip_method, "INVITE"))
+        {
+          if (status >= 100 && status <= 199)
+            {
+          } else if (status >= 300 && status <= 699)
+            {
+          } else
+            {
+              OSIP_TRACE (osip_trace
+                          (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                           "eXosip: Wrong parameter?\n"));
+	      osip_message_free (answer);
+              return -1;
+            }
+        }
+    }
+
+  /* is the transaction already answered? */
+  if (tr->state == IST_COMPLETED
+      || tr->state == IST_CONFIRMED
+      || tr->state == IST_TERMINATED
+      || tr->state == NIST_COMPLETED || tr->state == NIST_TERMINATED)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: transaction already answered\n"));
+      osip_message_free (answer);
+      return -1;
+    }
+
+  if (answer == NULL)
+    {
+      if (0 == osip_strcasecmp (tr->orig_request->sip_method, "INVITE"))
+        {
+          if (status < 200)
+            i = _eXosip_default_answer_invite_1xx (jc, jd, status);
+          else
+            i = _eXosip_default_answer_invite_3456xx (jc, jd, status);
+          if (i != 0)
+            {
+              OSIP_TRACE (osip_trace
+                          (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                           "eXosip: cannot send response!\n"));
+              return -1;
+            }
+      } else
+        {
+          /* TODO */
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                       "eXosip: a response must be given!\n"));
+          return -1;
+        }
+      return 0;
+  } else
+    {
+      i = 0;
+    }
+
+  if (0 == osip_strcasecmp (tr->orig_request->sip_method, "INVITE"))
+    {
+      if (MSG_IS_STATUS_1XX (answer))
+        {
+          if (jd == NULL)
+            {
+              i = eXosip_dialog_init_as_uas (&jd, tr->orig_request, answer);
+              if (i != 0)
+                {
+                  OSIP_TRACE (osip_trace
+                              (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                               "eXosip: cannot create dialog!\n"));
+                  i = 0;
+              } else
+                {
+                  ADD_ELEMENT (jc->c_dialogs, jd);
+                }
+            }
+      } else if (MSG_IS_STATUS_2XX (answer))
+        {
+          if (jd == NULL)
+            {
+              i = eXosip_dialog_init_as_uas (&jd, tr->orig_request, answer);
+              if (i != 0)
+                {
+                  OSIP_TRACE (osip_trace
+                              (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                               "eXosip: cannot create dialog!\n"));
+		  osip_message_free (answer);
+                  return -1;
+                }
+              ADD_ELEMENT (jc->c_dialogs, jd);
+          } else
+            i = 0;
+
+          eXosip_dialog_set_200ok (jd, answer);
+          osip_dialog_set_state (jd->d_dialog, DIALOG_CONFIRMED);
+      } else if (answer->status_code >= 300 && answer->status_code <= 699)
+        {
+          i = 0;
+      } else
+        {
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                       "eXosip: wrong status code (101<status<699)\n"));
+	  osip_message_free (answer);
+          return -1;
+        }
+      if (i != 0)
+	{
+	  osip_message_free (answer);
+	  return -1;
+	}
+    }
+
+  evt_answer = osip_new_outgoing_sipmessage (answer);
+  evt_answer->transactionid = tr->transactionid;
+
+  osip_transaction_add_event (tr, evt_answer);
+  eXosip_update ();
+  __eXosip_wakeup ();
+  return 0;
+}
+
+int
+eXosip_call_terminate (int cid, int did)
+{
+  int i;
+  osip_transaction_t *tr;
+  osip_message_t *request = NULL;
+  eXosip_dialog_t *jd = NULL;
+  eXosip_call_t *jc = NULL;
+  char *transport=NULL;
+
+  if (did > 0)
+    {
+      eXosip_call_dialog_find (did, &jc, &jd);
+      if (jd == NULL)
+        {
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                       "eXosip: No call here?\n"));
+          return -1;
+        }
+  } else
+    {
+      eXosip_call_find (cid, &jc);
+    }
+
+  if (jc == NULL)
+    {
+      return -1;
+    }
+
+  tr = eXosip_find_last_out_invite (jc, jd);
+  if (tr != NULL && tr->last_response != NULL
+      && MSG_IS_STATUS_1XX (tr->last_response))
+    {
+      i = generating_cancel (&request, tr->orig_request);
+      if (i != 0)
+        {
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                       "eXosip: cannot terminate this call!\n"));
+          return -2;
+        }
+      i = eXosip_create_cancel_transaction (jc, jd, request);
+      if (i != 0)
+        {
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                       "eXosip: cannot initiate SIP transaction!\n"));
+          return i;
+        }
+      if (jd != NULL)
+        {
+          osip_dialog_free (jd->d_dialog);
+          jd->d_dialog = NULL;
+          eXosip_update(); //AMD 30/09/05
+        }
+      return 0;
+    }
+
+  if (jd == NULL || jd->d_dialog == NULL)
+    {
+      /* Check if some dialog exists */
+      if (jd != NULL && jd->d_dialog != NULL)
+        {
+	  transport = NULL;
+	  if (tr!=NULL && tr->orig_request!=NULL)
+	    transport = _eXosip_transport_protocol(tr->orig_request);
+	  if (transport==NULL)
+	    i = generating_bye (&request, jd->d_dialog, "UDP");
+	  else
+	    i = generating_bye (&request, jd->d_dialog, transport);
+          if (i != 0)
+            {
+              OSIP_TRACE (osip_trace
+                          (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                           "eXosip: cannot terminate this call!\n"));
+              return -2;
+            }
+
+	  if (jc->response_auth!=NULL)
+	    eXosip_add_authentication_information (request, jc->response_auth);
+
+          i = eXosip_create_transaction (jc, jd, request);
+          if (i != 0)
+            {
+              OSIP_TRACE (osip_trace
+                          (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                           "eXosip: cannot initiate SIP transaction!\n"));
+              return -2;
+            }
+
+          osip_dialog_free (jd->d_dialog);
+          jd->d_dialog = NULL;
+          eXosip_update(); //AMD 30/09/05
+          return 0;
+        }
+
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: No established dialog!\n"));
+      return -1;
+    }
+
+  if (tr == NULL)
+    {
+      /*this may not be enough if it's a re-INVITE! */
+      tr = eXosip_find_last_inc_invite (jc, jd);
+      if (tr != NULL && tr->last_response != NULL &&
+          MSG_IS_STATUS_1XX (tr->last_response))
+        {                       /* answer with 603 */
+          i = eXosip_call_send_answer (tr->transactionid, 603, NULL);
+          return i;
+        }
+    }
+
+  transport = NULL;
+  if (tr!=NULL && tr->orig_request!=NULL)
+    transport = _eXosip_transport_protocol(tr->orig_request);
+  if (transport==NULL)
+    i = generating_bye (&request, jd->d_dialog, "UDP");
+  else
+    i = generating_bye (&request, jd->d_dialog, transport);
+
+  if (i != 0)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: cannot terminate this call!\n"));
+      return -2;
+    }
+  if (jc->response_auth!=NULL)
+    eXosip_add_authentication_information (request, jc->response_auth);
+
+  i = eXosip_create_transaction (jc, jd, request);
+  if (i != 0)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: cannot initiate SIP transaction!\n"));
+      return -2;
+    }
+
+  osip_dialog_free (jd->d_dialog);
+  jd->d_dialog = NULL;
+  eXosip_update(); //AMD 30/09/05
+  return 0;
+}
+
+int
+eXosip_call_build_prack (int tid, osip_message_t ** prack)
+{
+  eXosip_dialog_t *jd = NULL;
+  eXosip_call_t *jc = NULL;
+  osip_transaction_t *tr = NULL;
+
+  osip_header_t *rseq;
+  char *transport;
+  int i;
+
+  *prack = NULL;
+
+  if (tid > 0)
+    {
+      _eXosip_call_transaction_find (tid, &jc, &jd, &tr);
+    }
+  if (jc == NULL || jd == NULL || jd->d_dialog == NULL
+      || tr == NULL || tr->orig_request == NULL
+      || tr->orig_request->sip_method == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: No call here or no transaction for call\n"));
+      return -1;
+    }
+
+  if (0 != osip_strcasecmp (tr->orig_request->sip_method, "INVITE"))
+    return -1;
+
+  /* PRACK are only send in the PROCEEDING state */
+  if (tr->state != ICT_PROCEEDING)
+    return -1;
+
+  if (tr->orig_request->cseq == NULL
+      || tr->orig_request->cseq->number == NULL
+      || tr->orig_request->cseq->method == NULL)
+    return -1;
+
+  transport = NULL;
+  if (tr!=NULL && tr->orig_request!=NULL)
+    transport = _eXosip_transport_protocol(tr->orig_request);
+
+  if (transport==NULL)
+    i = _eXosip_build_request_within_dialog (prack, "PRACK", jd->d_dialog, "UDP");
+  else
+    i = _eXosip_build_request_within_dialog (prack, "PRACK", jd->d_dialog, transport);
+
+  if (i != 0)
+    return -2;
+
+  osip_message_header_get_byname (tr->last_response, "RSeq", 0, &rseq);
+  if (rseq != NULL && rseq->hvalue != NULL)
+    {
+      char tmp[128];
+
+      memset (tmp, '\0', sizeof (tmp));
+      snprintf (tmp, 127, "%s %s %s", rseq->hvalue,
+                tr->orig_request->cseq->number, tr->orig_request->cseq->method);
+      osip_message_set_header (*prack, "RAck", tmp);
+    }
+
+  return 0;
+}
+
+int
+eXosip_call_send_prack (int tid, osip_message_t * prack)
+{
+  eXosip_dialog_t *jd = NULL;
+  eXosip_call_t *jc = NULL;
+  osip_transaction_t *tr = NULL;
+
+  osip_event_t *sipevent;
+  int i;
+
+  if (prack == NULL)
+    return -1;
+
+  if (tid > 0)
+    {
+      _eXosip_call_transaction_find (tid, &jc, &jd, &tr);
+    }
+  if (jc == NULL || jd == NULL || jd->d_dialog == NULL
+      || tr == NULL || tr->orig_request == NULL
+      || tr->orig_request->sip_method == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: No call here or no transaction for call\n"));
+      osip_message_free (prack);
+      return -1;
+    }
+
+  if (0 != osip_strcasecmp (tr->orig_request->sip_method, "INVITE"))
+    {
+      osip_message_free (prack);
+      return -1;
+    }
+
+  /* PRACK are only send in the PROCEEDING state */
+  if (tr->state != ICT_PROCEEDING)
+    {
+      osip_message_free (prack);
+      return -1;
+    }
+
+  tr = NULL;
+  i = osip_transaction_init (&tr, NICT, eXosip.j_osip, prack);
+
+  if (i != 0)
+    {
+      osip_message_free (prack);
+      return -2;
+    }
+
+  osip_list_add (jd->d_out_trs, tr, 0);
+
+  sipevent = osip_new_outgoing_sipmessage (prack);
+  sipevent->transactionid = tr->transactionid;
+
+  osip_transaction_set_your_instance (tr, __eXosip_new_jinfo (jc, jd, NULL, NULL));
+  osip_transaction_add_event (tr, sipevent);
+  __eXosip_wakeup ();
+  return 0;
+}
+
+
+int
+_eXosip_call_redirect_request (eXosip_call_t * jc,
+                               eXosip_dialog_t * jd, osip_transaction_t * out_tr)
+{
+  osip_transaction_t *tr = NULL;
+  osip_message_t *msg = NULL;
+  osip_event_t *sipevent;
+
+  char locip[256];
+  int cseq;
+  char tmp[256];
+  osip_via_t *via;
+  osip_contact_t *co;
+  int pos;
+  int i;
+  int protocol = IPPROTO_UDP;
+
+  if (jc == NULL)
+    return -1;
+  if (jd != NULL)
+    {
+      if (jd->d_out_trs == NULL)
+        return -1;
+    }
+  if (out_tr == NULL
+      || out_tr->orig_request == NULL || out_tr->last_response == NULL)
+    return -1;
+
+  osip_message_clone (out_tr->orig_request, &msg);
+  if (msg == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: could not clone msg for authentication\n"));
+      return -1;
+    }
+
+  via = (osip_via_t *) osip_list_get (msg->vias, 0);
+  if (via == NULL || msg->cseq == NULL || msg->cseq->number == NULL)
+    {
+      osip_message_free (msg);
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: missing via or cseq header\n"));
+      return -1;
+    }
+
+  co = NULL;
+  pos = 0;
+  while (!osip_list_eol (out_tr->last_response->contacts, pos))
+    {
+      co = (osip_contact_t *) osip_list_get (out_tr->last_response->contacts, pos);
+      if (co != NULL && co->url != NULL && co->url->url_params != NULL)
+        {
+          /* check tranport? Only allow UDP, right now */
+          osip_uri_param_t *u_param;
+          int pos2;
+
+          u_param = NULL;
+          pos2 = 0;
+          while (!osip_list_eol (co->url->url_params, pos2))
+            {
+              u_param =
+                (osip_uri_param_t *) osip_list_get (co->url->url_params, pos2);
+              if (u_param == NULL || u_param->gname == NULL
+                  || u_param->gvalue == NULL)
+                {
+                  u_param = NULL;
+                  /* skip */
+              } else if (0 == osip_strcasecmp (u_param->gvalue, "transport"))
+                {
+                  if (0 == osip_strcasecmp (u_param->gvalue, "udp"))
+                    {
+#if 0
+                      /* remove the UDP parameter */
+                      osip_list_remove (co->url->url_params, pos2);
+                      osip_uri_param_free (u_param);
+#endif
+                      u_param = NULL;
+		      protocol=IPPROTO_UDP;
+                      break;    /* ok */
+                    }
+		  else if (0 == osip_strcasecmp (u_param->gvalue, "tcp"))
+		    {
+#if 0
+                      osip_list_remove (co->url->url_params, pos2);
+                      osip_uri_param_free (u_param);
+#endif
+		      protocol=IPPROTO_TCP;
+                      u_param = NULL;
+		    }
+                  break;
+                }
+              pos2++;
+            }
+
+          if (u_param == NULL || u_param->gname == NULL || u_param->gvalue == NULL)
+            {
+              break;            /* default is udp! */
+            }
+        }
+      pos++;
+      co = NULL;
+    }
+
+  if (co == NULL || co->url == NULL)
+    {
+      osip_message_free (msg);
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: contact header\n"));
+      return -1;
+    }
+
+  /* TODO:
+     remove extra parameter from new request-uri
+     check usual parameter like "transport"
+   */
+
+  /* replace request-uri with NEW contact address */
+  osip_uri_free (msg->req_uri);
+  msg->req_uri = NULL;
+  osip_uri_clone (co->url, &msg->req_uri);
+
+  /* increment cseq */
+  cseq = atoi (msg->cseq->number);
+  osip_free (msg->cseq->number);
+  msg->cseq->number = strdup_printf ("%i", cseq + 1);
+  if (jd != NULL && jd->d_dialog != NULL)
+    {
+      jd->d_dialog->local_cseq++;
+    }
+
+  osip_list_remove (msg->vias, 0);
+  osip_via_free (via);
+
+  if (protocol==IPPROTO_UDP)
+    {
+      eXosip_guess_ip_for_via (eXosip.net_interfaces[0].net_ip_family, locip,
+			       sizeof (locip));
+      if (eXosip.net_interfaces[0].net_ip_family == AF_INET6)
+	snprintf (tmp, 256, "SIP/2.0/UDP [%s]:%s;branch=z9hG4bK%u",
+		  locip, eXosip.net_interfaces[0].net_port, via_branch_new_random ());
+      else
+	snprintf (tmp, 256, "SIP/2.0/UDP %s:%s;rport;branch=z9hG4bK%u",
+		  locip, eXosip.net_interfaces[0].net_port, via_branch_new_random ());
+    }
+  else if (protocol==IPPROTO_TCP)
+    {
+      eXosip_guess_ip_for_via (eXosip.net_interfaces[1].net_ip_family, locip,
+			       sizeof (locip));
+      if (eXosip.net_interfaces[1].net_ip_family == AF_INET6)
+	snprintf (tmp, 256, "SIP/2.0/TCP [%s]:%s;branch=z9hG4bK%u",
+		  locip, eXosip.net_interfaces[1].net_port, via_branch_new_random ());
+      else
+	snprintf (tmp, 256, "SIP/2.0/TCP %s:%s;rport;branch=z9hG4bK%u",
+		  locip, eXosip.net_interfaces[1].net_port, via_branch_new_random ());
+    }
+  else
+    {
+      /* tls? */
+      osip_message_free (msg);
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: unsupported protocol\n"));
+      return -1;
+    }
+
+  osip_via_init (&via);
+  osip_via_parse (via, tmp);
+  osip_list_add (msg->vias, via, 0);
+
+  eXosip_add_authentication_information (msg, out_tr->last_response);
+  osip_message_force_update (msg);
+
+  if (0 != osip_strcasecmp (msg->sip_method, "INVITE"))
+    {
+      i = osip_transaction_init (&tr, NICT, eXosip.j_osip, msg);
+  } else
+    {
+      i = osip_transaction_init (&tr, ICT, eXosip.j_osip, msg);
+    }
+
+  if (i != 0)
+    {
+      osip_message_free (msg);
+      return -1;
+    }
+
+  if (out_tr == jc->c_out_tr)
+    {
+      /* replace with the new tr */
+      osip_list_add (eXosip.j_transactions, jc->c_out_tr, 0);
+      jc->c_out_tr = tr;
+
+      /* fix dialog issue */
+      if (jd!=NULL)
+      {
+        REMOVE_ELEMENT(jc->c_dialogs, jd);
+        eXosip_dialog_free(jd);
+        jd=NULL;
+      }
+    } else
+    {
+      /* add the new tr for the current dialog */
+      osip_list_add (jd->d_out_trs, tr, 0);
+    }
+
+  sipevent = osip_new_outgoing_sipmessage (msg);
+
+  osip_transaction_set_your_instance (tr, __eXosip_new_jinfo (jc, jd, NULL, NULL));
+  osip_transaction_add_event (tr, sipevent);
+
+  eXosip_update ();             /* fixed? */
+  __eXosip_wakeup ();
+  return 0;
+}
+
+int
+_eXosip_call_send_request_with_credential (eXosip_call_t * jc,
+                                           eXosip_dialog_t * jd,
+                                           osip_transaction_t * out_tr)
+{
+  osip_transaction_t *tr = NULL;
+  osip_message_t *msg = NULL;
+  osip_event_t *sipevent;
+
+  char locip[256];
+  int cseq;
+  char tmp[256];
+  osip_via_t *via;
+  int i;
+  int pos;
+
+  if (jc == NULL)
+    return -1;
+  if (jd != NULL)
+    {
+      if (jd->d_out_trs == NULL)
+        return -1;
+    }
+  if (out_tr == NULL
+      || out_tr->orig_request == NULL || out_tr->last_response == NULL)
+    return -1;
+
+  osip_message_clone (out_tr->orig_request, &msg);
+  if (msg == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: could not clone msg for authentication\n"));
+      return -1;
+    }
+
+  /* remove all previous authentication headers */
+  pos=0;
+  while (!osip_list_eol(msg->authorizations, pos))
+    {
+      osip_authorization_t *auth;
+      auth = (osip_authorization_t*)osip_list_get(msg->authorizations, pos);
+      osip_list_remove(msg->authorizations, pos);
+      osip_authorization_free(auth);
+      pos++;
+    }
+
+  pos=0;
+  while (!osip_list_eol(msg->proxy_authorizations, pos))
+    {
+      osip_proxy_authorization_t *auth;
+      auth = (osip_proxy_authorization_t*)osip_list_get(msg->proxy_authorizations, pos);
+      osip_list_remove(msg->proxy_authorizations, pos);
+      osip_authorization_free(auth);
+      pos++;
+    }
+
+
+  via = (osip_via_t *) osip_list_get (msg->vias, 0);
+  if (via == NULL || msg->cseq == NULL || msg->cseq->number == NULL)
+    {
+      osip_message_free (msg);
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: missing via or cseq header\n"));
+      return -1;
+    }
+
+  /* increment cseq */
+  cseq = atoi (msg->cseq->number);
+  osip_free (msg->cseq->number);
+  msg->cseq->number = strdup_printf ("%i", cseq + 1);
+  if (jd != NULL && jd->d_dialog != NULL)
+    {
+      jd->d_dialog->local_cseq++;
+    }
+
+  osip_list_remove (msg->vias, 0);
+  osip_via_free (via);
+  i = _eXosip_find_protocol(out_tr->orig_request);
+  if (i==IPPROTO_UDP)
+    {
+      eXosip_guess_ip_for_via (eXosip.net_interfaces[0].net_ip_family, locip,
+			       sizeof (locip));
+      if (eXosip.net_interfaces[0].net_ip_family == AF_INET6)
+	snprintf (tmp, 256, "SIP/2.0/UDP [%s]:%s;branch=z9hG4bK%u",
+		  locip, eXosip.net_interfaces[0].net_port, via_branch_new_random ());
+      else
+	snprintf (tmp, 256, "SIP/2.0/UDP %s:%s;rport;branch=z9hG4bK%u",
+		  locip, eXosip.net_interfaces[0].net_port, via_branch_new_random ());
+    }
+  else if (i==IPPROTO_TCP)
+    {
+      eXosip_guess_ip_for_via (eXosip.net_interfaces[1].net_ip_family, locip,
+			       sizeof (locip));
+      if (eXosip.net_interfaces[1].net_ip_family == AF_INET6)
+	snprintf (tmp, 256, "SIP/2.0/TCP [%s]:%s;branch=z9hG4bK%u",
+		  locip, eXosip.net_interfaces[1].net_port, via_branch_new_random ());
+      else
+	snprintf (tmp, 256, "SIP/2.0/TCP %s:%s;rport;branch=z9hG4bK%u",
+		  locip, eXosip.net_interfaces[1].net_port, via_branch_new_random ());
+    }
+  else
+    {
+      /* tls? */
+      osip_message_free (msg);
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: unsupported protocol\n"));
+      return -1;
+    }
+
+  osip_via_init (&via);
+  osip_via_parse (via, tmp);
+  osip_list_add (msg->vias, via, 0);
+
+  eXosip_add_authentication_information (msg, out_tr->last_response);
+  osip_message_force_update (msg);
+
+  if (0 != osip_strcasecmp (msg->sip_method, "INVITE"))
+    {
+      i = osip_transaction_init (&tr, NICT, eXosip.j_osip, msg);
+  } else
+    {
+      i = osip_transaction_init (&tr, ICT, eXosip.j_osip, msg);
+    }
+
+  if (i != 0)
+    {
+      osip_message_free (msg);
+      return -1;
+    }
+
+  if (out_tr == jc->c_out_tr)
+    {
+      /* replace with the new tr */
+      osip_list_add (eXosip.j_transactions, jc->c_out_tr, 0);
+      jc->c_out_tr = tr;
+
+      /* fix dialog issue */
+      if (jd!=NULL)
+      {
+        REMOVE_ELEMENT(jc->c_dialogs, jd);
+        eXosip_dialog_free(jd);
+        jd=NULL;
+      }
+  } else
+    {
+      /* add the new tr for the current dialog */
+      osip_list_add (jd->d_out_trs, tr, 0);
+    }
+
+  sipevent = osip_new_outgoing_sipmessage (msg);
+
+  osip_transaction_set_your_instance (tr, __eXosip_new_jinfo (jc, jd, NULL, NULL));
+  osip_transaction_add_event (tr, sipevent);
+
+  eXosip_update ();             /* fixed? */
+  __eXosip_wakeup ();
+  return 0;
+}
diff --git a/exosip2/eXconf.c b/exosip2/eXconf.c
new file mode 100644
index 0000000000..2e89e3ae20
--- /dev/null
+++ b/exosip2/eXconf.c
@@ -0,0 +1,803 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002, 2003  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+#include "eXosip2.h"
+#include <eXosip2/eXosip.h>
+
+#include <osip2/osip_mt.h>
+#include <osip2/osip_condv.h>
+
+extern eXosip_t eXosip;
+
+int ipv6_enable = 0;
+
+static void *_eXosip_thread (void *arg);
+static int _eXosip_execute (void);
+static void _eXosip_keep_alive(void);
+
+void
+eXosip_enable_ipv6 (int _ipv6_enable)
+{
+  ipv6_enable = _ipv6_enable;
+}
+
+void
+eXosip_masquerade_contact (const char *public_address, int port)
+{
+  if (public_address == NULL || public_address[0] == '\0')
+    {
+      memset (eXosip.net_interfaces[0].net_firewall_ip, '\0',
+	      sizeof (eXosip.net_interfaces[0].net_firewall_ip));
+      memset (eXosip.net_interfaces[1].net_firewall_ip, '\0',
+	      sizeof (eXosip.net_interfaces[1].net_firewall_ip));
+      memset (eXosip.net_interfaces[2].net_firewall_ip, '\0',
+	      sizeof (eXosip.net_interfaces[2].net_firewall_ip));
+      return;
+    }
+
+  snprintf (eXosip.net_interfaces[0].net_firewall_ip,
+	    sizeof (eXosip.net_interfaces[0].net_firewall_ip), "%s",
+            public_address);
+  snprintf (eXosip.net_interfaces[1].net_firewall_ip,
+	    sizeof (eXosip.net_interfaces[1].net_firewall_ip), "%s",
+            public_address);
+  snprintf (eXosip.net_interfaces[2].net_firewall_ip,
+	    sizeof (eXosip.net_interfaces[2].net_firewall_ip), "%s",
+            public_address);
+
+  if (port>0)
+    {
+      snprintf (eXosip.net_interfaces[0].net_port,
+		sizeof (eXosip.net_interfaces[0].net_port), "%i", port);
+      snprintf (eXosip.net_interfaces[1].net_port,
+		sizeof (eXosip.net_interfaces[1].net_port), "%i", port);
+      snprintf (eXosip.net_interfaces[2].net_port,
+		sizeof (eXosip.net_interfaces[2].net_port), "%i", port);
+    }
+  return;
+}
+
+int
+eXosip_force_masquerade_contact (const char *public_address)
+{
+  if (public_address == NULL || public_address[0] == '\0')
+    {
+      memset (eXosip.net_interfaces[0].net_firewall_ip, '\0',
+	      sizeof (eXosip.net_interfaces[0].net_firewall_ip));
+      memset (eXosip.net_interfaces[1].net_firewall_ip, '\0',
+	      sizeof (eXosip.net_interfaces[1].net_firewall_ip));
+      memset (eXosip.net_interfaces[2].net_firewall_ip, '\0',
+	      sizeof (eXosip.net_interfaces[2].net_firewall_ip));
+      eXosip.forced_localip = 0;
+      return 0;
+    }
+  eXosip.forced_localip = 1;
+  snprintf (eXosip.net_interfaces[0].net_firewall_ip, 50, "%s", public_address);
+  snprintf (eXosip.net_interfaces[1].net_firewall_ip, 50, "%s", public_address);
+  snprintf (eXosip.net_interfaces[2].net_firewall_ip, 50, "%s", public_address);
+  return 0;
+}
+
+int
+eXosip_guess_localip (int family, char *address, int size)
+{
+  return eXosip_guess_ip_for_via (family, address, size);
+}
+
+int
+eXosip_is_public_address (const char *c_address)
+{
+  return (0 != strncmp (c_address, "192.168", 7)
+          && 0 != strncmp (c_address, "10.", 3)
+          && 0 != strncmp (c_address, "172.16.", 7)
+          && 0 != strncmp (c_address, "172.17.", 7)
+          && 0 != strncmp (c_address, "172.18.", 7)
+          && 0 != strncmp (c_address, "172.19.", 7)
+          && 0 != strncmp (c_address, "172.20.", 7)
+          && 0 != strncmp (c_address, "172.21.", 7)
+          && 0 != strncmp (c_address, "172.22.", 7)
+          && 0 != strncmp (c_address, "172.23.", 7)
+          && 0 != strncmp (c_address, "172.24.", 7)
+          && 0 != strncmp (c_address, "172.25.", 7)
+          && 0 != strncmp (c_address, "172.26.", 7)
+          && 0 != strncmp (c_address, "172.27.", 7)
+          && 0 != strncmp (c_address, "172.28.", 7)
+          && 0 != strncmp (c_address, "172.29.", 7)
+          && 0 != strncmp (c_address, "172.30.", 7)
+          && 0 != strncmp (c_address, "172.31.", 7)
+          && 0 != strncmp (c_address, "169.254", 7));
+}
+
+void
+eXosip_set_user_agent (const char *user_agent)
+{
+  osip_free (eXosip.user_agent);
+  eXosip.user_agent = osip_strdup (user_agent);
+}
+
+void
+eXosip_kill_transaction (osip_list_t * transactions)
+{
+  osip_transaction_t *transaction;
+
+  if (!osip_list_eol (transactions, 0))
+    {
+      /* some transaction are still used by osip,
+         transaction should be released by modules! */
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "module sfp: _osip_kill_transaction transaction should be released by modules!\n"));
+    }
+
+  while (!osip_list_eol (transactions, 0))
+    {
+      transaction = osip_list_get (transactions, 0);
+
+      __eXosip_delete_jinfo (transaction);
+      osip_transaction_free (transaction);
+    }
+}
+
+void
+eXosip_quit (void)
+{
+  jauthinfo_t *jauthinfo;
+  eXosip_call_t *jc;
+  eXosip_notify_t *jn;
+  eXosip_subscribe_t *js;
+  eXosip_reg_t *jreg;
+  eXosip_pub_t *jpub;
+  int i;
+  int pos;
+
+  eXosip.j_stop_ua = 1;         /* ask to quit the application */
+  __eXosip_wakeup ();
+  __eXosip_wakeup_event ();
+
+  i = osip_thread_join ((struct osip_thread *) eXosip.j_thread);
+  if (i != 0)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: can't terminate thread!\n"));
+    }
+  osip_free ((struct osip_thread *) eXosip.j_thread);
+
+  jpipe_close (eXosip.j_socketctl);
+  jpipe_close (eXosip.j_socketctl_event);
+
+  osip_free (eXosip.user_agent);
+
+  for (jc = eXosip.j_calls; jc != NULL; jc = eXosip.j_calls)
+    {
+      REMOVE_ELEMENT (eXosip.j_calls, jc);
+      eXosip_call_free (jc);
+    }
+
+  for (js = eXosip.j_subscribes; js != NULL; js = eXosip.j_subscribes)
+    {
+      REMOVE_ELEMENT (eXosip.j_subscribes, js);
+      eXosip_subscribe_free (js);
+    }
+
+  for (jn = eXosip.j_notifies; jn != NULL; jn = eXosip.j_notifies)
+    {
+      REMOVE_ELEMENT (eXosip.j_notifies, jn);
+      eXosip_notify_free (jn);
+    }
+
+  osip_mutex_destroy ((struct osip_mutex *) eXosip.j_mutexlock);
+  osip_cond_destroy ((struct osip_cond *) eXosip.j_cond);
+
+  if (eXosip.net_interfaces[0].net_socket)
+    {
+      close (eXosip.net_interfaces[0].net_socket);
+      eXosip.net_interfaces[0].net_socket = -1;
+    }
+  if (eXosip.net_interfaces[1].net_socket)
+    {
+      close (eXosip.net_interfaces[1].net_socket);
+      eXosip.net_interfaces[1].net_socket = -1;
+    }
+  if (eXosip.net_interfaces[2].net_socket)
+    {
+      close (eXosip.net_interfaces[2].net_socket);
+      eXosip.net_interfaces[2].net_socket = -1;
+    }
+
+  for (pos=0; pos<EXOSIP_MAX_SOCKETS; pos++)
+    {
+      if (eXosip.net_interfaces[0].net_socket_tab[pos].socket!=0)
+	close (eXosip.net_interfaces[0].net_socket_tab[pos].socket);
+      if (eXosip.net_interfaces[1].net_socket_tab[pos].socket!=0)
+	close (eXosip.net_interfaces[1].net_socket_tab[pos].socket);
+      if (eXosip.net_interfaces[2].net_socket_tab[pos].socket!=0)
+	close (eXosip.net_interfaces[2].net_socket_tab[pos].socket);
+    }
+
+  for (jreg = eXosip.j_reg; jreg != NULL; jreg = eXosip.j_reg)
+    {
+      REMOVE_ELEMENT (eXosip.j_reg, jreg);
+      eXosip_reg_free (jreg);
+    }
+
+  for (jpub = eXosip.j_pub; jpub != NULL; jpub = eXosip.j_pub)
+    {
+      REMOVE_ELEMENT (eXosip.j_pub, jpub);
+      _eXosip_pub_free (jpub);
+    }
+
+  while (!osip_list_eol (eXosip.j_transactions, 0))
+    {
+      osip_transaction_t *tr =
+        (osip_transaction_t *) osip_list_get (eXosip.j_transactions, 0);
+      if (tr->state == IST_TERMINATED || tr->state == ICT_TERMINATED
+          || tr->state == NICT_TERMINATED || tr->state == NIST_TERMINATED)
+        {
+          OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                                  "Release a terminated transaction\n"));
+          osip_list_remove (eXosip.j_transactions, 0);
+          __eXosip_delete_jinfo (tr);
+          osip_transaction_free (tr);
+      } else
+        {
+          osip_list_remove (eXosip.j_transactions, 0);
+          __eXosip_delete_jinfo (tr);
+          osip_transaction_free (tr);
+        }
+    }
+
+  osip_free (eXosip.j_transactions);
+
+  eXosip_kill_transaction (eXosip.j_osip->osip_ict_transactions);
+  eXosip_kill_transaction (eXosip.j_osip->osip_nict_transactions);
+  eXosip_kill_transaction (eXosip.j_osip->osip_ist_transactions);
+  eXosip_kill_transaction (eXosip.j_osip->osip_nist_transactions);
+  osip_release (eXosip.j_osip);
+
+  {
+    eXosip_event_t *ev;
+
+    for (ev = osip_fifo_tryget (eXosip.j_events); ev != NULL;
+         ev = osip_fifo_tryget (eXosip.j_events))
+      eXosip_event_free (ev);
+  }
+
+  osip_fifo_free (eXosip.j_events);
+
+  for (jauthinfo = eXosip.authinfos; jauthinfo != NULL;
+       jauthinfo = eXosip.authinfos)
+    {
+      REMOVE_ELEMENT (eXosip.authinfos, jauthinfo);
+      osip_free (jauthinfo);
+    }
+
+  return;
+}
+
+int eXosip_set_socket(int transport, int socket, int port)
+{
+  if (eXosip.net_interfaces[0].net_socket>0)
+    close(eXosip.net_interfaces[0].net_socket);
+
+  eXosip.net_interfaces[0].net_socket = socket;
+  snprintf (eXosip.net_interfaces[0].net_port,
+	    sizeof (eXosip.net_interfaces[0].net_port), "%i", port);
+
+  eXosip.j_thread = (void *) osip_thread_create (20000, _eXosip_thread, NULL);
+  if (eXosip.j_thread == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: Cannot start thread!\n"));
+      return -1;
+    }
+  return 0;
+}
+
+#ifdef IPV6_V6ONLY
+int setsockopt_ipv6only (int sock)
+{
+  int on = 1;
+
+  return setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
+		    (char *)&on, sizeof(on));
+}
+#endif	/* IPV6_V6ONLY */
+
+int
+eXosip_listen_addr (int transport, const char *addr, int port, int family,
+		    int secure)
+{
+  int res;
+  struct addrinfo *addrinfo = NULL;
+  struct addrinfo *curinfo;
+  const char *node = addr;
+  int sock = -1;
+  struct eXosip_net *net_int;
+  char localip[256];
+
+  if (transport==IPPROTO_UDP)
+    net_int = &eXosip.net_interfaces[0];
+  else if (transport==IPPROTO_TCP)
+    net_int = &eXosip.net_interfaces[1];
+  else if (transport==IPPROTO_TCP && secure != 0)
+    net_int = &eXosip.net_interfaces[2];
+  else
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: unknown protocol (use IPPROTO_UDP or IPPROTO_TCP!\n"));
+      return -1;
+    }
+
+  if (eXosip.http_port)
+  {
+      /* USE TUNNEL CAPABILITY */
+      transport=IPPROTO_TCP;
+  }
+
+  if (port < 0)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: port must be higher than 0!\n"));
+      return -1;
+    }
+
+  net_int->net_ip_family = family;
+  if (family == AF_INET6)
+    {
+      ipv6_enable = 1;
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                   "IPv6 is enabled. Pls report bugs\n"));
+    }
+
+  eXosip_guess_localip (net_int->net_ip_family, localip,
+			sizeof (localip));
+  if (localip[0] == '\0')
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: No ethernet interface found!\n"));
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: using 127.0.0.1 (debug mode)!\n"));
+      /* we should always fallback on something. The linphone user will surely
+         start linphone BEFORE setting its dial up connection. */
+    }
+
+  if (!node) {
+    node = ipv6_enable ? "::" : "0.0.0.0";
+  }
+
+
+  res = eXosip_get_addrinfo(&addrinfo, node, port, transport);
+  if (res)
+    return -1;
+    
+  for (curinfo = addrinfo; curinfo; curinfo = curinfo->ai_next)
+    {
+      socklen_t len;
+
+      OSIP_TRACE (osip_trace
+		  (__FILE__, __LINE__, OSIP_INFO2, NULL,
+		   "eXosip: address for protocol %d (search %d)\n",
+		   curinfo->ai_protocol, transport));
+      if (curinfo->ai_protocol && curinfo->ai_protocol != transport)	
+	{
+	  OSIP_TRACE (osip_trace
+		      (__FILE__, __LINE__, OSIP_INFO2, NULL,
+		       "eXosip: Skipping protocol %d\n",
+		       curinfo->ai_protocol));
+	  continue;
+	}
+
+      sock = (int)socket(curinfo->ai_family, curinfo->ai_socktype,
+			 curinfo->ai_protocol);
+      if (sock < 0)
+	{
+	  OSIP_TRACE (osip_trace
+		      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+		       "eXosip: Cannot create socket!\n",
+		       strerror(errno)));
+	  continue;
+	}
+
+    if (eXosip.http_port)
+    {
+        break;
+    }
+
+      if (curinfo->ai_family == AF_INET6)
+	{
+#ifdef IPV6_V6ONLY
+	  if (setsockopt_ipv6only(sock))
+	    {
+	      close(sock);
+	      sock = -1;
+	      OSIP_TRACE (osip_trace
+			  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+			   "eXosip: Cannot set socket option!\n",
+			   strerror(errno)));
+	      continue;
+	    }
+#endif	/* IPV6_V6ONLY */
+	}
+      
+      res = bind (sock, curinfo->ai_addr, curinfo->ai_addrlen);
+      if (res < 0)
+	{
+	  OSIP_TRACE (osip_trace
+		      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+		       "eXosip: Cannot bind socket node:%s family:%d %s\n",
+		       node, curinfo->ai_family, strerror(errno)));
+	  close(sock);
+	  sock = -1;
+	  continue;
+	}
+      len = sizeof(net_int->ai_addr);
+      res = getsockname(sock, (struct sockaddr*)&net_int->ai_addr,
+			&len );
+      if (res!=0)
+	{
+	  OSIP_TRACE (osip_trace
+		      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+		       "eXosip: Cannot get socket name (%s)\n",
+		       strerror(errno)));
+	  memcpy(&net_int->ai_addr, curinfo->ai_addr, curinfo->ai_addrlen);
+	}
+
+      if (transport!=IPPROTO_UDP)
+	{
+	  res = listen(sock, SOMAXCONN);
+	  if (res < 0)
+	    {
+	      OSIP_TRACE (osip_trace
+			  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+		       "eXosip: Cannot bind socket node:%s family:%d %s\n",
+			   node, curinfo->ai_family, strerror(errno)));
+	      close(sock);
+	      sock = -1;
+	      continue;
+	    }
+        }
+      
+      break;
+    }
+
+  freeaddrinfo(addrinfo);
+
+  if (sock < 0)
+    {
+      OSIP_TRACE (osip_trace
+		  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+		   "eXosip: Cannot bind on port: %i\n",
+		   port));
+      return -1;
+    }
+
+  if (eXosip.http_port)
+      net_int->net_protocol = IPPROTO_UDP;
+  else
+      net_int->net_protocol = transport;
+  net_int->net_socket = sock;
+
+  if (port==0)
+    {
+      /* get port number from socket */
+      if (ipv6_enable == 0)
+	port = ntohs (((struct sockaddr_in*)&net_int->ai_addr)->sin_port);
+      else
+	port = ntohs (((struct sockaddr_in6*)&net_int->ai_addr)->sin6_port);
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                   "eXosip: Binding on port %i!\n", port));
+    }
+
+  snprintf (net_int->net_port,
+	    sizeof (net_int->net_port) - 1, "%i", port);
+
+
+
+  if (eXosip.http_port)
+  {
+        /* only ipv4 */
+        struct sockaddr_in	_addr;
+	    char http_req[2048];
+	    char http_reply[2048];
+        int len;
+        _addr.sin_port = (unsigned short) htons(eXosip.http_port);
+        _addr.sin_addr.s_addr = inet_addr(eXosip.http_proxy);
+		_addr.sin_family = PF_INET;
+
+		if (connect(net_int->net_socket, (struct sockaddr *) &_addr, sizeof(_addr)) == -1)
+		{
+            OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                  "eXosip: Failed to connect to http server on %s:%i!\n", eXosip.http_proxy, port));
+			return -1;
+		}
+
+        sprintf(http_req, "GET / HTTP/1.1\r\nUdpHost: %s:%d\r\n\r\n", eXosip.http_outbound_proxy, 5060);
+
+		len = send(net_int->net_socket, http_req, (int) strlen(http_req), 0);
+
+		if (len < 0)
+			return -1;
+
+		osip_usleep(50000);
+
+		if ((len = recv(net_int->net_socket, http_reply, sizeof(http_reply), 0)) > 0)
+			http_reply[len] = '\0';
+		else
+			return -1;
+
+		if (strncmp(http_reply, "HTTP/1.0 200 OK\r\n", 17) == 0 || strncmp(http_reply, "HTTP/1.1 200 OK\r\n", 17) == 0)
+        {
+        }
+		else
+			return -1;
+  }
+
+  eXosip.j_thread = (void *) osip_thread_create (20000, _eXosip_thread, NULL);
+  if (eXosip.j_thread == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: Cannot start thread!\n"));
+      return -1;
+    }
+  return 0;
+}
+
+int
+eXosip_init (void)
+{
+  osip_t *osip;
+
+  memset (&eXosip, 0, sizeof (eXosip));
+
+#ifdef WIN32
+  /* Initializing windows socket library */
+  {
+    WORD wVersionRequested;
+    WSADATA wsaData;
+    int i;
+
+    wVersionRequested = MAKEWORD (1, 1);
+    i = WSAStartup (wVersionRequested, &wsaData);
+    if (i != 0)
+      {
+        OSIP_TRACE (osip_trace
+                    (__FILE__, __LINE__, OSIP_WARNING, NULL,
+                     "eXosip: Unable to initialize WINSOCK, reason: %d\n", i));
+        /* return -1; It might be already initilized?? */
+      }
+  }
+#endif
+
+  eXosip.user_agent = osip_strdup ("eXosip/" EXOSIP_VERSION);
+
+  eXosip.j_calls = NULL;
+  eXosip.j_stop_ua = 0;
+  eXosip.j_thread = NULL;
+  eXosip.j_transactions = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
+  osip_list_init (eXosip.j_transactions);
+  eXosip.j_reg = NULL;
+
+  eXosip.j_cond = (struct osip_cond *) osip_cond_init ();
+
+  eXosip.j_mutexlock = (struct osip_mutex *) osip_mutex_init ();
+
+  if (-1 == osip_init (&osip))
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: Cannot initialize osip!\n"));
+      return -1;
+    }
+
+  osip_set_application_context (osip, &eXosip);
+
+  eXosip_set_callbacks (osip);
+
+  eXosip.j_osip = osip;
+
+  /* open a TCP socket to wake up the application when needed. */
+  eXosip.j_socketctl = jpipe ();
+  if (eXosip.j_socketctl == NULL)
+    return -1;
+
+  eXosip.j_socketctl_event = jpipe ();
+  if (eXosip.j_socketctl_event == NULL)
+    return -1;
+
+  /* To be changed in osip! */
+  eXosip.j_events = (osip_fifo_t *) osip_malloc (sizeof (osip_fifo_t));
+  osip_fifo_init (eXosip.j_events);
+
+  return 0;
+}
+
+
+static int
+_eXosip_execute (void)
+{
+  struct timeval lower_tv;
+  int i;
+
+  osip_timers_gettimeout (eXosip.j_osip, &lower_tv);
+  if (lower_tv.tv_sec > 15)
+    {
+      lower_tv.tv_sec = 15;
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                   "eXosip: Reseting timer to 15s before waking up!\n"));
+  } else
+    {
+        /*  add a small amount of time on windows to avoid
+            waking up too early. (probably a bad time precision) */
+        if (lower_tv.tv_usec<900000)
+            lower_tv.tv_usec = 100000; /* add 10ms */
+        else 
+        {
+            lower_tv.tv_usec = 10000; /* add 10ms */
+            lower_tv.tv_sec++;
+        }
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                   "eXosip: timer sec:%i usec:%i!\n",
+                   lower_tv.tv_sec, lower_tv.tv_usec));
+    }
+  i = eXosip_read_message (1, lower_tv.tv_sec, lower_tv.tv_usec);
+
+  if (i == -2)
+    {
+      return -2;
+    }
+
+  eXosip_lock ();
+  osip_timers_ict_execute (eXosip.j_osip);
+  osip_timers_nict_execute (eXosip.j_osip);
+  osip_timers_ist_execute (eXosip.j_osip);
+  osip_timers_nist_execute (eXosip.j_osip);
+
+  osip_ict_execute (eXosip.j_osip);
+  osip_nict_execute (eXosip.j_osip);
+  osip_ist_execute (eXosip.j_osip);
+  osip_nist_execute (eXosip.j_osip);
+
+  /* free all Calls that are in the TERMINATED STATE? */
+  eXosip_release_terminated_calls ();
+  eXosip_release_terminated_registrations ();
+
+  eXosip_unlock ();
+
+
+  if (eXosip.keep_alive>0)
+  {
+      _eXosip_keep_alive();
+  }
+
+  return 0;
+}
+
+int eXosip_set_option(eXosip_option opt, void *value)
+{
+    int val;
+    char *tmp;
+	switch (opt) {
+		case EXOSIP_OPT_UDP_KEEP_ALIVE:
+            val = *((int*)value);
+            eXosip.keep_alive = val; /* value in ms */
+            break;
+		case EXOSIP_OPT_UDP_LEARN_PORT:
+            val = *((int*)value);
+            eXosip.learn_port = val; /* value in ms */
+            break;
+		case EXOSIP_OPT_SET_HTTP_TUNNEL_PORT:
+            val = *((int*)value);
+            eXosip.http_port = val; /* value in ms */
+            break;
+		case EXOSIP_OPT_SET_HTTP_TUNNEL_PROXY:
+            tmp = (char*)value;
+            memset(eXosip.http_proxy, '\0', sizeof(eXosip.http_proxy));
+            if (tmp!=NULL && tmp[0]!='\0')
+                strncpy(eXosip.http_proxy, tmp, sizeof(eXosip.http_proxy)); /* value in proxy:port */
+            break;
+		case EXOSIP_OPT_SET_HTTP_OUTBOUND_PROXY:
+            tmp = (char*)value;
+            memset(eXosip.http_outbound_proxy, '\0', sizeof(eXosip.http_outbound_proxy));
+            if (tmp!=NULL && tmp[0]!='\0')
+                strncpy(eXosip.http_outbound_proxy, tmp, sizeof(eXosip.http_outbound_proxy)); /* value in proxy:port */
+            break;
+            
+    }
+    return 0;
+}
+
+static void
+_eXosip_keep_alive(void)
+{
+    static struct timeval mtimer = { 0, 0 };
+
+    eXosip_reg_t *jr;
+    struct eXosip_net *net;
+    char buf[4] = "jaK";
+    struct timeval now;
+    osip_gettimeofday (&now, NULL);
+
+    if (mtimer.tv_sec==0 && mtimer.tv_usec==0)
+    {
+        /* first init */
+        osip_gettimeofday (&mtimer, NULL);
+	    add_gettimeofday (&mtimer, eXosip.keep_alive);
+    }
+
+    if (osip_timercmp (&now, &mtimer, <))
+    {
+        return; /* not yet time */
+    }
+
+    /* reset timer */
+    osip_gettimeofday (&mtimer, NULL);
+	add_gettimeofday (&mtimer, eXosip.keep_alive);
+
+    net = &eXosip.net_interfaces[0];
+    if (net == NULL)
+    {
+        return ;
+    }
+
+    for (jr = eXosip.j_reg; jr != NULL; jr = jr->next)
+    {
+        if (jr->len>0)
+        {
+            if (sendto (net->net_socket, (const void *) buf, 4, 0,	 
+                (struct sockaddr *) &(jr->addr), jr->len )>0)
+            {
+                OSIP_TRACE (osip_trace
+                            (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                            "eXosip: Keep Alive sent on UDP!\n"));
+            }
+        }
+    }
+}
+
+void *
+_eXosip_thread (void *arg)
+{
+  int i;
+
+  while (eXosip.j_stop_ua == 0)
+    {
+      i = _eXosip_execute ();
+      if (i == -2)
+        osip_thread_exit ();
+    }
+  osip_thread_exit ();
+  return NULL;
+}
+
diff --git a/exosip2/eXinsubscription_api.c b/exosip2/eXinsubscription_api.c
new file mode 100644
index 0000000000..973cfef6c1
--- /dev/null
+++ b/exosip2/eXinsubscription_api.c
@@ -0,0 +1,567 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002,2003,2004,2005  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+
+#include "eXosip2.h"
+
+extern eXosip_t eXosip;
+
+static int _eXosip_insubscription_transaction_find (int tid,
+                                                    eXosip_notify_t ** jn,
+                                                    eXosip_dialog_t ** jd,
+                                                    osip_transaction_t ** tr);
+
+static int
+_eXosip_insubscription_transaction_find (int tid, eXosip_notify_t ** jn,
+                                         eXosip_dialog_t ** jd,
+                                         osip_transaction_t ** tr)
+{
+  for (*jn = eXosip.j_notifies; *jn != NULL; *jn = (*jn)->next)
+    {
+      if ((*jn)->n_inc_tr != NULL && (*jn)->n_inc_tr->transactionid == tid)
+        {
+          *tr = (*jn)->n_inc_tr;
+          *jd = (*jn)->n_dialogs;
+          return 0;
+        }
+      if ((*jn)->n_out_tr != NULL && (*jn)->n_out_tr->transactionid == tid)
+        {
+          *tr = (*jn)->n_out_tr;
+          *jd = (*jn)->n_dialogs;
+          return 0;
+        }
+      for (*jd = (*jn)->n_dialogs; *jd != NULL; *jd = (*jd)->next)
+        {
+          osip_transaction_t *transaction;
+          int pos = 0;
+
+          while (!osip_list_eol ((*jd)->d_inc_trs, pos))
+            {
+              transaction =
+                (osip_transaction_t *) osip_list_get ((*jd)->d_inc_trs, pos);
+              if (transaction != NULL && transaction->transactionid == tid)
+                {
+                  *tr = transaction;
+                  return 0;
+                }
+              pos++;
+            }
+
+          pos = 0;
+          while (!osip_list_eol ((*jd)->d_out_trs, pos))
+            {
+              transaction =
+                (osip_transaction_t *) osip_list_get ((*jd)->d_out_trs, pos);
+              if (transaction != NULL && transaction->transactionid == tid)
+                {
+                  *tr = transaction;
+                  return 0;
+                }
+              pos++;
+            }
+        }
+    }
+  *jd = NULL;
+  *jn = NULL;
+  return -1;
+}
+
+int
+eXosip_insubscription_build_answer (int tid, int status, osip_message_t ** answer)
+{
+  int i = -1;
+  eXosip_dialog_t *jd = NULL;
+  eXosip_notify_t *jn = NULL;
+  osip_transaction_t *tr = NULL;
+
+  *answer = NULL;
+
+  if (tid > 0)
+    {
+      _eXosip_insubscription_transaction_find (tid, &jn, &jd, &tr);
+    }
+  if (tr == NULL || jd == NULL || jn == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: No incoming subscription here?\n"));
+      return -1;
+    }
+
+  if (status < 101 || status > 699)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: wrong status code (101<status<699)\n"));
+      return -1;
+    }
+
+  if (jd != NULL)
+    i =
+      _eXosip_build_response_default (answer, jd->d_dialog, status,
+                                      tr->orig_request);
+  else
+    i = _eXosip_build_response_default (answer, NULL, status, tr->orig_request);
+
+  if (i != 0)
+    {
+      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                              "ERROR: Could not create response for %s\n",
+                              tr->orig_request->sip_method));
+      return -1;
+    }
+
+  if (status >= 200 && status <= 299)
+    _eXosip_notify_add_expires_in_2XX_for_subscribe (jn, *answer);
+
+  if (status < 300)
+    i = complete_answer_that_establish_a_dialog (*answer, tr->orig_request);
+
+  return 0;
+}
+
+int
+eXosip_insubscription_send_answer (int tid, int status, osip_message_t * answer)
+{
+  int i = -1;
+  eXosip_dialog_t *jd = NULL;
+  eXosip_notify_t *jn = NULL;
+  osip_transaction_t *tr = NULL;
+  osip_event_t *evt_answer;
+
+  if (tid > 0)
+    {
+      _eXosip_insubscription_transaction_find (tid, &jn, &jd, &tr);
+    }
+  if (jd == NULL || tr == NULL || tr->orig_request == NULL
+      || tr->orig_request->sip_method == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: No incoming subscription here?\n"));
+      osip_message_free (answer);
+      return -1;
+    }
+
+  if (answer == NULL)
+    {
+      if (0 == osip_strcasecmp (tr->orig_request->sip_method, "SUBSCRIBE"))
+        {
+          if (status >= 101 && status <= 199)
+            {
+          } else if (status >= 300 && status <= 699)
+            {
+          } else
+            {
+              OSIP_TRACE (osip_trace
+                          (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                           "eXosip: Wrong parameter?\n"));
+              return -1;
+            }
+        }
+    }
+
+  /* is the transaction already answered? */
+  if (tr->state == NIST_COMPLETED || tr->state == NIST_TERMINATED)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: transaction already answered\n"));
+      osip_message_free (answer);
+      return -1;
+    }
+
+  if (answer == NULL)
+    {
+      if (0 == osip_strcasecmp (tr->orig_request->sip_method, "SUBSCRIBE"))
+        {
+          if (status < 200)
+            i = _eXosip_insubscription_answer_1xx (jn, jd, status);
+          else
+            i = _eXosip_insubscription_answer_3456xx (jn, jd, status);
+          if (i != 0)
+            {
+              OSIP_TRACE (osip_trace
+                          (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                           "eXosip: cannot send response!\n"));
+              return -1;
+            }
+      } else
+        {
+          /* TODO */
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                       "eXosip: a response must be given!\n"));
+          return -1;
+        }
+      return 0;
+  } else
+    {
+      i = 0;
+    }
+
+  if (0 == osip_strcasecmp (tr->orig_request->sip_method, "SUBSCRIBE"))
+    {
+      if (MSG_IS_STATUS_1XX (answer))
+        {
+      } else if (MSG_IS_STATUS_2XX (answer))
+        {
+          eXosip_dialog_set_200ok (jd, answer);
+          osip_dialog_set_state (jd->d_dialog, DIALOG_CONFIRMED);
+      } else if (answer->status_code >= 300 && answer->status_code <= 699)
+        {
+          i = 0;
+      } else
+        {
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                       "eXosip: wrong status code (101<status<699)\n"));
+	  osip_message_free (answer);
+          return -1;
+        }
+      if (i != 0)
+        {
+	  osip_message_free (answer);
+	  return -1;
+	}
+    }
+
+  evt_answer = osip_new_outgoing_sipmessage (answer);
+  evt_answer->transactionid = tr->transactionid;
+
+  osip_transaction_add_event (tr, evt_answer);
+  eXosip_update ();
+  __eXosip_wakeup ();
+  return 0;
+}
+
+int
+eXosip_insubscription_build_notify (int did, int subscription_status,
+                                    int subscription_reason,
+                                    osip_message_t ** request)
+{
+  eXosip_dialog_t *jd = NULL;
+  eXosip_notify_t *jn = NULL;
+
+  char subscription_state[50];
+  char *tmp;
+  int now = time (NULL);
+
+  int i;
+
+  *request = NULL;
+  if (did > 0)
+    {
+      eXosip_notify_dialog_find (did, &jn, &jd);
+    }
+  if (jd == NULL || jn == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: No incoming subscription here?\n"));
+      return -1;
+    }
+
+  i = eXosip_insubscription_build_request (did, "NOTIFY", request);
+  if (i != 0)
+    {
+      return i;
+    }
+#ifndef SUPPORT_MSN
+  if (subscription_status == EXOSIP_SUBCRSTATE_PENDING)
+    osip_strncpy (subscription_state, "pending;expires=", 16);
+  else if (subscription_status == EXOSIP_SUBCRSTATE_ACTIVE)
+    osip_strncpy (subscription_state, "active;expires=", 15);
+  else if (subscription_status == EXOSIP_SUBCRSTATE_TERMINATED)
+    {
+      if (subscription_reason == DEACTIVATED)
+        osip_strncpy (subscription_state, "terminated;reason=deactivated", 29);
+      else if (subscription_reason == PROBATION)
+        osip_strncpy (subscription_state, "terminated;reason=probation", 27);
+      else if (subscription_reason == REJECTED)
+        osip_strncpy (subscription_state, "terminated;reason=rejected", 26);
+      else if (subscription_reason == TIMEOUT)
+        osip_strncpy (subscription_state, "terminated;reason=timeout", 25);
+      else if (subscription_reason == GIVEUP)
+        osip_strncpy (subscription_state, "terminated;reason=giveup", 24);
+      else if (subscription_reason == NORESOURCE)
+        osip_strncpy (subscription_state, "terminated;reason=noresource", 28);
+      else
+        osip_strncpy (subscription_state, "terminated;reason=noresource", 28);
+  } else
+    osip_strncpy (subscription_state, "pending;expires=", 16);
+
+  tmp = subscription_state + strlen (subscription_state);
+  if (subscription_status != EXOSIP_SUBCRSTATE_TERMINATED)
+    sprintf (tmp, "%i", jn->n_ss_expires - now);
+  osip_message_set_header (*request, "Subscription-State", subscription_state);
+#endif
+
+  return 0;
+}
+
+int
+eXosip_insubscription_build_request (int did, const char *method,
+                                     osip_message_t ** request)
+{
+  eXosip_dialog_t *jd = NULL;
+  eXosip_notify_t *jn = NULL;
+
+  osip_transaction_t *transaction;
+  char *transport;
+  int i;
+
+  *request = NULL;
+  if (method == NULL || method[0] == '\0')
+    return -1;
+
+  if (did > 0)
+    {
+      eXosip_notify_dialog_find (did, &jn, &jd);
+    }
+  if (jd == NULL || jn == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: No incoming subscription here?\n"));
+      return -1;
+    }
+
+  transaction = NULL;
+  transaction = eXosip_find_last_out_notify (jn, jd);
+  if (transaction != NULL)
+    {
+      if (transaction->state != NICT_TERMINATED &&
+          transaction->state != NIST_TERMINATED &&
+          transaction->state != NICT_COMPLETED &&
+          transaction->state != NIST_COMPLETED)
+        return -1;
+    }
+
+  transport = NULL;
+  if (transaction==NULL)
+    transaction = jn->n_inc_tr;
+
+  if (transaction!=NULL && transaction->orig_request!=NULL)
+    transport = _eXosip_transport_protocol(transaction->orig_request);
+
+  transaction = NULL;
+
+  if (transport==NULL)
+    i = _eXosip_build_request_within_dialog (request, method, jd->d_dialog, "UDP");
+  else
+    i = _eXosip_build_request_within_dialog (request, method, jd->d_dialog, transport);
+  if (i != 0)
+    return -2;
+
+  return 0;
+}
+
+int
+eXosip_insubscription_send_request (int did, osip_message_t * request)
+{
+  eXosip_dialog_t *jd = NULL;
+  eXosip_notify_t *jn = NULL;
+
+  osip_transaction_t *transaction;
+  osip_event_t *sipevent;
+  int i;
+
+  if (request == NULL)
+    return -1;
+
+  if (did > 0)
+    {
+      eXosip_notify_dialog_find (did, &jn, &jd);
+    }
+  if (jd == NULL || jn == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: No incoming subscription here?\n"));
+      osip_message_free (request);
+      return -1;
+    }
+
+  transaction = NULL;
+  transaction = eXosip_find_last_out_notify (jn, jd);
+  if (transaction != NULL)
+    {
+      if (transaction->state != NICT_TERMINATED &&
+          transaction->state != NIST_TERMINATED &&
+          transaction->state != NICT_COMPLETED &&
+          transaction->state != NIST_COMPLETED)
+        {
+          osip_message_free (request);
+          return -1;
+        }
+      transaction = NULL;
+    }
+
+  i = osip_transaction_init (&transaction, NICT, eXosip.j_osip, request);
+  if (i != 0)
+    {
+      osip_message_free (request);
+      return -1;
+    }
+
+  osip_list_add (jd->d_out_trs, transaction, 0);
+
+  sipevent = osip_new_outgoing_sipmessage (request);
+  sipevent->transactionid = transaction->transactionid;
+
+  osip_transaction_set_your_instance (transaction,
+                                      __eXosip_new_jinfo (NULL, jd, NULL, jn));
+  osip_transaction_add_event (transaction, sipevent);
+  __eXosip_wakeup ();
+  return 0;
+}
+
+int
+_eXosip_insubscription_send_request_with_credential (eXosip_notify_t * jn,
+                                                     eXosip_dialog_t * jd,
+                                                     osip_transaction_t * out_tr)
+{
+  osip_transaction_t *tr = NULL;
+  osip_message_t *msg = NULL;
+  osip_event_t *sipevent;
+
+  char locip[256];
+  int cseq;
+  char tmp[256];
+  osip_via_t *via;
+  int i;
+
+  if (jn == NULL)
+    return -1;
+  if (jd != NULL)
+    {
+      if (jd->d_out_trs == NULL)
+        return -1;
+    }
+
+  if (out_tr == NULL)
+    {
+      out_tr = eXosip_find_last_out_notify (jn, jd);
+    }
+
+  if (out_tr == NULL
+      || out_tr->orig_request == NULL || out_tr->last_response == NULL)
+    return -1;
+
+  osip_message_clone (out_tr->orig_request, &msg);
+  if (msg == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: could not clone msg for authentication\n"));
+      return -1;
+    }
+
+  via = (osip_via_t *) osip_list_get (msg->vias, 0);
+  if (via == NULL || msg->cseq == NULL || msg->cseq->number == NULL)
+    {
+      osip_message_free (msg);
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: missing via or cseq header\n"));
+      return -1;
+    }
+
+  /* increment cseq */
+  cseq = atoi (msg->cseq->number);
+  osip_free (msg->cseq->number);
+  msg->cseq->number = strdup_printf ("%i", cseq + 1);
+  if (jd != NULL && jd->d_dialog != NULL)
+    {
+      jd->d_dialog->local_cseq++;
+    }
+
+  osip_list_remove (msg->vias, 0);
+  osip_via_free (via);
+
+  i = _eXosip_find_protocol(out_tr->orig_request);
+  if (i==IPPROTO_UDP)
+    {
+      eXosip_guess_ip_for_via (eXosip.net_interfaces[0].net_ip_family, locip,
+			       sizeof (locip));
+      if (eXosip.net_interfaces[0].net_ip_family == AF_INET6)
+	snprintf (tmp, 256, "SIP/2.0/UDP [%s]:%s;branch=z9hG4bK%u",
+		  locip, eXosip.net_interfaces[0].net_port,
+		  via_branch_new_random ());
+      else
+	snprintf (tmp, 256, "SIP/2.0/UDP %s:%s;rport;branch=z9hG4bK%u",
+		  locip, eXosip.net_interfaces[0].net_port,
+		  via_branch_new_random ());
+    }
+  else if (i==IPPROTO_TCP)
+    {
+      eXosip_guess_ip_for_via (eXosip.net_interfaces[1].net_ip_family, locip,
+			       sizeof (locip));
+      if (eXosip.net_interfaces[1].net_ip_family == AF_INET6)
+	snprintf (tmp, 256, "SIP/2.0/TCP [%s]:%s;branch=z9hG4bK%u",
+		  locip, eXosip.net_interfaces[1].net_port,
+		  via_branch_new_random ());
+      else
+	snprintf (tmp, 256, "SIP/2.0/TCP %s:%s;rport;branch=z9hG4bK%u",
+		  locip, eXosip.net_interfaces[1].net_port,
+		  via_branch_new_random ());
+    }
+  else
+    {
+      /* tls? */
+      osip_message_free (msg);
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: unsupported protocol\n"));
+      return -1;
+    }
+
+  osip_via_init (&via);
+  osip_via_parse (via, tmp);
+  osip_list_add (msg->vias, via, 0);
+
+  eXosip_add_authentication_information (msg, out_tr->last_response);
+  osip_message_force_update (msg);
+
+  i = osip_transaction_init (&tr, NICT, eXosip.j_osip, msg);
+
+  if (i != 0)
+    {
+      osip_message_free (msg);
+      return -1;
+    }
+
+  /* add the new tr for the current dialog */
+  osip_list_add (jd->d_out_trs, tr, 0);
+
+  sipevent = osip_new_outgoing_sipmessage (msg);
+
+  osip_transaction_set_your_instance (tr, __eXosip_new_jinfo (NULL, jd, NULL, jn));
+  osip_transaction_add_event (tr, sipevent);
+
+  eXosip_update ();             /* fixed? */
+  __eXosip_wakeup ();
+  return 0;
+}
diff --git a/exosip2/eXmessage_api.c b/exosip2/eXmessage_api.c
new file mode 100644
index 0000000000..c21b649fff
--- /dev/null
+++ b/exosip2/eXmessage_api.c
@@ -0,0 +1,196 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002,2003,2004,2005  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+
+#include "eXosip2.h"
+
+extern eXosip_t eXosip;
+
+int
+eXosip_message_build_request (osip_message_t ** message, const char *method,
+                              const char *to, const char *from, const char *route)
+{
+  int i;
+
+  *message = NULL;
+  if (method != NULL && *method == '\0')
+    return -1;
+  if (to != NULL && *to == '\0')
+    return -1;
+  if (from != NULL && *from == '\0')
+    return -1;
+  if (route != NULL && *route == '\0')
+    route = NULL;
+
+  i = generating_request_out_of_dialog (message, method, to, "UDP", from, route);
+  if (i != 0)
+    return -1;
+
+  return 0;
+}
+
+int
+eXosip_message_send_request (osip_message_t * message)
+{
+  osip_transaction_t *transaction;
+  osip_event_t *sipevent;
+  int i;
+
+  i = osip_transaction_init (&transaction, NICT, eXosip.j_osip, message);
+  if (i != 0)
+    {
+      osip_message_free (message);
+      return -1;
+    }
+
+  osip_list_add (eXosip.j_transactions, transaction, 0);
+
+  sipevent = osip_new_outgoing_sipmessage (message);
+  sipevent->transactionid = transaction->transactionid;
+
+  osip_transaction_set_your_instance (transaction,
+                                      __eXosip_new_jinfo (NULL, NULL, NULL, NULL));
+  osip_transaction_add_event (transaction, sipevent);
+
+  __eXosip_wakeup ();
+  return 0;
+}
+
+int
+eXosip_message_build_answer (int tid, int status, osip_message_t ** answer)
+{
+  osip_transaction_t *tr = NULL;
+  int i = -1;
+
+  if (tid > 0)
+    {
+      eXosip_transaction_find (tid, &tr);
+    }
+  if (tr == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: No call here?\n"));
+      return -1;
+    }
+  if (status > 100 && status < 200)
+    {
+#if 0
+      /* TODO: not implemented */
+      i = _eXosip_build_response_default (response, NULL, code, tr->orig_request);
+#endif
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: status code 1xx for message not implemented (use 200<status<699)\n"));
+      return -1;
+  } else if (status > 199 && status < 300)
+    {
+      i = _eXosip_build_response_default (answer, NULL, status, tr->orig_request);
+  } else if (status > 300 && status < 699)
+    {
+      i = _eXosip_build_response_default (answer, NULL, status, tr->orig_request);
+  } else
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: wrong status code (200<status<699)\n"));
+      return -1;
+    }
+  if (i != 0)
+    return -1;
+  return 0;
+}
+
+int
+eXosip_message_send_answer (int tid, int status, osip_message_t * answer)
+{
+  osip_transaction_t *tr = NULL;
+  osip_event_t *evt_answer;
+  int i = -1;
+
+  if (tid > 0)
+    {
+      eXosip_transaction_find (tid, &tr);
+    }
+  if (tr == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: No MESSAGE transaction found\n"));
+      osip_message_free (answer);
+      return -1;
+    }
+
+  /* is the transaction already answered? */
+  if (tr->state == NIST_COMPLETED || tr->state == NIST_TERMINATED)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: transaction already answered\n"));
+      osip_message_free (answer);
+      return -1;
+    }
+
+  if (answer == NULL)
+    {
+      if (status > 100 && status < 200)
+        {
+#if 0
+          /* TODO: not implemented */
+          i =
+            _eXosip_build_response_default (response, NULL, code,
+                                            tr->orig_request);
+#endif
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                       "eXosip: status code 1xx for message not implemented (use 200<status<699)\n"));
+          return -1;
+      } else if (status > 199 && status < 300)
+        {
+          i =
+            _eXosip_build_response_default (&answer, NULL, status,
+                                            tr->orig_request);
+      } else if (status > 300 && status < 699)
+        {
+          i =
+            _eXosip_build_response_default (&answer, NULL, status,
+                                            tr->orig_request);
+      } else
+        {
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                       "eXosip: wrong status code (200<status<699)\n"));
+          return -1;
+        }
+      if (i != 0)
+        return -1;
+    }
+
+  evt_answer = osip_new_outgoing_sipmessage (answer);
+  evt_answer->transactionid = tr->transactionid;
+
+  osip_transaction_add_event (tr, evt_answer);
+  __eXosip_wakeup ();
+  return 0;
+}
diff --git a/exosip2/eXoptions_api.c b/exosip2/eXoptions_api.c
new file mode 100644
index 0000000000..e8c1ec6406
--- /dev/null
+++ b/exosip2/eXoptions_api.c
@@ -0,0 +1,200 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002,2003,2004,2005  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+
+#include "eXosip2.h"
+
+extern eXosip_t eXosip;
+
+int
+eXosip_options_build_request (osip_message_t ** options, const char *to,
+                              const char *from, const char *route)
+{
+  int i;
+
+  *options = NULL;
+  if (to != NULL && *to == '\0')
+    return -1;
+  if (from != NULL && *from == '\0')
+    return -1;
+  if (route != NULL && *route == '\0')
+    route = NULL;
+
+  i = generating_request_out_of_dialog (options, "OPTIONS", to, "UDP", from,
+                                        route);
+  if (i != 0)
+    return -1;
+
+  /* after this delay, we should send a CANCEL */
+  osip_message_set_expires (*options, "120");
+
+  /* osip_message_set_organization(*invite, "Jack's Org"); */
+  return 0;
+}
+
+int
+eXosip_options_send_request (osip_message_t * options)
+{
+  osip_transaction_t *transaction;
+  osip_event_t *sipevent;
+  int i;
+
+  i = osip_transaction_init (&transaction, NICT, eXosip.j_osip, options);
+  if (i != 0)
+    {
+      osip_message_free (options);
+      return -1;
+    }
+
+  osip_list_add (eXosip.j_transactions, transaction, 0);
+
+  sipevent = osip_new_outgoing_sipmessage (options);
+  sipevent->transactionid = transaction->transactionid;
+
+  osip_transaction_set_your_instance (transaction,
+                                      __eXosip_new_jinfo (NULL, NULL, NULL, NULL));
+  osip_transaction_add_event (transaction, sipevent);
+
+  __eXosip_wakeup ();
+  return 0;
+}
+
+int
+eXosip_options_build_answer (int tid, int status, osip_message_t ** answer)
+{
+  osip_transaction_t *tr = NULL;
+  int i = -1;
+
+  *answer = NULL;
+  if (tid > 0)
+    {
+      eXosip_transaction_find (tid, &tr);
+    }
+  if (tr == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: No call here?\n"));
+      return -1;
+    }
+  if (status > 100 && status < 200)
+    {
+#if 0
+      /* TODO: not implemented */
+      i = _eXosip_build_response_default (response, NULL, code, tr->orig_request);
+#endif
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: status code 1xx for options not implemented (use 200<status<699)\n"));
+      return -1;
+  } else if (status > 199 && status < 300)
+    {
+      i = _eXosip_build_response_default (answer, NULL, status, tr->orig_request);
+  } else if (status > 300 && status < 699)
+    {
+      i = _eXosip_build_response_default (answer, NULL, status, tr->orig_request);
+  } else
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: wrong status code (200<status<699)\n"));
+      return -1;
+    }
+  if (i != 0)
+    return -1;
+  return 0;
+}
+
+int
+eXosip_options_send_answer (int tid, int status, osip_message_t * answer)
+{
+  osip_transaction_t *tr = NULL;
+  osip_event_t *evt_answer;
+  int i = -1;
+
+  if (tid > 0)
+    {
+      eXosip_transaction_find (tid, &tr);
+    }
+  if (tr == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: No OPTIONS transaction found\n"));
+      osip_message_free (answer);
+      return -1;
+    }
+
+  /* is the transaction already answered? */
+  if (tr->state == NIST_COMPLETED || tr->state == NIST_TERMINATED)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: transaction already answered\n"));
+      osip_message_free (answer);
+      return -1;
+    }
+
+  if (answer == NULL)
+    {
+      if (status > 100 && status < 200)
+        {
+#if 0
+          /* TODO: not implemented */
+          i =
+            _eXosip_build_response_default (response, NULL, code,
+                                            tr->orig_request);
+#endif
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                       "eXosip: status code 1xx for options not implemented (use 200<status<699)\n"));
+          return -1;
+      } else if (status > 199 && status < 300)
+        {
+          i =
+            _eXosip_build_response_default (&answer, NULL, status,
+                                            tr->orig_request);
+      } else if (status > 300 && status < 699)
+        {
+          i =
+            _eXosip_build_response_default (&answer, NULL, status,
+                                            tr->orig_request);
+      } else
+        {
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                       "eXosip: wrong status code (200<status<699)\n"));
+          return -1;
+        }
+      if (i != 0)
+        return -1;
+    }
+
+  evt_answer = osip_new_outgoing_sipmessage (answer);
+  evt_answer->transactionid = tr->transactionid;
+
+  osip_transaction_add_event (tr, evt_answer);
+  __eXosip_wakeup ();
+  return 0;
+}
diff --git a/exosip2/eXosip.c b/exosip2/eXosip.c
new file mode 100644
index 0000000000..c93f3cf3a5
--- /dev/null
+++ b/exosip2/eXosip.c
@@ -0,0 +1,760 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002,2003,2004,2005  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+#include "eXosip2.h"
+#include <eXosip2/eXosip.h>
+
+
+
+#ifndef  WIN32
+#include <memory.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#endif
+
+/* Private functions */
+static jauthinfo_t *eXosip_find_authentication_info (const char *username,
+                                                     const char *realm);
+
+eXosip_t eXosip;
+
+void
+__eXosip_wakeup (void)
+{
+  jpipe_write (eXosip.j_socketctl, "w", 1);
+}
+
+void
+__eXosip_wakeup_event (void)
+{
+  jpipe_write (eXosip.j_socketctl_event, "w", 1);
+}
+
+
+int
+eXosip_lock (void)
+{
+  return osip_mutex_lock ((struct osip_mutex *) eXosip.j_mutexlock);
+}
+
+int
+eXosip_unlock (void)
+{
+  return osip_mutex_unlock ((struct osip_mutex *) eXosip.j_mutexlock);
+}
+
+int
+eXosip_transaction_find (int tid, osip_transaction_t ** transaction)
+{
+  int pos = 0;
+
+  *transaction = NULL;
+  while (!osip_list_eol (eXosip.j_transactions, pos))
+    {
+      osip_transaction_t *tr;
+
+      tr = (osip_transaction_t *) osip_list_get (eXosip.j_transactions, pos);
+      if (tr->transactionid == tid)
+        {
+          *transaction = tr;
+          return 0;
+        }
+      pos++;
+    }
+  return -1;
+}
+
+void
+eXosip_automatic_action (void)
+{
+  eXosip_call_t *jc;
+  eXosip_subscribe_t *js;
+  eXosip_dialog_t *jd;
+  eXosip_notify_t *jn;
+
+  eXosip_reg_t *jr;
+  int now;
+
+  now = time (NULL);
+
+  for (jc = eXosip.j_calls; jc != NULL; jc = jc->next)
+    {
+      if (jc->c_id < 1)
+        {
+      } else if (jc->c_dialogs == NULL || jc->c_dialogs->d_dialog == NULL)
+        {
+          /* an EARLY dialog may have failed with 401,407 or 3Xx */
+
+          osip_transaction_t *out_tr = NULL;
+
+          out_tr = jc->c_out_tr;
+
+          if (out_tr != NULL
+              && (out_tr->state == ICT_TERMINATED
+                  || out_tr->state == NICT_TERMINATED
+                  || out_tr->state == ICT_COMPLETED
+                  || out_tr->state == NICT_COMPLETED) &&
+              now - out_tr->birth_time < 120 &&
+              out_tr->orig_request != NULL &&
+              out_tr->last_response != NULL &&
+              (out_tr->last_response->status_code == 401
+               || out_tr->last_response->status_code == 407))
+            {
+              /* retry with credential */
+              if (jc->c_retry < 3)
+                {
+                  int i;
+
+                  i = _eXosip_call_send_request_with_credential (jc, NULL, out_tr);
+                  if (i != 0)
+                    {
+                      OSIP_TRACE (osip_trace
+                                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                                   "eXosip: could not clone msg for authentication\n"));
+                    }
+                  jc->c_retry++;
+                }
+          } else if (out_tr != NULL
+                     && (out_tr->state == ICT_TERMINATED
+                         || out_tr->state == NICT_TERMINATED
+                         || out_tr->state == ICT_COMPLETED
+                         || out_tr->state == NICT_COMPLETED) &&
+                     now - out_tr->birth_time < 120 &&
+                     out_tr->orig_request != NULL &&
+                     out_tr->last_response != NULL &&
+                     (out_tr->last_response->status_code >= 300
+                      && out_tr->last_response->status_code <= 399))
+            {
+              /* retry with credential */
+              int i;
+
+              i = _eXosip_call_redirect_request (jc, NULL, out_tr);
+              if (i != 0)
+                {
+                  OSIP_TRACE (osip_trace
+                              (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                               "eXosip: could not clone msg for redirection\n"));
+                }
+            }
+        }
+
+      for (jd = jc->c_dialogs; jd != NULL; jd = jd->next)
+        {
+          if (jd->d_dialog == NULL)     /* finished call */
+            {
+          } else
+            {
+              osip_transaction_t *out_tr = NULL;
+
+              out_tr = osip_list_get (jd->d_out_trs, 0);
+              if (out_tr == NULL)
+                out_tr = jc->c_out_tr;
+
+              if (out_tr != NULL
+                  && (out_tr->state == ICT_TERMINATED
+                      || out_tr->state == NICT_TERMINATED
+                      || out_tr->state == ICT_COMPLETED
+                      || out_tr->state == NICT_COMPLETED) &&
+                  now - out_tr->birth_time < 120 &&
+                  out_tr->orig_request != NULL &&
+                  out_tr->last_response != NULL &&
+                  (out_tr->last_response->status_code == 401
+                   || out_tr->last_response->status_code == 407))
+                {
+                  /* retry with credential */
+                  if (jd->d_retry < 3)
+                    {
+                      int i;
+
+                      i =
+                        _eXosip_call_send_request_with_credential (jc, jd, out_tr);
+                      if (i != 0)
+                        {
+                          OSIP_TRACE (osip_trace
+                                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                                       "eXosip: could not clone msg for authentication\n"));
+                        }
+                      jd->d_retry++;
+                    }
+              } else if (out_tr != NULL
+                         && (out_tr->state == ICT_TERMINATED
+                             || out_tr->state == NICT_TERMINATED
+                             || out_tr->state == ICT_COMPLETED
+                             || out_tr->state == NICT_COMPLETED) &&
+                         now - out_tr->birth_time < 120 &&
+                         out_tr->orig_request != NULL &&
+                         out_tr->last_response != NULL &&
+                         (out_tr->last_response->status_code >= 300
+                          && out_tr->last_response->status_code <= 399))
+                {
+                  /* retry with credential */
+                  int i;
+
+                  i = _eXosip_call_redirect_request (jc, jd, out_tr);
+                  if (i != 0)
+                    {
+                      OSIP_TRACE (osip_trace
+                                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                                   "eXosip: could not clone msg for redirection\n"));
+                    }
+                }
+            }
+        }
+    }
+
+  for (js = eXosip.j_subscribes; js != NULL; js = js->next)
+    {
+      if (js->s_id < 1)
+        {
+      } else if (js->s_dialogs == NULL)
+        {
+          osip_transaction_t *out_tr = NULL;
+
+          out_tr = js->s_out_tr;
+
+          if (out_tr != NULL
+              && (out_tr->state == NICT_TERMINATED
+                  || out_tr->state == NICT_COMPLETED) &&
+              now - out_tr->birth_time < 120 &&
+              out_tr->orig_request != NULL &&
+              out_tr->last_response != NULL &&
+              (out_tr->last_response->status_code == 401
+               || out_tr->last_response->status_code == 407))
+            {
+              /* retry with credential */
+              if (js->s_retry < 3)
+                {
+                  int i;
+
+                  i =
+                    _eXosip_subscribe_send_request_with_credential (js, NULL,
+                                                                    out_tr);
+                  if (i != 0)
+                    {
+                      OSIP_TRACE (osip_trace
+                                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                                   "eXosip: could not clone msg for authentication\n"));
+                    }
+                  js->s_retry++;
+                }
+            }
+        }
+
+      for (jd = js->s_dialogs; jd != NULL; jd = jd->next)
+        {
+          if (jd->d_dialog != NULL)     /* finished call */
+            {
+              if (jd->d_id >= 1)
+                {
+                  osip_transaction_t *out_tr = NULL;
+
+                  out_tr = osip_list_get (jd->d_out_trs, 0);
+                  if (out_tr == NULL)
+                    out_tr = js->s_out_tr;
+
+                  if (out_tr != NULL
+                      && (out_tr->state == NICT_TERMINATED
+                          || out_tr->state == NICT_COMPLETED) &&
+                      now - out_tr->birth_time < 120 &&
+                      out_tr->orig_request != NULL &&
+                      out_tr->last_response != NULL &&
+                      (out_tr->last_response->status_code == 401
+                       || out_tr->last_response->status_code == 407))
+                    {
+                      /* retry with credential */
+                      if (jd->d_retry < 3)
+                        {
+                          int i;
+
+                          i =
+                            _eXosip_subscribe_send_request_with_credential
+                            (js, jd, out_tr);
+                          if (i != 0)
+                            {
+                              OSIP_TRACE (osip_trace
+                                          (__FILE__, __LINE__, OSIP_ERROR,
+                                           NULL,
+                                           "eXosip: could not clone suscbribe for authentication\n"));
+                            }
+                          jd->d_retry++;
+                        }
+                  } else if (js->s_reg_period == 0 || out_tr == NULL)
+                    {
+                  } else if (now - out_tr->birth_time > js->s_reg_period - 60)
+                    {           /* will expires in 60 sec: send refresh! */
+                      int i;
+
+                      i =
+                        _eXosip_subscribe_send_request_with_credential (js,
+                                                                        jd,
+                                                                        out_tr);
+                      if (i != 0)
+                        {
+                          OSIP_TRACE (osip_trace
+                                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                                       "eXosip: could not clone subscribe for refresh\n"));
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+
+  for (jn = eXosip.j_notifies; jn != NULL; jn = jn->next)
+    {
+      for (jd = jn->n_dialogs; jd != NULL; jd = jd->next)
+        {
+          if (jd->d_dialog != NULL)     /* finished call */
+            {
+              if (jd->d_id >= 1)
+                {
+                  osip_transaction_t *out_tr = NULL;
+
+                  out_tr = osip_list_get (jd->d_out_trs, 0);
+
+                  if (out_tr != NULL
+                      && (out_tr->state == NICT_TERMINATED
+                          || out_tr->state == NICT_COMPLETED) &&
+                      now - out_tr->birth_time < 120 &&
+                      out_tr->orig_request != NULL &&
+                      out_tr->last_response != NULL &&
+                      (out_tr->last_response->status_code == 401
+                       || out_tr->last_response->status_code == 407))
+                    {
+                      /* retry with credential */
+                      if (jd->d_retry < 3)
+                        {
+                          int i;
+
+                          i =
+                            _eXosip_insubscription_send_request_with_credential
+                            (jn, jd, out_tr);
+                          if (i != 0)
+                            {
+                              OSIP_TRACE (osip_trace
+                                          (__FILE__, __LINE__, OSIP_ERROR,
+                                           NULL,
+                                           "eXosip: could not clone notify for authentication\n"));
+                            }
+                          jd->d_retry++;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+
+  for (jr = eXosip.j_reg; jr != NULL; jr = jr->next)
+    {
+      if (jr->r_id >= 1 && jr->r_last_tr != NULL)
+        {
+          if (jr->r_reg_period == 0)
+            {
+              /* skip refresh! */
+          } else if (now - jr->r_last_tr->birth_time > 900)
+            {
+              /* automatic refresh */
+              eXosip_register_send_register (jr->r_id, NULL);
+          } else if (now - jr->r_last_tr->birth_time > jr->r_reg_period - 60)
+            {
+              /* automatic refresh */
+              eXosip_register_send_register (jr->r_id, NULL);
+          } else if (now - jr->r_last_tr->birth_time > 120 &&
+                     (jr->r_last_tr->last_response == NULL
+                      || (!MSG_IS_STATUS_2XX (jr->r_last_tr->last_response))))
+            {
+              /* automatic refresh */
+              eXosip_register_send_register (jr->r_id, NULL);
+          } else if (now - jr->r_last_tr->birth_time < 120 &&
+                     jr->r_last_tr->orig_request != NULL &&
+                     (jr->r_last_tr->last_response != NULL
+                      && (jr->r_last_tr->last_response->status_code == 401
+                          || jr->r_last_tr->last_response->status_code == 407)))
+            {
+              if (jr->r_retry < 3)
+                {
+                  /* TODO: improve support for several retries when
+                     several credentials are needed */
+                  eXosip_register_send_register (jr->r_id, NULL);
+                  jr->r_retry++;
+                }
+            }
+        }
+    }
+}
+
+void
+eXosip_update ()
+{
+  static int static_id = 1;
+  eXosip_call_t *jc;
+  eXosip_subscribe_t *js;
+  eXosip_notify_t *jn;
+  eXosip_dialog_t *jd;
+  int now;
+
+  if (static_id > 100000)
+    static_id = 1;              /* loop */
+
+  now = time (NULL);
+  for (jc = eXosip.j_calls; jc != NULL; jc = jc->next)
+    {
+      if (jc->c_id < 1)
+        {
+          jc->c_id = static_id;
+          static_id++;
+        }
+      for (jd = jc->c_dialogs; jd != NULL; jd = jd->next)
+        {
+          if (jd->d_dialog != NULL)     /* finished call */
+            {
+              if (jd->d_id < 1)
+                {
+                  jd->d_id = static_id;
+                  static_id++;
+                }
+          } else
+            jd->d_id = -1;
+        }
+    }
+
+  for (js = eXosip.j_subscribes; js != NULL; js = js->next)
+    {
+      if (js->s_id < 1)
+        {
+          js->s_id = static_id;
+          static_id++;
+        }
+      for (jd = js->s_dialogs; jd != NULL; jd = jd->next)
+        {
+          if (jd->d_dialog != NULL)     /* finished call */
+            {
+              if (jd->d_id < 1)
+                {
+                  jd->d_id = static_id;
+                  static_id++;
+                }
+          } else
+            jd->d_id = -1;
+        }
+    }
+
+  for (jn = eXosip.j_notifies; jn != NULL; jn = jn->next)
+    {
+      if (jn->n_id < 1)
+        {
+          jn->n_id = static_id;
+          static_id++;
+        }
+      for (jd = jn->n_dialogs; jd != NULL; jd = jd->next)
+        {
+          if (jd->d_dialog != NULL)     /* finished call */
+            {
+              if (jd->d_id < 1)
+                {
+                  jd->d_id = static_id;
+                  static_id++;
+                }
+          } else
+            jd->d_id = -1;
+        }
+    }
+}
+
+static jauthinfo_t *
+eXosip_find_authentication_info (const char *username, const char *realm)
+{
+  jauthinfo_t *fallback = NULL;
+  jauthinfo_t *authinfo;
+
+  for (authinfo = eXosip.authinfos; authinfo != NULL; authinfo = authinfo->next)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                   "INFO: authinfo: %s %s\n", realm, authinfo->realm));
+      if (0 == strcmp (authinfo->username, username))
+        {
+          if (authinfo->realm == NULL || authinfo->realm[0] == '\0')
+            {
+              fallback = authinfo;
+          } else if (strcmp (realm, authinfo->realm) == 0
+                     || 0 == strncmp (realm + 1, authinfo->realm,
+                                      strlen (realm) - 2))
+            {
+              return authinfo;
+            }
+        }
+    }
+
+  /* no matching username has been found for this realm,
+     try with another username... */
+  for (authinfo = eXosip.authinfos; authinfo != NULL; authinfo = authinfo->next)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                   "INFO: authinfo: %s %s\n", realm, authinfo->realm));
+      if (authinfo->realm == NULL || authinfo->realm[0] == '\0')
+        {
+          fallback = authinfo;
+      } else if (strcmp (realm, authinfo->realm) == 0
+                 || 0 == strncmp (realm + 1, authinfo->realm, strlen (realm) - 2))
+        {
+          return authinfo;
+        }
+    }
+
+  return fallback;
+}
+
+
+int
+eXosip_clear_authentication_info ()
+{
+  jauthinfo_t *jauthinfo;
+
+  for (jauthinfo = eXosip.authinfos; jauthinfo != NULL;
+       jauthinfo = eXosip.authinfos)
+    {
+      REMOVE_ELEMENT (eXosip.authinfos, jauthinfo);
+      osip_free (jauthinfo);
+    }
+  return 0;
+}
+
+int
+eXosip_add_authentication_info (const char *username, const char *userid,
+                                const char *passwd, const char *ha1,
+                                const char *realm)
+{
+  jauthinfo_t *authinfos;
+
+  if (username == NULL || username[0] == '\0')
+    return -1;
+  if (userid == NULL || userid[0] == '\0')
+    return -1;
+
+  if (passwd != NULL && passwd[0] != '\0')
+    {
+  } else if (ha1 != NULL && ha1[0] != '\0')
+    {
+  } else
+    return -1;
+
+  authinfos = (jauthinfo_t *) osip_malloc (sizeof (jauthinfo_t));
+  if (authinfos == NULL)
+    return -1;
+  memset (authinfos, 0, sizeof (jauthinfo_t));
+
+  snprintf (authinfos->username, 50, "%s", username);
+  snprintf (authinfos->userid, 50, "%s", userid);
+  if (passwd != NULL && passwd[0] != '\0')
+    snprintf (authinfos->passwd, 50, "%s", passwd);
+  else if (ha1 != NULL && ha1[0] != '\0')
+    snprintf (authinfos->ha1, 50, "%s", ha1);
+  if (realm != NULL && realm[0] != '\0')
+    snprintf (authinfos->realm, 50, "%s", realm);
+
+  ADD_ELEMENT (eXosip.authinfos, authinfos);
+  return 0;
+}
+
+int
+eXosip_add_authentication_information (osip_message_t * req,
+                                       osip_message_t * last_response)
+{
+  osip_authorization_t *aut = NULL;
+  osip_www_authenticate_t *wwwauth = NULL;
+  osip_proxy_authorization_t *proxy_aut = NULL;
+  osip_proxy_authenticate_t *proxyauth = NULL;
+  jauthinfo_t *authinfo = NULL;
+  int pos;
+  int i;
+
+  if (req == NULL
+      || req->from == NULL
+      || req->from->url == NULL || req->from->url->username == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                   "authinfo: Invalid message\n"));
+      return -1;
+    }
+
+  pos = 0;
+  osip_message_get_www_authenticate (last_response, pos, &wwwauth);
+  osip_message_get_proxy_authenticate (last_response, pos, &proxyauth);
+  if (wwwauth == NULL && proxyauth == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                   "authinfo: No WWW-Authenticate or Proxy-Authenticate\n"));
+      return -1;
+    }
+
+  while (wwwauth != NULL)
+    {
+      char *uri;
+
+      authinfo = eXosip_find_authentication_info (req->from->url->username,
+                                                  wwwauth->realm);
+      if (authinfo == NULL)
+	{
+	  OSIP_TRACE (osip_trace
+		      (__FILE__, __LINE__, OSIP_INFO2, NULL,
+		       "authinfo: No authentication found for %s %s\n",
+		       req->from->url->username, wwwauth->realm));
+	  return -1;
+	}
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                   "authinfo: %s\n", authinfo->username));
+      i = osip_uri_to_str (req->req_uri, &uri);
+      if (i != 0)
+        return -1;
+
+      i = __eXosip_create_authorization_header (last_response, uri,
+                                                authinfo->userid,
+                                                authinfo->passwd,
+                                                authinfo->ha1, &aut,
+						req->sip_method);
+      osip_free (uri);
+      if (i != 0)
+        return -1;
+
+      if (aut != NULL)
+        {
+          osip_list_add (req->authorizations, aut, -1);
+          osip_message_force_update (req);
+        }
+
+      pos++;
+      osip_message_get_www_authenticate (last_response, pos, &wwwauth);
+    }
+
+  pos = 0;
+  while (proxyauth != NULL)
+    {
+      char *uri;
+
+      authinfo = eXosip_find_authentication_info (req->from->url->username,
+                                                  proxyauth->realm);
+      if (authinfo == NULL)
+	{
+	  OSIP_TRACE (osip_trace
+		      (__FILE__, __LINE__, OSIP_INFO2, NULL,
+		       "authinfo: No authentication found for %s %s\n",
+		       req->from->url->username, proxyauth->realm));
+	  return -1;
+	}
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                   "authinfo: %s\n", authinfo->username));
+      i = osip_uri_to_str (req->req_uri, &uri);
+      if (i != 0)
+        return -1;
+
+      i = __eXosip_create_proxy_authorization_header (last_response, uri,
+                                                      authinfo->userid,
+                                                      authinfo->passwd,
+                                                      authinfo->ha1,
+                                                      &proxy_aut,
+						      req->sip_method);
+      osip_free (uri);
+      if (i != 0)
+        return -1;
+
+      if (proxy_aut != NULL)
+        {
+          osip_list_add (req->proxy_authorizations, proxy_aut, -1);
+          osip_message_force_update (req);
+        }
+
+      pos++;
+      osip_message_get_proxy_authenticate (last_response, pos, &proxyauth);
+    }
+
+  return 0;
+}
+
+int
+eXosip_update_top_via (osip_message_t * sip)
+{
+  char locip[50];
+  char *tmp = (char *) osip_malloc (256 * sizeof (char));
+  osip_via_t *via = (osip_via_t *) osip_list_get (sip->vias, 0);
+  int i;
+
+  i = _eXosip_find_protocol(sip);
+
+  osip_list_remove (sip->vias, 0);
+  osip_via_free (via);
+#ifdef SM
+  eXosip_get_localip_for (sip->req_uri->host, locip, 49);
+#else 
+  if (i==IPPROTO_UDP)
+    eXosip_guess_ip_for_via (eXosip.net_interfaces[0].net_ip_family, locip, 49);
+  else if (i==IPPROTO_TCP)
+     eXosip_guess_ip_for_via (eXosip.net_interfaces[1].net_ip_family, locip, 49);
+  else
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: unsupported protocol (using default UDP)\n"));
+      eXosip_guess_ip_for_via (eXosip.net_interfaces[0].net_ip_family, locip, 49);
+    }
+#endif
+  if (i==IPPROTO_UDP)
+    {
+      if (eXosip.net_interfaces[0].net_ip_family == AF_INET6)
+	snprintf (tmp, 256, "SIP/2.0/UDP [%s]:%s;branch=z9hG4bK%u",
+		  locip, eXosip.net_interfaces[0].net_port,
+		  via_branch_new_random ());
+      else
+	snprintf (tmp, 256, "SIP/2.0/UDP %s:%s;rport;branch=z9hG4bK%u",
+		  locip, eXosip.net_interfaces[0].net_port,
+		  via_branch_new_random ());
+    }
+  else if (i==IPPROTO_TCP)
+    {
+      if (eXosip.net_interfaces[1].net_ip_family == AF_INET6)
+	snprintf (tmp, 256, "SIP/2.0/TCP [%s]:%s;branch=z9hG4bK%u",
+		  locip, eXosip.net_interfaces[1].net_port,
+		  via_branch_new_random ());
+      else
+	snprintf (tmp, 256, "SIP/2.0/TCP %s:%s;rport;branch=z9hG4bK%u",
+		  locip, eXosip.net_interfaces[1].net_port,
+		  via_branch_new_random ());
+    }
+
+  osip_via_init (&via);
+  osip_via_parse (via, tmp);
+  osip_list_add (sip->vias, via, 0);
+  osip_free (tmp);
+
+  return 0;
+}
diff --git a/exosip2/eXosip2.h b/exosip2/eXosip2.h
new file mode 100644
index 0000000000..0ef78c5842
--- /dev/null
+++ b/exosip2/eXosip2.h
@@ -0,0 +1,533 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002, 2003  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+#ifndef __EXOSIP2_H__
+#define __EXOSIP2_H__
+
+#ifdef WIN32
+#include <stdio.h>
+#include <stdlib.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#define snprintf _snprintf
+#define close(s) closesocket(s)
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#endif
+
+#include <stdio.h>
+
+#include <osip2/osip.h>
+#include <osip2/osip_dialog.h>
+
+#include <eXosip2/eXosip.h>
+
+#include "jpipe.h"
+
+#ifndef JD_EMPTY
+
+#define JD_EMPTY          0
+#define JD_INITIALIZED    1
+#define JD_TRYING         2
+#define JD_QUEUED         3
+#define JD_RINGING        4
+#define JD_ESTABLISHED    5
+#define JD_REDIRECTED     6
+#define JD_AUTH_REQUIRED  7
+#define JD_CLIENTERROR    8
+#define JD_SERVERERROR    9
+#define JD_GLOBALFAILURE  10
+#define JD_TERMINATED     11
+
+#define JD_MAX            11
+
+#endif
+
+#define EXOSIP_VERSION	"0.1"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+  void eXosip_update (void);
+  void __eXosip_wakeup (void);
+
+  struct __eXosip_sockaddr
+  {
+    u_char ss_len;
+    u_char ss_family;
+    u_char padding[128 - 2];
+  };
+
+  typedef struct eXosip_dialog_t eXosip_dialog_t;
+
+  struct eXosip_dialog_t
+  {
+
+    int d_id;
+    int d_STATE;
+    osip_dialog_t *d_dialog;    /* active dialog */
+
+    int d_timer;
+    osip_message_t *d_200Ok;
+    osip_message_t *d_ack;
+
+    osip_list_t *d_inc_trs;
+    osip_list_t *d_out_trs;
+    int d_retry;                /* avoid too many unsuccessfull retry */
+
+    eXosip_dialog_t *next;
+    eXosip_dialog_t *parent;
+  };
+
+  typedef struct eXosip_subscribe_t eXosip_subscribe_t;
+
+  struct eXosip_subscribe_t
+  {
+
+    int s_id;
+    int s_ss_status;
+    int s_ss_reason;
+    int s_reg_period;
+    eXosip_dialog_t *s_dialogs;
+
+    int s_retry;                /* avoid too many unsuccessfull retry */
+    osip_transaction_t *s_inc_tr;
+    osip_transaction_t *s_out_tr;
+
+    eXosip_subscribe_t *next;
+    eXosip_subscribe_t *parent;
+  };
+
+  typedef struct eXosip_notify_t eXosip_notify_t;
+
+  struct eXosip_notify_t
+  {
+
+    int n_id;
+    char n_uri[255];
+    int n_online_status;
+
+    int n_ss_status;
+    int n_ss_reason;
+    int n_ss_expires;
+    eXosip_dialog_t *n_dialogs;
+
+    osip_transaction_t *n_inc_tr;
+    osip_transaction_t *n_out_tr;
+
+    eXosip_notify_t *next;
+    eXosip_notify_t *parent;
+  };
+
+  typedef struct eXosip_call_t eXosip_call_t;
+
+  struct eXosip_call_t
+  {
+
+    int c_id;
+    eXosip_dialog_t *c_dialogs;
+    osip_transaction_t *c_inc_tr;
+    osip_transaction_t *c_out_tr;
+    int c_retry;                /* avoid too many unsuccessfull retry */
+    osip_transaction_t *c_inc_options_tr;
+    osip_transaction_t *c_out_options_tr;
+    void *external_reference;
+
+    /* cache old credentials for reuse in next request */
+    osip_message_t *response_auth;
+
+    eXosip_call_t *next;
+    eXosip_call_t *parent;
+  };
+
+
+  typedef struct eXosip_reg_t eXosip_reg_t;
+
+  struct eXosip_reg_t
+  {
+
+    int r_id;
+
+    int r_reg_period;           /* delay between registration */
+    char *r_aor;                /* sip identity */
+    char *r_registrar;          /* registrar */
+    char *r_contact;            /* list of contacts string */
+
+    osip_transaction_t *r_last_tr;
+    int r_retry;                /* avoid too many unsuccessfull retry */
+
+    char transport[10];         /* transport used for registration */
+
+    struct __eXosip_sockaddr addr;
+    int len;
+
+    eXosip_reg_t *next;
+    eXosip_reg_t *parent;
+  };
+
+
+  typedef struct eXosip_pub_t eXosip_pub_t;
+
+  struct eXosip_pub_t
+  {
+    int p_id;
+
+    time_t p_expires;           /* expiration date (started+period) */
+    int p_period;               /* delay between registration */
+    char p_aor[256];            /* sip identity */
+    char p_sip_etag[64];        /* sip_etag from 200ok */
+
+    osip_transaction_t *p_last_tr;
+    eXosip_pub_t *next;
+    eXosip_pub_t *parent;
+  };
+
+  int _eXosip_pub_update (eXosip_pub_t ** pub, osip_transaction_t * tr,
+                          osip_message_t * answer);
+  int _eXosip_pub_find_by_aor (eXosip_pub_t ** pub, const char *aor);
+  int _eXosip_pub_init (eXosip_pub_t ** pub, const char *aor, const char *exp);
+  void _eXosip_pub_free (eXosip_pub_t * pub);
+
+  typedef struct jauthinfo_t jauthinfo_t;
+
+  struct jauthinfo_t
+  {
+    char username[50];
+    char userid[50];
+    char passwd[50];
+    char ha1[50];
+    char realm[50];
+    jauthinfo_t *parent;
+    jauthinfo_t *next;
+  };
+
+  int
+    __eXosip_create_authorization_header (osip_message_t * previous_answer,
+                                          const char *rquri,
+                                          const char *username,
+                                          const char *passwd,
+                                          const char *ha1,
+                                          osip_authorization_t ** auth,
+					  const char *method);
+  int __eXosip_create_proxy_authorization_header (osip_message_t *
+                                                  previous_answer,
+                                                  const char *rquri,
+                                                  const char *username,
+                                                  const char *passwd,
+                                                  const char *ha1,
+                                                  osip_proxy_authorization_t
+                                                  ** auth,
+						  const char *method);
+
+  eXosip_event_t *eXosip_event_init_for_call (int type, eXosip_call_t * jc,
+                                              eXosip_dialog_t * jd,
+                                              osip_transaction_t * tr);
+
+  eXosip_event_t *eXosip_event_init_for_subscribe (int type,
+                                                   eXosip_subscribe_t * js,
+                                                   eXosip_dialog_t * jd,
+                                                   osip_transaction_t * tr);
+  eXosip_event_t *eXosip_event_init_for_notify (int type,
+                                                eXosip_notify_t * jn,
+                                                eXosip_dialog_t * jd,
+                                                osip_transaction_t * tr);
+  eXosip_event_t *eXosip_event_init_for_reg (int type, eXosip_reg_t * jr,
+                                             osip_transaction_t * tr);
+  eXosip_event_t *eXosip_event_init_for_message (int type,
+                                                 osip_transaction_t * tr);
+
+  int eXosip_event_init (eXosip_event_t ** je, int type);
+  void report_call_event (int evt, eXosip_call_t * jc, eXosip_dialog_t * jd,
+                          osip_transaction_t * tr);
+  void report_options_event (int evt, osip_transaction_t * tr);
+  void report_event (eXosip_event_t * je, osip_message_t * sip);
+  int eXosip_event_add (eXosip_event_t * je);
+  eXosip_event_t *eXosip_event_wait (int tv_s, int tv_ms);
+  eXosip_event_t *eXosip_event_get (void);
+
+  typedef void (*eXosip_callback_t) (int type, eXosip_event_t *);
+
+  char *strdup_printf (const char *fmt, ...);
+
+#define eXosip_trace(loglevel,args)  do        \
+{                       \
+	char *__strmsg;  \
+	__strmsg=strdup_printf args ;    \
+	OSIP_TRACE(osip_trace(__FILE__,__LINE__,(loglevel),NULL,"%s\n",__strmsg)); \
+	osip_free (__strmsg);        \
+}while (0);
+
+#ifndef EXOSIP_MAX_SOCKETS
+#define EXOSIP_MAX_SOCKETS 200
+#endif
+
+  /* structure used for keepalive management with connected protocols (TCP or TLS) */
+  struct eXosip_socket {
+    int  socket;
+    char remote_ip[50];
+    int  remote_port;
+  };
+
+  struct eXosip_net {
+    char net_firewall_ip[50];     /* ip address to use for masquerading contacts */
+    int  net_ip_family;           /* AF_INET6 or AF_INET */
+    struct sockaddr_storage ai_addr;
+    char net_port[20];            /* port for receiving message/connection */
+    int  net_socket;              /* initial socket for receiving message/connection */
+    int  net_protocol;            /* initial socket for receiving message/connection */
+    struct eXosip_socket net_socket_tab[EXOSIP_MAX_SOCKETS];
+  };
+
+  char *_eXosip_transport_protocol(osip_message_t *msg);
+  int _eXosip_find_protocol(osip_message_t *msg);
+  int _eXosip_tcp_find_socket(char *host, int port);
+  int _eXosip_tcp_connect_socket(char *host, int port);
+  int setsockopt_ipv6only (int sock);
+
+  int _eXosip_recvfrom(int s, char *buf, int len, unsigned int flags, struct sockaddr *from, socklen_t *fromlen);
+  int _eXosip_sendto(int s,  const void* buf,  size_t len,  int flags,
+    const struct sockaddr* to,  socklen_t tolen);
+
+  typedef struct eXosip_t eXosip_t;
+
+  struct eXosip_t
+  {
+    int forced_localip;         /* set to 1 for masquerading contact headers */
+    struct eXosip_net net_interfaces[3];
+    char *user_agent;
+
+    eXosip_call_t *j_calls;             /* my calls        */
+    eXosip_subscribe_t *j_subscribes;   /* my friends      */
+    eXosip_notify_t *j_notifies;        /* my susbscribers */
+    osip_list_t *j_transactions;
+
+    eXosip_reg_t *j_reg;        /* my registrations */
+    eXosip_pub_t *j_pub;        /* my publications  */
+
+    void *j_cond;
+    void *j_mutexlock;
+
+    osip_t *j_osip;
+    int j_stop_ua;
+    void *j_thread;
+    jpipe_t *j_socketctl;
+    jpipe_t *j_socketctl_event;
+
+    osip_fifo_t *j_events;
+
+    jauthinfo_t *authinfos;
+
+    int   keep_alive;
+    int   learn_port;
+    int   http_port;
+    char  http_proxy[256];
+    char  http_outbound_proxy[256];
+  };
+
+  typedef struct jinfo_t jinfo_t;
+
+  struct jinfo_t
+  {
+    eXosip_dialog_t *jd;
+    eXosip_call_t *jc;
+    eXosip_subscribe_t *js;
+    eXosip_notify_t *jn;
+  };
+
+  int eXosip_guess_ip_for_via (int family, char *address, int size);
+
+/**
+ * Prepare addrinfo for socket binding and resolv hostname
+ * 
+ * @param addrinfo  informations about the connections
+ * @param hostname  hostname to resolv.
+ * @param service   port number or "sip" SRV record if service=0
+ */
+  int eXosip_get_addrinfo (struct addrinfo **addrinfo, const char *hostname,
+                           int service, int protocol);
+
+  int eXosip_set_callbacks (osip_t * osip);
+  int cb_snd_message (osip_transaction_t * tr, osip_message_t * sip,
+			   char *host, int port, int out_socket);
+  int cb_udp_snd_message (osip_transaction_t * tr, osip_message_t * sip,
+                          char *host, int port, int out_socket);
+  int cb_tcp_snd_message (osip_transaction_t * tr, osip_message_t * sip,
+                          char *host, int port, int out_socket);
+  char *osip_call_id_new_random (void);
+  char *osip_to_tag_new_random (void);
+  char *osip_from_tag_new_random (void);
+  unsigned int via_branch_new_random (void);
+  void __eXosip_delete_jinfo (osip_transaction_t * transaction);
+  jinfo_t *__eXosip_new_jinfo (eXosip_call_t * jc, eXosip_dialog_t * jd,
+                               eXosip_subscribe_t * js, eXosip_notify_t * jn);
+
+  int eXosip_dialog_init_as_uac (eXosip_dialog_t ** jd, osip_message_t * _200Ok);
+  int eXosip_dialog_init_as_uas (eXosip_dialog_t ** jd,
+                                 osip_message_t * _invite,
+                                 osip_message_t * _200Ok);
+  void eXosip_dialog_free (eXosip_dialog_t * jd);
+  void eXosip_dialog_set_state (eXosip_dialog_t * jd, int state);
+  void eXosip_delete_early_dialog (eXosip_dialog_t * jd);
+
+
+  int isrfc1918 (char *ipaddr);
+  void eXosip_get_localip_from_via (osip_message_t *, char *localip, int size);
+  int generating_request_out_of_dialog (osip_message_t ** dest,
+                                        const char *method, const char *to,
+                                        const char *transport,
+                                        const char *from, const char *proxy);
+  int generating_publish (osip_message_t ** message, const char *to,
+                          const char *from, const char *route);
+  int generating_cancel (osip_message_t ** dest,
+                         osip_message_t * request_cancelled);
+  int generating_bye (osip_message_t ** bye, osip_dialog_t * dialog, char *transport);
+  int generating_ack_for_2xx (osip_message_t ** ack, osip_dialog_t * dialog);
+
+  int eXosip_update_top_via (osip_message_t * sip);
+  int eXosip_add_authentication_information (osip_message_t * req,
+                                             osip_message_t * last_response);
+  int _eXosip_reg_find (eXosip_reg_t ** reg, osip_transaction_t * tr);
+  int eXosip_reg_init (eXosip_reg_t ** jr, const char *from,
+                       const char *proxy, const char *contact);
+  void eXosip_reg_free (eXosip_reg_t * jreg);
+  int generating_register (osip_message_t ** reg, char *transport, char *from,
+                           char *proxy, char *contact, int expires);
+
+  int _eXosip_call_redirect_request (eXosip_call_t * jc,
+                                     eXosip_dialog_t * jd,
+                                     osip_transaction_t * out_tr);
+  int _eXosip_call_send_request_with_credential (eXosip_call_t * jc,
+                                                 eXosip_dialog_t * jd,
+                                                 osip_transaction_t * out_tr);
+  int eXosip_transaction_find (int tid, osip_transaction_t ** transaction);
+  int eXosip_call_dialog_find (int jid, eXosip_call_t ** jc,
+                               eXosip_dialog_t ** jd);
+  int eXosip_notify_dialog_find (int nid, eXosip_notify_t ** jn,
+                                 eXosip_dialog_t ** jd);
+  int eXosip_subscribe_dialog_find (int nid, eXosip_subscribe_t ** js,
+                                    eXosip_dialog_t ** jd);
+  int eXosip_call_find (int cid, eXosip_call_t ** jc);
+  int eXosip_dialog_set_200ok (eXosip_dialog_t * _jd, osip_message_t * _200Ok);
+
+  int _eXosip_answer_invite_3456xx (eXosip_call_t * jc, eXosip_dialog_t * jd,
+                                    int code, osip_message_t ** answer);
+  int _eXosip_answer_invite_2xx (eXosip_call_t * jc, eXosip_dialog_t * jd,
+                                 int code, osip_message_t ** answer);
+  int _eXosip_answer_invite_1xx (eXosip_call_t * jc, eXosip_dialog_t * jd,
+                                 int code, osip_message_t ** answer);
+  int _eXosip_default_answer_invite_1xx (eXosip_call_t * jc,
+                                         eXosip_dialog_t * jd, int code);
+  int _eXosip_default_answer_invite_3456xx (eXosip_call_t * jc,
+                                            eXosip_dialog_t * jd, int code);
+  int _eXosip_insubscription_answer_1xx (eXosip_notify_t * jc,
+                                         eXosip_dialog_t * jd, int code);
+  int _eXosip_insubscription_answer_2xx (eXosip_notify_t * jn,
+                                         eXosip_dialog_t * jd, int code);
+  int _eXosip_insubscription_answer_3456xx (eXosip_notify_t * jn,
+                                            eXosip_dialog_t * jd, int code);
+
+  int eXosip_build_response_default (int jid, int status);
+  int _eXosip_build_response_default (osip_message_t ** dest,
+                                      osip_dialog_t * dialog, int status,
+                                      osip_message_t * request);
+  int complete_answer_that_establish_a_dialog (osip_message_t * response,
+                                               osip_message_t * request);
+  int _eXosip_build_request_within_dialog (osip_message_t ** dest,
+                                           const char *method,
+                                           osip_dialog_t * dialog,
+                                           const char *transport);
+  void eXosip_kill_transaction (osip_list_t * transactions);
+  int eXosip_remove_transaction_from_call (osip_transaction_t * tr,
+                                           eXosip_call_t * jc);
+  osip_transaction_t *eXosip_find_last_inc_notify (eXosip_subscribe_t * jn,
+                                                   eXosip_dialog_t * jd);
+  osip_transaction_t *eXosip_find_last_out_notify (eXosip_notify_t * jn,
+                                                   eXosip_dialog_t * jd);
+  osip_transaction_t *eXosip_find_last_inc_subscribe (eXosip_notify_t * jn,
+                                                      eXosip_dialog_t * jd);
+  osip_transaction_t *eXosip_find_last_out_subscribe (eXosip_subscribe_t * js,
+                                                      eXosip_dialog_t * jd);
+
+  osip_transaction_t *eXosip_find_last_transaction (eXosip_call_t * jc,
+                                                    eXosip_dialog_t * jd,
+                                                    const char *method);
+  osip_transaction_t *eXosip_find_last_inc_transaction (eXosip_call_t * jc,
+                                                        eXosip_dialog_t * jd,
+                                                        const char *method);
+  osip_transaction_t *eXosip_find_last_out_transaction (eXosip_call_t * jc,
+                                                        eXosip_dialog_t * jd,
+                                                        const char *method);
+  osip_transaction_t *eXosip_find_last_invite (eXosip_call_t * jc,
+                                               eXosip_dialog_t * jd);
+  osip_transaction_t *eXosip_find_last_inc_invite (eXosip_call_t * jc,
+                                                   eXosip_dialog_t * jd);
+  osip_transaction_t *eXosip_find_last_out_invite (eXosip_call_t * jc,
+                                                   eXosip_dialog_t * jd);
+
+
+  int eXosip_call_init (eXosip_call_t ** jc);
+  void eXosip_call_free (eXosip_call_t * jc);
+  void __eXosip_call_remove_dialog_reference_in_call (eXosip_call_t * jc,
+                                                      eXosip_dialog_t * jd);
+  int eXosip_read_message (int max_message_nb, int sec_max, int usec_max);
+  void eXosip_release_terminated_calls (void);
+  void eXosip_release_terminated_registrations (void);
+
+
+  int eXosip_subscribe_init (eXosip_subscribe_t ** js);
+  void eXosip_subscribe_free (eXosip_subscribe_t * js);
+  int _eXosip_subscribe_set_refresh_interval (eXosip_subscribe_t * js,
+                                              osip_message_t * inc_subscribe);
+  int eXosip_subscribe_need_refresh (eXosip_subscribe_t * js,
+                                     eXosip_dialog_t * jd, int now);
+  int _eXosip_subscribe_send_request_with_credential (eXosip_subscribe_t * js,
+                                                      eXosip_dialog_t * jd,
+                                                      osip_transaction_t * out_tr);
+  int eXosip_notify_init (eXosip_notify_t ** jn, osip_message_t * inc_subscribe);
+  void eXosip_notify_free (eXosip_notify_t * jn);
+  int _eXosip_notify_set_contact_info (eXosip_notify_t * jn, char *uri);
+  int _eXosip_notify_set_refresh_interval (eXosip_notify_t * jn,
+                                           osip_message_t * inc_subscribe);
+  void _eXosip_notify_add_expires_in_2XX_for_subscribe (eXosip_notify_t * jn,
+                                                        osip_message_t * answer);
+  int _eXosip_insubscription_send_request_with_credential (eXosip_notify_t *
+                                                           jn,
+                                                           eXosip_dialog_t *
+                                                           jd,
+                                                           osip_transaction_t
+                                                           * out_tr);
+
+  int eXosip_is_public_address (const char *addr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/exosip2/eXpublish_api.c b/exosip2/eXpublish_api.c
new file mode 100644
index 0000000000..36a937664b
--- /dev/null
+++ b/exosip2/eXpublish_api.c
@@ -0,0 +1,168 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002,2003,2004,2005  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+#include "eXosip2.h"
+#include <eXosip2/eXosip.h>
+
+extern eXosip_t eXosip;
+
+int
+eXosip_build_publish (osip_message_t ** message,
+                      const char *to,
+                      const char *from,
+                      const char *route,
+                      const char *event,
+                      const char *expires, const char *ctype, const char *body)
+{
+  int i;
+
+  *message = NULL;
+
+  if (to == NULL || to[0] == '\0')
+    return -1;
+  if (from == NULL || from[0] == '\0')
+    return -1;
+  if (event == NULL || event[0] == '\0')
+    return -1;
+  if (ctype == NULL || ctype[0] == '\0')
+    {
+      if (body != NULL && body[0] != '\0')
+        return -1;
+  } else
+    {
+      if (body == NULL || body[0] == '\0')
+        return -1;
+    }
+
+  i = generating_publish (message, to, from, route);
+  if (i != 0)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: cannot send message (cannot build PUBLISH)! "));
+      return -1;
+    }
+
+  if (body != NULL && body[0] != '\0' && ctype != NULL && ctype[0] != '\0')
+    {
+      osip_message_set_content_type (*message, ctype);
+      osip_message_set_body (*message, body, strlen (body));
+      osip_message_set_header (*message, "Content-Disposition",
+                               "render;handling=required");
+    }
+  if (expires != NULL && expires[0] != '\0')
+    osip_message_set_expires (*message, expires);
+  else
+    osip_message_set_expires (*message, "3600");
+
+  osip_message_set_header (*message, "Event", event);
+  return 0;
+}
+
+int
+eXosip_publish (osip_message_t * message, const char *to)
+{
+  osip_transaction_t *transaction;
+  osip_event_t *sipevent;
+  int i;
+  eXosip_pub_t *pub = NULL;
+
+  if (message == NULL)
+    return -1;
+  if (message->cseq == NULL || message->cseq->number == NULL)
+    {
+      osip_message_free (message);
+      return -1;
+    }
+  if (to == NULL)
+    {
+      osip_message_free (message);
+      return -1;
+    }
+
+  i = _eXosip_pub_find_by_aor (&pub, to);
+  if (i != 0 || pub == NULL)
+    {
+      osip_header_t *expires;
+
+      osip_message_get_expires (message, 0, &expires);
+      if (expires == NULL || expires->hvalue == NULL)
+        {
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                       "eXosip: missing expires header in PUBLISH!"));
+          osip_message_free (message);
+          return -1;
+      } else
+        {
+          /* start a new publication context */
+          _eXosip_pub_init (&pub, to, expires->hvalue);
+          if (pub == NULL)
+	    {
+	      osip_message_free (message);
+	      return -1;
+	    }
+          ADD_ELEMENT (eXosip.j_pub, pub);
+        }
+  } else
+    {
+      if (pub->p_sip_etag != NULL && pub->p_sip_etag[0] != '\0')
+        {
+          /* increase cseq */
+          osip_message_set_header (message, "SIP-If-Match", pub->p_sip_etag);
+        }
+
+      if (pub->p_last_tr != NULL && pub->p_last_tr->cseq != NULL
+          && pub->p_last_tr->cseq->number != NULL)
+        {
+          int osip_cseq_num = osip_atoi (pub->p_last_tr->cseq->number);
+          int length = strlen (pub->p_last_tr->cseq->number);
+
+          osip_cseq_num++;
+          osip_free (message->cseq->number);
+          message->cseq->number = (char *) osip_malloc (length + 2);    /* +2 like for 9 to 10 */
+          sprintf (message->cseq->number, "%i", osip_cseq_num);
+        }
+    }
+
+  i = osip_transaction_init (&transaction, NICT, eXosip.j_osip, message);
+  if (i != 0)
+    {
+      osip_message_free (message);
+      return -1;
+    }
+
+  if (pub->p_last_tr != NULL)
+    osip_list_add (eXosip.j_transactions, pub->p_last_tr, 0);
+  pub->p_last_tr = transaction;
+
+  sipevent = osip_new_outgoing_sipmessage (message);
+  sipevent->transactionid = transaction->transactionid;
+
+  osip_transaction_set_your_instance (transaction,
+                                      __eXosip_new_jinfo (NULL, NULL, NULL, NULL));
+  osip_transaction_add_event (transaction, sipevent);
+  __eXosip_wakeup ();
+  return 0;
+}
diff --git a/exosip2/eXrefer_api.c b/exosip2/eXrefer_api.c
new file mode 100644
index 0000000000..9b6a2ec5a6
--- /dev/null
+++ b/exosip2/eXrefer_api.c
@@ -0,0 +1,74 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002,2003,2004,2005  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+#include "eXosip2.h"
+#include <eXosip2/eXosip.h>
+
+extern eXosip_t eXosip;
+
+int
+eXosip_refer_build_request (osip_message_t ** refer, const char *refer_to,
+                            const char *from, const char *to, const char *proxy)
+{
+  int i;
+
+  *refer = NULL;
+  i = generating_request_out_of_dialog (refer, "REFER", to, "UDP", from, proxy);
+  if (i != 0)
+    {
+      return -1;
+    }
+
+  osip_message_set_header (*refer, "Refer-to", refer_to);
+  return 0;
+}
+
+int
+eXosip_refer_send_request (osip_message_t * refer)
+{
+  osip_transaction_t *transaction;
+  osip_event_t *sipevent;
+  int i;
+
+  if (refer == NULL)
+    return -1;
+
+  i = osip_transaction_init (&transaction, NICT, eXosip.j_osip, refer);
+  if (i != 0)
+    {
+      osip_message_free (refer);
+      return -1;
+    }
+
+  osip_list_add (eXosip.j_transactions, transaction, 0);
+
+  sipevent = osip_new_outgoing_sipmessage (refer);
+  sipevent->transactionid = transaction->transactionid;
+
+  osip_transaction_set_your_instance (transaction,
+                                      __eXosip_new_jinfo (NULL, NULL, NULL, NULL));
+  osip_transaction_add_event (transaction, sipevent);
+  __eXosip_wakeup ();
+  return 0;
+}
diff --git a/exosip2/eXregister_api.c b/exosip2/eXregister_api.c
new file mode 100644
index 0000000000..23f61f240e
--- /dev/null
+++ b/exosip2/eXregister_api.c
@@ -0,0 +1,376 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002,2003,2004,2005  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+
+#include "eXosip2.h"
+
+extern eXosip_t eXosip;
+
+static int _eXosip_register_build_register (eXosip_reg_t * jr,
+                                            osip_message_t ** _reg);
+
+static eXosip_reg_t *
+eXosip_reg_find (int rid)
+{
+  eXosip_reg_t *jr;
+
+  for (jr = eXosip.j_reg; jr != NULL; jr = jr->next)
+    {
+      if (jr->r_id == rid)
+        {
+          return jr;
+        }
+    }
+  return NULL;
+}
+
+
+static int
+_eXosip_register_build_register (eXosip_reg_t * jr, osip_message_t ** _reg)
+{
+  osip_message_t *reg=NULL;
+  struct eXosip_net *net;
+  int i;
+
+  reg = NULL;
+  *_reg = NULL;
+
+  if (jr->r_last_tr != NULL)
+    {
+      if (jr->r_last_tr->state != NICT_TERMINATED
+          && jr->r_last_tr->state != NICT_COMPLETED)
+        return -1;
+      else
+        {
+          osip_message_t *last_response=NULL;
+	  osip_transaction_t *tr;
+	  osip_message_clone(jr->r_last_tr->orig_request, &reg);
+	  if (reg==NULL)
+	    return -1;
+          /* reg = jr->r_last_tr->orig_request; */
+	  if (jr->r_last_tr->last_response!=NULL)
+	    {
+	      osip_message_clone(jr->r_last_tr->last_response, &last_response);
+	      if (last_response==NULL)
+		{
+		  osip_message_free(reg);
+		  return -1;
+		}
+	    }
+
+	  __eXosip_delete_jinfo (jr->r_last_tr);
+	  tr = jr->r_last_tr;
+	  jr->r_last_tr = NULL;
+	  osip_list_add (eXosip.j_transactions, tr, 0);
+
+          /* modify the REGISTER request */
+          {
+            int osip_cseq_num = osip_atoi (reg->cseq->number);
+            int length = strlen (reg->cseq->number);
+
+
+            osip_authorization_t *aut;
+            osip_proxy_authorization_t *proxy_aut;
+
+            aut = (osip_authorization_t *) osip_list_get (reg->authorizations, 0);
+            while (aut != NULL)
+              {
+                osip_list_remove (reg->authorizations, 0);
+                osip_authorization_free (aut);
+                aut =
+                  (osip_authorization_t *) osip_list_get (reg->authorizations, 0);
+              }
+
+            proxy_aut =
+              (osip_proxy_authorization_t *) osip_list_get (reg->
+                                                            proxy_authorizations,
+                                                            0);
+            while (proxy_aut != NULL)
+              {
+                osip_list_remove (reg->proxy_authorizations, 0);
+                osip_proxy_authorization_free (proxy_aut);
+                proxy_aut =
+                  (osip_proxy_authorization_t *) osip_list_get (reg->
+                                                                proxy_authorizations,
+                                                                0);
+              }
+
+            if (0==osip_strcasecmp(jr->transport, "udp"))
+              net = &eXosip.net_interfaces[0];
+            else if (0==osip_strcasecmp(jr->transport, "tcp"))
+              net = &eXosip.net_interfaces[1];
+            else
+              {
+                OSIP_TRACE (osip_trace
+                            (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                             "eXosip: unsupported protocol '%s' (default to UDP)\n",
+                             jr->transport));
+                net = &eXosip.net_interfaces[0];
+              }
+
+	    /*
+	      modify the port number when masquerading is ON.
+	    */
+	    if (net->net_firewall_ip[0]!='\0')
+	      {
+		int pos=0;
+		while (!osip_list_eol(reg->contacts,pos))
+		  {
+		    osip_contact_t *co;
+		    co = (osip_contact_t *)osip_list_get(reg->contacts,pos);
+		    pos++;
+		    if (co!=NULL && co->url!=NULL && co->url->host!=NULL
+			&& 0==osip_strcasecmp(co->url->host,
+					      net->net_firewall_ip))
+		      {
+			if (co->url->port==NULL &&
+			    0!=osip_strcasecmp(net->net_port, "5060"))
+			  {
+			    co->url->port=osip_strdup(net->net_port);
+			  }
+			else if (co->url->port!=NULL &&
+				 0!=osip_strcasecmp(net->net_port, co->url->port))
+			  {
+			    osip_free(co->url->port);
+			    co->url->port=osip_strdup(net->net_port);
+			  }
+		      }
+		  }
+	      }
+
+	    if (-1 == eXosip_update_top_via (reg))
+	      {
+		osip_message_free (reg);
+		if (last_response != NULL)
+		  osip_message_free (last_response);
+                return -1;
+              }
+
+            osip_cseq_num++;
+            osip_free (reg->cseq->number);
+            reg->cseq->number = (char *) osip_malloc (length + 2);      /* +2 like for 9 to 10 */
+            sprintf (reg->cseq->number, "%i", osip_cseq_num);
+
+            {
+              osip_header_t *exp;
+
+              osip_message_header_get_byname (reg, "expires", 0, &exp);
+              osip_free (exp->hvalue);
+              exp->hvalue = (char *) osip_malloc (10);
+              snprintf (exp->hvalue, 9, "%i", jr->r_reg_period);
+            }
+
+            osip_message_force_update (reg);
+          }
+
+          if (last_response != NULL)
+            {
+              if (MSG_IS_STATUS_4XX (last_response))
+                {
+                  eXosip_add_authentication_information (reg, last_response);
+                }
+              osip_message_free (last_response);
+            }
+        }
+    }
+  if (reg == NULL)
+    {
+      i = generating_register (&reg, jr->transport,
+			       jr->r_aor, jr->r_registrar, jr->r_contact,
+			       jr->r_reg_period);
+      if (i != 0)
+        {
+          return -2;
+        }
+    }
+
+  *_reg = reg;
+  return 0;
+}
+
+int
+eXosip_register_build_initial_register (const char *from, const char *proxy,
+                                        const char *contact, int expires,
+                                        osip_message_t ** reg)
+{
+  eXosip_reg_t *jr = NULL;
+  int i;
+
+  *reg = NULL;
+
+  if (eXosip.net_interfaces[0].net_socket<=0
+      && eXosip.net_interfaces[1].net_socket<=0
+      && eXosip.net_interfaces[2].net_socket<=0)
+    return -1;
+
+  /* Avoid adding the same registration info twice to prevent mem leaks */
+  for (jr = eXosip.j_reg; jr != NULL; jr = jr->next)
+    {
+      if (strcmp (jr->r_aor, from) == 0 && strcmp (jr->r_registrar, proxy) == 0)
+        {
+          break;
+        }
+    }
+  if (jr == NULL)
+    {
+      /* Add new registration info */
+      i = eXosip_reg_init (&jr, from, proxy, contact);
+      if (i != 0)
+        {
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                       "eXosip: cannot register! "));
+          return i;
+        }
+      ADD_ELEMENT (eXosip.j_reg, jr);
+    }
+
+  /* Guess transport from existing connections */
+  if (eXosip.net_interfaces[0].net_socket>0)
+    osip_strncpy(jr->transport, "UDP", sizeof(jr->transport)-1);
+  else if (eXosip.net_interfaces[1].net_socket>0)
+    osip_strncpy(jr->transport, "TCP", sizeof(jr->transport)-1);
+  else if (eXosip.net_interfaces[2].net_socket>0)
+    osip_strncpy(jr->transport, "TLS", sizeof(jr->transport)-1);
+
+  /* build register */
+  jr->r_reg_period = expires;
+
+  i = _eXosip_register_build_register (jr, reg);
+  if (i != 0)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: cannot build REGISTER!"));
+      *reg = NULL;
+      return i;
+    }
+  return jr->r_id;
+}
+
+int
+eXosip_register_build_register (int rid, int expires, osip_message_t ** reg)
+{
+  eXosip_reg_t *jr;
+  int i;
+
+  *reg = NULL;
+  jr = eXosip_reg_find (rid);
+  if (jr == NULL)
+    {
+      /* fprintf(stderr, "eXosip: no registration info saved!\n"); */
+      return -1;
+    }
+  jr->r_reg_period = expires;
+  if (jr->r_reg_period == 0)
+    {
+    } /* unregistration */
+  else if (jr->r_reg_period > 3600)
+    jr->r_reg_period = 3600;
+  else if (jr->r_reg_period < 200)      /* too low */
+    jr->r_reg_period = 200;
+
+  if (jr->r_last_tr != NULL)
+    {
+      if (jr->r_last_tr->state != NICT_TERMINATED
+          && jr->r_last_tr->state != NICT_COMPLETED)
+        {
+          /* fprintf(stderr, "eXosip: a registration is already pending!\n"); */
+          return -1;
+        }
+    }
+
+  i = _eXosip_register_build_register (jr, reg);
+  if (i != 0)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: cannot build REGISTER!"));
+      *reg = NULL;
+      return i;
+    }
+  return 0;
+}
+
+int
+eXosip_register_send_register (int rid, osip_message_t * reg)
+{
+  osip_transaction_t *transaction;
+  osip_event_t *sipevent;
+  eXosip_reg_t *jr;
+  char *transport;
+  int i;
+
+  jr = eXosip_reg_find (rid);
+  if (jr == NULL)
+    {
+      osip_message_free (reg);
+      return -1;
+    }
+
+  if (jr->r_last_tr != NULL)
+    {
+      if (jr->r_last_tr->state != NICT_TERMINATED
+          && jr->r_last_tr->state != NICT_COMPLETED)
+        {
+          osip_message_free (reg);
+          return -1;
+        }
+    }
+
+  if (reg == NULL)
+    {
+      i = _eXosip_register_build_register (jr, &reg);
+      if (i != 0)
+        {
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                       "eXosip: cannot build REGISTER!"));
+          return i;
+        }
+    }
+
+  transport = _eXosip_transport_protocol(reg);
+  osip_strncpy(jr->transport, transport, sizeof(jr->transport)-1);
+
+  i = osip_transaction_init (&transaction, NICT, eXosip.j_osip, reg);
+  if (i != 0)
+    {
+      /* TODO: release the j_call.. */
+
+      osip_message_free (reg);
+      return -2;
+    }
+
+  jr->r_last_tr = transaction;
+
+  /* send REGISTER */
+  sipevent = osip_new_outgoing_sipmessage (reg);
+  sipevent->transactionid = transaction->transactionid;
+  osip_message_force_update (reg);
+
+  osip_transaction_add_event (transaction, sipevent);
+  __eXosip_wakeup ();
+  return 0;
+}
diff --git a/exosip2/eXsubscription_api.c b/exosip2/eXsubscription_api.c
new file mode 100644
index 0000000000..84c25f2880
--- /dev/null
+++ b/exosip2/eXsubscription_api.c
@@ -0,0 +1,372 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002,2003,2004,2005  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+
+#include "eXosip2.h"
+
+extern eXosip_t eXosip;
+
+int
+eXosip_subscribe_build_initial_request (osip_message_t ** sub, const char *to,
+                                        const char *from, const char *route,
+                                        const char *event, int expires)
+{
+  char tmp[10];
+  int i;
+  osip_uri_param_t *uri_param = NULL;
+  osip_to_t *_to=NULL;
+
+  *sub = NULL;
+  if (to != NULL && *to == '\0')
+    return -1;
+  if (from != NULL && *from == '\0')
+    return -1;
+  if (event != NULL && *event == '\0')
+    return -1;
+  if (route != NULL && *route == '\0')
+    route = NULL;
+
+  i = osip_to_init(&_to);
+  if (i!=0)
+    return -1;
+  
+  i = osip_to_parse(_to, to);
+  if (i!=0)
+    {
+      osip_to_free(_to);
+      return -1;
+    }
+
+  osip_uri_uparam_get_byname(_to->url, "transport", &uri_param);
+  if (uri_param != NULL && uri_param->gvalue != NULL)
+    {
+      i = generating_request_out_of_dialog (sub, "SUBSCRIBE", to, "UDP", from, route);
+    }
+  else
+    {
+      if (eXosip.net_interfaces[0].net_socket>0)
+	i = generating_request_out_of_dialog (sub, "SUBSCRIBE", to, "UDP", from, route);
+      else if (eXosip.net_interfaces[1].net_socket>0)
+	i = generating_request_out_of_dialog (sub, "SUBSCRIBE", to, "TCP", from, route);
+      else
+	i = generating_request_out_of_dialog (sub, "SUBSCRIBE", to, "UDP", from, route);
+    }
+
+  osip_to_free(_to);
+  if (i != 0)
+    return -1;
+
+  snprintf (tmp, 10, "%i", expires);
+  osip_message_set_expires (*sub, tmp);
+
+  osip_message_set_header (*sub, "Event", event);
+
+  return 0;
+}
+
+int
+eXosip_subscribe_send_initial_request (osip_message_t * subscribe)
+{
+  eXosip_subscribe_t *js = NULL;
+  osip_transaction_t *transaction;
+  osip_event_t *sipevent;
+  int i;
+
+  i = eXosip_subscribe_init (&js);
+  if (i != 0)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: cannot subscribe."));
+      osip_message_free (subscribe);
+      return -1;
+    }
+
+  i = osip_transaction_init (&transaction, NICT, eXosip.j_osip, subscribe);
+  if (i != 0)
+    {
+      eXosip_subscribe_free (js);
+      osip_message_free (subscribe);
+      return -1;
+    }
+
+  _eXosip_subscribe_set_refresh_interval (js, subscribe);
+  js->s_out_tr = transaction;
+
+  sipevent = osip_new_outgoing_sipmessage (subscribe);
+  sipevent->transactionid = transaction->transactionid;
+
+  osip_transaction_set_your_instance (transaction,
+                                      __eXosip_new_jinfo (NULL, NULL, js, NULL));
+  osip_transaction_add_event (transaction, sipevent);
+
+  ADD_ELEMENT (eXosip.j_subscribes, js);
+  eXosip_update ();             /* fixed? */
+  __eXosip_wakeup ();
+  return 0;
+}
+
+int
+eXosip_subscribe_build_refresh_request (int did, osip_message_t ** sub)
+{
+  eXosip_dialog_t *jd = NULL;
+  eXosip_subscribe_t *js = NULL;
+
+  osip_transaction_t *transaction;
+  char *transport;
+  int i;
+
+  *sub = NULL;
+  if (did > 0)
+    {
+      eXosip_subscribe_dialog_find (did, &js, &jd);
+    }
+  if (jd == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: No subscribe here?\n"));
+      return -1;
+    }
+
+  transaction = NULL;
+  transaction = eXosip_find_last_out_subscribe (js, jd);
+
+  if (transaction != NULL)
+    {
+      if (transaction->state != NICT_TERMINATED &&
+          transaction->state != NIST_TERMINATED &&
+          transaction->state != NICT_COMPLETED &&
+          transaction->state != NIST_COMPLETED)
+        return -1;
+    }
+
+  transport = NULL;
+  if (transaction!=NULL && transaction->orig_request!=NULL)
+    transport = _eXosip_transport_protocol(transaction->orig_request);
+
+  transaction = NULL;
+
+  if (transport==NULL)
+    i = _eXosip_build_request_within_dialog (sub, "SUBSCRIBE", jd->d_dialog, "UDP");
+  else
+    i = _eXosip_build_request_within_dialog (sub, "SUBSCRIBE", jd->d_dialog, transport);
+
+  if (i != 0)
+    return -2;
+
+  return 0;
+}
+
+int
+eXosip_subscribe_send_refresh_request (int did, osip_message_t * sub)
+{
+  eXosip_dialog_t *jd = NULL;
+  eXosip_subscribe_t *js = NULL;
+
+  osip_transaction_t *transaction;
+  osip_event_t *sipevent;
+  int i;
+
+  if (did > 0)
+    {
+      eXosip_subscribe_dialog_find (did, &js, &jd);
+    }
+  if (jd == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: No subscribe here?\n"));
+      osip_message_free (sub);
+      return -1;
+    }
+
+  transaction = NULL;
+  transaction = eXosip_find_last_out_subscribe (js, jd);
+
+  if (transaction != NULL)
+    {
+      if (transaction->state != NICT_TERMINATED &&
+          transaction->state != NIST_TERMINATED &&
+          transaction->state != NICT_COMPLETED &&
+          transaction->state != NIST_COMPLETED)
+	{
+	  osip_message_free (sub);
+	  return -1;
+	}
+      transaction = NULL;
+    }
+
+  transaction = NULL;
+  i = osip_transaction_init (&transaction, NICT, eXosip.j_osip, sub);
+
+  if (i != 0)
+    {
+      osip_message_free (sub);
+      return -2;
+    }
+
+  _eXosip_subscribe_set_refresh_interval (js, sub);
+  osip_list_add (jd->d_out_trs, transaction, 0);
+
+  sipevent = osip_new_outgoing_sipmessage (sub);
+  sipevent->transactionid = transaction->transactionid;
+
+  osip_transaction_set_your_instance (transaction,
+                                      __eXosip_new_jinfo (NULL, jd, js, NULL));
+  osip_transaction_add_event (transaction, sipevent);
+  __eXosip_wakeup ();
+  return 0;
+}
+
+int
+_eXosip_subscribe_send_request_with_credential (eXosip_subscribe_t * js,
+                                                eXosip_dialog_t * jd,
+                                                osip_transaction_t * out_tr)
+{
+  osip_transaction_t *tr = NULL;
+  osip_message_t *msg = NULL;
+  osip_event_t *sipevent;
+
+  char locip[256];
+  int cseq;
+  char tmp[256];
+  osip_via_t *via;
+  int i;
+
+  if (js == NULL)
+    return -1;
+  if (jd != NULL)
+    {
+      if (jd->d_out_trs == NULL)
+        return -1;
+    }
+
+  if (out_tr == NULL)
+    {
+      out_tr = eXosip_find_last_out_subscribe (js, jd);
+    }
+
+  if (out_tr == NULL
+      || out_tr->orig_request == NULL || out_tr->last_response == NULL)
+    return -1;
+
+  osip_message_clone (out_tr->orig_request, &msg);
+  if (msg == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: could not clone msg for authentication\n"));
+      return -1;
+    }
+
+  via = (osip_via_t *) osip_list_get (msg->vias, 0);
+  if (via == NULL || msg->cseq == NULL || msg->cseq->number == NULL)
+    {
+      osip_message_free (msg);
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: missing via or cseq header\n"));
+      return -1;
+    }
+
+  /* increment cseq */
+  cseq = atoi (msg->cseq->number);
+  osip_free (msg->cseq->number);
+  msg->cseq->number = strdup_printf ("%i", cseq + 1);
+  if (jd != NULL && jd->d_dialog != NULL)
+    {
+      jd->d_dialog->local_cseq++;
+    }
+
+  osip_list_remove (msg->vias, 0);
+  osip_via_free (via);
+  i = _eXosip_find_protocol(out_tr->orig_request);
+  if (i==IPPROTO_UDP)
+    {
+      eXosip_guess_ip_for_via (eXosip.net_interfaces[0].net_ip_family, locip,
+			       sizeof (locip));
+      if (eXosip.net_interfaces[0].net_ip_family == AF_INET6)
+	snprintf (tmp, 256, "SIP/2.0/UDP [%s]:%s;branch=z9hG4bK%u",
+		  locip, eXosip.net_interfaces[0].net_port, via_branch_new_random ());
+      else
+	snprintf (tmp, 256, "SIP/2.0/UDP %s:%s;rport;branch=z9hG4bK%u",
+		  locip, eXosip.net_interfaces[0].net_port, via_branch_new_random ());
+    }
+  else if (i==IPPROTO_TCP)
+    {
+      eXosip_guess_ip_for_via (eXosip.net_interfaces[1].net_ip_family, locip,
+			       sizeof (locip));
+      if (eXosip.net_interfaces[1].net_ip_family == AF_INET6)
+	snprintf (tmp, 256, "SIP/2.0/TCP [%s]:%s;branch=z9hG4bK%u",
+		  locip, eXosip.net_interfaces[1].net_port, via_branch_new_random ());
+      else
+	snprintf (tmp, 256, "SIP/2.0/TCP %s:%s;rport;branch=z9hG4bK%u",
+		  locip, eXosip.net_interfaces[1].net_port, via_branch_new_random ());
+    }
+  else
+    {
+      /* tls? */
+      osip_message_free (msg);
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: unsupported protocol\n"));
+      return -1;
+    }
+
+  osip_via_init (&via);
+  osip_via_parse (via, tmp);
+  osip_list_add (msg->vias, via, 0);
+
+  eXosip_add_authentication_information (msg, out_tr->last_response);
+  osip_message_force_update (msg);
+
+  i = osip_transaction_init (&tr, NICT, eXosip.j_osip, msg);
+
+  if (i != 0)
+    {
+      osip_message_free (msg);
+      return -1;
+    }
+
+  if (out_tr == js->s_out_tr)
+    {
+      /* replace with the new tr */
+      osip_list_add (eXosip.j_transactions, js->s_out_tr, 0);
+      js->s_out_tr = tr;
+  } else
+    {
+      /* add the new tr for the current dialog */
+      osip_list_add (jd->d_out_trs, tr, 0);
+    }
+
+  sipevent = osip_new_outgoing_sipmessage (msg);
+
+  osip_transaction_set_your_instance (tr, __eXosip_new_jinfo (NULL, jd, js, NULL));
+  osip_transaction_add_event (tr, sipevent);
+
+  eXosip_update ();             /* fixed? */
+  __eXosip_wakeup ();
+  return 0;
+}
diff --git a/exosip2/eXtransport.c b/exosip2/eXtransport.c
new file mode 100644
index 0000000000..2624ab8a92
--- /dev/null
+++ b/exosip2/eXtransport.c
@@ -0,0 +1,279 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002,2003,2004,2005  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+
+#include "eXosip2.h"
+
+extern eXosip_t eXosip;
+
+char *_eXosip_transport_protocol(osip_message_t *msg)
+{
+  osip_via_t *via;
+  via = (osip_via_t *) osip_list_get (msg->vias, 0);
+  if (via == NULL || via->protocol == NULL)
+    return NULL;
+  return via->protocol;
+}
+
+int _eXosip_find_protocol(osip_message_t *msg)
+{
+  osip_via_t *via;
+  via = (osip_via_t *) osip_list_get (msg->vias, 0);
+  if (via == NULL || via->protocol == NULL)
+    return -1;
+  else if (0==osip_strcasecmp(via->protocol, "UDP"))
+	return IPPROTO_UDP;
+  else if (0==osip_strcasecmp(via->protocol, "TCP"))
+    return IPPROTO_TCP;
+  return -1;;
+}
+
+int _eXosip_tcp_find_socket(char *host, int port)
+{
+  int pos;
+  struct eXosip_net *net;
+
+  net = &eXosip.net_interfaces[1];
+
+  for (pos=0;pos<EXOSIP_MAX_SOCKETS;pos++)
+    {
+      if (net->net_socket_tab[pos].socket!=0)
+	{
+	  if (0==osip_strcasecmp(net->net_socket_tab[pos].remote_ip, host)
+	      && port == net->net_socket_tab[pos].remote_port)
+	    return net->net_socket_tab[pos].socket;
+	}
+    }
+  return -1;
+}
+
+int _eXosip_tcp_connect_socket(char *host, int port)
+{
+  int pos;
+  struct eXosip_net *net;
+
+  int res;
+  struct addrinfo *addrinfo = NULL;
+  struct addrinfo *curinfo;
+  int sock = -1;
+
+  net = &eXosip.net_interfaces[1];
+
+  for (pos=0;pos<EXOSIP_MAX_SOCKETS;pos++)
+    {
+      if (net->net_socket_tab[pos].socket==0)
+	{
+	  break;
+	}
+    }
+
+  if (pos==EXOSIP_MAX_SOCKETS)
+    return -1;
+
+  res = eXosip_get_addrinfo(&addrinfo, host, port, IPPROTO_TCP);
+  if (res)
+    return -1;
+
+
+  for (curinfo = addrinfo; curinfo; curinfo = curinfo->ai_next)
+    {
+      if (curinfo->ai_protocol && curinfo->ai_protocol != IPPROTO_TCP)
+	{
+	  OSIP_TRACE (osip_trace
+		      (__FILE__, __LINE__, OSIP_INFO2, NULL,
+		       "eXosip: Skipping protocol %d\n",
+		       curinfo->ai_protocol));
+	  continue;
+	}
+
+      sock = (int)socket(curinfo->ai_family, curinfo->ai_socktype,
+			 curinfo->ai_protocol);
+      if (sock < 0)
+	{
+	  OSIP_TRACE (osip_trace
+		      (__FILE__, __LINE__, OSIP_INFO2, NULL,
+		       "eXosip: Cannot create socket!\n",
+		       strerror(errno)));
+	  continue;
+	}
+      
+      if (curinfo->ai_family == AF_INET6)
+	{
+#ifdef IPV6_V6ONLY
+	  if (setsockopt_ipv6only(sock))
+	    {
+	      close(sock);
+	      sock = -1;
+	      OSIP_TRACE (osip_trace
+			  (__FILE__, __LINE__, OSIP_INFO2, NULL,
+			   "eXosip: Cannot set socket option!\n",
+			   strerror(errno)));
+	      continue;
+	    }
+#endif	/* IPV6_V6ONLY */
+	}
+      
+#if 0
+      res = bind (sock, (struct sockaddr*)&net->ai_addr, curinfo->ai_addrlen);
+      if (res < 0)
+	{
+	  OSIP_TRACE (osip_trace
+		      (__FILE__, __LINE__, OSIP_INFO2, NULL,
+		       "eXosip: Cannot bind socket %s\n",
+		       strerror(errno)));
+	  close(sock);
+	  sock = -1;
+	  continue;
+	}
+#endif
+
+      res = connect (sock, curinfo->ai_addr, curinfo->ai_addrlen);
+      if (res < 0)
+	{
+	  OSIP_TRACE (osip_trace
+		      (__FILE__, __LINE__, OSIP_INFO2, NULL,
+		       "eXosip: Cannot bind socket node:%s family:%d %s\n",
+		       host, curinfo->ai_family, strerror(errno)));
+	  close(sock);
+	  sock = -1;
+	  continue;
+	}
+
+      break;
+    }
+
+  freeaddrinfo(addrinfo);
+
+  if (sock>0)
+    {
+      net->net_socket_tab[pos].socket = sock;
+      osip_strncpy(net->net_socket_tab[pos].remote_ip, host,
+		   sizeof(net->net_socket_tab[pos].remote_ip)-1);
+      net->net_socket_tab[pos].remote_port = port;
+      return sock;
+    }
+
+  return -1;
+}
+
+
+int eXosip_transport_set(osip_message_t *msg, const char *transport)
+{
+  osip_via_t *via;
+
+  via = (osip_via_t *) osip_list_get (msg->vias, 0);
+  if (via == NULL || via->protocol == NULL)
+    return -1;
+  
+  if (0==osip_strcasecmp(via->protocol, transport))
+    return 0;
+
+  osip_free(via->protocol);
+  via->protocol = osip_strdup(transport);
+  return 0;
+}
+
+int _eXosip_recvfrom(int s, char *buf, int len, unsigned int flags, struct sockaddr *from, socklen_t *fromlen)
+{
+    int message_size=0;
+    int length_done=0;
+    int real_size=0;
+    int i;
+    int extra_data_discarded;
+
+    if (!eXosip.http_port)
+    {
+        return recvfrom(s, buf, len, flags, from, fromlen);
+    }
+
+
+    /* we get the size of the HTTP data */
+    i = recv (eXosip.net_interfaces[0].net_socket, (char *) &(message_size), 4, 0);
+
+    real_size = message_size;
+    if (message_size<0)
+    {
+        return -1; /* Connection error? */
+    }
+    if (message_size==0)
+    {
+        buf[0]='\0';
+        return 0;
+    }
+    if (message_size>len-1)
+        message_size = len-1;
+
+    length_done=0;
+
+    i = recv (eXosip.net_interfaces[0].net_socket, buf, message_size, 0);
+    length_done = i;
+
+    if (length_done==real_size)
+    {
+        return length_done;
+    }
+
+    if (length_done<message_size)
+    {
+        /* continue reading up to message_size */
+        while (length_done<message_size)
+        {
+            i = recv (eXosip.net_interfaces[0].net_socket, buf+length_done, message_size-length_done, 0);
+            length_done = length_done+i;
+        }
+    }
+
+    extra_data_discarded = length_done;
+    while (extra_data_discarded<real_size)
+    {
+        char buf2[2048];
+        /* We have to discard the end of data... up to the next message */
+        i = recv (eXosip.net_interfaces[0].net_socket, buf2, 2048, 0);
+        extra_data_discarded = extra_data_discarded+i;
+    }
+    return length_done;
+}
+
+int _eXosip_sendto(int s,  const void* buf,  size_t len,  int flags,
+  const struct sockaddr* to,  socklen_t tolen)
+{
+    int i;
+    char buf2[10000];
+
+    if (!eXosip.http_port)
+    {
+       i = sendto(s, buf, len, flags, to, tolen);
+       return i;
+    }
+
+    memset(buf2, '\0', sizeof(buf2));
+    memcpy(buf2, &len, sizeof(int));
+    memcpy(buf2+sizeof(int), buf, len);
+
+    i = send(s, (char *) buf2, len+sizeof(int), 0); /* use TCP connection to proxy */
+    if (i>0)
+        i=i-sizeof(int);
+
+    return i;
+}
\ No newline at end of file
diff --git a/exosip2/eXutils.c b/exosip2/eXutils.c
new file mode 100644
index 0000000000..764209695b
--- /dev/null
+++ b/exosip2/eXutils.c
@@ -0,0 +1,694 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002, 2003  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+#include <osipparser2/osip_port.h>
+#include "eXosip2.h"
+
+extern eXosip_t eXosip;
+
+#ifdef WIN32
+
+/* You need the Platform SDK to compile this. */
+#include <Windows.h>
+#include <Iphlpapi.h>
+
+int
+ppl_dns_get_local_fqdn (char **servername, char **serverip,
+                        char **netmask, unsigned int WIN32_interface)
+{
+  unsigned int pos;
+
+  *servername = NULL;           /* no name on win32? */
+  *serverip = NULL;
+  *netmask = NULL;
+
+  /* First, try to get the interface where we should listen */
+  {
+    DWORD size_of_iptable = 0;
+    PMIB_IPADDRTABLE ipt;
+    PMIB_IFROW ifrow;
+
+    if (GetIpAddrTable (NULL, &size_of_iptable, TRUE) == ERROR_INSUFFICIENT_BUFFER)
+      {
+        ifrow = (PMIB_IFROW) _alloca (sizeof (MIB_IFROW));
+        ipt = (PMIB_IPADDRTABLE) _alloca (size_of_iptable);
+        if (ifrow == NULL || ipt == NULL)
+          {
+            /* not very usefull to continue */
+            OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO4, NULL,
+                                    "ERROR alloca failed\r\n"));
+            return -1;
+          }
+
+        if (!GetIpAddrTable (ipt, &size_of_iptable, TRUE))
+          {
+            /* look for the best public interface */
+
+            for (pos = 0; pos < ipt->dwNumEntries && *netmask == NULL; ++pos)
+              {
+                /* index is */
+                struct in_addr addr;
+                struct in_addr mask;
+
+                ifrow->dwIndex = ipt->table[pos].dwIndex;
+                if (GetIfEntry (ifrow) == NO_ERROR)
+                  {
+                    switch (ifrow->dwType)
+                      {
+                        case MIB_IF_TYPE_LOOPBACK:
+                          /*    break; */
+                        case MIB_IF_TYPE_ETHERNET:
+                        default:
+                          addr.s_addr = ipt->table[pos].dwAddr;
+                          mask.s_addr = ipt->table[pos].dwMask;
+                          if (ipt->table[pos].dwIndex == WIN32_interface)
+                            {
+                              *servername = NULL;       /* no name on win32? */
+                              *serverip = osip_strdup (inet_ntoa (addr));
+                              *netmask = osip_strdup (inet_ntoa (mask));
+                              OSIP_TRACE (osip_trace
+                                          (__FILE__, __LINE__, OSIP_INFO4, NULL,
+                                           "Interface ethernet: %s/%s\r\n",
+                                           *serverip, *netmask));
+                              break;
+                            }
+                      }
+                  }
+              }
+          }
+      }
+  }
+
+  if (*serverip == NULL || *netmask == NULL)
+    {
+      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL,
+                              "ERROR No network interface found\r\n"));
+      return -1;
+    }
+
+  return 0;
+}
+
+int
+eXosip_guess_ip_for_via (int family, char *address, int size)
+{
+  /* w2000 and W95/98 */
+  unsigned long best_interface_index;
+  DWORD hr;
+
+  /* NT4 (sp4 only?) */
+  PMIB_IPFORWARDTABLE ipfwdt;
+  DWORD siz_ipfwd_table = 0;
+  unsigned int ipf_cnt;
+
+  address[0] = '\0';
+  best_interface_index = -1;
+  /* w2000 and W95/98 only */
+
+  hr = GetBestInterface (inet_addr ("217.12.3.11"), &best_interface_index);
+  if (hr)
+    {
+      LPVOID lpMsgBuf;
+
+      FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                     FORMAT_MESSAGE_FROM_SYSTEM |
+                     FORMAT_MESSAGE_IGNORE_INSERTS,
+                     NULL,
+                     hr,
+                     MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+                     (LPSTR) & lpMsgBuf, 0, NULL);
+
+      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO4, NULL,
+                              "GetBestInterface: %s\r\n", lpMsgBuf));
+      best_interface_index = -1;
+    }
+
+  if (best_interface_index != -1)
+    {                           /* probably W2000 or W95/W98 */
+      char *servername;
+      char *serverip;
+      char *netmask;
+
+      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO4, NULL,
+                              "Default Interface found %i\r\n",
+                              best_interface_index));
+
+      if (0 == ppl_dns_get_local_fqdn (&servername, &serverip, &netmask,
+                                       best_interface_index))
+        {
+          osip_strncpy (address, serverip, size - 1);
+          osip_free (servername);
+          osip_free (serverip);
+          osip_free (netmask);
+          return 0;
+        }
+      return -1;
+    }
+
+
+  if (!GetIpForwardTable (NULL, &siz_ipfwd_table, FALSE) ==
+      ERROR_INSUFFICIENT_BUFFER
+      || !(ipfwdt = (PMIB_IPFORWARDTABLE) alloca (siz_ipfwd_table)))
+    {
+      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO4, NULL,
+                              "Allocation error\r\n"));
+      return -1;
+    }
+
+
+  /* NT4 (sp4 support only?) */
+  if (!GetIpForwardTable (ipfwdt, &siz_ipfwd_table, FALSE))
+    {
+      for (ipf_cnt = 0; ipf_cnt < ipfwdt->dwNumEntries; ++ipf_cnt)
+        {
+          if (ipfwdt->table[ipf_cnt].dwForwardDest == 0)
+            {                   /* default gateway found */
+              char *servername;
+              char *serverip;
+              char *netmask;
+
+              OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO4, NULL,
+                                      "Default Interface found %i\r\n",
+                                      ipfwdt->table[ipf_cnt].dwForwardIfIndex));
+
+              if (0 == ppl_dns_get_local_fqdn (&servername,
+                                               &serverip,
+                                               &netmask,
+                                               ipfwdt->table[ipf_cnt].
+                                               dwForwardIfIndex))
+                {
+                  osip_strncpy (address, serverip, size);
+                  osip_free (servername);
+                  osip_free (serverip);
+                  osip_free (netmask);
+                  return 0;
+                }
+              return -1;
+            }
+        }
+
+    }
+
+    OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL,
+                            "Please define a default network interface.\r\n"));
+#ifdef WANT_INTERFACE_ANYWAY
+
+
+  /* NT4 (sp4 support only?) */
+  if (!GetIpForwardTable (ipfwdt, &siz_ipfwd_table, FALSE))
+    {
+      for (ipf_cnt = 0; ipf_cnt < ipfwdt->dwNumEntries; ++ipf_cnt)
+        {
+            char *servername;
+            char *serverip;
+            char *netmask;
+
+            OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO4, NULL,
+                                    "Default Interface found %i\r\n",
+                                    ipfwdt->table[ipf_cnt].dwForwardIfIndex));
+
+            if (0 == ppl_dns_get_local_fqdn (&servername,
+                                            &serverip,
+                                            &netmask,
+                                            ipfwdt->table[ipf_cnt].
+                                            dwForwardIfIndex))
+            {
+                /* search for public */
+                if (eXosip_is_public_address(serverip) == 0)
+                {
+                    osip_strncpy (address, serverip, size);
+                    osip_free (servername);
+                    osip_free (serverip);
+                    osip_free (netmask);
+                    return 0;
+                }
+                osip_free (servername);
+                osip_free (serverip);
+                osip_free (netmask);
+            }
+        }
+    }
+
+    OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                            "No public interface found. searching private\r\n"));
+
+  /* NT4 (sp4 support only?) */
+  if (!GetIpForwardTable (ipfwdt, &siz_ipfwd_table, FALSE))
+    {
+      for (ipf_cnt = 0; ipf_cnt < ipfwdt->dwNumEntries; ++ipf_cnt)
+        {
+            char *servername;
+            char *serverip;
+            char *netmask;
+
+            OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO4, NULL,
+                                    "Default Interface found %i\r\n",
+                                    ipfwdt->table[ipf_cnt].dwForwardIfIndex));
+
+            if (0 == ppl_dns_get_local_fqdn (&servername,
+                                            &serverip,
+                                            &netmask,
+                                            ipfwdt->table[ipf_cnt].
+                                            dwForwardIfIndex))
+            {
+                osip_strncpy (address, serverip, size);
+                osip_free (servername);
+                osip_free (serverip);
+                osip_free (netmask);
+                return 0;
+            }
+        }
+    }
+
+  {
+      char *lo = osip_strdup("127.0.0.1");
+      osip_strncpy (address, lo, size);
+      osip_free(lo);
+      return 0;
+  }
+
+    OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                            "No interface found. returning 127.0.0.1\r\n"));
+  /* no default gateway interface found */
+  return 0;
+#else
+  return -1;
+#endif /* WANT_INTERFACE_ANYWAY */
+}
+
+
+#else /* sun, *BSD, linux, and other? */
+
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <unistd.h>
+#include <sys/param.h>
+
+#include <stdio.h>
+
+static int ppl_dns_default_gateway_ipv4 (char *address, int size);
+static int ppl_dns_default_gateway_ipv6 (char *address, int size);
+
+
+int
+eXosip_guess_ip_for_via (int familiy, char *address, int size)
+{
+  if (familiy == AF_INET6)
+    {
+      return ppl_dns_default_gateway_ipv6 (address, size);
+  } else
+    {
+      return ppl_dns_default_gateway_ipv4 (address, size);
+    }
+}
+
+/* This is a portable way to find the default gateway.
+ * The ip of the default interface is returned.
+ */
+static int
+ppl_dns_default_gateway_ipv4 (char *address, int size)
+{
+#ifdef __APPLE_CC__
+  int len;
+#else
+  unsigned int len;
+#endif
+  int sock_rt, on = 1;
+  struct sockaddr_in iface_out;
+  struct sockaddr_in remote;
+
+  memset (&remote, 0, sizeof (struct sockaddr_in));
+
+  remote.sin_family = AF_INET;
+  remote.sin_addr.s_addr = inet_addr ("217.12.3.11");
+  remote.sin_port = htons (11111);
+
+  memset (&iface_out, 0, sizeof (iface_out));
+  sock_rt = socket (AF_INET, SOCK_DGRAM, 0);
+
+  if (setsockopt (sock_rt, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) == -1)
+    {
+      perror ("DEBUG: [get_output_if] setsockopt(SOL_SOCKET, SO_BROADCAST");
+      close (sock_rt);
+      return -1;
+    }
+
+  if (connect
+      (sock_rt, (struct sockaddr *) &remote, sizeof (struct sockaddr_in)) == -1)
+    {
+      perror ("DEBUG: [get_output_if] connect");
+      close (sock_rt);
+      return -1;
+    }
+
+  len = sizeof (iface_out);
+  if (getsockname (sock_rt, (struct sockaddr *) &iface_out, &len) == -1)
+    {
+      perror ("DEBUG: [get_output_if] getsockname");
+      close (sock_rt);
+      return -1;
+    }
+
+  close (sock_rt);
+  if (iface_out.sin_addr.s_addr == 0)
+    {                           /* what is this case?? */
+      return -1;
+    }
+  osip_strncpy (address, inet_ntoa (iface_out.sin_addr), size - 1);
+  return 0;
+}
+
+
+/* This is a portable way to find the default gateway.
+ * The ip of the default interface is returned.
+ */
+static int
+ppl_dns_default_gateway_ipv6 (char *address, int size)
+{
+#ifdef __APPLE_CC__
+  int len;
+#else
+  unsigned int len;
+#endif
+  int sock_rt, on = 1;
+  struct sockaddr_in6 iface_out;
+  struct sockaddr_in6 remote;
+
+  memset (&remote, 0, sizeof (struct sockaddr_in6));
+
+  remote.sin6_family = AF_INET6;
+  inet_pton (AF_INET6, "2001:638:500:101:2e0:81ff:fe24:37c6", &remote.sin6_addr);
+  remote.sin6_port = htons (11111);
+
+  memset (&iface_out, 0, sizeof (iface_out));
+  sock_rt = socket (AF_INET6, SOCK_DGRAM, 0);
+
+  if (setsockopt (sock_rt, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) == -1)
+    {
+      perror ("DEBUG: [get_output_if] setsockopt(SOL_SOCKET, SO_BROADCAST");
+      close (sock_rt);
+      return -1;
+    }
+
+  if (connect
+      (sock_rt, (struct sockaddr *) &remote, sizeof (struct sockaddr_in6)) == -1)
+    {
+      perror ("DEBUG: [get_output_if] connect");
+      close (sock_rt);
+      return -1;
+    }
+
+  len = sizeof (iface_out);
+  if (getsockname (sock_rt, (struct sockaddr *) &iface_out, &len) == -1)
+    {
+      perror ("DEBUG: [get_output_if] getsockname");
+      close (sock_rt);
+      return -1;
+    }
+  close (sock_rt);
+
+  if (iface_out.sin6_addr.s6_addr == 0)
+    {                           /* what is this case?? */
+      return -1;
+    }
+  inet_ntop (AF_INET6, (const void *) &iface_out.sin6_addr, address, size - 1);
+  return 0;
+}
+
+#endif
+
+int
+eXosip_get_localip_for (const char *address_to_reach, char *loc, int size)
+{
+  int err, tmp;
+  struct addrinfo hints;
+  struct addrinfo *res = NULL;
+  struct sockaddr_storage addr;
+  int sock;
+
+#ifdef __APPLE_CC__
+  int s;
+#else
+  socklen_t s;
+#endif
+#ifdef MAXHOSTNAMELEN
+  if (size > MAXHOSTNAMELEN)
+    size = MAXHOSTNAMELEN;
+#else
+  if (size > 256)
+      size = 256;
+#endif
+  if (eXosip.forced_localip)
+    {
+      if (size > sizeof (eXosip.net_interfaces[0].net_firewall_ip))
+        size = sizeof (eXosip.net_interfaces[0].net_firewall_ip);
+      strncpy (loc, eXosip.net_interfaces[0].net_firewall_ip, size);
+      return 0;
+    }
+
+  strcpy (loc, "127.0.0.1");    /* always fallback to local loopback */
+
+  memset (&hints, 0, sizeof (hints));
+  hints.ai_family = PF_UNSPEC;
+  hints.ai_socktype = SOCK_DGRAM;
+  /*hints.ai_flags=AI_NUMERICHOST|AI_CANONNAME; */
+  err = getaddrinfo (address_to_reach, "5060", &hints, &res);
+  if (err != 0)
+    {
+      eXosip_trace (OSIP_ERROR,
+                    ("Error in getaddrinfo for %s: %s\n", address_to_reach,
+                     gai_strerror (err)));
+      return -1;
+    }
+  if (res == NULL)
+    {
+      eXosip_trace (OSIP_ERROR, ("getaddrinfo reported nothing !"));
+      return -1;
+    }
+  sock = socket (res->ai_family, SOCK_DGRAM, 0);
+  tmp = 1;
+  err = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&tmp, sizeof (int));
+  if (err < 0)
+    {
+      eXosip_trace (OSIP_ERROR, ("Error in setsockopt: %s\n", strerror (errno)));
+      return -1;
+    }
+  err = connect (sock, res->ai_addr, res->ai_addrlen);
+  if (err < 0)
+    {
+      eXosip_trace (OSIP_ERROR, ("Error in connect: %s\n", strerror (errno)));
+      freeaddrinfo (res);
+      close (sock);
+      return -1;
+    }
+  freeaddrinfo (res);
+  res = NULL;
+  s = sizeof (addr);
+  err = getsockname (sock, (struct sockaddr *) &addr, &s);
+  if (err != 0)
+    {
+      eXosip_trace (OSIP_ERROR, ("Error in getsockname: %s\n", strerror (errno)));
+      close (sock);
+      return -1;
+    }
+
+  err =
+    getnameinfo ((struct sockaddr *) &addr, s, loc, size, NULL, 0, NI_NUMERICHOST);
+  if (err != 0)
+    {
+      eXosip_trace (OSIP_ERROR, ("getnameinfo error:%s", strerror (errno)));
+      return -1;
+    }
+  close (sock);
+  eXosip_trace (OSIP_INFO1,
+                ("Outgoing interface to reach %s is %s.\n", address_to_reach,
+                 loc));
+  return 0;
+}
+
+
+#ifdef SM
+
+void
+eXosip_get_localip_from_via (osip_message_t * mesg, char *locip, int size)
+{
+  osip_via_t *via = NULL;
+  char *host;
+
+  via = (osip_via_t *) osip_list_get (mesg->vias, 0);
+  if (via == NULL)
+    {
+      host = "15.128.128.93";
+      eXosip_trace (OSIP_ERROR, ("Could not get via:%s"));
+  } else
+    host = via->host;
+  eXosip_get_localip_for (host, locip, size);
+
+}
+#endif
+
+char *
+strdup_printf (const char *fmt, ...)
+{
+  /* Guess we need no more than 100 bytes. */
+  int n, size = 100;
+  char *p;
+  va_list ap;
+
+  if ((p = osip_malloc (size)) == NULL)
+    return NULL;
+  while (1)
+    {
+      /* Try to print in the allocated space. */
+      va_start (ap, fmt);
+#ifdef WIN32
+      n = _vsnprintf (p, size, fmt, ap);
+#else
+      n = vsnprintf (p, size, fmt, ap);
+#endif
+      va_end (ap);
+      /* If that worked, return the string. */
+      if (n > -1 && n < size)
+        return p;
+      /* Else try again with more space. */
+      if (n > -1)               /* glibc 2.1 */
+        size = n + 1;           /* precisely what is needed */
+      else                      /* glibc 2.0 */
+        size *= 2;              /* twice the old size */
+      if ((p = realloc (p, size)) == NULL)
+        return NULL;
+    }
+}
+
+int
+eXosip_get_addrinfo (struct addrinfo **addrinfo, const char *hostname,
+		     int service, int protocol)
+{
+#ifndef WIN32
+  struct in_addr addr;
+  struct in6_addr addrv6;
+#else
+  unsigned long int one_inet_addr;
+#endif
+  struct addrinfo hints;
+  int error;
+  char portbuf[10];
+
+  if (hostname==NULL)
+    return -1;
+
+  if (service != -1) /* -1 for SRV record */
+    snprintf (portbuf, sizeof (portbuf), "%i", service);
+
+  memset (&hints, 0, sizeof (hints));
+#ifndef WIN32
+  if (inet_pton (AF_INET, hostname, &addr) > 0)
+    {
+      /* ipv4 address detected */
+      hints.ai_flags = AI_NUMERICHOST;
+      hints.ai_family = PF_INET;
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                   "IPv4 address detected: %s\n", hostname));
+  } else if (inet_pton (AF_INET6, hostname, &addrv6) > 0)
+    {
+      /* ipv6 address detected */
+      /* Do the resolution anyway */
+      hints.ai_flags = AI_CANONNAME;
+      hints.ai_family = PF_INET6;
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                   "IPv6 address detected: %s\n", hostname));
+  } else
+    {
+      /* hostname must be resolved */
+      hints.ai_flags = AI_CANONNAME;
+      if (protocol==IPPROTO_UDP)
+	hints.ai_family = (eXosip.net_interfaces[0].net_ip_family == AF_INET) ? PF_INET : PF_INET6;
+      else if (protocol==IPPROTO_TCP)
+	hints.ai_family = (eXosip.net_interfaces[1].net_ip_family == AF_INET) ? PF_INET : PF_INET6;
+      else
+	{
+	  hints.ai_family = (eXosip.net_interfaces[0].net_ip_family == AF_INET) ? PF_INET : PF_INET6;
+	  OSIP_TRACE (osip_trace
+		      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+		       "eXosip: unsupported protocol (default to UDP)\n"));
+	}
+
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                   "Not an IPv4 or IPv6 address: %s\n", hostname));
+    }
+#else
+  if ((int) (one_inet_addr = inet_addr (hostname)) == -1)
+    hints.ai_flags = AI_CANONNAME;
+  else
+    hints.ai_flags = AI_NUMERICHOST;
+
+#ifdef IPV6_SUPPORT
+  hints.ai_family = PF_UNSPEC;  /* ipv6 support */
+#else
+  hints.ai_family = PF_INET;    /* ipv4 only support */
+#endif
+
+#endif
+
+  if (protocol==IPPROTO_UDP)
+    hints.ai_socktype = SOCK_DGRAM;
+  else
+    hints.ai_socktype = SOCK_STREAM;
+
+  hints.ai_protocol = protocol; /* IPPROTO_UDP or IPPROTO_TCP */
+  if (service == -1) /* -1 for SRV record */
+    {
+      error = getaddrinfo (hostname, "sip", &hints, addrinfo);
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                   "SRV resolution with udp-sip-%s\n", hostname));
+  } else
+    {
+      error = getaddrinfo (hostname, portbuf, &hints, addrinfo);
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                   "DNS resolution with %s:%i\n", hostname, service));
+    }
+  if (error || *addrinfo == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                   "getaddrinfo failure. %s:%s (%s)\n", hostname, portbuf,
+                   gai_strerror (error)));
+      return -1;
+    }
+
+  return 0;
+}
+
diff --git a/exosip2/inet_ntop.c b/exosip2/inet_ntop.c
new file mode 100644
index 0000000000..d3d765c263
--- /dev/null
+++ b/exosip2/inet_ntop.c
@@ -0,0 +1,217 @@
+/* This is from the BIND 4.9.4 release, modified to compile by itself */
+
+/* Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#if defined(WIN32)
+
+#include <osipparser2/osip_port.h>
+#include "eXosip2.h"
+
+#include <windowsx.h>
+#include <winsock2.h>
+#include <Ws2tcpip.h>
+#include <Iphlpapi.h>
+
+#include "inet_ntop.h"
+
+/* added by adm */
+/*
+ * the definitions below are valid for 32-bit architectures and will have to
+ * be adjusted for 16- or 64-bit architectures
+ */
+typedef unsigned __int8		uint8_t;
+typedef unsigned __int16	uint16_t;
+typedef unsigned __int32	uint32_t;
+typedef unsigned __int64    uint64_t;
+typedef __int8		int8_t;
+typedef __int16		int16_t;
+typedef __int32		int32_t;
+typedef __int64		int64_t;
+typedef unsigned long	in_addr_t;
+
+/* !added by amd */
+
+#define	IN6ADDRSZ	16
+#define	INT16SZ		 2
+
+#ifndef	AF_INET6
+#define	AF_INET6	AF_MAX+1	/* just to let this compile */
+#endif
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static const char *_inet_ntop4(const u_char *src, char *dst, size_t size);
+static const char *_inet_ntop6(const u_char *src, char *dst, size_t size);
+
+/* char *
+ * inet_ntop(af, src, dst, size)
+ *	convert a network format address to presentation format.
+ * return:
+ *	pointer to presentation format address (`dst'), or NULL (see errno).
+ * author:
+ *	Paul Vixie, 1996.
+ */
+const char *
+_inet_ntop(af, src, dst, size)
+	int af;
+	const void *src;
+	char *dst;
+	size_t size;
+{
+	switch (af) {
+	case AF_INET:
+		return (_inet_ntop4(src, dst, size));
+	case AF_INET6:
+		return (_inet_ntop6(src, dst, size));
+	default:
+		errno = EAFNOSUPPORT;
+		return (NULL);
+	}
+	/* NOTREACHED */
+}
+
+/* const char *
+ * inet_ntop4(src, dst, size)
+ *	format an IPv4 address, more or less like inet_ntoa()
+ * return:
+ *	`dst' (as a const)
+ * notes:
+ *	(1) uses no statics
+ *	(2) takes a u_char* not an in_addr as input
+ * author:
+ *	Paul Vixie, 1996.
+ */
+static const char *
+_inet_ntop4(src, dst, size)
+	const u_char *src;
+	char *dst;
+	size_t size;
+{
+	static const char fmt[] = "%u.%u.%u.%u";
+	char tmp[sizeof "255.255.255.255"];
+
+	sprintf(tmp, fmt, src[0], src[1], src[2], src[3]);
+	if ((size_t)strlen(tmp) > size) {
+		errno = ENOSPC;
+		return (NULL);
+	}
+	strcpy(dst, tmp);
+	return (dst);
+}
+
+/* const char *
+ * inet_ntop6(src, dst, size)
+ *	convert IPv6 binary address into presentation (printable) format
+ * author:
+ *	Paul Vixie, 1996.
+ */
+static const char *
+_inet_ntop6(src, dst, size)
+	const u_char *src;
+	char *dst;
+	size_t size;
+{
+	/*
+	 * Note that int32_t and int16_t need only be "at least" large enough
+	 * to contain a value of the specified size.  On some systems, like
+	 * Crays, there is no such thing as an integer variable with 16 bits.
+	 * Keep this in mind if you think this function should have been coded
+	 * to use pointer overlays.  All the world's not a VAX.
+	 */
+	char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
+	struct { int base, len; } best, cur;
+	uint32_t words[IN6ADDRSZ / INT16SZ];
+	int i;
+
+	/*
+	 * Preprocess:
+	 *	Copy the input (bytewise) array into a wordwise array.
+	 *	Find the longest run of 0x00's in src[] for :: shorthanding.
+	 */
+	memset(words, 0, sizeof words);
+	for (i = 0; i < IN6ADDRSZ; i++)
+		words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
+	best.base = -1;
+	cur.base = -1;
+	for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
+		if (words[i] == 0) {
+			if (cur.base == -1)
+				cur.base = i, cur.len = 1;
+			else
+				cur.len++;
+		} else {
+			if (cur.base != -1) {
+				if (best.base == -1 || cur.len > best.len)
+					best = cur;
+				cur.base = -1;
+			}
+		}
+	}
+	if (cur.base != -1) {
+		if (best.base == -1 || cur.len > best.len)
+			best = cur;
+	}
+	if (best.base != -1 && best.len < 2)
+		best.base = -1;
+
+	/*
+	 * Format the result.
+	 */
+	tp = tmp;
+	for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
+		/* Are we inside the best run of 0x00's? */
+		if (best.base != -1 && i >= best.base &&
+		    i < (best.base + best.len)) {
+			if (i == best.base)
+				*tp++ = ':';
+			continue;
+		}
+		/* Are we following an initial run of 0x00s or any real hex? */
+		if (i != 0)
+			*tp++ = ':';
+		/* Is this address an encapsulated IPv4? */
+		if (i == 6 && best.base == 0 &&
+		    (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
+			if (!_inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
+				return (NULL);
+			tp += strlen(tp);
+			break;
+		}
+		sprintf(tp, "%x", words[i]);
+		tp += strlen(tp);
+	}
+	/* Was it a trailing run of 0x00's? */
+	if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
+		*tp++ = ':';
+	*tp++ = '\0';
+
+	/*
+	 * Check for overflow, copy, and we're done.
+	 */
+	if ((size_t) (tp - tmp) > size) {
+		errno = ENOSPC;
+		return (NULL);
+	}
+	strcpy(dst, tmp);
+	return (dst);
+}
+
+#endif
+
diff --git a/exosip2/inet_ntop.h b/exosip2/inet_ntop.h
new file mode 100644
index 0000000000..d965806f77
--- /dev/null
+++ b/exosip2/inet_ntop.h
@@ -0,0 +1,21 @@
+
+#if defined(WIN32)
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#ifndef EAFNOSUPPORT
+#define EAFNOSUPPORT	WSAEAFNOSUPPORT
+#endif
+
+
+const char *_inet_ntop(int af, const void *src, char *dst, size_t size);
+
+#define inet_ntop _inet_ntop
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* WIN32 */
diff --git a/exosip2/jauth.c b/exosip2/jauth.c
new file mode 100644
index 0000000000..63c9539d9d
--- /dev/null
+++ b/exosip2/jauth.c
@@ -0,0 +1,489 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002, 2003  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+#include "eXosip2.h"
+#include <eXosip2/eXosip.h>
+
+#include <osip2/osip_mt.h>
+#include <osip2/osip_condv.h>
+
+/* #include <osip2/global.h> */
+#include <osipparser2/osip_md5.h>
+
+/* TAKEN from rcf2617.txt */
+
+#define HASHLEN 16
+typedef char HASH[HASHLEN];
+
+#define HASHHEXLEN 32
+typedef char HASHHEX[HASHHEXLEN + 1];
+
+#define IN
+#define OUT
+
+extern eXosip_t eXosip;
+
+/* Private functions */
+static void CvtHex (IN HASH Bin, OUT HASHHEX Hex);
+static void DigestCalcHA1 (IN const char *pszAlg, IN const char *pszUserName,
+                           IN const char *pszRealm,
+                           IN const char *pszPassword,
+                           IN const char *pszNonce, IN const char *pszCNonce,
+                           OUT HASHHEX SessionKey);
+static void DigestCalcResponse (IN HASHHEX HA1, IN const char *pszNonce,
+                                IN const char *pszNonceCount,
+                                IN const char *pszCNonce,
+                                IN const char *pszQop,
+                                IN const char *pszMethod,
+                                IN const char *pszDigestUri,
+                                IN HASHHEX HEntity, OUT HASHHEX Response);
+
+static void
+CvtHex (IN HASH Bin, OUT HASHHEX Hex)
+{
+  unsigned short i;
+  unsigned char j;
+
+  for (i = 0; i < HASHLEN; i++)
+    {
+      j = (Bin[i] >> 4) & 0xf;
+      if (j <= 9)
+        Hex[i * 2] = (j + '0');
+      else
+        Hex[i * 2] = (j + 'a' - 10);
+      j = Bin[i] & 0xf;
+      if (j <= 9)
+        Hex[i * 2 + 1] = (j + '0');
+      else
+        Hex[i * 2 + 1] = (j + 'a' - 10);
+    };
+  Hex[HASHHEXLEN] = '\0';
+}
+
+/* calculate H(A1) as per spec */
+static void
+DigestCalcHA1 (IN const char *pszAlg,
+               IN const char *pszUserName,
+               IN const char *pszRealm,
+               IN const char *pszPassword,
+               IN const char *pszNonce,
+               IN const char *pszCNonce, OUT HASHHEX SessionKey)
+{
+  MD5_CTX Md5Ctx;
+  HASH HA1;
+
+  MD5Init (&Md5Ctx);
+  MD5Update (&Md5Ctx, (unsigned char *) pszUserName, strlen (pszUserName));
+  MD5Update (&Md5Ctx, (unsigned char *) ":", 1);
+  MD5Update (&Md5Ctx, (unsigned char *) pszRealm, strlen (pszRealm));
+  MD5Update (&Md5Ctx, (unsigned char *) ":", 1);
+  MD5Update (&Md5Ctx, (unsigned char *) pszPassword, strlen (pszPassword));
+  MD5Final ((unsigned char *) HA1, &Md5Ctx);
+  if ((pszAlg != NULL) && osip_strcasecmp (pszAlg, "md5-sess") == 0)
+    {
+      MD5Init (&Md5Ctx);
+      MD5Update (&Md5Ctx, (unsigned char *) HA1, HASHLEN);
+      MD5Update (&Md5Ctx, (unsigned char *) ":", 1);
+      MD5Update (&Md5Ctx, (unsigned char *) pszNonce, strlen (pszNonce));
+      MD5Update (&Md5Ctx, (unsigned char *) ":", 1);
+      MD5Update (&Md5Ctx, (unsigned char *) pszCNonce, strlen (pszCNonce));
+      MD5Final ((unsigned char *) HA1, &Md5Ctx);
+    }
+  CvtHex (HA1, SessionKey);
+}
+
+/* calculate request-digest/response-digest as per HTTP Digest spec */
+static void
+DigestCalcResponse (IN HASHHEX HA1,     /* H(A1) */
+                    IN const char *pszNonce,    /* nonce from server */
+                    IN const char *pszNonceCount,       /* 8 hex digits */
+                    IN const char *pszCNonce,   /* client nonce */
+                    IN const char *pszQop,      /* qop-value: "", "auth", "auth-int" */
+                    IN const char *pszMethod,   /* method from the request */
+                    IN const char *pszDigestUri,        /* requested URL */
+                    IN HASHHEX HEntity, /* H(entity body) if qop="auth-int" */
+                    OUT HASHHEX Response
+                    /* request-digest or response-digest */ )
+{
+  MD5_CTX Md5Ctx;
+  HASH HA2;
+  HASH RespHash;
+  HASHHEX HA2Hex;
+
+  /* calculate H(A2) */
+  MD5Init (&Md5Ctx);
+  MD5Update (&Md5Ctx, (unsigned char *) pszMethod, strlen (pszMethod));
+  MD5Update (&Md5Ctx, (unsigned char *) ":", 1);
+  MD5Update (&Md5Ctx, (unsigned char *) pszDigestUri, strlen (pszDigestUri));
+
+  if (pszQop != NULL)
+    {
+
+      /*#define AUTH_INT_SUPPORT *//* experimental  */
+#ifdef AUTH_INT_SUPPORT         /* experimental  */
+      char *index = strchr (pszQop, 'i');
+
+      while (index != NULL && index - pszQop >= 5 && strlen (index) >= 3)
+        {
+          if (osip_strncasecmp (index - 5, "auth-int", 8) == 0)
+            {
+              goto auth_withqop;
+            }
+          index = strchr (index + 1, 'i');
+        }
+
+      strchr (pszQop, 'a');
+      while (index != NULL && strlen (index) >= 4)
+        {
+          if (osip_strncasecmp (index - 5, "auth", 4) == 0)
+            {
+              /* and in the case of a unknown token
+                 like auth1. It is not auth, but this
+                 implementation will think it is!??
+                 This is may not happen but it's a bug!
+               */
+              goto auth_withqop;
+            }
+          index = strchr (index + 1, 'a');
+        }
+#endif
+      goto auth_withoutqop;
+
+    };
+
+auth_withoutqop:
+  MD5Final ((unsigned char *) HA2, &Md5Ctx);
+  CvtHex (HA2, HA2Hex);
+
+  /* calculate response */
+  MD5Init (&Md5Ctx);
+  MD5Update (&Md5Ctx, (unsigned char *) HA1, HASHHEXLEN);
+  MD5Update (&Md5Ctx, (unsigned char *) ":", 1);
+  MD5Update (&Md5Ctx, (unsigned char *) pszNonce, strlen (pszNonce));
+  MD5Update (&Md5Ctx, (unsigned char *) ":", 1);
+
+  goto end;
+
+#ifdef AUTH_INT_SUPPORT         /* experimental  */
+auth_withqop:
+#endif
+
+  MD5Update (&Md5Ctx, (unsigned char *) ":", 1);
+  MD5Update (&Md5Ctx, (unsigned char *) HEntity, HASHHEXLEN);
+  MD5Final ((unsigned char *) HA2, &Md5Ctx);
+  CvtHex (HA2, HA2Hex);
+
+  /* calculate response */
+  MD5Init (&Md5Ctx);
+  MD5Update (&Md5Ctx, (unsigned char *) HA1, HASHHEXLEN);
+  MD5Update (&Md5Ctx, (unsigned char *) ":", 1);
+  MD5Update (&Md5Ctx, (unsigned char *) pszNonce, strlen (pszNonce));
+  MD5Update (&Md5Ctx, (unsigned char *) ":", 1);
+  MD5Update (&Md5Ctx, (unsigned char *) pszNonceCount, strlen (pszNonceCount));
+  MD5Update (&Md5Ctx, (unsigned char *) ":", 1);
+  MD5Update (&Md5Ctx, (unsigned char *) pszCNonce, strlen (pszCNonce));
+  MD5Update (&Md5Ctx, (unsigned char *) ":", 1);
+  MD5Update (&Md5Ctx, (unsigned char *) pszQop, strlen (pszQop));
+  MD5Update (&Md5Ctx, (unsigned char *) ":", 1);
+
+end:
+  MD5Update (&Md5Ctx, (unsigned char *) HA2Hex, HASHHEXLEN);
+  MD5Final ((unsigned char *) RespHash, &Md5Ctx);
+  CvtHex (RespHash, Response);
+}
+
+
+int
+__eXosip_create_authorization_header (osip_message_t * previous_answer,
+                                      const char *rquri, const char *username,
+                                      const char *passwd, const char *ha1,
+                                      osip_authorization_t ** auth,
+				      const char *method)
+{
+  osip_authorization_t *aut;
+  osip_www_authenticate_t *wa = NULL;
+
+  osip_message_get_www_authenticate (previous_answer, 0, &wa);
+
+  /* make some test */
+  if (passwd == NULL)
+    return -1;
+  if (wa == NULL || wa->auth_type == NULL
+      || (wa->realm == NULL) || (wa->nonce == NULL))
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "www_authenticate header is not acceptable.\n"));
+      return -1;
+    }
+  if (0 != osip_strcasecmp ("Digest", wa->auth_type))
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "Authentication method not supported. (Digest only).\n"));
+      return -1;
+    }
+  /* "MD5" is invalid, but some servers use it. */
+  if (wa->algorithm != NULL && 0 != osip_strcasecmp ("MD5", wa->algorithm)
+      && 0 != osip_strcasecmp ("\"MD5\"", wa->algorithm))
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "Authentication method not supported. (Digest only).\n"));
+      return -1;
+    }
+  if (0 != osip_authorization_init (&aut))
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "allocation with authorization_init failed.\n"));
+      return -1;
+    }
+
+  /* just copy some feilds from response to new request */
+  osip_authorization_set_auth_type (aut, osip_strdup ("Digest"));
+  osip_authorization_set_realm (aut,
+                                osip_strdup (osip_www_authenticate_get_realm
+                                             (wa)));
+  osip_authorization_set_nonce (aut,
+                                osip_strdup (osip_www_authenticate_get_nonce
+                                             (wa)));
+  if (osip_www_authenticate_get_opaque (wa) != NULL)
+    osip_authorization_set_opaque (aut,
+                                   osip_strdup
+                                   (osip_www_authenticate_get_opaque (wa)));
+  /* copy the username field in new request */
+  aut->username = osip_malloc (strlen (username) + 3);
+  sprintf (aut->username, "\"%s\"", username);
+
+  {
+    char *tmp = osip_malloc (strlen (rquri) + 3);
+
+    sprintf (tmp, "\"%s\"", rquri);
+    osip_authorization_set_uri (aut, tmp);
+  }
+
+  osip_authorization_set_algorithm (aut, osip_strdup ("MD5"));
+
+  {
+    char *pszNonce =
+      osip_strdup_without_quote (osip_www_authenticate_get_nonce (wa));
+    char *pszCNonce = NULL;
+    const char *pszUser = username;
+    char *pszRealm =
+      osip_strdup_without_quote (osip_authorization_get_realm (aut));
+    const char *pszPass = NULL;
+    char *pszAlg = osip_strdup ("MD5");
+    char *szNonceCount = NULL;
+    const char *pszMethod = method; /* previous_answer->cseq->method; */
+    char *pszQop = NULL;
+    const char *pszURI = rquri;
+
+    HASHHEX HA1;
+    HASHHEX HA2 = "";
+    HASHHEX Response;
+    const char *pha1 = NULL;
+
+    pszPass = passwd;
+    if (osip_authorization_get_nonce_count (aut) != NULL)
+      szNonceCount = osip_strdup (osip_authorization_get_nonce_count (aut));
+    if (osip_authorization_get_message_qop (aut) != NULL)
+      pszQop = osip_strdup (osip_authorization_get_message_qop (aut));
+
+    if (ha1 && ha1[0])
+      {
+	/* Depending on algorithm=md5 */
+	pha1 = ha1;
+      }
+    else
+      {
+	DigestCalcHA1 (pszAlg, pszUser, pszRealm, pszPass, pszNonce, pszCNonce, HA1);
+	pha1 = HA1;
+      }
+
+    DigestCalcResponse ((char *)pha1, pszNonce, szNonceCount, pszCNonce, pszQop,
+                        pszMethod, pszURI, HA2, Response);
+    OSIP_TRACE (osip_trace
+                (__FILE__, __LINE__, OSIP_INFO4, NULL,
+                 "Response in authorization |%s|\n", Response));
+    {
+      char *resp = osip_malloc (35);
+
+      sprintf (resp, "\"%s\"", Response);
+      osip_authorization_set_response (aut, resp);
+    }
+    osip_free (pszAlg);         /* xkd, 2004-5-13 */
+    osip_free (pszNonce);
+    osip_free (pszCNonce);
+    osip_free (pszRealm);
+    osip_free (pszQop);
+    osip_free (szNonceCount);
+  }
+
+  *auth = aut;
+  return 0;
+}
+
+int
+__eXosip_create_proxy_authorization_header (osip_message_t * previous_answer,
+                                            const char *rquri,
+                                            const char *username,
+                                            const char *passwd,
+                                            const char *ha1,
+                                            osip_proxy_authorization_t ** auth,
+					    const char *method)
+{
+  osip_proxy_authorization_t *aut;
+  osip_proxy_authenticate_t *wa;
+
+  osip_message_get_proxy_authenticate (previous_answer, 0, &wa);
+
+  /* make some test */
+  if (passwd == NULL)
+    return -1;
+  if (wa == NULL || wa->auth_type == NULL
+      || (wa->realm == NULL) || (wa->nonce == NULL))
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "www_authenticate header is not acceptable.\n"));
+      return -1;
+    }
+  if (0 != osip_strcasecmp ("Digest", wa->auth_type))
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "Authentication method not supported. (Digest only).\n"));
+      return -1;
+    }
+  /* "MD5" is invalid, but some servers use it. */
+  if (wa->algorithm != NULL && 0 != osip_strcasecmp ("MD5", wa->algorithm)
+      && 0 != osip_strcasecmp ("\"MD5\"", wa->algorithm))
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "Authentication method not supported. (MD5 Digest only).\n"));
+      return -1;
+    }
+  if (0 != osip_proxy_authorization_init (&aut))
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "allocation with authorization_init failed.\n"));
+      return -1;
+    }
+
+  /* just copy some feilds from response to new request */
+  osip_proxy_authorization_set_auth_type (aut, osip_strdup ("Digest"));
+  osip_proxy_authorization_set_realm (aut,
+                                      osip_strdup
+                                      (osip_proxy_authenticate_get_realm (wa)));
+  osip_proxy_authorization_set_nonce (aut,
+                                      osip_strdup
+                                      (osip_proxy_authenticate_get_nonce (wa)));
+  if (osip_proxy_authenticate_get_opaque (wa) != NULL)
+    osip_proxy_authorization_set_opaque (aut,
+                                         osip_strdup
+                                         (osip_proxy_authenticate_get_opaque
+                                          (wa)));
+  /* copy the username field in new request */
+  aut->username = osip_malloc (strlen (username) + 3);
+  sprintf (aut->username, "\"%s\"", username);
+
+  {
+    char *tmp = osip_malloc (strlen (rquri) + 3);
+
+    sprintf (tmp, "\"%s\"", rquri);
+    osip_proxy_authorization_set_uri (aut, tmp);
+  }
+  osip_proxy_authorization_set_algorithm (aut, osip_strdup ("MD5"));
+
+  {
+    char *pszNonce = NULL;
+    char *pszCNonce = NULL;
+    const char *pszUser = username;
+    char *pszRealm =
+      osip_strdup_without_quote (osip_proxy_authorization_get_realm (aut));
+    const char *pszPass = NULL;
+    char *pszAlg = osip_strdup ("MD5");
+    char *szNonceCount = NULL;
+    char *pszMethod = (char *)method; /* previous_answer->cseq->method; */
+    char *pszQop = NULL;
+    const char *pszURI = rquri;
+
+    HASHHEX HA1;
+    HASHHEX HA2 = "";
+    HASHHEX Response;
+    const char *pha1 = NULL;
+
+    pszPass = passwd;
+
+    if (osip_www_authenticate_get_nonce (wa) == NULL)
+      return -1;
+    pszNonce = osip_strdup_without_quote (osip_www_authenticate_get_nonce (wa));
+
+    /* should upgrade szNonceCount */
+    /* should add szNonceCount in aut */
+    /* should upgrade pszCNonce */
+    /* should add pszCNonce in aut */
+
+    if (osip_proxy_authenticate_get_qop_options (wa) != NULL)
+      {
+        szNonceCount = osip_strdup ("00000001");
+        /* MUST be incremented on each */
+        pszQop = osip_strdup (osip_proxy_authenticate_get_qop_options (wa));
+        pszCNonce = osip_strdup ("234abcc436e2667097e7fe6eia53e8dd");
+      }
+    if (ha1 && ha1[0])
+      {
+	/* Depending on algorithm=md5 */
+	pha1 = ha1;
+      }
+    else
+      {
+	DigestCalcHA1 (pszAlg, pszUser, pszRealm, pszPass, pszNonce, pszCNonce, HA1);
+	pha1 = HA1;
+      }
+    DigestCalcResponse ((char *)pha1, pszNonce, szNonceCount, pszCNonce, pszQop,
+                        pszMethod, pszURI, HA2, Response);
+    OSIP_TRACE (osip_trace
+                (__FILE__, __LINE__, OSIP_INFO4, NULL,
+                 "Response in proxy_authorization |%s|\n", Response));
+    {
+      char *resp = osip_malloc (35);
+
+      sprintf (resp, "\"%s\"", Response);
+      osip_proxy_authorization_set_response (aut, resp);
+    }
+    osip_free (pszAlg);         /* xkd, 2004-5-13 */
+    osip_free (pszNonce);
+    osip_free (pszCNonce);
+    osip_free (pszRealm);
+    osip_free (pszQop);
+    osip_free (szNonceCount);
+  }
+
+  *auth = aut;
+  return 0;
+}
diff --git a/exosip2/jcall.c b/exosip2/jcall.c
new file mode 100644
index 0000000000..cd13c0432e
--- /dev/null
+++ b/exosip2/jcall.c
@@ -0,0 +1,119 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002, 2003  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+
+#include "eXosip2.h"
+
+extern eXosip_t eXosip;
+
+int
+eXosip_call_find (int cid, eXosip_call_t ** jc)
+{
+  for (*jc = eXosip.j_calls; *jc != NULL; *jc = (*jc)->next)
+    {
+      if ((*jc)->c_id == cid)
+        {
+          return 0;
+        }
+    }
+  *jc = NULL;
+  return -1;
+}
+
+int
+eXosip_call_init (eXosip_call_t ** jc)
+{
+  *jc = (eXosip_call_t *) osip_malloc (sizeof (eXosip_call_t));
+  if (*jc == NULL)
+    return -1;
+  memset (*jc, 0, sizeof (eXosip_call_t));
+
+  (*jc)->c_id = -1;             /* make sure the eXosip_update will assign a valid id to the call */
+  return 0;
+}
+
+void
+__eXosip_call_remove_dialog_reference_in_call (eXosip_call_t * jc,
+                                               eXosip_dialog_t * jd)
+{
+  eXosip_dialog_t *_jd;
+  jinfo_t *ji;
+
+  if (jc == NULL)
+    return;
+  if (jd == NULL)
+    return;
+
+
+  for (_jd = jc->c_dialogs; _jd != NULL; _jd = _jd->next)
+    {
+      if (jd == _jd)
+        break;
+    }
+  if (_jd == NULL)
+    {
+      /* dialog not found??? */
+    }
+
+  ji = osip_transaction_get_your_instance (jc->c_inc_tr);
+  if (ji != NULL && ji->jd == jd)
+    ji->jd = NULL;
+  ji = osip_transaction_get_your_instance (jc->c_out_tr);
+  if (ji != NULL && ji->jd == jd)
+    ji->jd = NULL;
+}
+
+void
+eXosip_call_free (eXosip_call_t * jc)
+{
+  /* ... */
+
+  eXosip_dialog_t *jd;
+
+  if (jc->response_auth!=NULL)
+    osip_message_free(jc->response_auth);
+
+  for (jd = jc->c_dialogs; jd != NULL; jd = jc->c_dialogs)
+    {
+      REMOVE_ELEMENT (jc->c_dialogs, jd);
+      eXosip_dialog_free (jd);
+    }
+
+  __eXosip_delete_jinfo (jc->c_inc_tr);
+  __eXosip_delete_jinfo (jc->c_out_tr);
+  if (jc->c_inc_tr != NULL)
+    osip_list_add (eXosip.j_transactions, jc->c_inc_tr, 0);
+  if (jc->c_out_tr != NULL)
+    osip_list_add (eXosip.j_transactions, jc->c_out_tr, 0);
+
+  __eXosip_delete_jinfo (jc->c_inc_options_tr);
+  __eXosip_delete_jinfo (jc->c_out_options_tr);
+  if (jc->c_inc_options_tr != NULL)
+    osip_list_add (eXosip.j_transactions, jc->c_inc_options_tr, 0);
+  if (jc->c_out_options_tr != NULL)
+    osip_list_add (eXosip.j_transactions, jc->c_out_options_tr, 0);
+
+  osip_free (jc);
+
+}
diff --git a/exosip2/jcallback.c b/exosip2/jcallback.c
new file mode 100644
index 0000000000..84e9b646b7
--- /dev/null
+++ b/exosip2/jcallback.c
@@ -0,0 +1,2053 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002, 2003  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+#include <stdlib.h>
+
+#ifdef WIN32
+#include <windowsx.h>
+#include <winsock2.h>
+#include <Ws2tcpip.h>
+#include "inet_ntop.h"
+
+#else
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#endif
+
+#include <eXosip2/eXosip.h>
+#include "eXosip2.h"
+
+extern eXosip_t eXosip;
+
+
+/* Private functions */
+static void rcvregister_failure (int type, osip_transaction_t * tr,
+                                 osip_message_t * sip);
+static void cb_ict_kill_transaction (int type, osip_transaction_t * tr);
+static void cb_ist_kill_transaction (int type, osip_transaction_t * tr);
+static void cb_nict_kill_transaction (int type, osip_transaction_t * tr);
+static void cb_nist_kill_transaction (int type, osip_transaction_t * tr);
+static void cb_rcvinvite (int type, osip_transaction_t * tr, osip_message_t * sip);
+static void cb_rcvack (int type, osip_transaction_t * tr, osip_message_t * sip);
+static void cb_rcvack2 (int type, osip_transaction_t * tr, osip_message_t * sip);
+static void cb_rcvregister (int type, osip_transaction_t * tr,
+                            osip_message_t * sip);
+static void cb_rcvcancel (int type, osip_transaction_t * tr, osip_message_t * sip);
+static void cb_rcvrequest (int type, osip_transaction_t * tr,
+                              osip_message_t * sip);
+static void cb_sndinvite (int type, osip_transaction_t * tr, osip_message_t * sip);
+static void cb_sndack (int type, osip_transaction_t * tr, osip_message_t * sip);
+static void cb_sndregister (int type, osip_transaction_t * tr,
+                            osip_message_t * sip);
+static void cb_sndbye (int type, osip_transaction_t * tr, osip_message_t * sip);
+static void cb_sndcancel (int type, osip_transaction_t * tr, osip_message_t * sip);
+static void cb_sndinfo (int type, osip_transaction_t * tr, osip_message_t * sip);
+static void cb_sndoptions (int type, osip_transaction_t * tr,
+                           osip_message_t * sip);
+static void cb_sndnotify (int type, osip_transaction_t * tr, osip_message_t * sip);
+static void cb_sndsubscribe (int type, osip_transaction_t * tr,
+                             osip_message_t * sip);
+static void cb_sndunkrequest (int type, osip_transaction_t * tr,
+                              osip_message_t * sip);
+static void cb_rcv1xx (int type, osip_transaction_t * tr, osip_message_t * sip);
+static void cb_rcv2xx_4invite (osip_transaction_t * tr, osip_message_t * sip);
+static void cb_rcv2xx_4subscribe (osip_transaction_t * tr, osip_message_t * sip);
+static void cb_rcv2xx (int type, osip_transaction_t * tr, osip_message_t * sip);
+static void cb_rcv3xx (int type, osip_transaction_t * tr, osip_message_t * sip);
+static void cb_rcv4xx (int type, osip_transaction_t * tr, osip_message_t * sip);
+static void cb_rcv5xx (int type, osip_transaction_t * tr, osip_message_t * sip);
+static void cb_rcv6xx (int type, osip_transaction_t * tr, osip_message_t * sip);
+static void cb_snd1xx (int type, osip_transaction_t * tr, osip_message_t * sip);
+static void cb_snd2xx (int type, osip_transaction_t * tr, osip_message_t * sip);
+static void cb_snd3xx (int type, osip_transaction_t * tr, osip_message_t * sip);
+static void cb_snd4xx (int type, osip_transaction_t * tr, osip_message_t * sip);
+static void cb_snd5xx (int type, osip_transaction_t * tr, osip_message_t * sip);
+static void cb_snd6xx (int type, osip_transaction_t * tr, osip_message_t * sip);
+static void cb_rcvresp_retransmission (int type, osip_transaction_t * tr,
+                                       osip_message_t * sip);
+static void cb_sndreq_retransmission (int type, osip_transaction_t * tr,
+                                      osip_message_t * sip);
+static void cb_sndresp_retransmission (int type, osip_transaction_t * tr,
+                                       osip_message_t * sip);
+static void cb_rcvreq_retransmission (int type, osip_transaction_t * tr,
+                                      osip_message_t * sip);
+static void cb_transport_error (int type, osip_transaction_t * tr, int error);
+
+
+int
+cb_snd_message (osip_transaction_t * tr, osip_message_t * sip, char *host,
+		int port, int out_socket)
+{
+  int i;
+  osip_via_t *via;
+  if (eXosip.net_interfaces[0].net_socket == 0
+      && eXosip.net_interfaces[1].net_socket == 0)
+    return -1;
+
+  if (host == NULL)
+    {
+      host = sip->req_uri->host;
+      if (sip->req_uri->port != NULL)
+        port = osip_atoi (sip->req_uri->port);
+      else
+        port = 5060;
+    }
+
+  via = (osip_via_t *) osip_list_get(sip->vias, 0);
+  if (via==NULL || via->protocol==NULL)
+    return -1;
+
+  i = -1;
+  if (osip_strcasecmp(via->protocol, "udp")==0)
+    {
+      i = cb_udp_snd_message (tr, sip, host, port, out_socket);
+    }
+  else
+    {
+      i = cb_tcp_snd_message (tr, sip, host, port, out_socket);
+    }
+  if (i != 0)
+    {
+      return -1;
+    }
+
+  return 0;
+
+}
+
+int
+cb_udp_snd_message (osip_transaction_t * tr, osip_message_t * sip, char *host,
+                    int port, int out_socket)
+{
+  int len = 0;
+  size_t length = 0;
+  struct addrinfo *addrinfo;
+  struct __eXosip_sockaddr addr;
+  char *message;
+#ifdef INET6_ADDRSTRLEN
+  char ipbuf[INET6_ADDRSTRLEN];
+#else
+  char ipbuf[46];
+#endif
+  int i;
+  struct eXosip_net *net;
+
+  if (eXosip.net_interfaces[0].net_socket == 0)
+    return -1;
+
+  net = &eXosip.net_interfaces[0];
+
+  if (eXosip.http_port)
+  {
+    i = osip_message_to_str (sip, &message, &length);
+
+    if (i != 0 || length <= 0)
+        {
+        return -1;
+        }
+    if (0 >
+        _eXosip_sendto (net->net_socket, (const void *) message, length, 0,
+	        (struct sockaddr *) &addr, len ))
+    {
+        /* should reopen connection! */
+        osip_free (message);
+        return -1;
+    }
+    return 0;
+  }
+
+  if (host == NULL)
+    {
+      host = sip->req_uri->host;
+      if (sip->req_uri->port != NULL)
+        port = osip_atoi (sip->req_uri->port);
+      else
+        port = 5060;
+    }
+
+  i = eXosip_get_addrinfo (&addrinfo, host, port, IPPROTO_UDP);
+  if (i != 0)
+    {
+      return -1;
+    }
+
+  memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen);
+  len = addrinfo->ai_addrlen;
+
+  freeaddrinfo (addrinfo);
+
+  i = osip_message_to_str (sip, &message, &length);
+
+  if (i != 0 || length <= 0)
+    {
+      return -1;
+    }
+
+  switch (addr.ss_family)
+    {
+    case AF_INET:
+      inet_ntop(addr.ss_family, &(((struct sockaddr_in*)&addr)->sin_addr), ipbuf, sizeof(ipbuf));
+      break;
+    case AF_INET6:
+      inet_ntop(addr.ss_family, &(((struct sockaddr_in6*)&addr)->sin6_addr), ipbuf, sizeof(ipbuf));
+      break;
+    default:
+      strncpy(ipbuf, "(unknown)", sizeof(ipbuf));
+      break;
+    }
+  
+  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
+			  "Message sent: \n%s (to dest=%s:%i)\n",
+			  message, ipbuf, port));
+  if (0 >
+      _eXosip_sendto (net->net_socket, (const void *) message, length, 0,
+	      (struct sockaddr *) &addr, len ))
+    {
+#ifdef WIN32
+      if (WSAECONNREFUSED == WSAGetLastError ())
+#else
+      if (ECONNREFUSED == errno)
+#endif
+        {
+          /* This can be considered as an error, but for the moment,
+             I prefer that the application continue to try sending
+             message again and again... so we are not in a error case.
+             Nevertheless, this error should be announced!
+             ALSO, UAS may not have any other options than retry always
+             on the same port.
+           */
+          osip_free (message);
+          return 1;
+      } else
+        {
+          /* SIP_NETWORK_ERROR; */
+          osip_free (message);
+          return -1;
+        }
+    }
+
+
+    if (eXosip.keep_alive>0)
+    {
+        if (MSG_IS_REGISTER(sip))
+        {
+            eXosip_reg_t *reg = NULL;
+            if (_eXosip_reg_find(&reg, tr)==0)
+            {
+                memcpy (&(reg->addr), &addr, len);
+                reg->len = len;
+            }
+        }
+    }
+
+  osip_free (message);
+  return 0;
+
+}
+
+int
+cb_tcp_snd_message (osip_transaction_t * tr, osip_message_t * sip, char *host,
+                    int port, int out_socket)
+{
+  size_t length = 0;
+  char *message;
+  int i;
+  struct eXosip_net *net;
+  if (eXosip.net_interfaces[1].net_socket == 0)
+    return -1;
+
+  if (host == NULL)
+    {
+      host = sip->req_uri->host;
+      if (sip->req_uri->port != NULL)
+        port = osip_atoi (sip->req_uri->port);
+      else
+        port = 5060;
+    }
+
+  net = &eXosip.net_interfaces[1];
+
+  i = osip_message_to_str (sip, &message, &length);
+  
+  if (i != 0 || length <= 0)
+    {
+      return -1;
+    }
+
+  /* Step 1: find existing socket to send message */
+  if (out_socket<=0)
+    {
+      out_socket = _eXosip_tcp_find_socket(host, port);
+      
+      /* Step 2: create new socket with host:port */
+      if (out_socket<=0)
+	{
+	  out_socket = _eXosip_tcp_connect_socket(host, port);
+	}
+      
+      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
+			      "Message sent: \n%s (to dest=%s:%i)\n",
+			      message, host, port));
+    }
+  else
+    {
+      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
+			      "Message sent: \n%s (reusing REQUEST connection)\n",
+			      message, host, port));
+    }
+
+  if (out_socket<=0)
+    {
+      return -1;
+    }
+
+
+  if (0 > send (out_socket, (const void *) message, length, 0))
+    {
+#ifdef WIN32
+      if (WSAECONNREFUSED == WSAGetLastError ())
+#else
+      if (ECONNREFUSED == errno)
+#endif
+        {
+          /* This can be considered as an error, but for the moment,
+             I prefer that the application continue to try sending
+             message again and again... so we are not in a error case.
+             Nevertheless, this error should be announced!
+             ALSO, UAS may not have any other options than retry always
+             on the same port.
+           */
+          osip_free (message);
+          return 1;
+      } else
+        {
+          /* SIP_NETWORK_ERROR; */
+	  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
+				  "TCP error: \n%s\n",
+				  strerror(errno)));
+          osip_free (message);
+          return -1;
+        }
+    }
+
+  osip_free (message);
+  return 0;
+
+}
+
+static void
+cb_ict_kill_transaction (int type, osip_transaction_t * tr)
+{
+  int i;
+
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL,
+               "cb_ict_kill_transaction (id=%i)\r\n", tr->transactionid));
+
+  i = osip_remove_transaction (eXosip.j_osip, tr);
+  if (i != 0)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_BUG, NULL,
+                   "cb_ict_kill_transaction Error: Could not remove transaction from the oSIP stack? (id=%i)\r\n",
+                   tr->transactionid));
+    }
+}
+
+static void
+cb_ist_kill_transaction (int type, osip_transaction_t * tr)
+{
+  int i;
+
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL,
+               "cb_ist_kill_transaction (id=%i)\r\n", tr->transactionid));
+  i = osip_remove_transaction (eXosip.j_osip, tr);
+  if (i != 0)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_BUG, NULL,
+                   "cb_ist_kill_transaction Error: Could not remove transaction from the oSIP stack? (id=%i)\r\n",
+                   tr->transactionid));
+    }
+}
+
+static void
+cb_nict_kill_transaction (int type, osip_transaction_t * tr)
+{
+  int i;
+  eXosip_dialog_t *jd;
+  eXosip_call_t *jc;
+  eXosip_subscribe_t *js;
+  eXosip_notify_t *jn;
+  jinfo_t *jinfo = (jinfo_t *) osip_transaction_get_your_instance (tr);
+
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL,
+               "cb_nict_kill_transaction (id=%i)\r\n", tr->transactionid));
+  i = osip_remove_transaction (eXosip.j_osip, tr);
+  if (i != 0)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_BUG, NULL,
+                   "cb_nict_kill_transaction Error: Could not remove transaction from the oSIP stack? (id=%i)\r\n",
+                   tr->transactionid));
+    }
+
+  if (MSG_IS_REGISTER (tr->orig_request)
+      && type == OSIP_NICT_KILL_TRANSACTION && tr->last_response == NULL)
+    {
+      eXosip_event_t *je;
+      eXosip_reg_t *jreg = NULL;
+
+      /* find matching j_reg */
+      _eXosip_reg_find (&jreg, tr);
+      if (jreg != NULL)
+        {
+          je = eXosip_event_init_for_reg (EXOSIP_REGISTRATION_FAILURE, jreg, tr);
+          report_event (je, NULL);
+        }
+      return;
+    }
+
+  if (jinfo == NULL)
+    return;
+  jd = jinfo->jd;
+  jc = jinfo->jc;
+  jn = jinfo->jn;
+  js = jinfo->js;
+
+  if (jn == NULL && js == NULL)
+    return;
+
+  /* no answer to a NOTIFY request! */
+  if (MSG_IS_NOTIFY (tr->orig_request)
+      && type == OSIP_NICT_KILL_TRANSACTION && tr->last_response == NULL)
+    {
+      /* delete the dialog! */
+      REMOVE_ELEMENT (eXosip.j_notifies, jn);
+      eXosip_notify_free (jn);
+      return;
+    }
+
+  if (MSG_IS_NOTIFY (tr->orig_request)
+      && type == OSIP_NICT_KILL_TRANSACTION
+      && tr->last_response != NULL && tr->last_response->status_code > 299)
+    {
+      /* delete the dialog! */
+      if (tr->last_response->status_code != 407
+          && tr->last_response->status_code != 401)
+        {
+          REMOVE_ELEMENT (eXosip.j_notifies, jn);
+          eXosip_notify_free (jn);
+          return;
+        }
+    }
+
+  if (MSG_IS_NOTIFY (tr->orig_request)
+      && type == OSIP_NICT_KILL_TRANSACTION
+      && tr->last_response != NULL
+      && tr->last_response->status_code > 199
+      && tr->last_response->status_code < 300)
+    {
+      if (jn->n_ss_status == EXOSIP_SUBCRSTATE_TERMINATED)
+        {
+          /* delete the dialog! */
+          REMOVE_ELEMENT (eXosip.j_notifies, jn);
+          eXosip_notify_free (jn);
+          return;
+        }
+    }
+
+  /* no answer to a SUBSCRIBE request! */
+  if (MSG_IS_SUBSCRIBE (tr->orig_request)
+      && type == OSIP_NICT_KILL_TRANSACTION && tr->last_response == NULL)
+    {
+      /* delete the dialog! */
+      REMOVE_ELEMENT (eXosip.j_subscribes, js);
+      eXosip_subscribe_free (js);
+      return;
+    }
+
+  /* detect SUBSCRIBE request that close the dialogs! */
+  /* expires=0 with MSN */
+  if (MSG_IS_SUBSCRIBE (tr->orig_request) && type == OSIP_NICT_KILL_TRANSACTION)
+    {
+      osip_header_t *expires;
+
+      osip_message_get_expires (tr->orig_request, 0, &expires);
+      if (expires == NULL || expires->hvalue == NULL)
+        {
+      } else if (0 == strcmp (expires->hvalue, "0"))
+        {
+          /* delete the dialog! */
+          REMOVE_ELEMENT (eXosip.j_subscribes, js);
+          eXosip_subscribe_free (js);
+          return;
+        }
+    }
+}
+
+static void
+cb_nist_kill_transaction (int type, osip_transaction_t * tr)
+{
+  int i;
+
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL,
+               "cb_nist_kill_transaction (id=%i)\r\n", tr->transactionid));
+  i = osip_remove_transaction (eXosip.j_osip, tr);
+  if (i != 0)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_BUG, NULL,
+                   "cb_nist_kill_transaction Error: Could not remove transaction from the oSIP stack? (id=%i)\r\n",
+                   tr->transactionid));
+    }
+
+}
+
+static void
+cb_rcvinvite (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL, "cb_rcvinvite (id=%i)\n",
+               tr->transactionid));
+}
+
+static void
+cb_rcvack (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL, "cb_rcvack (id=%i)\n",
+               tr->transactionid));
+}
+
+static void
+cb_rcvack2 (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL, "cb_rcvack2 (id=%i)\r\n",
+               tr->transactionid));
+}
+
+static void
+cb_rcvregister (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  eXosip_event_t *je;
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL,
+               "cb_rcvregister (id=%i)\r\n", tr->transactionid));
+  
+  je = eXosip_event_init_for_message (EXOSIP_MESSAGE_NEW, tr);
+  eXosip_event_add (je);
+  return;
+}
+
+static void
+cb_rcvcancel (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL,
+               "cb_rcvcancel (id=%i)\r\n", tr->transactionid));
+}
+
+static void
+cb_rcvrequest (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  eXosip_dialog_t *jd;
+  eXosip_call_t *jc;
+  eXosip_notify_t *jn;
+  eXosip_subscribe_t *js;
+
+  eXosip_event_t *je;
+
+  jinfo_t *jinfo = (jinfo_t *) osip_transaction_get_your_instance (tr);
+
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL,
+               "cb_rcvunkrequest (id=%i)\r\n", tr->transactionid));
+
+  if (jinfo == NULL)
+    {
+      eXosip_event_t *je;
+      
+      je = eXosip_event_init_for_message (EXOSIP_MESSAGE_NEW, tr);
+      eXosip_event_add (je);
+      return;
+    }
+
+  jd = jinfo->jd;
+  jc = jinfo->jc;
+  jn = jinfo->jn;
+  js = jinfo->js;
+  if (jc == NULL && jn == NULL && js == NULL)
+    {
+      eXosip_event_t *je;
+      
+      je = eXosip_event_init_for_message (EXOSIP_MESSAGE_NEW, tr);
+      eXosip_event_add (je);
+      return;
+    }
+  else if (jc!=NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                   "cb_rcv? (id=%i)\r\n", tr->transactionid));
+
+      report_call_event (EXOSIP_CALL_MESSAGE_NEW, jc, jd, tr);
+      return;
+    }
+  else if (jn!=NULL)
+    {
+      if (MSG_IS_SUBSCRIBE (sip))
+	{
+	  je = eXosip_event_init_for_notify (EXOSIP_IN_SUBSCRIPTION_NEW, jn, jd, tr);
+	  report_event (je, NULL);
+	  return;
+	}
+      return;
+    }
+  else if (js!=NULL)
+    {
+      if (MSG_IS_NOTIFY (sip))
+	{
+	  je = eXosip_event_init_for_subscribe (EXOSIP_SUBSCRIPTION_NOTIFY, js, jd, tr);
+	  report_event (je, NULL);      
+	  return;
+	}
+      return;
+    }
+}
+
+static void
+cb_sndinvite (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL,
+               "cb_sndinvite (id=%i)\r\n", tr->transactionid));
+}
+
+static void
+cb_sndack (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL, "cb_sndack (id=%i)\r\n",
+               tr->transactionid));
+}
+
+static void
+cb_sndregister (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL,
+               "cb_sndregister (id=%i)\r\n", tr->transactionid));
+}
+
+static void
+cb_sndbye (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL, "cb_sndbye (id=%i)\r\n",
+               tr->transactionid));
+}
+
+static void
+cb_sndcancel (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL,
+               "cb_sndcancel (id=%i)\r\n", tr->transactionid));
+}
+
+static void
+cb_sndinfo (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL, "cb_sndinfo (id=%i)\r\n",
+               tr->transactionid));
+}
+
+static void
+cb_sndoptions (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL,
+               "cb_sndoptions (id=%i)\r\n", tr->transactionid));
+}
+
+static void
+cb_sndnotify (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL,
+               "cb_sndnotify (id=%i)\r\n", tr->transactionid));
+}
+
+static void
+cb_sndsubscribe (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL,
+               "cb_sndsubscibe (id=%i)\r\n", tr->transactionid));
+}
+
+static void
+cb_sndunkrequest (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL,
+               "cb_sndunkrequest (id=%i)\r\n", tr->transactionid));
+}
+
+void
+__eXosip_delete_jinfo (osip_transaction_t * transaction)
+{
+  jinfo_t *ji;
+
+  if (transaction == NULL)
+    return;
+  ji = osip_transaction_get_your_instance (transaction);
+  osip_free (ji);
+  osip_transaction_set_your_instance (transaction, NULL);
+}
+
+jinfo_t *
+__eXosip_new_jinfo (eXosip_call_t * jc, eXosip_dialog_t * jd,
+                    eXosip_subscribe_t * js, eXosip_notify_t * jn)
+{
+  jinfo_t *ji = (jinfo_t *) osip_malloc (sizeof (jinfo_t));
+
+  if (ji == NULL)
+    return NULL;
+  ji->jd = jd;
+  ji->jc = jc;
+  ji->js = js;
+  ji->jn = jn;
+  return ji;
+}
+
+static void
+cb_rcv1xx (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  eXosip_dialog_t *jd;
+  eXosip_call_t *jc;
+  eXosip_subscribe_t *js;
+  eXosip_notify_t *jn;
+  jinfo_t *jinfo = (jinfo_t *) osip_transaction_get_your_instance (tr);
+
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL, "cb_rcv1xx (id=%i)\r\n",
+               tr->transactionid));
+
+  if (eXosip.learn_port>0)
+  {
+      struct eXosip_net *net;
+      net = &eXosip.net_interfaces[0];
+      /* EXOSIP_OPT_UDP_LEARN_PORT option set */
+#if 1
+      /* learn through rport */
+      if (net->net_firewall_ip[0]!='\0')
+      {
+        osip_via_t *via=NULL;
+        osip_generic_param_t *br;
+        int i = osip_message_get_via (sip, 0, &via);
+        if (via!=NULL && via->protocol!=NULL
+            && osip_strcasecmp(via->protocol, "udp")==0)
+        {
+            osip_via_param_get_byname (via, "rport", &br);
+            if (br!=NULL && br->gvalue!=NULL)
+            {
+                snprintf(net->net_port, 20, "%s", br->gvalue);
+                OSIP_TRACE (osip_trace
+                            (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                            "cb_rcv1xx (id=%i) SIP port modified from rport in REGISTER answer\r\n",
+                            tr->transactionid));
+            }
+        }
+      }
+#else
+      /* learn through REGISTER? */
+      if (net->net_firewall_ip[0]!='\0')
+	      {
+		int pos=0;
+		while (!osip_list_eol(reg->contacts,pos))
+		  {
+		    osip_contact_t *co;
+		    co = (osip_contact_t *)osip_list_get(reg->contacts,pos);
+		    pos++;
+		    if (co!=NULL && co->url!=NULL && co->url->host!=NULL
+			&& 0==osip_strcasecmp(co->url->host,
+					      net->net_firewall_ip))
+		      {
+			if (co->url->port==NULL &&
+			    0!=osip_strcasecmp(net->net_port, "5060"))
+			  {
+			    co->url->port=osip_strdup(net->net_port);
+			  }
+			else if (co->url->port!=NULL &&
+				 0!=osip_strcasecmp(net->net_port, co->url->port))
+			  {
+			    osip_free(co->url->port);
+			    co->url->port=osip_strdup(net->net_port);
+			  }
+		      }
+		  }
+	      }
+#endif
+  }
+
+  if (jinfo == NULL)
+    return;
+  jd = jinfo->jd;
+  jc = jinfo->jc;
+  jn = jinfo->jn;
+  js = jinfo->js;
+
+  if (MSG_IS_RESPONSE_FOR (sip, "OPTIONS"))
+    {
+      if (jc == NULL)
+        {
+	  eXosip_event_t *je;
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                       "cb_rcv1xx (id=%i) OPTIONS outside of any call\r\n",
+                       tr->transactionid));
+      
+	  je = eXosip_event_init_for_message (EXOSIP_MESSAGE_PROCEEDING, tr);
+	  eXosip_event_add (je);
+          return;
+      }
+      report_call_event (EXOSIP_CALL_MESSAGE_PROCEEDING, jc, jd, tr);
+      return;
+    }
+
+  if (MSG_IS_RESPONSE_FOR (sip, "INVITE") && MSG_TEST_CODE (sip, 100))
+    {
+      report_call_event (EXOSIP_CALL_PROCEEDING, jc, jd, tr);
+    }
+
+  if ((MSG_IS_RESPONSE_FOR (sip, "INVITE")
+       || MSG_IS_RESPONSE_FOR (sip, "SUBSCRIBE")) && !MSG_TEST_CODE (sip, 100))
+    {
+      int i;
+
+      /* for SUBSCRIBE, test if the dialog has been already created
+         with a previous NOTIFY */
+      if (jd == NULL && js != NULL && js->s_dialogs != NULL
+          && MSG_IS_RESPONSE_FOR (sip, "SUBSCRIBE"))
+        {
+          /* find if existing dialog match the to tag */
+          osip_generic_param_t *tag;
+          int i;
+
+          i = osip_to_get_tag (sip->to, &tag);
+          if (i == 0 && tag != NULL && tag->gvalue != NULL)
+            {
+              for (jd = js->s_dialogs; jd != NULL; jd = jd->next)
+                {
+                  if (0 == strcmp (jd->d_dialog->remote_tag, tag->gvalue))
+                    {
+                      OSIP_TRACE (osip_trace
+                                  (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                                   "eXosip: found established early dialog for this subscribe\n"));
+                      jinfo->jd = jd;
+                      break;
+                    }
+                }
+            }
+        }
+
+      if (jd == NULL)           /* This transaction initiate a dialog in the case of
+                                   INVITE (else it would be attached to a "jd" element. */
+        {
+          /* allocate a jd */
+
+          i = eXosip_dialog_init_as_uac (&jd, sip);
+          if (i != 0)
+            {
+              OSIP_TRACE (osip_trace
+                          (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                           "eXosip: cannot establish a dialog\n"));
+              return;
+            }
+          if (jc != NULL)
+            {
+              ADD_ELEMENT (jc->c_dialogs, jd);
+              jinfo->jd = jd;
+              eXosip_update ();
+          } else if (js != NULL)
+            {
+              ADD_ELEMENT (js->s_dialogs, jd);
+              jinfo->jd = jd;
+              eXosip_update ();
+          } else if (jn != NULL)
+            {
+              ADD_ELEMENT (jn->n_dialogs, jd);
+              jinfo->jd = jd;
+              eXosip_update ();
+          } else
+            {
+#ifndef WIN32
+              assert (0 == 0);
+#else
+              exit (0);
+#endif
+            }
+          osip_transaction_set_your_instance (tr, jinfo);
+      } else
+        {
+          osip_dialog_update_route_set_as_uac (jd->d_dialog, sip);
+        }
+
+      if (jd != NULL)
+        jd->d_STATE = JD_TRYING;
+      if (jd != NULL && MSG_IS_RESPONSE_FOR (sip, "INVITE")
+          && sip->status_code < 180)
+        {
+          report_call_event (EXOSIP_CALL_PROCEEDING, jc, jd, tr);
+      } else if (jd != NULL && MSG_IS_RESPONSE_FOR (sip, "INVITE")
+                 && sip->status_code >= 180)
+        {
+          report_call_event (EXOSIP_CALL_RINGING, jc, jd, tr);
+      } else if (jd != NULL && MSG_IS_RESPONSE_FOR (sip, "SUBSCRIBE"))
+        {
+          eXosip_event_t *je;
+
+          je =
+            eXosip_event_init_for_subscribe (EXOSIP_SUBSCRIPTION_PROCEEDING,
+                                             js, jd, tr);
+          report_event (je, sip);
+        }
+      if (MSG_TEST_CODE (sip, 180) && jd != NULL)
+        {
+          jd->d_STATE = JD_RINGING;
+      } else if (MSG_TEST_CODE (sip, 183) && jd != NULL)
+        {
+          jd->d_STATE = JD_QUEUED;
+        }
+
+    }
+}
+
+static void
+cb_rcv2xx_4invite (osip_transaction_t * tr, osip_message_t * sip)
+{
+  int i;
+  eXosip_dialog_t *jd;
+  eXosip_call_t *jc;
+  jinfo_t *jinfo = (jinfo_t *) osip_transaction_get_your_instance (tr);
+
+  if (jinfo == NULL)
+    return;
+  jd = jinfo->jd;
+  jc = jinfo->jc;
+  if (jd == NULL)               /* This transaction initiate a dialog in the case of
+                                   INVITE (else it would be attached to a "jd" element. */
+    {
+      /* allocate a jd */
+      i = eXosip_dialog_init_as_uac (&jd, sip);
+      if (i != 0)
+        {
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                       "eXosip: cannot establish a dialog\n"));
+          return;
+        }
+      ADD_ELEMENT (jc->c_dialogs, jd);
+      jinfo->jd = jd;
+      eXosip_update ();
+      osip_transaction_set_your_instance (tr, jinfo);
+  } else
+    {
+      /* Here is a special case:
+         We have initiated a dialog and we have received informationnal
+         answers from 2 or more remote SIP UA. Those answer can be
+         differentiated with the "To" header's tag.
+
+         We have used the first informationnal answer to create a
+         dialog, but we now want to be sure the 200ok received is
+         for the dialog this dialog.
+
+         We have to check the To tag and if it does not match, we
+         just have to modify the existing dialog and replace it. */
+      osip_generic_param_t *tag;
+      int i;
+
+      i = osip_to_get_tag (sip->to, &tag);
+      i = 1;                    /* default is the same dialog */
+
+      if (jd->d_dialog == NULL || jd->d_dialog->remote_tag == NULL)
+        {
+          /* There are real use-case where a BYE is received/processed before
+             the 200ok of the previous INVITE. In this case, jd->d_dialog is
+             empty and the transaction should be silently discarded. */
+          /* a ACK should still be sent... -but there is no dialog built- */
+          return;
+        }
+
+      if (jd->d_dialog->remote_tag == NULL && tag == NULL)
+        {
+        } /* non compliant remote UA -> assume it is the same dialog */
+      else if (jd->d_dialog->remote_tag != NULL && tag == NULL)
+        {
+          i = 0;
+        } /* different dialog! */
+      else if (jd->d_dialog->remote_tag == NULL && tag != NULL)
+        {
+          i = 0;
+        } /* different dialog! */
+      else if (jd->d_dialog->remote_tag != NULL && tag != NULL
+               && tag->gvalue != NULL
+               && 0 != strcmp (jd->d_dialog->remote_tag, tag->gvalue))
+        {
+          i = 0;
+        }
+      /* different dialog! */
+      if (i == 1)               /* just update the dialog */
+        {
+          osip_dialog_update_route_set_as_uac (jd->d_dialog, sip);
+          osip_dialog_set_state (jd->d_dialog, DIALOG_CONFIRMED);
+      } else
+        {
+          /* the best thing is to update the repace the current dialog
+             information... Much easier than creating a useless dialog! */
+          osip_dialog_free (jd->d_dialog);
+          i = osip_dialog_init_as_uac (&(jd->d_dialog), sip);
+          if (i != 0)
+            {
+              OSIP_TRACE (osip_trace
+                          (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                           "Cannot replace the dialog.\r\n"));
+          } else
+            {
+              OSIP_TRACE (osip_trace
+                          (__FILE__, __LINE__, OSIP_WARNING, NULL,
+                           "The dialog has been replaced with the new one fro 200ok.\r\n"));
+            }
+        }
+    }
+
+  jd->d_STATE = JD_ESTABLISHED;
+
+  eXosip_dialog_set_200ok (jd, sip);
+
+  report_call_event (EXOSIP_CALL_ANSWERED, jc, jd, tr);
+
+  /* look for the SDP information and decide if this answer was for
+     an initial INVITE, an HoldCall, or a RetreiveCall */
+
+  /* don't handle hold/unhold by now... */
+  /* eXosip_update_audio_session(tr); */
+
+}
+
+static void
+cb_rcv2xx_4subscribe (osip_transaction_t * tr, osip_message_t * sip)
+{
+  int i;
+  eXosip_dialog_t *jd;
+  eXosip_subscribe_t *js;
+  jinfo_t *jinfo = (jinfo_t *) osip_transaction_get_your_instance (tr);
+
+  if (jinfo == NULL)
+    return;
+  jd = jinfo->jd;
+  js = jinfo->js;
+  _eXosip_subscribe_set_refresh_interval (js, sip);
+
+
+  /* for SUBSCRIBE, test if the dialog has been already created
+     with a previous NOTIFY */
+  if (jd == NULL && js != NULL && js->s_dialogs != NULL
+      && MSG_IS_RESPONSE_FOR (sip, "SUBSCRIBE"))
+    {
+      /* find if existing dialog match the to tag */
+      osip_generic_param_t *tag;
+      int i;
+
+      i = osip_to_get_tag (sip->to, &tag);
+      if (i == 0 && tag != NULL && tag->gvalue != NULL)
+        {
+          for (jd = js->s_dialogs; jd != NULL; jd = jd->next)
+            {
+              if (0 == strcmp (jd->d_dialog->remote_tag, tag->gvalue))
+                {
+                  OSIP_TRACE (osip_trace
+                              (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                               "eXosip: found established early dialog for this subscribe\n"));
+                  jinfo->jd = jd;
+                  break;
+                }
+            }
+        }
+    }
+
+  if (jd == NULL)               /* This transaction initiate a dialog in the case of
+                                   SUBSCRIBE (else it would be attached to a "jd" element. */
+    {
+      /* allocate a jd */
+      i = eXosip_dialog_init_as_uac (&jd, sip);
+      if (i != 0)
+        {
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                       "eXosip: cannot establish a dialog\n"));
+          return;
+        }
+      ADD_ELEMENT (js->s_dialogs, jd);
+      jinfo->jd = jd;
+      eXosip_update ();
+      osip_transaction_set_your_instance (tr, jinfo);
+  } else
+    {
+      osip_dialog_update_route_set_as_uac (jd->d_dialog, sip);
+      osip_dialog_set_state (jd->d_dialog, DIALOG_CONFIRMED);
+    }
+
+  jd->d_STATE = JD_ESTABLISHED;
+  /* look for the body information */
+
+  {
+    eXosip_event_t *je;
+
+    je =
+      eXosip_event_init_for_subscribe (EXOSIP_SUBSCRIPTION_ANSWERED, js, jd, tr);
+    report_event (je, sip);
+  }
+
+}
+
+static void
+cb_rcv2xx (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  eXosip_dialog_t *jd;
+  eXosip_call_t *jc;
+  eXosip_subscribe_t *js;
+  eXosip_notify_t *jn;
+  jinfo_t *jinfo = (jinfo_t *) osip_transaction_get_your_instance (tr);
+
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL, "cb_rcv2xx (id=%i)\r\n",
+               tr->transactionid));
+
+  if (MSG_IS_RESPONSE_FOR (sip, "PUBLISH"))
+    {
+      eXosip_pub_t *pub;
+      eXosip_event_t *je;
+      int i;
+
+      i = _eXosip_pub_update (&pub, tr, sip);
+      if (i != 0)
+        {
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                       "cb_rcv2xx (id=%i) No publication to update\r\n",
+                       tr->transactionid));
+        }
+      je = eXosip_event_init_for_message (EXOSIP_MESSAGE_ANSWERED, tr);
+      report_event (je, sip);
+      return;
+  } else if (MSG_IS_RESPONSE_FOR (sip, "REGISTER"))
+    {
+      eXosip_event_t *je;
+      eXosip_reg_t *jreg = NULL;
+
+      /* find matching j_reg */
+      _eXosip_reg_find (&jreg, tr);
+      if (jreg != NULL)
+        {
+          je = eXosip_event_init_for_reg (EXOSIP_REGISTRATION_SUCCESS, jreg, tr);
+          report_event (je, sip);
+          jreg->r_retry = 0;    /* reset value */
+        }
+
+
+        if (eXosip.learn_port>0)
+        {
+            struct eXosip_net *net;
+            net = &eXosip.net_interfaces[0];
+            /* EXOSIP_OPT_UDP_LEARN_PORT option set */
+#if 1
+            /* learn through rport */
+           if (net->net_firewall_ip[0]!='\0')
+           { 
+                osip_via_t *via=NULL;
+                osip_generic_param_t *br;
+                int i = osip_message_get_via (sip, 0, &via);
+                if (via!=NULL && via->protocol!=NULL
+                    && osip_strcasecmp(via->protocol, "udp")==0)
+                {
+                    osip_via_param_get_byname (via, "rport", &br);
+                    if (br!=NULL && br->gvalue!=NULL)
+                    {
+                        snprintf(net->net_port, 20, "%s", br->gvalue);
+                        OSIP_TRACE (osip_trace
+                            (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                            "cb_rcv1xx (id=%i) SIP port modified from rport in REGISTER answer\r\n",
+                            tr->transactionid));
+                    }
+                }
+            }
+#else
+            /* learn through REGISTER? */
+            if (net->net_firewall_ip[0]!='\0')
+            {
+                int pos=0;
+                while (!osip_list_eol(reg->contacts,pos))
+                {
+                    osip_contact_t *co;
+                    co = (osip_contact_t *)osip_list_get(reg->contacts,pos);
+                    pos++;
+                    if (co!=NULL && co->url!=NULL && co->url->host!=NULL
+                        && 0==osip_strcasecmp(co->url->host,
+                        net->net_firewall_ip))
+                    {
+                        if (co->url->port==NULL &&
+                            0!=osip_strcasecmp(net->net_port, "5060"))
+                        {
+                            co->url->port=osip_strdup(net->net_port);
+                        }
+                        else if (co->url->port!=NULL &&
+                            0!=osip_strcasecmp(net->net_port, co->url->port))
+                        {
+                            osip_free(co->url->port);
+                            co->url->port=osip_strdup(net->net_port);
+                        }
+                    }
+                }
+            }
+#endif
+        }
+
+        return;
+  }
+
+  if (jinfo == NULL)
+    return;
+  jd = jinfo->jd;
+  jc = jinfo->jc;
+  jn = jinfo->jn;
+  js = jinfo->js;
+
+  if (jd != NULL)
+    jd->d_retry = 0;            /* reset marker for authentication */
+  if (jc != NULL)
+    jc->c_retry = 0;            /* reset marker for authentication */
+  if (js != NULL)
+    js->s_retry = 0;            /* reset marker for authentication */
+
+  if (MSG_IS_RESPONSE_FOR (sip, "INVITE"))
+    {
+      cb_rcv2xx_4invite (tr, sip);
+  } else if (MSG_IS_RESPONSE_FOR (sip, "SUBSCRIBE"))
+    {
+      cb_rcv2xx_4subscribe (tr, sip);
+  } else if (MSG_IS_RESPONSE_FOR (sip, "BYE"))
+    {
+      if (jd != NULL)
+        jd->d_STATE = JD_TERMINATED;
+  } else if (MSG_IS_RESPONSE_FOR (sip, "NOTIFY"))
+    {
+#ifdef SUPPORT_MSN
+      osip_header_t *expires;
+
+      osip_message_header_get_byname (tr->orig_request, "expires", 0, &expires);
+      if (expires == NULL || expires->hvalue == NULL)
+        {
+          /* UNCOMPLIANT UA without a subscription-state header */
+      } else if (0 == osip_strcasecmp (expires->hvalue, "0"))
+        {
+          /* delete the dialog! */
+          if (jn != NULL)
+            {
+              REMOVE_ELEMENT (eXosip.j_notifies, jn);
+              eXosip_notify_free (jn);
+            }
+        }
+#else
+      osip_header_t *sub_state;
+
+      osip_message_header_get_byname (tr->orig_request, "subscription-state",
+                                      0, &sub_state);
+      if (sub_state == NULL || sub_state->hvalue == NULL)
+        {
+          /* UNCOMPLIANT UA without a subscription-state header */
+      } else if (0 == osip_strncasecmp (sub_state->hvalue, "terminated", 10))
+        {
+          /* delete the dialog! */
+          if (jn != NULL)
+            {
+              REMOVE_ELEMENT (eXosip.j_notifies, jn);
+              eXosip_notify_free (jn);
+            }
+        }
+#endif
+  } else if (jc!=NULL)
+    {
+      report_call_event (EXOSIP_CALL_MESSAGE_ANSWERED, jc, jd, tr);
+      return;
+  } else if (jc==NULL && js==NULL && jn==NULL)
+    {
+      eXosip_event_t *je;
+      /* For all requests outside of calls */
+      je = eXosip_event_init_for_message (EXOSIP_MESSAGE_ANSWERED, tr);
+      report_event (je, sip);
+      return;
+    }
+}
+
+void
+eXosip_delete_early_dialog (eXosip_dialog_t * jd)
+{
+  if (jd == NULL)               /* bug? */
+    return;
+
+  /* an early dialog was created, but the call is not established */
+  if (jd->d_dialog != NULL && jd->d_dialog->state == DIALOG_EARLY)
+    {
+      osip_dialog_free (jd->d_dialog);
+      jd->d_dialog = NULL;
+      eXosip_update(); //AMD 30/09/05
+      eXosip_dialog_set_state (jd, JD_TERMINATED);
+    }
+}
+
+static void
+rcvregister_failure (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  eXosip_event_t *je;
+  eXosip_reg_t *jreg = NULL;
+
+  /* find matching j_reg */
+  _eXosip_reg_find (&jreg, tr);
+  if (jreg != NULL)
+    {
+      je = eXosip_event_init_for_reg (EXOSIP_REGISTRATION_FAILURE, jreg, tr);
+      report_event (je, sip);
+    }
+}
+
+static void
+cb_rcv3xx (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  eXosip_dialog_t *jd;
+  eXosip_call_t *jc;
+  eXosip_subscribe_t *js;
+  eXosip_notify_t *jn;
+  jinfo_t *jinfo = (jinfo_t *) osip_transaction_get_your_instance (tr);
+
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL, "cb_rcv3xx (id=%i)\r\n",
+               tr->transactionid));
+
+  if (MSG_IS_RESPONSE_FOR (sip, "PUBLISH"))
+    {
+      eXosip_event_t *je;
+      eXosip_pub_t *pub;
+      int i;
+
+      i = _eXosip_pub_update (&pub, tr, sip);
+      if (i != 0)
+        {
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                       "cb_rcv3xx (id=%i) No publication to update\r\n",
+                       tr->transactionid));
+        }
+      je = eXosip_event_init_for_message (EXOSIP_MESSAGE_REDIRECTED, tr);
+      report_event (je, sip);
+      return;
+  } else if (MSG_IS_RESPONSE_FOR (sip, "REGISTER"))
+    {
+      rcvregister_failure (type, tr, sip);
+      return;
+    }
+
+  if (jinfo == NULL)
+    return;
+  jd = jinfo->jd;
+  jc = jinfo->jc;
+  jn = jinfo->jn;
+  js = jinfo->js;
+
+  if (MSG_IS_RESPONSE_FOR (sip, "INVITE"))
+    {
+      report_call_event (EXOSIP_CALL_REDIRECTED, jc, jd, tr);
+  } else if (MSG_IS_RESPONSE_FOR (sip, "SUBSCRIBE"))
+    {
+      eXosip_event_t *je;
+
+      je =
+        eXosip_event_init_for_subscribe (EXOSIP_SUBSCRIPTION_REDIRECTED, js,
+                                         jd, tr);
+      report_event (je, sip);
+  } else if (jc!=NULL)
+    {
+      report_call_event (EXOSIP_CALL_MESSAGE_REDIRECTED, jc, jd, tr);
+      return;
+  } else if (jc==NULL && js==NULL && jn==NULL)
+    {
+      eXosip_event_t *je;
+      /* For all requests outside of calls */
+      je = eXosip_event_init_for_message (EXOSIP_MESSAGE_REDIRECTED, tr);
+      report_event (je, sip);
+      return;
+    }
+
+  if (jd == NULL)
+    return;
+  if (MSG_IS_RESPONSE_FOR (sip, "INVITE")
+      || MSG_IS_RESPONSE_FOR (sip, "SUBSCRIBE"))
+    {
+      eXosip_delete_early_dialog (jd);
+      if (jd->d_dialog == NULL)
+        jd->d_STATE = JD_REDIRECTED;
+    }
+
+}
+
+static void
+cb_rcv4xx (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  eXosip_dialog_t *jd;
+  eXosip_call_t *jc;
+  eXosip_subscribe_t *js;
+  eXosip_notify_t *jn;
+  jinfo_t *jinfo = (jinfo_t *) osip_transaction_get_your_instance (tr);
+
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL, "cb_rcv4xx (id=%i)\r\n",
+               tr->transactionid));
+
+  if (MSG_IS_RESPONSE_FOR (sip, "PUBLISH"))
+    {
+      eXosip_pub_t *pub;
+      eXosip_event_t *je; 
+      int i;
+
+      i = _eXosip_pub_update (&pub, tr, sip);
+      if (i != 0)
+        {
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                       "cb_rcv4xx (id=%i) No publication to update\r\n",
+                       tr->transactionid));
+        }
+      /* For all requests outside of calls */
+      je = eXosip_event_init_for_message (EXOSIP_MESSAGE_REQUESTFAILURE, tr);
+      report_event (je, sip);
+      return;
+  } else if (MSG_IS_RESPONSE_FOR (sip, "REGISTER"))
+    {
+      rcvregister_failure (type, tr, sip);
+      return;
+    }
+
+  if (jinfo == NULL)
+    return;
+  jd = jinfo->jd;
+  jc = jinfo->jc;
+  jn = jinfo->jn;
+  js = jinfo->js;
+
+  if (MSG_IS_RESPONSE_FOR (sip, "INVITE"))
+    {
+      report_call_event (EXOSIP_CALL_REQUESTFAILURE, jc, jd, tr);
+  } else if (MSG_IS_RESPONSE_FOR (sip, "SUBSCRIBE"))
+    {
+      eXosip_event_t *je;
+
+      je =
+        eXosip_event_init_for_subscribe (EXOSIP_SUBSCRIPTION_REQUESTFAILURE,
+                                         js, jd, tr);
+      report_event (je, sip);
+  } else if (jc!=NULL)
+    {
+      report_call_event (EXOSIP_CALL_MESSAGE_REQUESTFAILURE, jc, jd, tr);
+      return;
+  } else if (jc==NULL && js==NULL && jn==NULL)
+    {
+      eXosip_event_t *je;
+      /* For all requests outside of calls */
+      je = eXosip_event_init_for_message (EXOSIP_MESSAGE_REQUESTFAILURE, tr);
+      report_event (je, sip);
+      return;
+    }
+
+  if (jc!=NULL)
+    {
+      if (MSG_TEST_CODE (sip, 401) || MSG_TEST_CODE (sip, 407))
+	{
+	  if (jc->response_auth!=NULL)
+	    osip_message_free(jc->response_auth);
+	  
+	  osip_message_clone(sip, &jc->response_auth);
+	}
+    }
+  if (jd == NULL)
+    return;
+  if (MSG_IS_RESPONSE_FOR (sip, "INVITE")
+      || MSG_IS_RESPONSE_FOR (sip, "SUBSCRIBE"))
+    {
+      eXosip_delete_early_dialog (jd);
+      if (MSG_TEST_CODE (sip, 401) || MSG_TEST_CODE (sip, 407))
+        jd->d_STATE = JD_AUTH_REQUIRED;
+      else
+        jd->d_STATE = JD_CLIENTERROR;
+    }
+
+}
+
+static void
+cb_rcv5xx (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  eXosip_dialog_t *jd;
+  eXosip_call_t *jc;
+  eXosip_subscribe_t *js;
+  eXosip_notify_t *jn;
+  jinfo_t *jinfo = (jinfo_t *) osip_transaction_get_your_instance (tr);
+
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL, "cb_rcv5xx (id=%i)\r\n",
+               tr->transactionid));
+
+  if (MSG_IS_RESPONSE_FOR (sip, "PUBLISH"))
+    {
+      eXosip_pub_t *pub;
+      eXosip_event_t *je;
+      int i;
+
+      i = _eXosip_pub_update (&pub, tr, sip);
+      if (i != 0)
+        {
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                       "cb_rcv3xx (id=%i) No publication to update\r\n",
+                       tr->transactionid));
+        }
+      je = eXosip_event_init_for_message (EXOSIP_MESSAGE_SERVERFAILURE, tr);
+      report_event (je, sip);
+      return;
+  } else if (MSG_IS_RESPONSE_FOR (sip, "REGISTER"))
+    {
+      rcvregister_failure (type, tr, sip);
+      return;
+    }
+
+  if (jinfo == NULL)
+    return;
+  jd = jinfo->jd;
+  jc = jinfo->jc;
+  jn = jinfo->jn;
+  js = jinfo->js;
+
+  if (MSG_IS_RESPONSE_FOR (sip, "INVITE"))
+    {
+      report_call_event (EXOSIP_CALL_SERVERFAILURE, jc, jd, tr);
+  } else if (MSG_IS_RESPONSE_FOR (sip, "SUBSCRIBE"))
+    {
+      eXosip_event_t *je;
+
+      je =
+        eXosip_event_init_for_subscribe (EXOSIP_SUBSCRIPTION_SERVERFAILURE,
+                                         js, jd, tr);
+      report_event (je, sip);
+  } else if (jc!=NULL)
+    {
+      report_call_event (EXOSIP_CALL_MESSAGE_SERVERFAILURE, jc, jd, tr);
+      return;
+  } else if (jc==NULL && js==NULL && jn==NULL)
+    {
+      eXosip_event_t *je;
+      /* For all requests outside of calls */
+      je = eXosip_event_init_for_message (EXOSIP_MESSAGE_SERVERFAILURE, tr);
+      report_event (je, sip);
+      return;
+    }
+
+  if (jd == NULL)
+    return;
+  if (MSG_IS_RESPONSE_FOR (sip, "INVITE")
+      || MSG_IS_RESPONSE_FOR (sip, "SUBSCRIBE"))
+    {
+      eXosip_delete_early_dialog (jd);
+      jd->d_STATE = JD_SERVERERROR;
+    }
+
+}
+
+static void
+cb_rcv6xx (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  eXosip_dialog_t *jd;
+  eXosip_call_t *jc;
+  eXosip_subscribe_t *js;
+  eXosip_notify_t *jn;
+  jinfo_t *jinfo = (jinfo_t *) osip_transaction_get_your_instance (tr);
+
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL, "cb_rcv6xx (id=%i)\r\n",
+               tr->transactionid));
+
+  if (MSG_IS_RESPONSE_FOR (sip, "PUBLISH"))
+    {
+      eXosip_pub_t *pub;
+      eXosip_event_t *je;
+      int i;
+
+      i = _eXosip_pub_update (&pub, tr, sip);
+      if (i != 0)
+        {
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                       "cb_rcv6xx (id=%i) No publication to update\r\n",
+                       tr->transactionid));
+        }
+      je = eXosip_event_init_for_message (EXOSIP_MESSAGE_GLOBALFAILURE, tr);
+      report_event (je, sip);
+      return;
+  } else if (MSG_IS_RESPONSE_FOR (sip, "REGISTER"))
+    {
+      rcvregister_failure (type, tr, sip);
+      return;
+    }
+
+  if (jinfo == NULL)
+    return;
+  jd = jinfo->jd;
+  jc = jinfo->jc;
+  jn = jinfo->jn;
+  js = jinfo->js;
+
+  if (MSG_IS_RESPONSE_FOR (sip, "INVITE"))
+    {
+      report_call_event (EXOSIP_CALL_GLOBALFAILURE, jc, jd, tr);
+  } else if (MSG_IS_RESPONSE_FOR (sip, "SUBSCRIBE"))
+    {
+      eXosip_event_t *je;
+
+      je =
+        eXosip_event_init_for_subscribe (EXOSIP_SUBSCRIPTION_GLOBALFAILURE,
+                                         js, jd, tr);
+      report_event (je, sip);
+  } else if (jc!=NULL)
+    {
+      report_call_event (EXOSIP_CALL_MESSAGE_GLOBALFAILURE, jc, jd, tr);
+      return;
+  } else if (jc==NULL && js==NULL && jn==NULL)
+    {
+      eXosip_event_t *je;
+      /* For all requests outside of calls */
+      je = eXosip_event_init_for_message (EXOSIP_MESSAGE_GLOBALFAILURE, tr);
+      report_event (je, sip);
+      return;
+    }
+
+  if (jd == NULL)
+    return;
+  if (MSG_IS_RESPONSE_FOR (sip, "INVITE")
+      || MSG_IS_RESPONSE_FOR (sip, "SUBSCRIBE"))
+    {
+      eXosip_delete_early_dialog (jd);
+      jd->d_STATE = JD_GLOBALFAILURE;
+    }
+
+}
+
+static void
+cb_snd1xx (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  eXosip_dialog_t *jd;
+  eXosip_call_t *jc;
+  jinfo_t *jinfo = (jinfo_t *) osip_transaction_get_your_instance (tr);
+
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL, "cb_snd1xx (id=%i)\r\n",
+               tr->transactionid));
+
+  if (jinfo == NULL)
+    return;
+  jd = jinfo->jd;
+  jc = jinfo->jc;
+  if (jd == NULL)
+    return;
+  jd->d_STATE = JD_TRYING;
+}
+
+static void
+cb_snd2xx (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  eXosip_dialog_t *jd;
+  eXosip_call_t *jc;
+  jinfo_t *jinfo = (jinfo_t *) osip_transaction_get_your_instance (tr);
+
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL, "cb_snd2xx (id=%i)\r\n",
+               tr->transactionid));
+  if (jinfo == NULL)
+    return;
+  jd = jinfo->jd;
+  jc = jinfo->jc;
+  if (jd == NULL)
+    return;
+  if (MSG_IS_RESPONSE_FOR (sip, "INVITE")
+      || MSG_IS_RESPONSE_FOR (sip, "SUBSCRIBE"))
+    {
+      jd->d_STATE = JD_ESTABLISHED;
+      return;
+    }
+  jd->d_STATE = JD_ESTABLISHED;
+}
+
+static void
+cb_snd3xx (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  eXosip_dialog_t *jd;
+  eXosip_call_t *jc;
+  jinfo_t *jinfo = (jinfo_t *) osip_transaction_get_your_instance (tr);
+
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL, "cb_snd3xx (id=%i)\r\n",
+               tr->transactionid));
+  if (jinfo == NULL)
+    return;
+  jd = jinfo->jd;
+  jc = jinfo->jc;
+  if (jd == NULL)
+    return;
+  if (MSG_IS_RESPONSE_FOR (sip, "INVITE")
+      || MSG_IS_RESPONSE_FOR (sip, "SUBSCRIBE"))
+    {
+      eXosip_delete_early_dialog (jd);
+    }
+  jd->d_STATE = JD_REDIRECTED;
+
+  if (MSG_IS_RESPONSE_FOR (sip, "INVITE"))
+    {
+      /* only close calls if this is the initial INVITE */
+      if (jc!=NULL && tr == jc->c_inc_tr)
+	{
+	  report_call_event (EXOSIP_CALL_CLOSED, jc, jd, tr);
+	}
+    }
+}
+
+static void
+cb_snd4xx (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  eXosip_dialog_t *jd;
+  eXosip_call_t *jc;
+  jinfo_t *jinfo = (jinfo_t *) osip_transaction_get_your_instance (tr);
+
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL, "cb_snd4xx (id=%i)\r\n",
+               tr->transactionid));
+  if (jinfo == NULL)
+    return;
+  jd = jinfo->jd;
+  jc = jinfo->jc;
+  if (jd == NULL)
+    return;
+  if (MSG_IS_RESPONSE_FOR (sip, "INVITE")
+      || MSG_IS_RESPONSE_FOR (sip, "SUBSCRIBE"))
+    {
+      eXosip_delete_early_dialog (jd);
+    }
+  jd->d_STATE = JD_CLIENTERROR;
+
+  if (MSG_IS_RESPONSE_FOR (sip, "INVITE"))
+    {
+      /* only close calls if this is the initial INVITE */
+      if (jc!=NULL && tr == jc->c_inc_tr)
+	{
+	  report_call_event (EXOSIP_CALL_CLOSED, jc, jd, tr);
+	}
+    }
+
+}
+
+static void
+cb_snd5xx (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  eXosip_dialog_t *jd;
+  eXosip_call_t *jc;
+  jinfo_t *jinfo = (jinfo_t *) osip_transaction_get_your_instance (tr);
+
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL, "cb_snd5xx (id=%i)\r\n",
+               tr->transactionid));
+  if (jinfo == NULL)
+    return;
+  jd = jinfo->jd;
+  jc = jinfo->jc;
+  if (jd == NULL)
+    return;
+  if (MSG_IS_RESPONSE_FOR (sip, "INVITE")
+      || MSG_IS_RESPONSE_FOR (sip, "SUBSCRIBE"))
+    {
+      eXosip_delete_early_dialog (jd);
+    }
+  jd->d_STATE = JD_SERVERERROR;
+
+  if (MSG_IS_RESPONSE_FOR (sip, "INVITE"))
+    {
+      /* only close calls if this is the initial INVITE */
+      if (jc!=NULL && tr == jc->c_inc_tr)
+	{
+	  report_call_event (EXOSIP_CALL_CLOSED, jc, jd, tr);
+	}
+    }
+
+}
+
+static void
+cb_snd6xx (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  eXosip_dialog_t *jd;
+  eXosip_call_t *jc;
+  jinfo_t *jinfo = (jinfo_t *) osip_transaction_get_your_instance (tr);
+
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL, "cb_snd6xx (id=%i)\r\n",
+               tr->transactionid));
+  if (jinfo == NULL)
+    return;
+  jd = jinfo->jd;
+  jc = jinfo->jc;
+  if (jd == NULL)
+    return;
+  if (MSG_IS_RESPONSE_FOR (sip, "INVITE")
+      || MSG_IS_RESPONSE_FOR (sip, "SUBSCRIBE"))
+    {
+      eXosip_delete_early_dialog (jd);
+    }
+  jd->d_STATE = JD_GLOBALFAILURE;
+
+  if (MSG_IS_RESPONSE_FOR (sip, "INVITE"))
+    {
+      /* only close calls if this is the initial INVITE */
+      if (jc!=NULL && tr == jc->c_inc_tr)
+	{
+	  report_call_event (EXOSIP_CALL_CLOSED, jc, jd, tr);
+	}
+    }
+
+}
+
+static void
+cb_rcvresp_retransmission (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL,
+               "cb_rcvresp_retransmission (id=%i)\r\n", tr->transactionid));
+}
+
+static void
+cb_sndreq_retransmission (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL,
+               "cb_sndreq_retransmission (id=%i)\r\n", tr->transactionid));
+}
+
+static void
+cb_sndresp_retransmission (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL,
+               "cb_sndresp_retransmission (id=%i)\r\n", tr->transactionid));
+}
+
+static void
+cb_rcvreq_retransmission (int type, osip_transaction_t * tr, osip_message_t * sip)
+{
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL,
+               "cb_rcvreq_retransmission (id=%i)\r\n", tr->transactionid));
+}
+
+static void
+cb_transport_error (int type, osip_transaction_t * tr, int error)
+{
+  eXosip_dialog_t *jd;
+  eXosip_call_t *jc;
+  eXosip_subscribe_t *js;
+  eXosip_notify_t *jn;
+  jinfo_t *jinfo = (jinfo_t *) osip_transaction_get_your_instance (tr);
+
+  OSIP_TRACE (osip_trace
+              (__FILE__, __LINE__, OSIP_INFO1, NULL,
+               "cb_transport_error (id=%i)\r\n", tr->transactionid));
+  if (jinfo == NULL)
+    return;
+  jd = jinfo->jd;
+  jc = jinfo->jc;
+  jn = jinfo->jn;
+  js = jinfo->js;
+
+  if (jn == NULL && js == NULL)
+    return;
+
+  if (MSG_IS_NOTIFY (tr->orig_request) && type == OSIP_NICT_TRANSPORT_ERROR)
+    {
+      /* delete the dialog! */
+      REMOVE_ELEMENT (eXosip.j_notifies, jn);
+      eXosip_notify_free (jn);
+    }
+
+  if (MSG_IS_SUBSCRIBE (tr->orig_request) && type == OSIP_NICT_TRANSPORT_ERROR)
+    {
+      /* delete the dialog! */
+      REMOVE_ELEMENT (eXosip.j_subscribes, js);
+      eXosip_subscribe_free (js);
+    }
+
+  if (MSG_IS_OPTIONS (tr->orig_request) && jc->c_dialogs == NULL
+      && type == OSIP_NICT_TRANSPORT_ERROR)
+    {
+      /* delete the dialog! */
+      REMOVE_ELEMENT (eXosip.j_calls, jc);
+      eXosip_call_free (jc);
+    }
+}
+
+
+
+int
+eXosip_set_callbacks (osip_t * osip)
+{
+  /* register all callbacks */
+
+  osip_set_cb_send_message (osip, &cb_snd_message);
+
+  osip_set_kill_transaction_callback (osip, OSIP_ICT_KILL_TRANSACTION,
+                                      &cb_ict_kill_transaction);
+  osip_set_kill_transaction_callback (osip, OSIP_IST_KILL_TRANSACTION,
+                                      &cb_ist_kill_transaction);
+  osip_set_kill_transaction_callback (osip, OSIP_NICT_KILL_TRANSACTION,
+                                      &cb_nict_kill_transaction);
+  osip_set_kill_transaction_callback (osip, OSIP_NIST_KILL_TRANSACTION,
+                                      &cb_nist_kill_transaction);
+
+  osip_set_message_callback (osip, OSIP_ICT_STATUS_2XX_RECEIVED_AGAIN,
+                             &cb_rcvresp_retransmission);
+  osip_set_message_callback (osip, OSIP_ICT_STATUS_3456XX_RECEIVED_AGAIN,
+                             &cb_rcvresp_retransmission);
+  osip_set_message_callback (osip, OSIP_ICT_INVITE_SENT_AGAIN,
+                             &cb_sndreq_retransmission);
+  osip_set_message_callback (osip, OSIP_IST_STATUS_2XX_SENT_AGAIN,
+                             &cb_sndresp_retransmission);
+  osip_set_message_callback (osip, OSIP_IST_STATUS_3456XX_SENT_AGAIN,
+                             &cb_sndresp_retransmission);
+  osip_set_message_callback (osip, OSIP_IST_INVITE_RECEIVED_AGAIN,
+                             &cb_rcvreq_retransmission);
+  osip_set_message_callback (osip, OSIP_NICT_STATUS_2XX_RECEIVED_AGAIN,
+                             &cb_rcvresp_retransmission);
+  osip_set_message_callback (osip, OSIP_NICT_STATUS_3456XX_RECEIVED_AGAIN,
+                             &cb_rcvresp_retransmission);
+  osip_set_message_callback (osip, OSIP_NICT_REQUEST_SENT_AGAIN,
+                             &cb_sndreq_retransmission);
+  osip_set_message_callback (osip, OSIP_NIST_STATUS_2XX_SENT_AGAIN,
+                             &cb_sndresp_retransmission);
+  osip_set_message_callback (osip, OSIP_NIST_STATUS_3456XX_SENT_AGAIN,
+                             &cb_sndresp_retransmission);
+  osip_set_message_callback (osip, OSIP_NIST_REQUEST_RECEIVED_AGAIN,
+                             &cb_rcvreq_retransmission);
+
+  osip_set_transport_error_callback (osip, OSIP_ICT_TRANSPORT_ERROR,
+                                     &cb_transport_error);
+  osip_set_transport_error_callback (osip, OSIP_IST_TRANSPORT_ERROR,
+                                     &cb_transport_error);
+  osip_set_transport_error_callback (osip, OSIP_NICT_TRANSPORT_ERROR,
+                                     &cb_transport_error);
+  osip_set_transport_error_callback (osip, OSIP_NIST_TRANSPORT_ERROR,
+                                     &cb_transport_error);
+
+  osip_set_message_callback (osip, OSIP_ICT_INVITE_SENT, &cb_sndinvite);
+  osip_set_message_callback (osip, OSIP_ICT_ACK_SENT, &cb_sndack);
+  osip_set_message_callback (osip, OSIP_NICT_REGISTER_SENT, &cb_sndregister);
+  osip_set_message_callback (osip, OSIP_NICT_BYE_SENT, &cb_sndbye);
+  osip_set_message_callback (osip, OSIP_NICT_CANCEL_SENT, &cb_sndcancel);
+  osip_set_message_callback (osip, OSIP_NICT_INFO_SENT, &cb_sndinfo);
+  osip_set_message_callback (osip, OSIP_NICT_OPTIONS_SENT, &cb_sndoptions);
+  osip_set_message_callback (osip, OSIP_NICT_SUBSCRIBE_SENT, &cb_sndsubscribe);
+  osip_set_message_callback (osip, OSIP_NICT_NOTIFY_SENT, &cb_sndnotify);
+  /*  osip_set_cb_nict_sndprack   (osip,&cb_sndprack); */
+  osip_set_message_callback (osip, OSIP_NICT_UNKNOWN_REQUEST_SENT,
+                             &cb_sndunkrequest);
+
+  osip_set_message_callback (osip, OSIP_ICT_STATUS_1XX_RECEIVED, &cb_rcv1xx);
+  osip_set_message_callback (osip, OSIP_ICT_STATUS_2XX_RECEIVED, &cb_rcv2xx);
+  osip_set_message_callback (osip, OSIP_ICT_STATUS_3XX_RECEIVED, &cb_rcv3xx);
+  osip_set_message_callback (osip, OSIP_ICT_STATUS_4XX_RECEIVED, &cb_rcv4xx);
+  osip_set_message_callback (osip, OSIP_ICT_STATUS_5XX_RECEIVED, &cb_rcv5xx);
+  osip_set_message_callback (osip, OSIP_ICT_STATUS_6XX_RECEIVED, &cb_rcv6xx);
+
+  osip_set_message_callback (osip, OSIP_IST_STATUS_1XX_SENT, &cb_snd1xx);
+  osip_set_message_callback (osip, OSIP_IST_STATUS_2XX_SENT, &cb_snd2xx);
+  osip_set_message_callback (osip, OSIP_IST_STATUS_3XX_SENT, &cb_snd3xx);
+  osip_set_message_callback (osip, OSIP_IST_STATUS_4XX_SENT, &cb_snd4xx);
+  osip_set_message_callback (osip, OSIP_IST_STATUS_5XX_SENT, &cb_snd5xx);
+  osip_set_message_callback (osip, OSIP_IST_STATUS_6XX_SENT, &cb_snd6xx);
+
+  osip_set_message_callback (osip, OSIP_NICT_STATUS_1XX_RECEIVED, &cb_rcv1xx);
+  osip_set_message_callback (osip, OSIP_NICT_STATUS_2XX_RECEIVED, &cb_rcv2xx);
+  osip_set_message_callback (osip, OSIP_NICT_STATUS_3XX_RECEIVED, &cb_rcv3xx);
+  osip_set_message_callback (osip, OSIP_NICT_STATUS_4XX_RECEIVED, &cb_rcv4xx);
+  osip_set_message_callback (osip, OSIP_NICT_STATUS_5XX_RECEIVED, &cb_rcv5xx);
+  osip_set_message_callback (osip, OSIP_NICT_STATUS_6XX_RECEIVED, &cb_rcv6xx);
+
+  osip_set_message_callback (osip, OSIP_NIST_STATUS_1XX_SENT, &cb_snd1xx);
+  osip_set_message_callback (osip, OSIP_NIST_STATUS_2XX_SENT, &cb_snd2xx);
+  osip_set_message_callback (osip, OSIP_NIST_STATUS_3XX_SENT, &cb_snd3xx);
+  osip_set_message_callback (osip, OSIP_NIST_STATUS_4XX_SENT, &cb_snd4xx);
+  osip_set_message_callback (osip, OSIP_NIST_STATUS_5XX_SENT, &cb_snd5xx);
+  osip_set_message_callback (osip, OSIP_NIST_STATUS_6XX_SENT, &cb_snd6xx);
+
+  osip_set_message_callback (osip, OSIP_IST_INVITE_RECEIVED, &cb_rcvinvite);
+  osip_set_message_callback (osip, OSIP_IST_ACK_RECEIVED, &cb_rcvack);
+  osip_set_message_callback (osip, OSIP_IST_ACK_RECEIVED_AGAIN, &cb_rcvack2);
+  osip_set_message_callback (osip, OSIP_NIST_REGISTER_RECEIVED, &cb_rcvregister);
+  osip_set_message_callback (osip, OSIP_NIST_CANCEL_RECEIVED, &cb_rcvcancel);
+  osip_set_message_callback (osip, OSIP_NIST_BYE_RECEIVED, &cb_rcvrequest);
+  osip_set_message_callback (osip, OSIP_NIST_INFO_RECEIVED, &cb_rcvrequest);
+  osip_set_message_callback (osip, OSIP_NIST_OPTIONS_RECEIVED, &cb_rcvrequest);
+  osip_set_message_callback (osip, OSIP_NIST_SUBSCRIBE_RECEIVED, &cb_rcvrequest);
+  osip_set_message_callback (osip, OSIP_NIST_NOTIFY_RECEIVED, &cb_rcvrequest);
+  osip_set_message_callback (osip, OSIP_NIST_UNKNOWN_REQUEST_RECEIVED,
+                             &cb_rcvrequest);
+
+  return 0;
+}
diff --git a/exosip2/jdialog.c b/exosip2/jdialog.c
new file mode 100644
index 0000000000..d8010252cb
--- /dev/null
+++ b/exosip2/jdialog.c
@@ -0,0 +1,217 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002, 2003  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+#include "eXosip2.h"
+
+extern eXosip_t eXosip;
+
+void
+eXosip_dialog_set_state (eXosip_dialog_t * jd, int state)
+{
+  jd->d_STATE = state;
+}
+
+
+int
+eXosip_call_dialog_find (int jid, eXosip_call_t ** jc, eXosip_dialog_t ** jd)
+{
+  for (*jc = eXosip.j_calls; *jc != NULL; *jc = (*jc)->next)
+    {
+      for (*jd = (*jc)->c_dialogs; *jd != NULL; *jd = (*jd)->next)
+        {
+          if ((*jd)->d_id == jid)
+            return 0;
+        }
+    }
+  *jd = NULL;
+  *jc = NULL;
+  return -1;
+}
+
+int
+eXosip_notify_dialog_find (int nid, eXosip_notify_t ** jn, eXosip_dialog_t ** jd)
+{
+  for (*jn = eXosip.j_notifies; *jn != NULL; *jn = (*jn)->next)
+    {
+      for (*jd = (*jn)->n_dialogs; *jd != NULL; *jd = (*jd)->next)
+        {
+          if ((*jd)->d_id == nid)
+            return 0;
+        }
+    }
+  *jd = NULL;
+  *jn = NULL;
+  return -1;
+}
+
+int
+eXosip_subscribe_dialog_find (int sid, eXosip_subscribe_t ** js,
+                              eXosip_dialog_t ** jd)
+{
+  for (*js = eXosip.j_subscribes; *js != NULL; *js = (*js)->next)
+    {
+      *jd = NULL;
+      if ((*js)->s_id == sid)
+        return 0;
+      for (*jd = (*js)->s_dialogs; *jd != NULL; *jd = (*jd)->next)
+        {
+          if ((*jd)->d_id == sid)
+            return 0;
+        }
+    }
+  *jd = NULL;
+  *js = NULL;
+  return -1;
+}
+
+int
+eXosip_dialog_set_200ok (eXosip_dialog_t * jd, osip_message_t * _200Ok)
+{
+  int i;
+
+  if (jd == NULL)
+    return -1;
+  i = osip_message_clone (_200Ok, &(jd->d_200Ok));
+  if (i != 0)
+    {
+      return -1;
+    }
+  return 0;
+}
+
+int
+eXosip_dialog_init_as_uac (eXosip_dialog_t ** _jd, osip_message_t * _200Ok)
+{
+  int i;
+  eXosip_dialog_t *jd;
+
+  *_jd = NULL;
+  jd = (eXosip_dialog_t *) osip_malloc (sizeof (eXosip_dialog_t));
+  memset (jd, 0, sizeof (eXosip_dialog_t));
+
+  jd->d_id = -1;                /* not yet available to user */
+  jd->d_STATE = JD_EMPTY;
+
+  if (MSG_IS_REQUEST (_200Ok))
+    {
+      i =
+        osip_dialog_init_as_uac_with_remote_request (&(jd->d_dialog), _200Ok, -1);
+  } else
+    {                           /* normal usage with response */
+      i = osip_dialog_init_as_uac (&(jd->d_dialog), _200Ok);
+    }
+  if (i != 0)
+    {
+      osip_free (jd);
+      return -1;
+    }
+
+  jd->d_timer = time (NULL);
+  jd->d_200Ok = NULL;
+  jd->d_ack = NULL;
+  jd->next = NULL;
+  jd->parent = NULL;
+  jd->d_out_trs = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
+  osip_list_init (jd->d_out_trs);
+  jd->d_inc_trs = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
+  osip_list_init (jd->d_inc_trs);
+
+  /* jd->d_bh = sdp_handler_new(); */
+  *_jd = jd;
+  return 0;
+}
+
+int
+eXosip_dialog_init_as_uas (eXosip_dialog_t ** _jd, osip_message_t * _invite,
+                           osip_message_t * _200Ok)
+{
+  int i;
+  eXosip_dialog_t *jd;
+
+  *_jd = NULL;
+  jd = (eXosip_dialog_t *) osip_malloc (sizeof (eXosip_dialog_t));
+  memset (jd, 0, sizeof (eXosip_dialog_t));
+  jd->d_id = -1;                /* not yet available to user */
+  jd->d_STATE = JD_EMPTY;
+  i = osip_dialog_init_as_uas (&(jd->d_dialog), _invite, _200Ok);
+  if (i != 0)
+    {
+      osip_free (jd);
+      return -1;
+    }
+
+  jd->d_timer = time (NULL);
+  jd->d_200Ok = NULL;
+  jd->d_ack = NULL;
+  jd->next = NULL;
+  jd->parent = NULL;
+  jd->d_out_trs = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
+  osip_list_init (jd->d_out_trs);
+  jd->d_inc_trs = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
+  osip_list_init (jd->d_inc_trs);
+
+#ifdef SUPPORT_MSN
+  /* bugguy MSN */
+  jd->d_dialog->local_cseq = 1;
+#endif
+
+  /* jd->d_bh = sdp_handler_new(); */
+  *_jd = jd;
+  return 0;
+}
+
+void
+eXosip_dialog_free (eXosip_dialog_t * jd)
+{
+  while (!osip_list_eol (jd->d_inc_trs, 0))
+    {
+      osip_transaction_t *tr;
+
+      tr = (osip_transaction_t *) osip_list_get (jd->d_inc_trs, 0);
+      osip_list_remove (jd->d_inc_trs, 0);
+      __eXosip_delete_jinfo (tr);
+      osip_list_add (eXosip.j_transactions, tr, 0);
+    }
+
+  while (!osip_list_eol (jd->d_out_trs, 0))
+    {
+      osip_transaction_t *tr;
+
+      tr = (osip_transaction_t *) osip_list_get (jd->d_out_trs, 0);
+      osip_list_remove (jd->d_out_trs, 0);
+      __eXosip_delete_jinfo (tr);
+      osip_list_add (eXosip.j_transactions, tr, 0);
+    }
+
+  osip_message_free (jd->d_200Ok);
+  osip_message_free (jd->d_ack);
+
+  osip_dialog_free (jd->d_dialog);
+
+  osip_free (jd->d_out_trs);
+  osip_free (jd->d_inc_trs);
+  osip_free (jd);
+
+  eXosip_update ();
+}
diff --git a/exosip2/jevents.c b/exosip2/jevents.c
new file mode 100644
index 0000000000..a59092ce99
--- /dev/null
+++ b/exosip2/jevents.c
@@ -0,0 +1,511 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002, 2003  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+#include "eXosip2.h"
+#include <eXosip2/eXosip.h>
+#include <osip2/osip_condv.h>
+
+extern eXosip_t eXosip;
+
+static int _eXosip_event_fill_messages (eXosip_event_t * je,
+                                        osip_transaction_t * tr);
+
+static int
+_eXosip_event_fill_messages (eXosip_event_t * je, osip_transaction_t * tr)
+{
+  int i;
+
+  if (tr != NULL && tr->orig_request != NULL)
+    {
+      i = osip_message_clone (tr->orig_request, &je->request);
+      if (i != 0)
+        {
+          OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                                  "failed to clone request for event\n"));
+        }
+    }
+  if (tr != NULL && tr->last_response != NULL)
+    {
+      i = osip_message_clone (tr->last_response, &je->response);
+      if (i != 0)
+        {
+          OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                                  "failed to clone response for event\n"));
+        }
+    }
+  if (tr != NULL && tr->ack != NULL)
+    {
+      i = osip_message_clone (tr->ack, &je->ack);
+      if (i != 0)
+        {
+          OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                                  "failed to clone ACK for event\n"));
+        }
+    }
+  return 0;
+}
+
+eXosip_event_t *
+eXosip_event_init_for_call (int type, eXosip_call_t * jc,
+                            eXosip_dialog_t * jd, osip_transaction_t * tr)
+{
+  eXosip_event_t *je;
+
+  eXosip_event_init (&je, type);
+  if (je == NULL)
+    return NULL;
+  if (jc == NULL)
+    return NULL;
+
+  je->cid = jc->c_id;
+  if (jd != NULL)
+    je->did = jd->d_id;
+  if (tr != NULL)
+    je->tid = tr->transactionid;
+
+  je->external_reference = jc->external_reference;
+
+  _eXosip_event_fill_messages (je, tr);
+  return je;
+}
+
+eXosip_event_t *
+eXosip_event_init_for_subscribe (int type, eXosip_subscribe_t * js,
+                                 eXosip_dialog_t * jd, osip_transaction_t * tr)
+{
+  eXosip_event_t *je;
+
+  eXosip_event_init (&je, type);
+  if (je == NULL)
+    return NULL;
+  if (js == NULL)
+    return NULL;
+
+  je->sid = js->s_id;
+  if (jd != NULL)
+    je->did = jd->d_id;
+  if (tr != NULL)
+    je->tid = tr->transactionid;
+
+  je->ss_status = js->s_ss_status;
+  je->ss_reason = js->s_ss_reason;
+
+  /* je->external_reference = js->external_reference; */
+
+  _eXosip_event_fill_messages (je, tr);
+
+  return je;
+}
+
+eXosip_event_t *
+eXosip_event_init_for_notify (int type, eXosip_notify_t * jn,
+                              eXosip_dialog_t * jd, osip_transaction_t * tr)
+{
+  eXosip_event_t *je;
+
+  eXosip_event_init (&je, type);
+  if (je == NULL)
+    return NULL;
+  if (jn == NULL)
+    return NULL;
+
+  je->nid = jn->n_id;
+  if (jd != NULL)
+    je->did = jd->d_id;
+  if (tr != NULL)
+    je->tid = tr->transactionid;
+
+  je->ss_status = jn->n_ss_status;
+  je->ss_reason = jn->n_ss_reason;
+
+  /*je->external_reference = jc->external_reference; */
+
+  _eXosip_event_fill_messages (je, tr);
+
+  return je;
+}
+
+eXosip_event_t *
+eXosip_event_init_for_reg (int type, eXosip_reg_t * jr, osip_transaction_t * tr)
+{
+  eXosip_event_t *je;
+
+  eXosip_event_init (&je, type);
+  if (je == NULL)
+    return NULL;
+  if (jr == NULL)
+    return NULL;
+  je->rid = jr->r_id;
+
+  _eXosip_event_fill_messages (je, tr);
+  return je;
+}
+
+eXosip_event_t *
+eXosip_event_init_for_message (int type, osip_transaction_t * tr)
+{
+  eXosip_event_t *je;
+
+  eXosip_event_init (&je, type);
+  if (je == NULL)
+    return NULL;
+
+  if (tr != NULL)
+    je->tid = tr->transactionid;
+
+  _eXosip_event_fill_messages (je, tr);
+
+  return je;
+}
+
+int
+eXosip_event_init (eXosip_event_t ** je, int type)
+{
+  *je = (eXosip_event_t *) osip_malloc (sizeof (eXosip_event_t));
+  if (*je == NULL)
+    return -1;
+
+  memset (*je, 0, sizeof (eXosip_event_t));
+  (*je)->type = type;
+
+  if (type == EXOSIP_CALL_NOANSWER)
+    {
+      sprintf ((*je)->textinfo, "No answer for this Call!");
+  } else if (type == EXOSIP_CALL_PROCEEDING)
+    {
+      sprintf ((*je)->textinfo, "Call is being processed!");
+  } else if (type == EXOSIP_CALL_RINGING)
+    {
+      sprintf ((*je)->textinfo, "Remote phone is ringing!");
+  } else if (type == EXOSIP_CALL_ANSWERED)
+    {
+      sprintf ((*je)->textinfo, "Remote phone has answered!");
+  } else if (type == EXOSIP_CALL_REDIRECTED)
+    {
+      sprintf ((*je)->textinfo, "Call is redirected!");
+  } else if (type == EXOSIP_CALL_REQUESTFAILURE)
+    {
+      sprintf ((*je)->textinfo, "4xx received for Call!");
+  } else if (type == EXOSIP_CALL_SERVERFAILURE)
+    {
+      sprintf ((*je)->textinfo, "5xx received for Call!");
+  } else if (type == EXOSIP_CALL_GLOBALFAILURE)
+    {
+      sprintf ((*je)->textinfo, "6xx received for Call!");
+  } else if (type == EXOSIP_CALL_INVITE)
+    {
+      sprintf ((*je)->textinfo, "New call received!");
+  } else if (type == EXOSIP_CALL_ACK)
+    {
+      sprintf ((*je)->textinfo, "ACK received!");
+  } else if (type == EXOSIP_CALL_CANCELLED)
+    {
+      sprintf ((*je)->textinfo, "Call has been cancelled!");
+  } else if (type == EXOSIP_CALL_TIMEOUT)
+    {
+      sprintf ((*je)->textinfo, "Timeout. Gave up!");
+  } else if (type == EXOSIP_CALL_REINVITE)
+    {
+      sprintf ((*je)->textinfo, "INVITE within call received!");
+  } else if (type == EXOSIP_CALL_CLOSED)
+    {
+      sprintf ((*je)->textinfo, "Bye Received!");
+  } else if (type == EXOSIP_CALL_RELEASED)
+    {
+      sprintf ((*je)->textinfo, "Call Context is released!");
+  } else if (type == EXOSIP_REGISTRATION_SUCCESS)
+    {
+      sprintf ((*je)->textinfo, "User is successfully registred!");
+  } else if (type == EXOSIP_REGISTRATION_FAILURE)
+    {
+      sprintf ((*je)->textinfo, "Registration failed!");
+  } else if (type == EXOSIP_CALL_MESSAGE_NEW)
+    {
+      sprintf ((*je)->textinfo, "New request received!");
+  } else if (type == EXOSIP_CALL_MESSAGE_PROCEEDING)
+    {
+      sprintf ((*je)->textinfo, "request is being processed!");
+  } else if (type == EXOSIP_CALL_MESSAGE_ANSWERED)
+    {
+      sprintf ((*je)->textinfo, "2xx received for request!");
+  } else if (type == EXOSIP_CALL_MESSAGE_REDIRECTED)
+    {
+      sprintf ((*je)->textinfo, "3xx received for request!");
+  } else if (type == EXOSIP_CALL_MESSAGE_REQUESTFAILURE)
+    {
+      sprintf ((*je)->textinfo, "4xx received for request!");
+  } else if (type == EXOSIP_CALL_MESSAGE_SERVERFAILURE)
+    {
+      sprintf ((*je)->textinfo, "5xx received for request!");
+  } else if (type == EXOSIP_CALL_MESSAGE_GLOBALFAILURE)
+    {
+      sprintf ((*je)->textinfo, "5xx received for request!");
+  } else if (type == EXOSIP_MESSAGE_NEW)
+    {
+      sprintf ((*je)->textinfo, "New request outside call received!");
+  } else if (type == EXOSIP_MESSAGE_PROCEEDING)
+    {
+      sprintf ((*je)->textinfo, "request outside call is being processed!");
+  } else if (type == EXOSIP_MESSAGE_ANSWERED)
+    {
+      sprintf ((*je)->textinfo, "2xx received for request outside call!");
+  } else if (type == EXOSIP_MESSAGE_REDIRECTED)
+    {
+      sprintf ((*je)->textinfo, "3xx received for request outside call!");
+  } else if (type == EXOSIP_MESSAGE_REQUESTFAILURE)
+    {
+      sprintf ((*je)->textinfo, "4xx received for request outside call!");
+  } else if (type == EXOSIP_MESSAGE_SERVERFAILURE)
+    {
+      sprintf ((*je)->textinfo, "5xx received for request outside call!");
+  } else if (type == EXOSIP_MESSAGE_GLOBALFAILURE)
+    {
+      sprintf ((*je)->textinfo, "5xx received for request outside call!");
+  } else if (type == EXOSIP_SUBSCRIPTION_NOANSWER)
+    {
+      sprintf ((*je)->textinfo, "No answer for this SUBSCRIBE!");
+  } else if (type == EXOSIP_SUBSCRIPTION_PROCEEDING)
+    {
+      sprintf ((*je)->textinfo, "SUBSCRIBE is being processed!");
+  } else if (type == EXOSIP_SUBSCRIPTION_ANSWERED)
+    {
+      sprintf ((*je)->textinfo, "2xx received for SUBSCRIBE!");
+  } else if (type == EXOSIP_SUBSCRIPTION_REDIRECTED)
+    {
+      sprintf ((*je)->textinfo, "3xx received for SUBSCRIBE!");
+  } else if (type == EXOSIP_SUBSCRIPTION_REQUESTFAILURE)
+    {
+      sprintf ((*je)->textinfo, "4xx received for SUBSCRIBE!");
+  } else if (type == EXOSIP_SUBSCRIPTION_SERVERFAILURE)
+    {
+      sprintf ((*je)->textinfo, "5xx received for SUBSCRIBE!");
+  } else if (type == EXOSIP_SUBSCRIPTION_GLOBALFAILURE)
+    {
+      sprintf ((*je)->textinfo, "5xx received for SUBSCRIBE!");
+  } else if (type == EXOSIP_SUBSCRIPTION_NOTIFY)
+    {
+      sprintf ((*je)->textinfo, "NOTIFY request for subscription!");
+  } else if (type == EXOSIP_SUBSCRIPTION_RELEASED)
+    {
+      sprintf ((*je)->textinfo, "Subscription has terminate!");
+  } else if (type == EXOSIP_IN_SUBSCRIPTION_NEW)
+    {
+      sprintf ((*je)->textinfo, "New incoming SUBSCRIBE!");
+  } else if (type == EXOSIP_IN_SUBSCRIPTION_RELEASED)
+    {
+      sprintf ((*je)->textinfo, "Incoming Subscription has terminate!");
+  } else
+    {
+      (*je)->textinfo[0] = '\0';
+    }
+  return 0;
+}
+
+void
+eXosip_event_free (eXosip_event_t * je)
+{
+  if (je == NULL)
+    return;
+  if (je->request != NULL)
+    osip_message_free (je->request);
+  if (je->response != NULL)
+    osip_message_free (je->response);
+  if (je->ack != NULL)
+    osip_message_free (je->ack);
+  osip_free (je);
+}
+
+void
+report_event (eXosip_event_t * je, osip_message_t * sip)
+{
+  if (je != NULL)
+    {
+      eXosip_event_add (je);
+    }
+}
+
+void
+report_call_event (int evt, eXosip_call_t * jc,
+                   eXosip_dialog_t * jd, osip_transaction_t * tr)
+{
+  eXosip_event_t *je;
+
+  je = eXosip_event_init_for_call (evt, jc, jd, tr);
+  report_event (je, NULL);
+}
+
+void
+report_options_event (int evt, osip_transaction_t * tr)
+{
+  eXosip_event_t *je;
+
+  eXosip_event_init (&je, evt);
+  if (je == NULL)
+    return;
+
+  if (tr != NULL)
+    je->tid = tr->transactionid;
+
+  _eXosip_event_fill_messages (je, tr);
+  report_event (je, NULL);
+}
+
+int
+eXosip_event_add (eXosip_event_t * je)
+{
+  int i = osip_fifo_add (eXosip.j_events, (void *) je);
+
+  osip_cond_signal ((struct osip_cond *) eXosip.j_cond);
+  __eXosip_wakeup_event ();
+  return i;
+}
+
+#if 0
+#ifdef CLOCK_REALTIME
+/* if CLOCK_REALTIME exist, then clock_gettime should be defined */
+
+#define OSIP_CLOCK_REALTIME CLOCK_REALTIME
+
+void
+__eXosip_clock_gettime (clockid_t cid, struct timespec *time)
+{
+  clock_gettime (cid, time);
+}
+
+#elif defined (WIN32) || defined (_WIN32_WCE)
+
+#include <sys/types.h>
+#include <sys/timeb.h>
+
+#define OSIP_CLOCK_REALTIME 4002
+
+void
+__eXosip_clock_gettime (unsigned int clock_id, struct timespec *time)
+{
+  struct _timeb time_val;
+
+  if (clock_id != OSIP_CLOCK_REALTIME)
+    return;
+
+  _ftime (&time_val);
+  time->tv_sec = time_val.time;
+  time->tv_nsec = time_val.millitm * 1000000;
+  return;
+}
+#endif
+#endif
+
+eXosip_event_t *
+eXosip_event_wait (int tv_s, int tv_ms)
+{
+  eXosip_event_t *je = NULL;
+
+#if 0                           /* this does not seems to work. by now */
+#if defined (CLOCK_REALTIME) || defined (WIN32) || defined (_WIN32_WCE)
+  int i;
+
+  struct timespec deadline;
+  struct timespec interval;
+  long tot_ms = (tv_s * 1000) + tv_ms;
+
+  static struct osip_mutex *mlock = NULL;
+
+  if (mlock == NULL)
+    mlock = osip_mutex_init ();
+
+  je = (eXosip_event_t *) osip_fifo_tryget (eXosip.j_events);
+  if (je)
+    return je;
+
+  interval.tv_sec = tot_ms / 1000;
+  interval.tv_nsec = (tot_ms % 1000) * 1000000L;
+
+  __eXosip_clock_gettime (OSIP_CLOCK_REALTIME, &deadline);
+
+  if ((deadline.tv_nsec += interval.tv_nsec) >= 1000000000L)
+    {
+      deadline.tv_nsec -= 1000000000L;
+      deadline.tv_sec += 1;
+  } else
+    deadline.tv_nsec += interval.tv_nsec;
+
+  deadline.tv_sec += interval.tv_sec;
+
+  i = osip_cond_timedwait ((struct osip_cond *) eXosip.j_cond,
+                           (struct osip_mutex *) mlock, &deadline);
+
+#endif
+#else
+  /* basic replacement */
+  {
+    fd_set fdset;
+    struct timeval tv;
+    int max, i;
+
+    FD_ZERO (&fdset);
+#if defined (WIN32) || defined (_WIN32_WCE)
+    FD_SET ((unsigned int) jpipe_get_read_descr (eXosip.j_socketctl_event),
+            &fdset);
+#else
+    FD_SET (jpipe_get_read_descr (eXosip.j_socketctl_event), &fdset);
+#endif
+    max = jpipe_get_read_descr (eXosip.j_socketctl_event);
+    tv.tv_sec = tv_s;
+    tv.tv_usec = tv_ms * 1000;
+
+    je = (eXosip_event_t *) osip_fifo_tryget (eXosip.j_events);
+    if (je != NULL)
+      return je;
+
+    if (tv_s == 0 && tv_ms == 0)
+      return NULL;
+
+    i = select (max + 1, &fdset, NULL, NULL, &tv);
+    if (i <= 0)
+      return 0;
+
+    if (FD_ISSET (jpipe_get_read_descr (eXosip.j_socketctl_event), &fdset))
+      {
+        char buf[500];
+
+        jpipe_read (eXosip.j_socketctl_event, buf, 499);
+      }
+
+    je = (eXosip_event_t *) osip_fifo_tryget (eXosip.j_events);
+    if (je != NULL)
+      return je;
+  }
+#endif
+
+  return je;
+}
+
+eXosip_event_t *
+eXosip_event_get ()
+{
+  eXosip_event_t *je;
+
+  je = (eXosip_event_t *) osip_fifo_get (eXosip.j_events);
+  return je;
+}
diff --git a/exosip2/jnotify.c b/exosip2/jnotify.c
new file mode 100644
index 0000000000..ab9049a173
--- /dev/null
+++ b/exosip2/jnotify.c
@@ -0,0 +1,202 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002, 2003  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+
+#include "eXosip2.h"
+
+extern eXosip_t eXosip;
+
+osip_transaction_t *
+eXosip_find_last_inc_subscribe (eXosip_notify_t * jn, eXosip_dialog_t * jd)
+{
+  osip_transaction_t *inc_tr;
+  int pos;
+
+  inc_tr = NULL;
+  pos = 0;
+  if (jd != NULL)
+    {
+      while (!osip_list_eol (jd->d_inc_trs, pos))
+        {
+          inc_tr = osip_list_get (jd->d_inc_trs, pos);
+          if (0 == strcmp (inc_tr->cseq->method, "SUBSCRIBE"))
+            break;
+          else
+            inc_tr = NULL;
+          pos++;
+        }
+  } else
+    inc_tr = NULL;
+
+  if (inc_tr == NULL)
+    return jn->n_inc_tr;        /* can be NULL */
+
+  return inc_tr;
+}
+
+
+osip_transaction_t *
+eXosip_find_last_out_notify (eXosip_notify_t * jn, eXosip_dialog_t * jd)
+{
+  osip_transaction_t *out_tr;
+  int pos;
+
+  out_tr = NULL;
+  pos = 0;
+  if (jd != NULL)
+    {
+      while (!osip_list_eol (jd->d_out_trs, pos))
+        {
+          out_tr = osip_list_get (jd->d_out_trs, pos);
+          if (0 == strcmp (out_tr->cseq->method, "NOTIFY"))
+            return out_tr;
+          pos++;
+        }
+    }
+
+  return NULL;
+}
+
+int
+eXosip_notify_init (eXosip_notify_t ** jn, osip_message_t * inc_subscribe)
+{
+  osip_contact_t *co;
+  char *uri;
+  int i;
+  char locip[50];
+
+#ifdef SM
+  eXosip_get_localip_from_via (inc_subscribe, locip, 49);
+#else
+  i = _eXosip_find_protocol(inc_subscribe);
+  if (i==IPPROTO_UDP)
+    {
+      eXosip_guess_ip_for_via (eXosip.net_interfaces[0].net_ip_family, locip, 49);
+    }
+  else if (i==IPPROTO_TCP)
+    {
+      eXosip_guess_ip_for_via (eXosip.net_interfaces[1].net_ip_family, locip, 49);
+    }
+  else
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: unsupported protocol (default to UDP)\n"));
+      eXosip_guess_ip_for_via (eXosip.net_interfaces[0].net_ip_family, locip, 49);
+      return -1;
+    }
+    
+#endif
+  if (inc_subscribe == NULL
+      || inc_subscribe->to == NULL || inc_subscribe->to->url == NULL)
+    return -1;
+  co = (osip_contact_t *) osip_list_get (inc_subscribe->contacts, 0);
+  if (co == NULL || co->url == NULL)
+    return -1;
+
+  *jn = (eXosip_notify_t *) osip_malloc (sizeof (eXosip_notify_t));
+  if (*jn == NULL)
+    return -1;
+  memset (*jn, 0, sizeof (eXosip_notify_t));
+
+  i = osip_uri_to_str (co->url, &uri);
+  if (i != 0)
+    {
+      osip_free (*jn);
+      *jn = NULL;
+      return -1;
+    }
+  osip_strncpy ((*jn)->n_uri, uri, 254);
+  osip_free (uri);
+
+  return 0;
+}
+
+void
+eXosip_notify_free (eXosip_notify_t * jn)
+{
+  /* ... */
+
+  eXosip_dialog_t *jd;
+
+  for (jd = jn->n_dialogs; jd != NULL; jd = jn->n_dialogs)
+    {
+      REMOVE_ELEMENT (jn->n_dialogs, jd);
+      eXosip_dialog_free (jd);
+    }
+
+  __eXosip_delete_jinfo (jn->n_inc_tr);
+  __eXosip_delete_jinfo (jn->n_out_tr);
+  if (jn->n_inc_tr != NULL)
+    osip_list_add (eXosip.j_transactions, jn->n_inc_tr, 0);
+  if (jn->n_out_tr != NULL)
+    osip_list_add (eXosip.j_transactions, jn->n_out_tr, 0);
+  osip_free (jn);
+}
+
+int
+_eXosip_notify_set_refresh_interval (eXosip_notify_t * jn,
+                                     osip_message_t * inc_subscribe)
+{
+  osip_header_t *exp;
+  int now;
+
+  now = time (NULL);
+  if (jn == NULL || inc_subscribe == NULL)
+    return -1;
+
+  osip_message_get_expires (inc_subscribe, 0, &exp);
+  if (exp == NULL || exp->hvalue == NULL)
+    jn->n_ss_expires = now + 600;
+  else
+    {
+      jn->n_ss_expires = osip_atoi (exp->hvalue);
+      if (jn->n_ss_expires != -1)
+        jn->n_ss_expires = now + jn->n_ss_expires;
+      else                      /* on error, set it to default */
+        jn->n_ss_expires = now + 600;
+    }
+
+  return 0;
+}
+
+void
+_eXosip_notify_add_expires_in_2XX_for_subscribe (eXosip_notify_t * jn,
+                                                 osip_message_t * answer)
+{
+  char tmp[20];
+  int now;
+
+  now = time (NULL);
+
+  if (jn->n_ss_expires - now < 0)
+    {
+      tmp[0] = '0';
+      tmp[1] = '\0';
+  } else
+    {
+      sprintf (tmp, "%i", jn->n_ss_expires - now);
+    }
+  osip_message_set_expires (answer, tmp);
+}
diff --git a/exosip2/jpipe.c b/exosip2/jpipe.c
new file mode 100644
index 0000000000..004306aa77
--- /dev/null
+++ b/exosip2/jpipe.c
@@ -0,0 +1,230 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002, 2003  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+#include "jpipe.h"
+
+#ifndef WIN32
+
+jpipe_t *
+jpipe ()
+{
+  jpipe_t *my_pipe = (jpipe_t *) osip_malloc (sizeof (jpipe_t));
+
+  if (my_pipe == NULL)
+    return NULL;
+
+  if (0 != pipe (my_pipe->pipes))
+    {
+      osip_free (my_pipe);
+      return NULL;
+    }
+  return my_pipe;
+}
+
+int
+jpipe_close (jpipe_t * apipe)
+{
+  if (apipe == NULL)
+    return -1;
+  close (apipe->pipes[0]);
+  close (apipe->pipes[1]);
+  osip_free (apipe);
+  return 0;
+}
+
+
+/**
+ * Write in a pipe.
+ */
+int
+jpipe_write (jpipe_t * apipe, const void *buf, int count)
+{
+  if (apipe == NULL)
+    return -1;
+  return write (apipe->pipes[1], buf, count);
+}
+
+/**
+ * Read in a pipe.
+ */
+int
+jpipe_read (jpipe_t * apipe, void *buf, int count)
+{
+  if (apipe == NULL)
+    return -1;
+  return read (apipe->pipes[0], buf, count);
+}
+
+/**
+ * Get descriptor of reading pipe.
+ */
+int
+jpipe_get_read_descr (jpipe_t * apipe)
+{
+  if (apipe == NULL)
+    return -1;
+  return apipe->pipes[0];
+}
+
+#else
+
+jpipe_t *
+jpipe ()
+{
+  int s = 0;
+  int timeout = 0;
+  static int aport = 10500;
+  struct sockaddr_in raddr;
+  int j;
+
+  jpipe_t *my_pipe = (jpipe_t *) osip_malloc (sizeof (jpipe_t));
+
+  if (my_pipe == NULL)
+    return NULL;
+
+  s = (int) socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
+  if (0 > s)
+    {
+      osip_free (my_pipe);
+      return NULL;
+    }
+  my_pipe->pipes[1] = (int) socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
+  if (0 > my_pipe->pipes[1])
+    {
+      closesocket (s);
+      osip_free (my_pipe);
+      return NULL;
+    }
+
+  raddr.sin_addr.s_addr = inet_addr ("127.0.0.1");
+  raddr.sin_family = AF_INET;
+
+  j = 50;
+  while (aport++ && j-- > 0)
+    {
+      raddr.sin_port = htons ((short) aport);
+      if (bind (s, (struct sockaddr *) &raddr, sizeof (raddr)) < 0)
+        {
+          OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL,
+                                  "Failed to bind one local socket %i!\n", aport));
+      } else
+        break;
+    }
+
+  if (j == 0)
+    {
+      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                              "Failed to bind a local socket, aborting!\n"));
+      closesocket (s);
+      closesocket (my_pipe->pipes[1]);
+      osip_free (my_pipe);
+    }
+
+  j = listen (s, 1);
+  if (j != 0)
+    {
+      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                              "Failed to listen on a local socket, aborting!\n"));
+      closesocket (s);
+      closesocket (my_pipe->pipes[1]);
+      osip_free (my_pipe);
+    }
+
+  j = setsockopt (my_pipe->pipes[1],
+                  SOL_SOCKET,
+                  SO_RCVTIMEO, (const char *) &timeout, sizeof (timeout));
+  if (j != NO_ERROR)
+    {
+      /* failed for some reason... */
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "udp plugin; cannot set O_NONBLOCK to the file desciptor!\n"));
+      closesocket (s);
+      closesocket (my_pipe->pipes[1]);
+      osip_free (my_pipe);
+    }
+
+  connect (my_pipe->pipes[1], (struct sockaddr *) &raddr, sizeof (raddr));
+
+  my_pipe->pipes[0] = accept (s, NULL, NULL);
+
+  if (my_pipe->pipes[0] <= 0)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "udp plugin; Failed to call accept!\n"));
+      closesocket (s);
+      closesocket (my_pipe->pipes[1]);
+      osip_free (my_pipe);
+    }
+
+  return my_pipe;
+}
+
+int
+jpipe_close (jpipe_t * apipe)
+{
+  if (apipe == NULL)
+    return -1;
+  closesocket (apipe->pipes[0]);
+  closesocket (apipe->pipes[1]);
+  osip_free (apipe);
+  return 0;
+}
+
+
+/**
+ * Write in a pipe.
+ */
+int
+jpipe_write (jpipe_t * apipe, const void *buf, int count)
+{
+  if (apipe == NULL)
+    return -1;
+  return send (apipe->pipes[1], buf, count, 0);
+}
+
+/**
+ * Read in a pipe.
+ */
+int
+jpipe_read (jpipe_t * apipe, void *buf, int count)
+{
+  if (apipe == NULL)
+    return -1;
+  return recv (apipe->pipes[0], buf, count, 0 /* MSG_DONTWAIT */ );     /* BUG?? */
+}
+
+/**
+ * Get descriptor of reading pipe.
+ */
+int
+jpipe_get_read_descr (jpipe_t * apipe)
+{
+  if (apipe == NULL)
+    return -1;
+  return apipe->pipes[0];
+}
+
+#endif
diff --git a/exosip2/jpipe.h b/exosip2/jpipe.h
new file mode 100644
index 0000000000..1a8862c4f6
--- /dev/null
+++ b/exosip2/jpipe.h
@@ -0,0 +1,109 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002, 2003  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifndef _JPIPE_H_
+#define _JPIPE_H_
+
+#include <eXosip2/eXosip.h>
+
+#ifndef WIN32
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#endif
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+/**
+ * @file jpipe.h
+ * @brief PPL Pipe Handling Routines
+ */
+
+/**
+ * @defgroup JPIPE Pipe Handling
+ * @ingroup PPL
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#ifndef WIN32
+
+/**
+ * Structure for storing a pipe descriptor
+ * @defvar jpipe_t
+ */
+  typedef struct jpipe_t jpipe_t;
+
+  struct jpipe_t
+  {
+    int pipes[2];
+  };
+
+#else
+
+/**
+ * Structure for storing a pipe descriptor
+ * @defvar ppl_pipe_t
+ */
+  typedef struct jpipe_t jpipe_t;
+
+  struct jpipe_t
+  {
+    int pipes[2];
+  };
+
+#endif
+
+/**
+ * Get New pipe pair.
+ */
+  jpipe_t *jpipe (void);
+
+/**
+ * Close pipe
+ */
+  int jpipe_close (jpipe_t * apipe);
+
+/**
+ * Write in a pipe.
+ */
+  int jpipe_write (jpipe_t * pipe, const void *buf, int count);
+
+/**
+ * Read in a pipe.
+ */
+  int jpipe_read (jpipe_t * pipe, void *buf, int count);
+
+/**
+ * Get descriptor of reading pipe.
+ */
+  int jpipe_get_read_descr (jpipe_t * pipe);
+
+#ifdef __cplusplus
+}
+#endif
+/** @} */
+#endif
diff --git a/exosip2/jpublish.c b/exosip2/jpublish.c
new file mode 100644
index 0000000000..ef75828af5
--- /dev/null
+++ b/exosip2/jpublish.c
@@ -0,0 +1,122 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002, 2003  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+#include "eXosip2.h"
+
+extern eXosip_t eXosip;
+
+int
+_eXosip_pub_update (eXosip_pub_t ** pub, osip_transaction_t * tr,
+                    osip_message_t * answer)
+{
+  eXosip_pub_t *jpub;
+
+  *pub = NULL;
+
+  for (jpub = eXosip.j_pub; jpub != NULL; jpub = jpub->next)
+    {
+      if (jpub->p_last_tr == NULL)
+        {                       /*bug? */
+      } else if (tr == jpub->p_last_tr)
+        {
+          /* update the sip_etag parameter */
+          if (answer == NULL)
+            {                   /* bug? */
+          } else if (MSG_IS_STATUS_2XX (answer))
+            {
+              osip_header_t *sip_etag = NULL;
+
+              osip_message_header_get_byname (answer, "SIP-ETag", 0, &sip_etag);
+              if (sip_etag != NULL && sip_etag->hvalue != NULL)
+                snprintf (jpub->p_sip_etag, 64, "%s", sip_etag->hvalue);
+            }
+          *pub = jpub;
+          return 0;
+        }
+    }
+  return -1;
+}
+
+int
+_eXosip_pub_find_by_aor (eXosip_pub_t ** pub, const char *aor)
+{
+  eXosip_pub_t *jpub;
+  eXosip_pub_t *ptr;
+  time_t now;
+
+  *pub = NULL;
+
+  /* delete expired publications */
+  now = time (NULL);
+  ptr = eXosip.j_pub;
+  for (jpub = ptr; jpub != NULL; jpub = ptr)
+    {
+      ptr = jpub->next;
+      if (now - jpub->p_expires > 60)
+        {
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_WARNING, NULL,
+                       "eXosip: removing expired publication!"));
+          REMOVE_ELEMENT (eXosip.j_pub, jpub);
+          _eXosip_pub_free (jpub);
+        }
+    }
+
+  for (jpub = eXosip.j_pub; jpub != NULL; jpub = jpub->next)
+    {
+      if (osip_strcasecmp (aor, jpub->p_aor) == 0)
+        {
+          *pub = jpub;
+          return 0;
+        }
+    }
+  return -1;
+}
+
+int
+_eXosip_pub_init (eXosip_pub_t ** pub, const char *aor, const char *exp)
+{
+  eXosip_pub_t *jpub;
+
+  *pub = NULL;
+
+  jpub = (eXosip_pub_t *) osip_malloc (sizeof (eXosip_pub_t));
+  if (jpub == 0)
+    return -1;
+  memset (jpub, 0, sizeof (eXosip_pub_t));
+  snprintf (jpub->p_aor, 256, "%s", aor);
+
+  jpub->p_expires = atoi (exp) + time (NULL);
+  jpub->p_period = atoi (exp);
+
+  *pub = jpub;
+  return 0;
+}
+
+void
+_eXosip_pub_free (eXosip_pub_t * pub)
+{
+  if (pub->p_last_tr != NULL)
+    osip_list_add (eXosip.j_transactions, pub->p_last_tr, 0);
+  osip_free (pub);
+}
diff --git a/exosip2/jreg.c b/exosip2/jreg.c
new file mode 100644
index 0000000000..ecd32872b1
--- /dev/null
+++ b/exosip2/jreg.c
@@ -0,0 +1,104 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002, 2003  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+#include "eXosip2.h"
+
+extern eXosip_t eXosip;
+
+int
+eXosip_reg_init (eXosip_reg_t ** jr, const char *from, const char *proxy,
+                 const char *contact)
+{
+  static int r_id;
+
+  *jr = (eXosip_reg_t *) osip_malloc (sizeof (eXosip_reg_t));
+  if (*jr == NULL)
+    return -1;
+
+  if (r_id > 1000000)           /* keep it non-negative */
+    r_id = 0;
+
+  memset (*jr, '\0', sizeof (eXosip_reg_t));
+
+  (*jr)->r_id = ++r_id;
+  (*jr)->r_reg_period = 3600;   /* delay between registration */
+  (*jr)->r_aor = osip_strdup (from);    /* sip identity */
+  (*jr)->r_contact = osip_strdup (contact);     /* sip identity */
+  (*jr)->r_registrar = osip_strdup (proxy);     /* registrar */
+
+  return 0;
+}
+
+void
+eXosip_reg_free (eXosip_reg_t * jreg)
+{
+
+  osip_free (jreg->r_aor);
+  osip_free (jreg->r_contact);
+  osip_free (jreg->r_registrar);
+
+  if (jreg->r_last_tr != NULL)
+    {
+      if (jreg->r_last_tr->state == IST_TERMINATED ||
+          jreg->r_last_tr->state == ICT_TERMINATED ||
+          jreg->r_last_tr->state == NICT_TERMINATED ||
+          jreg->r_last_tr->state == NIST_TERMINATED)
+        {
+          OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                                  "Release a terminated transaction\n"));
+          __eXosip_delete_jinfo (jreg->r_last_tr);
+          if (jreg->r_last_tr != NULL)
+            osip_list_add (eXosip.j_transactions, jreg->r_last_tr, 0);
+      } else
+        {
+          OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                                  "Release a non-terminated transaction\n"));
+          __eXosip_delete_jinfo (jreg->r_last_tr);
+          if (jreg->r_last_tr != NULL)
+            osip_list_add (eXosip.j_transactions, jreg->r_last_tr, 0);
+        }
+    }
+
+  osip_free (jreg);
+}
+
+int
+_eXosip_reg_find (eXosip_reg_t ** reg, osip_transaction_t * tr)
+{
+  eXosip_reg_t *jreg;
+
+  *reg = NULL;
+  if (tr == NULL)
+    return -1;
+
+  for (jreg = eXosip.j_reg; jreg != NULL; jreg = jreg->next)
+    {
+      if (jreg->r_last_tr == tr)
+        {
+          *reg = jreg;
+          return 0;
+        }
+    }
+  return -1;
+}
diff --git a/exosip2/jrequest.c b/exosip2/jrequest.c
new file mode 100644
index 0000000000..ae24979e2f
--- /dev/null
+++ b/exosip2/jrequest.c
@@ -0,0 +1,999 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002, 2003  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+#include "eXosip2.h"
+
+#ifndef WIN32
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#ifdef __APPLE_CC__
+#include <unistd.h>
+#endif
+#else
+#include <windows.h>
+#include <Iphlpapi.h>
+#endif
+
+extern eXosip_t eXosip;
+
+/* Private functions */
+static int dialog_fill_route_set (osip_dialog_t * dialog,
+                                  osip_message_t * request);
+
+/* should use cryptographically random identifier is RECOMMENDED.... */
+/* by now this should lead to identical call-id when application are
+   started at the same time...   */
+char *
+osip_call_id_new_random ()
+{
+  char *tmp = (char *) osip_malloc (33);
+  unsigned int number = osip_build_random_number ();
+
+  sprintf (tmp, "%u", number);
+  return tmp;
+}
+
+char *
+osip_from_tag_new_random (void)
+{
+  return osip_call_id_new_random ();
+}
+
+char *
+osip_to_tag_new_random (void)
+{
+  return osip_call_id_new_random ();
+}
+
+unsigned int
+via_branch_new_random (void)
+{
+  return osip_build_random_number ();
+}
+
+/* prepare a minimal request (outside of a dialog) with required headers */
+/* 
+   method is the type of request. ("INVITE", "REGISTER"...)
+   to is the remote target URI
+   transport is either "TCP" or "UDP" (by now, only UDP is implemented!)
+*/
+int
+generating_request_out_of_dialog (osip_message_t ** dest, const char *method,
+                                  const char *to, const char *transport,
+                                  const char *from, const char *proxy)
+{
+  /* Section 8.1:
+     A valid request contains at a minimum "To, From, Call-iD, Cseq,
+     Max-Forwards and Via
+   */
+  int i;
+  osip_message_t *request;
+  char locip[50];
+  int doing_register;
+  char *register_callid_number = NULL;
+  struct eXosip_net *net;
+
+  if (0==osip_strcasecmp(transport, "udp"))
+    net = &eXosip.net_interfaces[0];
+  else if (0==osip_strcasecmp(transport, "tcp"))
+    net = &eXosip.net_interfaces[1];
+  else
+    {
+      OSIP_TRACE (osip_trace
+		  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+		   "eXosip: unsupported protocol (default to UDP)\n"));
+    net = &eXosip.net_interfaces[0];
+    }
+
+  *dest = NULL;
+
+  i = osip_message_init (&request);
+  if (i != 0)
+    return -1;
+
+  /* prepare the request-line */
+  osip_message_set_method (request, osip_strdup (method));
+  osip_message_set_version (request, osip_strdup ("SIP/2.0"));
+  osip_message_set_status_code (request, 0);
+  osip_message_set_reason_phrase (request, NULL);
+
+  doing_register = 0 == strcmp ("REGISTER", method);
+
+  if (doing_register)
+    {
+      osip_uri_init (&(request->req_uri));
+      i = osip_uri_parse (request->req_uri, proxy);
+      if (i != 0)
+        {
+          goto brood_error_1;
+        }
+      osip_message_set_to (request, from);
+  } else
+    {
+      /* in any cases except REGISTER: */
+      i = osip_message_set_to (request, to);
+      if (i != 0)
+        {
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                       "ERROR: callee address does not seems to be a sipurl: %s\n",
+                       to));
+          goto brood_error_1;
+        }
+      if (proxy != NULL && proxy[0] != 0)
+        {                       /* equal to a pre-existing route set */
+          /* if the pre-existing route set contains a "lr" (compliance
+             with bis-08) then the req_uri should contains the remote target
+             URI */
+          osip_uri_param_t *lr_param;
+          osip_route_t *o_proxy;
+
+#ifndef __VXWORKS_OS__
+          osip_route_init (&o_proxy);
+#else
+          osip_route_init2 (&o_proxy);
+#endif
+          i = osip_route_parse (o_proxy, proxy);
+          if (i != 0)
+            {
+              osip_route_free (o_proxy);
+              goto brood_error_1;
+            }
+
+          osip_uri_uparam_get_byname (o_proxy->url, "lr", &lr_param);
+          if (lr_param != NULL) /* to is the remote target URI in this case! */
+            {
+              osip_uri_clone (request->to->url, &(request->req_uri));
+              /* "[request] MUST includes a Route header field containing
+                 the route set values in order." */
+              osip_list_add (request->routes, o_proxy, 0);
+          } else
+            /* if the first URI of route set does not contain "lr", the req_uri
+               is set to the first uri of route set */
+            {
+              request->req_uri = o_proxy->url;
+              o_proxy->url = NULL;
+              osip_route_free (o_proxy);
+              /* add the route set */
+              /* "The UAC MUST add a route header field containing
+                 the remainder of the route set values in order.
+                 The UAC MUST then place the remote target URI into
+                 the route header field as the last value
+               */
+              osip_message_set_route (request, to);
+            }
+      } else                    /* No route set (outbound proxy) is used */
+        {
+          /* The UAC must put the remote target URI (to field) in the req_uri */
+          i = osip_uri_clone (request->to->url, &(request->req_uri));
+          if (i != 0)
+            goto brood_error_1;
+        }
+    }
+  /*guess the local ip since req uri is known */
+#ifdef SM
+  eXosip_get_localip_for (request->req_uri->host, locip, 49);
+#else
+  if (0==osip_strcasecmp(transport, "udp"))
+    eXosip_guess_ip_for_via (eXosip.net_interfaces[0].net_ip_family, locip, 49);
+  else if (0==osip_strcasecmp(transport, "tcp"))
+    eXosip_guess_ip_for_via (eXosip.net_interfaces[1].net_ip_family, locip, 49);
+  else
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: unsupported protocol (default to UDP)\n"));
+      eXosip_guess_ip_for_via (eXosip.net_interfaces[0].net_ip_family, locip, 49);
+    }
+#endif
+  /* set To and From */
+  osip_message_set_from (request, from);
+  /* add a tag */
+  osip_from_set_tag (request->from, osip_from_tag_new_random ());
+
+  /* set the cseq and call_id header */
+  {
+    osip_call_id_t *callid;
+    osip_cseq_t *cseq;
+    char *num;
+    char *cidrand;
+
+    /* call-id is always the same for REGISTRATIONS */
+    i = osip_call_id_init (&callid);
+    if (i != 0)
+      goto brood_error_1;
+    cidrand = osip_call_id_new_random ();
+    osip_call_id_set_number (callid, cidrand);
+    if (doing_register)
+      register_callid_number = cidrand;
+
+    osip_call_id_set_host (callid, osip_strdup (locip));
+    request->call_id = callid;
+
+    i = osip_cseq_init (&cseq);
+    if (i != 0)
+      goto brood_error_1;
+    num = osip_strdup (doing_register ? "1" : "20");
+    osip_cseq_set_number (cseq, num);
+    osip_cseq_set_method (cseq, osip_strdup (method));
+    request->cseq = cseq;
+  }
+
+  /* always add the Max-Forward header */
+  osip_message_set_max_forwards (request, "5"); /* a UA should start a request with 70 */
+
+#define MASQUERADE_VIA
+#ifdef MASQUERADE_VIA
+  /* should be useless with compliant UA */
+  if (eXosip.net_interfaces[0].net_firewall_ip[0] != '\0')
+    {
+      char *c_address = request->req_uri->host;
+
+      struct addrinfo *addrinfo;
+      struct __eXosip_sockaddr addr;
+
+      i = eXosip_get_addrinfo (&addrinfo, request->req_uri->host, 5060, IPPROTO_UDP);
+      if (i == 0)
+        {
+          memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen);
+          freeaddrinfo (addrinfo);
+          c_address = inet_ntoa (((struct sockaddr_in *) &addr)->sin_addr);
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                       "eXosip: here is the resolved destination host=%s\n",
+                       c_address));
+        }
+
+      if (eXosip_is_public_address (c_address))
+        {
+          char tmp[200];
+
+          snprintf (tmp, 200, "SIP/2.0/%s %s:%s;rport;branch=z9hG4bK%u",
+                    transport, eXosip.net_interfaces[0].net_firewall_ip,
+		    net->net_port,
+                    via_branch_new_random ());
+          osip_message_set_via (request, tmp);
+      } else
+        {
+          char tmp[200];
+
+          if (net->net_ip_family == AF_INET6)
+            snprintf (tmp, 200, "SIP/2.0/%s [%s]:%s;branch=z9hG4bK%u",
+                      transport, locip, net->net_port,
+                      via_branch_new_random ());
+          else
+            snprintf (tmp, 200, "SIP/2.0/%s %s:%s;rport;branch=z9hG4bK%u",
+                      transport, locip, net->net_port,
+                      via_branch_new_random ());
+          osip_message_set_via (request, tmp);
+        }
+  } else
+    {
+      char tmp[200];
+
+      if (net->net_ip_family == AF_INET6)
+        snprintf (tmp, 200, "SIP/2.0/%s [%s]:%s;branch=z9hG4bK%u", transport,
+                  locip, net->net_port,
+		  via_branch_new_random ());
+      else
+        snprintf (tmp, 200, "SIP/2.0/%s %s:%s;rport;branch=z9hG4bK%u",
+                  transport, locip, net->net_port,
+		  via_branch_new_random ());
+      osip_message_set_via (request, tmp);
+    }
+
+#else
+  {
+    char tmp[200];
+
+    if (net->net_ip_family == AF_INET6)
+      spnrintf (tmp, 200, "SIP/2.0/%s [%s]:%s;branch=z9hG4bK%u", transport,
+                locip, net->net_port,
+		via_branch_new_random ());
+    else
+      spnrintf (tmp, 200, "SIP/2.0/%s %s:%s;branch=z9hG4bK%u", transport,
+                locip, net->net_port,
+		via_branch_new_random ());
+
+    osip_message_set_via (request, tmp);
+  }
+#endif
+
+  /* add specific headers for each kind of request... */
+
+  if (0 == strcmp ("INVITE", method) || 0 == strcmp ("SUBSCRIBE", method))
+    {
+      char *contact;
+      osip_from_t *a_from;
+      int i;
+
+      i = osip_from_init (&a_from);
+      if (i == 0)
+        i = osip_from_parse (a_from, from);
+
+      if (i == 0 && a_from != NULL
+          && a_from->url != NULL && a_from->url->username != NULL)
+        {
+          contact = (char *) osip_malloc (50 + strlen (a_from->url->username));
+
+          if (eXosip.net_interfaces[0].net_firewall_ip[0] != '\0')
+            {
+              char *c_address = request->req_uri->host;
+
+              struct addrinfo *addrinfo;
+              struct __eXosip_sockaddr addr;
+
+	      i = eXosip_get_addrinfo (&addrinfo, request->req_uri->host, 5060, IPPROTO_TCP);
+              if (i == 0)
+                {
+                  memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen);
+                  freeaddrinfo (addrinfo);
+                  c_address = inet_ntoa (((struct sockaddr_in *) &addr)->sin_addr);
+                  OSIP_TRACE (osip_trace
+                              (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                               "eXosip: here is the resolved destination host=%s\n",
+                               c_address));
+                }
+
+              if (eXosip_is_public_address (c_address))
+                {
+                  sprintf (contact, "<sip:%s@%s:%s>", a_from->url->username,
+                           eXosip.net_interfaces[0].net_firewall_ip,
+			   net->net_port);
+              } else
+                {
+                  sprintf (contact, "<sip:%s@%s:%s>", a_from->url->username,
+                           locip, net->net_port);
+                }
+          } else
+            {
+              sprintf (contact, "<sip:%s@%s:%s>", a_from->url->username,
+                       locip, net->net_port);
+            }
+          osip_message_set_contact (request, contact);
+          osip_free (contact);
+        }
+      osip_from_free (a_from);
+
+      /* This is probably useless for other messages */
+      osip_message_set_allow (request, "INVITE");
+      osip_message_set_allow (request, "ACK");
+      osip_message_set_allow (request, "UPDATE");
+      osip_message_set_allow (request, "INFO");
+      osip_message_set_allow (request, "CANCEL");
+      osip_message_set_allow (request, "BYE");
+      osip_message_set_allow (request, "OPTIONS");
+      osip_message_set_allow (request, "REFER");
+      osip_message_set_allow (request, "SUBSCRIBE");
+      osip_message_set_allow (request, "NOTIFY");
+      osip_message_set_allow (request, "MESSAGE");
+    }
+
+  if (0 == strcmp ("REGISTER", method))
+    {
+  } else if (0 == strcmp ("INFO", method))
+    {
+  } else if (0 == strcmp ("OPTIONS", method))
+    {
+      osip_message_set_accept (request, "application/sdp");
+    }
+
+  osip_message_set_user_agent (request, eXosip.user_agent);
+  /*  else if ... */
+  *dest = request;
+  return 0;
+
+brood_error_1:
+  osip_message_free (request);
+  *dest = NULL;
+  return -1;
+}
+
+int
+generating_register (osip_message_t ** reg, char *transport, char *from,
+                     char *proxy, char *contact, int expires)
+{
+  osip_from_t *a_from;
+  int i;
+  char locip[50];
+  struct eXosip_net *net;
+
+  i = generating_request_out_of_dialog (reg, "REGISTER", NULL, transport, from, proxy);
+  if (i != 0)
+    return -1;
+
+  i = _eXosip_find_protocol(*reg);
+  if (i==IPPROTO_UDP)
+      net = &eXosip.net_interfaces[0];
+  else if (i==IPPROTO_TCP)
+      net = &eXosip.net_interfaces[1];
+  else
+    {
+      net = &eXosip.net_interfaces[0];
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: unsupported protocol\n"));
+      return -1;
+    }
+
+#ifdef SM
+  eXosip_get_localip_for ((*reg)->req_uri->host, locip, 49);
+#else
+  eXosip_guess_ip_for_via (net->net_ip_family, locip, 49);
+#endif
+
+  if (contact == NULL)
+    {
+      i = osip_from_init (&a_from);
+      if (i == 0)
+        i = osip_from_parse (a_from, from);
+
+      if (i == 0 && a_from != NULL
+          && a_from->url != NULL && a_from->url->username != NULL)
+        {
+          contact = (char *) osip_malloc (50 + strlen (a_from->url->username));
+          if (eXosip.net_interfaces[0].net_firewall_ip[0] != '\0')
+            {
+              char *c_address = (*reg)->req_uri->host;
+
+              struct addrinfo *addrinfo;
+              struct __eXosip_sockaddr addr;
+
+	      i = eXosip_get_addrinfo (&addrinfo, (*reg)->req_uri->host, 5060, IPPROTO_UDP);
+              if (i == 0)
+                {
+                  memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen);
+                  freeaddrinfo (addrinfo);
+                  c_address = inet_ntoa (((struct sockaddr_in *) &addr)->sin_addr);
+                  OSIP_TRACE (osip_trace
+                              (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                               "eXosip: here is the resolved destination host=%s\n",
+                               c_address));
+                }
+
+              if (eXosip_is_public_address (c_address))
+                {
+                  sprintf (contact, "<sip:%s@%s:%s>", a_from->url->username,
+                           eXosip.net_interfaces[0].net_firewall_ip,
+			   net->net_port);
+              } else
+                {
+                  sprintf (contact, "<sip:%s@%s:%s>", a_from->url->username,
+                           locip, net->net_port);
+                }
+          } else
+            {
+              sprintf (contact, "<sip:%s@%s:%s>", a_from->url->username,
+                       locip, net->net_port);
+            }
+
+          osip_message_set_contact (*reg, contact);
+          osip_free (contact);
+        }
+      osip_from_free (a_from);
+  } else
+    {
+      osip_message_set_contact (*reg, contact);
+    }
+
+  {
+    char exp[10];               /* MUST never be ouside 1 and 3600 */
+
+    snprintf (exp, 9, "%i", expires);
+    osip_message_set_expires (*reg, exp);
+  }
+
+  osip_message_set_content_length (*reg, "0");
+
+  return 0;
+}
+
+int
+generating_publish (osip_message_t ** message, const char *to,
+                    const char *from, const char *route)
+{
+  int i;
+
+  if (to != NULL && *to == '\0')
+    return -1;
+
+  if (route != NULL && *route == '\0')
+    route = NULL;
+
+  i = generating_request_out_of_dialog (message, "PUBLISH", to, "UDP", from,
+					route);
+  if (i != 0)
+    return -1;
+
+  /* osip_message_set_organization(*message, "Jack's Org"); */
+
+  return 0;
+}
+
+static int
+dialog_fill_route_set (osip_dialog_t * dialog, osip_message_t * request)
+{
+  /* if the pre-existing route set contains a "lr" (compliance
+     with bis-08) then the req_uri should contains the remote target
+     URI */
+  int i;
+  int pos = 0;
+  osip_uri_param_t *lr_param;
+  osip_route_t *route;
+  char *last_route;
+
+  /* AMD bug: fixed 17/06/2002 */
+
+#ifdef OSIP_FUTURE_FIX_2_3
+    route = (osip_route_t *) osip_list_get (dialog->route_set, 0);
+#else
+  if (dialog->type == CALLER)
+    {
+      pos = osip_list_size (dialog->route_set) - 1;
+      route = (osip_route_t *) osip_list_get (dialog->route_set, pos);
+  } else
+    route = (osip_route_t *) osip_list_get (dialog->route_set, 0);
+#endif
+
+  osip_uri_uparam_get_byname (route->url, "lr", &lr_param);
+  if (lr_param != NULL)         /* the remote target URI is the req_uri! */
+    {
+      i = osip_uri_clone (dialog->remote_contact_uri->url, &(request->req_uri));
+      if (i != 0)
+        return -1;
+      /* "[request] MUST includes a Route header field containing
+         the route set values in order." */
+      /* AMD bug: fixed 17/06/2002 */
+      pos = 0;                  /* first element is at index 0 */
+      while (!osip_list_eol (dialog->route_set, pos))
+        {
+          osip_route_t *route2;
+
+          route = osip_list_get (dialog->route_set, pos);
+          i = osip_route_clone (route, &route2);
+          if (i != 0)
+            return -1;
+#ifdef OSIP_FUTURE_FIX_2_3
+            osip_list_add (request->routes, route2, -1);
+#else
+          if (dialog->type == CALLER)
+            osip_list_add (request->routes, route2, 0);
+          else
+            osip_list_add (request->routes, route2, -1);
+          pos++;
+#endif
+        }
+      return 0;
+    }
+
+  /* if the first URI of route set does not contain "lr", the req_uri
+     is set to the first uri of route set */
+
+
+  i = osip_uri_clone (route->url, &(request->req_uri));
+  if (i != 0)
+    return -1;
+  /* add the route set */
+  /* "The UAC MUST add a route header field containing
+     the remainder of the route set values in order. */
+  pos = 0;                      /* yes it is */
+
+  while (!osip_list_eol (dialog->route_set, pos))       /* not the first one in the list */
+    {
+      osip_route_t *route2;
+
+      route = osip_list_get (dialog->route_set, pos);
+      i = osip_route_clone (route, &route2);
+      if (i != 0)
+        return -1;
+#ifdef OSIP_FUTURE_FIX_2_3
+      if (!osip_list_eol (dialog->route_set, pos + 1))
+        osip_list_add (request->routes, route2, -1);
+      else
+        osip_route_free (route2);
+#else
+      if (dialog->type == CALLER)
+        {
+          if (pos != osip_list_size (dialog->route_set) - 1)
+            osip_list_add (request->routes, route2, 0);
+          else
+            osip_route_free (route2);
+      } else
+        {
+          if (!osip_list_eol (dialog->route_set, pos + 1))
+            osip_list_add (request->routes, route2, -1);
+          else
+            osip_route_free (route2);
+        }
+#endif
+      pos++;
+    }
+
+  /* The UAC MUST then place the remote target URI into
+     the route header field as the last value */
+  i = osip_uri_to_str (dialog->remote_contact_uri->url, &last_route);
+  if (i != 0)
+    return -1;
+  i = osip_message_set_route (request, last_route);
+  osip_free (last_route);
+  if (i != 0)
+    {
+      return -1;
+    }
+
+  /* route header and req_uri set */
+  return 0;
+}
+
+int
+_eXosip_build_request_within_dialog (osip_message_t ** dest,
+                                     const char *method,
+                                     osip_dialog_t * dialog, const char *transport)
+{
+  int i;
+  osip_message_t *request;
+  char locip[50];
+  struct eXosip_net *net;
+
+  i = osip_message_init (&request);
+  if (i != 0) 
+   return -1;
+
+  if (dialog->remote_contact_uri == NULL)
+    {
+      /* this dialog is probably not established! or the remote UA
+         is not compliant with the latest RFC
+       */
+      osip_message_free (request);
+      return -1;
+    }
+
+  if (0==osip_strcasecmp(transport, "udp"))
+    net = &eXosip.net_interfaces[0];
+  else if (0==osip_strcasecmp(transport, "tcp"))
+    net = &eXosip.net_interfaces[1];
+  else
+    {
+      OSIP_TRACE (osip_trace
+		  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+		   "eXosip: unsupported protocol -%s- (default to UDP)\n"));
+    net = &eXosip.net_interfaces[0];
+    }
+
+#ifdef SM
+  eXosip_get_localip_for (dialog->remote_contact_uri->url->host, locip, 49);
+#else
+  eXosip_guess_ip_for_via (net->net_ip_family, locip, 49);
+#endif
+  /* prepare the request-line */
+  request->sip_method = osip_strdup (method);
+  request->sip_version = osip_strdup ("SIP/2.0");
+  request->status_code = 0;
+  request->reason_phrase = NULL;
+
+  /* and the request uri???? */
+  if (osip_list_eol (dialog->route_set, 0))
+    {
+      /* The UAC must put the remote target URI (to field) in the req_uri */
+      i = osip_uri_clone (dialog->remote_contact_uri->url, &(request->req_uri));
+      if (i != 0)
+        goto grwd_error_1;
+  } else
+    {
+      /* fill the request-uri, and the route headers. */
+      dialog_fill_route_set (dialog, request);
+    }
+
+  /* To and From already contains the proper tag! */
+  i = osip_to_clone (dialog->remote_uri, &(request->to));
+  if (i != 0)
+    goto grwd_error_1;
+  i = osip_from_clone (dialog->local_uri, &(request->from));
+  if (i != 0)
+    goto grwd_error_1;
+
+  /* set the cseq and call_id header */
+  osip_message_set_call_id (request, dialog->call_id);
+
+  if (0 == strcmp ("ACK", method))
+    {
+      osip_cseq_t *cseq;
+      char *tmp;
+
+      i = osip_cseq_init (&cseq);
+      if (i != 0)
+        goto grwd_error_1;
+      tmp = osip_malloc (20);
+      sprintf (tmp, "%i", dialog->local_cseq);
+      osip_cseq_set_number (cseq, tmp);
+      osip_cseq_set_method (cseq, osip_strdup (method));
+      request->cseq = cseq;
+  } else
+    {
+      osip_cseq_t *cseq;
+      char *tmp;
+
+      i = osip_cseq_init (&cseq);
+      if (i != 0)
+        goto grwd_error_1;
+      dialog->local_cseq++;     /* we should we do that?? */
+      tmp = osip_malloc (20);
+      sprintf (tmp, "%i", dialog->local_cseq);
+      osip_cseq_set_number (cseq, tmp);
+      osip_cseq_set_method (cseq, osip_strdup (method));
+      request->cseq = cseq;
+    }
+
+  /* always add the Max-Forward header */
+  osip_message_set_max_forwards (request, "5"); /* a UA should start a request with 70 */
+
+
+  /* even for ACK for 2xx (ACK within a dialog), the branch ID MUST
+     be a new ONE! */
+#ifdef MASQUERADE_VIA
+  /* should be useless with compliant UA */
+  if (eXosip.net_interfaces[0].net_firewall_ip[0] != '\0')
+    {
+      char *c_address = request->req_uri->host;
+
+      struct addrinfo *addrinfo;
+      struct __eXosip_sockaddr addr;
+
+      i = eXosip_get_addrinfo (&addrinfo, request->req_uri->host, 5060, IPPROTO_UDP);
+      if (i == 0)
+        {
+          memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen);
+          freeaddrinfo (addrinfo);
+          c_address = inet_ntoa (((struct sockaddr_in *) &addr)->sin_addr);
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                       "eXosip: here is the resolved destination host=%s\n",
+                       c_address));
+        }
+
+      if (eXosip_is_public_address (c_address))
+        {
+          char tmp[200];
+
+          sprintf (tmp, "SIP/2.0/%s %s:%s;rport;branch=z9hG4bK%u", transport,
+                   eXosip.net_interfaces[0].net_firewall_ip,
+                   net->net_port,
+		   via_branch_new_random ());
+          osip_message_set_via (request, tmp);
+      } else
+        {
+          char tmp[200];
+
+          if (eXosip.net_interfaces[0].net_ip_family == AF_INET6)
+            snprintf (tmp, 200, "SIP/2.0/%s [%s]:%s;branch=z9hG4bK%u",
+                      transport, locip, net->net_port,
+                      via_branch_new_random ());
+          else
+            snprintf (tmp, 200, "SIP/2.0/%s %s:%s;rport;branch=z9hG4bK%u",
+                      transport, locip, net->net_port,
+                      via_branch_new_random ());
+
+          osip_message_set_via (request, tmp);
+        }
+  } else
+    {
+      char tmp[200];
+
+      if (net->net_ip_family == AF_INET6)
+        snprintf (tmp, 200, "SIP/2.0/%s [%s]:%s;branch=z9hG4bK%u", transport,
+                  locip, net->net_port,
+		  via_branch_new_random ());
+      else
+        snprintf (tmp, 200, "SIP/2.0/%s %s:%s;rport;branch=z9hG4bK%u",
+                  transport, locip, net->net_port,
+		  via_branch_new_random ());
+
+      osip_message_set_via (request, tmp);
+    }
+
+#else
+  {
+    char tmp[200];
+
+    if (net->net_ip_family == AF_INET6)
+      sprintf (tmp, "SIP/2.0/%s [%s]:%s;branch=z9hG4bK%u", transport,
+               locip, net->net_port,
+	       via_branch_new_random ());
+    else
+      sprintf (tmp, "SIP/2.0/%s %s:%s;branch=z9hG4bK%u", transport,
+               locip, net->net_port,
+	       via_branch_new_random ());
+
+    osip_message_set_via (request, tmp);
+  }
+#endif
+
+  /* add specific headers for each kind of request... */
+
+  {
+    char contact[200];
+
+    if (net->net_firewall_ip[0] != '\0')
+      {
+        char *c_address = request->req_uri->host;
+
+        struct addrinfo *addrinfo;
+        struct __eXosip_sockaddr addr;
+
+        i = eXosip_get_addrinfo (&addrinfo, request->req_uri->host, 5060, IPPROTO_UDP);
+        if (i == 0)
+          {
+            memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen);
+            freeaddrinfo (addrinfo);
+            c_address = inet_ntoa (((struct sockaddr_in *) &addr)->sin_addr);
+            OSIP_TRACE (osip_trace
+                        (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                         "eXosip: here is the resolved destination host=%s\n",
+                         c_address));
+          }
+
+        if (eXosip_is_public_address (c_address))
+          {
+            sprintf (contact, "<sip:%s@%s:%s>",
+                     dialog->local_uri->url->username,
+		     eXosip.net_interfaces[0].net_firewall_ip,
+                     net->net_port);
+        } else
+          {
+            sprintf (contact, "<sip:%s@%s:%s>",
+                     dialog->local_uri->url->username, locip,
+		     net->net_port);
+          }
+    } else
+      {
+        sprintf (contact, "<sip:%s@%s:%s>", dialog->local_uri->url->username,
+                 locip, net->net_port);
+      }
+    osip_message_set_contact (request, contact);
+    /* Here we'll add the supported header if it's needed! */
+    /* the require header must be added by the upper layer if needed */
+  }
+
+  if (0 == strcmp ("NOTIFY", method))
+    {
+  } else if (0 == strcmp ("INFO", method))
+    {
+
+  } else if (0 == strcmp ("OPTIONS", method))
+    {
+      osip_message_set_accept (request, "application/sdp");
+  } else if (0 == strcmp ("ACK", method))
+    {
+      /* The ACK MUST contains the same credential than the INVITE!! */
+      /* TODO... */
+    }
+
+  osip_message_set_user_agent (request, eXosip.user_agent);
+  /*  else if ... */
+  *dest = request;
+  return 0;
+
+  /* grwd_error_2: */
+  dialog->local_cseq--;
+grwd_error_1:
+  osip_message_free (request);
+  *dest = NULL;
+  return -1;
+}
+
+/* this request is only build within a dialog!! */
+int
+generating_bye (osip_message_t ** bye, osip_dialog_t * dialog, char *transport)
+{
+  int i;
+
+  i = _eXosip_build_request_within_dialog (bye, "BYE", dialog, transport);
+  if (i != 0)
+    return -1;
+
+  return 0;
+}
+
+/* It is RECOMMENDED to only cancel INVITE request */
+int
+generating_cancel (osip_message_t ** dest, osip_message_t * request_cancelled)
+{
+  int i;
+  osip_message_t *request;
+
+  i = osip_message_init (&request);
+  if (i != 0)
+    return -1;
+
+  /* prepare the request-line */
+  osip_message_set_method (request, osip_strdup ("CANCEL"));
+  osip_message_set_version (request, osip_strdup ("SIP/2.0"));
+  osip_message_set_status_code (request, 0);
+  osip_message_set_reason_phrase (request, NULL);
+
+  i = osip_uri_clone (request_cancelled->req_uri, &(request->req_uri));
+  if (i != 0)
+    goto gc_error_1;
+
+  i = osip_to_clone (request_cancelled->to, &(request->to));
+  if (i != 0)
+    goto gc_error_1;
+  i = osip_from_clone (request_cancelled->from, &(request->from));
+  if (i != 0)
+    goto gc_error_1;
+
+  /* set the cseq and call_id header */
+  i = osip_call_id_clone (request_cancelled->call_id, &(request->call_id));
+  if (i != 0)
+    goto gc_error_1;
+  i = osip_cseq_clone (request_cancelled->cseq, &(request->cseq));
+  if (i != 0)
+    goto gc_error_1;
+  osip_free (request->cseq->method);
+  request->cseq->method = osip_strdup ("CANCEL");
+
+  /* copy ONLY the top most Via Field (this method is also used by proxy) */
+  {
+    osip_via_t *via;
+    osip_via_t *via2;
+
+    i = osip_message_get_via (request_cancelled, 0, &via);
+    if (i != 0)
+      goto gc_error_1;
+    i = osip_via_clone (via, &via2);
+    if (i != 0)
+      goto gc_error_1;
+    osip_list_add (request->vias, via2, -1);
+  }
+
+  /* add the same route-set than in the previous request */
+  {
+    int pos = 0;
+    osip_route_t *route;
+    osip_route_t *route2;
+
+    while (!osip_list_eol (request_cancelled->routes, pos))
+      {
+        route = (osip_route_t *) osip_list_get (request_cancelled->routes, pos);
+        i = osip_route_clone (route, &route2);
+        if (i != 0)
+          goto gc_error_1;
+        osip_list_add (request->routes, route2, -1);
+        pos++;
+      }
+  }
+
+  osip_message_set_max_forwards (request, "70");        /* a UA should start a request with 70 */
+  osip_message_set_user_agent (request, eXosip.user_agent);
+
+  *dest = request;
+  return 0;
+
+gc_error_1:
+  osip_message_free (request);
+  *dest = NULL;
+  return -1;
+}
+
diff --git a/exosip2/jresponse.c b/exosip2/jresponse.c
new file mode 100644
index 0000000000..6135f56505
--- /dev/null
+++ b/exosip2/jresponse.c
@@ -0,0 +1,736 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002, 2003  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+#include "eXosip2.h"
+
+extern eXosip_t eXosip;
+
+
+int
+_eXosip_build_response_default (osip_message_t ** dest,
+                                osip_dialog_t * dialog, int status,
+                                osip_message_t * request)
+{
+  osip_generic_param_t *tag;
+  osip_message_t *response;
+  int pos;
+  int i;
+
+  *dest = NULL;
+  if (request == NULL)
+    return -1;
+
+  i = osip_message_init (&response);
+  if (i != 0)
+    return -1;
+  /* initialise osip_message_t structure */
+  /* yet done... */
+
+  response->sip_version = (char *) osip_malloc (8 * sizeof (char));
+  sprintf (response->sip_version, "SIP/2.0");
+  osip_message_set_status_code (response, status);
+
+  /* handle some internal reason definitions. */
+  if (MSG_IS_NOTIFY (request) && status == 481)
+    {
+      response->reason_phrase = osip_strdup ("Subcription Does Not Exist");
+  } else if (MSG_IS_SUBSCRIBE (request) && status == 202)
+    {
+      response->reason_phrase = osip_strdup ("Accepted subscription");
+  } else
+    {
+      response->reason_phrase = osip_strdup (osip_message_get_reason (status));
+      if (response->reason_phrase == NULL)
+        {
+          if (response->status_code == 101)
+            response->reason_phrase = osip_strdup ("Dialog Establishement");
+          else
+            response->reason_phrase = osip_strdup ("Unknown code");
+        }
+      response->req_uri = NULL;
+      response->sip_method = NULL;
+    }
+
+  i = osip_to_clone (request->to, &(response->to));
+  if (i != 0)
+    goto grd_error_1;
+
+  i = osip_to_get_tag (response->to, &tag);
+  if (i != 0)
+    {                           /* we only add a tag if it does not already contains one! */
+      if ((dialog != NULL) && (dialog->local_tag != NULL))
+        /* it should contain the local TAG we created */
+        {
+          osip_to_set_tag (response->to, osip_strdup (dialog->local_tag));
+      } else
+        {
+          if (status != 100)
+            osip_to_set_tag (response->to, osip_to_tag_new_random ());
+        }
+    }
+
+  i = osip_from_clone (request->from, &(response->from));
+  if (i != 0)
+    goto grd_error_1;
+
+  pos = 0;
+  while (!osip_list_eol (request->vias, pos))
+    {
+      osip_via_t *via;
+      osip_via_t *via2;
+
+      via = (osip_via_t *) osip_list_get (request->vias, pos);
+      i = osip_via_clone (via, &via2);
+      if (i != -0)
+        goto grd_error_1;
+      osip_list_add (response->vias, via2, -1);
+      pos++;
+    }
+
+  i = osip_call_id_clone (request->call_id, &(response->call_id));
+  if (i != 0)
+    goto grd_error_1;
+  i = osip_cseq_clone (request->cseq, &(response->cseq));
+  if (i != 0)
+    goto grd_error_1;
+
+  if (MSG_IS_SUBSCRIBE (request))
+    {
+      osip_header_t *exp;
+      osip_header_t *evt_hdr;
+
+      osip_message_header_get_byname (request, "event", 0, &evt_hdr);
+      if (evt_hdr != NULL && evt_hdr->hvalue != NULL)
+	osip_message_set_header (response, "Event", evt_hdr->hvalue);
+      else
+	osip_message_set_header (response, "Event", "presence");
+      i = osip_message_get_expires (request, 0, &exp);
+      if (exp == NULL)
+        {
+          osip_header_t *cp;
+
+          i = osip_header_clone (exp, &cp);
+          if (cp != NULL)
+            osip_list_add (response->headers, cp, 0);
+        }
+    }
+
+  osip_message_set_allow (response, "INVITE");
+  osip_message_set_allow (response, "ACK");
+  osip_message_set_allow (response, "OPTIONS");
+  osip_message_set_allow (response, "CANCEL");
+  osip_message_set_allow (response, "BYE");
+  osip_message_set_allow (response, "SUBSCRIBE");
+  osip_message_set_allow (response, "NOTIFY");
+  osip_message_set_allow (response, "MESSAGE");
+  osip_message_set_allow (response, "INFO");
+  osip_message_set_allow (response, "REFER");
+  osip_message_set_allow (response, "UPDATE");
+
+  *dest = response;
+  return 0;
+
+grd_error_1:
+  osip_message_free (response);
+  return -1;
+}
+
+int
+complete_answer_that_establish_a_dialog (osip_message_t * response,
+                                         osip_message_t * request)
+{
+  int i;
+  int pos = 0;
+  char contact[1000];
+  char locip[50];
+  struct eXosip_net *net;
+  /* 12.1.1:
+     copy all record-route in response
+     add a contact with global scope
+   */
+  while (!osip_list_eol (request->record_routes, pos))
+    {
+      osip_record_route_t *rr;
+      osip_record_route_t *rr2;
+
+      rr = osip_list_get (request->record_routes, pos);
+      i = osip_record_route_clone (rr, &rr2);
+      if (i != 0)
+        return -1;
+      osip_list_add (response->record_routes, rr2, -1);
+      pos++;
+    }
+
+  i = _eXosip_find_protocol(response);
+  if (i==IPPROTO_UDP)
+    {
+      net = &eXosip.net_interfaces[0];
+    }
+  else if (i==IPPROTO_TCP)
+    {
+      net = &eXosip.net_interfaces[1];
+    }
+  else
+    {
+      net = &eXosip.net_interfaces[0];
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: unsupported protocol (default to UDP)\n"));
+      return -1;
+    }
+
+#ifdef SM
+  eXosip_get_localip_from_via (response, locip, 49);
+#else
+  eXosip_guess_ip_for_via (net->net_ip_family, locip, 49);
+#endif
+
+  if (request->to->url->username == NULL)
+    snprintf (contact, 1000, "<sip:%s:%s>", locip, net->net_port);
+  else
+    snprintf (contact, 1000, "<sip:%s@%s:%s>", request->to->url->username,
+              locip, net->net_port);
+
+  if (eXosip.net_interfaces[0].net_firewall_ip[0] != '\0')
+    {
+      osip_contact_t *con =
+        (osip_contact_t *) osip_list_get (request->contacts, 0);
+      if (con != NULL && con->url != NULL && con->url->host != NULL)
+        {
+          char *c_address = con->url->host;
+
+          struct addrinfo *addrinfo;
+          struct __eXosip_sockaddr addr;
+	  i = eXosip_get_addrinfo (&addrinfo, con->url->host, 5060, IPPROTO_UDP);
+          if (i == 0)
+            {
+              memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen);
+              freeaddrinfo (addrinfo);
+              c_address = inet_ntoa (((struct sockaddr_in *) &addr)->sin_addr);
+              OSIP_TRACE (osip_trace
+                          (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                           "eXosip: here is the resolved destination host=%s\n",
+                           c_address));
+            }
+
+          /* If c_address is a PUBLIC address, the request was
+             coming from the PUBLIC network. */
+          if (eXosip_is_public_address (c_address))
+            {
+              if (request->to->url->username == NULL)
+                snprintf (contact, 1000, "<sip:%s:%s>",
+			  eXosip.net_interfaces[0].net_firewall_ip,
+                          net->net_port);
+              else
+                snprintf (contact, 1000, "<sip:%s@%s:%s>",
+                          request->to->url->username,
+			  eXosip.net_interfaces[0].net_firewall_ip,
+                          net->net_port);
+            }
+        }
+    }
+
+  osip_message_set_contact (response, contact);
+
+  return 0;
+}
+
+int
+_eXosip_answer_invite_1xx (eXosip_call_t * jc, eXosip_dialog_t * jd, int code,
+                           osip_message_t ** answer)
+{
+  int i;
+  osip_transaction_t *tr;
+
+  *answer = NULL;
+  tr = eXosip_find_last_inc_invite (jc, jd);
+  if (tr == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: cannot find transaction to answer"));
+      return -1;
+    }
+  /* is the transaction already answered? */
+  if (tr->state == IST_COMPLETED
+      || tr->state == IST_CONFIRMED || tr->state == IST_TERMINATED)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: transaction already answered\n"));
+      return -1;
+    }
+
+  if (jd == NULL)
+    i = _eXosip_build_response_default (answer, NULL, code, tr->orig_request);
+  else
+    i =
+      _eXosip_build_response_default (answer, jd->d_dialog, code,
+                                      tr->orig_request);
+
+  if (i != 0)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "ERROR: Could not create response for invite\n"));
+      return -2;
+    }
+
+  osip_message_set_content_length (*answer, "0");
+  /*  send message to transaction layer */
+
+  if (code > 100)
+    {
+      i = complete_answer_that_establish_a_dialog (*answer, tr->orig_request);
+    }
+
+  return 0;
+}
+
+int
+_eXosip_answer_invite_2xx (eXosip_call_t * jc, eXosip_dialog_t * jd, int code,
+                           osip_message_t ** answer)
+{
+  int i;
+  osip_transaction_t *tr;
+
+  *answer = NULL;
+  tr = eXosip_find_last_inc_invite (jc, jd);
+
+  if (tr == NULL || tr->orig_request == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: cannot find transaction to answer\n"));
+      return -1;
+    }
+
+  if (jd != NULL && jd->d_dialog == NULL)
+    {                           /* element previously removed */
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: cannot answer this closed transaction\n"));
+      return -1;
+    }
+
+  /* is the transaction already answered? */
+  if (tr->state == IST_COMPLETED
+      || tr->state == IST_CONFIRMED || tr->state == IST_TERMINATED)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: transaction already answered\n"));
+      return -1;
+    }
+
+  if (jd == NULL)
+    i = _eXosip_build_response_default (answer, NULL, code, tr->orig_request);
+  else
+    i =
+      _eXosip_build_response_default (answer, jd->d_dialog, code,
+                                      tr->orig_request);
+
+  if (i != 0)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                   "ERROR: Could not create response for invite\n"));
+      return -1;
+    }
+
+  /* request that estabish a dialog: */
+  /* 12.1.1 UAS Behavior */
+  {
+    i = complete_answer_that_establish_a_dialog (*answer, tr->orig_request);
+    if (i != 0)
+      goto g2atii_error_1;;     /* ?? */
+  }
+
+  return 0;
+
+g2atii_error_1:
+  osip_message_free (*answer);
+  return -1;
+}
+
+int
+_eXosip_answer_invite_3456xx (eXosip_call_t * jc, eXosip_dialog_t * jd,
+                              int code, osip_message_t ** answer)
+{
+  int i;
+  osip_transaction_t *tr;
+
+  *answer = NULL;
+  tr = eXosip_find_last_inc_invite (jc, jd);
+  if (tr == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: cannot find transaction to answer"));
+      return -1;
+    }
+  /* is the transaction already answered? */
+  if (tr->state == IST_COMPLETED
+      || tr->state == IST_CONFIRMED || tr->state == IST_TERMINATED)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: transaction already answered\n"));
+      return -1;
+    }
+
+  i =
+    _eXosip_build_response_default (answer, jd->d_dialog, code, tr->orig_request);
+  if (i != 0)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                   "ERROR: Could not create response for invite\n"));
+      return -1;
+    }
+
+  if ((300 <= code) && (code <= 399))
+    {
+      /* Should add contact fields */
+      /* ... */
+    }
+
+  osip_message_set_content_length (*answer, "0");
+  /*  send message to transaction layer */
+
+  return 0;
+}
+
+int
+_eXosip_default_answer_invite_1xx (eXosip_call_t * jc, eXosip_dialog_t * jd,
+                                   int code)
+{
+  osip_event_t *evt_answer;
+  osip_message_t *response;
+  int i;
+  osip_transaction_t *tr;
+
+  tr = eXosip_find_last_inc_invite (jc, jd);
+  if (tr == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: cannot find transaction to answer"));
+      return -1;
+    }
+  /* is the transaction already answered? */
+  if (tr->state == IST_COMPLETED
+      || tr->state == IST_CONFIRMED || tr->state == IST_TERMINATED)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: transaction already answered\n"));
+      return -1;
+    }
+
+  if (jd == NULL)
+    i = _eXosip_build_response_default (&response, NULL, code, tr->orig_request);
+  else
+    i =
+      _eXosip_build_response_default (&response, jd->d_dialog, code,
+                                      tr->orig_request);
+
+  if (i != 0)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "ERROR: Could not create response for invite\n"));
+      return -2;
+    }
+
+  osip_message_set_content_length (response, "0");
+  /*  send message to transaction layer */
+
+  if (code > 100)
+    {
+      /* request that estabish a dialog: */
+      /* 12.1.1 UAS Behavior */
+      i = complete_answer_that_establish_a_dialog (response, tr->orig_request);
+
+      if (jd == NULL)
+        {
+          i = eXosip_dialog_init_as_uas (&jd, tr->orig_request, response);
+          if (i != 0)
+            {
+              OSIP_TRACE (osip_trace
+                          (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                           "eXosip: cannot create dialog!\n"));
+          } else
+            {
+              ADD_ELEMENT (jc->c_dialogs, jd);
+            }
+        }
+    }
+
+  evt_answer = osip_new_outgoing_sipmessage (response);
+  evt_answer->transactionid = tr->transactionid;
+
+  osip_transaction_add_event (tr, evt_answer);
+  __eXosip_wakeup ();
+
+  return 0;
+}
+
+int
+_eXosip_default_answer_invite_3456xx (eXosip_call_t * jc,
+                                      eXosip_dialog_t * jd, int code)
+{
+  osip_event_t *evt_answer;
+  osip_message_t *response;
+  int i;
+  osip_transaction_t *tr;
+
+  tr = eXosip_find_last_inc_invite (jc, jd);
+  if (tr == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: cannot find transaction to answer"));
+      return -1;
+    }
+  /* is the transaction already answered? */
+  if (tr->state == IST_COMPLETED
+      || tr->state == IST_CONFIRMED || tr->state == IST_TERMINATED)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: transaction already answered\n"));
+      return -1;
+    }
+
+  i =
+    _eXosip_build_response_default (&response, jd->d_dialog, code,
+                                    tr->orig_request);
+  if (i != 0)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                   "ERROR: Could not create response for invite\n"));
+      return -1;
+    }
+
+  osip_message_set_content_length (response, "0");
+  /*  send message to transaction layer */
+
+  evt_answer = osip_new_outgoing_sipmessage (response);
+  evt_answer->transactionid = tr->transactionid;
+
+  osip_transaction_add_event (tr, evt_answer);
+  __eXosip_wakeup ();
+  return 0;
+}
+
+
+int
+_eXosip_insubscription_answer_1xx (eXosip_notify_t * jn, eXosip_dialog_t * jd,
+                                   int code)
+{
+  osip_event_t *evt_answer;
+  osip_message_t *response;
+  int i;
+  osip_transaction_t *tr;
+
+  tr = eXosip_find_last_inc_subscribe (jn, jd);
+  if (tr == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: cannot find transaction to answer"));
+      return -1;
+    }
+
+  if (jd == NULL)
+    i = _eXosip_build_response_default (&response, NULL, code, tr->orig_request);
+  else
+    i =
+      _eXosip_build_response_default (&response, jd->d_dialog, code,
+                                      tr->orig_request);
+
+  if (i != 0)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "ERROR: Could not create response for subscribe\n"));
+      return -1;
+    }
+
+  if (code > 100)
+    {
+      /* request that estabish a dialog: */
+      /* 12.1.1 UAS Behavior */
+      i = complete_answer_that_establish_a_dialog (response, tr->orig_request);
+
+      if (jd == NULL)
+        {
+          i = eXosip_dialog_init_as_uas (&jd, tr->orig_request, response);
+          if (i != 0)
+            {
+              OSIP_TRACE (osip_trace
+                          (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                           "eXosip: cannot create dialog!\n"));
+            }
+          ADD_ELEMENT (jn->n_dialogs, jd);
+        }
+    }
+
+  evt_answer = osip_new_outgoing_sipmessage (response);
+  evt_answer->transactionid = tr->transactionid;
+
+  osip_transaction_add_event (tr, evt_answer);
+  __eXosip_wakeup ();
+  return 0;
+}
+
+int
+_eXosip_insubscription_answer_2xx (eXosip_notify_t * jn, eXosip_dialog_t * jd,
+                                   int code)
+{
+  osip_event_t *evt_answer;
+  osip_message_t *response;
+  int i;
+  osip_transaction_t *tr;
+
+  tr = eXosip_find_last_inc_subscribe (jn, jd);
+
+  if (tr == NULL || tr->orig_request == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: cannot find transaction to answer\n"));
+      return -1;
+    }
+
+  if (jd != NULL && jd->d_dialog == NULL)
+    {                           /* element previously removed, this is a no hop! */
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: cannot answer this closed transaction\n"));
+      return -1;
+    }
+
+  if (jd == NULL)
+    i = _eXosip_build_response_default (&response, NULL, code, tr->orig_request);
+  else
+    i =
+      _eXosip_build_response_default (&response, jd->d_dialog, code,
+                                      tr->orig_request);
+
+  if (i != 0)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                   "ERROR: Could not create response for subscribe\n"));
+      code = 500;               /* ? which code to use? */
+      return -1;
+    }
+
+  /* request that estabish a dialog: */
+  /* 12.1.1 UAS Behavior */
+  {
+    i = complete_answer_that_establish_a_dialog (response, tr->orig_request);
+    if (i != 0)
+      goto g2atii_error_1;;     /* ?? */
+  }
+
+  /* THIS RESPONSE MUST BE SENT RELIABILY until the final ACK is received !! */
+  /* this response must be stored at the upper layer!!! (it will be destroyed */
+  /* right after being sent! */
+
+  if (jd == NULL)
+    {
+      i = eXosip_dialog_init_as_uas (&jd, tr->orig_request, response);
+      if (i != 0)
+        {
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                       "eXosip: cannot create dialog!\n"));
+          return -1;
+        }
+      ADD_ELEMENT (jn->n_dialogs, jd);
+    }
+
+  eXosip_dialog_set_200ok (jd, response);
+  evt_answer = osip_new_outgoing_sipmessage (response);
+  evt_answer->transactionid = tr->transactionid;
+
+  osip_transaction_add_event (tr, evt_answer);
+  __eXosip_wakeup ();
+
+  osip_dialog_set_state (jd->d_dialog, DIALOG_CONFIRMED);
+  return 0;
+
+g2atii_error_1:
+  osip_message_free (response);
+  return -1;
+}
+
+int
+_eXosip_insubscription_answer_3456xx (eXosip_notify_t * jn,
+                                      eXosip_dialog_t * jd, int code)
+{
+  osip_event_t *evt_answer;
+  osip_message_t *response;
+  int i;
+  osip_transaction_t *tr;
+
+  tr = eXosip_find_last_inc_subscribe (jn, jd);
+  if (tr == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: cannot find transaction to answer"));
+      return -1;
+    }
+  if (jd == NULL)
+    i = _eXosip_build_response_default (&response, NULL, code, tr->orig_request);
+  else
+    i =
+      _eXosip_build_response_default (&response, jd->d_dialog, code,
+                                      tr->orig_request);
+  if (i != 0)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                   "ERROR: Could not create response for subscribe\n"));
+      return -1;
+    }
+
+  if ((300 <= code) && (code <= 399))
+    {
+      /* Should add contact fields */
+      /* ... */
+    }
+
+  evt_answer = osip_new_outgoing_sipmessage (response);
+  evt_answer->transactionid = tr->transactionid;
+
+  osip_transaction_add_event (tr, evt_answer);
+  __eXosip_wakeup ();
+  return 0;
+}
diff --git a/exosip2/jsubscribe.c b/exosip2/jsubscribe.c
new file mode 100644
index 0000000000..7f58c79367
--- /dev/null
+++ b/exosip2/jsubscribe.c
@@ -0,0 +1,150 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002, 2003  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+
+#include "eXosip2.h"
+
+extern eXosip_t eXosip;
+
+osip_transaction_t *
+eXosip_find_last_out_subscribe (eXosip_subscribe_t * js, eXosip_dialog_t * jd)
+{
+  osip_transaction_t *out_tr;
+  int pos;
+
+  out_tr = NULL;
+  pos = 0;
+  if (jd != NULL)
+    {
+      while (!osip_list_eol (jd->d_out_trs, pos))
+        {
+          out_tr = osip_list_get (jd->d_out_trs, pos);
+          if (0 == strcmp (out_tr->cseq->method, "SUBSCRIBE"))
+            break;
+          else
+            out_tr = NULL;
+          pos++;
+        }
+  } else
+    out_tr = NULL;
+
+  if (out_tr == NULL)
+    return js->s_out_tr;        /* can be NULL */
+
+  return out_tr;
+}
+
+osip_transaction_t *
+eXosip_find_last_inc_notify (eXosip_subscribe_t * js, eXosip_dialog_t * jd)
+{
+  osip_transaction_t *out_tr;
+  int pos;
+
+  out_tr = NULL;
+  pos = 0;
+  if (jd != NULL)
+    {
+      while (!osip_list_eol (jd->d_out_trs, pos))
+        {
+          out_tr = osip_list_get (jd->d_out_trs, pos);
+          if (0 == strcmp (out_tr->cseq->method, "NOTIFY"))
+            return out_tr;
+          pos++;
+        }
+    }
+
+  return NULL;
+}
+
+
+int
+eXosip_subscribe_init (eXosip_subscribe_t ** js)
+{
+  *js = (eXosip_subscribe_t *) osip_malloc (sizeof (eXosip_subscribe_t));
+  if (*js == NULL)
+    return -1;
+  memset (*js, 0, sizeof (eXosip_subscribe_t));
+  return 0;
+}
+
+void
+eXosip_subscribe_free (eXosip_subscribe_t * js)
+{
+  /* ... */
+
+  eXosip_dialog_t *jd;
+
+  for (jd = js->s_dialogs; jd != NULL; jd = js->s_dialogs)
+    {
+      REMOVE_ELEMENT (js->s_dialogs, jd);
+      eXosip_dialog_free (jd);
+    }
+
+  __eXosip_delete_jinfo (js->s_inc_tr);
+  __eXosip_delete_jinfo (js->s_out_tr);
+  if (js->s_inc_tr != NULL)
+    osip_list_add (eXosip.j_transactions, js->s_inc_tr, 0);
+  if (js->s_out_tr != NULL)
+    osip_list_add (eXosip.j_transactions, js->s_out_tr, 0);
+
+  osip_free (js);
+}
+
+int
+_eXosip_subscribe_set_refresh_interval (eXosip_subscribe_t * js,
+                                        osip_message_t * out_subscribe)
+{
+  osip_header_t *exp;
+
+  if (js == NULL || out_subscribe == NULL)
+    return -1;
+
+  osip_message_get_expires (out_subscribe, 0, &exp);
+  if (exp == NULL || exp->hvalue == NULL)
+    js->s_reg_period = 3600;
+  else
+    {
+      js->s_reg_period = osip_atoi (exp->hvalue);
+      if (js->s_reg_period < 0)
+        js->s_reg_period = 3600;
+    }
+
+  return 0;
+}
+
+int
+eXosip_subscribe_need_refresh (eXosip_subscribe_t * js, eXosip_dialog_t * jd,
+                               int now)
+{
+  osip_transaction_t *out_tr = NULL;
+
+  if (jd != NULL)
+    out_tr = osip_list_get (jd->d_out_trs, 0);
+  if (out_tr == NULL)
+    out_tr = js->s_out_tr;
+
+  if (now - out_tr->birth_time > js->s_reg_period - 60)
+    return 0;
+  return -1;
+}
diff --git a/exosip2/misc.c b/exosip2/misc.c
new file mode 100644
index 0000000000..b811c4764d
--- /dev/null
+++ b/exosip2/misc.c
@@ -0,0 +1,239 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002, 2003  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+
+#include "eXosip2.h"
+
+extern eXosip_t eXosip;
+
+
+/* some methods to extract transaction information from a eXosip_call_t */
+
+int
+eXosip_remove_transaction_from_call (osip_transaction_t * tr, eXosip_call_t * jc)
+{
+  osip_transaction_t *inc_tr;
+  osip_transaction_t *out_tr;
+  eXosip_dialog_t *jd;
+  int pos = 0;
+
+  if (jc->c_inc_tr == tr)
+    {
+      jc->c_inc_tr = NULL;      /* can be NULL */
+      return 0;
+    }
+
+  for (jd = jc->c_dialogs; jd != NULL; jd = jd->next)
+    {
+      pos = 0;
+      while (!osip_list_eol (jd->d_inc_trs, pos))
+        {
+          inc_tr = osip_list_get (jd->d_inc_trs, pos);
+          if (inc_tr == tr)
+            {
+              osip_list_remove (jd->d_inc_trs, pos);
+              return 0;
+            }
+          pos++;
+        }
+    }
+
+  if (jc->c_out_tr == tr)
+    {
+      jc->c_out_tr = NULL;      /* can be NULL */
+      return 0;
+    }
+
+  for (jd = jc->c_dialogs; jd != NULL; jd = jd->next)
+    {
+      pos = 0;
+      while (!osip_list_eol (jd->d_out_trs, pos))
+        {
+          out_tr = osip_list_get (jd->d_out_trs, pos);
+          if (out_tr == tr)
+            {
+              osip_list_remove (jd->d_out_trs, pos);
+              return 0;
+            }
+          pos++;
+        }
+    }
+
+  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                          "eXosip: No information.\n"));
+  return -1;
+}
+
+osip_transaction_t *
+eXosip_find_last_transaction (eXosip_call_t * jc, eXosip_dialog_t * jd,
+                              const char *method)
+{
+  osip_transaction_t *inc_tr;
+  osip_transaction_t *out_tr;
+
+  inc_tr = eXosip_find_last_inc_transaction (jc, jd, method);
+  out_tr = eXosip_find_last_out_transaction (jc, jd, method);
+  if (inc_tr == NULL)
+    return out_tr;
+  if (out_tr == NULL)
+    return inc_tr;
+
+  if (inc_tr->birth_time > out_tr->birth_time)
+    return inc_tr;
+  return out_tr;
+}
+
+osip_transaction_t *
+eXosip_find_last_inc_transaction (eXosip_call_t * jc, eXosip_dialog_t * jd,
+                                  const char *method)
+{
+  osip_transaction_t *inc_tr;
+  int pos;
+
+  inc_tr = NULL;
+  pos = 0;
+  if (method == NULL || method[0] == '\0')
+    return NULL;
+  if (jd != NULL)
+    {
+      while (!osip_list_eol (jd->d_inc_trs, pos))
+        {
+          inc_tr = osip_list_get (jd->d_inc_trs, pos);
+          if (0 == osip_strcasecmp (inc_tr->cseq->method, method))
+            break;
+          else
+            inc_tr = NULL;
+          pos++;
+        }
+  } else
+    inc_tr = NULL;
+
+  return inc_tr;
+}
+
+osip_transaction_t *
+eXosip_find_last_out_transaction (eXosip_call_t * jc, eXosip_dialog_t * jd,
+                                  const char *method)
+{
+  osip_transaction_t *out_tr;
+  int pos;
+
+  out_tr = NULL;
+  pos = 0;
+  if (jd == NULL && jc == NULL)
+    return NULL;
+  if (method == NULL || method[0] == '\0')
+    return NULL;
+
+  if (jd != NULL)
+    {
+      while (!osip_list_eol (jd->d_out_trs, pos))
+        {
+          out_tr = osip_list_get (jd->d_out_trs, pos);
+          if (0 == osip_strcasecmp (out_tr->cseq->method, method))
+            break;
+          else
+            out_tr = NULL;
+          pos++;
+        }
+    }
+
+  return out_tr;
+}
+
+osip_transaction_t *
+eXosip_find_last_invite (eXosip_call_t * jc, eXosip_dialog_t * jd)
+{
+  osip_transaction_t *inc_tr;
+  osip_transaction_t *out_tr;
+
+  inc_tr = eXosip_find_last_inc_invite (jc, jd);
+  out_tr = eXosip_find_last_out_invite (jc, jd);
+  if (inc_tr == NULL)
+    return out_tr;
+  if (out_tr == NULL)
+    return inc_tr;
+
+  if (inc_tr->birth_time > out_tr->birth_time)
+    return inc_tr;
+  return out_tr;
+}
+
+osip_transaction_t *
+eXosip_find_last_inc_invite (eXosip_call_t * jc, eXosip_dialog_t * jd)
+{
+  osip_transaction_t *inc_tr;
+  int pos;
+
+  inc_tr = NULL;
+  pos = 0;
+  if (jd != NULL)
+    {
+      while (!osip_list_eol (jd->d_inc_trs, pos))
+        {
+          inc_tr = osip_list_get (jd->d_inc_trs, pos);
+          if (0 == strcmp (inc_tr->cseq->method, "INVITE"))
+            break;
+          else
+            inc_tr = NULL;
+          pos++;
+        }
+  } else
+    inc_tr = NULL;
+
+  if (inc_tr == NULL)
+    return jc->c_inc_tr;        /* can be NULL */
+
+  return inc_tr;
+}
+
+osip_transaction_t *
+eXosip_find_last_out_invite (eXosip_call_t * jc, eXosip_dialog_t * jd)
+{
+  osip_transaction_t *out_tr;
+  int pos;
+
+  out_tr = NULL;
+  pos = 0;
+  if (jd == NULL && jc == NULL)
+    return NULL;
+
+  if (jd != NULL)
+    {
+      while (!osip_list_eol (jd->d_out_trs, pos))
+        {
+          out_tr = osip_list_get (jd->d_out_trs, pos);
+          if (0 == strcmp (out_tr->cseq->method, "INVITE"))
+            break;
+          else
+            out_tr = NULL;
+          pos++;
+        }
+    }
+
+  if (out_tr == NULL)
+    return jc->c_out_tr;        /* can be NULL */
+
+  return out_tr;
+}
diff --git a/exosip2/sdp_offans.c b/exosip2/sdp_offans.c
new file mode 100644
index 0000000000..0d30fdcc19
--- /dev/null
+++ b/exosip2/sdp_offans.c
@@ -0,0 +1,204 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002, 2003  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+#include "eXosip2.h"
+
+extern eXosip_t eXosip;
+
+sdp_message_t *_eXosip_get_remote_sdp (osip_transaction_t * invite_tr);
+sdp_message_t *_eXosip_get_local_sdp (osip_transaction_t * invite_tr);
+
+
+sdp_message_t *
+eXosip_get_remote_sdp (int jid)
+{
+  eXosip_dialog_t *jd = NULL;
+  eXosip_call_t *jc = NULL;
+  osip_transaction_t *invite_tr = NULL;
+
+  if (jid > 0)
+    {
+      eXosip_call_dialog_find (jid, &jc, &jd);
+    }
+  if (jc == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: No call here?\n"));
+      return NULL;
+    }
+  invite_tr = eXosip_find_last_invite (jc, jd);
+  if (invite_tr == NULL)
+    return NULL;
+
+  return _eXosip_get_remote_sdp (invite_tr);
+}
+
+sdp_message_t *
+eXosip_get_local_sdp (int jid)
+{
+  eXosip_dialog_t *jd = NULL;
+  eXosip_call_t *jc = NULL;
+  osip_transaction_t *invite_tr = NULL;
+
+  if (jid > 0)
+    {
+      eXosip_call_dialog_find (jid, &jc, &jd);
+    }
+  if (jc == NULL)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: No call here?\n"));
+      return NULL;
+    }
+  invite_tr = eXosip_find_last_invite (jc, jd);
+  if (invite_tr == NULL)
+    return NULL;
+
+  return _eXosip_get_local_sdp (invite_tr);
+}
+
+sdp_message_t *
+_eXosip_get_remote_sdp (osip_transaction_t * invite_tr)
+{
+  osip_message_t *message;
+
+  if (invite_tr == NULL)
+    return NULL;
+  if (invite_tr->ctx_type == IST)
+    message = invite_tr->orig_request;
+  else if (invite_tr->ctx_type == ICT)
+    message = invite_tr->last_response;
+  else
+    return NULL;
+  return eXosip_get_sdp_info (message);
+}
+
+sdp_message_t *
+_eXosip_get_local_sdp (osip_transaction_t * invite_tr)
+{
+  osip_message_t *message;
+
+  if (invite_tr == NULL)
+    return NULL;
+  if (invite_tr->ctx_type == IST)
+    message = invite_tr->last_response;
+  else if (invite_tr->ctx_type == ICT)
+    message = invite_tr->orig_request;
+  else
+    return NULL;
+  return eXosip_get_sdp_info (message);
+}
+
+sdp_message_t *
+eXosip_get_sdp_info (osip_message_t * message)
+{
+  osip_content_type_t *ctt;
+  osip_mime_version_t *mv;
+  sdp_message_t *sdp;
+  osip_body_t *oldbody;
+  int pos;
+
+  if (message == NULL)
+    return NULL;
+
+  /* get content-type info */
+  ctt = osip_message_get_content_type (message);
+  mv = osip_message_get_mime_version (message);
+  if (mv == NULL && ctt == NULL)
+    return NULL;                /* previous message was not correct or empty */
+  if (mv != NULL)
+    {
+      /* look for the SDP body */
+      /* ... */
+  } else if (ctt != NULL)
+    {
+      if (ctt->type == NULL || ctt->subtype == NULL)
+        /* it can be application/sdp or mime... */
+        return NULL;
+      if (osip_strcasecmp (ctt->type, "application") != 0 ||
+          osip_strcasecmp (ctt->subtype, "sdp") != 0)
+        {
+          return NULL;
+        }
+    }
+
+  pos = 0;
+  while (!osip_list_eol (message->bodies, pos))
+    {
+      int i;
+
+      oldbody = (osip_body_t *) osip_list_get (message->bodies, pos);
+      pos++;
+      sdp_message_init (&sdp);
+      i = sdp_message_parse (sdp, oldbody->body);
+      if (i == 0)
+        return sdp;
+      sdp_message_free (sdp);
+      sdp = NULL;
+    }
+  return NULL;
+}
+
+
+sdp_connection_t *
+eXosip_get_audio_connection (sdp_message_t * sdp)
+{
+  int pos = 0;
+  sdp_media_t *med = (sdp_media_t *) osip_list_get (sdp->m_medias, 0);
+
+  while (med != NULL)
+    {
+      if (med->m_media != NULL && osip_strcasecmp (med->m_media, "audio") == 0)
+        break;
+      pos++;
+      med = (sdp_media_t *) osip_list_get (sdp->m_medias, pos);
+    }
+  if (med == NULL)
+    return NULL;                /* no audio stream */
+  if (osip_list_eol (med->c_connections, 0))
+    return sdp->c_connection;
+
+  /* just return the first one... */
+  return (sdp_connection_t *) osip_list_get (med->c_connections, 0);
+}
+
+
+sdp_media_t *
+eXosip_get_audio_media (sdp_message_t * sdp)
+{
+  int pos = 0;
+  sdp_media_t *med = (sdp_media_t *) osip_list_get (sdp->m_medias, 0);
+
+  while (med != NULL)
+    {
+      if (med->m_media != NULL && osip_strcasecmp (med->m_media, "audio") == 0)
+        return med;
+      pos++;
+      med = (sdp_media_t *) osip_list_get (sdp->m_medias, pos);
+    }
+
+  return NULL;
+}
diff --git a/exosip2/udp.c b/exosip2/udp.c
new file mode 100644
index 0000000000..f70b12daa7
--- /dev/null
+++ b/exosip2/udp.c
@@ -0,0 +1,2307 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002, 2003  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+#include "eXosip2.h"
+#include <eXosip2/eXosip.h>
+
+#ifndef WIN32
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#ifdef __APPLE_CC__
+#include <unistd.h>
+#endif
+#else
+#include <windows.h>
+#endif
+
+extern eXosip_t eXosip;
+extern int ipv6_enable;
+
+/* Private functions */
+static void eXosip_send_default_answer (eXosip_dialog_t * jd,
+                                        osip_transaction_t * transaction,
+                                        osip_event_t * evt,
+                                        int status,
+                                        char *reason_phrase,
+                                        char *warning, int line);
+static void eXosip_process_info (eXosip_call_t * jc, eXosip_dialog_t * jd,
+                                 osip_transaction_t * transaction,
+                                 osip_event_t * evt);
+static void eXosip_process_options (eXosip_call_t * jc, eXosip_dialog_t * jd,
+                                    osip_transaction_t * transaction,
+                                    osip_event_t * evt);
+static void eXosip_process_bye (eXosip_call_t * jc, eXosip_dialog_t * jd,
+                                osip_transaction_t * transaction,
+                                osip_event_t * evt);
+static void eXosip_process_refer (eXosip_call_t * jc, eXosip_dialog_t * jd,
+                                  osip_transaction_t * transaction,
+                                  osip_event_t * evt);
+static void eXosip_process_ack (eXosip_call_t * jc, eXosip_dialog_t * jd,
+                                osip_event_t * evt);
+static void eXosip_process_prack (eXosip_call_t * jc, eXosip_dialog_t * jd,
+                                  osip_transaction_t * transaction,
+                                  osip_event_t * evt);
+static int cancel_match_invite (osip_transaction_t * invite,
+                                osip_message_t * cancel);
+static void eXosip_process_cancel (osip_transaction_t * transaction,
+                                   osip_event_t * evt);
+static osip_event_t *eXosip_process_reinvite (eXosip_call_t * jc,
+                                              eXosip_dialog_t * jd,
+                                              osip_transaction_t *
+                                              transaction, osip_event_t * evt);
+static void eXosip_process_new_options (osip_transaction_t * transaction,
+                                        osip_event_t * evt);
+static void eXosip_process_new_invite (osip_transaction_t * transaction,
+                                       osip_event_t * evt);
+static int eXosip_event_package_is_supported (osip_transaction_t *
+                                              transaction, osip_event_t * evt);
+static void eXosip_process_new_subscribe (osip_transaction_t * transaction,
+                                          osip_event_t * evt);
+static void eXosip_process_subscribe_within_call (eXosip_notify_t * jn,
+                                                  eXosip_dialog_t * jd,
+                                                  osip_transaction_t *
+                                                  transaction, osip_event_t * evt);
+static void eXosip_process_notify_within_dialog (eXosip_subscribe_t * js,
+                                                 eXosip_dialog_t * jd,
+                                                 osip_transaction_t *
+                                                 transaction, osip_event_t * evt);
+static int eXosip_match_notify_for_subscribe (eXosip_subscribe_t * js,
+                                              osip_message_t * notify);
+static void eXosip_process_message_outside_of_dialog (osip_transaction_t * tr,
+						      osip_event_t * evt);
+static void eXosip_process_refer_outside_of_dialog (osip_transaction_t * tr,
+						    osip_event_t * evt);
+static void eXosip_process_message_within_dialog (eXosip_call_t * jc,
+						  eXosip_dialog_t * jd,
+						  osip_transaction_t * transaction,
+						  osip_event_t * evt);
+static void eXosip_process_newrequest (osip_event_t * evt, int socket);
+static void eXosip_process_response_out_of_transaction (osip_event_t * evt);
+static int eXosip_pendingosip_transaction_exist (eXosip_call_t * jc,
+                                                 eXosip_dialog_t * jd);
+static int eXosip_release_finished_calls (eXosip_call_t * jc,
+                                          eXosip_dialog_t * jd);
+static int eXosip_release_aborted_calls (eXosip_call_t * jc, eXosip_dialog_t * jd);
+
+
+static void
+eXosip_send_default_answer (eXosip_dialog_t * jd,
+                            osip_transaction_t * transaction,
+                            osip_event_t * evt,
+                            int status,
+                            char *reason_phrase, char *warning, int line)
+{
+  osip_event_t *evt_answer;
+  osip_message_t *answer;
+  int i;
+
+  /* osip_list_add(eXosip.j_transactions, transaction, 0); */
+  osip_transaction_set_your_instance (transaction, NULL);
+
+  /* THIS METHOD DOES NOT ACCEPT STATUS CODE BETWEEN 101 and 299 */
+  if (status > 100 && status < 299 && MSG_IS_INVITE (evt->sip))
+    return;
+
+  if (jd != NULL)
+    i = _eXosip_build_response_default (&answer, jd->d_dialog, status, evt->sip);
+  else
+    i = _eXosip_build_response_default (&answer, NULL, status, evt->sip);
+
+  if (i != 0 || answer == NULL)
+    {
+      return;
+    }
+
+  if (reason_phrase != NULL)
+    {
+      char *_reason;
+
+      _reason = osip_message_get_reason_phrase (answer);
+      if (_reason != NULL)
+        osip_free (_reason);
+      _reason = osip_strdup (reason_phrase);
+      osip_message_set_reason_phrase (answer, _reason);
+    }
+
+  osip_message_set_content_length (answer, "0");
+
+  if (status == 500)
+    osip_message_set_retry_after (answer, "10");
+
+  evt_answer = osip_new_outgoing_sipmessage (answer);
+  evt_answer->transactionid = transaction->transactionid;
+  osip_transaction_add_event (transaction, evt_answer);
+  __eXosip_wakeup ();
+
+}
+
+static void
+eXosip_process_options (eXosip_call_t * jc, eXosip_dialog_t * jd,
+                        osip_transaction_t * transaction, osip_event_t * evt)
+{
+  osip_list_add (jd->d_inc_trs, transaction, 0);
+  osip_transaction_set_your_instance (transaction,
+                                      __eXosip_new_jinfo (jc, jd, NULL, NULL));
+  __eXosip_wakeup ();
+}
+
+static void
+eXosip_process_info (eXosip_call_t * jc, eXosip_dialog_t * jd,
+                     osip_transaction_t * transaction, osip_event_t * evt)
+{
+  osip_list_add (jd->d_inc_trs, transaction, 0);
+  osip_transaction_set_your_instance (transaction,
+                                      __eXosip_new_jinfo (jc, jd, NULL, NULL));
+  __eXosip_wakeup ();
+}
+
+
+static void
+eXosip_process_bye (eXosip_call_t * jc, eXosip_dialog_t * jd,
+                    osip_transaction_t * transaction, osip_event_t * evt)
+{
+  osip_event_t *evt_answer;
+  osip_message_t *answer;
+  int i;
+
+  osip_transaction_set_your_instance (transaction,
+                                      __eXosip_new_jinfo (jc, NULL /*jd */ ,
+                                                          NULL, NULL));
+
+  i = _eXosip_build_response_default (&answer, jd->d_dialog, 200, evt->sip);
+  if (i != 0)
+    {
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+      return;
+    }
+  osip_message_set_content_length (answer, "0");
+
+  evt_answer = osip_new_outgoing_sipmessage (answer);
+  evt_answer->transactionid = transaction->transactionid;
+
+  osip_list_add (jd->d_inc_trs, transaction, 0);
+
+  /* Release the eXosip_dialog */
+  osip_dialog_free (jd->d_dialog);
+  jd->d_dialog = NULL;
+  report_call_event (EXOSIP_CALL_CLOSED, jc, jd, transaction);
+  eXosip_update(); /* AMD 30/09/05 */
+
+  osip_transaction_add_event (transaction, evt_answer);
+  __eXosip_wakeup ();
+}
+
+static void
+eXosip_process_refer (eXosip_call_t * jc, eXosip_dialog_t * jd,
+                      osip_transaction_t * transaction, osip_event_t * evt)
+{
+  osip_header_t *referto_head = NULL;
+  osip_contact_t *referto;
+  int i;
+
+  /* check if the refer is valid */
+  osip_message_header_get_byname (evt->sip, "refer-to", 0, &referto_head);
+  if (referto_head == NULL || referto_head->hvalue == NULL)
+    {
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+      eXosip_send_default_answer (jd, transaction, evt, 400,
+                                  "Missing Refer-To header",
+                                  "Missing Refer-To header", __LINE__);
+      return;
+    }
+  /* check if refer-to is well-formed */
+  osip_contact_init (&referto);
+  i = osip_contact_parse (referto, referto_head->hvalue);
+  if (i != 0)
+    {
+      osip_contact_free (referto);
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+      eXosip_send_default_answer (jd, transaction, evt, 400,
+                                  "Non valid Refer-To header",
+                                  "Non valid Refer-To header", __LINE__);
+      return;
+    }
+
+  osip_contact_free (referto);
+
+  /* check policy so we can decline immediatly the refer */
+
+  osip_transaction_set_your_instance (transaction,
+                                      __eXosip_new_jinfo (jc, jd, NULL, NULL));
+  osip_list_add (jd->d_inc_trs, transaction, 0);
+  __eXosip_wakeup ();
+}
+
+static void
+eXosip_process_notify_for_refer (eXosip_call_t * jc, eXosip_dialog_t * jd,
+                                 osip_transaction_t * transaction,
+                                 osip_event_t * evt)
+{
+  osip_event_t *evt_answer;
+  osip_message_t *answer;
+  int i;
+  osip_transaction_t *ref;
+  osip_header_t *event_hdr;
+  osip_header_t *sub_state;
+  osip_content_type_t *ctype;
+  osip_body_t *body = NULL;
+
+  /* get the event type and return "489 Bad Event". */
+  osip_message_header_get_byname (evt->sip, "event", 0, &event_hdr);
+  if (event_hdr == NULL || event_hdr->hvalue == NULL)
+    {
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+      eXosip_send_default_answer (jd, transaction, evt, 400,
+                                  "Missing Event header in Notify",
+                                  "Missing Event header in Notify", __LINE__);
+      return;
+    }
+  if (NULL==strstr(event_hdr->hvalue, "refer"))
+    {
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+      eXosip_send_default_answer (jd, transaction, evt, 501,
+                                  "Unsupported Event header",
+                                  "Unsupported Event header in Notify", __LINE__);
+      return;
+    }
+  osip_message_header_get_byname (evt->sip, "subscription-state", 0, &sub_state);
+  if (sub_state == NULL || sub_state->hvalue == NULL)
+    {
+#ifndef CISCO_BUG
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+      eXosip_send_default_answer (jd, transaction, evt, 400, "Missing Header",
+                                  "Missing subscription-state Header", __LINE__);
+      return;
+#else
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_WARNING, NULL,
+                   "eXosip: Missing subscription-state Header (cisco 7960 bug)\n"));
+#endif
+    }
+
+  ctype = osip_message_get_content_type (evt->sip);
+  if (ctype == NULL || ctype->type == NULL || ctype->subtype == NULL)
+    {
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+      eXosip_send_default_answer (jd, transaction, evt, 400, "Missing Header",
+                                  "Missing Content-Type Header", __LINE__);
+      return;
+    }
+  if (0 != osip_strcasecmp (ctype->type, "message")
+      || 0 != osip_strcasecmp (ctype->subtype, "sipfrag"))
+    {
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+      eXosip_send_default_answer (jd, transaction, evt, 501,
+                                  "Unsupported body type",
+                                  "Unsupported body type", __LINE__);
+      return;
+    }
+
+  osip_message_get_body (evt->sip, 0, &body);
+  if (body == NULL || body->body == NULL)
+    {
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+      eXosip_send_default_answer (jd, transaction, evt, 400, "Missing Body",
+                                  "Missing Body", __LINE__);
+      return;
+    }
+
+#if 0
+  report_call_event (EXOSIP_CALL_REFER_STATUS, jc, jd, transaction);
+#endif
+
+  /* check if a refer was sent previously! */
+  ref = eXosip_find_last_out_transaction (jc, jd, "REFER");
+  if (ref == NULL)
+    {
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+      eXosip_send_default_answer (jd, transaction, evt, 481, NULL,
+                                  "No associated refer", __LINE__);
+      return;
+    }
+
+  osip_transaction_set_your_instance (transaction,
+                                      __eXosip_new_jinfo (jc, jd, NULL, NULL));
+  /* for now, send default response of 200ok.  eventually, application should
+     be deciding how to answer NOTIFY messages */
+  i = _eXosip_build_response_default (&answer, jd->d_dialog, 200, evt->sip);
+  if (i != 0)
+    {
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+      return;
+    }
+
+  i = complete_answer_that_establish_a_dialog (answer, evt->sip);
+
+  evt_answer = osip_new_outgoing_sipmessage (answer);
+  evt_answer->transactionid = transaction->transactionid;
+
+  osip_list_add (jd->d_inc_trs, transaction, 0);
+
+  osip_transaction_add_event (transaction, evt_answer);
+  __eXosip_wakeup ();
+}
+
+static void
+eXosip_process_ack (eXosip_call_t * jc, eXosip_dialog_t * jd, osip_event_t * evt)
+{
+  /* TODO: We should find the matching transaction for this ACK
+     and also add the ACK in the event. */
+  eXosip_event_t *je;
+  int i;
+
+  je = eXosip_event_init_for_call (EXOSIP_CALL_ACK, jc, jd, NULL);
+  if (je!=NULL)
+    {
+      i = osip_message_clone (evt->sip, &je->ack);
+      if (i != 0)
+        {
+          OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                                  "failed to clone ACK for event\n"));
+        }
+      else
+	report_event (je, NULL);
+    }
+
+  osip_event_free (evt);
+}
+
+static void
+eXosip_process_prack (eXosip_call_t * jc, eXosip_dialog_t * jd,
+                      osip_transaction_t * transaction, osip_event_t * evt)
+{
+  osip_event_t *evt_answer;
+  osip_message_t *answer;
+  int i;
+
+  osip_transaction_set_your_instance (transaction,
+                                      __eXosip_new_jinfo (jc, jd, NULL, NULL));
+  i = _eXosip_build_response_default (&answer, jd->d_dialog, 200, evt->sip);
+  if (i != 0)
+    {
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+      return;
+    }
+
+  evt_answer = osip_new_outgoing_sipmessage (answer);
+  evt_answer->transactionid = transaction->transactionid;
+
+  osip_list_add (jd->d_inc_trs, transaction, 0);
+
+  osip_transaction_add_event (transaction, evt_answer);
+  __eXosip_wakeup ();
+}
+
+static int
+cancel_match_invite (osip_transaction_t * invite, osip_message_t * cancel)
+{
+  osip_generic_param_t *br;
+  osip_generic_param_t *br2;
+  osip_via_t *via;
+
+  osip_via_param_get_byname (invite->topvia, "branch", &br);
+  via = osip_list_get (cancel->vias, 0);
+  if (via == NULL)
+    return -1;                  /* request without via??? */
+  osip_via_param_get_byname (via, "branch", &br2);
+  if (br != NULL && br2 == NULL)
+    return -1;
+  if (br2 != NULL && br == NULL)
+    return -1;
+  if (br2 != NULL && br != NULL)        /* compliant UA  :) */
+    {
+      if (br->gvalue != NULL && br2->gvalue != NULL &&
+          0 == strcmp (br->gvalue, br2->gvalue))
+        return 0;
+      return -1;
+    }
+  /* old backward compatibility mechanism */
+  if (0 != osip_call_id_match (invite->callid, cancel->call_id))
+    return -1;
+  if (0 != osip_to_tag_match (invite->to, cancel->to))
+    return -1;
+  if (0 != osip_from_tag_match (invite->from, cancel->from))
+    return -1;
+  if (0 != osip_via_match (invite->topvia, via))
+    return -1;
+  return 0;
+}
+
+static void
+eXosip_process_cancel (osip_transaction_t * transaction, osip_event_t * evt)
+{
+  osip_transaction_t *tr;
+  osip_event_t *evt_answer;
+  osip_message_t *answer;
+  int i;
+
+  eXosip_call_t *jc;
+  eXosip_dialog_t *jd;
+
+  tr = NULL;
+  jd = NULL;
+  /* first, look for a Dialog in the map of element */
+  for (jc = eXosip.j_calls; jc != NULL; jc = jc->next)
+    {
+      if (jc->c_inc_tr != NULL)
+        {
+          i = cancel_match_invite (jc->c_inc_tr, evt->sip);
+          if (i == 0)
+            {
+              tr = jc->c_inc_tr;
+	      /* fixed */
+	      if (jc->c_dialogs!=NULL)
+		jd = jc->c_dialogs;
+              break;
+            }
+        }
+      tr = NULL;
+      for (jd = jc->c_dialogs; jd != NULL; jd = jd->next)
+        {
+          int pos = 0;
+
+          while (!osip_list_eol (jd->d_inc_trs, pos))
+            {
+              tr = osip_list_get (jd->d_inc_trs, pos);
+              i = cancel_match_invite (tr, evt->sip);
+              if (i == 0)
+                break;
+              tr = NULL;
+              pos++;
+            }
+        }
+      if (jd != NULL)
+        break;                  /* tr has just been found! */
+    }
+
+  if (tr == NULL)               /* we didn't found the transaction to cancel */
+    {
+      i = _eXosip_build_response_default (&answer, NULL, 481, evt->sip);
+      if (i != 0)
+        {
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                       "eXosip: cannot cancel transaction.\n"));
+          osip_list_add (eXosip.j_transactions, tr, 0);
+          osip_transaction_set_your_instance (tr, NULL);
+          return;
+        }
+      osip_message_set_content_length (answer, "0");
+      evt_answer = osip_new_outgoing_sipmessage (answer);
+      evt_answer->transactionid = transaction->transactionid;
+      osip_transaction_add_event (transaction, evt_answer);
+
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+      osip_transaction_set_your_instance (transaction, NULL);
+      __eXosip_wakeup ();
+      return;
+    }
+
+  if (tr->state == IST_TERMINATED || tr->state == IST_CONFIRMED
+      || tr->state == IST_COMPLETED)
+    {
+      /* I can't find the status code in the rfc?
+         (I read I must answer 200? wich I found strange)
+         I probably misunderstood it... and prefer to send 481
+         as the transaction has been answered. */
+      if (jd == NULL)
+        i = _eXosip_build_response_default (&answer, NULL, 481, evt->sip);
+      else
+        i = _eXosip_build_response_default (&answer, jd->d_dialog, 481, evt->sip);
+      if (i != 0)
+        {
+          OSIP_TRACE (osip_trace
+                      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                       "eXosip: cannot cancel transaction.\n"));
+          osip_list_add (eXosip.j_transactions, tr, 0);
+          osip_transaction_set_your_instance (tr, NULL);
+          return;
+        }
+      osip_message_set_content_length (answer, "0");
+      evt_answer = osip_new_outgoing_sipmessage (answer);
+      evt_answer->transactionid = transaction->transactionid;
+      osip_transaction_add_event (transaction, evt_answer);
+
+      if (jd != NULL)
+        osip_list_add (jd->d_inc_trs, transaction, 0);
+      else
+        osip_list_add (eXosip.j_transactions, transaction, 0);
+      osip_transaction_set_your_instance (transaction, NULL);
+      __eXosip_wakeup ();
+
+      return;
+    }
+
+  {
+    if (jd == NULL)
+      i = _eXosip_build_response_default (&answer, NULL, 200, evt->sip);
+    else
+      i = _eXosip_build_response_default (&answer, jd->d_dialog, 200, evt->sip);
+    if (i != 0)
+      {
+        OSIP_TRACE (osip_trace
+                    (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                     "eXosip: cannot cancel transaction.\n"));
+        osip_list_add (eXosip.j_transactions, tr, 0);
+        osip_transaction_set_your_instance (tr, NULL);
+        return;
+      }
+    osip_message_set_content_length (answer, "0");
+    evt_answer = osip_new_outgoing_sipmessage (answer);
+    evt_answer->transactionid = transaction->transactionid;
+    osip_transaction_add_event (transaction, evt_answer);
+    __eXosip_wakeup ();
+
+    if (jd != NULL)
+      osip_list_add (jd->d_inc_trs, transaction, 0);
+    else
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+    osip_transaction_set_your_instance (transaction, NULL);
+
+    /* answer transaction to cancel */
+    if (jd == NULL)
+      i = _eXosip_build_response_default (&answer, NULL, 487, tr->orig_request);
+    else
+      i = _eXosip_build_response_default (&answer, jd->d_dialog, 487,
+                                          tr->orig_request);
+    if (i != 0)
+      {
+        OSIP_TRACE (osip_trace
+                    (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                     "eXosip: cannot cancel transaction.\n"));
+        osip_list_add (eXosip.j_transactions, tr, 0);
+        osip_transaction_set_your_instance (tr, NULL);
+        return;
+      }
+    osip_message_set_content_length (answer, "0");
+    evt_answer = osip_new_outgoing_sipmessage (answer);
+    evt_answer->transactionid = tr->transactionid;
+    osip_transaction_add_event (tr, evt_answer);
+    __eXosip_wakeup ();
+  }
+}
+
+static osip_event_t *
+eXosip_process_reinvite (eXosip_call_t * jc, eXosip_dialog_t * jd,
+                         osip_transaction_t * transaction, osip_event_t * evt)
+{
+  osip_message_t *answer;
+  osip_event_t *sipevent;
+  int i;
+
+  i = _eXosip_build_response_default (&answer, jd->d_dialog, 100, evt->sip);
+  if (i != 0)
+    {
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+      eXosip_send_default_answer (jd, transaction, evt, 500,
+                                  "Internal SIP Error",
+                                  "Failed to build Answer for INVITE within call",
+                                  __LINE__);
+      return NULL;
+    }
+
+  complete_answer_that_establish_a_dialog (answer, evt->sip);
+
+  osip_transaction_set_your_instance (transaction,
+                                      __eXosip_new_jinfo (jc, jd, NULL, NULL));
+  sipevent = osip_new_outgoing_sipmessage (answer);
+  sipevent->transactionid = transaction->transactionid;
+
+  osip_list_add (jd->d_inc_trs, transaction, 0);
+
+  osip_ist_execute (eXosip.j_osip);
+
+  report_call_event (EXOSIP_CALL_REINVITE, jc, jd, transaction);
+  return sipevent;
+}
+
+static void
+eXosip_process_new_options (osip_transaction_t * transaction, osip_event_t * evt)
+{
+  osip_list_add (eXosip.j_transactions, transaction, 0);
+  __eXosip_wakeup ();           /* needed? */
+}
+
+static void
+eXosip_process_new_invite (osip_transaction_t * transaction, osip_event_t * evt)
+{
+  osip_event_t *evt_answer;
+  int i;
+  eXosip_call_t *jc;
+  eXosip_dialog_t *jd;
+  osip_message_t *answer;
+
+  eXosip_call_init (&jc);
+
+  ADD_ELEMENT (eXosip.j_calls, jc);
+
+  i = _eXosip_build_response_default (&answer, NULL, 101, evt->sip);
+  if (i != 0)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: cannot create dialog."));
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+      osip_transaction_set_your_instance (transaction, NULL);
+      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                              "ERROR: Could not create response for invite\n"));
+      return;
+    }
+  osip_message_set_content_length (answer, "0");
+  i = complete_answer_that_establish_a_dialog (answer, evt->sip);
+  if (i != 0)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: cannot complete answer!\n"));
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+      osip_transaction_set_your_instance (transaction, NULL);
+      osip_message_free (answer);
+      return;
+    }
+
+  i = eXosip_dialog_init_as_uas (&jd, evt->sip, answer);
+  if (i != 0)
+    {
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: cannot create dialog!\n"));
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+      osip_transaction_set_your_instance (transaction, NULL);
+      osip_message_free (answer);
+      return;
+    }
+  ADD_ELEMENT (jc->c_dialogs, jd);
+
+  osip_transaction_set_your_instance (transaction,
+                                      __eXosip_new_jinfo (jc, jd, NULL, NULL));
+
+  evt_answer = osip_new_outgoing_sipmessage (answer);
+  evt_answer->transactionid = transaction->transactionid;
+
+  eXosip_update ();
+  jc->c_inc_tr = transaction;
+  osip_transaction_add_event (transaction, evt_answer);
+
+  /* be sure the invite will be processed
+     before any API call on this dialog */
+  osip_ist_execute (eXosip.j_osip);
+
+  if (transaction->orig_request != NULL)
+    {
+      report_call_event (EXOSIP_CALL_INVITE, jc, jd, transaction);
+    }
+
+  __eXosip_wakeup ();
+
+}
+
+static int
+eXosip_event_package_is_supported (osip_transaction_t * transaction,
+                                   osip_event_t * evt)
+{
+  osip_header_t *event_hdr;
+  int code;
+
+  /* get the event type and return "489 Bad Event". */
+  osip_message_header_get_byname (evt->sip, "event", 0, &event_hdr);
+  if (event_hdr == NULL || event_hdr->hvalue == NULL)
+    {
+#ifdef SUPPORT_MSN
+      /* msn don't show any event header */
+      code = 200;               /* Bad Request... anyway... */
+#else
+      code = 400;               /* Bad Request */
+#endif
+  } else if (0 != osip_strcasecmp (event_hdr->hvalue, "presence"))
+    code = 489;
+  else
+    code = 200;
+  if (code != 200)
+    {
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+      eXosip_send_default_answer (NULL, transaction, evt, code, NULL, NULL,
+                                  __LINE__);
+      return 0;
+    }
+  return -1;
+}
+
+static void
+eXosip_process_new_subscribe (osip_transaction_t * transaction, osip_event_t * evt)
+{
+  osip_event_t *evt_answer;
+  eXosip_notify_t *jn;
+  eXosip_dialog_t *jd;
+  osip_message_t *answer;
+  int i;
+
+  eXosip_notify_init (&jn, evt->sip);
+  _eXosip_notify_set_refresh_interval (jn, evt->sip);
+
+  i = _eXosip_build_response_default (&answer, NULL, 101, evt->sip);
+  if (i != 0)
+    {
+      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                              "ERROR: Could not create response for invite\n"));
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+      eXosip_notify_free (jn);
+      return;
+    }
+  i = complete_answer_that_establish_a_dialog (answer, evt->sip);
+  if (i != 0)
+    {
+      osip_message_free (answer);
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: cannot complete answer!\n"));
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+      eXosip_notify_free (jn);
+      return;
+    }
+
+  i = eXosip_dialog_init_as_uas (&jd, evt->sip, answer);
+  if (i != 0)
+    {
+      osip_message_free (answer);
+      OSIP_TRACE (osip_trace
+                  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                   "eXosip: cannot create dialog!\n"));
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+      eXosip_notify_free (jn);
+      return;
+    }
+  ADD_ELEMENT (jn->n_dialogs, jd);
+
+  osip_transaction_set_your_instance (transaction,
+                                      __eXosip_new_jinfo (NULL, jd, NULL, jn));
+
+  evt_answer = osip_new_outgoing_sipmessage (answer);
+  evt_answer->transactionid = transaction->transactionid;
+  osip_transaction_add_event (transaction, evt_answer);
+
+  ADD_ELEMENT (eXosip.j_notifies, jn);
+  __eXosip_wakeup ();
+
+  jn->n_inc_tr = transaction;
+
+  eXosip_update ();
+  __eXosip_wakeup ();
+}
+
+static void
+eXosip_process_subscribe_within_call (eXosip_notify_t * jn,
+                                      eXosip_dialog_t * jd,
+                                      osip_transaction_t * transaction,
+                                      osip_event_t * evt)
+{
+  _eXosip_notify_set_refresh_interval (jn, evt->sip);
+  osip_transaction_set_your_instance (transaction,
+                                      __eXosip_new_jinfo (NULL, jd, NULL, jn));
+
+  /* if subscribe request contains expires="0", close the subscription */
+  {
+    int now = time (NULL);
+
+    if (jn->n_ss_expires - now <= 0)
+      {
+        jn->n_ss_status = EXOSIP_SUBCRSTATE_TERMINATED;
+        jn->n_ss_reason = TIMEOUT;
+      }
+  }
+
+  osip_list_add (jd->d_inc_trs, transaction, 0);
+  __eXosip_wakeup ();
+  return;
+}
+
+static void
+eXosip_process_notify_within_dialog (eXosip_subscribe_t * js,
+                                     eXosip_dialog_t * jd,
+                                     osip_transaction_t * transaction,
+                                     osip_event_t * evt)
+{
+  osip_message_t *answer;
+  osip_event_t *sipevent;
+  osip_header_t *sub_state;
+
+#ifdef SUPPORT_MSN
+  osip_header_t *expires;
+#endif
+  int i;
+
+  if (jd == NULL)
+    {
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+      eXosip_send_default_answer (jd, transaction, evt, 500,
+                                  "Internal SIP Error",
+                                  "No dialog for this NOTIFY", __LINE__);
+      return;
+    }
+
+  /* if subscription-state has a reason state set to terminated,
+     we close the dialog */
+#ifndef SUPPORT_MSN
+  osip_message_header_get_byname (evt->sip, "subscription-state", 0, &sub_state);
+  if (sub_state == NULL || sub_state->hvalue == NULL)
+    {
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+      eXosip_send_default_answer (jd, transaction, evt, 400, NULL, NULL, __LINE__);
+      return;
+    }
+#endif
+
+  i = _eXosip_build_response_default (&answer, jd->d_dialog, 200, evt->sip);
+  if (i != 0)
+    {
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+      eXosip_send_default_answer (jd, transaction, evt, 500,
+                                  "Internal SIP Error",
+                                  "Failed to build Answer for NOTIFY", __LINE__);
+      return;
+    }
+#ifdef SUPPORT_MSN
+  osip_message_header_get_byname (evt->sip, "expires", 0, &expires);
+  if (expires != NULL && expires->hvalue != NULL
+      && 0 == osip_strcasecmp (expires->hvalue, "0"))
+    {
+      /* delete the dialog! */
+      js->s_ss_status = EXOSIP_SUBCRSTATE_TERMINATED;
+      {
+        eXosip_event_t *je;
+
+        je = eXosip_event_init_for_subscribe (EXOSIP_SUBSCRIPTION_NOTIFY, js, jd);
+        eXosip_event_add (je);
+      }
+
+      sipevent = osip_new_outgoing_sipmessage (answer);
+      sipevent->transactionid = transaction->transactionid;
+      osip_transaction_add_event (transaction, sipevent);
+
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+
+      REMOVE_ELEMENT (eXosip.j_subscribes, js);
+      eXosip_subscribe_free (js);
+      __eXosip_wakeup ();
+
+      return;
+  } else
+    {
+      osip_transaction_set_your_instance (transaction,
+                                          __eXosip_new_jinfo (NULL, jd, js, NULL));
+      js->s_ss_status = EXOSIP_SUBCRSTATE_ACTIVE;
+    }
+#else
+  /* modify the status of user */
+  if (0 == osip_strncasecmp (sub_state->hvalue, "active", 6))
+    {
+      js->s_ss_status = EXOSIP_SUBCRSTATE_ACTIVE;
+  } else if (0 == osip_strncasecmp (sub_state->hvalue, "pending", 7))
+    {
+      js->s_ss_status = EXOSIP_SUBCRSTATE_PENDING;
+    }
+
+  if (0 == osip_strncasecmp (sub_state->hvalue, "terminated", 10))
+    {
+      /* delete the dialog! */
+      js->s_ss_status = EXOSIP_SUBCRSTATE_TERMINATED;
+
+      {
+        eXosip_event_t *je;
+
+        je =
+          eXosip_event_init_for_subscribe (EXOSIP_SUBSCRIPTION_NOTIFY, js, jd,
+                                           transaction);
+        eXosip_event_add (je);
+      }
+
+      sipevent = osip_new_outgoing_sipmessage (answer);
+      sipevent->transactionid = transaction->transactionid;
+      osip_transaction_add_event (transaction, sipevent);
+
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+
+      REMOVE_ELEMENT (eXosip.j_subscribes, js);
+      eXosip_subscribe_free (js);
+      __eXosip_wakeup ();
+      return;
+  } else
+    {
+      osip_transaction_set_your_instance (transaction,
+                                          __eXosip_new_jinfo (NULL, jd, js, NULL));
+    }
+#endif
+
+  osip_list_add (jd->d_inc_trs, transaction, 0);
+
+  sipevent = osip_new_outgoing_sipmessage (answer);
+  sipevent->transactionid = transaction->transactionid;
+  osip_transaction_add_event (transaction, sipevent);
+
+  __eXosip_wakeup ();
+  return;
+}
+
+static int
+eXosip_match_notify_for_subscribe (eXosip_subscribe_t * js,
+                                   osip_message_t * notify)
+{
+  osip_transaction_t *out_sub;
+
+  if (js == NULL)
+    return -1;
+  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                          "Trying to match notify with subscribe\n"));
+
+  out_sub = eXosip_find_last_out_subscribe (js, NULL);
+  if (out_sub == NULL || out_sub->orig_request == NULL)
+    return -1;
+  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                          "subscribe transaction found\n"));
+
+  /* some checks to avoid crashing on bad requests */
+  if (notify == NULL || notify->cseq == NULL
+      || notify->cseq->method == NULL || notify->to == NULL)
+    return -1;
+
+  if (0 != osip_call_id_match (out_sub->callid, notify->call_id))
+    return -1;
+
+  {
+    /* The From tag of outgoing request must match
+       the To tag of incoming notify:
+     */
+    osip_generic_param_t *tag_from;
+    osip_generic_param_t *tag_to;
+
+    osip_from_param_get_byname (out_sub->from, "tag", &tag_from);
+    osip_from_param_get_byname (notify->to, "tag", &tag_to);
+    if (tag_to == NULL || tag_to->gvalue == NULL)
+      {
+        OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                                "Uncompliant user agent: no tag in from of outgoing request\n"));
+        return -1;
+      }
+    if (tag_from == NULL || tag_to->gvalue == NULL)
+      {
+        OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                                "Uncompliant user agent: no tag in to of incoming request\n"));
+        return -1;
+      }
+
+    if (0 != strcmp (tag_from->gvalue, tag_to->gvalue))
+      return -1;
+  }
+
+  return 0;
+}
+
+static void
+eXosip_process_message_outside_of_dialog (osip_transaction_t * transaction,
+                                          osip_event_t * evt)
+{
+  osip_list_add (eXosip.j_transactions, transaction, 0);
+  __eXosip_wakeup ();           /* needed? */
+  return;
+}
+
+static void
+eXosip_process_refer_outside_of_dialog (osip_transaction_t * transaction,
+					osip_event_t * evt)
+{
+  osip_list_add (eXosip.j_transactions, transaction, 0);
+  __eXosip_wakeup ();           /* needed? */
+  return;
+}
+
+static void
+eXosip_process_message_within_dialog (eXosip_call_t * jc,
+				      eXosip_dialog_t * jd,
+				      osip_transaction_t * transaction,
+				      osip_event_t * evt)
+{
+  osip_list_add (jd->d_inc_trs, transaction, 0);
+  osip_transaction_set_your_instance (transaction,
+                                      __eXosip_new_jinfo (jc, jd, NULL, NULL));
+  __eXosip_wakeup ();
+  return;
+}
+
+
+static void
+eXosip_process_newrequest (osip_event_t * evt, int socket)
+{
+  osip_transaction_t *transaction;
+  osip_event_t *evt_answer;
+  osip_message_t *answer;
+  int i;
+  int ctx_type;
+  eXosip_call_t *jc;
+  eXosip_subscribe_t *js;
+  eXosip_notify_t *jn;
+  eXosip_dialog_t *jd;
+
+  if (MSG_IS_INVITE (evt->sip))
+    {
+      ctx_type = IST;
+  } else if (MSG_IS_ACK (evt->sip))
+    {                           /* this should be a ACK for 2xx (but could be a late ACK!) */
+      ctx_type = -1;
+  } else if (MSG_IS_REQUEST (evt->sip))
+    {
+      ctx_type = NIST;
+  } else
+    {                           /* We should handle late response and 200 OK before coming here. */
+      ctx_type = -1;
+      osip_event_free (evt);
+      return;
+    }
+
+  transaction = NULL;
+  if (ctx_type != -1)
+    {
+      i = osip_transaction_init (&transaction,
+                                 (osip_fsm_type_t) ctx_type,
+                                 eXosip.j_osip, evt->sip);
+      if (i != 0)
+        {
+          osip_event_free (evt);
+          return;
+        }
+
+      osip_transaction_set_in_socket(transaction, socket);
+      osip_transaction_set_out_socket(transaction, socket);
+
+      evt->transactionid = transaction->transactionid;
+      osip_transaction_set_your_instance (transaction, NULL);
+
+      osip_transaction_add_event (transaction, evt);
+      if (ctx_type == IST)
+        {
+          i = _eXosip_build_response_default (&answer, NULL, 100, evt->sip);
+          if (i != 0)
+            {
+              __eXosip_delete_jinfo (transaction);
+              osip_transaction_free (transaction);
+              return;
+            }
+
+          osip_message_set_content_length (answer, "0");
+          /*  send message to transaction layer */
+
+          evt_answer = osip_new_outgoing_sipmessage (answer);
+          evt_answer->transactionid = transaction->transactionid;
+
+          /* add the REQUEST & the 100 Trying */
+          osip_transaction_add_event (transaction, evt_answer);
+          __eXosip_wakeup ();
+        }
+    }
+
+  if (MSG_IS_CANCEL (evt->sip))
+    {
+      /* special handling for CANCEL */
+      /* in the new spec, if the CANCEL has a Via branch, then it
+         is the same as the one in the original INVITE */
+      eXosip_process_cancel (transaction, evt);
+      return;
+    }
+
+  jd = NULL;
+  /* first, look for a Dialog in the map of element */
+  for (jc = eXosip.j_calls; jc != NULL; jc = jc->next)
+    {
+      for (jd = jc->c_dialogs; jd != NULL; jd = jd->next)
+        {
+          if (jd->d_dialog != NULL)
+            {
+              if (osip_dialog_match_as_uas (jd->d_dialog, evt->sip) == 0)
+                break;
+            }
+        }
+      if (jd != NULL)
+        break;
+    }
+
+
+  if (jd != NULL)
+    {
+      osip_transaction_t *old_trn;
+
+      /* it can be:
+         1: a new INVITE offer.
+         2: a REFER request from one of the party.
+         2: a BYE request from one of the party.
+         3: a REQUEST with a wrong CSeq.
+         4: a NOT-SUPPORTED method with a wrong CSeq.
+       */
+
+      if (!MSG_IS_BYE (evt->sip))
+        {
+          /* reject all requests for a closed dialog */
+          old_trn = eXosip_find_last_inc_transaction (jc, jd, "BYE");
+          if (old_trn == NULL)
+            old_trn = eXosip_find_last_out_transaction (jc, jd, "BYE");
+
+          if (old_trn != NULL)
+            {
+              osip_list_add (eXosip.j_transactions, transaction, 0);
+              eXosip_send_default_answer (jd, transaction, evt, 481, NULL,
+                                          NULL, __LINE__);
+              return;
+            }
+        }
+
+      if (MSG_IS_INVITE (evt->sip))
+        {
+          /* the previous transaction MUST be freed */
+          old_trn = eXosip_find_last_inc_invite (jc, jd);
+
+          if (old_trn != NULL && old_trn->state != IST_TERMINATED)
+            {
+              osip_list_add (eXosip.j_transactions, transaction, 0);
+              eXosip_send_default_answer (jd, transaction, evt, 500,
+                                          "Retry Later",
+                                          "An INVITE is not terminated", __LINE__);
+              return;
+            }
+
+          old_trn = eXosip_find_last_out_invite (jc, jd);
+          if (old_trn != NULL && old_trn->state != ICT_TERMINATED)
+            {
+              osip_list_add (eXosip.j_transactions, transaction, 0);
+              eXosip_send_default_answer (jd, transaction, evt, 491, NULL,
+                                          NULL, __LINE__);
+              return;
+            }
+
+          osip_dialog_update_osip_cseq_as_uas (jd->d_dialog, evt->sip);
+          osip_dialog_update_route_set_as_uas (jd->d_dialog, evt->sip);
+
+          eXosip_process_reinvite (jc, jd, transaction, evt);
+      } else if (MSG_IS_BYE (evt->sip))
+        {
+          old_trn = eXosip_find_last_inc_transaction (jc, jd, "BYE");
+
+          if (old_trn != NULL)  /* && old_trn->state!=NIST_TERMINATED) */
+            {                   /* this situation should NEVER occur?? (we can't receive
+                                   two different BYE for one call! */
+              osip_list_add (eXosip.j_transactions, transaction, 0);
+              eXosip_send_default_answer (jd, transaction, evt, 500,
+                                          "Call Already Terminated",
+                                          "A pending BYE has already terminate this call",
+                                          __LINE__);
+              return;
+            }
+          /* osip_transaction_free(old_trn); */
+          eXosip_process_bye (jc, jd, transaction, evt);
+      } else if (MSG_IS_ACK (evt->sip))
+        {
+          eXosip_process_ack (jc, jd, evt);
+      } else if (MSG_IS_REFER (evt->sip))
+        {
+          eXosip_process_refer (jc, jd, transaction, evt);
+      } else if (MSG_IS_OPTIONS (evt->sip))
+        {
+          eXosip_process_options (jc, jd, transaction, evt);
+      } else if (MSG_IS_INFO (evt->sip))
+        {
+          eXosip_process_info (jc, jd, transaction, evt);
+      } else if (MSG_IS_NOTIFY (evt->sip))
+        {
+          eXosip_process_notify_for_refer (jc, jd, transaction, evt);
+      } else if (MSG_IS_PRACK (evt->sip))
+        {
+          eXosip_process_prack (jc, jd, transaction, evt);
+      } else if (MSG_IS_MESSAGE (evt->sip))
+        {
+          eXosip_process_message_within_dialog (jc, jd, transaction, evt);
+      } else if (MSG_IS_SUBSCRIBE (evt->sip))
+        {
+          osip_list_add (eXosip.j_transactions, transaction, 0);
+          eXosip_send_default_answer (jd, transaction, evt, 489, NULL,
+                                      "Bad Event", __LINE__);
+      } else
+        {
+#if 0
+          osip_list_add (eXosip.j_transactions, transaction, 0);
+          eXosip_send_default_answer (jd, transaction, evt, 405, NULL,
+                                      "Method Not Allowed", __LINE__);
+#else
+	  eXosip_process_message_within_dialog (jc, jd, transaction, evt);
+#endif
+        }
+      return;
+    }
+
+  if (MSG_IS_ACK (evt->sip))
+    {
+      /* no transaction has been found for this ACK! */
+      osip_event_free (evt);
+      return;
+    }
+
+  if (MSG_IS_INFO (evt->sip))
+    {
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+      eXosip_send_default_answer (jd, transaction, evt, 481, NULL, NULL, __LINE__);
+      return;                   /* fixed */
+    }
+  if (MSG_IS_OPTIONS (evt->sip))
+    {
+      eXosip_process_new_options (transaction, evt);
+      return;
+  } else if (MSG_IS_INVITE (evt->sip))
+    {
+      eXosip_process_new_invite (transaction, evt);
+      return;
+  } else if (MSG_IS_BYE (evt->sip))
+    {
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+      eXosip_send_default_answer (jd, transaction, evt, 481, NULL, NULL, __LINE__);
+      return;
+    }
+
+  js = NULL;
+  /* first, look for a Dialog in the map of element */
+  for (js = eXosip.j_subscribes; js != NULL; js = js->next)
+    {
+      for (jd = js->s_dialogs; jd != NULL; jd = jd->next)
+        {
+          if (jd->d_dialog != NULL)
+            {
+              if (osip_dialog_match_as_uas (jd->d_dialog, evt->sip) == 0)
+                break;
+            }
+        }
+      if (jd != NULL)
+        break;
+    }
+
+  if (js != NULL)
+    {
+      /* dialog found */
+      osip_transaction_t *old_trn;
+
+      /* it can be:
+         1: a new INVITE offer.
+         2: a REFER request from one of the party.
+         2: a BYE request from one of the party.
+         3: a REQUEST with a wrong CSeq.
+         4: a NOT-SUPPORTED method with a wrong CSeq.
+       */
+      if (MSG_IS_MESSAGE (evt->sip))
+        {
+          /* eXosip_process_imessage_within_subscribe_dialog(transaction, evt); */
+          osip_list_add (eXosip.j_transactions, transaction, 0);
+          eXosip_send_default_answer (jd, transaction, evt,
+                                      SIP_NOT_IMPLEMENTED, NULL,
+                                      "MESSAGEs within dialogs are not implemented.",
+                                      __LINE__);
+          return;
+      } else if (MSG_IS_NOTIFY (evt->sip))
+        {
+          /* the previous transaction MUST be freed */
+          old_trn = eXosip_find_last_inc_notify (js, jd);
+
+          /* shouldn't we wait for the COMPLETED state? */
+          if (old_trn != NULL && old_trn->state != NIST_TERMINATED)
+            {
+              /* retry later? */
+              osip_list_add (eXosip.j_transactions, transaction, 0);
+              eXosip_send_default_answer (jd, transaction, evt, 500,
+                                          "Retry Later",
+                                          "A pending NOTIFY is not terminated",
+                                          __LINE__);
+              return;
+            }
+
+          osip_dialog_update_osip_cseq_as_uas (jd->d_dialog, evt->sip);
+          osip_dialog_update_route_set_as_uas (jd->d_dialog, evt->sip);
+
+          eXosip_process_notify_within_dialog (js, jd, transaction, evt);
+      } else
+        {
+          osip_list_add (eXosip.j_transactions, transaction, 0);
+          eXosip_send_default_answer (jd, transaction, evt, 501, NULL,
+                                      "Just Not Implemented", __LINE__);
+        }
+      return;
+    }
+
+  if (MSG_IS_NOTIFY (evt->sip))
+    {
+      /* let's try to check if the NOTIFY is related to an existing
+         subscribe */
+      js = NULL;
+      /* first, look for a Dialog in the map of element */
+      for (js = eXosip.j_subscribes; js != NULL; js = js->next)
+        {
+          if (eXosip_match_notify_for_subscribe (js, evt->sip) == 0)
+            {
+              i = eXosip_dialog_init_as_uac (&jd, evt->sip);
+              if (i != 0)
+                {
+                  OSIP_TRACE (osip_trace
+                              (__FILE__, __LINE__, OSIP_ERROR, NULL,
+                               "eXosip: cannot establish a dialog\n"));
+                  return;
+                }
+
+              /* update local cseq from subscribe request */
+              if (js->s_out_tr != NULL && js->s_out_tr->cseq != NULL
+                  && js->s_out_tr->cseq->number != NULL)
+                {
+                  jd->d_dialog->local_cseq = atoi (js->s_out_tr->cseq->number);
+                  OSIP_TRACE (osip_trace
+                              (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                               "eXosip: local cseq has been updated\n"));
+                }
+
+              ADD_ELEMENT (js->s_dialogs, jd);
+              eXosip_update ();
+
+              eXosip_process_notify_within_dialog (js, jd, transaction, evt);
+              return;
+            }
+        }
+
+      osip_list_add (eXosip.j_transactions, transaction, 0);
+      eXosip_send_default_answer (NULL, transaction, evt, 481, NULL, NULL,
+                                  __LINE__);
+      return;
+    }
+
+  jn = NULL;
+  /* first, look for a Dialog in the map of element */
+  for (jn = eXosip.j_notifies; jn != NULL; jn = jn->next)
+    {
+      for (jd = jn->n_dialogs; jd != NULL; jd = jd->next)
+        {
+          if (jd->d_dialog != NULL)
+            {
+              if (osip_dialog_match_as_uas (jd->d_dialog, evt->sip) == 0)
+                break;
+            }
+        }
+      if (jd != NULL)
+        break;
+    }
+
+  if (jn != NULL)
+    {
+      /* dialog found */
+      osip_transaction_t *old_trn;
+
+      /* it can be:
+         1: a new INVITE offer.
+         2: a REFER request from one of the party.
+         2: a BYE request from one of the party.
+         3: a REQUEST with a wrong CSeq.
+         4: a NOT-SUPPORTED method with a wrong CSeq.
+       */
+      if (MSG_IS_MESSAGE (evt->sip))
+        {
+          osip_list_add (eXosip.j_transactions, transaction, 0);
+          eXosip_send_default_answer (jd, transaction, evt,
+                                      SIP_NOT_IMPLEMENTED, NULL,
+                                      "MESSAGEs within dialogs are not implemented.",
+                                      __LINE__);
+          return;
+      } else if (MSG_IS_SUBSCRIBE (evt->sip))
+        {
+          /* the previous transaction MUST be freed */
+          old_trn = eXosip_find_last_inc_subscribe (jn, jd);
+
+          /* shouldn't we wait for the COMPLETED state? */
+          if (old_trn != NULL && old_trn->state != NIST_TERMINATED
+              && old_trn->state != NIST_COMPLETED)
+            {
+              /* retry later? */
+              osip_list_add (eXosip.j_transactions, transaction, 0);
+              eXosip_send_default_answer (jd, transaction, evt, 500,
+                                          "Retry Later",
+                                          "A SUBSCRIBE is not terminated",
+                                          __LINE__);
+              return;
+            }
+
+          osip_dialog_update_osip_cseq_as_uas (jd->d_dialog, evt->sip);
+          osip_dialog_update_route_set_as_uas (jd->d_dialog, evt->sip);
+
+          eXosip_process_subscribe_within_call (jn, jd, transaction, evt);
+      } else
+        {
+          osip_list_add (eXosip.j_transactions, transaction, 0);
+          eXosip_send_default_answer (jd, transaction, evt, 501, NULL, NULL,
+                                      __LINE__);
+        }
+      return;
+    }
+
+  if (MSG_IS_MESSAGE (evt->sip))
+    {
+      eXosip_process_message_outside_of_dialog (transaction, evt);
+      return;
+    }
+
+  if (MSG_IS_REFER (evt->sip))
+    {
+      eXosip_process_refer_outside_of_dialog (transaction, evt);
+      return;
+    }
+
+  if (MSG_IS_SUBSCRIBE (evt->sip))
+    {
+
+      if (0 == eXosip_event_package_is_supported (transaction, evt))
+        {
+          return;
+        }
+      eXosip_process_new_subscribe (transaction, evt);
+      return;
+    }
+
+  /* default answer */
+  osip_list_add (eXosip.j_transactions, transaction, 0);
+#if 0
+  eXosip_send_default_answer (NULL, transaction, evt, 501, NULL, NULL, __LINE__);
+#endif
+}
+
+static void
+eXosip_process_response_out_of_transaction (osip_event_t * evt)
+{
+  osip_event_free (evt);
+}
+
+static int _eXosip_handle_incoming_message(char *buf, size_t len, int socket,
+					   char *host, int port);
+
+static int _eXosip_handle_incoming_message(char *buf, size_t len, int socket,
+					   char *host, int port)
+{
+  osip_transaction_t *transaction = NULL;
+  osip_event_t *sipevent;
+  int i;
+
+  sipevent = osip_parse (buf, len);
+  transaction = NULL;
+  if (sipevent != NULL && sipevent->sip != NULL)
+    {
+    }
+  else
+    {
+      OSIP_TRACE (osip_trace
+		  (__FILE__, __LINE__, OSIP_ERROR, NULL,
+		   "Could not parse SIP message\n"));
+      osip_event_free (sipevent);
+      return -1;
+    }
+
+  OSIP_TRACE (osip_trace
+	      (__FILE__, __LINE__, OSIP_INFO1, NULL,
+	       "Message received from: %s:%i\n",
+	       host, port));
+  
+  osip_message_fix_last_via_header (sipevent->sip,
+				    host,
+				    port);
+  
+  i = osip_find_transaction_and_add_event (eXosip.j_osip, sipevent);
+  if (i != 0)
+    {
+      /* this event has no transaction, */
+      OSIP_TRACE (osip_trace
+		  (__FILE__, __LINE__, OSIP_INFO1, NULL,
+		   "This is a request\n", buf));
+      eXosip_lock ();
+      if (MSG_IS_REQUEST (sipevent->sip))
+	eXosip_process_newrequest (sipevent, socket);
+      else if (MSG_IS_RESPONSE (sipevent->sip))
+	eXosip_process_response_out_of_transaction (sipevent);
+      eXosip_unlock ();
+    }
+  else
+    {
+      /* handled by oSIP ! */
+      return 0;
+    }
+  return 0;
+}
+
+#if defined (WIN32) || defined (_WIN32_WCE)
+#define eXFD_SET(A, B)   FD_SET((unsigned int) A, B)
+#else
+#define eXFD_SET(A, B)   FD_SET(A, B)
+#endif
+
+/* if second==-1 && useconds==-1  -> wait for ever
+   if max_message_nb<=0  -> infinite loop....  */
+int
+eXosip_read_message (int max_message_nb, int sec_max, int usec_max)
+{
+  fd_set osip_fdset;
+  struct timeval tv;
+  char *buf;
+
+  tv.tv_sec = sec_max;
+  tv.tv_usec = usec_max;
+
+  buf = (char *) osip_malloc (SIP_MESSAGE_MAX_LENGTH * sizeof (char) + 1);
+  while (max_message_nb != 0 && eXosip.j_stop_ua == 0)
+    {
+      int i;
+      int max;
+      int wakeup_socket = jpipe_get_read_descr (eXosip.j_socketctl);
+
+      FD_ZERO (&osip_fdset);
+      if (eXosip.net_interfaces[0].net_socket>0)
+	{
+	  eXFD_SET (eXosip.net_interfaces[0].net_socket, &osip_fdset);
+	  max = eXosip.net_interfaces[0].net_socket;
+	}
+      if (eXosip.net_interfaces[1].net_socket>0)
+	{
+	  int pos;
+	  struct eXosip_net *net = &eXosip.net_interfaces[1];
+	  eXFD_SET (net->net_socket, &osip_fdset);
+	  if (net->net_socket>max)
+	    max = net->net_socket;
+
+	  for (pos=0;pos<EXOSIP_MAX_SOCKETS;pos++)
+	    {
+	      if (net->net_socket_tab[pos].socket!=0)
+		{
+		  eXFD_SET (net->net_socket_tab[pos].socket, &osip_fdset);
+		  if (net->net_socket_tab[pos].socket>max)
+		    max = net->net_socket_tab[pos].socket;
+		}
+	    }
+	}
+
+      if (eXosip.net_interfaces[2].net_socket>0)
+	{
+	  eXFD_SET (eXosip.net_interfaces[2].net_socket, &osip_fdset);
+	  if (eXosip.net_interfaces[2].net_socket>max)
+	    max = eXosip.net_interfaces[2].net_socket;
+	}
+
+
+      eXFD_SET (wakeup_socket, &osip_fdset);
+      if (wakeup_socket > max)
+        max = wakeup_socket;
+
+      if ((sec_max == -1) || (usec_max == -1))
+        i = select (max + 1, &osip_fdset, NULL, NULL, NULL);
+      else
+        i = select (max + 1, &osip_fdset, NULL, NULL, &tv);
+
+      if ((i == -1) && (errno == EINTR || errno == EAGAIN))
+        continue;
+
+      if ((i > 0) && FD_ISSET (wakeup_socket, &osip_fdset))
+        {
+          char buf2[500];
+
+          jpipe_read (eXosip.j_socketctl, buf2, 499);
+        }
+
+      if (0 == i || eXosip.j_stop_ua != 0)
+        {
+	} else if (-1 == i)
+	  {
+	    osip_free (buf);
+	    return -2;            /* error */
+	  } else if (FD_ISSET (eXosip.net_interfaces[1].net_socket, &osip_fdset))
+	    {
+	      /* accept incoming connection */
+	      char src6host[NI_MAXHOST];
+	      int recvport = 0;
+	      struct sockaddr_storage sa;
+	      int sock;
+	      int i;
+	      int pos;
+#ifdef __linux
+	      socklen_t slen;
+#else
+	      int slen;
+#endif
+	      if (ipv6_enable == 0)
+		slen = sizeof (struct sockaddr_in);
+	      else
+		slen = sizeof (struct sockaddr_in6);
+
+	      for (pos=0; pos<EXOSIP_MAX_SOCKETS; pos++)
+		{
+		  if (eXosip.net_interfaces[1].net_socket_tab[pos].socket==0)
+		    break;
+		}
+	      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
+				      "creating TCP socket at index: %i\n", pos));
+	      sock = accept(eXosip.net_interfaces[1].net_socket, (struct sockaddr *) &sa, 
+			 &slen);
+	      if (sock<0)
+		{
+		  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
+					  "Error accepting TCP socket\n"));
+		  break;
+		}
+	      eXosip.net_interfaces[1].net_socket_tab[pos].socket = sock;
+	      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
+				      "New TCP connection accepted\n"));
+
+	      memset(src6host, 0, sizeof(src6host));
+	      
+	      if (ipv6_enable == 0)
+		recvport = ntohs (((struct sockaddr_in*)&sa)->sin_port);
+	      else
+		recvport = ntohs (((struct sockaddr_in6*)&sa)->sin6_port);
+	      
+	      i = getnameinfo((struct sockaddr*)&sa, slen,
+			      src6host, NI_MAXHOST,
+			      NULL, 0,
+			      NI_NUMERICHOST);
+	      
+	      if (i!=0)
+		{
+		  OSIP_TRACE (osip_trace
+			      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+			       "Message received from: %s:%i Error with getnameinfo\n",
+			       src6host, recvport));
+		}
+	      else           
+		{
+		  OSIP_TRACE (osip_trace
+			      (__FILE__, __LINE__, OSIP_INFO1, NULL,
+			       "Message received from: %s:%i\n",
+			       src6host, recvport));
+		  osip_strncpy(eXosip.net_interfaces[1].net_socket_tab[pos].remote_ip,
+			       src6host,
+			       sizeof(eXosip.net_interfaces[1].net_socket_tab[pos].remote_ip));
+		  eXosip.net_interfaces[1].net_socket_tab[pos].remote_port = recvport;
+		}
+
+	  } else if (FD_ISSET (eXosip.net_interfaces[0].net_socket, &osip_fdset))
+	    {
+	      /*AMDstruct sockaddr_in sa; */
+	      struct sockaddr_storage sa;
+
+#ifdef __linux
+	      socklen_t slen;
+#else
+	      int slen;
+#endif
+	      if (ipv6_enable == 0)
+		slen = sizeof (struct sockaddr_in);
+	      else
+		slen = sizeof (struct sockaddr_in6);
+
+          i = _eXosip_recvfrom (eXosip.net_interfaces[0].net_socket, buf, SIP_MESSAGE_MAX_LENGTH, 0,
+			    (struct sockaddr *) &sa, &slen);
+
+         if (i > 5)            /* we expect at least one byte, otherwise there's no doubt that it is not a sip message ! */
+		{
+		  /* Message might not end with a "\0" but we know the number of */
+		  /* char received! */
+		  osip_transaction_t *transaction = NULL;
+		  osip_event_t *sipevent;
+
+		  osip_strncpy (buf + i, "\0", 1);
+		  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
+					  "Received message: \n%s\n", buf));
+#ifdef WIN32
+		  if (strlen (buf) > 412)
+		    {
+		      OSIP_TRACE (osip_trace
+				  (__FILE__, __LINE__, OSIP_INFO1, NULL,
+				   "Message suite: \n%s\n", buf + 412));
+		    }
+#endif
+
+		  sipevent = osip_parse (buf, i);
+		  transaction = NULL;
+		  if (sipevent != NULL && sipevent->sip != NULL)
+          {
+            if (!eXosip.http_port)
+            {
+		      char src6host[NI_MAXHOST];
+		      char src6buf[NI_MAXSERV];
+		      int recvport = 0;
+		      memset(src6host, 0, sizeof(src6host));
+		      memset(src6buf, 0, sizeof(src6buf));
+		  
+		      if (ipv6_enable == 0)
+			recvport = ntohs (((struct sockaddr_in*)&sa)->sin_port);
+		      else
+			recvport = ntohs (((struct sockaddr_in6*)&sa)->sin6_port);
+
+		      i = getnameinfo((struct sockaddr*)&sa, slen,
+				      src6host, NI_MAXHOST,
+				      NULL, 0,
+				      NI_NUMERICHOST);
+
+		      if (i!=0)
+			{
+			  OSIP_TRACE (osip_trace
+				      (__FILE__, __LINE__, OSIP_ERROR, NULL,
+				       "Message received from: %s:%i (serv=%s) Error with getnameinfo\n",
+				       src6host, recvport, src6buf));
+			}
+		      else           
+			{
+			  OSIP_TRACE (osip_trace
+				      (__FILE__, __LINE__, OSIP_INFO1, NULL,
+				       "Message received from: %s:%i (serv=%s)\n",
+				       src6host, recvport, src6buf));          
+			}
+
+		      OSIP_TRACE (osip_trace
+				  (__FILE__, __LINE__, OSIP_INFO1, NULL,
+				   "Message received from: %s:%i (serv=%s)\n",
+				   src6host, recvport, src6buf));
+
+		      osip_message_fix_last_via_header (sipevent->sip,
+							src6host,
+							recvport);
+            }
+		      i =
+			osip_find_transaction_and_add_event (eXosip.j_osip, sipevent);
+		      if (i != 0)
+			{
+			  /* this event has no transaction, */
+			  OSIP_TRACE (osip_trace
+				      (__FILE__, __LINE__, OSIP_INFO1, NULL,
+				       "This is a request\n", buf));
+			  eXosip_lock ();
+			  if (MSG_IS_REQUEST (sipevent->sip))
+			    eXosip_process_newrequest (sipevent, 0);
+			  else if (MSG_IS_RESPONSE (sipevent->sip))
+			    eXosip_process_response_out_of_transaction (sipevent);
+			  eXosip_unlock ();
+			} else
+			  {
+			    /* handled by oSIP ! */
+			  }
+		    } else
+		      {
+			OSIP_TRACE (osip_trace
+				    (__FILE__, __LINE__, OSIP_ERROR, NULL,
+				     "Could not parse SIP message\n"));
+			osip_event_free (sipevent);
+		      }
+		} else if (i < 0)
+		  {
+		    OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
+					    "Could not read socket\n"));
+		  } else
+		    {
+		      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
+					      "Dummy SIP message received\n"));
+		    }
+	    }
+      else
+	{
+	  /* loop over all TCP socket */
+	  int pos = 0;
+	  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
+				  "TCP DATA ready?\n"));
+	  for (pos=0; pos<EXOSIP_MAX_SOCKETS; pos++)
+	    {
+	      if (eXosip.net_interfaces[1].net_socket_tab[pos].socket>0
+		  && FD_ISSET (eXosip.net_interfaces[1].net_socket_tab[pos].socket, &osip_fdset))
+		{
+		  OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
+					  "TCP DATA ready! message received\n"));
+		  i = recv (eXosip.net_interfaces[1].net_socket_tab[pos].socket,
+			    buf, SIP_MESSAGE_MAX_LENGTH, 0);
+		  if (i > 5)
+		    {
+		      osip_strncpy (buf + i, "\0", 1);
+		      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
+					      "Received TCP message: \n%s\n", buf));
+#ifdef WIN32
+		      if (strlen (buf) > 412)
+			{
+			  OSIP_TRACE (osip_trace
+				      (__FILE__, __LINE__, OSIP_INFO1, NULL,
+				       "Message suite: \n%s\n", buf + 412));
+			}
+#endif
+		      _eXosip_handle_incoming_message(buf, i,
+						      eXosip.net_interfaces[1].net_socket_tab[pos].socket,
+						      eXosip.net_interfaces[1].net_socket_tab[pos].remote_ip,
+						      eXosip.net_interfaces[1].net_socket_tab[pos].remote_port);
+		    }
+		  else if (i < 0)
+		    {
+		      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL,
+					      "Could not read socket - close it\n"));
+		      close(eXosip.net_interfaces[1].net_socket_tab[pos].socket);
+		      memset(&(eXosip.net_interfaces[1].net_socket_tab[pos]),
+			     0, sizeof(struct eXosip_socket));
+		    }
+		  else if (i==0)
+		    {
+		      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
+					      "End of stream (read 0 byte from %s:%i)\n", eXosip.net_interfaces[1].net_socket_tab[pos].remote_ip, eXosip.net_interfaces[1].net_socket_tab[pos].remote_port));
+		      close(eXosip.net_interfaces[1].net_socket_tab[pos].socket);
+		      memset(&(eXosip.net_interfaces[1].net_socket_tab[pos]),
+			     0, sizeof(struct eXosip_socket));
+		    }
+		  else
+		    {
+		      /* we expect at least one byte, otherwise there's no doubt that it is not a sip message ! */
+		      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
+					      "Dummy SIP message received (size=%i)\n", i));
+		    }
+		}
+	    }
+	}
+
+
+      max_message_nb--;
+    }
+  osip_free (buf);
+  return 0;
+}
+
+
+static int
+eXosip_pendingosip_transaction_exist (eXosip_call_t * jc, eXosip_dialog_t * jd)
+{
+  osip_transaction_t *tr;
+  int now = time (NULL);
+
+  tr = eXosip_find_last_inc_transaction (jc, jd, "BYE");
+  if (tr != NULL && tr->state != NIST_TERMINATED)
+    {                           /* Don't want to wait forever on broken transaction!! */
+      if (tr->birth_time + 180 < now)   /* Wait a max of 2 minutes */
+        {
+          /* remove the transaction from oSIP: */
+          osip_remove_transaction (eXosip.j_osip, tr);
+          eXosip_remove_transaction_from_call (tr, jc);
+	  osip_list_add (eXosip.j_transactions, tr, 0);
+      } else
+        return 0;
+    }
+
+  tr = eXosip_find_last_out_transaction (jc, jd, "BYE");
+  if (tr != NULL && tr->state != NICT_TERMINATED)
+    {                           /* Don't want to wait forever on broken transaction!! */
+      if (tr->birth_time + 180 < now)   /* Wait a max of 2 minutes */
+        {
+          /* remove the transaction from oSIP: */
+          osip_remove_transaction (eXosip.j_osip, tr);
+          eXosip_remove_transaction_from_call (tr, jc);
+	  osip_list_add (eXosip.j_transactions, tr, 0);
+      } else
+        return 0;
+    }
+
+  tr = eXosip_find_last_inc_invite (jc, jd);
+  if (tr != NULL && tr->state != IST_TERMINATED)
+    {                           /* Don't want to wait forever on broken transaction!! */
+      if (tr->birth_time + 180 < now)   /* Wait a max of 2 minutes */
+        {
+          /* remove the transaction from oSIP: */
+          /* osip_remove_transaction(eXosip.j_osip, tr);
+             eXosip_remove_transaction_from_call(tr, jc);
+             osip_transaction_free(tr); */
+      } else
+        return 0;
+    }
+
+  tr = eXosip_find_last_out_invite (jc, jd);
+  if (tr != NULL && tr->state != ICT_TERMINATED)
+    {                           /* Don't want to wait forever on broken transaction!! */
+      if (tr->birth_time + 180 < now)   /* Wait a max of 2 minutes */
+        {
+          /* remove the transaction from oSIP: */
+          /* osip_remove_transaction(eXosip.j_osip, tr);
+             eXosip_remove_transaction_from_call(tr, jc);
+             osip_transaction_free(tr); */
+      } else
+        return 0;
+    }
+
+  tr = eXosip_find_last_inc_transaction (jc, jd, "REFER");
+  if (tr != NULL && tr->state != IST_TERMINATED)
+    {                           /* Don't want to wait forever on broken transaction!! */
+      if (tr->birth_time + 180 < now)   /* Wait a max of 2 minutes */
+        {
+          /* remove the transaction from oSIP: */
+          osip_remove_transaction (eXosip.j_osip, tr);
+          eXosip_remove_transaction_from_call (tr, jc);
+	  osip_list_add (eXosip.j_transactions, tr, 0);
+      } else
+        return 0;
+    }
+
+  tr = eXosip_find_last_out_transaction (jc, jd, "REFER");
+  if (tr != NULL && tr->state != NICT_TERMINATED)
+    {                           /* Don't want to wait forever on broken transaction!! */
+      if (tr->birth_time + 180 < now)   /* Wait a max of 2 minutes */
+        {
+          /* remove the transaction from oSIP: */
+          osip_remove_transaction (eXosip.j_osip, tr);
+          eXosip_remove_transaction_from_call (tr, jc);
+	  osip_list_add (eXosip.j_transactions, tr, 0);
+      } else
+        return 0;
+    }
+
+  return -1;
+}
+
+static int
+eXosip_release_finished_calls (eXosip_call_t * jc, eXosip_dialog_t * jd)
+{
+  osip_transaction_t *tr;
+
+  tr = eXosip_find_last_inc_transaction (jc, jd, "BYE");
+  if (tr == NULL)
+    tr = eXosip_find_last_out_transaction (jc, jd, "BYE");
+
+  if (tr != NULL && (tr->state == NIST_TERMINATED || tr->state == NICT_TERMINATED))
+    {
+        int did = -2;
+        if (jd!=NULL)
+            did = jd->d_id;
+        OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,
+            "eXosip: eXosip_release_finished_calls remove a dialog (cid=%i did=%i)\n", jc->c_id, did));
+      /* Remove existing reference to the dialog from transactions! */
+      __eXosip_call_remove_dialog_reference_in_call (jc, jd);
+      REMOVE_ELEMENT (jc->c_dialogs, jd);
+      eXosip_dialog_free (jd);
+      return 0;
+    }
+  return -1;
+}
+
+
+
+static void
+__eXosip_release_call (eXosip_call_t * jc, eXosip_dialog_t * jd)
+{
+  REMOVE_ELEMENT (eXosip.j_calls, jc);
+  report_call_event (EXOSIP_CALL_RELEASED, jc, jd, NULL);
+  eXosip_call_free (jc);
+  __eXosip_wakeup ();
+}
+
+
+static int
+eXosip_release_aborted_calls (eXosip_call_t * jc, eXosip_dialog_t * jd)
+{
+  int now = time (NULL);
+  osip_transaction_t *tr;
+
+#if 0
+  tr = eXosip_find_last_inc_invite (jc, jd);
+  if (tr == NULL)
+    tr = eXosip_find_last_out_invite (jc, jd);
+#else
+  /* close calls only when the initial INVITE failed */
+  tr = jc->c_inc_tr;
+  if (tr==NULL)
+    tr = jc->c_out_tr;
+#endif
+
+  if (tr == NULL)
+    {
+      if (jd != NULL)
+        {
+          OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                                  "eXosip: eXosip_release_aborted_calls remove an empty dialog\n"));
+          __eXosip_call_remove_dialog_reference_in_call (jc, jd);
+          REMOVE_ELEMENT (jc->c_dialogs, jd);
+          eXosip_dialog_free (jd);
+          return 0;
+        }
+      return -1;
+    }
+
+  if (tr != NULL && tr->state != IST_TERMINATED && tr->state != ICT_TERMINATED && tr->birth_time + 180 < now)   /* Wait a max of 2 minutes */
+    {
+      if (jd != NULL)
+        {
+          OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                                  "eXosip: eXosip_release_aborted_calls remove a dialog for an unfinished transaction\n"));
+          __eXosip_call_remove_dialog_reference_in_call (jc, jd);
+          REMOVE_ELEMENT (jc->c_dialogs, jd);
+          report_call_event (EXOSIP_CALL_NOANSWER, jc, jd, NULL);
+          eXosip_dialog_free (jd);
+          __eXosip_wakeup ();
+          return 0;
+        }
+    }
+
+  if (tr != NULL && (tr->state == IST_TERMINATED || tr->state == ICT_TERMINATED))
+    {
+      if (tr == jc->c_inc_tr)
+        {
+          if (jc->c_inc_tr->last_response == NULL)
+            {
+              /* OSIP_TRACE(osip_trace(__FILE__,__LINE__,OSIP_INFO2,NULL,
+                 "eXosip: eXosip_release_aborted_calls transaction with no answer\n")); */
+          } else if (MSG_IS_STATUS_3XX (jc->c_inc_tr->last_response))
+            {
+              OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                                      "eXosip: eXosip_release_aborted_calls answered with a 3xx\n"));
+              __eXosip_release_call (jc, jd);
+              return 0;
+          } else if (MSG_IS_STATUS_4XX (jc->c_inc_tr->last_response))
+            {
+              OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                                      "eXosip: eXosip_release_aborted_calls answered with a 4xx\n"));
+              __eXosip_release_call (jc, jd);
+              return 0;
+          } else if (MSG_IS_STATUS_5XX (jc->c_inc_tr->last_response))
+            {
+              OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                                      "eXosip: eXosip_release_aborted_calls answered with a 5xx\n"));
+              __eXosip_release_call (jc, jd);
+              return 0;
+          } else if (MSG_IS_STATUS_6XX (jc->c_inc_tr->last_response))
+            {
+              OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                                      "eXosip: eXosip_release_aborted_calls answered with a 6xx\n"));
+              __eXosip_release_call (jc, jd);
+              return 0;
+            }
+      } else if (tr == jc->c_out_tr)
+        {
+          if (jc->c_out_tr->last_response == NULL)
+            {
+              OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                                      "eXosip: eXosip_release_aborted_calls completed with no answer\n"));
+              __eXosip_release_call (jc, jd);
+              return 0;
+          } else if (MSG_IS_STATUS_3XX (jc->c_out_tr->last_response))
+            {
+              OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                                      "eXosip: eXosip_release_aborted_calls completed answered with 3xx\n"));
+              __eXosip_release_call (jc, jd);
+              return 0;
+          } else if (MSG_IS_STATUS_4XX (jc->c_out_tr->last_response))
+            {
+              OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                                      "eXosip: eXosip_release_aborted_calls completed answered with 4xx\n"));
+              __eXosip_release_call (jc, jd);
+              return 0;
+          } else if (MSG_IS_STATUS_5XX (jc->c_out_tr->last_response))
+            {
+              OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                                      "eXosip: eXosip_release_aborted_calls completed answered with 5xx\n"));
+              __eXosip_release_call (jc, jd);
+              return 0;
+          } else if (MSG_IS_STATUS_6XX (jc->c_out_tr->last_response))
+            {
+              OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                                      "eXosip: eXosip_release_aborted_calls completed answered with 6xx\n"));
+              __eXosip_release_call (jc, jd);
+              return 0;
+            }
+        }
+    }
+
+  return -1;
+}
+
+
+void
+eXosip_release_terminated_calls (void)
+{
+  eXosip_dialog_t *jd;
+  eXosip_dialog_t *jdnext;
+  eXosip_call_t *jc;
+  eXosip_call_t *jcnext;
+  int now = time (NULL);
+  int pos;
+
+
+  for (jc = eXosip.j_calls; jc != NULL;)
+    {
+      jcnext = jc->next;
+      /* free call terminated with a BYE */
+
+      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,
+          "eXosip: working on (cid=%i)\n", jc->c_id));
+      for (jd = jc->c_dialogs; jd != NULL;)
+        {
+          jdnext = jd->next;
+          OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,
+              "eXosip: working on (cid=%i did=%i)\n", jc->c_id, jd->d_id));
+          if (0 == eXosip_pendingosip_transaction_exist (jc, jd))
+            {
+          } else if (0 == eXosip_release_finished_calls (jc, jd))
+            {
+              jd = jc->c_dialogs;
+          } else if (0 == eXosip_release_aborted_calls (jc, jd))
+            {
+              jdnext = NULL;
+          } else if (jd->d_id==-1)
+            {
+                OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL,
+                    "eXosip: eXosip_release_terminated_calls delete a removed dialog (cid=%i did=%i)\n", jc->c_id, jd->d_id));
+                /* Remove existing reference to the dialog from transactions! */
+                __eXosip_call_remove_dialog_reference_in_call (jc, jd);
+                REMOVE_ELEMENT (jc->c_dialogs, jd);
+                eXosip_dialog_free (jd);
+
+                jd = jc->c_dialogs;
+            }
+          jd = jdnext;
+        }
+      jc = jcnext;
+    }
+
+  for (jc = eXosip.j_calls; jc != NULL;)
+    {
+      jcnext = jc->next;
+      if (jc->c_dialogs == NULL)
+        {
+          /* release call for options requests */
+          if (jc->c_inc_options_tr != NULL)
+            {
+              if (jc->c_inc_options_tr->state == NIST_TERMINATED)
+                {
+                  OSIP_TRACE (osip_trace
+                              (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                               "eXosip: remove an incoming OPTIONS with no final answer\n"));
+                  __eXosip_release_call (jc, NULL);
+              } else if (jc->c_inc_options_tr->state != NIST_TERMINATED
+                         && jc->c_inc_options_tr->birth_time + 180 < now)
+                {
+                  OSIP_TRACE (osip_trace
+                              (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                               "eXosip: remove an incoming OPTIONS with no final answer\n"));
+                  __eXosip_release_call (jc, NULL);
+                }
+          } else if (jc->c_out_options_tr != NULL)
+            {
+              if (jc->c_out_options_tr->state == NICT_TERMINATED)
+                {
+                  OSIP_TRACE (osip_trace
+                              (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                               "eXosip: remove an outgoing OPTIONS with no final answer\n"));
+                  __eXosip_release_call (jc, NULL);
+              } else if (jc->c_out_options_tr->state != NIST_TERMINATED
+                         && jc->c_out_options_tr->birth_time + 180 < now)
+                {
+                  OSIP_TRACE (osip_trace
+                              (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                               "eXosip: remove an outgoing OPTIONS with no final answer\n"));
+                  __eXosip_release_call (jc, NULL);
+                }
+          } else if (jc->c_inc_tr != NULL
+                     && jc->c_inc_tr->state != IST_TERMINATED
+                     && jc->c_inc_tr->birth_time + 180 < now)
+            {
+              OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                                      "eXosip: remove an incoming call with no final answer\n"));
+              __eXosip_release_call (jc, NULL);
+          } else if (jc->c_out_tr != NULL
+                     && jc->c_out_tr->state != ICT_TERMINATED
+                     && jc->c_out_tr->birth_time + 180 < now)
+            {
+              OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                                      "eXosip: remove an outgoing call with no final answer\n"));
+              __eXosip_release_call (jc, NULL);
+          } else if (jc->c_inc_tr != NULL && jc->c_inc_tr->state != IST_TERMINATED)
+            {
+          } else if (jc->c_out_tr != NULL && jc->c_out_tr->state != ICT_TERMINATED)
+            {
+          } else                /* no active pending transaction */
+            {
+              OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                                      "eXosip: remove a call\n"));
+              __eXosip_release_call (jc, NULL);
+            }
+        }
+      jc = jcnext;
+    }
+
+  pos = 0;
+  while (!osip_list_eol (eXosip.j_transactions, pos))
+    {
+      osip_transaction_t *tr =
+        (osip_transaction_t *) osip_list_get (eXosip.j_transactions, pos);
+      if (tr->state == IST_TERMINATED || tr->state == ICT_TERMINATED
+          || tr->state == NICT_TERMINATED || tr->state == NIST_TERMINATED)
+
+        {                       /* free (transaction is already removed from the oSIP stack) */
+          OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
+                                  "Release a terminated transaction\n"));
+          osip_list_remove (eXosip.j_transactions, pos);
+          __eXosip_delete_jinfo (tr);
+          osip_transaction_free (tr);
+      } else if (tr->birth_time + 180 < now)    /* Wait a max of 2 minutes */
+        {
+          osip_list_remove (eXosip.j_transactions, pos);
+          __eXosip_delete_jinfo (tr);
+          osip_transaction_free (tr);
+      } else
+        pos++;
+    }
+}
+
+void
+eXosip_release_terminated_registrations (void)
+{
+  eXosip_reg_t *jr;
+  eXosip_reg_t *jrnext;
+  int now = time (NULL);
+
+  for (jr = eXosip.j_reg; jr != NULL;)
+    {
+      jrnext = jr->next;
+      if (jr->r_reg_period == 0 && jr->r_last_tr!=NULL)
+	{
+	  if (now - jr->r_last_tr->birth_time > 60)
+	    {
+	      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
+				      "Release a terminated registration\n"));
+	      REMOVE_ELEMENT (eXosip.j_reg, jr);
+	      eXosip_reg_free (jr);
+	    }
+	  else if (jr->r_last_tr->last_response!=NULL
+		   && jr->r_last_tr->last_response->status_code>=200
+		   && jr->r_last_tr->last_response->status_code<=299)
+	    {
+	      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL,
+				      "Release a terminated registration with 2xx\n"));
+	      REMOVE_ELEMENT (eXosip.j_reg, jr);
+	      eXosip_reg_free (jr);
+	    }
+	}
+
+      jr = jrnext;
+    }
+
+  return;
+}
diff --git a/include/Makefile.am b/include/Makefile.am
new file mode 100644
index 0000000000..72f64586eb
--- /dev/null
+++ b/include/Makefile.am
@@ -0,0 +1,3 @@
+
+SUBDIRS = eXosip2
+
diff --git a/include/eXosip2/Makefile.am b/include/eXosip2/Makefile.am
new file mode 100644
index 0000000000..5344a8b4c4
--- /dev/null
+++ b/include/eXosip2/Makefile.am
@@ -0,0 +1,6 @@
+
+
+noinst_HEADERS= eXosip.h eX_setup.h \
+eX_register.h eX_call.h eX_options.h eX_refer.h \
+eX_subscribe.h eX_publish.h eX_message.h
+
diff --git a/include/eXosip2/eX_call.h b/include/eXosip2/eX_call.h
new file mode 100644
index 0000000000..b42d47b852
--- /dev/null
+++ b/include/eXosip2/eX_call.h
@@ -0,0 +1,231 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002,2003,2004,2005  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+#ifndef __EX_CALL_H__
+#define __EX_CALL_H__
+
+#include <osipparser2/osip_parser.h>
+#include <osipparser2/sdp_message.h>
+#include <time.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * @file eX_call.h
+ * @brief eXosip call API
+ *
+ * This file provide the API needed to control calls. You can
+ * use it to:
+ *
+ * <ul>
+ * <li>build initial invite.</li>
+ * <li>send initial invite.</li>
+ * <li>build request within the call.</li>
+ * <li>send request within the call.</li>
+ * </ul>
+ *
+ * This API can be used to build the following messages:
+ * <pre>
+ *    INVITE, INFO, OPTIONS, REFER, UPDATE, NOTIFY
+ * </pre>
+ */
+
+/**
+ * @defgroup eXosip2_call eXosip2 INVITE and Call Management
+ * @ingroup eXosip2_msg
+ * @{
+ */
+
+  struct eXosip_call_t;
+
+/**
+ * Set a new application context for an existing call
+ *
+ * @param id       call-id or dialog-id of call
+ * @param reference New application context.
+ */
+  int eXosip_call_set_reference(int id, void *reference);
+
+/**
+ * Build a default INVITE message for a new call.
+ * 
+ * @param invite    Pointer for the SIP element to hold.
+ * @param to        SIP url for callee.
+ * @param from      SIP url for caller.
+ * @param route     Route header for INVITE. (optionnal)
+ * @param subject   Subject for the call.
+ */
+  int eXosip_call_build_initial_invite(osip_message_t **invite, const char *to,
+				       const char *from, const char *route,
+				       const char *subject);
+
+/**
+ * Initiate a call.
+ * 
+ * @param invite          SIP INVITE message to send.
+ */
+  int eXosip_call_send_initial_invite(osip_message_t *invite);
+
+/**
+ * Build a default request within a call. (INVITE, OPTIONS, INFO, REFER)
+ * 
+ * @param did          dialog id of call.
+ * @param method       request type to build.
+ * @param request      The sip request to build.
+ */
+  int eXosip_call_build_request(int did, const char *method,
+				osip_message_t **request);
+
+/**
+ * Build a default ACK for a 200ok received.
+ * 
+ * @param did          dialog id of call.
+ * @param ack          The sip request to build.
+ */
+  int eXosip_call_build_ack(int did, osip_message_t **ack);
+
+/**
+ * Send the ACK for the 200ok received..
+ * 
+ * @param did          dialog id of call.
+ * @param ack          SIP ACK message to send.
+ */
+  int eXosip_call_send_ack(int did, osip_message_t *ack);
+
+/**
+ * Build a default REFER for a call transfer.
+ * 
+ * @param did          dialog id of call.
+ * @param refer_to     url for call transfer (Refer-To header).
+ * @param request      The sip request to build.
+ */
+  int eXosip_call_build_refer(int did, const char *refer_to, osip_message_t **request);
+
+/**
+ * Build a default INFO within a call.
+ * 
+ * @param did          dialog id of call.
+ * @param request      The sip request to build.
+ */
+  int eXosip_call_build_info(int did, osip_message_t **request);
+
+/**
+ * Build a default OPTIONS within a call.
+ * 
+ * @param did          dialog id of call.
+ * @param request      The sip request to build.
+ */
+  int eXosip_call_build_options(int did, osip_message_t **request);
+
+/**
+ * Build a default UPDATE within a call.
+ * 
+ * @param did          dialog id of call.
+ * @param request      The sip request to build.
+ */
+  int eXosip_call_build_update(int did, osip_message_t **request);
+
+/**
+ * Build a default NOTIFY within a call.
+ * 
+ * @param did                   dialog id of call.
+ * @param subscription_status   Subscription status of the request.
+ * @param request               The sip request to build.
+ */
+  int eXosip_call_build_notify(int did, int subscription_status, osip_message_t **request);
+
+/**
+ * send the request within call. (INVITE, OPTIONS, INFO, REFER, UPDATE)
+ * 
+ * @param did          dialog id of call.
+ * @param request      The sip request to send.
+ */
+  int eXosip_call_send_request(int did, osip_message_t *request);
+
+/**
+ * Build default Answer for request.
+ * 
+ * @param tid          id of transaction to answer.
+ * @param status       Status code to use.
+ * @param answer       The sip answer to build.
+ */
+  int eXosip_call_build_answer(int tid, int status, osip_message_t **answer);
+
+/**
+ * Send Answer for invite.
+ * 
+ * @param tid          id of transaction to answer.
+ * @param status       response status if answer is NULL. (not allowed for 2XX)
+ * @param answer       The sip answer to send.
+ */
+  int eXosip_call_send_answer(int tid, int status, osip_message_t *answer);
+
+/**
+ * Terminate a call.
+ * send CANCEL, BYE or 603 Decline.
+ * 
+ * @param cid          call id of call.
+ * @param did          dialog id of call.
+ */
+  int eXosip_call_terminate(int cid, int did);
+
+/**
+ * Build a PRACK for invite.
+ * 
+ * @param tid          id of the invite transaction.
+ * @param prack        The sip prack to build.
+ */
+  int eXosip_call_build_prack(int tid, osip_message_t **prack);
+
+/**
+ * Send a PRACK for invite.
+ * 
+ * @param tid          id of the invite transaction.
+ * @param prack        The sip prack to send.
+ */
+  int eXosip_call_send_prack(int tid, osip_message_t *prack);
+
+/**
+ * Send a NOTIFY containing the information about a call transfer.
+ * 
+ * THIS METHOD WILL BE REPLACED or REMOVED, please use the
+ * new API to build NOTIFY.
+ * 
+ * @param did                  dialog id of call.
+ * @param subscription_status  the subscription status.
+ * @param body                 the body to attach to NOTIFY.
+ */
+  int eXosip_transfer_send_notify(int did, int subscription_status, char *body);
+
+/** @} */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/eXosip2/eX_message.h b/include/eXosip2/eX_message.h
new file mode 100644
index 0000000000..13f4a61ea4
--- /dev/null
+++ b/include/eXosip2/eX_message.h
@@ -0,0 +1,108 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002,2003,2004,2005  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+#ifndef __EX_MESSAGE_H__
+#define __EX_MESSAGE_H__
+
+#include <osipparser2/osip_parser.h>
+#include <time.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * @file eX_message.h
+ * @brief eXosip message request API
+ *
+ * This file provide the API needed to control MESSAGE requests. You can
+ * use it to:
+ *
+ * <ul>
+ * <li>build MESSAGE requests.</li>
+ * <li>send MESSAGE requests.</li>
+ * <li>build MESSAGE answers.</li>
+ * <li>send MESSAGE answers.</li>
+ * </ul>
+ */
+
+/**
+ * @defgroup eXosip2_message eXosip2 MESSAGE and messaging services outside of dialog
+ * @ingroup eXosip2_msg
+ * @{
+ */
+
+/**
+ * Build a default MESSAGE message.
+ * 
+ * This method will be updated to send any message outside of dialog
+ * In this later case, you'll specify the method to use in the second
+ * argument.
+ *
+ * By now, use this method only for the "MESSAGE" request.
+ *
+ * @param message   Pointer for the SIP request to build.
+ * @param method    request method. ("MESSAGE")
+ * @param to        SIP url for callee.
+ * @param from      SIP url for caller.
+ * @param route     Route header for INVITE. (optionnal)
+ */
+  int eXosip_message_build_request(osip_message_t **message, const char *method,
+				   const char *to, const char *from,
+				   const char *route);
+
+/**
+ * Send an MESSAGE request.
+ * 
+ * @param message          SIP MESSAGE message to send.
+ */
+  int eXosip_message_send_request(osip_message_t *message);
+
+/**
+ * Build answer for an MESSAGE request.
+ * 
+ * @param tid             id of MESSAGE transaction.
+ * @param status          status for SIP answer to build.
+ * @param answer          The SIP answer to build.
+ */
+  int eXosip_message_build_answer(int tid, int status, osip_message_t **answer);
+
+/**
+ * Send answer for an MESSAGE request.
+ * 
+ * @param tid             id of MESSAGE transaction.
+ * @param status          status for SIP answer to send.
+ * @param answer          The SIP answer to send. (default will be sent if NULL)
+ */
+  int eXosip_message_send_answer(int tid, int status, osip_message_t *answer);
+
+/** @} */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/eXosip2/eX_options.h b/include/eXosip2/eX_options.h
new file mode 100644
index 0000000000..a8325e9633
--- /dev/null
+++ b/include/eXosip2/eX_options.h
@@ -0,0 +1,100 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002,2003,2004,2005  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+#ifndef __EX_OPTIONS_H__
+#define __EX_OPTIONS_H__
+
+#include <osipparser2/osip_parser.h>
+#include <time.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * @file eX_options.h
+ * @brief eXosip options request API
+ *
+ * This file provide the API needed to control OPTIONS requests. You can
+ * use it to:
+ *
+ * <ul>
+ * <li>build OPTIONS requests.</li>
+ * <li>send OPTIONS requests.</li>
+ * <li>build OPTIONS answers.</li>
+ * <li>send OPTIONS answers.</li>
+ * </ul>
+ */
+
+/**
+ * @defgroup eXosip2_options eXosip2 OPTIONS and UA capabilities Management
+ * @ingroup eXosip2_msg
+ * @{
+ */
+
+/**
+ * Build a default OPTIONS message.
+ * 
+ * @param options   Pointer for the SIP request to build.
+ * @param to        SIP url for callee.
+ * @param from      SIP url for caller.
+ * @param route     Route header for INVITE. (optionnal)
+ */
+  int eXosip_options_build_request(osip_message_t **options, const char *to,
+				   const char *from, const char *route);
+
+/**
+ * Send an OPTIONS request.
+ * 
+ * @param options          SIP OPTIONS message to send.
+ */
+  int eXosip_options_send_request(osip_message_t *options);
+
+/**
+ * Build answer for an OPTIONS request.
+ * 
+ * @param tid             id of OPTIONS transaction.
+ * @param status          status for SIP answer to build.
+ * @param answer          The SIP answer to build.
+ */
+  int eXosip_options_build_answer(int tid, int status, osip_message_t **answer);
+
+/**
+ * Send answer for an OPTIONS request.
+ * 
+ * @param tid             id of OPTIONS transaction.
+ * @param status          status for SIP answer to send.
+ * @param answer          The SIP answer to send. (default will be sent if NULL)
+ */
+  int eXosip_options_send_answer(int tid, int status, osip_message_t *answer);
+
+/** @} */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/eXosip2/eX_publish.h b/include/eXosip2/eX_publish.h
new file mode 100644
index 0000000000..ebc9ccead1
--- /dev/null
+++ b/include/eXosip2/eX_publish.h
@@ -0,0 +1,92 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002,2003,2004,2005  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+#ifndef __EX_PUBLISH_H__
+#define __EX_PUBLISH_H__
+
+#include <osipparser2/osip_parser.h>
+#include <time.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * @file eX_publish.h
+ * @brief eXosip publish request API
+ *
+ * This file provide the API needed to control PUBLISH requests. You can
+ * use it to:
+ *
+ * <ul>
+ * <li>build PUBLISH requests.</li>
+ * <li>send PUBLISH requests.</li>
+ * </ul>
+ */
+
+/**
+ * @defgroup eXosip2_publish eXosip2 Publication Management
+ * @ingroup eXosip2_msg
+ * @{
+ */
+
+/**
+ * build publication for a user. (PUBLISH request)
+ * 
+ * @param message   returned published request.
+ * @param to        SIP url for callee.
+ * @param from      SIP url for caller.
+ * @param route     Route used for publication.
+ * @param event     SIP Event header.
+ * @param expires   SIP Expires header.
+ * @param ctype     Content-Type of body.
+ * @param body     body for publication.
+ */
+int eXosip_build_publish(osip_message_t **message,
+			 const char *to,
+			 const char *from,
+			 const char *route,
+			 const char *event,
+			 const char *expires,
+			 const char *ctype,
+			 const char *body);
+
+/**
+ * Send an Publication Message (PUBLISH request).
+ * 
+ * @param message is a ready to be sent publish message .
+ * @param sip_if_match is the SIP-If-Match header. (NULL for initial publication)
+ */
+int eXosip_publish (osip_message_t *message, const char *sip_if_match);
+
+
+/** @} */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/eXosip2/eX_refer.h b/include/eXosip2/eX_refer.h
new file mode 100644
index 0000000000..3c46cf41ef
--- /dev/null
+++ b/include/eXosip2/eX_refer.h
@@ -0,0 +1,84 @@
+
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002,2003,2004,2005  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+#ifndef __EX_REFER_H__
+#define __EX_REFER_H__
+
+#include <osipparser2/osip_parser.h>
+#include <time.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * @file eX_refer.h
+ * @brief eXosip transfer outside of calls API
+ *
+ * This file provide the API needed to request a blind transfer
+ * outside of any call.
+ *
+ * <ul>
+ * <li>build initial refer.</li>
+ * <li>send initial refer.</li>
+ * </ul>
+ *
+ */
+
+/**
+ * @defgroup eXosip2_refer eXosip2 REFER and blind tranfer Management outside of calls
+ * @ingroup eXosip2_msg
+ * @{
+ */
+
+/**
+ * Build a default REFER message for a blind transfer outside of any calls.
+ * 
+ * @param refer     Pointer for the SIP element to hold.
+ * @param refer_to  SIP url for transfer.
+ * @param from      SIP url for caller.
+ * @param to        SIP url for callee.
+ * @param route     Route header for REFER. (optionnal)
+ */
+int eXosip_refer_build_request(osip_message_t **refer, const char *refer_to,
+			       const char *from, const char *to,
+			       const char *route);
+
+/**
+ * Initiate a blind tranfer outside of any call.
+ * 
+ * @param refer     SIP REFER message to send.
+ */
+int eXosip_refer_send_request(osip_message_t *refer);
+
+/** @} */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/eXosip2/eX_register.h b/include/eXosip2/eX_register.h
new file mode 100644
index 0000000000..e0919219a1
--- /dev/null
+++ b/include/eXosip2/eX_register.h
@@ -0,0 +1,96 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002,2003,2004,2005  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+#ifndef __EX_REGISTER_H__
+#define __EX_REGISTER_H__
+
+#include <osipparser2/osip_parser.h>
+#include <time.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+/**
+ * @file eX_register.h
+ * @brief eXosip registration API
+ *
+ * This file provide the API needed to control registrations. You can
+ * use it to:
+ *
+ * <ul>
+ * <li>build initial REGISTER.</li>
+ * <li>build REGISTER.</li>
+ * <li>send REGISTER.</li>
+ * </ul>
+ */
+
+/**
+ * @defgroup eXosip2_registration eXosip2 REGISTER and Registration Management
+ * @ingroup eXosip2_msg
+ * @{
+ */
+
+  struct eXosip_reg_t;
+
+/**
+ * Build initial REGISTER request.
+ * 
+ * @param from      SIP url for caller.
+ * @param proxy     Proxy used for registration.
+ * @param contact   Contact address. (optional)
+ * @param expires   The expires value for registration.
+ * @param reg       The SIP request to build.
+ */
+  int eXosip_register_build_initial_register(const char *from, const char *proxy,
+					     const char *contact, int expires,
+					     osip_message_t **reg);
+
+/**
+ * Build a new REGISTER request for an existing registration.
+ * 
+ * @param rid       A unique identifier for the registration context
+ * @param expires   The expires value for registration.
+ * @param reg       The SIP request to build.
+ */
+  int eXosip_register_build_register(int rid, int expires, osip_message_t **reg);
+
+/**
+ * Send a REGISTER request for an existing registration.
+ * 
+ * @param rid       A unique identifier for the registration context
+ * @param reg       The SIP request to build. (NULL for default REGISTER)
+ */
+  int eXosip_register_send_register(int rid, osip_message_t *reg);
+
+/** @} */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/eXosip2/eX_setup.h b/include/eXosip2/eX_setup.h
new file mode 100644
index 0000000000..d6681cc552
--- /dev/null
+++ b/include/eXosip2/eX_setup.h
@@ -0,0 +1,258 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002,2003,2004,2005  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+#ifndef __EX_SETUP_H__
+#define __EX_SETUP_H__
+
+#include <osipparser2/osip_parser.h>
+#include <time.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * @file eX_setup.h
+ * @brief eXosip setup API
+ *
+ * This file provide the API needed to setup and configure
+ * the SIP endpoint.
+ *
+ */
+
+/**
+ * @defgroup eXosip2_conf eXosip2 configuration API
+ * @ingroup eXosip2_setup
+ * @{
+ */
+
+/**
+ * Initiate the eXtented oSIP library.
+ * 
+ */
+  int eXosip_init(void);
+
+/**
+ * Release ressource used by the eXtented oSIP library.
+ * 
+ */
+  void eXosip_quit(void);
+
+typedef enum {
+    EXOSIP_OPT_UDP_KEEP_ALIVE = 1,
+    EXOSIP_OPT_UDP_LEARN_PORT = 2,
+    EXOSIP_OPT_SET_HTTP_TUNNEL_PORT = 3,
+    EXOSIP_OPT_SET_HTTP_TUNNEL_PROXY = 4,
+    EXOSIP_OPT_SET_HTTP_OUTBOUND_PROXY = 5 /* used for http tunnel ONLY */
+} eXosip_option;
+
+/**
+ * Set eXosip options.
+ * See eXosip_option for available options.
+ *
+ * @param opt     option to configure.
+ * @param value   value for options.
+ * 
+ */
+int eXosip_set_option(eXosip_option opt, void *value);
+
+/**
+ * Lock the eXtented oSIP library.
+ * 
+ */
+  int eXosip_lock(void);
+
+/**
+ * UnLock the eXtented oSIP library.
+ * 
+ */
+  int eXosip_unlock(void);
+
+/**
+ * Listen on a specified socket.
+ * 
+ * @param transport IPPROTO_UDP for udp. (soon to come: TCP/TLS?)
+ * @param addr      the address to bind (NULL for all interface)
+ * @param port      the listening port. (0 for random port)
+ * @param family    the IP family (AF_INET or AF_INET6).
+ * @param secure    0 for UDP or TCP, 1 for TLS (with TCP).
+ */
+  int eXosip_listen_addr(int transport, const char *addr, int port, int family,
+			 int secure);
+
+/**
+ * Listen on a specified socket.
+ * 
+ * @param transport IPPROTO_UDP for udp. (soon to come: TCP/TLS?)
+ * @param socket socket to use for listening to UDP sip messages.
+ * @param port the listening port for masquerading.
+ */
+  int eXosip_set_socket(int transport, int socket, int port);
+
+/**
+ * Set the SIP User-Agent: header string.
+ *
+ * @param user_agent the User-Agent header to insert in messages.
+ */
+  void eXosip_set_user_agent(const char *user_agent);
+
+/**
+ * Use IPv6 instead of IPv4.
+ * 
+ * @param ipv6_enable  This paramter should be set to 1 to enable IPv6 mode.
+ */
+  void eXosip_enable_ipv6(int ipv6_enable);
+
+/**
+ * This method is used to replace contact address with
+ * the public address of your NAT. The ip address should
+ * be retreived manually (fixed IP address) or with STUN.
+ * This address will only be used when the remote
+ * correspondant appears to be on an DIFFERENT LAN.
+ *
+ * @param public_address 	the ip address.
+ * 
+ * If set to NULL, then the local ip address will be guessed 
+ * automatically (returns to default mode).
+ */
+  void eXosip_masquerade_contact(const char *public_address, int port);
+
+#ifndef DOXYGEN
+
+/**
+ * Force eXosip to use a specific ip address in all
+ * contact and Via headers in SIP message.
+ * **PLEASE DO NOT USE: use eXosip_masquerade_contact instead**
+ *
+ * @param localip 	the ip address.
+ *
+ * If set to NULL, then the local ip address will be guessed 
+ * automatically (returns to default mode).
+ *
+ * ******LINPHONE specific methods******
+ *
+ */
+int eXosip_force_masquerade_contact(const char *localip);
+
+/**
+ * Wake Up the eXosip_event_wait method.
+ * 
+ */
+  void __eXosip_wakeup_event(void);
+
+#define REMOVE_ELEMENT(first_element, element)   \
+       if (element->parent==NULL)                \
+	{ first_element = element->next;         \
+          if (first_element!=NULL)               \
+          first_element->parent = NULL; }        \
+       else \
+        { element->parent->next = element->next; \
+          if (element->next!=NULL)               \
+	element->next->parent = element->parent; \
+	element->next = NULL;                    \
+	element->parent = NULL; }
+
+#define ADD_ELEMENT(first_element, element) \
+   if (first_element==NULL)                 \
+    {                                       \
+      first_element   = element;            \
+      element->next   = NULL;               \
+      element->parent = NULL;               \
+    }                                       \
+  else                                      \
+    {                                       \
+      element->next   = first_element;      \
+      element->parent = NULL;               \
+      element->next->parent = element;      \
+      first_element = element;              \
+    }
+
+#define APPEND_ELEMENT(type_of_element_t, first_element, element) \
+  if (first_element==NULL)                            \
+    { first_element = element;                        \
+      element->next   = NULL; /* useless */           \
+      element->parent = NULL; /* useless */ }         \
+  else                                                \
+    { type_of_element_t *f;                           \
+      for (f=first_element; f->next!=NULL; f=f->next) \
+         { }                                          \
+      f->next    = element;                           \
+      element->parent = f;                            \
+      element->next   = NULL;                         \
+    }
+
+#endif
+
+/** @} */
+
+
+/**
+ * @defgroup eXosip2_network eXosip2 network API
+ * @ingroup eXosip2_setup
+ * @{
+ */
+
+/**
+ * Modify the transport protocol used to send SIP message.
+ * 
+ * @param msg         The SIP message to modify
+ * @param transport   transport protocol to use ("UDP", "TCP" or "TLS")
+ */
+  int eXosip_transport_set(osip_message_t *msg, const char *transport);
+
+/**
+ * Find the current localip (interface with default route).
+ * 
+ * @param family    AF_INET or AF_INET6
+ * @param address   a string containing the local IP address.
+ * @param size      The size of the string
+ */
+  int eXosip_guess_localip(int family, char *address, int size);
+
+#ifndef DOXYGEN
+
+/**
+ * Find the interface to be used to reach the specified host.
+ * 
+ * @param ip    a string containing the local IP address.
+ * @param localip	the local ip address to be used to reach host.
+ *
+ * You usually don't need this function at all.
+ *
+ * ******LINPHONE specific methods******
+ *
+ */
+int eXosip_get_localip_for(const char *host, char *localip, int size);
+
+#endif
+
+/** @} */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/eXosip2/eX_subscribe.h b/include/eXosip2/eX_subscribe.h
new file mode 100644
index 0000000000..55a581a0cb
--- /dev/null
+++ b/include/eXosip2/eX_subscribe.h
@@ -0,0 +1,189 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002,2003,2004,2005  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+#ifndef __EX_SUBSCRIBE_H__
+#define __EX_SUBSCRIBE_H__
+
+#include <osipparser2/osip_parser.h>
+#include <time.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * @file eX_subscribe.h
+ * @brief eXosip subscribe request API
+ *
+ * This file provide the API needed to control SUBSCRIBE requests. You can
+ * use it to:
+ *
+ * <ul>
+ * <li>build SUBSCRIBE requests.</li>
+ * <li>send SUBSCRIBE requests.</li>
+ * <li>build SUBSCRIBE answers.</li>
+ * <li>send SUBSCRIBE answers.</li>
+ * </ul>
+ */
+
+/**
+ * @defgroup eXosip2_subscribe eXosip2 SUBSCRIBE and outgoing subscriptions
+ * @ingroup eXosip2_msg
+ * @{
+ */
+
+typedef enum eXosip_ss {
+  EXOSIP_SUBCRSTATE_UNKNOWN,      /**< unknown subscription-state */
+  EXOSIP_SUBCRSTATE_PENDING,      /**< pending subscription-state */
+  EXOSIP_SUBCRSTATE_ACTIVE,       /**< active subscription-state */
+  EXOSIP_SUBCRSTATE_TERMINATED    /**< terminated subscription-state */
+} eXosip_ss_t;
+
+typedef enum eXosip_ss_reason {
+  DEACTIVATED,                   /**< deactivated for subscription-state */
+  PROBATION,                     /**< probation for subscription-state */
+  REJECTED,                      /**< rejected for subscription-state */
+  TIMEOUT,                       /**< timeout for subscription-state */
+  GIVEUP,                        /**< giveup for subscription-state */
+  NORESOURCE                     /**< noresource for subscription-state */
+} eXosip_ss_reason_t;
+
+
+typedef enum eXosip_ss_status {
+  EXOSIP_NOTIFY_UNKNOWN,     /**< unknown state for subscription */
+  EXOSIP_NOTIFY_PENDING,     /**< subscription not yet accepted */
+  EXOSIP_NOTIFY_ONLINE,      /**< online status */
+  EXOSIP_NOTIFY_BUSY,        /**< busy status */
+  EXOSIP_NOTIFY_BERIGHTBACK, /**< be right back status */
+  EXOSIP_NOTIFY_AWAY,        /**< away status */
+  EXOSIP_NOTIFY_ONTHEPHONE,  /**< on the phone status */
+  EXOSIP_NOTIFY_OUTTOLUNCH,  /**< out to lunch status */
+  EXOSIP_NOTIFY_CLOSED       /**< closed status */
+} eXosip_ss_status_t;
+
+/**
+ * Build a default initial SUBSCRIBE request.
+ * 
+ * @param subscribe Pointer for the SIP request to build.
+ * @param to        SIP url for callee.
+ * @param from      SIP url for caller.
+ * @param route     Route header for SUBSCRIBE. (optionnal)
+ * @param event     Event header for SUBSCRIBE.
+ * @param expires   Expires header for SUBSCRIBE.
+ */
+  int eXosip_subscribe_build_initial_request(osip_message_t **subscribe,
+					     const char *to, const char *from,
+					     const char *route, const char *event,
+					     int expires);
+
+/**
+ * Send an initial SUBSCRIBE request.
+ * 
+ * @param subscribe          SIP SUBSCRIBE message to send.
+ */
+  int eXosip_subscribe_send_initial_request(osip_message_t *subscribe);
+
+/**
+ * Build a default new SUBSCRIBE message.
+ * 
+ * @param did      identifier of the subscription.
+ * @param sub      Pointer for the SIP request to build.
+ */
+  int eXosip_subscribe_build_refresh_request(int did, osip_message_t **sub);
+
+/**
+ * Send a new SUBSCRIBE request.
+ * 
+ * @param did          identifier of the subscription.
+ * @param sub          SIP SUBSCRIBE message to send.
+ */
+  int eXosip_subscribe_send_refresh_request(int did, osip_message_t *sub);
+
+/** @} */
+
+/**
+ * @defgroup eXosip2_notify eXosip2 SUBSCRIBE and incoming subscriptions
+ * @ingroup eXosip2_msg
+ * @{
+ */
+
+/**
+ * Build answer for an SUBSCRIBE request.
+ * 
+ * @param tid             id of SUBSCRIBE transaction.
+ * @param status          status for SIP answer to build.
+ * @param answer          The SIP answer to build.
+ */
+  int eXosip_insubscription_build_answer(int tid, int status,
+					 osip_message_t **answer);
+
+/**
+ * Send answer for an SUBSCRIBE request.
+ * 
+ * @param tid             id of SUBSCRIBE transaction.
+ * @param status          status for SIP answer to send.
+ * @param answer          The SIP answer to send. (default will be sent if NULL)
+ */
+  int eXosip_insubscription_send_answer(int tid, int status,
+					osip_message_t *answer);
+
+/**
+ * Build a request within subscription.
+ * 
+ * @param did             id of incoming subscription.
+ * @param method          request method to build.
+ * @param request         The SIP request to build.
+ */
+  int eXosip_insubscription_build_request(int did, const char *method,
+					  osip_message_t **request);
+
+/**
+ * Build a NOTIFY request within subscription.
+ * 
+ * @param did                  id of incoming subscription.
+ * @param subscription_status  subscription status (pending, active, terminated)
+ * @param subscription_reason  subscription reason
+ * @param request              The SIP request to build.
+ */
+  int eXosip_insubscription_build_notify(int did, int subscription_status,
+					 int subscription_reason,
+					 osip_message_t **request);
+
+/**
+ * Send a request within subscription.
+ * 
+ * @param did             id of incoming subscription.
+ * @param request         The SIP request to send.
+ */
+  int eXosip_insubscription_send_request(int did, osip_message_t *request);
+					  
+/** @} */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/eXosip2/eXosip.h b/include/eXosip2/eXosip.h
new file mode 100644
index 0000000000..a66cbeda23
--- /dev/null
+++ b/include/eXosip2/eXosip.h
@@ -0,0 +1,301 @@
+/*
+  eXosip - This is the eXtended osip library.
+  Copyright (C) 2002,2003,2004,2005  Aymeric MOIZARD  - jack@atosc.org
+  
+  eXosip is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  
+  eXosip is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifdef ENABLE_MPATROL
+#include <mpatrol.h>
+#endif
+
+#ifndef __EXOSIP_H__
+#define __EXOSIP_H__
+
+#include <eXosip2/eX_setup.h>
+#include <eXosip2/eX_register.h>
+#include <eXosip2/eX_call.h>
+#include <eXosip2/eX_options.h>
+#include <eXosip2/eX_subscribe.h>
+#include <eXosip2/eX_refer.h>
+#include <eXosip2/eX_message.h>
+#include <eXosip2/eX_publish.h>
+
+#include <osipparser2/osip_parser.h>
+#include <osipparser2/sdp_message.h>
+#include <time.h>
+
+/**
+ * @file eXosip.h
+ * @brief eXosip API
+ *
+ * eXosip is a high layer library for rfc3261: the SIP protocol.
+ * It offers a simple API to make it easy to use. eXosip2 offers
+ * great flexibility for implementing SIP endpoint like:
+ * <ul>
+ * <li>SIP User-Agents</li>
+ * <li>SIP Voicemail or IVR</li>
+ * <li>SIP B2BUA</li>
+ * <li>any SIP server acting as an endpoint (music server...)</li>
+ * </ul>
+ *
+ * If you need to implement proxy or complex SIP applications,
+ * you should consider using osip instead.
+ *
+ * Here are the eXosip capabilities:
+ * <pre>
+ *    REGISTER                 to handle registration.
+ *    INVITE/BYE               to start/stop VoIP sessions.
+ *    INFO                     to send DTMF within a VoIP sessions.
+ *    OPTIONS                  to simulate VoIP sessions.
+ *    re-INVITE                to modify VoIP sessions
+ *    REFER/NOTIFY             to transfer calls.
+ *    MESSAGE                  to send Instant Message.
+ *    SUBSCRIBE/NOTIFY         to handle presence capabilities.
+ * </pre>
+ * <P>
+ */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+/**
+ * @defgroup eXosip2_authentication eXosip2 authentication API
+ * @ingroup eXosip2_msg
+ * @{
+ */
+
+/**
+ * Add authentication credentials. These are used when an outgoing
+ * request comes back with an authorization required response.
+ *
+ * @param username	username
+ * @param userid	login (usually equals the username)
+ * @param passwd	password
+ * @param ha1		currently ignored
+ * @param realm		realm within which credentials apply, or NULL
+ *			to apply credentials to unrecognized realms
+ */
+  int eXosip_add_authentication_info(const char *username, const char *userid,
+				     const char *passwd, const char *ha1,
+				     const char *realm);
+  
+/**
+ * Clear all authentication credentials stored in eXosip.
+ *
+ */
+  int eXosip_clear_authentication_info(void);
+
+/**
+ * Initiate some automatic actions:
+ *
+ *  Retry with credentials upon reception of 401/407.
+ *  Refresh REGISTER and SUBSCRIBE before the expiration delay.
+ *  Retry with Contact header upon reception of 3xx request.
+ * 
+ */
+  void eXosip_automatic_action(void);
+
+/** @} */
+  
+
+/**
+ * @defgroup eXosip2_sdp eXosip2 SDP helper API.
+ * @ingroup eXosip2_msg
+ * @{
+ */
+
+/**
+ * Get remote SDP body for the latest INVITE of call.
+ * 
+ * @param did          dialog id of call.
+ */
+  sdp_message_t *eXosip_get_remote_sdp(int did);
+
+/**
+ * Get local SDP body for the latest INVITE of call.
+ * 
+ * @param did          dialog id of call.
+ */
+  sdp_message_t *eXosip_get_local_sdp(int did);
+
+/**
+ * Get local SDP body for the given message.
+ * 
+ * @param message      message containing the SDP.
+ */
+  sdp_message_t *eXosip_get_sdp_info(osip_message_t *message);
+
+/**
+ * Get audio connection information for call.
+ * 
+ * @param sdp     sdp information.
+ */
+  sdp_connection_t *eXosip_get_audio_connection(sdp_message_t *sdp);
+
+/**
+ * Get audio media information for call.
+ * 
+ * @param sdp     sdp information.
+ */
+  sdp_media_t *eXosip_get_audio_media(sdp_message_t *sdp);
+
+/** @} */
+
+/**
+ * @defgroup eXosip2_event eXosip2 event API
+ * @ingroup eXosip2_setup
+ * @{
+ */
+
+/**
+ * Structure for event type description
+ * @var eXosip_event_type
+ */
+  typedef enum eXosip_event_type
+    {
+      /* REGISTER related events */
+      EXOSIP_REGISTRATION_NEW,         /**< announce new registration.       */
+      EXOSIP_REGISTRATION_SUCCESS,     /**< user is successfully registred.  */
+      EXOSIP_REGISTRATION_FAILURE,     /**< user is not registred.           */
+      EXOSIP_REGISTRATION_REFRESHED,   /**< registration has been refreshed. */
+      EXOSIP_REGISTRATION_TERMINATED,  /**< UA is not registred any more.    */
+      
+      /* INVITE related events within calls */
+      EXOSIP_CALL_INVITE,          /**< announce a new call                   */
+      EXOSIP_CALL_REINVITE,        /**< announce a new INVITE within call     */
+
+      EXOSIP_CALL_NOANSWER,        /**< announce no answer within the timeout */
+      EXOSIP_CALL_PROCEEDING,      /**< announce processing by a remote app   */
+      EXOSIP_CALL_RINGING,         /**< announce ringback                     */
+      EXOSIP_CALL_ANSWERED,        /**< announce start of call                */
+      EXOSIP_CALL_REDIRECTED,      /**< announce a redirection                */
+      EXOSIP_CALL_REQUESTFAILURE,  /**< announce a request failure            */
+      EXOSIP_CALL_SERVERFAILURE,   /**< announce a server failure             */
+      EXOSIP_CALL_GLOBALFAILURE,   /**< announce a global failure             */
+      EXOSIP_CALL_ACK,             /**< ACK received for 200ok to INVITE      */
+      
+      EXOSIP_CALL_CANCELLED,       /**< announce that call has been cancelled */
+      EXOSIP_CALL_TIMEOUT,         /**< announce that call has failed         */
+
+      /* request related events within calls (except INVITE) */
+      EXOSIP_CALL_MESSAGE_NEW,            /**< announce new incoming MESSAGE. */
+      EXOSIP_CALL_MESSAGE_PROCEEDING,     /**< announce a 1xx for MESSAGE. */
+      EXOSIP_CALL_MESSAGE_ANSWERED,       /**< announce a 200ok  */
+      EXOSIP_CALL_MESSAGE_REDIRECTED,     /**< announce a failure. */
+      EXOSIP_CALL_MESSAGE_REQUESTFAILURE, /**< announce a failure. */
+      EXOSIP_CALL_MESSAGE_SERVERFAILURE,  /**< announce a failure. */
+      EXOSIP_CALL_MESSAGE_GLOBALFAILURE,  /**< announce a failure. */
+
+      EXOSIP_CALL_CLOSED,          /**< a BYE was received for this call      */
+
+      /* for both UAS & UAC events */
+      EXOSIP_CALL_RELEASED,           /**< call context is cleared.            */
+      
+      /* response received for request outside calls */
+      EXOSIP_MESSAGE_NEW,            /**< announce new incoming MESSAGE. */
+      EXOSIP_MESSAGE_PROCEEDING,     /**< announce a 1xx for MESSAGE. */
+      EXOSIP_MESSAGE_ANSWERED,       /**< announce a 200ok  */
+      EXOSIP_MESSAGE_REDIRECTED,     /**< announce a failure. */
+      EXOSIP_MESSAGE_REQUESTFAILURE, /**< announce a failure. */
+      EXOSIP_MESSAGE_SERVERFAILURE,  /**< announce a failure. */
+      EXOSIP_MESSAGE_GLOBALFAILURE,  /**< announce a failure. */
+      
+      /* Presence and Instant Messaging */
+      EXOSIP_SUBSCRIPTION_UPDATE,       /**< announce incoming SUBSCRIBE.      */
+      EXOSIP_SUBSCRIPTION_CLOSED,       /**< announce end of subscription.     */
+      
+      EXOSIP_SUBSCRIPTION_NOANSWER,        /**< announce no answer              */
+      EXOSIP_SUBSCRIPTION_PROCEEDING,      /**< announce a 1xx                  */
+      EXOSIP_SUBSCRIPTION_ANSWERED,        /**< announce a 200ok                */
+      EXOSIP_SUBSCRIPTION_REDIRECTED,      /**< announce a redirection          */
+      EXOSIP_SUBSCRIPTION_REQUESTFAILURE,  /**< announce a request failure      */
+      EXOSIP_SUBSCRIPTION_SERVERFAILURE,   /**< announce a server failure       */
+      EXOSIP_SUBSCRIPTION_GLOBALFAILURE,   /**< announce a global failure       */
+      EXOSIP_SUBSCRIPTION_NOTIFY,          /**< announce new NOTIFY request     */
+      
+      EXOSIP_SUBSCRIPTION_RELEASED,        /**< call context is cleared.        */
+      
+      EXOSIP_IN_SUBSCRIPTION_NEW,          /**< announce new incoming SUBSCRIBE.*/
+      EXOSIP_IN_SUBSCRIPTION_RELEASED,     /**< announce end of subscription.   */
+      
+      EXOSIP_EVENT_COUNT                /**< MAX number of events              */
+    } eXosip_event_type_t;
+
+/**
+ * Structure for event description.
+ * @var eXosip_event_t
+ */
+  typedef struct eXosip_event eXosip_event_t;
+
+/**
+ * Structure for event description
+ * @struct eXosip_event
+ */
+  struct eXosip_event
+  {
+    eXosip_event_type_t type;               /**< type of the event */
+    char                textinfo[256];      /**< text description of event */ 
+    void               *external_reference; /**< external reference (for calls) */
+    
+    osip_message_t     *request;   /**< request within current transaction */
+    osip_message_t     *response;  /**< last response within current transaction */
+    osip_message_t     *ack;       /**< ack within current transaction */
+    
+    int tid; /**< unique id for transactions (to be used for answers) */
+    int did; /**< unique id for SIP dialogs */
+    
+    int rid; /**< unique id for registration */
+    int cid; /**< unique id for SIP calls (but multiple dialogs!) */
+    int sid; /**< unique id for outgoing subscriptions */
+    int nid; /**< unique id for incoming subscriptions */
+    
+    int ss_status;  /**< current Subscription-State for subscription */
+    int ss_reason;  /**< current Reason status for subscription */    
+  };
+  
+/**
+ * Free ressource in an eXosip event.
+ * 
+ * @param je    event to work on.
+ */
+void eXosip_event_free(eXosip_event_t *je);
+
+/**
+ * Wait for an eXosip event.
+ * 
+ * @param tv_s      timeout value (seconds).
+ * @param tv_ms     timeout value (mseconds).
+ */
+eXosip_event_t *eXosip_event_wait(int tv_s, int tv_ms);
+
+
+/**
+ * Wait for next eXosip event.
+ * 
+ */
+eXosip_event_t *eXosip_event_get(void);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ltmain.sh b/ltmain.sh
index 1a224ac2ae..9be0eb1c38 100644
--- a/ltmain.sh
+++ b/ltmain.sh
@@ -1,7 +1,7 @@
 # ltmain.sh - Provide generalized library-building support services.
 # NOTE: Changing this file will not affect anything until you rerun configure.
 #
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005
 # Free Software Foundation, Inc.
 # Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
 #
@@ -17,7 +17,7 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 #
 # As a special exception to the GNU General Public License, if you
 # distribute this file as part of a program that contains a
@@ -43,9 +43,14 @@ EXIT_FAILURE=1
 
 PROGRAM=ltmain.sh
 PACKAGE=libtool
-VERSION=1.5.6
-TIMESTAMP=" (1.1220.2.95 2004/04/11 05:50:42) Debian$Rev: 224 $"
+VERSION=1.5.16
+TIMESTAMP=" (1.1220.2.235 2005/04/25 18:13:26)"
 
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes.
+if test -n "${ZSH_VERSION+set}" ; then
+  setopt NO_GLOB_SUBST
+fi
 
 # Check that we have a working $echo.
 if test "X$1" = X--no-reexec; then
@@ -107,8 +112,9 @@ if test "${LANG+set}" = set; then
 fi
 
 # Make sure IFS has a sensible default
-: ${IFS=" 	
-"}
+lt_nl='
+'
+IFS=" 	$lt_nl"
 
 if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
   $echo "$modename: not configured to build any kind of library" 1>&2
@@ -127,6 +133,7 @@ show_help=
 execute_dlfiles=
 lo2o="s/\\.lo\$/.${objext}/"
 o2lo="s/\\.${objext}\$/.lo/"
+quote_scanset='[[~#^*{};<>?'"'"' 	]'
 
 #####################################
 # Shell function definitions:
@@ -138,7 +145,8 @@ o2lo="s/\\.${objext}\$/.lo/"
 # Need a lot of goo to handle *both* DLLs and import libs
 # Has to be a shell function in order to 'eat' the argument
 # that is supplied when $file_magic_command is called.
-func_win32_libid () {
+func_win32_libid ()
+{
   win32_libid_type="unknown"
   win32_fileres=`file -L $1 2>/dev/null`
   case $win32_fileres in
@@ -178,12 +186,13 @@ func_win32_libid () {
 # Only attempt this if the compiler in the base compile
 # command doesn't match the default compiler.
 # arg is usually of the form 'gcc ...'
-func_infer_tag () {
+func_infer_tag ()
+{
     if test -n "$available_tags" && test -z "$tagname"; then
       CC_quoted=
       for arg in $CC; do
 	case $arg in
-	  *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	  *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
 	  arg="\"$arg\""
 	  ;;
 	esac
@@ -204,7 +213,7 @@ func_infer_tag () {
 	    for arg in $CC; do
 	    # Double-quote args containing other shell metacharacters.
 	    case $arg in
-	      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	      *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
 	      arg="\"$arg\""
 	      ;;
 	    esac
@@ -235,6 +244,108 @@ func_infer_tag () {
       esac
     fi
 }
+
+
+# func_extract_an_archive dir oldlib
+func_extract_an_archive ()
+{
+    f_ex_an_ar_dir="$1"; shift
+    f_ex_an_ar_oldlib="$1"
+
+    $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)"
+    $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $?
+    if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
+     :
+    else
+      $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2
+      exit $EXIT_FAILURE
+    fi
+}
+
+# func_extract_archives gentop oldlib ...
+func_extract_archives ()
+{
+    my_gentop="$1"; shift
+    my_oldlibs=${1+"$@"}
+    my_oldobjs=""
+    my_xlib=""
+    my_xabs=""
+    my_xdir=""
+    my_status=""
+
+    $show "${rm}r $my_gentop"
+    $run ${rm}r "$my_gentop"
+    $show "$mkdir $my_gentop"
+    $run $mkdir "$my_gentop"
+    my_status=$?
+    if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then
+      exit $my_status
+    fi
+
+    for my_xlib in $my_oldlibs; do
+      # Extract the objects.
+      case $my_xlib in
+	[\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
+	*) my_xabs=`pwd`"/$my_xlib" ;;
+      esac
+      my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'`
+      my_xdir="$my_gentop/$my_xlib"
+
+      $show "${rm}r $my_xdir"
+      $run ${rm}r "$my_xdir"
+      $show "$mkdir $my_xdir"
+      $run $mkdir "$my_xdir"
+      status=$?
+      if test "$status" -ne 0 && test ! -d "$my_xdir"; then
+	exit $status
+      fi
+      case $host in
+      *-darwin*)
+	$show "Extracting $my_xabs"
+	# Do not bother doing anything if just a dry run
+	if test -z "$run"; then
+	  darwin_orig_dir=`pwd`
+	  cd $my_xdir || exit $?
+	  darwin_archive=$my_xabs
+	  darwin_curdir=`pwd`
+	  darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'`
+	  darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null`
+	  if test -n "$darwin_arches"; then 
+	    darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'`
+	    darwin_arch=
+	    $show "$darwin_base_archive has multiple architectures $darwin_arches"
+	    for darwin_arch in  $darwin_arches ; do
+	      mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+	      lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
+	      cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+	      func_extract_an_archive "`pwd`" "${darwin_base_archive}"
+	      cd "$darwin_curdir"
+	      $rm "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}"
+	    done # $darwin_arches
+      ## Okay now we have a bunch of thin objects, gotta fatten them up :)
+	    darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP`
+	    darwin_file=
+	    darwin_files=
+	    for darwin_file in $darwin_filelist; do
+	      darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP`
+	      lipo -create -output "$darwin_file" $darwin_files
+	    done # $darwin_filelist
+	    ${rm}r unfat-$$
+	    cd "$darwin_orig_dir"
+	  else
+	    cd "$darwin_orig_dir"
+ 	    func_extract_an_archive "$my_xdir" "$my_xabs"
+	  fi # $darwin_arches
+	fi # $run
+      ;;
+      *)
+        func_extract_an_archive "$my_xdir" "$my_xabs"
+        ;;
+      esac
+      my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
+    done
+    func_extract_archives_result="$my_oldobjs"
+}
 # End of Shell function definitions
 #####################################
 
@@ -305,10 +416,10 @@ do
   --version)
     $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
     $echo
-    $echo "Copyright (C) 2003  Free Software Foundation, Inc."
+    $echo "Copyright (C) 2005  Free Software Foundation, Inc."
     $echo "This is free software; see the source for copying conditions.  There is NO"
     $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
-    exit $EXIT_SUCCESS
+    exit $?
     ;;
 
   --config)
@@ -317,7 +428,7 @@ do
     for tagname in $taglist; do
       ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath"
     done
-    exit $EXIT_SUCCESS
+    exit $?
     ;;
 
   --debug)
@@ -342,7 +453,7 @@ do
     else
       $echo "disable static libraries"
     fi
-    exit $EXIT_SUCCESS
+    exit $?
     ;;
 
   --finish) mode="finish" ;;
@@ -399,7 +510,7 @@ if test -z "$show_help"; then
   # Infer the operation mode.
   if test -z "$mode"; then
     $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2
-    $echo "*** Future versions of Libtool will require -mode=MODE be specified." 1>&2
+    $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2
     case $nonopt in
     *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*)
       mode=link
@@ -516,7 +627,7 @@ if test -z "$show_help"; then
 	    # Many Bourne shells cannot handle close brackets correctly
 	    # in scan sets, so we specify it separately.
 	    case $arg in
-	      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	      *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
 	      arg="\"$arg\""
 	      ;;
 	    esac
@@ -547,8 +658,11 @@ if test -z "$show_help"; then
       case $lastarg in
       # Double-quote args containing other shell metacharacters.
       # Many Bourne shells cannot handle close brackets correctly
-      # in scan sets, so we specify it separately.
-      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+      # in scan sets, and some SunOS ksh mistreat backslash-escaping
+      # in scan sets (worked around with variable expansion),
+      # and furthermore cannot handle '|' '&' '(' ')' in scan sets 
+      # at all, so we specify them separately.
+      *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
 	lastarg="\"$lastarg\""
 	;;
       esac
@@ -621,6 +735,15 @@ if test -z "$show_help"; then
       esac
     done
 
+    qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"`
+    case $qlibobj in
+      *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+	qlibobj="\"$qlibobj\"" ;;
+    esac
+    if test "X$libobj" != "X$qlibobj"; then
+	$echo "$modename: libobj name \`$libobj' may not contain shell special characters."
+	exit $EXIT_FAILURE
+    fi
     objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
     xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
     if test "X$xdir" = "X$obj"; then
@@ -693,12 +816,17 @@ compiler."
 	$run $rm $removelist
 	exit $EXIT_FAILURE
       fi
-      $echo $srcfile > "$lockfile"
+      $echo "$srcfile" > "$lockfile"
     fi
 
     if test -n "$fix_srcfile_path"; then
       eval srcfile=\"$fix_srcfile_path\"
     fi
+    qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"`
+    case $qsrcfile in
+      *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
+      qsrcfile="\"$qsrcfile\"" ;;
+    esac
 
     $run $rm "$libobj" "${libobj}T"
 
@@ -720,10 +848,10 @@ EOF
       fbsd_hideous_sh_bug=$base_compile
 
       if test "$pic_mode" != no; then
-	command="$base_compile $srcfile $pic_flag"
+	command="$base_compile $qsrcfile $pic_flag"
       else
 	# Don't build PIC code
-	command="$base_compile $srcfile"
+	command="$base_compile $qsrcfile"
       fi
 
       if test ! -d "${xdir}$objdir"; then
@@ -803,9 +931,9 @@ EOF
     if test "$build_old_libs" = yes; then
       if test "$pic_mode" != yes; then
 	# Don't build PIC code
-	command="$base_compile $srcfile"
+	command="$base_compile $qsrcfile"
       else
-	command="$base_compile $srcfile $pic_flag"
+	command="$base_compile $qsrcfile $pic_flag"
       fi
       if test "$compiler_c_o" = yes; then
 	command="$command -o $obj"
@@ -983,7 +1111,7 @@ EOF
       arg="$1"
       shift
       case $arg in
-      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+      *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
 	qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test
 	;;
       *) qarg=$arg ;;
@@ -1227,6 +1355,11 @@ EOF
 	  prev=
 	  continue
 	  ;;
+        darwin_framework)
+	  compiler_flags="$compiler_flags $arg"
+	  prev=
+	  continue
+	  ;;
 	*)
 	  eval "$prev=\"\$arg\""
 	  prev=
@@ -1285,6 +1418,12 @@ EOF
 	continue
 	;;
 
+      -framework)
+        prev=darwin_framework
+        compiler_flags="$compiler_flags $arg"
+        continue
+        ;;
+
       -inst-prefix-dir)
 	prev=inst_prefix
 	continue
@@ -1345,7 +1484,7 @@ EOF
 	    # These systems don't actually have a C library (as such)
 	    test "X$arg" = "X-lc" && continue
 	    ;;
-	  *-*-openbsd* | *-*-freebsd*)
+	  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
 	    # Do not include libc due to us having libc/libc_r.
 	    test "X$arg" = "X-lc" && continue
 	    ;;
@@ -1356,7 +1495,7 @@ EOF
 	  esac
 	elif test "X$arg" = "X-lc_r"; then
 	 case $host in
-	 *-*-openbsd* | *-*-freebsd*)
+	 *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
 	   # Do not include libc_r directly, use -pthread flag.
 	   continue
 	   ;;
@@ -1366,8 +1505,20 @@ EOF
 	continue
 	;;
 
+      # Tru64 UNIX uses -model [arg] to determine the layout of C++
+      # classes, name mangling, and exception handling.
+      -model)
+	compile_command="$compile_command $arg"
+	compiler_flags="$compiler_flags $arg"
+	finalize_command="$finalize_command $arg"
+	prev=xcompiler
+	continue
+	;;
+
      -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe)
-	deplibs="$deplibs $arg"
+	compiler_flags="$compiler_flags $arg"
+	compile_command="$compile_command $arg"
+	finalize_command="$finalize_command $arg"
 	continue
 	;;
 
@@ -1376,18 +1527,19 @@ EOF
 	continue
 	;;
 
-      # gcc -m* arguments should be passed to the linker via $compiler_flags
-      # in order to pass architecture information to the linker
-      # (e.g. 32 vs 64-bit).  This may also be accomplished via -Wl,-mfoo
-      # but this is not reliable with gcc because gcc may use -mfoo to
-      # select a different linker, different libraries, etc, while
-      # -Wl,-mfoo simply passes -mfoo to the linker.
-      -m*)
+      # -64, -mips[0-9] enable 64-bit mode on the SGI compiler
+      # -r[0-9][0-9]* specifies the processor on the SGI compiler
+      # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler
+      # +DA*, +DD* enable 64-bit mode on the HP compiler
+      # -q* pass through compiler args for the IBM compiler
+      # -m* pass through architecture-specific compiler args for GCC
+      -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*)
+
 	# Unknown arguments in both finalize_command and compile_command need
 	# to be aesthetically quoted because they are evaled later.
 	arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
 	case $arg in
-	*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	*$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
 	  arg="\"$arg\""
 	  ;;
 	esac
@@ -1503,7 +1655,7 @@ EOF
 	for flag in $args; do
 	  IFS="$save_ifs"
 	  case $flag in
-	    *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	    *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
 	    flag="\"$flag\""
 	    ;;
 	  esac
@@ -1521,7 +1673,7 @@ EOF
 	for flag in $args; do
 	  IFS="$save_ifs"
 	  case $flag in
-	    *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	    *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
 	    flag="\"$flag\""
 	    ;;
 	  esac
@@ -1554,7 +1706,7 @@ EOF
 	# to be aesthetically quoted because they are evaled later.
 	arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
 	case $arg in
-	*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	*$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
 	  arg="\"$arg\""
 	  ;;
 	esac
@@ -1688,7 +1840,7 @@ EOF
 	# to be aesthetically quoted because they are evaled later.
 	arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
 	case $arg in
-	*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	*$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
 	  arg="\"$arg\""
 	  ;;
 	esac
@@ -1838,10 +1990,7 @@ EOF
 	case $pass in
 	dlopen) libs="$dlfiles" ;;
 	dlpreopen) libs="$dlprefiles" ;;
-	link)
-	  libs="$deplibs %DEPLIBS%"
-	  test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs"
-	  ;;
+	link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
 	esac
       fi
       if test "$pass" = dlopen; then
@@ -1858,7 +2007,7 @@ EOF
 	    compile_deplibs="$deplib $compile_deplibs"
 	    finalize_deplibs="$deplib $finalize_deplibs"
 	  else
-	    deplibs="$deplib $deplibs"
+	    compiler_flags="$compiler_flags $deplib"
 	  fi
 	  continue
 	  ;;
@@ -1977,7 +2126,22 @@ EOF
 	  fi
 	  case $linkmode in
 	  lib)
-	    if test "$deplibs_check_method" != pass_all; then
+	    valid_a_lib=no
+	    case $deplibs_check_method in
+	      match_pattern*)
+		set dummy $deplibs_check_method
+	        match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+		if eval $echo \"$deplib\" 2>/dev/null \
+		    | $SED 10q \
+		    | $EGREP "$match_pattern_regex" > /dev/null; then
+		  valid_a_lib=yes
+		fi
+		;;
+	      pass_all)
+		valid_a_lib=yes
+		;;
+            esac
+	    if test "$valid_a_lib" != yes; then
 	      $echo
 	      $echo "*** Warning: Trying to link with static lib archive $deplib."
 	      $echo "*** I have the capability to make that library automatically link in when"
@@ -2051,6 +2215,8 @@ EOF
 	# it will not redefine variables installed, or shouldnotlink
 	installed=yes
 	shouldnotlink=no
+	avoidtemprpath=
+
 
 	# Read the .la file
 	case $lib in
@@ -2149,11 +2315,19 @@ EOF
 	    dir="$libdir"
 	    absdir="$libdir"
 	  fi
+	  test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
 	else
-	  dir="$ladir/$objdir"
-	  absdir="$abs_ladir/$objdir"
-	  # Remove this search path later
-	  notinst_path="$notinst_path $abs_ladir"
+	  if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+	    dir="$ladir"
+	    absdir="$abs_ladir"
+	    # Remove this search path later
+	    notinst_path="$notinst_path $abs_ladir"
+	  else
+	    dir="$ladir/$objdir"
+	    absdir="$abs_ladir/$objdir"
+	    # Remove this search path later
+	    notinst_path="$notinst_path $abs_ladir"
+	  fi
 	fi # $installed = yes
 	name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
 
@@ -2226,7 +2400,7 @@ EOF
 	  if test -n "$library_names" &&
 	     { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
 	    # We need to hardcode the library path
-	    if test -n "$shlibpath_var"; then
+	    if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then
 	      # Make sure the rpath contains only unique directories.
 	      case "$temp_rpath " in
 	      *" $dir "*) ;;
@@ -2670,12 +2844,12 @@ EOF
 	      *) continue ;;
 	      esac
 	      case " $deplibs " in
-	      *" $depdepl "*) ;;
-	      *) deplibs="$depdepl $deplibs" ;;
+	      *" $path "*) ;;
+	      *) deplibs="$path $deplibs" ;;
 	      esac
 	      case " $deplibs " in
-	      *" $path "*) ;;
-	      *) deplibs="$deplibs $path" ;;
+	      *" $depdepl "*) ;;
+	      *) deplibs="$depdepl $deplibs" ;;
 	      esac
 	    done
 	  fi # link_all_deplibs != no
@@ -2929,11 +3103,6 @@ EOF
 	    age="$number_minor"
 	    revision="$number_minor"
 	    ;;
-	  *)
-	    $echo "$modename: unknown library version type \`$version_type'" 1>&2
-	    $echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
-	    exit $EXIT_FAILURE
-	    ;;
 	  esac
 	  ;;
 	no)
@@ -2947,7 +3116,7 @@ EOF
 	case $current in
 	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
 	*)
-	  $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2
+	  $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2
 	  $echo "$modename: \`$vinfo' is not valid version information" 1>&2
 	  exit $EXIT_FAILURE
 	  ;;
@@ -2956,7 +3125,7 @@ EOF
 	case $revision in
 	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
 	*)
-	  $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2
+	  $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2
 	  $echo "$modename: \`$vinfo' is not valid version information" 1>&2
 	  exit $EXIT_FAILURE
 	  ;;
@@ -2965,7 +3134,7 @@ EOF
 	case $age in
 	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
 	*)
-	  $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2
+	  $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2
 	  $echo "$modename: \`$vinfo' is not valid version information" 1>&2
 	  exit $EXIT_FAILURE
 	  ;;
@@ -2991,7 +3160,7 @@ EOF
 	  versuffix="$major.$age.$revision"
 	  # Darwin ld doesn't like 0 for these options...
 	  minor_current=`expr $current + 1`
-	  verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+	  verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
 	  ;;
 
 	freebsd-aout)
@@ -3197,7 +3366,7 @@ EOF
 	  *-*-netbsd*)
 	    # Don't link with libc until the a.out ld.so is fixed.
 	    ;;
-	  *-*-openbsd* | *-*-freebsd*)
+	  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
 	    # Do not include libc due to us having libc/libc_r.
 	    test "X$arg" = "X-lc" && continue
 	    ;;
@@ -3679,67 +3848,13 @@ EOF
 	    eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
 	  else
 	    gentop="$output_objdir/${outputname}x"
-	    $show "${rm}r $gentop"
-	    $run ${rm}r "$gentop"
-	    $show "$mkdir $gentop"
-	    $run $mkdir "$gentop"
-	    status=$?
-	    if test "$status" -ne 0 && test ! -d "$gentop"; then
-	      exit $status
-	    fi
 	    generated="$generated $gentop"
 
-	    for xlib in $convenience; do
-	      # Extract the objects.
-	      case $xlib in
-	      [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
-	      *) xabs=`pwd`"/$xlib" ;;
-	      esac
-	      xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
-	      xdir="$gentop/$xlib"
-
-	      $show "${rm}r $xdir"
-	      $run ${rm}r "$xdir"
-	      $show "$mkdir $xdir"
-	      $run $mkdir "$xdir"
-	      status=$?
-	      if test "$status" -ne 0 && test ! -d "$xdir"; then
-		exit $status
-	      fi
-	      # We will extract separately just the conflicting names and we will no
-	      # longer touch any unique names. It is faster to leave these extract
-	      # automatically by $AR in one run.
-	      $show "(cd $xdir && $AR x $xabs)"
-	      $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
-	      if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then
-		:
-	      else
-		$echo "$modename: warning: object name conflicts; renaming object files" 1>&2
-		$echo "$modename: warning: to ensure that they will not overwrite" 1>&2
-		$AR t "$xabs" | sort | uniq -cd | while read -r count name
-		do
-		  i=1
-		  while test "$i" -le "$count"
-		  do
-		   # Put our $i before any first dot (extension)
-		   # Never overwrite any file
-		   name_to="$name"
-		   while test "X$name_to" = "X$name" || test -f "$xdir/$name_to"
-		   do
-		     name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"`
-		   done
-		   $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')"
-		   $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $?
-		   i=`expr $i + 1`
-		  done
-		done
-	      fi
-
-	      libobjs="$libobjs "`find $xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
-	    done
+	    func_extract_archives $gentop $convenience
+	    libobjs="$libobjs $func_extract_archives_result"
 	  fi
 	fi
-
+	
 	if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
 	  eval flag=\"$thread_safe_flag_spec\"
 	  linker_flags="$linker_flags $flag"
@@ -3788,6 +3903,7 @@ EOF
 	    save_libobjs=$libobjs
 	  fi
 	  save_output=$output
+	  output_la=`$echo "X$output" | $Xsed -e "$basename"`
 
 	  # Clear the reloadable object creation command queue and
 	  # initialize k to one.
@@ -3797,7 +3913,7 @@ EOF
 	  delfiles=
 	  last_robj=
 	  k=1
-	  output=$output_objdir/$save_output-${k}.$objext
+	  output=$output_objdir/$output_la-${k}.$objext
 	  # Loop over the list of objects to be linked.
 	  for obj in $save_libobjs
 	  do
@@ -3817,9 +3933,9 @@ EOF
 		# the last one created.
 		eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\"
 	      fi
-	      last_robj=$output_objdir/$save_output-${k}.$objext
+	      last_robj=$output_objdir/$output_la-${k}.$objext
 	      k=`expr $k + 1`
-	      output=$output_objdir/$save_output-${k}.$objext
+	      output=$output_objdir/$output_la-${k}.$objext
 	      objlist=$obj
 	      len=1
 	    fi
@@ -3839,13 +3955,13 @@ EOF
 	    eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\"
           fi
 
-	  # Set up a command to remove the reloadale object files
+	  # Set up a command to remove the reloadable object files
 	  # after they are used.
 	  i=0
 	  while test "$i" -lt "$k"
 	  do
 	    i=`expr $i + 1`
-	    delfiles="$delfiles $output_objdir/$save_output-${i}.$objext"
+	    delfiles="$delfiles $output_objdir/$output_la-${i}.$objext"
 	  done
 
 	  $echo "creating a temporary reloadable object file: $output"
@@ -3977,64 +4093,10 @@ EOF
 	  eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\"
 	else
 	  gentop="$output_objdir/${obj}x"
-	  $show "${rm}r $gentop"
-	  $run ${rm}r "$gentop"
-	  $show "$mkdir $gentop"
-	  $run $mkdir "$gentop"
-	  status=$?
-	  if test "$status" -ne 0 && test ! -d "$gentop"; then
-	    exit $status
-	  fi
 	  generated="$generated $gentop"
 
-	  for xlib in $convenience; do
-	    # Extract the objects.
-	    case $xlib in
-	    [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
-	    *) xabs=`pwd`"/$xlib" ;;
-	    esac
-	    xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
-	    xdir="$gentop/$xlib"
-
-	    $show "${rm}r $xdir"
-	    $run ${rm}r "$xdir"
-	    $show "$mkdir $xdir"
-	    $run $mkdir "$xdir"
-	    status=$?
-	    if test "$status" -ne 0 && test ! -d "$xdir"; then
-	      exit $status
-	    fi
-	    # We will extract separately just the conflicting names and we will no
-	    # longer touch any unique names. It is faster to leave these extract
-	    # automatically by $AR in one run.
-	    $show "(cd $xdir && $AR x $xabs)"
-	    $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
-	    if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then
-	      :
-	    else
-	      $echo "$modename: warning: object name conflicts; renaming object files" 1>&2
-	      $echo "$modename: warning: to ensure that they will not overwrite" 1>&2
-	      $AR t "$xabs" | sort | uniq -cd | while read -r count name
-	      do
-		i=1
-		while test "$i" -le "$count"
-		do
-		 # Put our $i before any first dot (extension)
-		 # Never overwrite any file
-		 name_to="$name"
-		 while test "X$name_to" = "X$name" || test -f "$xdir/$name_to"
-		 do
-		   name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"`
-		 done
-		 $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')"
-		 $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $?
-		 i=`expr $i + 1`
-		done
-	      done
-	    fi
-
-	    reload_conv_objs="$reload_objs "`find $xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
-	  done
+	  func_extract_archives $gentop $convenience
+	  reload_conv_objs="$reload_objs $func_extract_archives_result"
 	fi
       fi
 
@@ -4296,12 +4358,12 @@ extern \"C\" {
 
 	    # Prepare the list of exported symbols
 	    if test -z "$export_symbols"; then
-	      export_symbols="$output_objdir/$output.exp"
+	      export_symbols="$output_objdir/$outputname.exp"
 	      $run $rm $export_symbols
 	      $run eval "${SED} -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
 	    else
-	      $run eval "${SED} -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"'
-	      $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T'
+	      $run eval "${SED} -e 's/\([ ][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
+	      $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
 	      $run eval 'mv "$nlist"T "$nlist"'
 	    fi
 	  fi
@@ -4353,7 +4415,26 @@ extern \"C\" {
 #endif
 
 /* The mapping between symbol names and symbols. */
+"
+
+	    case $host in
+	    *cygwin* | *mingw* )
+	  $echo >> "$output_objdir/$dlsyms" "\
+/* DATA imports from DLLs on WIN32 can't be const, because
+   runtime relocations are performed -- see ld's documentation
+   on pseudo-relocs */
+struct {
+"
+	      ;;
+	    * )
+	  $echo >> "$output_objdir/$dlsyms" "\
 const struct {
+"
+	      ;;
+	    esac
+
+
+	  $echo >> "$output_objdir/$dlsyms" "\
   const char *name;
   lt_ptr address;
 }
@@ -4582,7 +4663,7 @@ static const void *lt_preloaded_setup() {
 	esac
 	case $host in
 	  *cygwin* | *mingw* )
-	    cwrappersource=`$echo ${objdir}/lt-${output}.c`
+	    cwrappersource=`$echo ${objdir}/lt-${outputname}.c`
 	    cwrapper=`$echo ${output}.exe`
 	    $rm $cwrappersource $cwrapper
 	    trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
@@ -4815,7 +4896,7 @@ sed_quote_subst='$sed_quote_subst'
 
 # The HP-UX ksh and POSIX shell print the target directory to stdout
 # if CDPATH is set.
-if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
 
 relink_command=\"$relink_command\"
 
@@ -4992,71 +5073,73 @@ fi\
 
       if test -n "$addlibs"; then
 	gentop="$output_objdir/${outputname}x"
-	$show "${rm}r $gentop"
-	$run ${rm}r "$gentop"
-	$show "$mkdir $gentop"
-	$run $mkdir "$gentop"
-	status=$?
-	if test "$status" -ne 0 && test ! -d "$gentop"; then
-	  exit $status
-	fi
 	generated="$generated $gentop"
 
-	# Add in members from convenience archives.
-	for xlib in $addlibs; do
-	  # Extract the objects.
-	  case $xlib in
-	  [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
-	  *) xabs=`pwd`"/$xlib" ;;
-	  esac
-	  xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
-	  xdir="$gentop/$xlib"
-
-	  $show "${rm}r $xdir"
-	  $run ${rm}r "$xdir"
-	  $show "$mkdir $xdir"
-	  $run $mkdir "$xdir"
-	  status=$?
-	  if test "$status" -ne 0 && test ! -d "$xdir"; then
-	    exit $status
-	  fi
-	  # We will extract separately just the conflicting names and we will no
-	  # longer touch any unique names. It is faster to leave these extract
-	  # automatically by $AR in one run.
-	  $show "(cd $xdir && $AR x $xabs)"
-	  $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
-	  if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then
-	    :
-	  else
-	    $echo "$modename: warning: object name conflicts; renaming object files" 1>&2
-	    $echo "$modename: warning: to ensure that they will not overwrite" 1>&2
-	    $AR t "$xabs" | sort | uniq -cd | while read -r count name
-	    do
-	      i=1
-	      while test "$i" -le "$count"
-	      do
-	       # Put our $i before any first dot (extension)
-	       # Never overwrite any file
-	       name_to="$name"
-	       while test "X$name_to" = "X$name" || test -f "$xdir/$name_to"
-	       do
-		 name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"`
-	       done
-	       $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')"
-	       $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $?
-	       i=`expr $i + 1`
-	      done
-	    done
-	  fi
-
-	  oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP`
-	done
+	func_extract_archives $gentop $addlibs
+	oldobjs="$oldobjs $func_extract_archives_result"
       fi
 
       # Do each command in the archive commands.
       if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
        cmds=$old_archive_from_new_cmds
       else
+	# POSIX demands no paths to be encoded in archives.  We have
+	# to avoid creating archives with duplicate basenames if we
+	# might have to extract them afterwards, e.g., when creating a
+	# static archive out of a convenience library, or when linking
+	# the entirety of a libtool archive into another (currently
+	# not supported by libtool).
+	if (for obj in $oldobjs
+	    do
+	      $echo "X$obj" | $Xsed -e 's%^.*/%%'
+	    done | sort | sort -uc >/dev/null 2>&1); then
+	  :
+	else
+	  $echo "copying selected object files to avoid basename conflicts..."
+
+	  if test -z "$gentop"; then
+	    gentop="$output_objdir/${outputname}x"
+	    generated="$generated $gentop"
+
+	    $show "${rm}r $gentop"
+	    $run ${rm}r "$gentop"
+	    $show "$mkdir $gentop"
+	    $run $mkdir "$gentop"
+	    status=$?
+	    if test "$status" -ne 0 && test ! -d "$gentop"; then
+	      exit $status
+	    fi
+	  fi
+
+	  save_oldobjs=$oldobjs
+	  oldobjs=
+	  counter=1
+	  for obj in $save_oldobjs
+	  do
+	    objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+	    case " $oldobjs " in
+	    " ") oldobjs=$obj ;;
+	    *[\ /]"$objbase "*)
+	      while :; do
+		# Make sure we don't pick an alternate name that also
+		# overlaps.
+		newobj=lt$counter-$objbase
+		counter=`expr $counter + 1`
+		case " $oldobjs " in
+		*[\ /]"$newobj "*) ;;
+		*) if test ! -f "$gentop/$newobj"; then break; fi ;;
+		esac
+	      done
+	      $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
+	      $run ln "$obj" "$gentop/$newobj" ||
+	      $run cp "$obj" "$gentop/$newobj"
+	      oldobjs="$oldobjs $gentop/$newobj"
+	      ;;
+	    *) oldobjs="$oldobjs $obj" ;;
+	    esac
+	  done
+	fi
+
 	eval cmds=\"$old_archive_cmds\"
 
 	if len=`expr "X$cmds" : ".*"` &&
@@ -5070,20 +5153,7 @@ fi\
 	  objlist=
 	  concat_cmds=
 	  save_oldobjs=$oldobjs
-	  # GNU ar 2.10+ was changed to match POSIX; thus no paths are
-	  # encoded into archives.  This makes 'ar r' malfunction in
-	  # this piecewise linking case whenever conflicting object
-	  # names appear in distinct ar calls; check, warn and compensate.
-	    if (for obj in $save_oldobjs
-	    do
-	      $echo "X$obj" | $Xsed -e 's%^.*/%%'
-	    done | sort | sort -uc >/dev/null 2>&1); then
-	    :
-	  else
-	    $echo "$modename: warning: object name conflicts; overriding AR_FLAGS to 'cq'" 1>&2
-	    $echo "$modename: warning: to ensure that POSIX-compatible ar will work" 1>&2
-	    AR_FLAGS=cq
-	  fi
+
 	  # Is there a better way of finding the last object in the list?
 	  for obj in $save_oldobjs
 	  do
@@ -5295,7 +5365,7 @@ relink_command=\"$relink_command\""
       # Aesthetically quote it.
       arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
       case $arg in
-      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*)
+      *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
 	arg="\"$arg\""
 	;;
       esac
@@ -5311,7 +5381,7 @@ relink_command=\"$relink_command\""
     # Aesthetically quote it.
     arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
     case $arg in
-    *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*)
+    *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
       arg="\"$arg\""
       ;;
     esac
@@ -5359,7 +5429,7 @@ relink_command=\"$relink_command\""
       # Aesthetically quote the argument.
       arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
       case $arg in
-      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*)
+      *$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
 	arg="\"$arg\""
 	;;
       esac
@@ -6398,7 +6468,7 @@ esac
 $echo
 $echo "Try \`$modename --help' for more information about other modes."
 
-exit $EXIT_SUCCESS
+exit $?
 
 # The TAGs below are defined such that we never get into a situation
 # in which we disable both kinds of libraries.  Given conflicting
diff --git a/m4/Makefile.am b/m4/Makefile.am
new file mode 100644
index 0000000000..278ccdd862
--- /dev/null
+++ b/m4/Makefile.am
@@ -0,0 +1 @@
+EXTRA_DIST=speex.m4 osip.m4 exosip.m4 ilbc.m4
diff --git a/m4/acx_pthread.m4 b/m4/acx_pthread.m4
new file mode 100644
index 0000000000..ffc4ef417d
--- /dev/null
+++ b/m4/acx_pthread.m4
@@ -0,0 +1,224 @@
+dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+dnl
+dnl This macro figures out how to build C programs using POSIX
+dnl threads.  It sets the PTHREAD_LIBS output variable to the threads
+dnl library and linker flags, and the PTHREAD_CFLAGS output variable
+dnl to any special C compiler flags that are needed.  (The user can also
+dnl force certain compiler flags/libs to be tested by setting these
+dnl environment variables.)
+dnl
+dnl Also sets PTHREAD_CC to any special C compiler that is needed for
+dnl multi-threaded programs (defaults to the value of CC otherwise).
+dnl (This is necessary on AIX to use the special cc_r compiler alias.)
+dnl
+dnl If you are only building threads programs, you may wish to
+dnl use these variables in your default LIBS, CFLAGS, and CC:
+dnl
+dnl        LIBS="$PTHREAD_LIBS $LIBS"
+dnl        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+dnl        CC="$PTHREAD_CC"
+dnl
+dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute
+dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE
+dnl to that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
+dnl
+dnl ACTION-IF-FOUND is a list of shell commands to run if a threads
+dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands
+dnl to run it if it is not found.  If ACTION-IF-FOUND is not specified,
+dnl the default action will define HAVE_PTHREAD.
+dnl
+dnl Please let the authors know if this macro fails on any platform,
+dnl or if you have any other suggestions or comments.  This macro was
+dnl based on work by SGJ on autoconf scripts for FFTW (www.fftw.org)
+dnl (with help from M. Frigo), as well as ac_pthread and hb_pthread
+dnl macros posted by AFC to the autoconf macro repository.  We are also
+dnl grateful for the helpful feedback of numerous users.
+dnl
+dnl @version $Id$
+dnl @author Steven G. Johnson <stevenj@alum.mit.edu> and Alejandro Forero Cuervo <bachue@bachue.com>
+
+AC_DEFUN([ACX_PTHREAD], [
+AC_REQUIRE([AC_CANONICAL_HOST])
+acx_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on True64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
+        save_CFLAGS="$CFLAGS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+        save_LIBS="$LIBS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
+        AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)
+        AC_MSG_RESULT($acx_pthread_ok)
+        if test x"$acx_pthread_ok" = xno; then
+                PTHREAD_LIBS=""
+                PTHREAD_CFLAGS=""
+        fi
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try.  Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all.
+
+acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt"
+
+# The ordering *is* (sometimes) important.  Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+#       other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
+# -pthreads: Solaris/gcc
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+#      doesn't hurt to check since this sometimes defines pthreads too;
+#      also defines -D_REENTRANT)
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+
+case "${host_cpu}-${host_os}" in
+        *solaris*)
+
+        # On Solaris (at least, for some versions), libc contains stubbed
+        # (non-functional) versions of the pthreads routines, so link-based
+        # tests will erroneously succeed.  (We need to link with -pthread or
+        # -lpthread.)  (The stubs are missing pthread_cleanup_push, or rather
+        # a function called by this macro, so we could check for that, but
+        # who knows whether they'll stub that too in a future libc.)  So,
+        # we'll just look for -pthreads and -lpthread first:
+
+        acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags"
+        ;;
+esac
+
+if test x"$acx_pthread_ok" = xno; then
+for flag in $acx_pthread_flags; do
+
+        case $flag in
+                none)
+                AC_MSG_CHECKING([whether pthreads work without any flags])
+                ;;
+
+                -*)
+                AC_MSG_CHECKING([whether pthreads work with $flag])
+                PTHREAD_CFLAGS="$flag"
+                ;;
+
+                *)
+                AC_MSG_CHECKING([for the pthreads library -l$flag])
+                PTHREAD_LIBS="-l$flag"
+                ;;
+        esac
+
+        save_LIBS="$LIBS"
+        save_CFLAGS="$CFLAGS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+        # Check for various functions.  We must include pthread.h,
+        # since some functions may be macros.  (On the Sequent, we
+        # need a special flag -Kthread to make this header compile.)
+        # We check for pthread_join because it is in -lpthread on IRIX
+        # while pthread_create is in libc.  We check for pthread_attr_init
+        # due to DEC craziness with -lpthreads.  We check for
+        # pthread_cleanup_push because it is one of the few pthread
+        # functions on Solaris that doesn't have a non-functional libc stub.
+        # We try pthread_create on general principles.
+        AC_TRY_LINK([#include <pthread.h>],
+                    [pthread_t th; pthread_join(th, 0);
+                     pthread_attr_init(0); pthread_cleanup_push(0, 0);
+                     pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+                    [acx_pthread_ok=yes])
+
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+
+        AC_MSG_RESULT($acx_pthread_ok)
+        if test "x$acx_pthread_ok" = xyes; then
+                break;
+        fi
+
+        PTHREAD_LIBS=""
+        PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$acx_pthread_ok" = xyes; then
+        save_LIBS="$LIBS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        save_CFLAGS="$CFLAGS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+        # Detect AIX lossage: threads are created detached by default
+        # and the JOINABLE attribute has a nonstandard name (UNDETACHED).
+        AC_MSG_CHECKING([for joinable pthread attribute])
+        AC_TRY_LINK([#include <pthread.h>],
+                    [int attr=PTHREAD_CREATE_JOINABLE;],
+                    ok=PTHREAD_CREATE_JOINABLE, ok=unknown)
+        if test x"$ok" = xunknown; then
+                AC_TRY_LINK([#include <pthread.h>],
+                            [int attr=PTHREAD_CREATE_UNDETACHED;],
+                            ok=PTHREAD_CREATE_UNDETACHED, ok=unknown)
+        fi
+        if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then
+                AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok,
+                          [Define to the necessary symbol if this constant
+                           uses a non-standard name on your system.])
+        fi
+        AC_MSG_RESULT(${ok})
+        if test x"$ok" = xunknown; then
+                AC_MSG_WARN([we do not know how to create joinable pthreads])
+        fi
+
+        AC_MSG_CHECKING([if more special flags are required for pthreads])
+        flag=no
+        case "${host_cpu}-${host_os}" in
+                *-aix* | *-freebsd*)     flag="-D_THREAD_SAFE";;
+                *solaris* | alpha*-osf*) flag="-D_REENTRANT";;
+        esac
+        AC_MSG_RESULT(${flag})
+        if test "x$flag" != xno; then
+                PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
+        fi
+
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+
+        # More AIX lossage: must compile with cc_r
+        AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC})
+else
+        PTHREAD_CC="$CC"
+fi
+
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(PTHREAD_CFLAGS)
+AC_SUBST(PTHREAD_CC)
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$acx_pthread_ok" = xyes; then
+        ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
+        :
+else
+        acx_pthread_ok=no
+        $2
+fi
+
+])dnl ACX_PTHREAD
diff --git a/m4/exosip.m4 b/m4/exosip.m4
new file mode 100644
index 0000000000..f5ebdded80
--- /dev/null
+++ b/m4/exosip.m4
@@ -0,0 +1,88 @@
+AC_DEFUN([LP_SETUP_EXOSIP],[
+AC_REQUIRE([AC_CANONICAL_HOST])
+AC_REQUIRE([LP_CHECK_OSIP2])
+
+dnl *********************************************************************
+dnl Source packaging numbers
+EXOSIP_MAJOR_VERSION=1
+EXOSIP_MINOR_VERSION=9
+EXOSIP_MICRO_VERSION=1
+
+SONAME_MAJOR_VERSION=5
+SONAME_MINOR_VERSION=0
+SONAME_MICRO_VERSION=0
+
+dnl program extension
+EXOSIP_VERSION=$EXOSIP_MAJOR_VERSION.$EXOSIP_MINOR_VERSION.$EXOSIP_MICRO_VERSION
+
+LIBEXOSIP_SO_VERSION=$SONAME_MAJOR_VERSION:$SONAME_MINOR_VERSION:$SONAME_MICRO_VERSION
+
+AC_SUBST(LIBEXOSIP_SO_VERSION, $LIBEXOSIP_SO_VERSION)
+AC_SUBST(EXOSIP_VERSION)
+
+dnl support for linux-thread or posix thread (pthread.h)
+AC_ARG_ENABLE(pthread,
+[  --enable-pthread        enable support for POSIX threads. (autodetect)],
+enable_pthread=$enableval,enable_pthread="no")
+
+dnl compile with mt support
+if test "x$enable_pthread" = "xyes"; then
+  EXOSIP_CFLAGS="-DHAVE_PTHREAD"
+  EXOSIP_LIBS="-lpthread"
+else
+  ACX_PTHREAD()
+fi
+
+dnl eXosip embeded stuff
+EXOSIP_CFLAGS="$OSIP_CFLAGS -DOSIP_MT -DENABLE_TRACE -DNEW_TIMER -DSM -DMSN_SUPPORT -DUSE_TMP_BUFFER"
+EXOSIP_LIBS="$OSIP_LIBS"
+AC_CHECK_HEADERS(semaphore.h)
+AC_CHECK_HEADERS(sys/sem.h)
+case $target in
+  linux*)
+     EXOSIP_CFLAGS="$EXOSIP_CFLAGS -pedantic"
+     ;;
+  irix*)
+     ;;
+  hpux* | hp-ux*)
+     ;;
+  aix*)
+     ;;
+  osf*)
+     AC_CHECK_LIB(rt,sem_open,[EXOSIP_LIBS="$EXOSIP_LIBS -lrt"])
+     ;;
+  sunos*)
+     ;;
+  darwin*)
+     EXOSIP_CFLAGS="$EXOSIP_CFLAGS -pedantic"
+     ;;
+  *)
+     ;;
+esac
+
+AC_CHECK_LIB(posix4,sem_open,[EXOSIP_LIBS="$EXOSIP_LIBS -lposix4 -mt"])
+AC_CHECK_LIB(nsl,nis_add,[EXOSIP_LIBS="$EXOSIP_LIBS -lnsl"])
+AC_CHECK_LIB(socket,sendto,[EXOSIP_LIBS="$EXOSIP_LIBS -lsocket"])
+AC_CHECK_LIB(rt,clock_gettime,[EXOSIP_LIBS="$EXOSIP_LIBS -lrt"])
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS(ctype.h)
+AC_CHECK_HEADERS(string.h)
+AC_CHECK_HEADERS(strings.h)
+AC_CHECK_HEADERS(stdio.h)
+AC_CHECK_HEADERS(stdlib.h)
+AC_CHECK_HEADERS(unistd.h)
+AC_CHECK_HEADERS(stdarg.h)
+AC_CHECK_HEADERS(varargs.h)
+AC_CHECK_HEADERS(sys/time.h)
+AC_CHECK_HEADERS(assert.h)
+AC_CHECK_HEADERS(signal.h)
+AC_CHECK_HEADERS(sys/signal.h)
+AC_CHECK_HEADERS(malloc.h)
+AC_CHECK_HEADERS(sys/select.h)
+AC_CHECK_HEADERS(sys/types.h)
+AC_CHECK_HEADERS(fcntl.h)
+
+AC_SUBST(EXOSIP_CFLAGS)
+AC_SUBST(EXOSIP_LIBS)
+])
diff --git a/m4/ilbc.m4 b/m4/ilbc.m4
new file mode 100644
index 0000000000..465f8506d7
--- /dev/null
+++ b/m4/ilbc.m4
@@ -0,0 +1,33 @@
+AC_DEFUN([LP_CHECK_ILBC],[
+
+AC_ARG_WITH( ilbc,
+      [  --with-ilbc      Set prefix where ilbc headers and libs can be found (ex:/usr, /usr/local, none to disable ilbc support) [default=/usr] ],
+      [ ilbc_prefix=${withval}],[ ilbc_prefix="/usr" ])
+
+if test "$ilbc_prefix" = "none" ; then
+	AC_MSG_NOTICE([iLBC codec support disabled. ])
+else
+	ILBC_CFLAGS=" -I${ilbc_prefix}/include/ilbc"
+	ILBC_LIBS="-L${ilbc_prefix}/lib -lilbc -lm"
+	CPPFLAGS_save=$CPPFLAGS
+	CPPFLAGS=$ILBC_CFLAGS
+	LDFLAGS_save=$LDFLAGS
+	LDFLAGS=$ILBC_LIBS
+	AC_CHECK_HEADERS(iLBC_decode.h,[AC_CHECK_LIB(ilbc,iLBC_decode,ilbc_found=yes,ilbc_found=no)
+	],ilbc_found=no)
+	
+	CPPFLAGS=$CPPFLAGS_save
+	LDFLAGS=$LDFLAGS_save
+	
+	if test "$ilbc_found" = "no" ; then
+		AC_MSG_WARN([Could not find ilbc headers or libs. Please install ilbc package from http://www.linphone.org if you want iLBC codec support in linphone.])
+		ILBC_CFLAGS=
+		ILBC_LIBS=
+	else
+		AC_DEFINE(HAVE_ILBC,1,[Defined when we have ilbc codec lib])
+		AC_SUBST(ILBC_CFLAGS)
+		AC_SUBST(ILBC_LIBS)
+	fi	
+fi
+
+])
diff --git a/m4/osip.m4 b/m4/osip.m4
new file mode 100644
index 0000000000..6812524d87
--- /dev/null
+++ b/m4/osip.m4
@@ -0,0 +1,32 @@
+AC_DEFUN([LP_CHECK_OSIP2],[
+
+AC_ARG_WITH( osip,
+      [  --with-osip      Set prefix where osip can be found (ex:/usr or /usr/local)[default=/usr/local] ],
+      [ osip_prefix=${withval}],[ osip_prefix=/usr ])
+AC_SUBST(osip_prefix)
+
+
+OSIP_CFLAGS="-I$osip_prefix/include"
+OSIP_LIBS="-L$osip_prefix/lib"
+
+dnl check osip2 headers
+CPPFLAGS_save=$CPPFLAGS
+CPPFLAGS=$OSIP_CFLAGS
+AC_CHECK_HEADER([osip2/osip.h], ,AC_MSG_ERROR([Could not find osip2 headers !]))
+CPPFLAGS=$CPPFLAGS_save
+
+dnl check for osip2 libs
+LDFLAGS_save=$LDFLAGS
+LDFLAGS=$OSIP_LIBS
+dnl AC_CHECK_LIB adds osipparser2 to LIBS, I don't want that !
+LIBS_save=$LIBS
+AC_CHECK_LIB(osipparser2,osip_message_init, , AC_MSG_ERROR([Could not find osip2 libraries !]))
+LDFLAGS=$LDFLAGS_save
+LIBS=$LIBS_save
+
+OSIP_LIBS="$OSIP_LIBS -losipparser2 -losip2"
+
+AC_SUBST(OSIP_CFLAGS)
+AC_SUBST(OSIP_LIBS)
+
+])
diff --git a/m4/speex.m4 b/m4/speex.m4
new file mode 100644
index 0000000000..884d5684b2
--- /dev/null
+++ b/m4/speex.m4
@@ -0,0 +1,24 @@
+AC_DEFUN([LP_CHECK_SPEEX],[
+dnl only accept speex>=1.1.6 or 1.0.5 (the versions that have speex_encode_int )
+AC_ARG_WITH( speex,
+      [  --with-speex      Set prefix where speex lib can be found (ex:/usr, /usr/local) [default=/usr] ],
+      [ speex_prefix=${withval}],[ speex_prefix="/usr" ])
+
+SPEEX_CFLAGS=" -I${speex_prefix}/include -I${speex_prefix}/include/speex"
+SPEEX_LIBS="-L${speex_prefix}/lib -lspeex -lm"
+CPPFLAGS_save=$CPPFLAGS
+CPPFLAGS=$SPEEX_CFLAGS
+LDFLAGS_save=$LDFLAGS
+LDFLAGS=$SPEEX_LIBS
+AC_CHECK_HEADERS(speex.h,[AC_CHECK_LIB(speex,speex_encode_int,speex_found=yes,speex_found=no)
+],speex_found=no)
+
+if test "$speex_found" = "no" ; then
+AC_MSG_ERROR([Could not find a libspeex version that have the speex_encode_int() function. Please install libspeex=1.0.5 or libspeex>=1.1.6])
+fi
+
+AC_SUBST(SPEEX_CFLAGS)
+AC_SUBST(SPEEX_LIBS)
+CPPFLAGS=$CPPFLAGS_save
+LDFLAGS=$LDFLAGS_save
+])
diff --git a/m4/video.m4 b/m4/video.m4
new file mode 100644
index 0000000000..534277de1a
--- /dev/null
+++ b/m4/video.m4
@@ -0,0 +1,85 @@
+AC_DEFUN([LP_CHECK_DEP],[
+	dnl $1=dependency description
+	dnl $2=dependency short name, will be suffixed with _CFLAGS and _LIBS
+	dnl $3=headers's place
+	dnl $4=lib's place
+	dnl $5=header to check
+	dnl $6=lib to check
+	dnl $7=function to check in library
+	
+	NAME=$2
+	dep_headersdir=$3
+	dep_libsdir=$4
+	dep_header=$5
+	dep_lib=$6
+	dep_funclib=$7
+	
+	eval ${NAME}_CFLAGS=\"-I $dep_headersdir \"
+	eval ${NAME}_LIBS=\"-L $dep_libsdir -l$dep_lib\"
+	
+	CPPFLAGS_save=$CPPFLAGS
+	LDFLAGS_save=$LDFLAGS
+	CPPFLAGS="-I $dep_headersdir "
+	LDFLAGS="-L $dep_libsdir "
+	
+	AC_CHECK_HEADERS([$dep_header],[AC_CHECK_LIB([$dep_lib],[$dep_funclib],found=yes,found=no)
+	],found=no)
+	
+	if test "$found" = "yes" ; then
+		eval ${NAME}_found=yes
+		AC_DEFINE([HAVE_${NAME}],1,[Defined when we have found $1])
+		AC_SUBST(${NAME}_CFLAGS)
+		AC_SUBST(${NAME}_LIBS)
+	else
+		eval ${NAME}_found=no
+		eval ${NAME}_CFLAGS=
+		eval ${NAME}_LIBS=
+	fi
+	CPPFLAGS=$CPPFLAGS_save
+	LDFLAGS=$LDFLAGS_save
+	
+])
+
+
+AC_DEFUN([LP_CHECK_VIDEO],[
+
+	dnl conditionnal build of video support
+	AC_ARG_ENABLE(video,
+		  [  --enable-video    Turn on video support compiling: not functionnal for the moment],
+		  [case "${enableval}" in
+			yes) video=true ;;
+			no)  video=false ;;
+			*) AC_MSG_ERROR(bad value ${enableval} for --enable-video) ;;
+		  esac],[video=false])
+		  
+	AC_ARG_WITH( ffmpeg,
+		  [  --with-ffmpeg		Sets the installation prefix of ffmpeg, needed for video support. [default=/usr] ],
+		  [ ffmpegdir=${withval}],[ ffmpegdir=/usr ])
+	
+	AC_ARG_WITH( sdl,
+		  [  --with-sdl		Sets the installation prefix of libSDL, needed for video support. [default=/usr] ],
+		  [ libsdldir=${withval}],[ libsdldir=/usr ])
+	
+	if test "$video" = "true"; then
+		
+		dnl test for ffmpeg presence
+		LP_CHECK_DEP([ffmpeg],[FFMPEG],[${ffmpegdir}/include/ffmpeg],[${ffmpegdir}/lib],[avcodec.h],[avcodec],[avcodec_init])
+		if test "$FFMPEG_found" = "no" ; then
+			AC_MSG_ERROR([Could not find ffmpeg headers and library. This is mandatory for video support])
+		fi
+		
+		LP_CHECK_DEP([SDL],[SDL],[${libsdldir}/include],[${libsdldir}/lib],[SDL/SDL.h],[SDL],[SDL_Init])
+		if test "$SDL_found" = "no" ; then
+			AC_MSG_ERROR([Could not find libsdl headers and library. This is mandatory for video support])
+		fi
+	
+		VIDEO_CFLAGS=" $FFMPEG_CFLAGS $SDL_CFLAGS"
+		VIDEO_LIBS=" $FFMPEG_LIBS $SDL_LIBS"
+		
+		AC_DEFINE(VIDEO_ENABLED,1,[Set when video support is enabled])
+		
+	fi
+	
+	AC_SUBST(VIDEO_CFLAGS)
+	AC_SUBST(VIDEO_LIBS)
+])
diff --git a/src/Makefile.am b/src/Makefile.am
index 9c497591a4..72a9609419 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -22,8 +22,8 @@ sflphoned_SOURCES = call.cpp 	eventthread.cpp 	main.cpp 	sipvoiplink.cpp 	voIPLi
 sflphoned_CXXFLAGS = -DPREFIX=\"$(prefix)\" -DPROGSHAREDIR=\"${datadir}/sflphone\" $(ZEROCONFFLAGS)
 
 #sflphoned_LDFLAGS = -static
-sflphoned_LDADD =  gui/libguiframework.la audio/libaudio.la ../stund/libstun.la ../utilspp/libutilspp.la -lpthread $(SFLPHONE_LIBS) $(ZEROCONFLIB) $(LIB_DNSSD) config/libconfig.la 
+sflphoned_LDADD =  gui/libguiframework.la audio/libaudio.la ../stund/libstun.la ../utilspp/libutilspp.la $(top_builddir)/exosip2/libeXosip2.la $(SFLPHONE_LIBS) $(ZEROCONFLIB) $(LIB_DNSSD) config/libconfig.la 
 #KDE_CXXFLAGS = $(USE_EXCEPTIONS)
-AM_CPPFLAGS = -I$(top_srcdir) -I$(srcdir)/audio/pacpp/include  $(libccext2_CFLAGS) $(libccgnu2_CFLAGS) $(portaudio_CFLAGS)
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(srcdir)/audio/pacpp/include  $(libccext2_CFLAGS) $(libccgnu2_CFLAGS) $(portaudio_CFLAGS)
 
 noinst_HEADERS = observer.h
diff --git a/src/audio/Makefile.am b/src/audio/Makefile.am
index 9306d347bf..f095b0b8e4 100644
--- a/src/audio/Makefile.am
+++ b/src/audio/Makefile.am
@@ -10,7 +10,7 @@ libaudio_la_SOURCES = alaw.cpp alaw.h 	audiocodec.cpp audiocodec.h \
 			tonegenerator.cpp tonegenerator.h 	ulaw.cpp ulaw.h tone.cpp tonelist.cpp audioloop.cpp \
 	audiofile.cpp
 
-AM_CXXFLAGS = -I$(top_srcdir) -I$(srcdir)/pacpp/include/ $(libccext2_CFLAGS) $(libccrtp1_CFLAGS) $(portaudio_CFLAGS)
+AM_CXXFLAGS = -I$(top_srcdir)/include -I$(srcdir)/pacpp/include/ $(libccext2_CFLAGS) $(libccrtp1_CFLAGS) $(portaudio_CFLAGS)
 libaudio_la_LIBADD = gsm/libgsm.la pacpp/source/portaudiocpp/libportaudiocpp.la
 
 noinst_HEADERS = tone.h tonelist.h audioloop.h audiofile.h
-- 
GitLab