[Pkg-voip-commits] [belle-sip] 02/08: New upstream version 1.6.3

Dr. Tobias Quathamer toddy at debian.org
Mon Nov 6 13:10:01 UTC 2017


This is an automated email from the git hooks/post-receive script.

toddy pushed a commit to branch master
in repository belle-sip.

commit 01693e932a5c4ffb5af6917d4a112aa95c5a0809
Author: Dr. Tobias Quathamer <toddy at debian.org>
Date:   Mon Nov 6 13:36:18 2017 +0100

    New upstream version 1.6.3
---
 CMakeLists.txt                                     |  50 +-
 NEWS                                               |   6 +
 README.md                                          |   9 +
 belle-sip.spec.in                                  |   2 +-
 build/CMakeLists.txt                               |  50 ++
 .../rpm/belle-sip.spec.cmake                       |  43 +-
 cmake/BelleSIPConfig.cmake.in                      |  45 +-
 cmake/FindAntlr3.cmake                             |   2 +-
 cmake/FindZlib.cmake                               |   4 +-
 configure.ac                                       |   4 +-
 include/belle-sip/auth-helper.h                    |   7 +
 include/belle-sip/belle-sip.h                      |   2 +-
 include/belle-sip/defs.h                           |  21 +-
 include/belle-sip/headers.h                        |  51 ++
 include/belle-sip/list.h                           |   1 +
 include/belle-sip/object.h                         |  10 +
 include/belle-sip/resolver.h                       |   4 +-
 include/belle-sip/sip-uri.h                        |  10 +
 include/belle-sip/types.h                          |   4 +-
 include/belle-sip/utils.h                          |   4 +
 src/CMakeLists.txt                                 |  14 +-
 src/auth_helper.c                                  |  23 +-
 src/belle_sip_headers_impl.c                       | 141 ++++++
 src/belle_sip_internal.h                           |  52 ++-
 src/belle_sip_resolver.c                           |  87 ++--
 src/belle_sip_uri_impl.c                           |   3 +
 src/belle_sip_utils.c                              | 193 +++-----
 src/bodyhandler.c                                  |   5 +-
 src/channel.c                                      |  83 +++-
 src/channel.h                                      |   9 +-
 src/dialog.c                                       |  88 ++--
 src/dns.c                                          |  78 +++-
 src/dns.h                                          |   5 +-
 src/grammars/belle_sip_message.g                   | 190 +++++++-
 src/http-provider.c                                |   6 +-
 src/ict.c                                          |  15 +-
 src/nist.c                                         |   6 +-
 src/parserutils.h                                  |  18 +-
 src/port.c                                         |   8 +-
 src/port.h                                         |  16 +-
 src/provider.c                                     |  47 +-
 src/refresher.c                                    |  14 +-
 src/transaction.c                                  |  40 +-
 src/transports/stream_channel.c                    |  18 +-
 src/transports/stream_channel.h                    |   4 +-
 src/transports/stream_listeningpoint.c             |  10 +-
 src/transports/tls_channel.c                       |   2 +-
 src/transports/udp_listeningpoint.c                |  13 +-
 tester/CMakeLists.txt                              |  11 +-
 tester/Makefile.am                                 |   3 +
 ...ip_uri_tester.c => belle_sip_base_uri_tester.c} |  10 +-
 tester/belle_sip_fast_uri_tester.c                 |  62 +++
 tester/belle_sip_headers_tester.c                  |  97 +++-
 tester/belle_sip_register_tester.c                 | 149 ++++--
 tester/belle_sip_resolver_tester.c                 |   4 +-
 tester/belle_sip_tester.c                          |  19 +-
 tester/belle_sip_tester.h                          |   2 +
 tester/belle_sip_tester_windows.cpp                |   5 +-
 tester/belle_sip_uri_tester.c                      | 511 +--------------------
 tester/get.c                                       |   6 +-
 tester/parse.c                                     |  10 +-
 61 files changed, 1402 insertions(+), 1004 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9136406..df6d6ba 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,4 +1,4 @@
-############################################################################
+
 # CMakeLists.txt
 # Copyright (C) 2014  Belledonne Communications, Grenoble France
 #
@@ -21,7 +21,7 @@
 ############################################################################
 
 cmake_minimum_required(VERSION 3.0)
-project(belle-sip VERSION 1.6.1 LANGUAGES C CXX)
+project(belle-sip VERSION 1.6.3 LANGUAGES C CXX)
 
 
 set(PACKAGE "${PROJECT_NAME}")
@@ -42,22 +42,6 @@ option(ENABLE_TUNNEL "Enable tunnel support" OFF)
 option(ENABLE_TESTS "Enable compilation of tests" ON)
 
 
-macro(apply_compile_flags SOURCE_FILES)
-	if(${SOURCE_FILES})
-		set(options "")
-		foreach(a ${ARGV})
-			if(STRICT_OPTIONS_${a})
-				string(REPLACE ";" " " options_${a} "${STRICT_OPTIONS_${a}}")
-				set(options "${options} ${options_${a}}")
-			endif()
-		endforeach()
-		if(options)
-			set_source_files_properties(${${SOURCE_FILES}} PROPERTIES COMPILE_FLAGS "${options}")
-		endif()
-	endif()
-endmacro()
-
-
 include(CheckLibraryExists)
 include(CheckSymbolExists)
 include(CheckCSourceCompiles)
@@ -194,7 +178,7 @@ else()
 	endif()
 	if(ENABLE_STRICT)
 		list(APPEND STRICT_OPTIONS_CPP "-Werror" "-Wextra" "-Wno-unused-parameter" "-Wno-error=unknown-pragmas" "-Wuninitialized" "-fno-strict-aliasing")
-		list(APPEND STRICT_OPTIONS_C "-Wdeclaration-after-statement" "-Wstrict-prototypes -Wno-missing-field-initializers")
+		list(APPEND STRICT_OPTIONS_C "-Wdeclaration-after-statement" "-Wstrict-prototypes -Wno-missing-field-initializers" "-Wno-error=unused-result")
 	endif()
 	# this warning is generated by antlr so ignore it for now
 	list(APPEND STRICT_OPTIONS_C "-Wno-strict-prototypes" "-Wno-error=sign-compare")
@@ -213,12 +197,17 @@ if(APPLE)
 	endif()
 endif()
 string(REPLACE ";" " " LINK_FLAGS_STR "${LINK_FLAGS}")
-if(WIN32)
-	add_definitions(
-		-DBELLESIP_EXPORTS
-		-DBELLESIP_INTERNAL_EXPORTS
-	)
+
+set(BELLESIP_CPPFLAGS ${BCTOOLBOX_CPPFLAGS})
+if(ENABLE_STATIC)
+	list(APPEND BELLESIP_CPPFLAGS "-DBELLESIP_STATIC")
+endif()
+if(BELLESIP_CPPFLAGS)
+	list(REMOVE_DUPLICATES BELLESIP_CPPFLAGS)
+	add_definitions(${BELLESIP_CPPFLAGS})
 endif()
+add_definitions("-DBELLESIP_EXPORTS")
+
 if(CMAKE_SYSTEM_NAME STREQUAL "WindowsPhone" OR CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
 	add_definitions(
 		-DHAVE_COMPILER_TLS
@@ -270,15 +259,4 @@ install(FILES
 	DESTINATION ${CONFIG_PACKAGE_LOCATION}
 )
 
-
-# CPack settings
-set(CPACK_PACKAGE_NAME "belle-sip")
-set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
-set(CPACK_SOURCE_GENERATOR "TGZ")
-set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
-set(CPACK_SOURCE_IGNORE_FILES
-        "^${CMAKE_BINARY_DIR}"
-        "/\\\\..+"
-)
-
-include(CPack)
+add_subdirectory(build)
diff --git a/NEWS b/NEWS
index 4adf907..5a26d8a 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,9 @@
+belle_sip-1.6.2 -- July 21th, 2017
+	* Build fix for Windows
+
+belle_sip-1.6.2 -- July 20th, 2017
+	* Bug fixes
+
 belle_sip-1.6.1 -- March 2nd, 2017
 	* Fix bug around nsswitch.conf parsing on GNU/Linux
 
diff --git a/README.md b/README.md
index f574fc1..7cd412f 100644
--- a/README.md
+++ b/README.md
@@ -65,3 +65,12 @@ Note for packagers
 Our CMake scripts may automatically add some paths into research paths of generated binaries.
 To ensure that the installed binaries are striped of any rpath, use `-DCMAKE_SKIP_INSTALL_RPATH=ON`
 while you invoke cmake.
+
+Rpm packaging
+belle-sip can be generated with cmake3 using the following command:
+mkdir WORK
+cd WORK
+cmake3 ../
+make package_source
+rpmbuild -ta --clean --rmsource --rmspec belle-sip-<version>-<release>.tar.gz
+
diff --git a/belle-sip.spec.in b/belle-sip.spec.in
index 4deb4ad..26cd400 100755
--- a/belle-sip.spec.in
+++ b/belle-sip.spec.in
@@ -63,7 +63,7 @@ rm -rf $RPM_BUILD_ROOT
 
 %files
 %defattr(-,root,root)
-%doc AUTHORS ChangeLog COPYING NEWS README
+%doc AUTHORS ChangeLog COPYING NEWS README.md
 %{_libdir}/*.so.*
 
 %files devel
diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt
new file mode 100644
index 0000000..9db4d15
--- /dev/null
+++ b/build/CMakeLists.txt
@@ -0,0 +1,50 @@
+############################################################################
+# CMakeLists.txt
+# Copyright (C) 2017  Belledonne Communications, Grenoble France
+#
+############################################################################
+#
+# This program 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.
+#
+# This program 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+#
+############################################################################
+
+if (NOT CPACK_PACKAGE_NAME)
+	set(CPACK_PACKAGE_NAME "belle-sip")
+ENDIF()
+
+set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/../COPYING")
+
+set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
+set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
+set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
+
+set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}-${PROJECT_VERSION})
+
+set(CPACK_SOURCE_GENERATOR "TGZ")
+set(CPACK_SOURCE_IGNORE_FILES
+"${CMAKE_BINARY_DIR}"
+"^${PROJECT_SOURCE_DIR}/.git*"
+)
+bc_project_build_version(${PROJECT_VERSION} PROJECT_VERSION_BUILD)
+
+set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-${PROJECT_VERSION_BUILD}")
+
+message("-- Package file name is ${CPACK_PACKAGE_FILE_NAME}" )
+
+set(CPACK_SOURCE_PACKAGE_FILE_NAME ${CPACK_PACKAGE_FILE_NAME})
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/rpm/belle-sip.spec.cmake ${CMAKE_CURRENT_SOURCE_DIR}/../belle-sip.spec)
+
+include(CPack)
+
diff --git a/belle-sip.spec.in b/build/rpm/belle-sip.spec.cmake
similarity index 65%
copy from belle-sip.spec.in
copy to build/rpm/belle-sip.spec.cmake
index 4deb4ad..fcc2b8e 100755
--- a/belle-sip.spec.in
+++ b/build/rpm/belle-sip.spec.cmake
@@ -15,17 +15,20 @@
 %define _datadir           %{_datarootdir}
 %define _docdir            %{_datadir}/doc
 
+%define build_number @PROJECT_VERSION_BUILD@
+
+
 
 Name:           %{pkg_name}
-Version:        @VERSION@
-Release:        %(version=`git describe --tags --abbrev=40 | sed -rn 's/^.*-([0-9]+)-g[a-z0-9]{40}$/\1/p'` && if test -z "$version" ; then echo 0 ; else echo $version ; fi)%{?dist}
-Summary:        Linphone sip stack
+Version:        @PROJECT_VERSION@
+Release:        %build_number%{?dist}
+Summary:        Linphone's sip stack
 
 Group:          Applications/Communications
 License:        GPL
 URL:            http://www.belle-sip.org
-BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
-Source0: 	%{name}-%{version}.tar.gz
+Source0:        %{name}-%{version}-%{build_number}.tar.gz
+BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-buildroot
 %description
 Belle-sip is an object oriented SIP stack, written in C, used by Linphone.
 
@@ -40,18 +43,26 @@ Requires:      %{name} = %{version}-%{release}
 %description    devel
 Libraries and headers required to develop software with belle-sip
 
+%if 0%{?rhel} && 0%{?rhel} <= 7
+%global cmake_name cmake3
+%define ctest_name ctest3
+%else
+%global cmake_name cmake
+%define ctest_name ctest
+%endif
+
 %prep
-%setup -q
+%setup -n %{name}-%{version}-%build_number
 
 %build
-%configure \
-	--disable-tests --enable-static --docdir=%{_docdir}
-%__make %{?_smp_mflags}
-
+%{expand:%%%cmake_name} . -DCMAKE_INSTALL_LIBDIR:PATH=%{_libdir} -DCMAKE_PREFIX_PATH:PATH=%{_prefix}
+make %{?_smp_mflags}
 
 %install
-rm -rf $RPM_BUILD_ROOT
-make install DESTDIR=$RPM_BUILD_ROOT
+make install DESTDIR=%{buildroot}
+
+%check
+#%{ctest_name} -V %{?_smp_mflags}
 
 %clean
 rm -rf $RPM_BUILD_ROOT
@@ -63,16 +74,20 @@ rm -rf $RPM_BUILD_ROOT
 
 %files
 %defattr(-,root,root)
-%doc AUTHORS ChangeLog COPYING NEWS README
+%doc AUTHORS ChangeLog COPYING NEWS README.md
 %{_libdir}/*.so.*
 
 %files devel
 %defattr(-,root,root)
 %{_includedir}/belle-sip
 %{_libdir}/libbellesip.a
-%{_libdir}/libbellesip.la
 %{_libdir}/libbellesip.so
 %{_libdir}/pkgconfig/belle-sip.pc
+%{_datadir}/BelleSIP/cmake/BelleSIPConfig.cmake
+%{_datadir}/BelleSIP/cmake/BelleSIPConfigVersion.cmake
+%{_datadir}/BelleSIP/cmake/BelleSIPTargets-noconfig.cmake
+%{_datadir}/BelleSIP/cmake/BelleSIPTargets.cmake
+%{_bindir}/*
 
 %changelog
 * Mon Aug 19 2013 jehan.monnier <jehan.monnier at linphone.org>
diff --git a/cmake/BelleSIPConfig.cmake.in b/cmake/BelleSIPConfig.cmake.in
index a0932a8..cc0386e 100644
--- a/cmake/BelleSIPConfig.cmake.in
+++ b/cmake/BelleSIPConfig.cmake.in
@@ -26,41 +26,38 @@
 #  BELLESIP_FOUND - system has belle-sip
 #  BELLESIP_INCLUDE_DIRS - the belle-sip include directory
 #  BELLESIP_LIBRARIES - The libraries needed to use belle-sip
+#  BELLESIP_CPPFLAGS - The compilation flags needed to use belle-sip
 #  BELLESIP_LDFLAGS - The linking flags needed to use belle-sip
 
 if(NOT LINPHONE_BUILDER_GROUP_EXTERNAL_SOURCE_PATH_BUILDERS)
 	include("${CMAKE_CURRENT_LIST_DIR}/BelleSIPTargets.cmake")
 endif()
 
-if(LINPHONE_BUILDER_GROUP_EXTERNAL_SOURCE_PATH_BUILDERS)
-	include("${EP_bctoolbox_CONFIG_DIR}/BcToolboxConfig.cmake")
+if(@ENABLE_SHARED@)
+	set(BELLESIP_TARGETNAME bellesip)
+	set(BELLESIP_LIBRARIES ${BELLESIP_TARGETNAME})
 else()
-	find_package(BcToolbox 0.0.3 REQUIRED COMPONENTS core)
-endif()
-if(@ENABLE_TUNNEL@)
-	if(LINPHONE_BUILDER_GROUP_EXTERNAL_SOURCE_PATH_BUILDERS)
-		include("${EP_tunnel_CONFIG_DIR}/TunnelConfig.cmake")
-	else()
-		find_package(Tunnel)
+	set(BELLESIP_TARGETNAME bellesip-static)
+	if(TARGET ${BELLESIP_TARGETNAME})
+		if(LINPHONE_BUILDER_GROUP_EXTERNAL_SOURCE_PATH_BUILDERS)
+			set(BELLESIP_LIBRARIES ${BELLESIP_TARGETNAME})
+		else()
+			get_target_property(BELLESIP_LIBRARIES ${BELLESIP_TARGETNAME} LOCATION)
+		endif()
+		get_target_property(BELLESIP_LINK_LIBRARIES ${BELLESIP_TARGETNAME} INTERFACE_LINK_LIBRARIES)
+		if(BELLESIP_LINK_LIBRARIES)
+			list(APPEND BELLESIP_LIBRARIES ${BELLESIP_LINK_LIBRARIES})
+		endif()
 	endif()
 endif()
-
-get_filename_component(BELLESIP_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
+get_target_property(BELLESIP_INCLUDE_DIRS ${BELLESIP_TARGETNAME} INTERFACE_INCLUDE_DIRECTORIES)
 if(LINPHONE_BUILDER_GROUP_EXTERNAL_SOURCE_PATH_BUILDERS)
-	set(BELLESIP_INCLUDE_DIRS "${EP_bellesip_INCLUDE_DIR}")
+	list(INSERT BELLESIP_INCLUDE_DIRS 0 "${EP_bellesip_INCLUDE_DIR}")
 else()
-	set(BELLESIP_INCLUDE_DIRS "${BELLESIP_CMAKE_DIR}/../../../include")
+	list(INSERT BELLESIP_INCLUDE_DIRS 0 "@CMAKE_INSTALL_FULL_INCLUDEDIR@")
 endif()
-if(@ENABLE_SHARED@)
-	set(BELLESIP_LIBRARIES bellesip)
-else()
-	set(BELLESIP_LIBRARIES bellesip-static)
-endif()
-list(APPEND BELLESIP_INCLUDE_DIRS ${BCTOOLBOX_CORE_INCLUDE_DIRS})
-list(APPEND BELLESIP_LIBRARIES ${BCTOOLBOX_CORE_LIBRARIES})
+list(REMOVE_DUPLICATES BELLESIP_INCLUDE_DIRS)
+
+set(BELLESIP_CPPFLAGS @BELLESIP_CPPFLAGS@)
 set(BELLESIP_LDFLAGS "@LINK_FLAGS_STR@")
-if(TUNNEL_FOUND)
-	list(APPEND BELLESIP_INCLUDE_DIRS ${TUNNEL_INCLUDE_DIRS})
-	list(APPEND BELLESIP_LIBRARIES ${TUNNEL_LIBRARIES})
-endif()
 set(BELLESIP_FOUND 1)
diff --git a/cmake/FindAntlr3.cmake b/cmake/FindAntlr3.cmake
index e2d01a5..ed2baa5 100644
--- a/cmake/FindAntlr3.cmake
+++ b/cmake/FindAntlr3.cmake
@@ -70,7 +70,7 @@ if(NOT ANTLR3_COMMAND)
 	)
 
 	if(ANTLR3_JAR_PATH)
-		set(ANTLR3_COMMAND ${Java_JAVA_EXECUTABLE} -Xmx256m -jar ${ANTLR3_JAR_PATH})
+		set(ANTLR3_COMMAND ${Java_JAVA_EXECUTABLE} -Xmx384m -jar ${ANTLR3_JAR_PATH})
 	endif()
 endif()
 
diff --git a/cmake/FindZlib.cmake b/cmake/FindZlib.cmake
index 8f7e234..3cb42a4 100644
--- a/cmake/FindZlib.cmake
+++ b/cmake/FindZlib.cmake
@@ -26,8 +26,8 @@
 #  ZLIB_INCLUDE_DIRS - the zlib include directory
 #  ZLIB_LIBRARIES - The libraries needed to use zlib
 
-if(APPLE AND NOT IOS)
-	set(ZLIB_HINTS "/usr")
+if(APPLE AND NOT IOS AND NOT CMAKE_FIND_ROOT_PATH)
+	set(CMAKE_FIND_ROOT_PATH ${CMAKE_OSX_SYSROOT}) #On MACOSX zlib is from xcode SDK
 endif()
 if(ZLIB_HINTS)
 	set(ZLIB_LIBRARIES_HINTS "${ZLIB_HINTS}/lib")
diff --git a/configure.ac b/configure.ac
index a055532..fd547b7 100755
--- a/configure.ac
+++ b/configure.ac
@@ -128,7 +128,7 @@ case "$target_os" in
 esac
 
 if test "$strict" = "true"; then
-	STRICT_OPTIONS="$STRICT_OPTIONS -Werror -Wextra -Wno-unused-parameter -Wno-error=unknown-pragmas -Wuninitialized -Wno-error=strict-prototypes -Wno-missing-field-initializers"
+	STRICT_OPTIONS="$STRICT_OPTIONS -Werror -Wextra -Wno-unused-parameter -Wno-error=unknown-pragmas -Wuninitialized -Wno-error=strict-prototypes -Wno-missing-field-initializers -Wno-error=deprecated-declarations"
 fi
 
 dnl because of antlr3 we must accept a few warnings...
@@ -217,7 +217,7 @@ antlr_java_prefixes="$antlr_prefix/share/java /usr/local/share/java /usr/share/j
 	if test $JAVA = "no" ; then
 		AC_MSG_ERROR([Could not find java prog. Please install java ])
 	else
-		ANTLR="$JAVA -Xmx256m -jar $antlr_jar"
+		ANTLR="$JAVA -Xmx512m -jar $antlr_jar"
 	fi
 fi
 AC_SUBST(ANTLR_CFLAGS)
diff --git a/include/belle-sip/auth-helper.h b/include/belle-sip/auth-helper.h
index 26d98e7..3610aab 100644
--- a/include/belle-sip/auth-helper.h
+++ b/include/belle-sip/auth-helper.h
@@ -33,6 +33,13 @@ BELLE_SIP_BEGIN_DECLS
 BELLESIP_EXPORT belle_sip_header_authorization_t* belle_sip_auth_helper_create_authorization(const belle_sip_header_www_authenticate_t* authentication);
 
 /**
+ * Create an www_authenticate header from an authorization header, all common parameters are copyed.
+ * copy params: scheme, realm, nonce, algorithm, opaque
+ * @param authorization source to be used as input
+ * @return belle_sip_header_www_authenticate_t*
+ */
+BELLESIP_EXPORT belle_sip_header_www_authenticate_t* belle_sip_auth_helper_create_www_authenticate(const belle_sip_header_authorization_t* authorization);
+/**
  * Create an http authorization header from an www_authenticate header, all common parameters are copyed.
  * copy params: scheme, realm, nonce, algorithm, opaque
  * @param authentication source to be used as input
diff --git a/include/belle-sip/belle-sip.h b/include/belle-sip/belle-sip.h
index 5bbe128..55dbecc 100644
--- a/include/belle-sip/belle-sip.h
+++ b/include/belle-sip/belle-sip.h
@@ -43,7 +43,7 @@
 #include "belle-sip/belle-sdp.h"
 #include "belle-sip/bodyhandler.h"
 
-#ifdef ANDROID
+#ifdef __ANDROID__
 #include "belle-sip/wakelock.h"
 #endif
 
diff --git a/include/belle-sip/defs.h b/include/belle-sip/defs.h
index 8c953fe..65fe5b0 100644
--- a/include/belle-sip/defs.h
+++ b/include/belle-sip/defs.h
@@ -42,17 +42,18 @@ typedef unsigned __int64 uint64_t;
 #define BELLESIP_INLINE inline
 #endif
 
-#ifdef _WIN32
-#ifdef BELLESIP_EXPORTS
-#define BELLESIP_EXPORT __declspec(dllexport)
-#define BELLESIP_VAR_EXPORT __declspec(dllexport)
-#else
-#define BELLESIP_EXPORT
-#define BELLESIP_VAR_EXPORT extern __declspec(dllimport)
-#endif
+#ifdef _MSC_VER
+    #ifdef BELLESIP_STATIC
+        #define BELLESIP_EXPORT
+    #else
+        #ifdef BELLESIP_EXPORTS
+            #define BELLESIP_EXPORT __declspec(dllexport)
+        #else
+            #define BELLESIP_EXPORT __declspec(dllimport)
+        #endif
+    #endif
 #else
-#define BELLESIP_VAR_EXPORT extern
-#define BELLESIP_EXPORT extern
+    #define BELLESIP_EXPORT
 #endif
 
 #define BELLESIP_UNUSED(a) (void)a;
diff --git a/include/belle-sip/headers.h b/include/belle-sip/headers.h
index 69815f4..997fad1 100644
--- a/include/belle-sip/headers.h
+++ b/include/belle-sip/headers.h
@@ -59,6 +59,12 @@ BELLESIP_EXPORT belle_sip_header_address_t* belle_sip_header_address_create2(con
 
 BELLESIP_EXPORT belle_sip_header_address_t* belle_sip_header_address_parse (const char* address) ;
 
+/*
+ same as belle_sip_header_address_parse but with less syntax checking
+ */
+BELLESIP_EXPORT belle_sip_header_address_t* belle_sip_header_address_fast_parse (const char* address) ;
+
+
 /**
  * returns a sip uri. A header address cannot have both a sip uri and an absolute uri.
  */
@@ -753,6 +759,51 @@ BELLESIP_EXPORT void belle_sip_header_accept_set_subtype(belle_sip_header_accept
 #define BELLE_SIP_HEADER_ACCEPT(t) BELLE_SIP_CAST(t,belle_sip_header_accept_t)
 #define BELLE_SIP_ACCEPT "Accept"
 
+/******************************
+ * Reason header object inherent from parameters
+ *
+ ******************************/
+typedef struct _belle_sip_header_reason belle_sip_header_reason_t;
+BELLESIP_EXPORT belle_sip_header_reason_t* belle_sip_header_reason_new(void);
+BELLESIP_EXPORT belle_sip_header_reason_t* belle_sip_header_reason_parse (const char* reason) ;
+BELLESIP_EXPORT const char*	belle_sip_header_reason_get_protocol(const belle_sip_header_reason_t* reason);
+BELLESIP_EXPORT void belle_sip_header_reason_set_protocol(belle_sip_header_reason_t* reason,const char* protocol);
+BELLESIP_EXPORT int	belle_sip_header_reason_get_cause(const belle_sip_header_reason_t* reason);
+BELLESIP_EXPORT void belle_sip_header_reason_set_cause(belle_sip_header_reason_t* reason,int cause);
+BELLESIP_EXPORT void belle_sip_header_reason_set_text(belle_sip_header_reason_t* reason,const char* text);
+BELLESIP_EXPORT const char*	belle_sip_header_reason_get_text(const belle_sip_header_reason_t* reason);
+
+#define BELLE_SIP_HEADER_REASON(t) BELLE_SIP_CAST(t,belle_sip_header_reason_t)
+#define BELLE_SIP_REASON "Reason"
+
+
+/******************************
+ * Authentication-Info header inherit from header
+ *
+ ******************************/
+typedef struct _belle_sip_header_authentication_info belle_sip_header_authentication_info_t;
+
+BELLESIP_EXPORT belle_sip_header_authentication_info_t* belle_sip_header_authentication_info_new(void);
+BELLESIP_EXPORT belle_sip_header_authentication_info_t* belle_sip_header_authentication_info_parse(const char* authentication_info );
+BELLESIP_EXPORT const char*	belle_sip_header_authentication_info_get_next_nonce(const belle_sip_header_authentication_info_t* authentication_info );
+BELLESIP_EXPORT void belle_sip_header_authentication_info_set_next_nonce(belle_sip_header_authentication_info_t* authentication_info, const char* next_nonce);
+
+/*limited to a sinle value*/
+BELLESIP_EXPORT const char*	belle_sip_header_authentication_info_get_qop(const belle_sip_header_authentication_info_t* authentication_info);
+BELLESIP_EXPORT void belle_sip_header_authentication_info_set_qop(belle_sip_header_authentication_info_t* authentication_info, const char* qop);
+
+BELLESIP_EXPORT const char*	belle_sip_header_authentication_info_get_rsp_auth(const belle_sip_header_authentication_info_t* rsp_auth);
+BELLESIP_EXPORT void belle_sip_header_authentication_info_set_rsp_auth(belle_sip_header_authentication_info_t* authentication_info, const char* rsp_auth);
+
+BELLESIP_EXPORT const char* belle_sip_header_authentication_info_get_cnonce(const belle_sip_header_authentication_info_t* authentication_info);
+BELLESIP_EXPORT void belle_sip_header_authentication_info_set_cnonce(belle_sip_header_authentication_info_t* authentication_info, const char* cNonce);
+
+BELLESIP_EXPORT void belle_sip_header_authentication_info_set_nonce_count(belle_sip_header_authentication_info_t* authentication_info, int nonceCount);
+BELLESIP_EXPORT int	belle_sip_header_authentication_info_get_nonce_count(const belle_sip_header_authentication_info_t* authentication_info);
+
+
+#define BELLE_SIP_HEADER_AUTHENTICATION_INFO(t) BELLE_SIP_CAST(t,belle_sip_header_authentication_info_t)
+#define BELLE_SIP_AUTHENTICATION_INFO "Authentication-Info"
 
 BELLE_SIP_END_DECLS
 
diff --git a/include/belle-sip/list.h b/include/belle-sip/list.h
index 08af5e9..7d6c7b1 100644
--- a/include/belle-sip/list.h
+++ b/include/belle-sip/list.h
@@ -50,5 +50,6 @@ typedef struct _bctbx_list belle_sip_list_t;
 #define belle_sip_list_insert bctbx_list_insert
 #define belle_sip_list_copy bctbx_list_copy
 #define belle_sip_list_copy_with_data bctbx_list_copy_with_data
+#define belle_sip_list_copy_reverse_with_data bctbx_list_copy_reverse_with_data
 
 #endif /* BELLE_SIP_LIST_H_ */
diff --git a/include/belle-sip/object.h b/include/belle-sip/object.h
index 54aa6bf..6c965f7 100644
--- a/include/belle-sip/object.h
+++ b/include/belle-sip/object.h
@@ -55,6 +55,16 @@ typedef unsigned int belle_sip_type_id_t;
 	struct object_type##_vptr_struct{\
 		BELLE_SIP_OBJECT_VPTR_TYPE(parent_type) base;
 
+#define BELLE_SIP_DECLARE_VPTR_NO_EXPORT(object_type) \
+	typedef belle_sip_object_vptr_t BELLE_SIP_OBJECT_VPTR_TYPE(object_type);\
+	BELLE_SIP_OBJECT_VPTR_TYPE(object_type) * BELLE_SIP_OBJECT_GET_VPTR_FUNC(object_type)(void);
+
+#define BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN_NO_EXPORT(object_type, parent_type) \
+	typedef struct object_type##_vptr_struct BELLE_SIP_OBJECT_VPTR_TYPE(object_type);\
+	BELLE_SIP_OBJECT_VPTR_TYPE(object_type) * BELLE_SIP_OBJECT_GET_VPTR_FUNC(object_type)(void); \
+	struct object_type##_vptr_struct{\
+		BELLE_SIP_OBJECT_VPTR_TYPE(parent_type) base;
+
 #define BELLE_SIP_DECLARE_CUSTOM_VPTR_END };
 
 #define BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(object_type) \
diff --git a/include/belle-sip/resolver.h b/include/belle-sip/resolver.h
index 9b31517..c82f7ec 100644
--- a/include/belle-sip/resolver.h
+++ b/include/belle-sip/resolver.h
@@ -31,14 +31,14 @@ typedef struct belle_sip_resolver_context belle_sip_resolver_context_t;
  * Callback prototype for asynchronous DNS SRV resolution.
  * The srv_list contains struct dns_srv elements that must be taken and (possibly later) freed by the callee, using belle_sip_free().
  */
-typedef void (*belle_sip_resolver_srv_callback_t)(void *data, const char *name, belle_sip_list_t *srv_list);
+typedef void (*belle_sip_resolver_srv_callback_t)(void *data, const char *name, belle_sip_list_t *srv_list, uint32_t ttl);
 
 /**
  * Callback prototype for asynchronous DNS A and AAAA resolution.
  * The ai_list contains addrinfo elements that must be taken and (possibly later) freed by the callee, using freeaddrinfo().
  * These elements are linked by their ai_next field.
 **/
-typedef void (*belle_sip_resolver_callback_t)(void *data, const char *name, struct addrinfo *ai_list);
+typedef void (*belle_sip_resolver_callback_t)(void *data, const char *name, struct addrinfo *ai_list, uint32_t ttl);
 
 
 BELLE_SIP_BEGIN_DECLS
diff --git a/include/belle-sip/sip-uri.h b/include/belle-sip/sip-uri.h
index 80dc587..810a583 100644
--- a/include/belle-sip/sip-uri.h
+++ b/include/belle-sip/sip-uri.h
@@ -35,6 +35,16 @@ BELLESIP_EXPORT belle_sip_uri_t* belle_sip_uri_new(void);
  *
  */
 BELLESIP_EXPORT belle_sip_uri_t* belle_sip_uri_parse (const char* uri) ;
+
+/**
+ *
+ */
+BELLESIP_EXPORT belle_sip_uri_t* belle_sip_fast_uri_parse (const char* uri) ;
+
+/**
+ * same as belle_sip_uri_parse but with much less checks
+ */
+BELLESIP_EXPORT belle_sip_uri_t* belle_sip_fast_uri_parse (const char* uri) ;
 /**
  *
  */
diff --git a/include/belle-sip/types.h b/include/belle-sip/types.h
index b3a172e..bb1225c 100644
--- a/include/belle-sip/types.h
+++ b/include/belle-sip/types.h
@@ -143,7 +143,9 @@ BELLE_SIP_DECLARE_TYPES_BEGIN(belle_sip,1)
 	BELLE_SIP_TYPE_ID(belle_sip_header_event_t),
 	BELLE_SIP_TYPE_ID(belle_sip_header_supported_t),
 	BELLE_SIP_TYPE_ID(belle_sip_header_content_disposition_t),
-	BELLE_SIP_TYPE_ID(belle_sip_header_accept_t)
+	BELLE_SIP_TYPE_ID(belle_sip_header_accept_t),
+	BELLE_SIP_TYPE_ID(belle_sip_header_reason_t),
+	BELLE_SIP_TYPE_ID(belle_sip_header_authentication_info_t)
 BELLE_SIP_DECLARE_TYPES_END
 
 
diff --git a/include/belle-sip/utils.h b/include/belle-sip/utils.h
index 825e865..ee4f954 100644
--- a/include/belle-sip/utils.h
+++ b/include/belle-sip/utils.h
@@ -36,6 +36,7 @@
 
 
 #include "bctoolbox/logging.h"
+#include "bctoolbox/vconnect.h"
 
 BELLE_SIP_BEGIN_DECLS
 
@@ -136,6 +137,9 @@ BELLESIP_EXPORT uint64_t belle_sip_time_ms(void);
 
 BELLESIP_EXPORT unsigned int belle_sip_random(void);
 
+/** Connect API */
+BELLESIP_EXPORT void belle_sip_set_socket_api(bctbx_vsocket_api_t* my_api);
+
 #if defined(_WIN32)
 
 #include <winsock2.h>
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 192f858..315d427 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -165,11 +165,11 @@ if(APPLE)
 	)
 endif()
 
-apply_compile_flags(BELLE_SIP_SOURCE_FILES_C "CPP" "C")
-apply_compile_flags(BELLE_SIP_SOURCE_FILES_OBJC "CPP" "OBJC")
+bc_apply_compile_flags(BELLE_SIP_SOURCE_FILES_C STRICT_OPTIONS_CPP STRICT_OPTIONS_C)
+bc_apply_compile_flags(BELLE_SIP_SOURCE_FILES_OBJC STRICT_OPTIONS_CPP STRICT_OPTIONS_OBJC)
 if(BELLE_SIP_SOURCE_FILES_CXX)
 	set_source_files_properties(${BELLE_SIP_SOURCE_FILES_CXX} PROPERTIES LANGUAGE CXX)
-	apply_compile_flags(BELLE_SIP_SOURCE_FILES_CXX "CPP" "CXX")
+	bc_apply_compile_flags(BELLE_SIP_SOURCE_FILES_CXX STRICT_OPTIONS_CPP STRICT_OPTIONS_CXX)
 endif()
 if(MSVC)
 	get_source_file_property(DNS_C_COMPILE_FLAGS dns.c COMPILE_FLAGS)
@@ -186,6 +186,9 @@ if(MSVC)
 	set(SIP_MESSAGE_PARSER_COMPILE_FLAGS "${SIP_MESSAGE_PARSER_COMPILE_FLAGS} /wd4267") # Disable "possible loss of data" warnings
 	set_source_files_properties(grammars/belle_sip_messageParser.c PROPERTIES COMPILE_FLAGS "${SIP_MESSAGE_PARSER_COMPILE_FLAGS}")
 else()
+	get_source_file_property(DNS_C_COMPILE_FLAGS dns.c COMPILE_FLAGS)
+	set(DNS_C_COMPILE_FLAGS "${DNS_C_COMPILE_FLAGS} -Wno-error")
+	set_source_files_properties(dns.c PROPERTIES COMPILE_FLAGS "${DNS_C_COMPILE_FLAGS}")
 	get_source_file_property(SIP_MESSAGE_PARSER_COMPILE_FLAGS grammars/belle_sip_messageParser.c COMPILE_FLAGS)
 	set(SIP_MESSAGE_PARSER_COMPILE_FLAGS "${SIP_MESSAGE_PARSER_COMPILE_FLAGS} -Wno-sign-compare")
 	set_source_files_properties(grammars/belle_sip_messageParser.c PROPERTIES COMPILE_FLAGS "${SIP_MESSAGE_PARSER_COMPILE_FLAGS}")
@@ -196,7 +199,7 @@ if(ENABLE_STATIC)
 	add_library(bellesip-static STATIC ${BELLE_SIP_HEADER_FILES} ${BELLE_SIP_SOURCE_FILES_C} ${BELLE_SIP_SOURCE_FILES_CXX} ${BELLE_SIP_SOURCE_FILES_OBJC})
 	set_target_properties(bellesip-static PROPERTIES OUTPUT_NAME bellesip)
 	target_include_directories(bellesip-static PUBLIC ${INCLUDES})
-	target_link_libraries(bellesip-static ${LIBS})
+	target_link_libraries(bellesip-static INTERFACE ${LIBS})
 	if(NOT "${LINK_FLAGS_STR}" STREQUAL "")
 		set_target_properties(bellesip-static PROPERTIES LINK_FLAGS "${LINK_FLAGS_STR}")
 	endif()
@@ -231,6 +234,3 @@ if(ENABLE_SHARED)
 		PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
 	)
 endif()
-
-
-
diff --git a/src/auth_helper.c b/src/auth_helper.c
index 3bbd49c..18417ef 100644
--- a/src/auth_helper.c
+++ b/src/auth_helper.c
@@ -39,11 +39,27 @@ static void belle_sip_auth_helper_clone_authorization(belle_sip_header_authoriza
 	CLONE_STRING_GENERIC(belle_sip_header_www_authenticate,belle_sip_header_authorization,algorithm,authorization,authentication)
 	CLONE_STRING_GENERIC(belle_sip_header_www_authenticate,belle_sip_header_authorization,opaque,authorization,authentication)
 }
+
+static void belle_sip_auth_helper_clone_www_authenticate(belle_sip_header_www_authenticate_t* authentication, const belle_sip_header_authorization_t* authorization) {
+	CLONE_STRING_GENERIC(belle_sip_header_authorization,belle_sip_header_www_authenticate,scheme, authentication, authorization)
+	CLONE_STRING_GENERIC(belle_sip_header_authorization,belle_sip_header_www_authenticate,realm, authentication, authorization)
+	CLONE_STRING_GENERIC(belle_sip_header_authorization,belle_sip_header_www_authenticate,nonce, authentication, authorization)
+	CLONE_STRING_GENERIC(belle_sip_header_authorization,belle_sip_header_www_authenticate,algorithm,authentication ,authorization)
+	CLONE_STRING_GENERIC(belle_sip_header_authorization,belle_sip_header_www_authenticate,opaque,authentication, authorization)
+}
+
 belle_sip_header_authorization_t* belle_sip_auth_helper_create_authorization(const belle_sip_header_www_authenticate_t* authentication) {
 	belle_sip_header_authorization_t* authorization = belle_sip_header_authorization_new();
 	belle_sip_auth_helper_clone_authorization(authorization,authentication);
 	return authorization;
 }
+
+belle_sip_header_www_authenticate_t* belle_sip_auth_helper_create_www_authenticate(const belle_sip_header_authorization_t* authorization) {
+	belle_sip_header_www_authenticate_t* www_authenticate = belle_sip_header_www_authenticate_new();
+	belle_sip_auth_helper_clone_www_authenticate(www_authenticate, authorization);
+	return www_authenticate;
+}
+
 belle_http_header_authorization_t* belle_http_auth_helper_create_authorization(const belle_sip_header_www_authenticate_t* authentication) {
 	belle_http_header_authorization_t* authorization = belle_http_header_authorization_new();
 	belle_sip_auth_helper_clone_authorization(BELLE_SIP_HEADER_AUTHORIZATION(authorization),authentication);
@@ -69,7 +85,7 @@ int belle_sip_auth_helper_compute_ha1(const char* userid,const char* realm,const
 		 return -1;
 	}
 	if (!realm) {
-		 belle_sip_error("belle_sip_fill_authorization_header, password not found ");
+		 belle_sip_error("belle_sip_fill_authorization_header, realm not found ");
 		 return -1;
 	}
 
@@ -238,8 +254,3 @@ int belle_sip_auth_helper_fill_proxy_authorization(belle_sip_header_proxy_author
 
 
 }
-
-
-
-
-
diff --git a/src/belle_sip_headers_impl.c b/src/belle_sip_headers_impl.c
index e36bf64..270dec1 100644
--- a/src/belle_sip_headers_impl.c
+++ b/src/belle_sip_headers_impl.c
@@ -83,6 +83,8 @@ static struct header_name_func_pair  header_table[] = {
 	,{PROTO_SIP, 			"k",							(header_parse_func)belle_sip_header_supported_parse}
 	,{PROTO_SIP, 			BELLE_SIP_CONTENT_DISPOSITION,	(header_parse_func)belle_sip_header_content_disposition_parse}
 	,{PROTO_SIP, 			BELLE_SIP_ACCEPT,				(header_parse_func)belle_sip_header_accept_parse}
+	,{PROTO_SIP, 			BELLE_SIP_REASON,				(header_parse_func)belle_sip_header_reason_parse}
+	,{PROTO_SIP,			BELLE_SIP_AUTHENTICATION_INFO,	(header_parse_func)belle_sip_header_authentication_info_parse}
 };
 
 static belle_sip_header_t* belle_header_create(const char* name,const char* value,int protocol) {
@@ -310,6 +312,13 @@ belle_sip_header_address_t* belle_sip_header_address_create2(const char* display
 	return address;
 }
 
+/*fast header address implemenation*/
+typedef belle_sip_header_address_t belle_sip_fast_header_address_t;
+#define belle_sip_fast_header_address_parse belle_sip_header_address_fast_parse  
+BELLE_SIP_PARSE(fast_header_address)
+
+
+
 /******************************
  * Extension header inherits from header
  *
@@ -2021,4 +2030,136 @@ belle_sip_header_accept_t* belle_sip_header_accept_create (const char* type,cons
 GET_SET_STRING(belle_sip_header_accept,type);
 GET_SET_STRING(belle_sip_header_accept,subtype);
 
+/******************************
+ * Reason header object inherent from parameters
+ *
+ ******************************/
+struct _belle_sip_header_reason  {
+	belle_sip_parameters_t params_list;
+	const char* protocol;
+	const char* unquoted_text;
+};
+
+static void belle_sip_header_reason_destroy(belle_sip_header_reason_t* reason) {
+	DESTROY_STRING(reason,protocol);
+	DESTROY_STRING(reason,unquoted_text);
+}
+
+static void belle_sip_header_reason_clone(belle_sip_header_reason_t* reason, const belle_sip_header_reason_t* orig){
+	CLONE_STRING(belle_sip_header_reason,protocol,reason,orig)
+}
+
+belle_sip_error_code belle_sip_header_reason_marshal(belle_sip_header_reason_t* reason, char* buff, size_t buff_size, size_t *offset) {
+	belle_sip_error_code error=belle_sip_header_marshal(BELLE_SIP_HEADER(reason), buff, buff_size, offset);
+	if (error!=BELLE_SIP_OK) return error;
+		error=belle_sip_snprintf(buff,buff_size,offset,"%s ",reason->protocol);
+	if (error!=BELLE_SIP_OK) return error;
+		error=belle_sip_parameters_marshal(BELLE_SIP_PARAMETERS(reason), buff, buff_size, offset);
+	if (error!=BELLE_SIP_OK) return error;
+	if (reason->unquoted_text)
+		error=belle_sip_snprintf(buff,buff_size,offset,"; text=\"%s\"",reason->unquoted_text);
+	return error;
+}
+
+GET_SET_STRING(belle_sip_header_reason,unquoted_text);
+
+void belle_sip_header_reason_set_text(belle_sip_header_reason_t* reason,const char* text) {
+	belle_sip_parameters_remove_parameter(BELLE_SIP_PARAMETERS(reason),"text"); /*just in case*/
+	belle_sip_header_reason_set_unquoted_text((belle_sip_header_reason_t*)reason, text);
+}
+BELLESIP_EXPORT const char*	belle_sip_header_reason_get_text(const belle_sip_header_reason_t* reason) {
+	if (!reason->unquoted_text) {
+		/*try from params*/
+		const char * quoted = belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(reason), "text");
+		if (quoted) {
+			char* unquoted = _belle_sip_str_dup_and_unquote_string(quoted);
+			belle_sip_header_reason_set_unquoted_text((belle_sip_header_reason_t*)reason, unquoted); /*change internal param, ,even if reason is const*/
+			belle_sip_parameters_remove_parameter(BELLE_SIP_PARAMETERS(reason),"text");
+			belle_sip_free(unquoted);
+		}
+
+	}
+	return reason->unquoted_text;
+}
+
+GET_SET_STRING(belle_sip_header_reason,protocol);
+
+GET_SET_INT_PARAM(belle_sip_header_reason,cause,int);
+BELLE_SIP_PARSE(header_reason)
+BELLE_SIP_NEW_HEADER(header_reason,parameters,BELLE_SIP_REASON)
+
+/******************************
+ * AuthenticationInfo header hinerite from header
+ *
+ ******************************/
+
+struct _belle_sip_header_authentication_info  {
+	belle_sip_header_t header;
+	const char* rsp_auth;
+	const char* cnonce;
+	int nonce_count;
+	const char* qop;
+	const char* next_nonce;
+};
+static void belle_sip_header_authentication_info_destroy(belle_sip_header_authentication_info_t* authentication_info) {
+	DESTROY_STRING(authentication_info,rsp_auth);
+	DESTROY_STRING(authentication_info,cnonce);
+	DESTROY_STRING(authentication_info,qop);
+	DESTROY_STRING(authentication_info,next_nonce);
+	
+}
+
+static void belle_sip_header_authentication_info_clone(	belle_sip_header_authentication_info_t* authentication_info
+													   , const belle_sip_header_authentication_info_t* orig){
+	CLONE_STRING(belle_sip_header_authentication_info,rsp_auth,authentication_info,orig)
+	CLONE_STRING(belle_sip_header_authentication_info,cnonce,authentication_info,orig)
+	CLONE_STRING(belle_sip_header_authentication_info,qop,authentication_info,orig)
+	CLONE_STRING(belle_sip_header_authentication_info,next_nonce,authentication_info,orig)
+}
+
+belle_sip_error_code belle_sip_header_authentication_info_marshal(belle_sip_header_authentication_info_t* authentication_info, char* buff, size_t buff_size, size_t *offset) {
+	char* border="";
+	belle_sip_error_code error=belle_sip_header_marshal(BELLE_SIP_HEADER(authentication_info), buff, buff_size, offset);
+	if (error!=BELLE_SIP_OK) return error;
+	
+	if (authentication_info->rsp_auth) {
+		error=belle_sip_snprintf(buff,buff_size,offset,"%srspauth=\"%s\"", border,authentication_info->rsp_auth);
+		border=", ";
+	}
+	if (error!=BELLE_SIP_OK) return error;
 
+	if (authentication_info->cnonce) {
+		error=belle_sip_snprintf(buff,buff_size,offset,"%scnonce=\"%s\"", border, authentication_info->cnonce);
+		border=", ";
+	}
+	if (error!=BELLE_SIP_OK) return error;
+
+	if (authentication_info->nonce_count >= 0) {
+		error=belle_sip_snprintf(buff,buff_size,offset,"%snc=%08x", border, authentication_info->nonce_count);
+		border=", ";
+	}
+	if (error!=BELLE_SIP_OK) return error;
+
+	if (authentication_info->qop) {
+		error=belle_sip_snprintf(buff,buff_size,offset,"%sqop=%s", border, authentication_info->qop);
+		border=", ";
+	}
+	if (error!=BELLE_SIP_OK) return error;
+	
+	if (authentication_info->next_nonce) {
+		error=belle_sip_snprintf(buff,buff_size,offset,"%snextnonce=\"%s\"", border, authentication_info->next_nonce);
+	}
+	return error;
+
+
+}
+void belle_sip_header_authentication_info_init(belle_sip_header_authentication_info_t* header_authentication) {
+	header_authentication->nonce_count=-1;
+}
+BELLE_SIP_NEW_HEADER_INIT(header_authentication_info,header,BELLE_SIP_AUTHENTICATION_INFO,header_authentication_info)
+BELLE_SIP_PARSE(header_authentication_info)
+GET_SET_STRING(belle_sip_header_authentication_info,rsp_auth);
+GET_SET_STRING(belle_sip_header_authentication_info,qop);
+GET_SET_STRING(belle_sip_header_authentication_info,next_nonce);
+GET_SET_STRING(belle_sip_header_authentication_info,cnonce);
+GET_SET_INT(belle_sip_header_authentication_info,nonce_count,int);
diff --git a/src/belle_sip_internal.h b/src/belle_sip_internal.h
index d9acf9b..772a8a9 100644
--- a/src/belle_sip_internal.h
+++ b/src/belle_sip_internal.h
@@ -30,6 +30,7 @@
 
 #include "port.h"
 #include <bctoolbox/port.h>
+#include <bctoolbox/vconnect.h>
 
 #ifdef HAVE_CONFIG_H
 
@@ -81,6 +82,16 @@
 			__method=BELLE_SIP_INTERFACE_GET_METHODS(__obj,interface_name)->method;\
 			if (__method) BELLE_SIP_INTERFACE_GET_METHODS(__obj,interface_name)->
 
+#define __BELLE_SIP_INVOKE_LISTENER_REVERSE_BEGIN(list,interface_name,method) \
+	if (list!=NULL) {\
+		belle_sip_list_t *__copy=belle_sip_list_copy_reverse_with_data((list), (void* (*)(void*))belle_sip_object_ref);\
+		const belle_sip_list_t *__elem=__copy;\
+		do{\
+			void *__method;\
+			interface_name *__obj=(interface_name*)__elem->data;\
+			__method=BELLE_SIP_INTERFACE_GET_METHODS(__obj,interface_name)->method;\
+			if (__method) BELLE_SIP_INTERFACE_GET_METHODS(__obj,interface_name)->
+
 #define __BELLE_SIP_INVOKE_LISTENER_END \
 			__elem=__elem->next;\
 		}while(__elem!=NULL);\
@@ -97,12 +108,16 @@
 	method(__obj,arg);\
 	__BELLE_SIP_INVOKE_LISTENER_END
 
-
 #define BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(list,interface_name,method,arg1,arg2) \
 			__BELLE_SIP_INVOKE_LISTENER_BEGIN(list,interface_name,method)\
 			method(__obj,arg1,arg2);\
 			__BELLE_SIP_INVOKE_LISTENER_END
 
+#define BELLE_SIP_INVOKE_LISTENERS_REVERSE_ARG1_ARG2(list,interface_name,method,arg1,arg2) \
+			__BELLE_SIP_INVOKE_LISTENER_REVERSE_BEGIN(list,interface_name,method)\
+			method(__obj,arg1,arg2);\
+			__BELLE_SIP_INVOKE_LISTENER_END
+
 #define BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2_ARG3(list,interface_name,method,arg1,arg2,arg3) \
 			__BELLE_SIP_INVOKE_LISTENER_BEGIN(list,interface_name)\
 			method(__obj,arg1,arg2,arg3);\
@@ -211,6 +226,9 @@ BELLE_SIP_DECLARE_VPTR(belle_sip_header_event_t);
 BELLE_SIP_DECLARE_VPTR(belle_sip_header_supported_t);
 BELLE_SIP_DECLARE_VPTR(belle_sip_header_content_disposition_t);
 BELLE_SIP_DECLARE_VPTR(belle_sip_header_accept_t);
+BELLE_SIP_DECLARE_VPTR(belle_sip_header_reason_t);
+BELLE_SIP_DECLARE_VPTR(belle_sip_header_authentication_info_t);
+
 
 BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_resolver_context_t,belle_sip_source_t)
 	void (*cancel)(belle_sip_resolver_context_t *);
@@ -535,11 +553,11 @@ struct belle_sip_stack{
 	unsigned char dns_search_enabled;
 };
 
-BELLESIP_INTERNAL_EXPORT belle_sip_hop_t* belle_sip_hop_new(const char* transport, const char *cname, const char* host,int port);
-BELLESIP_INTERNAL_EXPORT belle_sip_hop_t* belle_sip_hop_new_from_uri(const belle_sip_uri_t *uri);
-BELLESIP_INTERNAL_EXPORT belle_sip_hop_t* belle_sip_hop_new_from_generic_uri(const belle_generic_uri_t *uri);
+BELLESIP_EXPORT belle_sip_hop_t* belle_sip_hop_new(const char* transport, const char *cname, const char* host,int port);
+BELLESIP_EXPORT belle_sip_hop_t* belle_sip_hop_new_from_uri(const belle_sip_uri_t *uri);
+BELLESIP_EXPORT belle_sip_hop_t* belle_sip_hop_new_from_generic_uri(const belle_generic_uri_t *uri);
 
-BELLESIP_INTERNAL_EXPORT belle_sip_hop_t * belle_sip_stack_get_next_hop(belle_sip_stack_t *stack, belle_sip_request_t *req);
+BELLESIP_EXPORT belle_sip_hop_t * belle_sip_stack_get_next_hop(belle_sip_stack_t *stack, belle_sip_request_t *req);
 
 /*
  belle_sip_provider_t
@@ -561,12 +579,12 @@ struct belle_sip_provider{
 	unsigned short unconditional_answer;
 };
 
-BELLESIP_INTERNAL_EXPORT belle_sip_provider_t *belle_sip_provider_new(belle_sip_stack_t *s, belle_sip_listening_point_t *lp);
+BELLESIP_EXPORT belle_sip_provider_t *belle_sip_provider_new(belle_sip_stack_t *s, belle_sip_listening_point_t *lp);
 void belle_sip_provider_add_client_transaction(belle_sip_provider_t *prov, belle_sip_client_transaction_t *t);
 belle_sip_client_transaction_t *belle_sip_provider_find_matching_client_transaction(belle_sip_provider_t *prov, belle_sip_response_t *resp);
 void belle_sip_provider_remove_client_transaction(belle_sip_provider_t *prov, belle_sip_client_transaction_t *t);
 void belle_sip_provider_add_server_transaction(belle_sip_provider_t *prov, belle_sip_server_transaction_t *t);
-BELLESIP_INTERNAL_EXPORT belle_sip_server_transaction_t * belle_sip_provider_find_matching_server_transaction(belle_sip_provider_t *prov,belle_sip_request_t *req);
+BELLESIP_EXPORT belle_sip_server_transaction_t * belle_sip_provider_find_matching_server_transaction(belle_sip_provider_t *prov,belle_sip_request_t *req);
 void belle_sip_provider_remove_server_transaction(belle_sip_provider_t *prov, belle_sip_server_transaction_t *t);
 void belle_sip_provider_set_transaction_terminated(belle_sip_provider_t *p, belle_sip_transaction_t *t);
 void *belle_sip_transaction_get_application_data_internal(const belle_sip_transaction_t *t);
@@ -579,7 +597,7 @@ void belle_sip_provider_remove_internal_sip_listener(belle_sip_provider_t *p, be
 belle_sip_client_transaction_t * belle_sip_provider_find_matching_client_transaction_from_req(belle_sip_provider_t *prov, belle_sip_request_t *req);
 belle_sip_dialog_t *belle_sip_provider_find_dialog_from_message(belle_sip_provider_t *prov, belle_sip_message_t *msg, int as_uas);
 /*for testing purpose only:*/
-BELLESIP_INTERNAL_EXPORT void belle_sip_provider_dispatch_message(belle_sip_provider_t *prov, belle_sip_message_t *msg);
+BELLESIP_EXPORT void belle_sip_provider_dispatch_message(belle_sip_provider_t *prov, belle_sip_message_t *msg);
 
 typedef struct listener_ctx{
 	belle_sip_listener_t *listener;
@@ -974,16 +992,16 @@ belle_sip_refresher_t* belle_sip_refresher_new(belle_sip_client_transaction_t* t
  * returns a char, even if entry is escaped*/
 size_t belle_sip_get_char (const char*a,char*out);
 /*return an escaped string*/
-BELLESIP_INTERNAL_EXPORT	char* belle_sip_uri_to_escaped_username(const char* buff) ;
-BELLESIP_INTERNAL_EXPORT	char* belle_sip_uri_to_escaped_userpasswd(const char* buff) ;
-BELLESIP_INTERNAL_EXPORT	char* belle_sip_uri_to_escaped_parameter(const char* buff) ;
-BELLESIP_INTERNAL_EXPORT	char* belle_sip_uri_to_escaped_header(const char* buff) ;
+BELLESIP_EXPORT	char* belle_sip_uri_to_escaped_username(const char* buff) ;
+BELLESIP_EXPORT	char* belle_sip_uri_to_escaped_userpasswd(const char* buff) ;
+BELLESIP_EXPORT	char* belle_sip_uri_to_escaped_parameter(const char* buff) ;
+BELLESIP_EXPORT	char* belle_sip_uri_to_escaped_header(const char* buff) ;
 
 
 /*(uri RFC 2396)*/
 
-BELLESIP_INTERNAL_EXPORT char* belle_generic_uri_to_escaped_query(const char* buff);
-BELLESIP_INTERNAL_EXPORT char* belle_generic_uri_to_escaped_path(const char* buff);
+BELLESIP_EXPORT char* belle_generic_uri_to_escaped_query(const char* buff);
+BELLESIP_EXPORT char* belle_generic_uri_to_escaped_path(const char* buff);
 
 #define BELLE_SIP_SOCKET_TIMEOUT 30000
 
@@ -1019,7 +1037,7 @@ belle_sip_header_extension_t* belle_sip_header_extension_new(void);
 
 belle_sip_header_extension_t* belle_sip_header_extension_parse (const char* extension) ;
 belle_sip_header_extension_t* belle_sip_header_extension_create (const char* name,const char* value);
-BELLESIP_INTERNAL_EXPORT const char* belle_sip_header_extension_get_value(const belle_sip_header_extension_t* extension);
+BELLESIP_EXPORT const char* belle_sip_header_extension_get_value(const belle_sip_header_extension_t* extension);
 void belle_sip_header_extension_set_value(belle_sip_header_extension_t* extension,const char* value);
 #define BELLE_SIP_HEADER_EXTENSION(t) BELLE_SIP_CAST(t,belle_sip_header_extension_t)
 
@@ -1070,4 +1088,8 @@ void belle_sip_multipart_body_handler_progress_cb(belle_sip_body_handler_t *obj,
  */
 belle_sip_list_t *belle_sip_parse_directory(const char *path, const char *file_type);
 
+typedef struct authorization_context authorization_context_t;
+BELLESIP_EXPORT void belle_sip_authorization_destroy(authorization_context_t* object);
+
+
 #endif
diff --git a/src/belle_sip_resolver.c b/src/belle_sip_resolver.c
index dfbdb29..a68a63d 100644
--- a/src/belle_sip_resolver.c
+++ b/src/belle_sip_resolver.c
@@ -18,8 +18,10 @@
 
 #include "belle_sip_internal.h"
 #include "dns.h"
+#include <bctoolbox/defs.h>
 
 #include <stdlib.h>
+#include <stdint.h>
 #ifdef __APPLE__
 #include "TargetConditionals.h"
 #endif
@@ -51,7 +53,7 @@ struct belle_sip_dns_srv{
 	belle_sip_combined_resolver_context_t *root_resolver;/* used internally to combine SRV and A queries*/
 	belle_sip_resolver_context_t *a_resolver; /* used internally to combine SRV and A queries*/
 	struct addrinfo *a_results; /* used internally to combine SRV and A queries*/
-	
+
 };
 
 static void belle_sip_dns_srv_destroy(belle_sip_dns_srv_t *obj){
@@ -102,6 +104,7 @@ BELLE_SIP_INSTANCIATE_VPTR(belle_sip_dns_srv_t, belle_sip_object_t,belle_sip_dns
 struct belle_sip_resolver_context{
 	belle_sip_source_t source;
 	belle_sip_stack_t *stack;
+	uint32_t min_ttl;
 	uint8_t notified;
 	uint8_t cancelled;
 	uint8_t pad[2];
@@ -167,6 +170,7 @@ struct belle_sip_dual_resolver_context{
 
 void belle_sip_resolver_context_init(belle_sip_resolver_context_t *obj, belle_sip_stack_t *stack){
 	obj->stack=stack;
+	obj->min_ttl = UINT32_MAX;
 	belle_sip_init_sockets(); /* Need to be called for DNS resolution to work on Windows platform. */
 }
 
@@ -195,10 +199,10 @@ static struct dns_resolv_conf *resconf(belle_sip_simple_resolver_context_t *ctx)
 		belle_sip_error("%s dns_resconf_open error: %s", __FUNCTION__, dns_strerror(error));
 		return NULL;
 	}
-	
+
 	path = belle_sip_stack_get_dns_resolv_conf_file(ctx->base.stack);
 	servers = ctx->base.stack->dns_servers;
-	
+
 	if (servers){
 		belle_sip_message("%s using application supplied dns server list.", __FUNCTION__);
 		error = dns_resconf_nameservers_from_list(ctx->resconf, servers);
@@ -218,7 +222,7 @@ static struct dns_resolv_conf *resconf(belle_sip_simple_resolver_context_t *ctx)
 		if (error) {
 			belle_sip_error("%s dns_resconf_loadwin error", __FUNCTION__);
 		}
-#elif defined(ANDROID)
+#elif defined(__ANDROID__)
 		error = dns_resconf_loadandroid(ctx->resconf);
 		if (error) {
 			belle_sip_error("%s dns_resconf_loadandroid error", __FUNCTION__);
@@ -250,13 +254,13 @@ static struct dns_resolv_conf *resconf(belle_sip_simple_resolver_context_t *ctx)
 			return NULL;
 		}
 	}
-	
+
 	if (error==0){
 		char ip[64];
 		char serv[10];
 		int using_ipv6=FALSE;
 		size_t i;
-		
+
 		belle_sip_message("Resolver is using DNS server(s):");
 		for(i=0;i<sizeof(ctx->resconf->nameserver)/sizeof(ctx->resconf->nameserver[0]);++i){
 			struct sockaddr *ns_addr=(struct sockaddr*)&ctx->resconf->nameserver[i];
@@ -339,7 +343,7 @@ static belle_sip_dns_srv_t *srv_elect_one(belle_sip_list_t *srv_list){
 	belle_sip_list_t *elem;
 	belle_sip_dns_srv_t *srv;
 	int rand_number;
-	
+
 	for(elem=srv_list;elem!=NULL;elem=elem->next){
 		srv=(belle_sip_dns_srv_t*)elem->data;
 		sum+=srv->weight;
@@ -417,11 +421,11 @@ static void simple_resolver_context_notify(belle_sip_resolver_context_t *obj) {
 #if USE_GETADDRINFO_FALLBACK
 		if (ctx->getaddrinfo_ai_list != NULL) ai_list = &ctx->getaddrinfo_ai_list;
 #endif
-		ctx->cb(ctx->cb_data, ctx->name, *ai_list);
+		ctx->cb(ctx->cb_data, ctx->name, *ai_list, BELLE_SIP_RESOLVER_CONTEXT(obj)->min_ttl);
 		*ai_list = NULL;
 	} else if (ctx->type == DNS_T_SRV) {
 		ctx->srv_list = srv_select_by_weight(ctx->srv_list);
-		ctx->srv_cb(ctx->srv_cb_data, ctx->name, ctx->srv_list);
+		ctx->srv_cb(ctx->srv_cb_data, ctx->name, ctx->srv_list, BELLE_SIP_RESOLVER_CONTEXT(obj)->min_ttl);
 	}
 }
 
@@ -431,7 +435,7 @@ static void dual_resolver_context_notify(belle_sip_resolver_context_t *obj) {
 	results = ai_list_append(results, ctx->a_results);
 	ctx->a_results = NULL;
 	ctx->aaaa_results = NULL;
-	ctx->cb(ctx->cb_data, ctx->name, results);
+	ctx->cb(ctx->cb_data, ctx->name, results, BELLE_SIP_RESOLVER_CONTEXT(obj)->min_ttl);
 }
 
 static void combined_resolver_context_cleanup(belle_sip_combined_resolver_context_t *ctx) {
@@ -449,7 +453,7 @@ static void combined_resolver_context_cleanup(belle_sip_combined_resolver_contex
 
 static void combined_resolver_context_notify(belle_sip_resolver_context_t *obj) {
 	belle_sip_combined_resolver_context_t *ctx = BELLE_SIP_COMBINED_RESOLVER_CONTEXT(obj);
-	ctx->cb(ctx->cb_data, ctx->name, ctx->final_results);
+	ctx->cb(ctx->cb_data, ctx->name, ctx->final_results, BELLE_SIP_RESOLVER_CONTEXT(obj)->min_ttl);
 	ctx->final_results = NULL;
 	combined_resolver_context_cleanup(ctx);
 }
@@ -458,7 +462,7 @@ static void append_dns_result(belle_sip_simple_resolver_context_t *ctx, struct a
 	char host[NI_MAXHOST + 1];
 	int gai_err;
 	int family=ctx->family;
-	
+
 	if ((gai_err=bctbx_getnameinfo(addr, addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST)) != 0){
 		belle_sip_error("append_dns_result(): getnameinfo() failed: %s",gai_strerror(gai_err));
 		return;
@@ -482,7 +486,7 @@ static int resolver_process_data(belle_sip_simple_resolver_context_t *ctx, unsig
 		belle_sip_warning("Simulating DNS timeout");
 		simulated_timeout=1;
 	}
-	
+
 	if (simulated_timeout || ((revents & BELLE_SIP_EVENT_TIMEOUT) && ((int)(belle_sip_time_ms()-ctx->start_time)>=timeout))) {
 		belle_sip_error("%s timed-out", __FUNCTION__);
 		belle_sip_resolver_context_notify(BELLE_SIP_RESOLVER_CONTEXT(ctx));
@@ -514,6 +518,7 @@ static int resolver_process_data(belle_sip_simple_resolver_context_t *ctx, unsig
 					sin6.sin6_family = AF_INET6;
 					sin6.sin6_port = ctx->port;
 					append_dns_result(ctx,&ctx->ai_list,(struct sockaddr*)&sin6,sizeof(sin6));
+					if (rr.ttl < BELLE_SIP_RESOLVER_CONTEXT(ctx)->min_ttl) BELLE_SIP_RESOLVER_CONTEXT(ctx)->min_ttl = rr.ttl;
 				} else if ((ctx->type == DNS_T_A) && (rr.class == DNS_C_IN) && (rr.type == DNS_T_A)) {
 					struct dns_a *a = &any.a;
 					struct sockaddr_in sin;
@@ -522,6 +527,7 @@ static int resolver_process_data(belle_sip_simple_resolver_context_t *ctx, unsig
 					sin.sin_family = AF_INET;
 					sin.sin_port = ctx->port;
 					append_dns_result(ctx,&ctx->ai_list,(struct sockaddr*)&sin,sizeof(sin));
+					if (rr.ttl < BELLE_SIP_RESOLVER_CONTEXT(ctx)->min_ttl) BELLE_SIP_RESOLVER_CONTEXT(ctx)->min_ttl = rr.ttl;
 				} else if ((ctx->type == DNS_T_SRV) && (rr.class == DNS_C_IN) && (rr.type == DNS_T_SRV)) {
 					char host[NI_MAXHOST + 1];
 					struct dns_srv *srv = &any.srv;
@@ -529,6 +535,7 @@ static int resolver_process_data(belle_sip_simple_resolver_context_t *ctx, unsig
 					snprintf(host, sizeof(host), "[target:%s port:%d prio:%d weight:%d]", srv->target, srv->port, srv->priority, srv->weight);
 					ctx->srv_list = belle_sip_list_insert_sorted(ctx->srv_list, belle_sip_object_ref(b_srv), srv_compare_prio);
 					belle_sip_message("SRV %s resolved to %s", ctx->name, host);
+					if (rr.ttl < BELLE_SIP_RESOLVER_CONTEXT(ctx)->min_ttl) BELLE_SIP_RESOLVER_CONTEXT(ctx)->min_ttl = rr.ttl;
 				}
 			}
 		}
@@ -536,6 +543,9 @@ static int resolver_process_data(belle_sip_simple_resolver_context_t *ctx, unsig
 #ifdef USE_GETADDRINFO_FALLBACK
 		ctx->getaddrinfo_cancelled = TRUE;
 #endif
+		if (dns_res_was_asymetric(ctx->R)){
+			belle_sip_warning("DNS answer was not received from the DNS server IP address the request was sent to. This seems to be a known issue with NAT64 networks created by Apple computers.");
+		}
 		belle_sip_resolver_context_notify(BELLE_SIP_RESOLVER_CONTEXT(ctx));
 		return BELLE_SIP_STOP;
 	}
@@ -662,7 +672,7 @@ static int _resolver_send_query(belle_sip_simple_resolver_context_t *ctx) {
 static int resolver_process_data_delayed(belle_sip_simple_resolver_context_t *ctx, unsigned int revents) {
 	int err=_resolver_send_query(ctx);
 	if (err==0) return BELLE_SIP_CONTINUE;
-	
+
 	return BELLE_SIP_STOP;
 }
 
@@ -684,6 +694,11 @@ static int _resolver_start_query(belle_sip_simple_resolver_context_t *ctx) {
 		return -1;
 
 	memset(&opts, 0, sizeof opts);
+	
+	/* When there are IPv6 nameservers, allow responses to arrive from an IP address that is not the IP address to which the request was sent originally.
+		* Mac' NAT64 network tend to do this sometimes.*/
+	opts.udp_uses_connect = ctx->resconf->iface.ss_family != AF_INET6;
+	if (!opts.udp_uses_connect) belle_sip_message("Resolver is not using connect().");
 
 	if (!(ctx->R = dns_res_open(ctx->resconf, ctx->hosts, dns_hints_mortal(dns_hints_local(ctx->resconf, &error)), cache(ctx), &opts, &error))) {
 		belle_sip_error("%s dns_res_open error [%s]: %s", __FUNCTION__, ctx->name, dns_strerror(error));
@@ -908,17 +923,18 @@ static char * srv_prefix_from_service_and_transport(const char *service, const c
 	return belle_sip_strdup_printf("_%s._udp.", service);
 }
 
-static void process_a_fallback_result(void *data, const char *name, struct addrinfo *ai_list){
+static void process_a_fallback_result(void *data, const char *name, struct addrinfo *ai_list, uint32_t ttl){
 	belle_sip_combined_resolver_context_t *ctx=(belle_sip_combined_resolver_context_t *)data;
 	ctx->final_results=ai_list;
 	belle_sip_resolver_context_notify(BELLE_SIP_RESOLVER_CONTEXT(ctx));
 }
 
-static void combined_resolver_context_check_finished(belle_sip_combined_resolver_context_t *obj){
+static void combined_resolver_context_check_finished(belle_sip_combined_resolver_context_t *obj, uint32_t ttl){
 	belle_sip_list_t *elem;
 	struct addrinfo *final=NULL;
 	unsigned char finished=TRUE;
-	
+
+	if (ttl < BELLE_SIP_RESOLVER_CONTEXT(obj)->min_ttl) BELLE_SIP_RESOLVER_CONTEXT(obj)->min_ttl = ttl;
 	for(elem=obj->srv_results;elem!=NULL;elem=elem->next){
 		belle_sip_dns_srv_t *srv=(belle_sip_dns_srv_t*)elem->data;
 		if (!srv->a_done) {
@@ -940,12 +956,13 @@ static void combined_resolver_context_check_finished(belle_sip_combined_resolver
 	}
 }
 
-static void process_a_from_srv(void *data, const char *name, struct addrinfo *ai_list){
+static void process_a_from_srv(void *data, const char *name, struct addrinfo *ai_list, uint32_t ttl){
 	belle_sip_dns_srv_t *srv=(belle_sip_dns_srv_t*)data;
 	srv->a_results=ai_list;
 	srv->a_done=TRUE;
 	belle_sip_message("A query finished for srv result [%s]",srv->target);
-	combined_resolver_context_check_finished(srv->root_resolver);
+	if (ttl < BELLE_SIP_RESOLVER_CONTEXT(srv->root_resolver)->min_ttl) BELLE_SIP_RESOLVER_CONTEXT(srv->root_resolver)->min_ttl = ttl;
+	combined_resolver_context_check_finished(srv->root_resolver, ttl);
 }
 
 static void srv_resolve_a(belle_sip_combined_resolver_context_t *obj, belle_sip_dns_srv_t *srv){
@@ -961,10 +978,11 @@ static void srv_resolve_a(belle_sip_combined_resolver_context_t *obj, belle_sip_
 	belle_sip_object_unref(srv);
 }
 
-static void process_srv_results(void *data, const char *name, belle_sip_list_t *srv_results){
+static void process_srv_results(void *data, const char *name, belle_sip_list_t *srv_results, uint32_t ttl){
 	belle_sip_combined_resolver_context_t *ctx=(belle_sip_combined_resolver_context_t *)data;
 	/*take a ref here, because the A resolution might succeed synchronously and terminate the context before exiting this function*/
 	belle_sip_object_ref(ctx);
+	if (ttl < BELLE_SIP_RESOLVER_CONTEXT(data)->min_ttl) BELLE_SIP_RESOLVER_CONTEXT(data)->min_ttl = ttl;
 	if (srv_results){
 		belle_sip_list_t *elem;
 		/* take a ref of each srv_results because the last A resolution may terminate synchronously
@@ -1014,7 +1032,7 @@ belle_sip_resolver_context_t * belle_sip_stack_resolve(belle_sip_stack_t *stack,
 		return BELLE_SIP_RESOLVER_CONTEXT(ctx);
 	} else {
 		/* There is no resolve to be done */
-		cb(data, name, res);
+		cb(data, name, res, UINT32_MAX);
 		return NULL;
 	}
 }
@@ -1052,14 +1070,14 @@ static void dual_resolver_context_check_finished(belle_sip_dual_resolver_context
 	}
 }
 
-static void on_ipv4_results(void *data, const char *name, struct addrinfo *ai_list) {
+static void on_ipv4_results(void *data, const char *name, struct addrinfo *ai_list, uint32_t ttl) {
 	belle_sip_dual_resolver_context_t *ctx = BELLE_SIP_DUAL_RESOLVER_CONTEXT(data);
 	ctx->a_results = ai_list;
 	ctx->a_notified = TRUE;
 	dual_resolver_context_check_finished(ctx);
 }
 
-static void on_ipv6_results(void *data, const char *name, struct addrinfo *ai_list) {
+static void on_ipv6_results(void *data, const char *name, struct addrinfo *ai_list, uint32_t ttl) {
 	belle_sip_dual_resolver_context_t *ctx = BELLE_SIP_DUAL_RESOLVER_CONTEXT(data);
 	ctx->aaaa_results = ai_list;
 	ctx->aaaa_notified = TRUE;
@@ -1095,6 +1113,7 @@ belle_sip_resolver_context_t * belle_sip_stack_resolve_a(belle_sip_stack_t *stac
 		switch(family){
 			case AF_UNSPEC:
 				family=AF_INET6;
+				BCTBX_NO_BREAK; /*intentionally no break*/
 			case AF_INET6:
 				return belle_sip_stack_resolve_dual(stack,name,port,cb,data);
 				break;
@@ -1106,7 +1125,7 @@ belle_sip_resolver_context_t * belle_sip_stack_resolve_a(belle_sip_stack_t *stac
 		}
 	} else {
 		/* There is no resolve to be done */
-		cb(data, name, res);
+		cb(data, name, res, UINT32_MAX);
 	}
 	return NULL;
 }
@@ -1148,33 +1167,33 @@ It works on all platform except for windows using ipv6 sockets. TODO: find a wor
 */
 int belle_sip_get_src_addr_for(const struct sockaddr *dest, socklen_t destlen, struct sockaddr *src, socklen_t *srclen, int local_port){
 	int af_type=dest->sa_family;
-	int sock=(int)socket(af_type,SOCK_DGRAM,IPPROTO_UDP);
+	int sock=(int)bctbx_socket(af_type,SOCK_DGRAM,IPPROTO_UDP);
 	int ret = 0;
-	
+
 	if (sock==(belle_sip_socket_t)-1){
 		if (af_type == AF_INET){
 			belle_sip_fatal("Could not create socket: %s",belle_sip_get_socket_error_string());
 		}
 		goto fail;
 	}
-	
+
 	if (af_type==AF_INET6 && (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6*)dest)->sin6_addr))){
 		/*this is actually required only for windows, who is unable to provide an ipv4 mapped local address if the remote is ipv4 mapped,
 		and unable to provide a correct local address if the remote address is true ipv6 address when in dual stack mode*/
 		belle_sip_socket_enable_dual_stack(sock);
 	}
-	
-	if (connect(sock,dest,destlen)==-1){
+	if (bctbx_connect(sock,dest,destlen)==-1){
+	//if (connect(sock,dest,destlen)==-1){
 		ret = -get_socket_error();
-		belle_sip_error("belle_sip_get_src_addr_for: connect() failed: %s",belle_sip_get_socket_error_string_from_code(-ret));
+		belle_sip_error("belle_sip_get_src_addr_for: bctbx_connect() failed: %s",belle_sip_get_socket_error_string_from_code(-ret));
 		goto fail;
 	}
-	if (getsockname(sock,src,srclen)==-1){
+	if (bctbx_getsockname(sock,src,srclen)==-1){
 		ret = -get_socket_error();
-		belle_sip_error("belle_sip_get_src_addr_for: getsockname() failed: %s",belle_sip_get_socket_error_string_from_code(-ret));
+		belle_sip_error("belle_sip_get_src_addr_for: bctbx_getsockname() failed: %s",belle_sip_get_socket_error_string_from_code(-ret));
 		goto fail;
 	}
-	
+
 	if (af_type==AF_INET6){
 		struct sockaddr_in6 *sin6=(struct sockaddr_in6*)src;
 		sin6->sin6_port=htons(local_port);
@@ -1182,7 +1201,7 @@ int belle_sip_get_src_addr_for(const struct sockaddr *dest, socklen_t destlen, s
 		struct sockaddr_in *sin=(struct sockaddr_in*)src;
 		sin->sin_port=htons(local_port);
 	}
-	
+
 	belle_sip_close_socket(sock);
 	return ret;
 fail:
diff --git a/src/belle_sip_uri_impl.c b/src/belle_sip_uri_impl.c
index 6f8d370..23615f3 100644
--- a/src/belle_sip_uri_impl.c
+++ b/src/belle_sip_uri_impl.c
@@ -501,3 +501,6 @@ int belle_sip_uri_check_components_from_context(const belle_sip_uri_t* uri,const
 
 
 }
+/*fast uri implemenation*/
+typedef belle_sip_uri_t belle_sip_fast_uri_t;
+BELLE_SIP_PARSE(fast_uri);
diff --git a/src/belle_sip_utils.c b/src/belle_sip_utils.c
index 40670ff..629421c 100644
--- a/src/belle_sip_utils.c
+++ b/src/belle_sip_utils.c
@@ -22,6 +22,7 @@
 #include <stdlib.h>
 #include <sys/stat.h>
 #include "belle_sip_internal.h"
+#include "bctoolbox/parser.h"
 
 #include "clock_gettime.h" /*for apple*/
 
@@ -89,7 +90,7 @@ static int find_best_clock_id (void) {
 #if 0
 	struct timespec ts;
 	static int clock_id=-1;
-#ifndef ANDROID
+#ifndef __ANDROID__
 #define DEFAULT_CLOCK_MODE CLOCK_MONOTONIC
 #else
 #define DEFAULT_CLOCK_MODE CLOCK_REALTIME /*monotonic clock stop during sleep mode*/
@@ -258,6 +259,12 @@ unsigned int belle_sip_random(void){
 #endif
 }
 
+
+void belle_sip_set_socket_api(bctbx_vsocket_api_t* my_api){
+
+	bctbx_vsocket_api_set_default(my_api);
+}
+
 static const char *symbols="aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789-~";
 
 /**
@@ -365,52 +372,14 @@ void belle_sip_util_copy_headers(belle_sip_message_t *orig, belle_sip_message_t
 	}
 }
 
-static int is_escaped_char(const char *a){
-	return a[0] == '%' && a[1] != '\0' && a[2] != '\0';
-}
-
-size_t belle_sip_get_char (const char*a, char*out) {
-	if (is_escaped_char(a)) {
-		unsigned int tmp;
-		sscanf(a+1,"%02x",&tmp);
-		*out=(char)tmp;
-		return 3;
-	} else {
-		*out=*a;
-		return 1;
-	}
-}
 
 char* belle_sip_to_unescaped_string(const char* buff) {
-	char *output_buff=belle_sip_malloc(strlen(buff)+1);
-	size_t i;
-	size_t out_buff_index=0;
-
-	for(i=0; buff[i]!='\0'; out_buff_index++) {
-		i+=belle_sip_get_char(buff+i,output_buff+out_buff_index);
-	}
-	output_buff[out_buff_index]='\0';
-	return output_buff;
+	return bctbx_unescaped_string(buff);
 }
 
-#define BELLE_SIP_NO_ESCAPES_SIZE 257
-static void noescapes_add_list(char noescapes[BELLE_SIP_NO_ESCAPES_SIZE], const char *allowed) {
-	while (*allowed) {
-		noescapes[(unsigned int) *allowed] = 1;
-		++allowed;
-	}
+size_t belle_sip_get_char(const char* a, char *b) {
+	return bctbx_get_char(a,b);
 }
-
-static void noescapes_add_range(char noescapes[BELLE_SIP_NO_ESCAPES_SIZE], char first, char last) {
-	memset(noescapes + (unsigned int)first, 1, last-first+1);
-}
-
-static void noescapes_add_alfanums(char noescapes[BELLE_SIP_NO_ESCAPES_SIZE]) {
-	noescapes_add_range(noescapes, '0', '9');
-	noescapes_add_range(noescapes, 'A', 'Z');
-	noescapes_add_range(noescapes, 'a', 'z');
-}
-
 /*
 static void print_noescapes_map(char noescapes[BELLE_SIP_NO_ESCAPES_SIZE], const char *name) {
 	unsigned int i;
@@ -423,9 +392,9 @@ static void print_noescapes_map(char noescapes[BELLE_SIP_NO_ESCAPES_SIZE], const
 }
 */
 
-static const char *get_sip_uri_username_noescapes(void) {
-	static char noescapes[BELLE_SIP_NO_ESCAPES_SIZE] = {0};
-	if (noescapes[BELLE_SIP_NO_ESCAPES_SIZE-1] == 0) {
+static const bctbx_noescape_rules_t* get_sip_uri_username_noescapes(void) {
+	static bctbx_noescape_rules_t noescapes = {0};
+	if (noescapes[BCTBX_NOESCAPE_RULES_USER_INDEX] == 0) {
 		// concurrent initialization should not be an issue
 		/*user             =  1*( unreserved / escaped / user-unreserved )
 		 unreserved  =  alphanum / mark
@@ -433,39 +402,39 @@ static const char *get_sip_uri_username_noescapes(void) {
 		 / "(" / ")"
 		user-unreserved  =  "&" / "=" / "+" / "$" / "," / ";" / "?" / "/"
 		*/
-		noescapes_add_alfanums(noescapes);
+		bctbx_noescape_rules_add_alfanums(noescapes);
 		/*mark*/
-		noescapes_add_list(noescapes, "-_.!~*'()");
+		bctbx_noescape_rules_add_list(noescapes, "-_.!~*'()");
 		/*user-unreserved*/
-		noescapes_add_list(noescapes, "&=+$,;?/");
+		bctbx_noescape_rules_add_list(noescapes, "&=+$,;?/");
 
-		noescapes[BELLE_SIP_NO_ESCAPES_SIZE-1] = 1; // initialized
+		noescapes[BCTBX_NOESCAPE_RULES_USER_INDEX] = 1; // initialized
 //		print_noescapes_map(noescapes, "uri_username");
 	}
-	return noescapes;
+	return (const bctbx_noescape_rules_t*)&noescapes;/*gcc asks for a cast, clang not*/
 }
 /*
  *
  * password         =  *( unreserved / escaped /
                     "&" / "=" / "+" / "$" / "," )
  * */
-static const char *get_sip_uri_userpasswd_noescapes(void) {
-	static char noescapes[BELLE_SIP_NO_ESCAPES_SIZE] = {0};
-	if (noescapes[BELLE_SIP_NO_ESCAPES_SIZE-1] == 0) {
+static const bctbx_noescape_rules_t* get_sip_uri_userpasswd_noescapes(void) {
+	static bctbx_noescape_rules_t noescapes = {0};
+	if (noescapes[BCTBX_NOESCAPE_RULES_USER_INDEX] == 0) {
 		// unreserved
-		noescapes_add_alfanums(noescapes);
-		noescapes_add_list(noescapes, "-_.!~*'()");
-		noescapes_add_list(noescapes, "&=+$,");
+		bctbx_noescape_rules_add_alfanums(noescapes);
+		bctbx_noescape_rules_add_list(noescapes, "-_.!~*'()");
+		bctbx_noescape_rules_add_list(noescapes, "&=+$,");
 
-		noescapes[BELLE_SIP_NO_ESCAPES_SIZE-1] = 1; // initialized
+		noescapes[BCTBX_NOESCAPE_RULES_USER_INDEX] = 1; // initialized
 
 	}
-	return noescapes;
+	return (const bctbx_noescape_rules_t*)&noescapes;/*gcc asks for a cast, clang not*/
 }
 
-static const char *get_sip_uri_parameter_noescapes(void) {
-	static char noescapes[BELLE_SIP_NO_ESCAPES_SIZE] = {0};
-	if (noescapes[BELLE_SIP_NO_ESCAPES_SIZE-1] == 0) {
+static  const bctbx_noescape_rules_t* get_sip_uri_parameter_noescapes(void) {
+	static bctbx_noescape_rules_t  noescapes= {0};
+	if (noescapes[BCTBX_NOESCAPE_RULES_USER_INDEX] == 0) {
 		/*
 		 other-param       =  pname [ "=" pvalue ]
 		 pname             =  1*paramchar
@@ -481,23 +450,23 @@ static const char *get_sip_uri_parameter_noescapes(void) {
 		 */
 		//param-unreserved  =
 
-		noescapes_add_list(noescapes,"[]/:&+$");
+		bctbx_noescape_rules_add_list(noescapes,"[]/:&+$");
 
 		// token
-		noescapes_add_alfanums(noescapes);
-		noescapes_add_list(noescapes, "-.!%*_+`'~");
+		bctbx_noescape_rules_add_alfanums(noescapes);
+		bctbx_noescape_rules_add_list(noescapes, "-.!%*_+`'~");
 
 		// unreserved
-		noescapes_add_list(noescapes, "-_.!~*'()");
+		bctbx_noescape_rules_add_list(noescapes, "-_.!~*'()");
 
-		noescapes[BELLE_SIP_NO_ESCAPES_SIZE-1] = 1; // initialized
+		noescapes[BCTBX_NOESCAPE_RULES_USER_INDEX] = 1; // initialized
 //		print_noescapes_map(noescapes, "uri_parameter");
 	}
-	return noescapes;
+	return (const bctbx_noescape_rules_t*)&noescapes;/*gcc asks for a cast, clang not*/
 }
-static const char *get_sip_uri_header_noescapes(void) {
-	static char noescapes[BELLE_SIP_NO_ESCAPES_SIZE] = {0};
-	if (noescapes[BELLE_SIP_NO_ESCAPES_SIZE-1] == 0) {
+static const bctbx_noescape_rules_t* get_sip_uri_header_noescapes(void) {
+	static bctbx_noescape_rules_t  noescapes= {0};
+	if (noescapes[BCTBX_NOESCAPE_RULES_USER_INDEX] == 0) {
 		/*
 		 unreserved  =  alphanum / mark
 		 mark        =  "-" / "_" / "." / "!" / "~" / "*" / "'"
@@ -514,61 +483,37 @@ static const char *get_sip_uri_header_noescapes(void) {
 
 		// unreserved
 		//alphanum
-		noescapes_add_alfanums(noescapes);
+		bctbx_noescape_rules_add_alfanums(noescapes);
 		//mark
-		noescapes_add_list(noescapes, "-_.!~*'()");
+		bctbx_noescape_rules_add_list(noescapes, "-_.!~*'()");
 
-		noescapes_add_list(noescapes, "[]/?:+$");
+		bctbx_noescape_rules_add_list(noescapes, "[]/?:+$");
 		//hnv-unreserved
-		noescapes[BELLE_SIP_NO_ESCAPES_SIZE-1] = 1; // initialized
+		noescapes[BCTBX_NOESCAPE_RULES_USER_INDEX] = 1; // initialized
 //		print_noescapes_map(noescapes, "uri_parameter");
 	}
-	return noescapes;
+	return (const bctbx_noescape_rules_t*)&noescapes;/*gcc asks for a cast, clang not*/
 }
 
-static char* belle_sip_escape(const char* buff, const char *noescapes) {
-	size_t outbuf_size=strlen(buff);
-	size_t orig_size=outbuf_size;
-	char *output_buff=(char*)belle_sip_malloc(outbuf_size + 1);
-	int i;
-	size_t out_buff_index=0;
-
-	for(i=0; buff[i] != '\0'; i++) {
-		int c = ((unsigned char*)buff)[i];
-		if (outbuf_size < out_buff_index + 3){
-			// we will possibly add 3 chars
-			outbuf_size += MAX(orig_size/2,3);
-			output_buff = belle_sip_realloc(output_buff, outbuf_size + 1);
-		}
-		if (noescapes[c] == 1) {
-			output_buff[out_buff_index++]=c;
-		} else {
-			// this will write 3 characters
-			out_buff_index+=snprintf(output_buff+out_buff_index, outbuf_size +1 - out_buff_index, "%%%02x", c);
-		}
-	}
-	output_buff[out_buff_index]='\0';
-	return output_buff;
-}
 
 char* belle_sip_uri_to_escaped_username(const char* buff) {
-	return belle_sip_escape(buff, get_sip_uri_username_noescapes());
+	return bctbx_escape(buff, *get_sip_uri_username_noescapes());
 }
 char* belle_sip_uri_to_escaped_userpasswd(const char* buff) {
-	return belle_sip_escape(buff, get_sip_uri_userpasswd_noescapes());
+	return bctbx_escape(buff, *get_sip_uri_userpasswd_noescapes());
 }
 char* belle_sip_uri_to_escaped_parameter(const char* buff) {
-	return belle_sip_escape(buff, get_sip_uri_parameter_noescapes());
+	return bctbx_escape(buff, *get_sip_uri_parameter_noescapes());
 }
 char* belle_sip_uri_to_escaped_header(const char* buff) {
-	return belle_sip_escape(buff, get_sip_uri_header_noescapes());
+	return bctbx_escape(buff, *get_sip_uri_header_noescapes());
 }
 
 
 /*uri (I.E RFC 2396)*/
-static const char *get_generic_uri_query_noescapes(void) {
-	static char noescapes[BELLE_SIP_NO_ESCAPES_SIZE] = {0};
-	if (noescapes[BELLE_SIP_NO_ESCAPES_SIZE-1] == 0) {
+static const bctbx_noescape_rules_t *get_generic_uri_query_noescapes(void) {
+	static bctbx_noescape_rules_t  noescapes= {0};
+	if (noescapes[BCTBX_NOESCAPE_RULES_USER_INDEX] == 0) {
 		/*
 	    uric          = reserved | unreserved | escaped
 		reserved      = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
@@ -584,18 +529,18 @@ static const char *get_generic_uri_query_noescapes(void) {
 
 		*/
 		/*unreserved*/
-		noescapes_add_alfanums(noescapes);
+		bctbx_noescape_rules_add_alfanums(noescapes);
 		/*mark*/
-		noescapes_add_list(noescapes, "-_.!~*'()");
-		noescapes_add_list(noescapes, "=&"); // otherwise how to pass parameters?
-		noescapes[BELLE_SIP_NO_ESCAPES_SIZE-1] = 1; // initialized
+		bctbx_noescape_rules_add_list(noescapes, "-_.!~*'()");
+		bctbx_noescape_rules_add_list(noescapes, "=&"); // otherwise how to pass parameters?
+		noescapes[BCTBX_NOESCAPE_RULES_USER_INDEX] = 1; // initialized
 	}
-	return noescapes;
+	return (const bctbx_noescape_rules_t*)&noescapes;/*gcc asks for a cast, clang not*/
 }
 
-static const char *get_generic_uri_path_noescapes(void) {
-	static char noescapes[BELLE_SIP_NO_ESCAPES_SIZE] = {0};
-	if (noescapes[BELLE_SIP_NO_ESCAPES_SIZE-1] == 0) {
+static const bctbx_noescape_rules_t *get_generic_uri_path_noescapes(void) {
+	static bctbx_noescape_rules_t  noescapes= {0};
+	if (noescapes[BCTBX_NOESCAPE_RULES_USER_INDEX] == 0) {
 		/*
 	    3.3. Path Component
 
@@ -621,25 +566,25 @@ static const char *get_generic_uri_path_noescapes(void) {
 
 		*/
 		/*unreserved*/
-		noescapes_add_alfanums(noescapes);
+		bctbx_noescape_rules_add_alfanums(noescapes);
 		/*mark*/
-		noescapes_add_list(noescapes, "-_.!~*'()");
+		bctbx_noescape_rules_add_list(noescapes, "-_.!~*'()");
 		/*pchar*/
-		noescapes_add_list(noescapes, ":@&=+$,");
+		bctbx_noescape_rules_add_list(noescapes, ":@&=+$,");
 		/*;*/
-		noescapes_add_list(noescapes, ";");
-		noescapes_add_list(noescapes, "/");
+		bctbx_noescape_rules_add_list(noescapes, ";");
+		bctbx_noescape_rules_add_list(noescapes, "/");
 
-		noescapes[BELLE_SIP_NO_ESCAPES_SIZE-1] = 1; // initialized
+		noescapes[BCTBX_NOESCAPE_RULES_USER_INDEX] = 1; // initialized
 	}
-	return noescapes;
+	return (const bctbx_noescape_rules_t*)&noescapes;/*gcc asks for a cast, clang not*/
 }
 
 char* belle_generic_uri_to_escaped_query(const char* buff) {
-	return belle_sip_escape(buff, get_generic_uri_query_noescapes());
+	return bctbx_escape(buff, *get_generic_uri_query_noescapes());
 }
 char* belle_generic_uri_to_escaped_path(const char* buff) {
-	return belle_sip_escape(buff, get_generic_uri_path_noescapes());
+	return bctbx_escape(buff, *get_generic_uri_path_noescapes());
 }
 
 char* belle_sip_string_to_backslash_less_unescaped_string(const char* buff) {
@@ -731,7 +676,7 @@ belle_sip_list_t *belle_sip_parse_directory(const char *path, const char *file_t
 	}
 
 	/* loop on all directory files */
-    errno = 0;
+	errno = 0;
 	ent = readdir(dir);
 	while (ent != NULL) {
 		/* filter on file type if given */
diff --git a/src/bodyhandler.c b/src/bodyhandler.c
index d723571..3cfeb56 100644
--- a/src/bodyhandler.c
+++ b/src/bodyhandler.c
@@ -154,8 +154,9 @@ int belle_sip_body_handler_send_chunk(belle_sip_body_handler_t *obj, belle_sip_m
 	if (obj->expected_size!=0){
 		to_send=MIN(*size,obj->expected_size-obj->transfered_size);
 	}
-	if (to_send==0) {
-		// Ane eWouldBlock error added a call to the function, nothing to send so return
+	if (to_send==0 && obj->transfered_size==obj->expected_size) {
+		// An eWouldBlock error added a call to the function, nothing to send so return
+		// In some case to_send=0 because not buffer is available but sendings not finished.
 		belle_sip_message("body handler [%p] : Nothing to send",obj);
 		*size=0;
 		return BELLE_SIP_STOP;
diff --git a/src/channel.c b/src/channel.c
index 4aa32fd..82f0016 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -22,7 +22,7 @@
 #include <ctype.h>
 #include <wchar.h>
 
-#ifdef ANDROID
+#ifdef __ANDROID__
 #include "wakelock_internal.h"
 #endif
 
@@ -32,10 +32,9 @@
 #define BELLE_SIP_CHANNEL_INVOKE_SENDING_LISTENERS(channel,msg) \
 	BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(channel->full_listeners, belle_sip_channel_listener_t, on_sending, channel, msg)
 
-
 #define BELLE_SIP_CHANNEL_INVOKE_STATE_LISTENERS(channel,state) \
-	BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(channel->full_listeners, belle_sip_channel_listener_t, on_state_changed, channel, state) \
-	BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(channel->state_listeners, belle_sip_channel_listener_t, on_state_changed, channel, state) 
+	BELLE_SIP_INVOKE_LISTENERS_REVERSE_ARG1_ARG2(channel->full_listeners, belle_sip_channel_listener_t, on_state_changed, channel, state) \
+	BELLE_SIP_INVOKE_LISTENERS_REVERSE_ARG1_ARG2(channel->state_listeners, belle_sip_channel_listener_t, on_state_changed, channel, state) 
 
 
 static void channel_prepare_continue(belle_sip_channel_t *obj);
@@ -126,6 +125,10 @@ static void belle_sip_channel_destroy(belle_sip_channel_t *obj){
 		belle_sip_main_loop_remove_source(obj->stack->ml,obj->inactivity_timer);
 		belle_sip_object_unref(obj->inactivity_timer);
 	}
+	if (obj->dns_ttl_timer) {
+		belle_sip_main_loop_remove_source(obj->stack->ml, obj->dns_ttl_timer);
+		belle_sip_object_unref(obj->dns_ttl_timer);
+	}
 	if (obj->public_ip) belle_sip_free(obj->public_ip);
 	if (obj->outgoing_messages) belle_sip_list_free_with_data(obj->outgoing_messages,belle_sip_object_unref);
 	if (obj->incoming_messages) belle_sip_list_free_with_data(obj->incoming_messages,belle_sip_object_unref);
@@ -371,9 +374,10 @@ static int check_body(belle_sip_channel_t *obj){
 
 	obj->input_stream.content_length= content_length_header ? belle_sip_header_content_length_get_content_length(content_length_header) : 0;
 
-	if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(msg,belle_sip_response_t) || BELLE_SIP_OBJECT_IS_INSTANCE_OF(msg,belle_sip_request_t)){
-		expect_body=obj->input_stream.content_length>0;
-	}else{/*http*/
+	expect_body=obj->input_stream.content_length>0;
+	
+	if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(msg,belle_http_response_t) || BELLE_SIP_OBJECT_IS_INSTANCE_OF(msg,belle_http_request_t)){
+		/*http chunked mode handling*/
 		if (belle_sip_message_get_header_by_type(msg, belle_sip_header_content_type_t)!=NULL){
 			belle_sip_header_t *transfer_encoding=belle_sip_message_get_header(msg,"Transfer-Encoding");
 
@@ -1012,6 +1016,12 @@ static void belle_sip_channel_handle_error(belle_sip_channel_t *obj){
 
 int belle_sip_channel_notify_timeout(belle_sip_channel_t *obj){
 	const int too_long=60;
+	
+	if (obj->state != BELLE_SIP_CHANNEL_READY){
+		/*no need to notify the timeout if the channel is already in error or retry state*/
+		return FALSE;
+	}
+	
 	if ((int)(belle_sip_time_ms() - obj->last_recv_time) >= (too_long * 1000)){
 		belle_sip_message("A timeout related to this channel occured and no message received during last %i seconds. This channel is suspect, moving to error state",too_long);
 		channel_set_state(obj,BELLE_SIP_CHANNEL_ERROR);
@@ -1373,8 +1383,9 @@ static void channel_process_queue(belle_sip_channel_t *obj){
 	belle_sip_message_t *msg;
 	belle_sip_object_ref(obj);/* we need to ref ourself because code below may trigger our destruction*/
 
-	if (obj->out_state!=OUTPUT_STREAM_IDLE)
+	if (obj->out_state!=OUTPUT_STREAM_IDLE) {
 		_send_message(obj);
+	}
 
 	while((msg=channel_pop_outgoing(obj))!=NULL && obj->state==BELLE_SIP_CHANNEL_READY && obj->out_state==OUTPUT_STREAM_IDLE) {
 		send_message(obj, msg);
@@ -1411,16 +1422,57 @@ void belle_sip_channel_set_ready(belle_sip_channel_t *obj, const struct sockaddr
 	channel_process_queue(obj);
 }
 
-static void channel_res_done(void *data, const char *name, struct addrinfo *ai_list){
+static int channel_dns_ttl_timeout(void *data, unsigned int event) {
+	belle_sip_channel_t *obj = (belle_sip_channel_t *)data;
+	belle_sip_message("Channel [%p]: DNS TTL timeout reached.", obj);
+	obj->dns_ttl_timedout = TRUE;
+	return BELLE_SIP_STOP;
+}
+
+static bool_t addrinfo_in_list(const struct addrinfo *ai, const struct addrinfo *list) {
+	const struct addrinfo *item = list;
+	bool_t in_list = FALSE;
+	while (item != NULL) {
+		if ((ai->ai_family == item->ai_family) && (bctbx_sockaddr_equals(ai->ai_addr, item->ai_addr))) {
+			in_list = TRUE;
+			break;
+		}
+		item = item->ai_next;
+	}
+	return in_list;
+}
+
+static void channel_res_done(void *data, const char *name, struct addrinfo *ai_list, uint32_t ttl){
 	belle_sip_channel_t *obj=(belle_sip_channel_t*)data;
 	if (obj->resolver_ctx){
 		belle_sip_object_unref(obj->resolver_ctx);
 		obj->resolver_ctx=NULL;
 	}
 	if (ai_list){
-		obj->peer_list=obj->current_peer=ai_list;
-		channel_set_state(obj,BELLE_SIP_CHANNEL_RES_DONE);
+		if (!obj->current_peer) {
+			obj->peer_list=obj->current_peer=ai_list;
+			channel_set_state(obj,BELLE_SIP_CHANNEL_RES_DONE);
+		} else {
+			if (addrinfo_in_list(obj->current_peer, ai_list)) {
+				belle_sip_message("channel[%p]: DNS resolution returned the currently used address, continue using it", obj);
+				obj->peer_list = ai_list;
+				channel_set_state(obj, BELLE_SIP_CHANNEL_READY);
+			} else {
+				belle_sip_message("channel[%p]: DNS resolution returned an address different than the one being used, reconnect to the new address", obj);
+				obj->peer_list = obj->current_peer = ai_list;
+				belle_sip_channel_close(obj);
+				belle_sip_main_loop_do_later(obj->stack->ml, (belle_sip_callback_t)channel_connect_next, belle_sip_object_ref(obj));
+				channel_set_state(obj, BELLE_SIP_CHANNEL_RETRY);
+			}
+		}
 		channel_prepare_continue(obj);
+		if (!obj->dns_ttl_timer ) {
+			obj->dns_ttl_timer = belle_sip_main_loop_create_timeout(obj->stack->ml, channel_dns_ttl_timeout, obj, ttl * 1000, "Channel DNS TTL timer");
+		} else {
+			/* Restart the timer for new period. */
+			belle_sip_source_set_timeout(obj->dns_ttl_timer, ttl * 1000);
+			belle_sip_main_loop_add_source(obj->stack->ml, obj->dns_ttl_timer);
+		}
 	}else{
 		belle_sip_error("%s: DNS resolution failed for %s", __FUNCTION__, name);
 		channel_set_state(obj,BELLE_SIP_CHANNEL_ERROR);
@@ -1531,7 +1583,14 @@ belle_sip_channel_t *belle_sip_channel_find_from_list(belle_sip_list_t *l, int a
 	return chan;
 }
 
-#ifdef ANDROID
+void belle_sip_channel_check_dns_reusability(belle_sip_channel_t *obj) {
+	if (obj->dns_ttl_timedout) {
+		obj->dns_ttl_timedout = FALSE;
+		belle_sip_channel_resolve(obj);
+	}
+}
+
+#ifdef __ANDROID__
 
 unsigned long belle_sip_begin_background_task(const char *name, belle_sip_background_task_end_callback_t cb, void *data){
     return wake_lock_acquire(name);
diff --git a/src/channel.h b/src/channel.h
index f88e7ec..efcb302 100644
--- a/src/channel.h
+++ b/src/channel.h
@@ -112,6 +112,7 @@ struct belle_sip_channel{
 	belle_sip_channel_input_stream_t input_stream;
 	belle_sip_list_t* incoming_messages;
 	belle_sip_source_t *inactivity_timer;
+	belle_sip_source_t *dns_ttl_timer;
 	uint64_t last_recv_time;
 	int simulated_recv_return; /* used to simulate network error. 0= no data (disconnected) >0= do nothing -1= network error, 1500 special number to silently discard incoming buffer*/
 	unsigned long bg_task_id;
@@ -124,6 +125,7 @@ struct belle_sip_channel{
 	unsigned char soft_error; /*set when this channel enters ERROR state because of error detected in upper layer */
 	int stop_logging_buffer; /*log buffer content only if this is non binary data, and stop it at the first occurence*/
 	bool_t closed_by_remote; /*If the channel has been remotely closed*/
+	bool_t dns_ttl_timedout;
 };
 
 #define BELLE_SIP_CHANNEL(obj)		BELLE_SIP_CAST(obj,belle_sip_channel_t)
@@ -205,7 +207,12 @@ void belle_sip_channel_force_close(belle_sip_channel_t *obj);
 int belle_sip_channel_notify_timeout(belle_sip_channel_t *obj);
 
 /*Used by transaction layer to report a server having internal errors, so that we can retry with another IP (in case of DNS SRV)*/
-BELLESIP_INTERNAL_EXPORT void belle_sip_channel_notify_server_error(belle_sip_channel_t *obj);
+BELLESIP_EXPORT void belle_sip_channel_notify_server_error(belle_sip_channel_t *obj);
+
+/*
+ * Check if the DNS TTL has expired. If this is the case, set the channel status to RES_IN_PROGRESS.
+ */
+void belle_sip_channel_check_dns_reusability(belle_sip_channel_t *obj);
 
 BELLE_SIP_END_DECLS
 
diff --git a/src/dialog.c b/src/dialog.c
index 35d223a..a7c8293 100644
--- a/src/dialog.c
+++ b/src/dialog.c
@@ -17,6 +17,7 @@
 */
 
 #include "belle_sip_internal.h"
+#include <bctoolbox/defs.h>
 
 static void belle_sip_dialog_init_200Ok_retrans(belle_sip_dialog_t *obj, belle_sip_response_t *resp);
 static int belle_sip_dialog_handle_200Ok(belle_sip_dialog_t *obj, belle_sip_response_t *msg);
@@ -54,7 +55,7 @@ static void belle_sip_dialog_uninit(belle_sip_dialog_t *obj){
 }
 
 BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_dialog_t);
-BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_dialog_t) 
+BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_dialog_t)
 		BELLE_SIP_VPTR_INIT(belle_sip_dialog_t, belle_sip_object_t,TRUE),
 		(belle_sip_object_destroy_t)belle_sip_dialog_uninit,
 		NULL,
@@ -146,7 +147,7 @@ static int belle_sip_dialog_init_as_uas(belle_sip_dialog_t *obj, belle_sip_reque
 
 	/*remote party already set */
 	obj->local_party=(belle_sip_header_address_t*)belle_sip_object_ref(to);
-	
+
 	return 0;
 }
 
@@ -180,7 +181,7 @@ static int belle_sip_dialog_init_as_uac(belle_sip_dialog_t *obj, belle_sip_reque
 	    && belle_sip_uri_is_secure(requri)){
 		obj->is_secure=TRUE;
 	}
-	
+
 	obj->local_cseq=belle_sip_header_cseq_get_seq_number(cseq);
 	/*call id is already set */
 	/*local_tag is already set*/
@@ -189,7 +190,7 @@ static int belle_sip_dialog_init_as_uac(belle_sip_dialog_t *obj, belle_sip_reque
 	if (strcmp(belle_sip_request_get_method(req),"INVITE")==0){
 		set_last_out_invite(obj,req);
 	}
-	
+
 	return 0;
 }
 
@@ -208,7 +209,7 @@ int belle_sip_dialog_expired(const belle_sip_dialog_t *dialog){
 static int belle_sip_dialog_schedule_expiration(belle_sip_dialog_t *dialog, belle_sip_message_t *request){
 	belle_sip_header_expires_t *expires = belle_sip_message_get_header_by_type(request, belle_sip_header_expires_t);
 	int expires_value;
-	
+
 	if (!expires) return BELLE_SIP_CONTINUE;
 	expires_value = belle_sip_header_expires_get_expires(expires);
 	if (dialog->expiration_timer){
@@ -218,7 +219,7 @@ static int belle_sip_dialog_schedule_expiration(belle_sip_dialog_t *dialog, bell
 	}
 	belle_sip_message("belle_sip_dialog_schedule_expiration() dialog=%p expires_value=%i", dialog, expires_value);
 	if (expires_value == 0) return BELLE_SIP_STOP;
-	dialog->expiration_timer = belle_sip_main_loop_create_timeout(dialog->provider->stack->ml, 
+	dialog->expiration_timer = belle_sip_main_loop_create_timeout(dialog->provider->stack->ml,
 					(belle_sip_source_func_t) belle_sip_dialog_on_expired,
 					dialog,
 					expires_value * 1000,
@@ -282,7 +283,7 @@ int belle_sip_dialog_establish(belle_sip_dialog_t *obj, belle_sip_request_t *req
 		belle_sip_error("No to in response.");
 		return -1;
 	}
-	
+
 	if (!obj->is_server) {
 		belle_sip_header_contact_t *ct=belle_sip_message_get_header_by_type(resp,belle_sip_header_contact_t);
 		const belle_sip_list_t* elem;
@@ -301,7 +302,7 @@ int belle_sip_dialog_establish(belle_sip_dialog_t *obj, belle_sip_request_t *req
 			obj->route_set=belle_sip_list_prepend(obj->route_set,belle_sip_object_ref(belle_sip_header_route_create(
 																													(belle_sip_header_address_t*)elem->data)));
 		}
-		
+
 		check_route_set(obj->route_set);
 		/*via might be unknown at dialog creation*/
 		if (strcasecmp(belle_sip_header_via_get_protocol(via),"TLS")==0
@@ -360,11 +361,11 @@ static void belle_sip_dialog_init_200Ok_retrans(belle_sip_dialog_t *obj, belle_s
 	obj->timer_200Ok=belle_sip_timeout_source_new((belle_sip_source_func_t)dialog_on_200Ok_timer,obj,cfg->T1);
 	belle_sip_object_set_name((belle_sip_object_t*)obj->timer_200Ok,"dialog_200Ok_timer");
 	belle_sip_main_loop_add_source(obj->provider->stack->ml,obj->timer_200Ok);
-	
+
 	obj->timer_200Ok_end=belle_sip_timeout_source_new((belle_sip_source_func_t)dialog_on_200Ok_end,obj,cfg->T1*64);
 	belle_sip_object_set_name((belle_sip_object_t*)obj->timer_200Ok_end,"dialog_200Ok_timer_end");
 	belle_sip_main_loop_add_source(obj->provider->stack->ml,obj->timer_200Ok_end);
-	
+
 	obj->last_200Ok=(belle_sip_response_t*)belle_sip_object_ref(resp);
 }
 
@@ -389,13 +390,13 @@ void belle_sip_dialog_stop_200Ok_retrans(belle_sip_dialog_t *obj){
 /* returns true if the dialog is terminated by the NOTIFY request or response*/
 static int belle_sip_dialog_should_terminate_by_notify(belle_sip_dialog_t *obj, belle_sip_transaction_t* transaction, int as_uas){
 	int should_terminate = FALSE;
-	
+
 	if (obj->type == BELLE_SIP_DIALOG_SUBSCRIBE_NOTIFY) {
 		belle_sip_request_t *req=belle_sip_transaction_get_request(transaction);
 		belle_sip_response_t *resp=belle_sip_transaction_get_response(transaction);
 		belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(req,belle_sip_header_subscription_state_t);
 		int code = resp ? belle_sip_response_get_status_code(resp) : 0;
-	
+
 		if (!subscription_state_header || strcasecmp(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,belle_sip_header_subscription_state_get_state(subscription_state_header)) ==0) {
 			if (as_uas){
 				/*terminate the dialog when the application replies the 200 Ok*/
@@ -445,10 +446,10 @@ int belle_sip_dialog_update(belle_sip_dialog_t *obj, belle_sip_transaction_t* tr
 	int is_notify = strcmp(belle_sip_request_get_method(req),"NOTIFY")==0;
 
 	belle_sip_message("Dialog [%p]: now updated by transaction [%p].",obj, transaction);
-	
+
 	if (resp)
 		code=belle_sip_response_get_status_code(resp);
-	
+
 	if (as_uas && code == 491) { /**/
 		belle_sip_message("Dialog [%p]: don't update last transaction by transaction [%p].",obj, transaction);
 	} else {
@@ -460,7 +461,7 @@ int belle_sip_dialog_update(belle_sip_dialog_t *obj, belle_sip_transaction_t* tr
 		belle_sip_header_privacy_t *privacy_header=belle_sip_message_get_header_by_type(req,belle_sip_header_privacy_t);
 		SET_OBJECT_PROPERTY(obj,privacy,privacy_header);
 	}
-	
+
 	/*first update local/remote cseq*/
 	if (as_uas) {
 		belle_sip_header_cseq_t* cseq=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_cseq_t);
@@ -470,7 +471,7 @@ int belle_sip_dialog_update(belle_sip_dialog_t *obj, belle_sip_transaction_t* tr
 		/*else ACK is handled by transaction, not dialog*/
 	}
 
-	
+
 	switch (obj->state){
 		case BELLE_SIP_DIALOG_NULL:
 			/*always establish a dialog*/
@@ -480,7 +481,8 @@ int belle_sip_dialog_update(belle_sip_dialog_t *obj, belle_sip_transaction_t* tr
 					set_state(obj,BELLE_SIP_DIALOG_EARLY);
 					break;
 				}/* no break  for code >200 because need to call belle_sip_dialog_establish_full*/
-			}/* no break*/
+			}
+			BCTBX_NO_BREAK; /*intentionally no break*/
 		case BELLE_SIP_DIALOG_EARLY:
 			/*don't terminate dialog for UPDATE*/
 			if (code>=300 && (is_invite || is_subscribe)) {
@@ -524,7 +526,7 @@ int belle_sip_dialog_update(belle_sip_dialog_t *obj, belle_sip_transaction_t* tr
 				belle_sip_header_contact_t *ct;
 				if (as_uas){
 					ct=belle_sip_message_get_header_by_type(req,belle_sip_header_contact_t);
-					
+
 				}else{
 					if (is_invite)
 						set_last_out_invite(obj,req);
@@ -533,7 +535,7 @@ int belle_sip_dialog_update(belle_sip_dialog_t *obj, belle_sip_transaction_t* tr
 				if (ct){
 					belle_sip_dialog_update_remote_target(obj, ct);
 				}
-				
+
 			}
 			if (is_invite){
 				if (code>=200 && code<300){
@@ -590,7 +592,7 @@ int belle_sip_dialog_update(belle_sip_dialog_t *obj, belle_sip_transaction_t* tr
 			/*ignore*/
 		break;
 	}
-	
+
 end:
 	if (delete_dialog) belle_sip_dialog_delete(obj);
 	else {
@@ -617,7 +619,7 @@ belle_sip_dialog_t *belle_sip_dialog_new(belle_sip_transaction_t *t){
 		belle_sip_error("belle_sip_dialog_new(): no from tag!");
 		return NULL;
 	}
-	
+
 	to = belle_sip_message_get_header_by_type(t->request,belle_sip_header_to_t);
 	if (to == NULL){
 		belle_sip_error("belle_sip_dialog_new(): no to in request!");
@@ -647,7 +649,7 @@ belle_sip_dialog_t *belle_sip_dialog_new(belle_sip_transaction_t *t){
 	obj->provider=t->provider;
 	obj->pending_trans_checking_enabled=1;
 	obj->call_id=(belle_sip_header_call_id_t*)belle_sip_object_ref(call_id);
-	
+
 	if (strcmp(belle_sip_request_get_method(t->request),"INVITE") == 0){
 		obj->type = BELLE_SIP_DIALOG_INVITE;
 	}else if (strcmp(belle_sip_request_get_method(t->request),"SUBSCRIBE") == 0){
@@ -655,10 +657,10 @@ belle_sip_dialog_t *belle_sip_dialog_new(belle_sip_transaction_t *t){
 	}else{
 		belle_sip_error("belle_sip_dialog_new(): unsupported request [%s] for creating a dialog.", belle_sip_request_get_method(t->request));
 	}
-	
+
 	belle_sip_object_ref(t);
 	obj->last_transaction=t;
-	
+
 	if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(t,belle_sip_server_transaction_t)){
 		obj->remote_tag=belle_sip_strdup(from_tag);
 		obj->local_tag=belle_sip_strdup(BELLE_SIP_SERVER_TRANSACTION(t)->to_tag);
@@ -677,7 +679,7 @@ belle_sip_dialog_t *belle_sip_dialog_new(belle_sip_transaction_t *t){
 		}
 		belle_sip_dialog_init_as_uac(obj,belle_sip_transaction_get_request(t));
 	}
-	
+
 
 	belle_sip_message("New %s dialog [%p] , local tag [%s], remote tag [%s]"
 			,obj->is_server?"server":"client"
@@ -692,7 +694,7 @@ belle_sip_request_t *belle_sip_dialog_create_ack(belle_sip_dialog_t *obj, unsign
 	belle_sip_header_cseq_t *cseqh;
 	belle_sip_request_t *invite=obj->last_out_invite;
 	belle_sip_request_t *ack;
-	
+
 	if (!invite){
 		belle_sip_error("No INVITE to ACK.");
 		return NULL;
@@ -734,12 +736,12 @@ belle_sip_request_t *belle_sip_dialog_create_ack(belle_sip_dialog_t *obj, unsign
 static belle_sip_request_t *create_request(belle_sip_dialog_t *obj, const char *method, int full){
 	belle_sip_request_t *req;
 	char* from_tag=NULL, *to_tag=NULL;
-	
+
 	if (!obj->remote_target){
 		belle_sip_error("dialog [%p]: no remote_target set, unable to create request.", obj);
 		return NULL;
 	}
-	
+
 	if (!belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(obj->local_party), "tag")) {
 		/*special case for dialog created by server transaction*/
 		from_tag = obj->local_tag;
@@ -757,7 +759,7 @@ static belle_sip_request_t *create_request(belle_sip_dialog_t *obj, const char *
 	                                                belle_sip_header_to_create(obj->remote_party,to_tag),
 	                                                belle_sip_header_via_new(),
 	                                                0);
-	
+
 	if (full && obj->route_set) {
 		belle_sip_message_add_headers((belle_sip_message_t*)req,obj->route_set);
 	}
@@ -784,7 +786,7 @@ static int dialog_can_create_request(belle_sip_dialog_t *obj, const char *method
 
 belle_sip_request_t * belle_sip_dialog_create_queued_request(belle_sip_dialog_t *obj, const char *method){
 	belle_sip_request_t *req;
-	
+
 	if (!dialog_can_create_request(obj, method)) return NULL;
 	if (strcmp(method,"INVITE")==0 || strcmp(method,"SUBSCRIBE")==0){
 		/*we don't allow requests that can update the dialog's state to be sent asynchronously*/
@@ -805,7 +807,7 @@ static void belle_sip_dialog_update_local_cseq(belle_sip_dialog_t *obj, const ch
 
 belle_sip_request_t *belle_sip_dialog_create_request(belle_sip_dialog_t *obj, const char *method){
 	belle_sip_request_t *req;
-	
+
 	if (!dialog_can_create_request(obj, method)) return NULL;
 	/*don't prevent to send a BYE in any case */
 	if (	obj->pending_trans_checking_enabled
@@ -819,7 +821,7 @@ belle_sip_request_t *belle_sip_dialog_create_request(belle_sip_dialog_t *obj, co
 		} /*else UPDATE transaction can be send in // */
 	}
 	belle_sip_dialog_update_local_cseq(obj,method);
-	
+
 	req=create_request(obj,method,TRUE);
 	return req;
 }
@@ -848,25 +850,25 @@ static belle_sip_request_t *_belle_sip_dialog_create_request_from(belle_sip_dial
 	const char *method=belle_sip_request_get_method(initial_req);
 	belle_sip_header_content_length_t* content_lenth;
 	belle_sip_list_t* headers;
-	
+
 	if (queued) req=belle_sip_dialog_create_queued_request(obj,method);
 	else req=belle_sip_dialog_create_request(obj,method);
-	
+
 	if (req==NULL) return NULL;
-	
+
 	content_lenth = belle_sip_message_get_header_by_type(initial_req,belle_sip_header_content_length_t);
 	/*first copy non system headers*/
 	headers = belle_sip_message_get_all_headers(BELLE_SIP_MESSAGE(initial_req));
 	belle_sip_list_for_each2(headers,(void (*)(void *, void *))copy_non_system_headers,req);
 	belle_sip_list_free(headers);
-	
+
 	/*replicate via user parameters, if any, useful for 'alias' parameter in SUBSCRIBE requests*/
 	{
 		belle_sip_header_via_t *orig_via=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(initial_req),belle_sip_header_via_t);
 		belle_sip_header_via_t *new_via=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_via_t);
 		belle_sip_parameters_copy_parameters_from(BELLE_SIP_PARAMETERS(new_via),BELLE_SIP_PARAMETERS(orig_via));
 	}
-	
+
 	/*copy body*/
 	if (content_lenth && belle_sip_header_content_length_get_content_length(content_lenth)>0) {
 		belle_sip_message_set_body(BELLE_SIP_MESSAGE(req),belle_sip_message_get_body(BELLE_SIP_MESSAGE(initial_req)),belle_sip_header_content_length_get_content_length(content_lenth));
@@ -884,7 +886,7 @@ belle_sip_request_t *belle_sip_dialog_create_queued_request_from(belle_sip_dialo
 
 void belle_sip_dialog_delete(belle_sip_dialog_t *obj){
 	size_t dropped_transactions;
-	
+
 	if (obj->expiration_timer){
 		belle_sip_main_loop_remove_source(obj->provider->stack->ml, obj->expiration_timer);
 		belle_sip_object_unref(obj->expiration_timer);
@@ -990,7 +992,7 @@ int belle_sip_dialog_match(belle_sip_dialog_t *obj, belle_sip_message_t *msg, in
 	call_id_value=belle_sip_header_call_id_get_call_id(call_id);
 	from_tag=belle_sip_header_from_get_tag(from);
 	to_tag=belle_sip_header_to_get_tag(to);
-	
+
 	return _belle_sip_dialog_match(obj,call_id_value,as_uas ? to_tag : from_tag, as_uas ? from_tag : to_tag);
 }
 
@@ -999,7 +1001,7 @@ int _belle_sip_dialog_match(belle_sip_dialog_t *obj, const char *call_id, const
 	/*Dialog created by notify matching subscription are still in NULL state if (obj->state==BELLE_SIP_DIALOG_NULL) belle_sip_fatal("_belle_sip_dialog_match() must not be used for dialog in null state.");*/
 	dcid=belle_sip_header_call_id_get_call_id(obj->call_id);
 	return strcmp(dcid,call_id)==0
-		&& strcmp(obj->local_tag,local_tag)==0 
+		&& strcmp(obj->local_tag,local_tag)==0
 		&& obj->remote_tag /* handle 180 without to tag */ && strcmp(obj->remote_tag,remote_tag)==0;
 }
 
@@ -1080,7 +1082,7 @@ int belle_sip_dialog_is_authorized_transaction(const belle_sip_dialog_t *dialog,
 		const char* last_transaction_request;
 		if (strcasecmp(method,"BYE")==0)
 			return TRUE; /*don't reject a BYE*/
-		
+
 		last_transaction_request = belle_sip_request_get_method(belle_sip_transaction_get_request(dialog->last_transaction));
 		if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(dialog->last_transaction,belle_sip_client_transaction_t)
 			&& strcmp(last_transaction_request,"SUBSCRIBE")==0 && strcmp(method,"NOTIFY")==0){
@@ -1103,9 +1105,9 @@ void belle_sip_dialog_queue_client_transaction(belle_sip_dialog_t *dialog, belle
 
 static void _belle_sip_dialog_process_queue(belle_sip_dialog_t* dialog){
 	belle_sip_client_transaction_t *tr=NULL;
-	
+
 	if (dialog->state==BELLE_SIP_DIALOG_TERMINATED || belle_sip_dialog_request_pending(dialog)) goto end;
-	
+
 	dialog->queued_ct=belle_sip_list_pop_front(dialog->queued_ct,(void**)&tr);
 	if (tr){
 		belle_sip_message("Dialog [%p]: sending queued request.",dialog);
diff --git a/src/dns.c b/src/dns.c
index 7e766b5..0594e93 100644
--- a/src/dns.c
+++ b/src/dns.c
@@ -112,11 +112,12 @@
 #include <resolv.h>
 #endif
 
-#ifdef ANDROID
+#ifdef __ANDROID__
 #include <sys/system_properties.h>
 #endif
 
 #include <bctoolbox/port.h>
+#include <bctoolbox/defs.h>
 
 /*
  * C O M P I L E R  V E R S I O N  &  F E A T U R E  D E T E C T I O N
@@ -243,7 +244,9 @@
 #if DNS_GNUC_PREREQ(0,0,0) && !DNS_GNUC_PREREQ(4,6,0)
 #define HAVE_STATIC_ASSERT 0 /* glibc doesn't check GCC version */
 #else
-#define HAVE_STATIC_ASSERT (defined static_assert)
+#if (defined static_assert)
+#define HAVE_STATIC_ASSERT 1
+#endif
 #endif
 #endif
 
@@ -414,11 +417,15 @@ const char *dns_strerror(int error) {
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 #ifndef HAVE___ATOMIC_FETCH_ADD
-#define HAVE___ATOMIC_FETCH_ADD (defined __ATOMIC_RELAXED)
+#if (defined __ATOMIC_RELAXED)
+#define HAVE___ATOMIC_FETCH_ADD 1
+#endif
 #endif
 
 #ifndef HAVE___ATOMIC_FETCH_SUB
-#define HAVE___ATOMIC_FETCH_SUB HAVE___ATOMIC_FETCH_ADD
+#if (defined __ATOMIC_RELAXED)
+#define HAVE___ATOMIC_FETCH_SUB 1
+#endif
 #endif
 
 #ifndef DNS_ATOMIC_FETCH_ADD
@@ -787,7 +794,9 @@ DNS_NOTUSED static size_t dns_strnlcpy(char *dst, size_t lim, const char *src, s
 } /* dns_strnlcpy() */
 
 
-#define DNS_HAVE_SOCKADDR_UN (defined AF_UNIX && !defined _WIN32)
+#if (defined AF_UNIX && !defined _WIN32)
+#define DNS_HAVE_SOCKADDR_UN 1
+#endif
 
 static size_t dns_af_len(int af) {
 	static const size_t table[AF_MAX]	= {
@@ -4965,7 +4974,7 @@ int dns_resconf_loadwin(struct dns_resolv_conf *resconf) {
 }
 #endif /* dns_resconf_loadwin() */
 
-#ifdef ANDROID
+#ifdef __ANDROID__
 int dns_resconf_loadandroid(struct dns_resolv_conf *resconf) {
 	char dns[PROP_VALUE_MAX];
 	char prop_name[PROP_NAME_MAX];
@@ -6261,11 +6270,15 @@ static void dns_socketclose(int *fd, const struct dns_options *opts) {
 #endif
 
 #ifndef HAVE_SOCK_CLOEXEC
-#define HAVE_SOCK_CLOEXEC (defined SOCK_CLOEXEC)
+#if (defined SOCK_CLOEXEC)
+#define HAVE_SOCK_CLOEXEC 1
+#endif
 #endif
 
 #ifndef HAVE_SOCK_NONBLOCK
-#define HAVE_SOCK_NONBLOCK (defined SOCK_NONBLOCK)
+#if (defined SOCK_NONBLOCK)
+#define HAVE_SOCK_NONBLOCK 1
+#endif
 #endif
 
 #define DNS_SO_MAXTRY	7
@@ -6285,7 +6298,7 @@ static int dns_socket(struct sockaddr *local, int type, int *error_) {
 #endif
 	if (-1 == (fd = socket(local->sa_family, type|flags, 0)))
 		goto soerr;
-	
+
 	if (local->sa_family == AF_INET6){
 		int value=0;
 		setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&value, sizeof(value));
@@ -6406,6 +6419,7 @@ struct dns_socket {
 
 	struct dns_packet *answer;
 	size_t alen, apos;
+	int ip_differ; /*set when remote address and response from which it is received are different*/
 }; /* struct dns_socket */
 
 
@@ -6471,7 +6485,7 @@ static void dns_so_closefds(struct dns_socket *so, int which) {
 static void dns_so_destroy(struct dns_socket *);
 
 static struct dns_socket *dns_so_init(struct dns_socket *so, const struct sockaddr *local, int type, const struct dns_options *opts, int *error) {
-	static const struct dns_socket so_initializer = { .opts = DNS_OPTS_INITIALIZER, .udp = -1, .tcp = -1, };
+	static const struct dns_socket so_initializer = { .opts = DNS_OPTS_INITIALIZER, .udp = -1, .tcp = -1};
 
 	*so		= so_initializer;
 	so->type	= type;
@@ -6736,8 +6750,9 @@ static int dns_so_tcp_recv(struct dns_socket *so) {
 #endif
 
 
-int dns_so_check(struct dns_socket *so) {
-	struct sockaddr_storage reset_ss;
+int dns_so_check(struct  dns_socket *so) {
+	struct sockaddr_storage tmp_ss;
+	socklen_t tmp_ss_len = sizeof(tmp_ss);
 	int error;
 	long n;
 
@@ -6746,23 +6761,41 @@ retry:
 	case DNS_SO_UDP_INIT:
 		so->state++;
 	case DNS_SO_UDP_CONN:
-		memset(&reset_ss, 0, sizeof(reset_ss));
-		connect(so->udp, (struct sockaddr *)&reset_ss, sizeof(reset_ss)); // Reset the previous connection
-		if (0 != connect(so->udp, (struct sockaddr *)&so->remote, dns_sa_len(&so->remote)))
-			goto soerr;
+		memset(&tmp_ss, 0, sizeof(tmp_ss));
+		connect(so->udp, (struct sockaddr *)&tmp_ss, sizeof(tmp_ss)); // Reset the previous connection
+		if (so->opts.udp_uses_connect){
+			if (0 != connect(so->udp, (struct sockaddr *)&so->remote, dns_sa_len(&so->remote)))
+				goto soerr;
+		}
 
 		so->state++;
 	case DNS_SO_UDP_SEND:
-		if (0 > (n = send(so->udp, (void *)so->query->data, so->query->end, 0)))
-			goto soerr;
+		if (so->opts.udp_uses_connect){
+			if (0 > (n = send(so->udp, (void *)so->query->data, so->query->end, 0)))
+				goto soerr;
+		}else{
+			if (0 > (n = sendto(so->udp, (void *)so->query->data, so->query->end, 0, (struct sockaddr *)&so->remote, dns_sa_len(&so->remote))))
+				goto soerr;
+		}
 
 		so->stat.udp.sent.bytes += n;
 		so->stat.udp.sent.count++;
 
 		so->state++;
 	case DNS_SO_UDP_RECV:
-		if (0 > (n = recv(so->udp, (void *)so->answer->data, so->answer->size, 0)))
-			goto soerr;
+		if (so->opts.udp_uses_connect){
+			if (0 > (n = recv(so->udp, (void *)so->answer->data, so->answer->size, 0)))
+				goto soerr;
+		}else{
+			memset(&tmp_ss, 0, sizeof(tmp_ss));
+			tmp_ss_len = sizeof(tmp_ss);
+			if (0 > (n = recvfrom(so->udp, (void *)so->answer->data, so->answer->size, 0, (struct sockaddr *)&tmp_ss, &tmp_ss_len)))
+				goto soerr;
+			if (memcmp(&tmp_ss, &so->remote, tmp_ss_len) != 0){
+				so->ip_differ = 1;
+			}
+			
+		}
 
 		so->stat.udp.rcvd.bytes += n;
 		so->stat.udp.rcvd.count++;
@@ -8120,6 +8153,10 @@ void dns_res_enable_search(struct dns_resolver *res, unsigned char enable) {
 	res->search_enabled = enable;
 }
 
+int dns_res_was_asymetric(struct dns_resolver *res){
+	return res->so.ip_differ;
+}
+
 
 /*
  * A D D R I N F O  R O U T I N E S
@@ -10045,4 +10082,3 @@ int main(int argc, char **argv) {
 #elif DNS_GNUC_PREREQ(4,6,0)
 #pragma GCC diagnostic pop
 #endif
-
diff --git a/src/dns.h b/src/dns.h
index d4b1dca..ac390ae 100644
--- a/src/dns.h
+++ b/src/dns.h
@@ -960,7 +960,7 @@ int dns_resconf_load_struct_res_state_nameservers(struct dns_resolv_conf *rescon
 DNS_PUBLIC int dns_resconf_loadwin(struct dns_resolv_conf *);
 #endif
 
-#ifdef ANDROID
+#ifdef __ANDROID__
 DNS_PUBLIC int dns_resconf_loadandroid(struct dns_resolv_conf *resconf);
 #endif
 
@@ -1098,6 +1098,7 @@ struct dns_options {
 		DNS_SYSPOLL,
 		DNS_LIBEVENT,
 	} events;
+	int udp_uses_connect;
 }; /* struct dns_options */
 
 
@@ -1202,6 +1203,8 @@ DNS_PUBLIC void dns_res_sethints(struct dns_resolver *, struct dns_hints *);
 
 DNS_PUBLIC void dns_res_enable_search(struct dns_resolver *, unsigned char enable);
 
+DNS_PUBLIC int dns_res_was_asymetric(struct dns_resolver *);
+
 
 /*
  * A D D R I N F O  I N T E R F A C E
diff --git a/src/grammars/belle_sip_message.g b/src/grammars/belle_sip_message.g
index 92fa0fd..a77c1de 100644
--- a/src/grammars/belle_sip_message.g
+++ b/src/grammars/belle_sip_message.g
@@ -81,7 +81,7 @@ options {
 #include "belle-sip/message.h"
 #include "belle-sip/http-message.h"
 #include "parserutils.h"
-BELLESIP_INTERNAL_EXPORT void belle_sip_header_address_set_quoted_displayname(belle_sip_header_address_t* address,const char* value);
+BELLESIP_EXPORT void belle_sip_header_address_set_quoted_displayname(belle_sip_header_address_t* address,const char* value);
 }
 
 @rulecatch 
@@ -668,24 +668,43 @@ header_address returns [belle_sip_header_address_t* ret]
 header_address_base[belle_sip_header_address_t* obj]      returns [belle_sip_header_address_t* ret]   
 @init { $ret=obj; }
      :  ( name_addr_with_generic_uri[BELLE_SIP_HEADER_ADDRESS($ret)]
-| addr_spec_with_generic_uri[BELLE_SIP_HEADER_ADDRESS($ret)]) { if (!belle_sip_header_address_get_uri($ret)
-																	&&
-																	!belle_sip_header_address_get_absolute_uri(($ret))) {
-																											belle_sip_object_unref($ret);
-																											$ret=NULL;
-																											}
-																};
+| addr_spec_with_generic_uri[BELLE_SIP_HEADER_ADDRESS($ret)]) 	{	if (!belle_sip_header_address_get_uri($ret) && !belle_sip_header_address_get_absolute_uri(($ret))) {
+						belle_sip_object_unref($ret);
+						$ret=NULL;
+						} 
+					};
 catch [ANTLR3_RECOGNITION_EXCEPTION]
 {
-  belle_sip_object_unref($ret);
-  $ret=NULL;
-}      
+   belle_sip_debug("[\%s]  reason [\%s]",(const char*)EXCEPTION->name,(const char*)EXCEPTION->message);
+   if ($ret) belle_sip_object_unref($ret);
+   $ret=NULL;
+} 
+
+fast_header_address  returns [belle_sip_header_address_t* ret]   
+ at init { $ret=belle_sip_header_address_new(); }
+     :  ( 	fast_name_addr_with_generic_uri[BELLE_SIP_HEADER_ADDRESS($ret)]
+	| fast_addr_spec_with_generic_uri[BELLE_SIP_HEADER_ADDRESS($ret)]) 	{	if (!belle_sip_header_address_get_uri($ret) && !belle_sip_header_address_get_absolute_uri(($ret))) {
+							belle_sip_object_unref($ret);
+							$ret=NULL;
+							} 
+						};
+catch [ANTLR3_RECOGNITION_EXCEPTION]
+{
+   belle_sip_debug("[\%s]  reason [\%s]",(const char*)EXCEPTION->name,(const char*)EXCEPTION->message);
+   if ($ret) belle_sip_object_unref($ret);
+   $ret=NULL;
+} 
+
 name_addr[belle_sip_header_address_t* object]      
   :      (lws? display_name[object])? sp_laquot  addr_spec[object] raquot_sp;
 
 name_addr_with_generic_uri[belle_sip_header_address_t* object]      
   :      (lws? display_name[object])? sp_laquot  addr_spec_with_generic_uri[object] raquot_sp;
 
+fast_name_addr_with_generic_uri[belle_sip_header_address_t* object]      
+  :      (lws? display_name[object])? sp_laquot  fast_addr_spec_with_generic_uri[object] raquot_sp;
+
+
 
 addr_spec[belle_sip_header_address_t* object]      
   :  lws? uri {belle_sip_header_address_set_uri(object,$uri.ret);} lws?;//| absoluteURI;
@@ -702,6 +721,18 @@ addr_spec_with_generic_uri[belle_sip_header_address_t* object]
 					 }}
   	) lws?;
   
+  fast_addr_spec_with_generic_uri[belle_sip_header_address_t* object]      
+  :  lws? (	fast_uri {belle_sip_header_address_set_uri(object,$fast_uri.ret);}  
+  	| 
+  	generic_uri { if (   strcasecmp(belle_generic_uri_get_scheme($generic_uri.ret),"sip") != 0
+					 &&  strcasecmp(belle_generic_uri_get_scheme($generic_uri.ret),"sips") != 0 ) {
+						 belle_sip_header_address_set_absolute_uri(object,$generic_uri.ret);
+					 } else {
+						 belle_sip_message("Cannot parse a sip/sips uri as a generic uri");
+						 belle_sip_object_unref($generic_uri.ret);
+					 }}
+  	) lws?;
+  	
 paramless_addr_spec[belle_sip_header_address_t* object]      
   :  lws? paramless_uri {belle_sip_header_address_set_uri(object,$paramless_uri.ret);} lws? ;//| absoluteURI;
   
@@ -1508,8 +1539,107 @@ accept_sub_media_type {belle_sip_header_accept_set_subtype($header_accept::curre
 accept_main_media_type: token;
 accept_sub_media_type: token;
 
+//****************************Reason***********************************//
+/*
+Reason            =  "Reason" HCOLON reason-value *(COMMA reason-value)
+ reason-value      =  protocol *(SEMI reason-params)
+ protocol          =  "SIP" / "Q.850" / token
+ reason-params     =  protocol-cause / reason-text
+                      / reason-extension
+ protocol-cause    =  "cause" EQUAL cause
+ cause             =  1*DIGIT
+ reason-text       =  "text" EQUAL quoted-string
+ reason-extension  =  generic-param
 
+*/
+header_reason  returns [belle_sip_header_reason_t* ret=NULL]
+scope { belle_sip_header_reason_t* current;belle_sip_header_reason_t* first; }
+ at init { $header_reason::current = NULL; $header_reason::first =NULL;}
+:   {IS_TOKEN(Reason)}? token /*'Reason'*/ hcolon header_reason_param  ( comma header_reason_param)* {$ret = $header_reason::first; };
+catch [ANTLR3_RECOGNITION_EXCEPTION]
+{
+   belle_sip_message("[\%s]  reason [\%s]",(const char*)EXCEPTION->name,(const char*)EXCEPTION->message);
+   $ret = $header_reason::first;
+   if ($ret) belle_sip_object_unref($ret);
+   $ret=NULL;
+} 
+header_reason_param 
+scope { belle_sip_header_reason_t* prev;}
+ at init { if ($header_reason::current == NULL) {
+            $header_reason::first = $header_reason::current = belle_sip_header_reason_new();
+             $header_reason_param::prev=NULL;
+         } else {
+            belle_sip_header_t* header = BELLE_SIP_HEADER($header_reason::current); 
+            $header_reason_param::prev=$header_reason::current;
+            belle_sip_header_set_next(header,(belle_sip_header_t*)($header_reason::current = belle_sip_header_reason_new()));
+         } 
+      }      
+	:header_reason_protocol {belle_sip_header_reason_set_protocol($header_reason::current,(const char*)$header_reason_protocol.text->chars);} 
+	(semi  generic_param [BELLE_SIP_PARAMETERS($header_reason::current)])*;
+header_reason_protocol
+	:	token;
 //*********************************************//
+
+/*
+AuthenticationInfo = "Authentication-Info" ":" auth-info
+        auth-info          = 1#(nextnonce | [ message-qop ]
+                               | [ response-auth ] | [ cnonce ]
+                               | [nonce-count] )
+        nextnonce          = "nextnonce" "=" nonce-value
+        response-auth      = "rspauth" "=" response-digest
+        response-digest    = <"> *LHEX <">
+*/
+
+header_authentication_info  returns [belle_sip_header_authentication_info_t* ret=NULL]     
+scope { belle_sip_header_authentication_info_t* current; }
+ at init {$header_authentication_info::current = belle_sip_header_authentication_info_new(); $ret=$header_authentication_info::current; }
+  :   {IS_TOKEN( Authentication-Info)}? token /*' Authentication-Info'*/ hcolon   auth_info ( comma auth_info)*;
+  catch [ANTLR3_RECOGNITION_EXCEPTION]
+{
+   belle_sip_message("[\%s]  reason [\%s]",(const char*)EXCEPTION->name,(const char*)EXCEPTION->message);
+   belle_sip_object_unref($header_authentication_info::current);
+   $ret=NULL;
+}
+ auth_info
+  	:	
+  ( next_nonce { belle_sip_header_authentication_info_set_next_nonce($header_authentication_info::current,(char*)$next_nonce.ret);
+                 belle_sip_free($next_nonce.ret);
+           }
+  |cnonce{
+            belle_sip_header_authentication_info_set_cnonce($header_authentication_info::current,(char*)$cnonce.ret);
+            belle_sip_free($cnonce.ret);
+           }
+  | authentication_info_message_qop{
+            belle_sip_header_authentication_info_set_qop($header_authentication_info::current,$authentication_info_message_qop.ret);
+           }
+   |nonce_count{
+            belle_sip_header_authentication_info_set_nonce_count($header_authentication_info::current,atoi((char*)$nonce_count.ret));
+           } 
+   |rspauth {
+   	belle_sip_header_authentication_info_set_rsp_auth($header_authentication_info::current,$rspauth.ret);
+   	 belle_sip_free($rspauth.ret);
+           }) ;
+
+qop_token
+	:	 {IS_TOKEN(qop)}? token/*'qop'*/;
+/*as defined by 3261*/
+authentication_info_message_qop  returns [const char* ret=NULL]     
+  :   qop_token equal  token  {  $ret = (const char*)$token.text->chars;};
+
+rspauth  returns [char* ret=NULL]             
+  :   {IS_TOKEN(rspauth)}? token /*'nonce'*/ equal quoted_string{
+                      $ret = _belle_sip_str_dup_and_unquote_string((char*)$quoted_string.text->chars);
+                       };
+next_nonce  returns [char* ret=NULL]             
+  :   {IS_TOKEN(nextnonce)}? token /*'nonce'*/ equal nonce_value{
+                      $ret = _belle_sip_str_dup_and_unquote_string((char*)$nonce_value.text->chars);
+                       };
+                       
+quoted_algorithm  returns [char* ret=NULL]             
+  :   {IS_TOKEN(nextnonce)}? token /*'nonce'*/ equal nonce_value{
+                      $ret = _belle_sip_str_dup_and_unquote_string((char*)$nonce_value.text->chars);
+                       };
+//**********************************************//
 header  returns [belle_sip_header_t* ret=NULL]
 	 : header_extension_base[FALSE] {$ret=$header_extension_base.ret;};
 	
@@ -1575,6 +1705,20 @@ catch [ANTLR3_RECOGNITION_EXCEPTION]
    $ret=NULL;
 }
 
+fast_uri  returns [belle_sip_uri_t* ret=NULL]    
+scope { belle_sip_uri_t* current; }
+ at init { $fast_uri::current = belle_sip_uri_new(); }
+   :  sip_schema[$fast_uri::current] ( ((userinfo[NULL])=>userinfo[$fast_uri::current] fast_hostport[$fast_uri::current]) | fast_hostport[$fast_uri::current] ) 
+   uri_parameters[$fast_uri::current]? 
+   headers[$fast_uri::current]? {$ret = $fast_uri::current;}; 
+catch [ANTLR3_RECOGNITION_EXCEPTION]
+{
+   belle_sip_message("[\%s]  reason [\%s]",(const char*)EXCEPTION->name,(const char*)EXCEPTION->message);
+   belle_sip_object_unref($fast_uri::current);
+   $ret=NULL;
+}
+
+
 sip_token:  {IS_TOKEN(sip)}? token;
 sips_token:  {IS_TOKEN(sips)}? token;
 
@@ -1604,6 +1748,12 @@ scope { belle_sip_uri_t* current; }
 @init {$hostport::current=uri;}
         :   host ( COLON port {belle_sip_uri_set_port($hostport::current,$port.ret);})? {belle_sip_uri_set_host($hostport::current,$host.ret);};
 
+fast_hostport[belle_sip_uri_t* uri] 
+scope { belle_sip_uri_t* current; }
+ at init {$fast_hostport::current=uri;}
+        :  fast_host ( COLON port {belle_sip_uri_set_port($fast_hostport::current,$port.ret);})? {belle_sip_uri_set_host($fast_hostport::current,$fast_host.ret);};
+
+
 uri_parameters[belle_sip_uri_t* uri] 
 scope { belle_sip_uri_t* current; }
 @init {$uri_parameters::current=uri;}    
@@ -1660,9 +1810,19 @@ hvalue          :  ( hnv_unreserved | unreserved | escaped )+;
 hnv_unreserved  :   LSBRAQUET | RSBRAQUET  | SLASH | QMARK | COLON | PLUS | DOLLARD ;
 
 
-//****************SIP end**********************/	
-	
+
+
 	
+
+fast_host returns [const char* ret]
+scope { const char* current; }
+ at init {$fast_host::current=$ret=NULL;}
+            :  (fast_hostname 	{$fast_host::current=(const char *)$fast_hostname.text->chars;}
+                    /*| ipv4address 	{$fast_host::current=(const char *)$ipv4address.text->chars;} because cannot discriminate quickly betwenn 192.168.0.1 and 192.168.0.com*/
+                    | ipv6reference  {$fast_host::current=(const char *)$ipv6reference.ret;})  {$ret=$fast_host::current;}; 
+ 	
+fast_hostname:  alphanum ( alphanum | DASH | DOT )*;
+
 //*************************common tokens*******************************/
 
 user_unreserved :  AND | EQUAL | PLUS | DOLLARD | COMMA | SEMI | QMARK | SLASH;
@@ -1671,14 +1831,14 @@ scope { const char* current; }
 @init {$host::current=$ret=NULL;}
             :   (hostname {$host::current=(const char *)$hostname.text->chars;}
                     | ipv4address {$host::current=(const char *)$ipv4address.text->chars;}
-                    | ipv6reference ) {$ret=$host::current;};
+                    | ipv6reference {$host::current=(const char *)$ipv6reference.ret;}) {$ret=$host::current;};
 hostname        :   ( domainlabel DOT )* (toplabel)=>toplabel DOT? ;
   
 domainlabel     :   alphanum | (alphanum ( alphanum | DASH )* alphanum) ;
 toplabel        :   alpha | (alpha (  DASH?  alphanum)+) ;
 
 ipv4address    :  three_digit DOT three_digit DOT three_digit DOT three_digit ;
-ipv6reference  :  LSBRAQUET ipv6address RSBRAQUET {$host::current=(const char *)$ipv6address.text->chars;};
+ipv6reference returns [const char* ret=NULL]  :  LSBRAQUET ipv6address RSBRAQUET {$ret=(const char *)$ipv6address.text->chars;};
 ipv6address    :  hexpart ( COLON ipv4address )? ;
 hexpart        :  hexseq | hexseq COLON COLON ( hexseq )? | COLON COLON ( hexseq )?;
 hexseq         :  hex4 ( COLON hex4)*;
diff --git a/src/http-provider.c b/src/http-provider.c
index 29a07e8..09d65cb 100644
--- a/src/http-provider.c
+++ b/src/http-provider.c
@@ -17,6 +17,8 @@
 */
 
 
+#include <bctoolbox/defs.h>
+
 #include "belle_sip_internal.h"
 
 typedef struct belle_http_channel_context belle_http_channel_context_t;
@@ -266,6 +268,7 @@ static void channel_state_changed(belle_sip_channel_listener_t *obj, belle_sip_c
 			break;
 		case BELLE_SIP_CHANNEL_ERROR:
 			http_channel_context_handle_io_error(ctx, chan);
+			BCTBX_NO_BREAK; /*intentionally no break*/
 		case BELLE_SIP_CHANNEL_DISCONNECTED:
 			if (!chan->force_close) provider_remove_channel(ctx->provider,chan);
 			break;
@@ -492,7 +495,7 @@ int belle_http_provider_set_tls_crypto_config(belle_http_provider_t *obj, belle_
 
 void belle_http_provider_set_recv_error(belle_http_provider_t *obj, int recv_error) {
 	belle_sip_list_t *it;
-	
+
 	for(it=obj->tcp_channels;it!=NULL;it=it->next){
 		belle_sip_channel_t *chan = (belle_sip_channel_t*)it->data;
 		chan->simulated_recv_return=recv_error;
@@ -504,4 +507,3 @@ void belle_http_provider_set_recv_error(belle_http_provider_t *obj, int recv_err
 		chan->base.notify_required=(recv_error<=0);
 	}
 }
-
diff --git a/src/ict.c b/src/ict.c
index e6a3eb6..4d8443a 100644
--- a/src/ict.c
+++ b/src/ict.c
@@ -16,10 +16,12 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-/** 
+/**
  * INVITE client transaction implementation.
 **/
 
+#include <bctoolbox/defs.h>
+
 #include "belle_sip_internal.h"
 
 
@@ -104,7 +106,7 @@ static void ict_on_response(belle_sip_ict_t *obj, belle_sip_response_t *resp){
 	switch (base->state){
 		case BELLE_SIP_TRANSACTION_CALLING:
 			belle_sip_transaction_set_state(base,BELLE_SIP_TRANSACTION_PROCEEDING);
-			/* no break*/
+			BCTBX_NO_BREAK; /*intentionally no break*/
 		case BELLE_SIP_TRANSACTION_PROCEEDING:
 			if (code>=300){
 				belle_sip_transaction_set_state(base,BELLE_SIP_TRANSACTION_COMPLETED);
@@ -140,6 +142,8 @@ static void ict_on_response(belle_sip_ict_t *obj, belle_sip_response_t *resp){
 static int ict_on_timer_A(belle_sip_ict_t *obj){
 	belle_sip_transaction_t *base=(belle_sip_transaction_t*)obj;
 
+	if (!base->channel) return BELLE_SIP_STOP;
+
 	switch(base->state){
 		case BELLE_SIP_TRANSACTION_CALLING:
 		{
@@ -152,7 +156,7 @@ static int ict_on_timer_A(belle_sip_ict_t *obj){
 		default:
 		break;
 	}
-	
+
 	return BELLE_SIP_CONTINUE;
 }
 
@@ -175,7 +179,7 @@ static void ict_send_request(belle_sip_ict_t *obj){
 	const belle_sip_timer_config_t *cfg=belle_sip_transaction_get_timer_config(base);
 
 	belle_sip_transaction_set_state(base,BELLE_SIP_TRANSACTION_CALLING);
-	
+
 	if (!belle_sip_channel_is_reliable(base->channel)){
 		obj->timer_A=belle_sip_timeout_source_new((belle_sip_source_func_t)ict_on_timer_A,obj,cfg->T1);
 		belle_sip_transaction_start_timer(base,obj->timer_A);
@@ -183,7 +187,7 @@ static void ict_send_request(belle_sip_ict_t *obj){
 
 	obj->timer_B=belle_sip_timeout_source_new((belle_sip_source_func_t)ict_on_timer_B,obj,cfg->T1*64);
 	belle_sip_transaction_start_timer(base,obj->timer_B);
-	
+
 	belle_sip_channel_queue_message(base->channel,(belle_sip_message_t*)base->request);
 }
 
@@ -212,4 +216,3 @@ belle_sip_ict_t *belle_sip_ict_new(belle_sip_provider_t *prov, belle_sip_request
 	belle_sip_client_transaction_init((belle_sip_client_transaction_t*)obj,prov,req);
 	return obj;
 }
-
diff --git a/src/nist.c b/src/nist.c
index 46290cf..a3b2fc4 100644
--- a/src/nist.c
+++ b/src/nist.c
@@ -16,10 +16,12 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-/** 
+/**
  * non-INVITE server transaction implementation.
 **/
 
+#include <bctoolbox/defs.h>
+
 #include "belle_sip_internal.h"
 
 static void nist_on_terminate(belle_sip_nist_t *obj){
@@ -63,7 +65,7 @@ static int nist_send_new_response(belle_sip_nist_t *obj, belle_sip_response_t *r
 				belle_sip_channel_queue_message(base->channel,(belle_sip_message_t*)resp);
 				break;
 			}
-			/* no break nist can directly pass from TRYING to PROCEEDING*/
+			BCTBX_NO_BREAK; /* no break nist can directly pass from TRYING to PROCEEDING*/
 		case BELLE_SIP_TRANSACTION_PROCEEDING:
 			if (code>=200){
 				nist_set_completed(obj);
diff --git a/src/parserutils.h b/src/parserutils.h
index 06fb725..9b756c5 100644
--- a/src/parserutils.h
+++ b/src/parserutils.h
@@ -20,9 +20,13 @@
 
 #include "port.h"
 
+static BELLESIP_INLINE int belle_sip_strcasecmp(const char*a, const char* b) {
+	if (!a || !b) return 0;
+	return strcasecmp(a,b) == 0;
+}
+
 #define IS_TOKEN(token) \
-		(INPUT->toStringTT(INPUT,LT(1),LT(strlen(#token)))->chars ?\
-		strcasecmp(#token,(const char*)(INPUT->toStringTT(INPUT,LT(1),LT(strlen(#token)))->chars)) == 0:0)
+		belle_sip_strcasecmp(#token,(const char*)INPUT->toStringTT(INPUT,LT(1),LT(strlen(#token)))->chars)
 
 
 #define IS_HEADER_NAMED(name,compressed_name) (IS_TOKEN(compressed_name) || IS_TOKEN(name))
@@ -33,10 +37,10 @@
 #define ANTLR3_LOG_EXCEPTION() belle_sip_message("[\%s] reason [\%s] at line[\%u] position[\%d]",(const char*)EXCEPTION->name,(const char*)EXCEPTION->message,EXCEPTION->line,EXCEPTION->charPositionInLine);
 
 
-BELLESIP_INTERNAL_EXPORT belle_sip_header_t* belle_sip_header_get_next(const belle_sip_header_t* headers);
-BELLESIP_INTERNAL_EXPORT void belle_sip_header_set_next(belle_sip_header_t* header,belle_sip_header_t* next);
+BELLESIP_EXPORT belle_sip_header_t* belle_sip_header_get_next(const belle_sip_header_t* headers);
+BELLESIP_EXPORT void belle_sip_header_set_next(belle_sip_header_t* header,belle_sip_header_t* next);
 
-BELLESIP_INTERNAL_EXPORT char* belle_sip_to_unescaped_string(const char* buff);
+BELLESIP_EXPORT char* belle_sip_to_unescaped_string(const char* buff);
 belle_sip_param_pair_t* belle_sip_param_pair_new(const char* name,const char* value);
 char* _belle_sip_str_dup_and_unquote_string(const char* quoted_string);
 
@@ -49,7 +53,7 @@ char* _belle_sip_str_dup_and_unquote_string(const char* quoted_string);
 
 remove any \
  * */
-BELLESIP_INTERNAL_EXPORT char* belle_sip_string_to_backslash_less_unescaped_string(const char* buff);
-BELLESIP_INTERNAL_EXPORT char* belle_sip_display_name_to_backslashed_escaped_string(const char* buff);
+BELLESIP_EXPORT char* belle_sip_string_to_backslash_less_unescaped_string(const char* buff);
+BELLESIP_EXPORT char* belle_sip_display_name_to_backslashed_escaped_string(const char* buff);
 
 #endif
diff --git a/src/port.c b/src/port.c
index ba7d897..4056af9 100644
--- a/src/port.c
+++ b/src/port.c
@@ -191,7 +191,7 @@ int belle_sip_thread_key_delete(belle_sip_thread_key_t key){
 	current_thread_data = NULL;
 	return 0;
 #else
-	return TlsFree(key) ? 0 : -1;
+	return TlsFree((DWORD)key) ? 0 : -1;
 #endif
 }
 
@@ -244,7 +244,7 @@ int belle_sip_socket_set_dscp(belle_sip_socket_t sock, int ai_family, int dscp){
 			belle_sip_error("Cannot set DSCP because socket family is unspecified.");
 			return -1;
 	}
-	retval = setsockopt(sock, proto, value_type, (const char*)&tos, sizeof(tos));
+	retval = bctbx_setsockopt(sock, proto, value_type, (const char*)&tos, sizeof(tos));
 	if (retval==-1)
 		belle_sip_error("Fail to set DSCP value on socket: %s",belle_sip_get_socket_error_string());
 	return retval;
@@ -255,9 +255,9 @@ int belle_sip_socket_set_dscp(belle_sip_socket_t sock, int ai_family, int dscp){
 
 int belle_sip_socket_enable_dual_stack(belle_sip_socket_t sock){
 	int value=0;
-	int err=setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&value, sizeof(value));
+	int err=bctbx_setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&value, sizeof(value));
 	if (err==-1){
-		belle_sip_warning("belle_sip_socket_enable_dual_stack: setsockopt(IPV6_ONLY) failed: %s",belle_sip_get_socket_error_string());
+		belle_sip_warning("belle_sip_socket_enable_dual_stack: bctbx_setsockopt(IPV6_ONLY) failed: %s",belle_sip_get_socket_error_string());
 	}
 	return err;
 }
diff --git a/src/port.h b/src/port.h
index 1b835d3..d80c48a 100644
--- a/src/port.h
+++ b/src/port.h
@@ -84,22 +84,12 @@
 #	endif
 #endif
 
-#if defined(_WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__)
-#ifdef BELLESIP_INTERNAL_EXPORTS
-#define BELLESIP_INTERNAL_EXPORT __declspec(dllexport)
-#else
-#define BELLESIP_INTERNAL_EXPORT
-#endif
-#else
-#define BELLESIP_INTERNAL_EXPORT extern
-#endif
-
 /*
  * Socket abstraction layer
  */
 
-BELLESIP_INTERNAL_EXPORT int belle_sip_init_sockets(void);
-BELLESIP_INTERNAL_EXPORT void belle_sip_uninit_sockets(void);
+BELLESIP_EXPORT int belle_sip_init_sockets(void);
+BELLESIP_EXPORT void belle_sip_uninit_sockets(void);
 int belle_sip_socket_set_nonblocking (belle_sip_socket_t sock);
 int belle_sip_socket_set_dscp(belle_sip_socket_t sock, int ai_family, int dscp);
 int belle_sip_socket_enable_dual_stack(belle_sip_socket_t sock);
@@ -166,7 +156,7 @@ typedef pthread_mutex_t belle_sip_mutex_t;
 #endif
 
 #ifndef BELLE_SIP_WINDOWS_DESKTOP
-BELLESIP_INTERNAL_EXPORT void belle_sip_sleep(unsigned int ms);
+BELLESIP_EXPORT void belle_sip_sleep(unsigned int ms);
 #else
 #define belle_sip_sleep Sleep
 #endif
diff --git a/src/provider.c b/src/provider.c
index f73af8e..0cba9eb 100644
--- a/src/provider.c
+++ b/src/provider.c
@@ -20,8 +20,8 @@
 #include "listeningpoint_internal.h"
 #include "md5.h"
 #include "belle-sip/message.h"
-
-typedef struct authorization_context {
+static void  belle_sip_provider_update_or_create_auth_context(belle_sip_provider_t *p,belle_sip_header_call_id_t* call_id,belle_sip_header_www_authenticate_t* authenticate,belle_sip_uri_t *from_uri,const char* realm) ;
+struct authorization_context {
 	belle_sip_header_call_id_t* callid;
 	const char* scheme;
 	const char* realm;
@@ -32,7 +32,7 @@ typedef struct authorization_context {
 	const char* algorithm;
 	int nonce_count;
 	int is_proxy;
-}authorization_context_t;
+};
 
 GET_SET_STRING(authorization_context,realm)
 GET_SET_STRING(authorization_context,nonce)
@@ -49,7 +49,7 @@ static authorization_context_t* belle_sip_authorization_create(belle_sip_header_
 	belle_sip_object_ref(result->callid);
 	return result;
 }
-static void belle_sip_authorization_destroy(authorization_context_t* object) {
+void belle_sip_authorization_destroy(authorization_context_t* object) {
 	DESTROY_STRING(object,scheme);
 	DESTROY_STRING(object,realm);
 	DESTROY_STRING(object,nonce);
@@ -210,7 +210,39 @@ static void belle_sip_provider_dispatch_response(belle_sip_provider_t* p, belle_
 				}
 			}
 		}
+		break;
 	}
+		default:
+			if (t!=NULL){
+				belle_sip_message_t* req = BELLE_SIP_MESSAGE(belle_sip_transaction_get_request((belle_sip_transaction_t*)t));
+				belle_sip_header_authentication_info_t *authentication_info = belle_sip_message_get_header_by_type(msg,belle_sip_header_authentication_info_t);
+				belle_sip_list_t *authorization_lst = NULL;
+				belle_sip_header_call_id_t *call_id = belle_sip_message_get_header_by_type(msg,belle_sip_header_call_id_t);
+				belle_sip_header_from_t *from = belle_sip_message_get_header_by_type(req,belle_sip_header_from_t);
+				belle_sip_uri_t *from_uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)from);
+				/*searching for authentication headers*/
+				authorization_lst = belle_sip_list_copy(belle_sip_message_get_headers(BELLE_SIP_MESSAGE(req),BELLE_SIP_AUTHORIZATION));
+				/*search for proxy authenticate*/
+				authorization_lst=belle_sip_list_concat(authorization_lst,belle_sip_list_copy(belle_sip_message_get_headers(BELLE_SIP_MESSAGE(req),BELLE_SIP_PROXY_AUTHORIZATION)));
+				/*update auth contexts with authenticate headers from response*/
+				for (;authentication_info && authorization_lst!=NULL;authorization_lst=authorization_lst->next) {
+					belle_sip_header_authorization_t *authorization=BELLE_SIP_HEADER_AUTHORIZATION(authorization_lst->data);
+					belle_sip_header_www_authenticate_t *www_authenticate = belle_sip_auth_helper_create_www_authenticate(authorization);
+					belle_sip_header_www_authenticate_set_nonce(www_authenticate, belle_sip_header_authentication_info_get_next_nonce(authentication_info));
+					belle_sip_message( "Updating auth context for ream [%s] next nonce is going to be [%s]"
+									  , belle_sip_header_www_authenticate_get_realm(www_authenticate)
+									  , belle_sip_header_authentication_info_get_next_nonce(authentication_info));
+					belle_sip_provider_update_or_create_auth_context(p
+																	 , call_id
+																	 , www_authenticate
+																	 , from_uri
+																	 ,belle_sip_header_www_authenticate_get_realm(www_authenticate));
+					belle_sip_object_unref(www_authenticate);
+				}
+				if (authorization_lst)
+					belle_sip_list_free(authorization_lst);
+			}
+			
 	}
 	if (t){ /*In some re-connection case, specially over udp, transaction may be found, but without associated channel*/
 		if (t->base.channel == NULL) {
@@ -801,7 +833,10 @@ belle_sip_channel_t * belle_sip_provider_get_channel(belle_sip_provider_t *p, co
 			lp=(belle_sip_listening_point_t*)l->data;
 			if (strcasecmp(belle_sip_listening_point_get_transport(lp),hop->transport)==0){
 				chan=belle_sip_listening_point_get_channel(lp,hop);
-				if (chan) return chan;
+				if (chan) {
+					belle_sip_channel_check_dns_reusability(chan);
+					return chan;
+				}
 				candidate=lp;
 			}
 		}
@@ -1013,6 +1048,7 @@ static void authorization_context_fill_from_auth(authorization_context_t* auth_c
 	}
 }
 
+
 static belle_sip_list_t* belle_sip_provider_get_auth_context_by_realm_or_call_id(belle_sip_provider_t *p,belle_sip_header_call_id_t* call_id,belle_sip_uri_t *from_uri,const char* realm) {
 	belle_sip_list_t* auth_context_lst=NULL;
 	belle_sip_list_t* result=NULL;
@@ -1089,6 +1125,7 @@ static void  belle_sip_provider_update_or_create_auth_context(belle_sip_provider
 	return;
 }
 
+
 int belle_sip_provider_add_authorization(belle_sip_provider_t *p, belle_sip_request_t* request, belle_sip_response_t *resp,
 					 belle_sip_uri_t *from_uri, belle_sip_list_t** auth_infos, const char* realm) {
 	belle_sip_header_call_id_t* call_id;
diff --git a/src/refresher.c b/src/refresher.c
index b01416b..46c04cb 100644
--- a/src/refresher.c
+++ b/src/refresher.c
@@ -16,6 +16,8 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
+#include <bctoolbox/defs.h>
+
 #include "belle_sip_internal.h"
 #include "belle-sip/refresher.h"
 
@@ -111,7 +113,7 @@ static void process_dialog_terminated(belle_sip_listener_t *user_ctx, const bell
 		 * so there is no need to reschedule a retry here.*/
 		belle_sip_warning("Refresher [%p] still started but expired, retrying",refresher);
 		if (refresher->listener) refresher->listener(refresher,refresher->user_data,481, "dialod terminated", TRUE);
-		
+
 	}
 
 }
@@ -258,7 +260,7 @@ static void process_response_event(belle_sip_listener_t *user_ctx, const belle_s
 		if (refresher->state==started) {
 			if (!refresher->first_acknoleged_request)
 				belle_sip_object_ref(refresher->first_acknoleged_request = request);
-			if (is_contact_address_acurate(refresher,request)) {
+			if (is_contact_address_acurate(refresher,request) || !belle_sip_provider_nat_helper_enabled(client_transaction->base.provider)) {
 				schedule_timer(refresher); /*re-arm timer*/
 			} else {
 				belle_sip_message("belle_sip_refresher_start(): refresher [%p] is resubmitting request because contact sent was not correct in original request.",refresher);
@@ -336,7 +338,7 @@ static void process_response_event(belle_sip_listener_t *user_ctx, const belle_s
 				return; /*do not notify this kind of error*/
 			}
 		}
-		/*intentionally no break*/
+		BCTBX_NO_BREAK; /*intentionally no break*/
 		case 505:
 		case 501:
 			/*irrecoverable errors, probably no need to retry later*/
@@ -534,8 +536,8 @@ static int belle_sip_refresher_refresh_internal(belle_sip_refresher_t* refresher
 
 					belle_sip_message_set_header((belle_sip_message_t*)request, (belle_sip_header_t*)belle_sip_provider_create_call_id(prov));
 					break;
-				} /*else nop, error case*/
-
+				}
+				BCTBX_NO_BREAK; /*else nop, error case*/
 			}
 			default: {
 				belle_sip_error("Unexpected dialog state [%s] for dialog [%p], cannot refresh [%s]"
@@ -574,7 +576,7 @@ static int belle_sip_refresher_refresh_internal(belle_sip_refresher_t* refresher
 
 	client_transaction = belle_sip_provider_create_client_transaction(prov,request);
 	client_transaction->base.is_internal=1;
-	
+
 	if (request ==  refresher->first_acknoleged_request) { /*request is now ref by transaction so no need to keepo it*/
 		belle_sip_object_unref(refresher->first_acknoleged_request);
 		refresher->first_acknoleged_request = NULL;
diff --git a/src/transaction.c b/src/transaction.c
index 17ffc46..08492fb 100644
--- a/src/transaction.c
+++ b/src/transaction.c
@@ -57,21 +57,23 @@ BELLESIP_EXPORT const char *belle_sip_transaction_get_method(const belle_sip_tra
 
 static void transaction_end_background_task(belle_sip_transaction_t *obj){
 	if (obj->bg_task_id){
-		belle_sip_message("channel [%p]: ending transaction background task with id=[%lx].",obj,obj->bg_task_id);
+		belle_sip_message("transaction [%p]: ending transaction background task with id=[%lx].",obj,obj->bg_task_id);
 		belle_sip_end_background_task(obj->bg_task_id);
 		obj->bg_task_id=0;
 	}
 }
 
 static void transaction_background_task_ended(belle_sip_transaction_t *obj){
-	belle_sip_warning("channel [%p]: transaction background task has to be ended now, but work isn't finished.",obj);
+	belle_sip_warning("transaction [%p]: transaction background task has to be ended now, but work isn't finished.",obj);
 	transaction_end_background_task(obj);
 }
 
 static void transaction_begin_background_task(belle_sip_transaction_t *obj){
 	if (obj->bg_task_id==0){
-		obj->bg_task_id=belle_sip_begin_background_task("belle-sip transaction",(void (*)(void*))transaction_background_task_ended, obj);
-		if (obj->bg_task_id) belle_sip_message("channel [%p]: starting transaction background task with id=[%lx].",obj,obj->bg_task_id);
+		char *transaction = bctbx_strdup_printf("belle-sip transaction(%p)", obj);
+        obj->bg_task_id=belle_sip_begin_background_task(transaction,(void (*)(void*))transaction_background_task_ended, obj);
+        if (obj->bg_task_id) belle_sip_message("transaction [%p]: starting transaction background task with id=[%lx].",obj,obj->bg_task_id);
+        bctbx_free(transaction);
 	}
 }
 
@@ -171,7 +173,7 @@ static void on_channel_state_changed(belle_sip_channel_listener_t *l, belle_sip_
 				t->channel = NULL;
 			}
 			belle_sip_object_unref(t);
-			
+
 		break;
 		default:
 			/*ignored*/
@@ -277,7 +279,7 @@ void belle_sip_transaction_notify_timeout(belle_sip_transaction_t *t){
 	belle_sip_object_ref(t);  /*take a ref in the case where the app calls belle_sip_transaction_terminate() within the timeout listener*/
 	if (strcmp(belle_sip_request_get_method(t->request),"REGISTER")==0){
 		if ( belle_sip_channel_notify_timeout(t->channel)==TRUE){
-			belle_sip_warning("Transaction [%p] reporting timeout, reporting to channel.",t);
+			belle_sip_warning("Transaction [%p] has timeout, reported to channel.",t);
 			t->timed_out=TRUE;
 		}
 	}else {
@@ -489,13 +491,13 @@ int belle_sip_client_transaction_send_request_to(belle_sip_client_transaction_t
 	}
 
 	if (t->base.sent_by_dialog_queue){
-		
+
 		/*it can be sent immediately, so update the request with latest cseq and route_set */
 		/*update route and contact just in case they changed*/
 		belle_sip_dialog_update_request(dialog,req);
 	} else if (t->base.request->dialog_queued){
 		/*this request was created by belle_sip_dialog_create_queued_request().*/
-		
+
 		if (dialog == NULL){
 			belle_sip_error("belle_sip_client_transaction_send_request(): transaction [%p], cannot send"
 				" request because it was created in the context of a dialog that appears to be "
@@ -503,7 +505,7 @@ int belle_sip_client_transaction_send_request_to(belle_sip_client_transaction_t
 			belle_sip_transaction_terminate(BELLE_SIP_TRANSACTION(t));
 			return -1;
 		}
-		
+
 		if (belle_sip_dialog_request_pending(dialog) || dialog->queued_ct!=NULL){
 			/*it cannot be sent immediately, queue the transaction into dialog*/
 			belle_sip_message("belle_sip_client_transaction_send_request(): transaction [%p], cannot send request now because dialog [%p] is busy"
@@ -694,8 +696,8 @@ belle_sip_request_t* belle_sip_client_transaction_create_authenticated_request(b
  contains a "Subscription-State" of "active" or "pending", it creates
  a new subscription and a new dialog (unless they have already been
  created by a matching response, as described above).
- 
- 
+
+
  */
 
 int belle_sip_client_transaction_is_notify_matching_pending_subscribe(belle_sip_client_transaction_t *trans
@@ -704,32 +706,32 @@ int belle_sip_client_transaction_is_notify_matching_pending_subscribe(belle_sip_
 	belle_sip_header_event_t *sub_event, *notif_event;
 	belle_sip_header_call_id_t *sub_call_id, *notif_call_id;
 	const char* sub_from_tag, *notif_to_tag;
-	
+
 	if (!belle_sip_transaction_state_is_transient(belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(trans)))
 		|| strcmp("SUBSCRIBE", belle_sip_transaction_get_method(BELLE_SIP_TRANSACTION(trans)))!=0) return 0;
-	
-	
+
+
 	if (strcmp("NOTIFY",belle_sip_request_get_method(notify)) != 0) {
 		belle_sip_error("belle_sip_client_transaction_is_notify_matching_pending_subscribe for dialog [%p], requires a notify request",notify);
 	}
-	
+
 	subscription = belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(trans));
 	sub_event = belle_sip_message_get_header_by_type(subscription, belle_sip_header_event_t);
 	if (!sub_event || !belle_sip_header_event_get_package_name(sub_event))
 		return 0;
-	
+
 	notif_event = belle_sip_message_get_header_by_type(notify, belle_sip_header_event_t);
 	if (!notif_event || !belle_sip_header_event_get_package_name(notif_event))
 		return 0;
-	
+
 	sub_call_id = belle_sip_message_get_header_by_type(subscription, belle_sip_header_call_id_t);
 	notif_call_id = belle_sip_message_get_header_by_type(notify, belle_sip_header_call_id_t);
 	sub_from_tag = belle_sip_header_from_get_tag(belle_sip_message_get_header_by_type(subscription, belle_sip_header_from_t));
 	notif_to_tag = belle_sip_header_to_get_tag(belle_sip_message_get_header_by_type(notify, belle_sip_header_to_t));
-	
+
 	return strcmp(belle_sip_header_call_id_get_call_id(sub_call_id),belle_sip_header_call_id_get_call_id(notif_call_id))==0
 	&& sub_from_tag && notif_to_tag && strcmp(sub_from_tag,notif_to_tag)==0
 	&& strcasecmp(belle_sip_header_event_get_package_name(sub_event),belle_sip_header_event_get_package_name(notif_event))==0;
-	
+
 }
 
diff --git a/src/transports/stream_channel.c b/src/transports/stream_channel.c
index c03539a..503bcef 100644
--- a/src/transports/stream_channel.c
+++ b/src/transports/stream_channel.c
@@ -22,7 +22,7 @@
 
 static void set_tcp_nodelay(belle_sip_socket_t sock){
 	int tmp=1;
-	int err=setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,(char*)&tmp,sizeof(tmp));
+	int err=bctbx_setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,(char*)&tmp,sizeof(tmp));
 	if (err == -1){
 		belle_sip_warning ("Fail to set TCP_NODELAY: %s.", belle_sip_get_socket_error_string());
 	}
@@ -124,16 +124,16 @@ int stream_channel_connect(belle_sip_stream_channel_t *obj, const struct addrinf
 	tmp=1;
 	
 	obj->base.ai_family=ai->ai_family;
-	sock=socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP);
+	sock=bctbx_socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP);
 	
 	if (sock==(belle_sip_socket_t)-1){
 		belle_sip_error("Could not create socket: %s",belle_sip_get_socket_error_string());
 		return -1;
 	}
 	
-	err=setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,(char*)&tmp,sizeof(tmp));
+	err=bctbx_setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,(char*)&tmp,sizeof(tmp));
 	if (err!=0){
-		belle_sip_error("setsockopt TCP_NODELAY failed: [%s]",belle_sip_get_socket_error_string());
+		belle_sip_error("bctbx_setsockopt TCP_NODELAY failed: [%s]",belle_sip_get_socket_error_string());
 	}
 	belle_sip_socket_set_nonblocking(sock);
 	if (ai->ai_family==AF_INET6){
@@ -187,14 +187,14 @@ int finalize_stream_connection(belle_sip_stream_channel_t *obj, unsigned int rev
 		return -1;
 	}
 	
-	err=getsockopt(sock,SOL_SOCKET,SO_ERROR,(void*)&errnum,&optlen);
+	err=bctbx_getsockopt(sock,SOL_SOCKET,SO_ERROR,(void*)&errnum,&optlen);
 	if (err!=0){
 		belle_sip_error("Failed to retrieve connection status for fd [%i]: cause [%s]",sock,belle_sip_get_socket_error_string());
 		return -1;
 	}else{
 		if (errnum==0){
 			/*obtain bind address for client*/
-			err=getsockname(sock,addr,slen);
+			err=bctbx_getsockname(sock,addr,slen);
 			if (err<0){
 				belle_sip_error("Failed to retrieve sockname  for fd [%i]: cause [%s]",sock,belle_sip_get_socket_error_string());
 				return -1;
@@ -261,7 +261,7 @@ belle_sip_channel_t * belle_sip_stream_channel_new_child(belle_sip_stack_t *stac
 	int err;
 	int optval=1;
 	
-	err = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+	err = bctbx_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
 			(char*)&optval, sizeof (optval));
 	if (err == -1){
 		belle_sip_warning ("Fail to set SIP/TCP address reusable: %s.", belle_sip_get_socket_error_string());
@@ -269,8 +269,8 @@ belle_sip_channel_t * belle_sip_stream_channel_new_child(belle_sip_stack_t *stac
 	
 	set_tcp_nodelay(sock);
 	
-	if (getsockname(sock,(struct sockaddr*)&localaddr,&local_len)==-1){
-		belle_sip_error("getsockname() failed: %s",belle_sip_get_socket_error_string());
+	if (bctbx_getsockname(sock,(struct sockaddr*)&localaddr,&local_len)==-1){
+		belle_sip_error("bctbx_getsockname() failed: %s",belle_sip_get_socket_error_string());
 		return NULL;
 	}
 	
diff --git a/src/transports/stream_channel.h b/src/transports/stream_channel.h
index 169ae0b..12b2af4 100644
--- a/src/transports/stream_channel.h
+++ b/src/transports/stream_channel.h
@@ -43,7 +43,7 @@ BELLE_SIP_DECLARE_CUSTOM_VPTR_END
 
 void belle_sip_stream_channel_init_client(belle_sip_stream_channel_t *obj, belle_sip_stack_t *stack, const char *bindip, int localport,const char *peer_cname, const char *dest, int port);
 
-BELLESIP_INTERNAL_EXPORT belle_sip_channel_t * belle_sip_stream_channel_new_client(belle_sip_stack_t *stack, const char *bindip, int localport, const char *peer_cname, const char *name, int port);
+BELLESIP_EXPORT belle_sip_channel_t * belle_sip_stream_channel_new_client(belle_sip_stack_t *stack, const char *bindip, int localport, const char *peer_cname, const char *name, int port);
 belle_sip_channel_t * belle_sip_stream_channel_new_child(belle_sip_stack_t *stack, belle_sip_socket_t sock, struct sockaddr *remote_addr, socklen_t slen);
 
 void stream_channel_close(belle_sip_stream_channel_t *obj);
@@ -55,5 +55,5 @@ int stream_channel_recv(belle_sip_stream_channel_t *obj, void *buf, size_t bufle
 
 
 /*for testing purpose*/
-BELLESIP_INTERNAL_EXPORT void belle_sip_channel_parse_stream(belle_sip_channel_t *obj, int end_of_stream);
+BELLESIP_EXPORT void belle_sip_channel_parse_stream(belle_sip_channel_t *obj, int end_of_stream);
 #endif /* STREAM_CHANNEL_H_ */
diff --git a/src/transports/stream_listeningpoint.c b/src/transports/stream_listeningpoint.c
index 13c89c1..3c33c13 100644
--- a/src/transports/stream_listeningpoint.c
+++ b/src/transports/stream_listeningpoint.c
@@ -70,6 +70,8 @@ static belle_sip_socket_t create_server_socket(const char *addr, int * port, int
 	
 	if (*port==-1) *port=0; /*random port for bind()*/
 
+	belle_sip_set_socket_api(NULL);
+
 	snprintf(portnum,sizeof(portnum),"%i",*port);
 	hints.ai_family=AF_UNSPEC;
 	hints.ai_socktype=SOCK_STREAM;
@@ -81,13 +83,13 @@ static belle_sip_socket_t create_server_socket(const char *addr, int * port, int
 		return -1;
 	}
 	*family=res->ai_family;
-	sock=socket(res->ai_family,res->ai_socktype,res->ai_protocol);
+	sock=bctbx_socket(res->ai_family,res->ai_socktype,res->ai_protocol);
 	if (sock==(belle_sip_socket_t)-1){
 		belle_sip_error("Cannot create TCP socket: %s",belle_sip_get_socket_error_string());
 		freeaddrinfo(res);
 		return -1;
 	}
-	err = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+	err = bctbx_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
 			(char*)&optval, sizeof (optval));
 	if (err == -1){
 		belle_sip_warning ("Fail to set SIP/TCP address reusable: %s.", belle_sip_get_socket_error_string());
@@ -108,14 +110,14 @@ static belle_sip_socket_t create_server_socket(const char *addr, int * port, int
 	if (*port==0){
 		struct sockaddr_storage saddr;
 		socklen_t saddr_len=sizeof(saddr);
-		err=getsockname(sock,(struct sockaddr*)&saddr,&saddr_len);
+		err=bctbx_getsockname(sock,(struct sockaddr*)&saddr,&saddr_len);
 		if (err==0){
 			err=bctbx_getnameinfo((struct sockaddr*)&saddr,saddr_len,NULL,0,portnum,sizeof(portnum),NI_NUMERICSERV|NI_NUMERICHOST);
 			if (err==0){
 				*port=atoi(portnum);
 				belle_sip_message("Random TCP port is %i",*port);
 			}else belle_sip_error("TCP bind failed, getnameinfo(): %s",gai_strerror(err));
-		}else belle_sip_error("TCP bind failed, getsockname(): %s",belle_sip_get_socket_error_string());
+		}else belle_sip_error("TCP bind failed, bctbx_getsockname(): %s",belle_sip_get_socket_error_string());
 	}
 	
 	err=listen(sock,64);
diff --git a/src/transports/tls_channel.c b/src/transports/tls_channel.c
index e4a7d50..a5e2620 100644
--- a/src/transports/tls_channel.c
+++ b/src/transports/tls_channel.c
@@ -413,7 +413,7 @@ static int tls_channel_connect_to(belle_sip_channel_t *obj, const struct addrinf
 	return -1;
 }
 
-static void http_proxy_res_done(void *data, const char *name, struct addrinfo *ai_list){
+static void http_proxy_res_done(void *data, const char *name, struct addrinfo *ai_list, uint32_t ttl){
 	belle_sip_tls_channel_t *obj=(belle_sip_tls_channel_t*)data;
 	if (obj->http_proxy_resolver_ctx){
 		belle_sip_object_unref(obj->http_proxy_resolver_ctx);
diff --git a/src/transports/udp_listeningpoint.c b/src/transports/udp_listeningpoint.c
index 2b27be2..55bb2aa 100644
--- a/src/transports/udp_listeningpoint.c
+++ b/src/transports/udp_listeningpoint.c
@@ -70,6 +70,9 @@ static belle_sip_socket_t create_udp_socket(const char *addr, int *port, int *fa
 	
 	if (*port==-1) *port=0; /*random port for bind()*/
 
+	belle_sip_set_socket_api(NULL);
+
+
 	snprintf(portnum,sizeof(portnum),"%i",*port);
 	hints.ai_family=AF_UNSPEC;
 	hints.ai_socktype=SOCK_DGRAM;
@@ -81,13 +84,13 @@ static belle_sip_socket_t create_udp_socket(const char *addr, int *port, int *fa
 		return -1;
 	}
 	*family=res->ai_family;
-	sock=socket(res->ai_family,res->ai_socktype,res->ai_protocol);
+	sock=bctbx_socket(res->ai_family,res->ai_socktype,res->ai_protocol);
 	if (sock==-1){
 		belle_sip_error("Cannot create UDP socket: %s",belle_sip_get_socket_error_string());
 		freeaddrinfo(res);
 		return -1;
 	}
-	err = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+	err = bctbx_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
 			(char*)&optval, sizeof (optval));
 	if (err == -1){
 		belle_sip_warning ("Fail to set SIP/UDP address reusable: %s.", belle_sip_get_socket_error_string());
@@ -96,7 +99,7 @@ static belle_sip_socket_t create_udp_socket(const char *addr, int *port, int *fa
 		belle_sip_socket_enable_dual_stack(sock);
 	}
 	
-	err=bctbx_bind(sock,res->ai_addr,(socklen_t)res->ai_addrlen);
+	err=bctbx_bind(sock,res->ai_addr,(socklen_t)res->ai_addrlen);	
 	if (err==-1){
 		belle_sip_error("udp bind() failed for %s port %i: %s",addr,*port,belle_sip_get_socket_error_string());
 		belle_sip_close_socket(sock);
@@ -107,14 +110,14 @@ static belle_sip_socket_t create_udp_socket(const char *addr, int *port, int *fa
 	if (*port==0){
 		struct sockaddr_storage saddr;
 		socklen_t saddr_len=sizeof(saddr);
-		err=getsockname(sock,(struct sockaddr*)&saddr,&saddr_len);
+		err=bctbx_getsockname(sock,(struct sockaddr*)&saddr,&saddr_len);
 		if (err==0){
 			err=bctbx_getnameinfo((struct sockaddr*)&saddr,saddr_len,NULL,0,portnum,sizeof(portnum),NI_NUMERICSERV|NI_NUMERICHOST);
 			if (err==0){
 				*port=atoi(portnum);
 				belle_sip_message("Random UDP port is %i",*port);
 			}else belle_sip_error("udp bind failed, getnameinfo(): %s",gai_strerror(err));
-		}else belle_sip_error("udp bind failed, getsockname(): %s",belle_sip_get_socket_error_string());
+		}else belle_sip_error("udp bind failed, bctbx_getsockname(): %s",belle_sip_get_socket_error_string());
 	}
 	return sock;
 }
diff --git a/tester/CMakeLists.txt b/tester/CMakeLists.txt
index d0cd98d..fa16b09 100644
--- a/tester/CMakeLists.txt
+++ b/tester/CMakeLists.txt
@@ -41,6 +41,7 @@ set(SOURCE_FILES_C
 	belle_sip_tester.c
 	belle_sip_tester.h
 	belle_sip_uri_tester.c
+	belle_sip_fast_uri_tester.c
 	cast_test.c
 	register_tester.h
 )
@@ -51,8 +52,8 @@ if (IOS)
 endif()
 
 string(REPLACE ";" " " LINK_FLAGS_STR "${LINK_FLAGS}")
-apply_compile_flags(SOURCE_FILES_C "CPP" "C")
-apply_compile_flags(SOURCE_FILES_OBJC "CPP" "OBJC")
+bc_apply_compile_flags(SOURCE_FILES_C STRICT_OPTIONS_CPP STRICT_OPTIONS_C)
+bc_apply_compile_flags(SOURCE_FILES_OBJC STRICT_OPTIONS_CPP STRICT_OPTIONS_OBJC)
 
 if(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
 	add_library(belle_sip_tester_static STATIC ${SOURCE_FILES_C})
@@ -110,8 +111,9 @@ else()
 
 
 	set(OBJECT_DESCRIBE_SOURCES describe.c)
-	apply_compile_flags(OBJECT_DESCRIBE_SOURCES "CPP" "C")
+	bc_apply_compile_flags(OBJECT_DESCRIBE_SOURCES STRICT_OPTIONS_CPP STRICT_OPTIONS_C)
 	add_executable(belle_sip_object_describe ${USE_BUNDLE} ${OBJECT_DESCRIBE_SOURCES})
+	set_target_properties(belle_sip_object_describe PROPERTIES LINKER_LANGUAGE CXX)
 	if(NOT "${LINK_FLAGS_STR}" STREQUAL "")
 		set_target_properties(belle_sip_object_describe PROPERTIES LINK_FLAGS "${LINK_FLAGS_STR}")
 	endif()
@@ -120,8 +122,9 @@ else()
 
 	set(PARSE_SOURCES parse.c)
 
-	apply_compile_flags(PARSE_SOURCES "CPP" "C")
+	bc_apply_compile_flags(PARSE_SOURCES STRICT_OPTIONS_CPP STRICT_OPTIONS_C)
 	add_executable(belle_sip_parse ${USE_BUNDLE} ${PARSE_SOURCES})
+	set_target_properties(belle_sip_parse PROPERTIES LINKER_LANGUAGE CXX)
 	if(NOT "${LINK_FLAGS_STR}" STREQUAL "")
 		set_target_properties(belle_sip_parse PROPERTIES LINK_FLAGS "${LINK_FLAGS_STR}")
 	endif()
diff --git a/tester/Makefile.am b/tester/Makefile.am
index bad6d64..45de779 100644
--- a/tester/Makefile.am
+++ b/tester/Makefile.am
@@ -3,6 +3,8 @@ if ENABLE_TESTS
 
 noinst_PROGRAMS=belle_sip_tester belle_sip_object_describe belle_sip_parse belle_http_get belle_sip_resolve
 
+EXTRA_DIST= belle_sip_base_uri_tester.c
+
 belle_sip_tester_SOURCES= \
 				auth_helper_tester.c \
 				belle_generic_uri_tester.c \
@@ -17,6 +19,7 @@ belle_sip_tester_SOURCES= \
 				belle_sip_resolver_tester.c \
 				belle_sip_tester.c belle_sip_tester.h\
 				belle_sip_uri_tester.c \
+				belle_sip_fast_uri_tester.c \
 				cast_test.c \
 				register_tester.h
 
diff --git a/tester/belle_sip_uri_tester.c b/tester/belle_sip_base_uri_tester.c
similarity index 98%
copy from tester/belle_sip_uri_tester.c
copy to tester/belle_sip_base_uri_tester.c
index 5b2abeb..20d3c91 100644
--- a/tester/belle_sip_uri_tester.c
+++ b/tester/belle_sip_base_uri_tester.c
@@ -39,7 +39,7 @@ static void testSIMPLEURI(void) {
 
 static void testCOMPLEXURI(void) {
 	belle_sip_uri_t* L_tmp;
-	belle_sip_uri_t *  L_uri = belle_sip_uri_parse("sip:toto at titi.com:5060;transport=tcp");
+	belle_sip_uri_t *  L_uri = belle_sip_uri_parse("sip:toto at 1titi.com:5060;transport=tcp");
 	char* l_raw_uri = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_uri));
 	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
 	L_tmp = belle_sip_uri_parse(l_raw_uri);
@@ -48,7 +48,7 @@ static void testCOMPLEXURI(void) {
 	belle_sip_free(l_raw_uri);
 	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_user(L_uri), "toto");
 	BC_ASSERT_EQUAL(belle_sip_uri_get_port(L_uri), 5060, int, "%d");
-	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_host(L_uri), "titi.com");
+	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_host(L_uri), "1titi.com");
 	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_transport_param(L_uri), "tcp");
 	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
 }
@@ -402,7 +402,7 @@ transp.-param (2)         o      -    -       o          o         o
 lr-param      --          o      -    -       -          o         o
 other-param   --          o      o    o       o          o         o
 headers       --          -      -    -       o          -         o*/
-void testUriComponentsChecker(void) {
+static void testUriComponentsChecker(void) {
 	belle_sip_uri_t* uri = belle_sip_uri_parse("sip:hostonly");
 	BC_ASSERT_TRUE(belle_sip_uri_check_components_from_request_uri(uri));
 	belle_sip_object_unref(uri);
@@ -435,7 +435,7 @@ void testUriComponentsChecker(void) {
 	}
 }
 
-void test_escaping_bad_chars(void){
+static void test_escaping_bad_chars(void){
 	char bad_uri[13] = { 'h', 'e', 'l', 'l', 'o', (char)0xa0, (char)0xc8, 'w', 'o', 'r', 'l', 'd', 0x0 };
 	char *escaped = belle_sip_uri_to_escaped_username(bad_uri);
 	const char *expected="hello%a0%c8world";
@@ -501,5 +501,3 @@ static test_t uri_tests[] = {
 	TEST_NO_TAG("Empty password", test_empty_password),
 };
 
-test_suite_t sip_uri_test_suite = {"SIP URI", NULL, NULL, belle_sip_tester_before_each, belle_sip_tester_after_each,
-								   sizeof(uri_tests) / sizeof(uri_tests[0]), uri_tests};
diff --git a/tester/belle_sip_fast_uri_tester.c b/tester/belle_sip_fast_uri_tester.c
new file mode 100644
index 0000000..ef2e15f
--- /dev/null
+++ b/tester/belle_sip_fast_uri_tester.c
@@ -0,0 +1,62 @@
+
+/*
+	belle-sip - SIP (RFC3261) library.
+ Copyright (C) 2010  Belledonne Communications SARL
+ 
+ This program 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.
+ 
+ This program 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "belle-sip/belle-sip.h"
+#include "belle_sip_tester.h"
+#include "belle_sip_internal.h"
+
+#include <inttypes.h>
+
+#define belle_sip_uri_parse belle_sip_fast_uri_parse
+
+/*test body*/
+#include "belle_sip_base_uri_tester.c"
+
+#undef belle_sip_uri_parse
+
+static void perf(void) {
+	uint64_t t1, t2, start=bctbx_get_cur_time_ms();
+	int i=0;
+	for (i=0;i<1000;i++) {
+		belle_sip_uri_t * uri = belle_sip_uri_parse("sip:+331231231231 at sip.exmaple.org;user=phone");
+		belle_sip_object_unref(uri);
+	}
+	
+	t1 = bctbx_get_cur_time_ms() - start;
+	start=bctbx_get_cur_time_ms();
+	belle_sip_message("t1 = %" PRIu64 "",t1);
+	
+	for (i=0;i<1000;i++) {
+		belle_sip_uri_t * uri = belle_sip_fast_uri_parse("sip:+331231231231 at sip.exmaple.org;user=phone");
+		belle_sip_object_unref(uri);
+	}
+	t2 = bctbx_get_cur_time_ms() - start;
+	belle_sip_message("t2 = %" PRIu64 "",t2);
+#ifdef __APPLE__ /*antlr3.4 seems much more sensitive to belle_sip_fast_uri_parse optimisation than 3.2, so reserving this test to apple platform where antlr3.2 is unlikely to be found*/
+	BC_ASSERT_GREATER(((float)(t1-t2))/(float)(t1), 0.4, float, "%f");
+#endif
+}
+static test_t tests[] ={TEST_NO_TAG("perf", perf)};
+
+
+test_suite_t fast_sip_uri_test_suite = {"FAST SIP URI", NULL, NULL, belle_sip_tester_before_each, belle_sip_tester_after_each,
+	sizeof(uri_tests) / sizeof(uri_tests[0]), uri_tests};
+
+test_suite_t perf_sip_uri_test_suite = {"FAST SIP URI 2", NULL, NULL, belle_sip_tester_before_each, belle_sip_tester_after_each,
+	sizeof(tests) / sizeof(tests[0]), tests};
diff --git a/tester/belle_sip_headers_tester.c b/tester/belle_sip_headers_tester.c
index 3a53b52..b0a019b 100644
--- a/tester/belle_sip_headers_tester.c
+++ b/tester/belle_sip_headers_tester.c
@@ -741,7 +741,7 @@ static void test_address_with_error_header(void) {
 static void test_address_header(void) {
 	belle_sip_uri_t* L_uri;
 	char* L_raw;
-	belle_sip_header_address_t* laddress = belle_sip_header_address_parse("\"toto\" <sip:liblinphone_tester at 81.56.11.2:5060>");
+	belle_sip_header_address_t* laddress = belle_sip_header_address_fast_parse("\"toto\" <sip:liblinphone_tester at 81.56.11.2:5060>");
 	BC_ASSERT_PTR_NOT_NULL(laddress);
 	L_raw = belle_sip_object_to_string(BELLE_SIP_OBJECT(laddress));
 	BC_ASSERT_PTR_NOT_NULL(L_raw);
@@ -768,6 +768,15 @@ static void test_address_header(void) {
 	BC_ASSERT_STRING_EQUAL("\"to\\to\"",belle_sip_header_address_get_displayname(laddress));
 	belle_sip_object_unref(BELLE_SIP_OBJECT(laddress));
 
+	laddress = belle_sip_header_address_parse("sips:example.com;transport=tls;maddr=sip1.example.com");
+	BC_ASSERT_PTR_NOT_NULL(laddress);
+	L_raw = belle_sip_object_to_string(BELLE_SIP_OBJECT(laddress));
+	BC_ASSERT_PTR_NOT_NULL(L_raw);
+	belle_sip_object_unref(BELLE_SIP_OBJECT(laddress));
+	laddress = belle_sip_header_address_parse(L_raw);
+	belle_sip_free(L_raw);
+	BC_ASSERT_STRING_EQUAL("sip1.example.com",belle_sip_uri_get_maddr_param(belle_sip_header_address_get_uri(laddress)));
+	belle_sip_object_unref(BELLE_SIP_OBJECT(laddress));
 
 
 }
@@ -775,7 +784,7 @@ static void test_address_header(void) {
 static void test_address_header_with_tel_uri(void) {
 	belle_generic_uri_t* L_uri;
 	char* L_raw;
-	belle_sip_header_address_t* laddress = belle_sip_header_address_parse("\"toto\" <tel:123456>");
+	belle_sip_header_address_t* laddress = belle_sip_header_address_fast_parse("\"toto\" <tel:123456>");
 	BC_ASSERT_PTR_NOT_NULL(laddress);
 	L_raw = belle_sip_object_to_string(BELLE_SIP_OBJECT(laddress));
 	BC_ASSERT_PTR_NOT_NULL(L_raw);
@@ -791,6 +800,27 @@ static void test_address_header_with_tel_uri(void) {
 	belle_sip_object_unref(BELLE_SIP_OBJECT(laddress));
 }
 
+static void test_address_header_with_urn(void) {
+	belle_generic_uri_t* L_uri;
+	char* L_raw;
+	belle_sip_header_address_t* laddress = belle_sip_header_address_fast_parse("urn:service:sos");
+	BC_ASSERT_PTR_NOT_NULL(laddress);
+	L_raw = belle_sip_object_to_string(BELLE_SIP_OBJECT(laddress));
+	BC_ASSERT_PTR_NOT_NULL(L_raw);
+	belle_sip_object_unref(BELLE_SIP_OBJECT(laddress));
+	laddress = belle_sip_header_address_parse(L_raw);
+	belle_sip_free(L_raw);
+
+	BC_ASSERT_PTR_NULL(belle_sip_header_address_get_displayname(laddress));
+	L_uri = belle_sip_header_address_get_absolute_uri(laddress);
+
+	BC_ASSERT_PTR_NOT_NULL(belle_generic_uri_get_scheme(L_uri));
+	BC_ASSERT_STRING_EQUAL(belle_generic_uri_get_scheme(L_uri), "urn");
+	BC_ASSERT_PTR_NOT_NULL(belle_generic_uri_get_opaque_part(L_uri));
+	BC_ASSERT_STRING_EQUAL(belle_generic_uri_get_opaque_part(L_uri), "service:sos");
+	belle_sip_object_unref(BELLE_SIP_OBJECT(laddress));
+}
+
 static void test_very_long_address_header(void) {
 	belle_sip_uri_t* L_uri;
 	const char* raw = "<sip:jehan at sip.linphone.org"
@@ -1133,10 +1163,69 @@ static void test_accept_header(void) {
 
 	BC_ASSERT_PTR_NULL(belle_sip_header_accept_parse("nimportequoi"));
 }
+static void test_reason_header(void) {
+	belle_sip_header_reason_t *L_tmp, *l_next;
+	belle_sip_header_reason_t* L_reason = BELLE_SIP_HEADER_REASON(belle_sip_header_create("Reason", "Q.850 ;cause=16 ;text=\"Busy Everywhere\""));
+	char* l_raw_header;
+	
+	BC_ASSERT_STRING_EQUAL(belle_sip_header_reason_get_text(L_reason),"Busy Everywhere");
+	belle_sip_header_reason_set_text(L_reason, "Terminated");
+	l_raw_header = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_reason));
+	
+	belle_sip_object_unref(BELLE_SIP_OBJECT(L_reason));
+	L_tmp = belle_sip_header_reason_parse(l_raw_header);
+	L_reason = BELLE_SIP_HEADER_REASON(belle_sip_object_clone(BELLE_SIP_OBJECT(L_tmp)));
+	belle_sip_object_unref(BELLE_SIP_OBJECT(L_tmp));
+	
+	BC_ASSERT_STRING_EQUAL(belle_sip_header_reason_get_text(L_reason),"Terminated");
+	BC_ASSERT_STRING_EQUAL(belle_sip_header_reason_get_protocol(L_reason),"Q.850");
+	BC_ASSERT_EQUAL(belle_sip_header_reason_get_cause(L_reason),16 , int,"%d");
+	belle_sip_object_unref(BELLE_SIP_OBJECT(L_reason));
+	belle_sip_free(l_raw_header);
+
+	L_reason = belle_sip_header_reason_parse("Reason: SIP ;cause=600 ;text=\"Busy Everywhere\", SIP ;cause=580 ;text=\"Precondition Failure\"");
+	l_next =BELLE_SIP_HEADER_REASON(belle_sip_header_get_next(BELLE_SIP_HEADER(L_reason)));
+	BC_ASSERT_PTR_NOT_NULL(l_next);
+	BC_ASSERT_EQUAL(belle_sip_header_reason_get_cause(l_next),580 , int,"%d");
+	belle_sip_object_unref(BELLE_SIP_OBJECT(L_reason));
+
+	
+	BC_ASSERT_PTR_NULL(belle_sip_header_reason_parse("nimportequoi"));
+}
+static void test_authentication_info_header(void) {
+	belle_sip_header_authentication_info_t *L_tmp;
+	belle_sip_header_authentication_info_t* L_authentication_info = BELLE_SIP_HEADER_AUTHENTICATION_INFO(belle_sip_header_create("Authentication-Info"
+																													, "nextnonce=\"47364c23432d2e131a5fb210812c\""
+																														", qop=auth"));
+	char* l_raw_header;
+	
+	BC_ASSERT_STRING_EQUAL(belle_sip_header_authentication_info_get_next_nonce(L_authentication_info),"47364c23432d2e131a5fb210812c");
+	belle_sip_header_authentication_info_set_next_nonce(L_authentication_info, "31a5fb210812c47364c23432d2e1");
+	l_raw_header = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_authentication_info));
+	
+	belle_sip_object_unref(BELLE_SIP_OBJECT(L_authentication_info));
+	L_tmp = belle_sip_header_authentication_info_parse(l_raw_header);
+	L_authentication_info = BELLE_SIP_HEADER_AUTHENTICATION_INFO(belle_sip_object_clone(BELLE_SIP_OBJECT(L_tmp)));
+	belle_sip_object_unref(BELLE_SIP_OBJECT(L_tmp));
+	
+	BC_ASSERT_STRING_EQUAL(belle_sip_header_authentication_info_get_next_nonce(L_authentication_info),"31a5fb210812c47364c23432d2e1");
+	BC_ASSERT_STRING_EQUAL(belle_sip_header_authentication_info_get_qop(L_authentication_info),"auth");
+	
+	belle_sip_object_unref(BELLE_SIP_OBJECT(L_authentication_info));
+	belle_sip_free(l_raw_header);
+	
+	
+	L_authentication_info = belle_sip_header_authentication_info_parse("Authentication-Info:nextnonce=\"WRSE5VkUg7kOjnP5sBZZzsxrsOQ8Eyp6ZNttXIA=\", qop=auth , rspauth=\"5e8518291c1320989df6966405e0b3d1\", cnonce=\"05bc00e63a7794182f9425da9266d00d\", nc=00000001");
+	BC_ASSERT_EQUAL(belle_sip_header_authentication_info_get_nonce_count(L_authentication_info),1, int, "%i");
+	belle_sip_object_unref(BELLE_SIP_OBJECT(L_authentication_info));
+	
+	BC_ASSERT_PTR_NULL(belle_sip_header_authentication_info_parse("nimportequoi"));
+}
 
 test_t headers_tests[] = {
 	TEST_NO_TAG("Address", test_address_header),
 	TEST_NO_TAG("Address tel uri", test_address_header_with_tel_uri),
+	TEST_NO_TAG("Address urn", test_address_header_with_urn),
 	TEST_NO_TAG("Header address (very long)", test_very_long_address_header),
 	TEST_NO_TAG("Address with error", test_address_with_error_header),
 	TEST_NO_TAG("Allow", test_allow_header),
@@ -1175,7 +1264,9 @@ test_t headers_tests[] = {
 	TEST_NO_TAG("Header event", test_event_header),
 	TEST_NO_TAG("Header Supported", test_supported_header),
 	TEST_NO_TAG("Header Content-Disposition", test_content_disposition_header),
-	TEST_NO_TAG("Header Accept", test_accept_header)
+	TEST_NO_TAG("Header Accept", test_accept_header),
+	TEST_NO_TAG("Header Reason", test_reason_header),
+	TEST_NO_TAG("Header Authentication-Info", test_authentication_info_header)
 };
 
 test_suite_t headers_test_suite = {"Headers", NULL, NULL, belle_sip_tester_before_each, belle_sip_tester_after_each,
diff --git a/tester/belle_sip_register_tester.c b/tester/belle_sip_register_tester.c
index 8de8c53..d12b6d7 100644
--- a/tester/belle_sip_register_tester.c
+++ b/tester/belle_sip_register_tester.c
@@ -766,7 +766,7 @@ static void process_message_response_event(void *user_ctx, const belle_sip_respo
 		}
 	}
 }
-static belle_sip_request_t* send_message(belle_sip_request_t *initial_request, const char* realm){
+static belle_sip_request_t* send_message_to(belle_sip_request_t *initial_request, const char* realm, belle_sip_uri_t *outbound){
 	int i;
 	int io_error_count=0;
 	belle_sip_request_t *message_request=NULL;
@@ -793,41 +793,54 @@ static belle_sip_request_t* send_message(belle_sip_request_t *initial_request, c
 	// 	belle_sip_header_set_name(BELLE_SIP_HEADER(h), BELLE_SIP_PROXY_AUTHORIZATION);
 	// }
 	clone_request = (belle_sip_request_t*)belle_sip_object_ref(belle_sip_object_clone((belle_sip_object_t*)message_request));
-	belle_sip_client_transaction_send_request_to(belle_sip_provider_create_client_transaction(prov,message_request),NULL);
+	belle_sip_client_transaction_send_request_to(belle_sip_provider_create_client_transaction(prov,message_request),outbound);
 	for(i=0; i<2 && io_error_count==0 &&is_register_ok==0;i++)
 		belle_sip_stack_sleep(stack,5000);
 
 	return clone_request;
 }
-static void reuse_nonce(void) {
+
+static void reuse_nonce_base(const char* outbound) {
 	belle_sip_request_t *register_request;
-	size_t initial_auth_context_count=belle_sip_list_size(prov->auth_contexts);
-	register_request=register_user_at_domain(stack, prov, "tcp",1,"marie","sip.linphone.org",NULL);
+	size_t initial_auth_context_count=0;/*belle_sip_list_size(prov->auth_contexts);*/
+	char outbound_uri[256];
+	/*reset auth context*/
+	prov->auth_contexts = belle_sip_list_free_with_data(prov->auth_contexts,(void(*)(void*))belle_sip_authorization_destroy);
+	
+	if (outbound)
+		snprintf(outbound_uri, sizeof(outbound_uri),"sip:%s",outbound);
+	
+	register_request=register_user_at_domain(stack, prov, "tcp",1,"marie",outbound,NULL);
+	
 	if (register_request) {
 		belle_sip_header_authorization_t * h = NULL;
 		belle_sip_request_t *message_request;
-		listener_callbacks.process_dialog_terminated=process_dialog_terminated;
-		listener_callbacks.process_io_error=process_io_error;
-		listener_callbacks.process_request_event=process_request_event;
-		listener_callbacks.process_response_event=process_message_response_event;
-		listener_callbacks.process_timeout=process_timeout;
-		listener_callbacks.process_transaction_terminated=process_transaction_terminated;
-		listener_callbacks.process_auth_requested=process_auth_requested;
-		listener_callbacks.listener_destroyed=NULL;
-		listener=belle_sip_listener_create_from_callbacks(&listener_callbacks,NULL);
-
-		belle_sip_provider_add_sip_listener(prov,BELLE_SIP_LISTENER(listener));
+		belle_sip_listener_callbacks_t cbs;
+		belle_sip_listener_t *reuse_nonce_listener;
+		cbs.process_dialog_terminated=process_dialog_terminated;
+		cbs.process_io_error=process_io_error;
+		cbs.process_request_event=process_request_event;
+		cbs.process_response_event=process_message_response_event;
+		cbs.process_timeout=process_timeout;
+		cbs.process_transaction_terminated=process_transaction_terminated;
+		cbs.process_auth_requested=process_auth_requested;
+		cbs.listener_destroyed=NULL;
+		reuse_nonce_listener=belle_sip_listener_create_from_callbacks(&cbs,NULL);
+
+		belle_sip_provider_add_sip_listener(prov,BELLE_SIP_LISTENER(reuse_nonce_listener));
 
 		/*currently only one nonce should have been used (the one for the REGISTER)*/
 		BC_ASSERT_EQUAL((unsigned int)belle_sip_list_size(prov->auth_contexts), (unsigned int)initial_auth_context_count+1,unsigned int,"%u");
 
 		/*this should reuse previous nonce*/
-		message_request=send_message(register_request, auth_domain);
+		message_request=send_message_to(register_request, auth_domain,outbound?belle_sip_uri_parse(outbound_uri):NULL);
 		BC_ASSERT_EQUAL(is_register_ok, 404,int,"%d");
 		h = BELLE_SIP_HEADER_AUTHORIZATION(belle_sip_message_get_header_by_type(
 					BELLE_SIP_MESSAGE(message_request), belle_sip_header_proxy_authorization_t
 				));
-		if (BC_ASSERT_PTR_NOT_NULL(h)) {
+		if (BC_ASSERT_PTR_NOT_NULL(h)
+			&& belle_sip_header_authorization_get_qop(h)
+			&& strcmp(belle_sip_header_authorization_get_qop(h),"auth")==0) {
 			char * first_nonce_used;
 			BC_ASSERT_EQUAL(2, belle_sip_header_authorization_get_nonce_count(h),int,"%d");
 			first_nonce_used = belle_sip_strdup(belle_sip_header_authorization_get_nonce(h));
@@ -837,7 +850,7 @@ static void reuse_nonce(void) {
 
 
 		/*new nonce should be created when not using outbound proxy realm*/
-		message_request=send_message(register_request, NULL);
+		message_request=send_message_to(register_request, NULL,outbound?belle_sip_uri_parse(outbound_uri):NULL);
 		BC_ASSERT_EQUAL(is_register_ok, 407,int,"%d");
 		h = BELLE_SIP_HEADER_AUTHORIZATION(belle_sip_message_get_header_by_type(
 				BELLE_SIP_MESSAGE(message_request), belle_sip_header_proxy_authorization_t
@@ -847,7 +860,7 @@ static void reuse_nonce(void) {
 
 
 		/*new nonce should be created here too*/
-		message_request=send_message(register_request, "wrongrealm");
+		message_request=send_message_to(register_request, "wrongrealm",outbound?belle_sip_uri_parse(outbound_uri):NULL);
 		BC_ASSERT_EQUAL(is_register_ok, 407,int,"%d");
 		h = BELLE_SIP_HEADER_AUTHORIZATION(belle_sip_message_get_header_by_type(
 				BELLE_SIP_MESSAGE(message_request), belle_sip_header_proxy_authorization_t
@@ -856,23 +869,106 @@ static void reuse_nonce(void) {
 		belle_sip_object_unref(message_request);
 
 
-		/*first nonce created should be reused*/
-		message_request=send_message(register_request, auth_domain);
-		BC_ASSERT_EQUAL(is_register_ok, 404,int,"%d");
+		/*first nonce created should be reused. this test is only for qop = auth*/
+		message_request=send_message_to(register_request, auth_domain,outbound?belle_sip_uri_parse(outbound_uri):NULL);
+		
 		h = BELLE_SIP_HEADER_AUTHORIZATION(belle_sip_message_get_header_by_type(
 				BELLE_SIP_MESSAGE(message_request), belle_sip_header_proxy_authorization_t
 			));
-		if (BC_ASSERT_PTR_NOT_NULL(h)) {
+		if (BC_ASSERT_PTR_NOT_NULL(h)
+			&& belle_sip_header_authorization_get_qop(h)
+			&& strcmp(belle_sip_header_authorization_get_qop(h),"auth")==0) {
+			BC_ASSERT_EQUAL(is_register_ok, 404,int,"%d");
 			BC_ASSERT_EQUAL(3, belle_sip_header_authorization_get_nonce_count(h),int,"%d");
 		}
 		belle_sip_object_unref(message_request);
 
-		belle_sip_provider_remove_sip_listener(prov,BELLE_SIP_LISTENER(listener));
+		belle_sip_provider_remove_sip_listener(prov,BELLE_SIP_LISTENER(reuse_nonce_listener));
 		unregister_user(stack,prov,register_request,1);
 		belle_sip_object_unref(register_request);
 	}
 }
+static void reuse_nonce(void) {
+	reuse_nonce_base("sip.linphone.org");
+}
+#define NONCE_SIZE  32
+void register_process_request_event(char *nonce, const belle_sip_request_event_t *event) {
+	belle_sip_request_t *req = belle_sip_request_event_get_request(event);
+	belle_sip_header_authorization_t *authorization;
+	int response_code = 407;
+	char *uri_as_string= belle_sip_uri_to_string(belle_sip_request_get_uri(req));
+	belle_sip_response_t * response_msg;
+	belle_sip_server_transaction_t *trans=belle_sip_provider_create_server_transaction(prov, req);
+	
+	if (strcasecmp(belle_sip_request_get_method(req), "REGISTER") == 0) {
+		response_code=401;
+	}
+	
+	if (	(authorization = belle_sip_message_get_header_by_type(req,belle_sip_header_authorization_t))
+		 || (authorization = BELLE_SIP_HEADER_AUTHORIZATION(belle_sip_message_get_header_by_type(req,belle_sip_header_proxy_authorization_t)))) {
+		 char ha1[33], ha2[33], response[33];
+		belle_sip_auth_helper_compute_ha1(belle_sip_header_authorization_get_username(authorization)
+										, belle_sip_header_authorization_get_realm(authorization)
+										  ,"secret", ha1);
+		belle_sip_auth_helper_compute_ha2(belle_sip_request_get_method(req)
+										  , uri_as_string, ha2);
+		belle_sip_auth_helper_compute_response(ha1,nonce, ha2, response);
+		if (strcmp(response, belle_sip_header_authorization_get_response(authorization)) == 0) {
+			belle_sip_message("Auth sucessfull");
+			if (strcasecmp(belle_sip_request_get_method(req), "MESSAGE") == 0) {
+				response_code = 404;
+			} else {
+				response_code = 200;
+			}
+		}
+	}
+	
+	belle_sip_random_token((nonce), NONCE_SIZE);
+	response_msg = belle_sip_response_create_from_request(req, response_code);
+	
+	if (response_code == 407 || response_code == 401 ) {
+		belle_sip_header_www_authenticate_t *www_authenticate = 401?belle_sip_header_www_authenticate_new():BELLE_SIP_HEADER_WWW_AUTHENTICATE(belle_sip_header_proxy_authenticate_new());
+	
+		
+		belle_sip_header_www_authenticate_set_realm(www_authenticate, "sip.linphone.org");
+		belle_sip_header_www_authenticate_set_domain(www_authenticate, "sip:sip.linphone.org");
+		belle_sip_header_www_authenticate_set_scheme(www_authenticate, "Digest");
+		belle_sip_header_www_authenticate_set_nonce(www_authenticate,nonce);
+		belle_sip_message_add_header(BELLE_SIP_MESSAGE(response_msg), BELLE_SIP_HEADER(www_authenticate));
+	} else {
+		belle_sip_header_authentication_info_t* authentication_info = belle_sip_header_authentication_info_new();
+		belle_sip_header_authentication_info_set_next_nonce(authentication_info, nonce);
+		belle_sip_message_add_header(BELLE_SIP_MESSAGE(response_msg), BELLE_SIP_HEADER(authentication_info));
+	}
+	
+	belle_sip_server_transaction_send_response(trans,response_msg);
+}
 
+static void test_register_with_next_nonce(void) {
+	belle_sip_listening_point_t *server_lp = belle_sip_stack_create_listening_point(stack,"0.0.0.0",bctbx_random()%20000 +1024,"TCP");
+	char  nonce [NONCE_SIZE];
+	belle_sip_listener_t *server_listener;
+	char listening_uri[256];
+	belle_sip_listener_callbacks_t cbs;
+	belle_sip_random_token((nonce), sizeof(nonce));
+	
+	cbs.process_dialog_terminated=NULL;
+	cbs.process_io_error=NULL;
+	cbs.process_request_event=(void (*)(void *user_ctx, const belle_sip_request_event_t *event))register_process_request_event;
+	cbs.process_response_event=NULL;
+	cbs.process_timeout=NULL;
+	cbs.process_transaction_terminated=NULL;
+	cbs.process_auth_requested=NULL;
+	cbs.listener_destroyed=NULL;
+	server_listener=belle_sip_listener_create_from_callbacks(&cbs,nonce);
+	belle_sip_provider_add_sip_listener(prov,server_listener);
+	belle_sip_provider_add_listening_point(prov,server_lp);
+	snprintf(listening_uri,sizeof(listening_uri), "127.0.0.1:%i;transport=tcp",belle_sip_listening_point_get_port(server_lp));
+
+	reuse_nonce_base(listening_uri);
+	belle_sip_provider_remove_sip_listener(prov, server_listener);
+	belle_sip_provider_remove_listening_point(prov, server_lp);
+}
 
 test_t register_tests[] = {
 	TEST_NO_TAG("Stateful UDP", stateful_register_udp),
@@ -901,7 +997,8 @@ test_t register_tests[] = {
 	TEST_NO_TAG("Register with DNS SRV failover TLS", register_dns_srv_tls),
 	TEST_NO_TAG("Register with DNS SRV failover TLS with http proxy", register_dns_srv_tls_with_http_proxy),
 	TEST_NO_TAG("Register with DNS load-balancing", register_dns_load_balancing),
-	TEST_NO_TAG("Nonce reutilization", reuse_nonce)
+	TEST_NO_TAG("Nonce reutilization", reuse_nonce),
+	TEST_NO_TAG("Next Nonce", test_register_with_next_nonce)
 };
 
 test_suite_t register_test_suite = {"Register", register_before_all, register_after_all, NULL,
diff --git a/tester/belle_sip_resolver_tester.c b/tester/belle_sip_resolver_tester.c
index d401820..4e7fa85 100644
--- a/tester/belle_sip_resolver_tester.c
+++ b/tester/belle_sip_resolver_tester.c
@@ -85,7 +85,7 @@ static void destroy_endpoint(endpoint_t *endpoint) {
 	belle_sip_uninit_sockets();
 }
 
-static void a_resolve_done(void *data, const char *name, struct addrinfo *ai_list) {
+static void a_resolve_done(void *data, const char *name, struct addrinfo *ai_list, uint32_t ttl) {
 	endpoint_t *client = (endpoint_t *)data;
 	BELLESIP_UNUSED(name);
 	client->resolve_done = 1;
@@ -96,7 +96,7 @@ static void a_resolve_done(void *data, const char *name, struct addrinfo *ai_lis
 		client->resolve_ko = 1;
 }
 
-static void srv_resolve_done(void *data, const char *name, belle_sip_list_t *srv_list) {
+static void srv_resolve_done(void *data, const char *name, belle_sip_list_t *srv_list, uint32_t ttl) {
 	endpoint_t *client = (endpoint_t *)data;
 	BELLESIP_UNUSED(name);
 	client->resolve_done = 1;
diff --git a/tester/belle_sip_tester.c b/tester/belle_sip_tester.c
index c7b061a..7744b81 100644
--- a/tester/belle_sip_tester.c
+++ b/tester/belle_sip_tester.c
@@ -94,6 +94,8 @@ void belle_sip_tester_init(void(*ftester_printf)(int level, const char *fmt, va_
 	ipv6_available=_belle_sip_tester_ipv6_available();
 	bc_tester_add_suite(&cast_test_suite);
 	bc_tester_add_suite(&sip_uri_test_suite);
+	bc_tester_add_suite(&fast_sip_uri_test_suite);
+	bc_tester_add_suite(&perf_sip_uri_test_suite);
 	bc_tester_add_suite(&generic_uri_test_suite);
 	bc_tester_add_suite(&headers_test_suite);
 	bc_tester_add_suite(&core_test_suite);
@@ -155,6 +157,9 @@ void belle_sip_tester_after_each(void) {
 }
 
 int belle_sip_tester_set_log_file(const char *filename) {
+	bctbx_log_handler_t *filehandler;
+	char* dir;
+	char* base;
 	if (log_file) {
 		fclose(log_file);
 	}
@@ -163,13 +168,19 @@ int belle_sip_tester_set_log_file(const char *filename) {
 		belle_sip_error("Cannot open file [%s] for writing logs because [%s]", filename, strerror(errno));
 		return -1;
 	}
+	dir = bctbx_dirname(filename);
+	base = bctbx_basename(filename);
 	belle_sip_message("Redirecting traces to file [%s]", filename);
-	belle_sip_set_log_file(log_file);
+	filehandler = bctbx_create_file_log_handler(0, dir, base, log_file);
+	bctbx_add_log_handler(filehandler);
+	bctbx_add_log_handler(filehandler);
+	if (dir) bctbx_free(dir);
+	if (base) bctbx_free(base);
 	return 0;
 }
 
 
-#if !defined(ANDROID) && !defined(TARGET_OS_IPHONE) && !(defined(BELLE_SIP_WINDOWS_PHONE) || defined(BELLE_SIP_WINDOWS_UNIVERSAL))
+#if !defined(__ANDROID__) && !defined(TARGET_OS_IPHONE) && !(defined(BELLE_SIP_WINDOWS_PHONE) || defined(BELLE_SIP_WINDOWS_UNIVERSAL))
 
 static const char* belle_sip_helper =
 		"\t\t\t--verbose\n"
@@ -202,7 +213,8 @@ int main (int argc, char *argv[]) {
 	if (env_domain) {
 		test_domain=env_domain;
 	}
-
+	bctbx_init_logger(TRUE);
+	
 	for(i=1;i<argc;++i){
 		if (strcmp(argv[i],"--verbose")==0){
 			belle_sip_set_log_level(BELLE_SIP_LOG_DEBUG);
@@ -238,6 +250,7 @@ int main (int argc, char *argv[]) {
 
 	ret = bc_tester_start(argv[0]);
 	belle_sip_tester_uninit();
+	bctbx_uninit_logger();
 	return ret;
 }
 
diff --git a/tester/belle_sip_tester.h b/tester/belle_sip_tester.h
index 58bd126..4fa562c 100644
--- a/tester/belle_sip_tester.h
+++ b/tester/belle_sip_tester.h
@@ -32,6 +32,8 @@ extern "C" {
 extern test_suite_t cast_test_suite;
 extern test_suite_t generic_uri_test_suite;
 extern test_suite_t sip_uri_test_suite;
+extern test_suite_t fast_sip_uri_test_suite;
+extern test_suite_t perf_sip_uri_test_suite;
 extern test_suite_t headers_test_suite;
 extern test_suite_t core_test_suite;
 extern test_suite_t sdp_test_suite;
diff --git a/tester/belle_sip_tester_windows.cpp b/tester/belle_sip_tester_windows.cpp
index d8e470d..d4b52be 100644
--- a/tester/belle_sip_tester_windows.cpp
+++ b/tester/belle_sip_tester_windows.cpp
@@ -46,7 +46,7 @@ static void nativeOutputTraceHandler(int lev, const char *fmt, va_list args)
 	}
 }
 
-static void belleSipNativeOutputTraceHandler(const char *domain, BctbxLogLevel lev, const char *fmt, va_list args)
+static void belleSipNativeOutputTraceHandler(void *info, const char *domain, BctbxLogLevel lev, const char *fmt, va_list args)
 {
 	nativeOutputTraceHandler((int)lev, fmt, args);
 }
@@ -103,6 +103,7 @@ bool NativeTester::run(Platform::String^ suiteName, Platform::String^ caseName,
 	std::wstring wscasename = caseName->Data();
 	char csuitename[MAX_SUITE_NAME_SIZE] = { 0 };
 	char ccasename[MAX_SUITE_NAME_SIZE] = { 0 };
+	bctbx_log_handler_t *log_handler = bctbx_create_log_handler(belleSipNativeOutputTraceHandler, NULL, NULL);
 	wcstombs(csuitename, wssuitename.c_str(), sizeof(csuitename));
 	wcstombs(ccasename, wscasename.c_str(), sizeof(ccasename));
 
@@ -112,7 +113,7 @@ bool NativeTester::run(Platform::String^ suiteName, Platform::String^ caseName,
 	else {
 		belle_sip_set_log_level(BELLE_SIP_LOG_ERROR);
 	}
-	belle_sip_set_log_handler(belleSipNativeOutputTraceHandler);
+	bctbx_add_log_handler(log_handler);
 	return bc_tester_run_tests(wssuitename == all ? 0 : csuitename, wscasename == all ? 0 : ccasename, NULL) != 0;
 }
 
diff --git a/tester/belle_sip_uri_tester.c b/tester/belle_sip_uri_tester.c
index 5b2abeb..c5c30f9 100644
--- a/tester/belle_sip_uri_tester.c
+++ b/tester/belle_sip_uri_tester.c
@@ -1,505 +1,32 @@
 /*
 	belle-sip - SIP (RFC3261) library.
-    Copyright (C) 2010  Belledonne Communications SARL
-
-    This program 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.
-
-    This program 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, see <http://www.gnu.org/licenses/>.
-*/
+ Copyright (C) 2017  Belledonne Communications SARL
+ 
+ This program 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.
+ 
+ This program 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, see <http://www.gnu.org/licenses/>.
+ */
 
 #include "belle-sip/belle-sip.h"
 #include "belle_sip_tester.h"
 #include "belle_sip_internal.h"
 
 
-static void testSIMPLEURI(void) {
-	belle_sip_uri_t* L_tmp;
-	belle_sip_uri_t* L_uri = belle_sip_uri_parse("sip:sip.titi.com");
-	char* l_raw_uri = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_uri));
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-	L_tmp = belle_sip_uri_parse(l_raw_uri);
-	L_uri = BELLE_SIP_URI(belle_sip_object_clone(BELLE_SIP_OBJECT(L_tmp)));
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_tmp));
-	belle_sip_free(l_raw_uri);
-
-	BC_ASSERT_PTR_NULL(belle_sip_uri_get_user(L_uri));
-	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_host(L_uri), "sip.titi.com");
-	BC_ASSERT_PTR_NULL(belle_sip_uri_get_transport_param(L_uri));
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-}
-
-static void testCOMPLEXURI(void) {
-	belle_sip_uri_t* L_tmp;
-	belle_sip_uri_t *  L_uri = belle_sip_uri_parse("sip:toto at titi.com:5060;transport=tcp");
-	char* l_raw_uri = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_uri));
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-	L_tmp = belle_sip_uri_parse(l_raw_uri);
-	L_uri = BELLE_SIP_URI(belle_sip_object_clone(BELLE_SIP_OBJECT(L_tmp)));
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_tmp));
-	belle_sip_free(l_raw_uri);
-	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_user(L_uri), "toto");
-	BC_ASSERT_EQUAL(belle_sip_uri_get_port(L_uri), 5060, int, "%d");
-	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_host(L_uri), "titi.com");
-	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_transport_param(L_uri), "tcp");
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-}
-
-static void testIPV6URI_base(const char* ip6) {
-	belle_sip_uri_t* L_tmp;
-	belle_sip_uri_t * L_uri;
-	char* l_raw_uri;
-	char uri[256];
-	snprintf(uri,sizeof(uri),"sip:toto@[%s]:5060;transport=tcp",ip6);
-	L_uri = belle_sip_uri_parse(uri);
-	l_raw_uri = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_uri));
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-	L_tmp = belle_sip_uri_parse(l_raw_uri);
-	L_uri = BELLE_SIP_URI(belle_sip_object_clone(BELLE_SIP_OBJECT(L_tmp)));
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_tmp));
-	belle_sip_free(l_raw_uri);
-	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_user(L_uri), "toto");
-	BC_ASSERT_EQUAL(belle_sip_uri_get_port(L_uri), 5060, int, "%d");
-	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_host(L_uri),ip6);
-	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_transport_param(L_uri), "tcp");
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-}
-
-static void testIPV6URI(void) {
-	testIPV6URI_base("fe80::1");
-	testIPV6URI_base("2a01:e35:1387:1020:6233:4bff:fe0b:5663");
-	testIPV6URI_base("2a01:e35:1387:1020:6233::5663");
-	testIPV6URI_base("::1");
-}
-
-static void testSIPSURI(void) {
-
-	belle_sip_uri_t *  L_uri = belle_sip_uri_parse("sips:linphone.org");
-	char* l_raw_uri = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_uri));
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-	L_uri = belle_sip_uri_parse(l_raw_uri);
-	belle_sip_free(l_raw_uri);
-	BC_ASSERT_EQUAL(belle_sip_uri_is_secure(L_uri), 1, int, "%d");
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-	L_uri = belle_sip_uri_parse("sip:linphone.org");
-	BC_ASSERT_EQUAL(belle_sip_uri_is_secure(L_uri), 0, int, "%d");
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-}
-
-static void test_ip_host(void) {
-	belle_sip_uri_t *  L_uri = belle_sip_uri_parse("sip:192.168.0.1");
-	char* l_raw_uri = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_uri));
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-	L_uri = belle_sip_uri_parse(l_raw_uri);
-	belle_sip_free(l_raw_uri);
-	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_host(L_uri), "192.168.0.1");
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-}
-
-static void test_lr(void) {
-	belle_sip_uri_t *  L_uri = belle_sip_uri_parse("sip:192.168.0.1;lr");
-	char* l_raw_uri = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_uri));
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-	L_uri = belle_sip_uri_parse(l_raw_uri);
-	belle_sip_free(l_raw_uri);
-	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_host(L_uri), "192.168.0.1");
-	BC_ASSERT_EQUAL(belle_sip_uri_has_lr_param(L_uri), 1, int, "%d");
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-
-}
-
-static void test_maddr(void) {
-	belle_sip_uri_t *  L_uri = belle_sip_uri_parse("sip:192.168.0.1;lr;maddr=linphone.org");
-	char* l_raw_uri = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_uri));
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-	L_uri = belle_sip_uri_parse(l_raw_uri);
-	belle_sip_free(l_raw_uri);
-	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_maddr_param(L_uri), "linphone.org");
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-
-}
-
-static void test_user_passwd(void) {
-	belle_sip_uri_t *  L_uri = belle_sip_uri_parse("sip:toto:tata at bla;");
-	char* l_raw_uri = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_uri));
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-	L_uri = belle_sip_uri_parse(l_raw_uri);
-	belle_sip_free(l_raw_uri);
-	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_user_password(L_uri), "tata");
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-
-}
-
-
-static void test_uri_parameters (void) {
-	char* l_raw_uri;
-	belle_sip_uri_t* L_tmp;
-	belle_sip_uri_t *  L_uri = belle_sip_uri_parse("sip:192.168.0.1;ttl=12");
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-
-	L_uri = belle_sip_uri_parse("sip:maddr=@192.168.0.1;lr;maddr=192.168.0.1;user=ip;ttl=140;transport=sctp;method=INVITE;rport=5060");
-	l_raw_uri = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_uri));
-
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-	L_tmp = belle_sip_uri_parse(l_raw_uri);
-	L_uri = BELLE_SIP_URI(belle_sip_object_clone(BELLE_SIP_OBJECT(L_tmp)));
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_tmp));
-
-	belle_sip_free(l_raw_uri);
-	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_maddr_param(L_uri), "192.168.0.1");
-	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_user_param(L_uri), "ip");
-	BC_ASSERT_EQUAL(belle_sip_uri_get_ttl_param(L_uri),140, int, "%d");
-	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_transport_param(L_uri), "sctp");
-	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_method_param(L_uri), "INVITE");
-
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-}
-
-static void test_headers(void) {
-	belle_sip_uri_t *  L_uri = belle_sip_uri_parse("sip:192.168.0.1?toto=titi");
-	char* l_raw_uri = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_uri));
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-	L_uri = belle_sip_uri_parse(l_raw_uri);
-	belle_sip_free(l_raw_uri);
-	if (!BC_ASSERT_PTR_NOT_NULL(belle_sip_uri_get_header(L_uri,"toto"))) return;
-	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_header(L_uri,"toto"), "titi");
-
-	BC_ASSERT_PTR_NULL(belle_sip_uri_get_header(L_uri,"bla"));
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-	L_uri = belle_sip_uri_parse("sip:192.168.0.1?toto=titi&header2=popo&header3=");
-	l_raw_uri = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_uri));
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-	L_uri = belle_sip_uri_parse(l_raw_uri);
-	belle_sip_free(l_raw_uri);
-
-	if (!BC_ASSERT_PTR_NOT_NULL(belle_sip_uri_get_header(L_uri,"toto"))) return;
-	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_header(L_uri,"header2"), "popo");
-	belle_sip_object_unref(L_uri);
-}
-static void test_escaped_headers(void) {
-	const char* raw_uri_2=	"sip:eNgwBpkNcH6EdTHlX0cq8 at toto.com?"
-							"P-Group-Id=Fu0hHIQ23H4hveVT:New%20Group"
-							"&P-Expert-Profile-Id=zKQOBOB2jTmUOjkB:New%20Group"
-							"&P-Reverse-Charging=0&P-Campaign-Id=none"
-							"&P-Embed-Url=https://toto.com/caller/?1.4.0-dev-42-91bdf0c%26id%3DFu0hHIQ23H4hveVT%26CAMPAIGN_ID%3Dnone";
-
-	belle_sip_uri_t *  L_uri = belle_sip_uri_parse("sip:toto at sip.linhone.org?User-to-User=323a313030363a3230385a48363039313941364b4342463845495936%3Bencoding%3Dhex");
-	char* l_raw_uri = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_uri));
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-	L_uri = belle_sip_uri_parse(l_raw_uri);
-	belle_sip_free(l_raw_uri);
-	if (!BC_ASSERT_PTR_NOT_NULL(belle_sip_uri_get_header(L_uri,"User-to-User"))) return;
-	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_header(L_uri,"User-to-User"), "323a313030363a3230385a48363039313941364b4342463845495936;encoding=hex");
-	belle_sip_object_unref(L_uri);
-
-	L_uri = belle_sip_uri_parse(raw_uri_2);
-	l_raw_uri = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_uri));
-	belle_sip_free(l_raw_uri);
-	if (!BC_ASSERT_PTR_NOT_NULL(belle_sip_uri_get_header(L_uri,"P-Embed-Url"))) return;
-	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_header(L_uri,"P-Embed-Url"), "https://toto.com/caller/?1.4.0-dev-42-91bdf0c&id=Fu0hHIQ23H4hveVT&CAMPAIGN_ID=none");
-	belle_sip_object_unref(L_uri);
-
-
-}
-
-static void testSIMPLEURI_error(void) {
-	belle_sip_uri_t* L_uri = belle_sip_uri_parse("siptcom");
-	BC_ASSERT_PTR_NULL(L_uri);
-
-}
-
-static void test_escaped_username(void) {
-	belle_sip_uri_t* L_tmp;
-	belle_sip_uri_t *  L_uri = belle_sip_uri_parse("sip:toto%40linphone.org at titi.com");
-	char* l_raw_uri = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_uri));
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-	L_tmp = belle_sip_uri_parse(l_raw_uri);
-	L_uri = BELLE_SIP_URI(belle_sip_object_clone(BELLE_SIP_OBJECT(L_tmp)));
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_tmp));
-	belle_sip_free(l_raw_uri);
-	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_user(L_uri), "toto at linphone.org");
-	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_host(L_uri), "titi.com");
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-}
-
-static void test_escaped_passwd(void) {
-	belle_sip_uri_t* L_tmp;
-	belle_sip_uri_t *  L_uri = belle_sip_uri_parse("sips:%22jehan%22%20%3cjehan%40sip2.linphone.org:544%3e at sip.linphone.org");
-	char* l_raw_uri = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_uri));
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-	L_tmp = belle_sip_uri_parse(l_raw_uri);
-	L_uri = BELLE_SIP_URI(belle_sip_object_clone(BELLE_SIP_OBJECT(L_tmp)));
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_tmp));
-	belle_sip_free(l_raw_uri);
-	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_user(L_uri), "\"jehan\" <jehan at sip2.linphone.org");
-	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_host(L_uri), "sip.linphone.org");
-	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_user_password(L_uri), "544>");
-
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-
-}
+/*test body*/
+#include "belle_sip_base_uri_tester.c"
 
 
-static void test_escaped_parameter(void) {
-	belle_sip_uri_t* L_tmp;
-	belle_sip_uri_t *  L_uri = belle_sip_uri_parse("sip:toto at titi.com;pa%3Dram=aa%40bb:5060[];o%40");
-	char* l_raw_uri = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_uri));
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-	L_tmp = belle_sip_uri_parse(l_raw_uri);
-	L_uri = BELLE_SIP_URI(belle_sip_object_clone(BELLE_SIP_OBJECT(L_tmp)));
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_tmp));
-	belle_sip_free(l_raw_uri);
-	BC_ASSERT_STRING_EQUAL(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(L_uri), "pa=ram"), "aa at bb:5060[]");
-	BC_ASSERT_TRUE(belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(L_uri), "o@"));
-	BC_ASSERT_STRING_EQUAL(belle_sip_uri_get_host(L_uri), "titi.com");
-	belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
-}
-
-static void test_uri_equals(void) {
-	belle_sip_uri_t* a;
-	belle_sip_uri_t* b;
-/*
-	 *    The URIs within each of the following sets are equivalent:
-
-	   sip:%61lice at atlanta.com;transport=TCP
-	   sip:alice at AtLanTa.CoM;Transport=tcp
-*/
-	a = belle_sip_uri_parse("sip:%61lice at atlanta.com;transport=TCP");
-	if (!BC_ASSERT_PTR_NOT_NULL(a)) return;
-	b = belle_sip_uri_parse("sip:alice at AtLanTa.CoM;Transport=tcp");
-	if (!BC_ASSERT_PTR_NOT_NULL(b)) return;
-	BC_ASSERT_TRUE(belle_sip_uri_equals(a,b));
-	belle_sip_object_unref(a);
-	belle_sip_object_unref(b);
-	/*
-	   sip:carol at chicago.com
-	   sip:carol at chicago.com;newparam=5
-	   sip:carol at chicago.com;security=on
-*/
-	a = belle_sip_uri_parse("sip:carol at chicago.com");
-	if (!BC_ASSERT_PTR_NOT_NULL(a)) return;
-	b = belle_sip_uri_parse("sip:carol at chicago.com;newparam=5");
-	if (!BC_ASSERT_PTR_NOT_NULL(b)) return;
-	BC_ASSERT_TRUE(belle_sip_uri_equals(a,b));
-	belle_sip_object_unref(a);
-	belle_sip_object_unref(b);
-/*
-
-	   sip:biloxi.com;transport=tcp;method=REGISTER?to=sip:bob%40biloxi.com
-	   sip:biloxi.com;method=REGISTER;transport=tcp?to=sip:bob%40biloxi.com
-*/
-	a = belle_sip_uri_parse("sip:biloxi.com;transport=tcp;method=REGISTER?to=sip:bob%40biloxi.com");
-	if (!BC_ASSERT_PTR_NOT_NULL(a)) return;
-	b = belle_sip_uri_parse("sip:biloxi.com;method=REGISTER;transport=tcp?to=sip:bob%40biloxi.com");
-	if (!BC_ASSERT_PTR_NOT_NULL(b)) return;
-	BC_ASSERT_TRUE(belle_sip_uri_equals(a,b));
-	belle_sip_object_unref(a);
-	belle_sip_object_unref(b);
-	/*
-	sip:alice at atlanta.com?subject=project%20x&priority=urgent
-	   sip:alice at atlanta.com?priority=urgent&subject=project%20x
-
-	   The URIs within each of the following sets are not equivalent:
-
-	   SIP:ALICE at AtLanTa.CoM;Transport=udp             (different usernames)
-	   sip:alice at AtLanTa.CoM;Transport=UDP
-*/
-	a = belle_sip_uri_parse("sip:ALICE at AtLanTa.CoM;Transport=udp");
-	if (!BC_ASSERT_PTR_NOT_NULL(a)) return;
-	b = belle_sip_uri_parse("sip:alice at AtLanTa.CoM;Transport=UDP");
-	if (!BC_ASSERT_PTR_NOT_NULL(b)) return;
-	BC_ASSERT_FALSE(belle_sip_uri_equals(a,b));
-	belle_sip_object_unref(a);
-	belle_sip_object_unref(b);
-	/*
-	   sip:bob at biloxi.com                   (can resolve to different ports)
-	   sip:bob at biloxi.com:5060
-*/
-	a = belle_sip_uri_parse("sip:ALICE at AtLanTa.CoM;Transport=udp");
-	if (!BC_ASSERT_PTR_NOT_NULL(a)) return;
-	b = belle_sip_uri_parse("sip:alice at AtLanTa.CoM;Transport=UDP");
-	if (!BC_ASSERT_PTR_NOT_NULL(b)) return;
-	BC_ASSERT_FALSE(belle_sip_uri_equals(a,b));
-	belle_sip_object_unref(a);
-	belle_sip_object_unref(b);
-	/*
-	sip:bob at biloxi.com              (can resolve to different transports)
-	   sip:bob at biloxi.com;transport=udp
-*/
-	a = belle_sip_uri_parse("sip:bob at biloxi.com");
-	if (!BC_ASSERT_PTR_NOT_NULL(a)) return;
-	b = belle_sip_uri_parse("sip:bob at biloxi.com;transport=udp");
-	if (!BC_ASSERT_PTR_NOT_NULL(b)) return;
-	BC_ASSERT_FALSE(belle_sip_uri_equals(a,b));
-	belle_sip_object_unref(a);
-	belle_sip_object_unref(b);
-/*	   sip:bob at biloxi.com     (can resolve to different port and transports)
-	   sip:bob at biloxi.com:6000;transport=tcp
-*/
-	a = belle_sip_uri_parse("sip:bob at biloxi.com");
-	if (!BC_ASSERT_PTR_NOT_NULL(a)) return;
-	b = belle_sip_uri_parse("sip:bob at biloxi.com:6000;transport=tcp");
-	if (!BC_ASSERT_PTR_NOT_NULL(b)) return;
-	BC_ASSERT_FALSE(belle_sip_uri_equals(a,b));
-	belle_sip_object_unref(a);
-	belle_sip_object_unref(b);
-	
-	a = belle_sip_uri_parse("sip:bob at biloxi.com");
-	if (!BC_ASSERT_PTR_NOT_NULL(a)) return;
-	b = belle_sip_uri_parse("sip:boba at biloxi.com");
-	if (!BC_ASSERT_PTR_NOT_NULL(b)) return;
-	BC_ASSERT_FALSE(belle_sip_uri_equals(a,b));
-	belle_sip_object_unref(a);
-	belle_sip_object_unref(b);
-
-	/*	   sip:carol at chicago.com                    (different header component)
-	   sip:carol at chicago.com?Subject=next%20meeting
-
-	   sip:bob at phone21.boxesbybob.com   (even though that's what
-	   sip:bob at 192.0.2.4                 phone21.boxesbybob.com resolves to)
-
-	   Note that equality is not transitive:
-
-	      o  sip:carol at chicago.com and sip:carol at chicago.com;security=on are
-	         equivalent
-
-	      o  sip:carol at chicago.com and sip:carol at chicago.com;security=off
-	         are equivalent
-
-	      o  sip:carol at chicago.com;security=on and
-	         sip:carol at chicago.com;security=off are not equivalent
-	Rosenberg, et. al.          Standards Track                   [Page 155]
-
-	RFC 3261            SIP: Session Initiation Protocol           June 2002
-
-	 */
-
-
-}
-
-/*
- * From 19.1.1 SIP and SIPS URI Components
- * 									   				dialog
-										reg./redir. Contact/
-			default  Req.-URI  To  From  Contact   R-R/Route  external
-user          --          o      o    o       o          o         o
-password      --          o      o    o       o          o         o
-host          --          m      m    m       m          m         m
-port          (1)         o      -    -       o          o         o
-user-param    ip          o      o    o       o          o         o
-method        INVITE      -      -    -       -          -         o
-maddr-param   --          o      -    -       o          o         o
-ttl-param     1           o      -    -       o          -         o
-transp.-param (2)         o      -    -       o          o         o
-lr-param      --          o      -    -       -          o         o
-other-param   --          o      o    o       o          o         o
-headers       --          -      -    -       o          -         o*/
-void testUriComponentsChecker(void) {
-	belle_sip_uri_t* uri = belle_sip_uri_parse("sip:hostonly");
-	BC_ASSERT_TRUE(belle_sip_uri_check_components_from_request_uri(uri));
-	belle_sip_object_unref(uri);
-
-	{
-	belle_sip_header_from_t*	header = belle_sip_header_from_parse("From: sip:linphone.org:5061");
-	BC_ASSERT_FALSE(belle_sip_uri_check_components_from_context(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(header)),NULL,"From"));
-	belle_sip_object_unref(header);
-	}
-	{
-	belle_sip_header_to_t*	header = belle_sip_header_to_parse("To: sip:linphone.org?header=interdit");
-	BC_ASSERT_FALSE(belle_sip_uri_check_components_from_context(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(header)),NULL,"To"));
-	belle_sip_object_unref(header);
-	}
-	{
-	belle_sip_header_contact_t*	header = belle_sip_header_contact_parse("Contact: <sip:linphone.org;lr>");
-	BC_ASSERT_FALSE(belle_sip_uri_check_components_from_context(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(header)),"REGISTER","Contact"));
-	BC_ASSERT_TRUE(belle_sip_uri_check_components_from_context(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(header)),NULL,"Contact"));
-	belle_sip_object_unref(header);
-	}
-	{
-	belle_sip_header_record_route_t*	header = belle_sip_header_record_route_parse("Record-Route: <sip:linphone.org;ttl=interdit>");
-	BC_ASSERT_FALSE(belle_sip_uri_check_components_from_context(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(header)),NULL,"Record-Route"));
-	belle_sip_object_unref(header);
-	}
-	{
-	belle_sip_uri_t* uri = belle_sip_uri_parse("sip:linphone.org:5061?header=toto");
-	BC_ASSERT_TRUE(belle_sip_uri_check_components_from_context(uri,NULL,"Any"));
-	belle_sip_object_unref(uri);
-	}
-}
-
-void test_escaping_bad_chars(void){
-	char bad_uri[13] = { 'h', 'e', 'l', 'l', 'o', (char)0xa0, (char)0xc8, 'w', 'o', 'r', 'l', 'd', 0x0 };
-	char *escaped = belle_sip_uri_to_escaped_username(bad_uri);
-	const char *expected="hello%a0%c8world";
-
-	BC_ASSERT_STRING_EQUAL(escaped, expected);
-
-	belle_sip_free(escaped);
-}
-
-
-static belle_sip_header_address_t* test_header_address_parsing(const char* address, int expect_fail){
-	belle_sip_header_address_t* header_address = belle_sip_header_address_parse(address);
-	if( expect_fail == TRUE ){
-		BC_ASSERT_PTR_NULL(header_address);
-	} else {
-		BC_ASSERT_PTR_NOT_NULL(header_address);
-	}
-	return header_address;
-}
-
-static void test_empty_password(void){
-	const char *address_fail = "sip:France:@+123456789";
-	const char *address_valid = "sip:France:@toto";
-	const char* passwd;
-	belle_sip_header_address_t* headerAddr;
-	belle_sip_uri_t* uri;
-
-	(void)test_header_address_parsing(address_fail, TRUE);
-
-	headerAddr = test_header_address_parsing(address_valid, FALSE);
-
-	BC_ASSERT_PTR_NOT_NULL(headerAddr);
-
-	uri = belle_sip_header_address_get_uri(headerAddr);
-	BC_ASSERT_PTR_NOT_NULL(uri);
-
-	passwd = belle_sip_uri_get_user_password(uri);
-	BC_ASSERT_PTR_EQUAL(passwd, NULL);
-
-	if (headerAddr) belle_sip_object_unref(headerAddr);
-}
+test_suite_t sip_uri_test_suite = {"SIP URI", NULL, NULL, belle_sip_tester_before_each, belle_sip_tester_after_each,
+	sizeof(uri_tests) / sizeof(uri_tests[0]), uri_tests};
 
 
-static test_t uri_tests[] = {
-	TEST_NO_TAG("Simple URI", testSIMPLEURI),
-	TEST_NO_TAG("Complex URI", testCOMPLEXURI),
-	TEST_NO_TAG("Escaped username", test_escaped_username),
-	TEST_NO_TAG("Escaped username with bad chars", test_escaping_bad_chars),
-	TEST_NO_TAG("Escaped parameter", test_escaped_parameter),
-	TEST_NO_TAG("Escaped passwd", test_escaped_passwd),
-	TEST_NO_TAG("User passwd", test_user_passwd),
-	TEST_NO_TAG("IP host", test_ip_host),
-	TEST_NO_TAG("lr", test_lr),
-	TEST_NO_TAG("maddr", test_maddr),
-	TEST_NO_TAG("headers", test_headers),
-	TEST_NO_TAG("Escaped headers", test_escaped_headers),
-	TEST_NO_TAG("URI parameters", test_uri_parameters),
-	TEST_NO_TAG("SIPS URI", testSIPSURI),
-	TEST_NO_TAG("URI equals", test_uri_equals),
-	TEST_NO_TAG("Simple URI error", testSIMPLEURI_error),
-	TEST_NO_TAG("IPv6 URI", testIPV6URI),
-	TEST_NO_TAG("URI components", testUriComponentsChecker),
-	TEST_NO_TAG("Empty password", test_empty_password),
-};
 
-test_suite_t sip_uri_test_suite = {"SIP URI", NULL, NULL, belle_sip_tester_before_each, belle_sip_tester_after_each,
-								   sizeof(uri_tests) / sizeof(uri_tests[0]), uri_tests};
diff --git a/tester/get.c b/tester/get.c
index cde7821..fe31ed8 100644
--- a/tester/get.c
+++ b/tester/get.c
@@ -32,6 +32,8 @@ static belle_sip_stack_t *stack=NULL;
 static void process_response(void *data, const belle_http_response_event_t *event){
 	belle_http_response_t *resp=event->response;
 	const char *body=belle_sip_message_get_body(BELLE_SIP_MESSAGE(resp));
+	fprintf(stdout,"Got response:\n");
+
 	if (body){
 		fprintf(stdout,"%s",body);
 	}
@@ -66,12 +68,14 @@ int main(int argc, char *argv[]){
 	if (argc<2){
 		usage(argv[0]);
 	}
+	bctbx_init_logger(1);
 	for (i = 2; i < argc; ++i){
 		if (strcmp(argv[i], "--ca-path") == 0){
 			i++;
 			ca_path = argv[i];
 		}else if (strcmp(argv[i], "--debug")==0){
-			belle_sip_set_log_level(BELLE_SIP_LOG_DEBUG);
+			fprintf(stderr, "Logs are enabled.\n");
+			bctbx_set_log_level(BCTBX_LOG_DOMAIN,BCTBX_LOG_DEBUG);
 		}else if (strcmp(argv[i], "--no-tls-check")==0){
 			check_tls = 0;
 		}else{
diff --git a/tester/parse.c b/tester/parse.c
index b67f273..1f757e3 100644
--- a/tester/parse.c
+++ b/tester/parse.c
@@ -80,21 +80,21 @@ int main(int argc, char *argv[]){
 	close(fd);
 	belle_sip_set_log_level(BELLE_SIP_LOG_DEBUG);
 
-	for (i=0;i<st.st_size;){
-		size_t read;
+	for (i=0;i<(int)st.st_size;){
+		size_t nbread;
 		if (strcasecmp(protocol,"sip")==0 || strcasecmp(protocol,"http")==0){
 			belle_sip_message_t *msg;
 			uint64_t begin,end;
 			begin=belle_sip_time_ms();
-			msg=belle_sip_message_parse_raw(str+i,st.st_size-i,&read);
+			msg=belle_sip_message_parse_raw(str+i,st.st_size-i,&nbread);
 			end=belle_sip_time_ms();
 			if (msg){
-				printf("Successfully parsed %s message of %i bytes in %i ms.\n",protocol,(int)read, (int)(end-begin));
+				printf("Successfully parsed %s message of %i bytes in %i ms.\n",protocol,(int)nbread, (int)(end-begin));
 			}else{
 				fprintf(stderr,"Failed to parse message.\n");
 				break;
 			}
-			i+=read;
+			i+=(int)nbread;
 		}else if (strcasecmp(protocol,"sdp")==0){
 			belle_sdp_session_description_t *sdp=belle_sdp_session_description_parse(str);
 			if (sdp){

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-voip/belle-sip.git



More information about the Pkg-voip-commits mailing list