[asterisk-scf-commits] asterisk-scf/release/pjproject.git branch "upstream" updated.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Thu Nov 18 10:35:18 CST 2010


branch "upstream" has been updated
       via  86617039868afa7561095f997e7bfc4029cb54c7 (commit)
      from  8033d49f4a403731c0ff915b07c7db5c597b7dd7 (commit)

Summary of changes:
 Makefile                                           |    5 +-
 configure-iphone                                   |    4 +-
 pjlib-util/build/Makefile                          |    2 +-
 pjlib-util/include/pjlib-util/http_client.h        |  103 +-
 pjlib-util/src/pjlib-util-test/http_client.c       |  146 +-
 pjlib-util/src/pjlib-util/http_client.c            |  652 ++-
 pjlib-util/src/pjlib-util/resolver.c               |   55 +-
 pjlib/build/Makefile                               |    2 +-
 pjlib/include/pj/activesock.h                      |   25 +-
 pjlib/include/pj/config.h                          |   12 +-
 pjlib/include/pj/config_site_sample.h              |    5 +-
 pjlib/src/pj/activesock.c                          |   30 +-
 pjlib/src/pj/config.c                              |    4 +-
 pjlib/src/pj/os_core_unix.c                        |   11 +-
 pjlib/src/pj/os_core_win32.c                       |    5 +-
 pjmedia/build/Makefile                             |    2 +-
 pjmedia/docs/doxygen.cfg                           |    3 +-
 pjmedia/include/pjmedia-audiodev/audiodev.h        |    6 +-
 pjmedia/include/pjmedia-codec/amr_helper.h         |   11 +-
 pjmedia/include/pjmedia-codec/types.h              |   19 +-
 pjmedia/include/pjmedia/conference.h               |    4 +-
 pjmedia/include/pjmedia/config.h                   |    6 +-
 pjmedia/include/pjmedia/delaybuf.h                 |    4 +-
 pjmedia/include/pjmedia/doxygen.h                  |  130 +-
 pjmedia/include/pjmedia/port.h                     |   38 +-
 pjmedia/include/pjmedia/rtcp_xr.h                  |    5 +-
 pjmedia/include/pjmedia/sdp.h                      |    6 +-
 pjmedia/include/pjmedia/stereo.h                   |    8 +-
 pjmedia/include/pjmedia/stream.h                   |    8 +-
 pjmedia/include/pjmedia/transport_ice.h            |    4 +-
 pjmedia/include/pjmedia/types.h                    |    4 +-
 pjmedia/src/pjmedia-audiodev/coreaudio_dev.c       |    4 +-
 pjmedia/src/pjmedia/rtp.c                          |   11 +-
 pjmedia/src/pjmedia/sdp_neg.c                      |   10 +-
 pjmedia/src/pjmedia/session.c                      |   19 +-
 pjmedia/src/pjmedia/stream.c                       |   13 +-
 pjmedia/src/pjmedia/transport_srtp.c               |  106 +-
 pjnath/build/Makefile                              |    2 +-
 .../MainWindow-iPad.xib}                           |  377 +-
 .../SecondView-iPad.xib}                           |   82 +-
 pjsip-apps/src/ipjsua/ipjsua-Info.plist            |    6 +-
 .../src/ipjsua/ipjsua.xcodeproj/project.pbxproj    |   28 +-
 pjsip-apps/src/pjsua/pjsua_app.c                   |   50 +-
 pjsip-apps/src/python/Makefile                     |    2 +-
 pjsip-apps/src/python/_pjsua.c                     |    6 +-
 pjsip-apps/src/python/_pjsua.h                     |   15 +-
 pjsip-apps/src/samples/httpdemo.c                  |   18 +-
 pjsip-apps/src/samples/simple_pjsua.c              |    4 +-
 pjsip-apps/src/symbian_ua/ua.cpp                   |    4 +-
 pjsip-apps/src/symbian_ua_gui/src/symbian_ua.cpp   |    2 +-
 pjsip/build/Makefile                               |    2 +-
 pjsip/docs/doxygen.cfg                             |    3 +-
 pjsip/include/pjsip-simple/presence.h              |   44 +-
 pjsip/include/pjsip/sip_config.h                   |   26 +-
 pjsip/include/pjsip/sip_errno.h                    |    7 +-
 pjsip/include/pjsip/sip_msg.h                      |   10 +-
 pjsip/include/pjsip/sip_transaction.h              |    5 +-
 pjsip/include/pjsua-lib/pjsua.h                    |  121 +-
 pjsip/include/pjsua-lib/pjsua_internal.h           |    6 +-
 pjsip/src/pjsip-simple/evsub.c                     |   22 +-
 pjsip/src/pjsip-simple/presence.c                  |   33 +-
 pjsip/src/pjsip-simple/presence_body.c             |   28 +-
 pjsip/src/pjsip-ua/sip_inv.c                       |   19 +-
 pjsip/src/pjsip/sip_config.c                       |    7 +-
 pjsip/src/pjsip/sip_errno.c                        |    3 +-
 pjsip/src/pjsip/sip_msg.c                          |    9 +-
 pjsip/src/pjsip/sip_multipart.c                    |   12 +-
 pjsip/src/pjsip/sip_parser.c                       |    2 +-
 pjsip/src/pjsip/sip_transaction.c                  |   69 +-
 pjsip/src/pjsip/sip_uri.c                          |   16 +-
 pjsip/src/pjsip/sip_util.c                         |    7 +-
 pjsip/src/pjsua-lib/pjsua_acc.c                    |   67 +-
 pjsip/src/pjsua-lib/pjsua_call.c                   |  385 +-
 pjsip/src/pjsua-lib/pjsua_core.c                   |   36 +-
 pjsip/src/pjsua-lib/pjsua_media.c                  |  182 +-
 pjsip/src/pjsua-lib/pjsua_pres.c                   |   36 +-
 pjsip/src/test/multipart_test.c                    |    6 +-
 tests/pjsua/scripts-call/150_srtp_0_3.py           |   11 +
 tests/pjsua/scripts-call/150_srtp_1_3.py           |   11 +
 tests/pjsua/scripts-call/150_srtp_2_3.py           |   11 +
 tests/pjsua/scripts-call/150_srtp_3_0.py           |   11 +
 tests/pjsua/scripts-call/150_srtp_3_1.py           |   11 +
 tests/pjsua/scripts-call/150_srtp_3_2.py           |   11 +
 tests/pjsua/scripts-call/150_srtp_3_3.py           |   11 +
 tests/pjsua/scripts-call/400_tel_uri.py            |   12 +
 ...ll.py => 235_reg_good_tel_uri_enocredential.py} |    6 +-
 ...-disabled-no-rtpmap.xml => uac-ticket-1148.xml} |    9 +-
 ...-481.xml => uas-subscribe-multipart-notify.xml} |  235 +-
 third_party/portaudio/LICENSE.txt                  |   81 -
 third_party/portaudio/README.txt                   |   98 -
 third_party/portaudio/SConstruct                   |  197 -
 third_party/portaudio/aclocal.m4                   | 6627 --------------------
 .../portaudio/build/dev-cpp}/.gitignore            |    0
 third_party/portaudio/build/dev-cpp/Makefile-dll   |   78 -
 .../portaudio/build/dev-cpp/Makefile-static        |   75 -
 .../portaudio/build/dev-cpp/portaudio-dll.dev      |  209 -
 .../portaudio/build/dev-cpp/portaudio-static.dev   |  209 -
 third_party/portaudio/build/dev-cpp/readme.txt     |   23 -
 .../portaudio/build/msvc}/.gitignore               |    0
 third_party/portaudio/build/msvc/portaudio.def     |   43 -
 third_party/portaudio/build/msvc/portaudio.dsp     |  269 -
 third_party/portaudio/build/msvc/portaudio.dsw     |   29 -
 third_party/portaudio/build/msvc/portaudio.sln     |   26 -
 third_party/portaudio/build/msvc/portaudio.vcproj  | 1512 -----
 third_party/portaudio/build/msvc/readme.txt        |  109 -
 .../portaudio/build/scons}/.gitignore              |    0
 .../portaudio/build/scons/SConscript_common        |   30 -
 third_party/portaudio/build/scons/SConscript_opts  |   91 -
 third_party/portaudio/config.sub                   | 1489 -----
 third_party/portaudio/index.html                   |  105 -
 third_party/portaudio/install-sh                   |  251 -
 third_party/portaudio/missing                      |  360 --
 {lib => third_party/portaudio/pablio}/.gitignore   |    0
 third_party/portaudio/pablio/README.txt            |   45 -
 third_party/portaudio/pablio/pablio.c              |  314 -
 third_party/portaudio/pablio/pablio.def            |   35 -
 third_party/portaudio/pablio/pablio.h              |  116 -
 third_party/portaudio/pablio/test_rw.c             |  105 -
 third_party/portaudio/pablio/test_rw_echo.c        |  129 -
 third_party/portaudio/pablio/test_w_saw.c          |  114 -
 third_party/portaudio/pablio/test_w_saw8.c         |  112 -
 third_party/portaudio/portaudio-2.0.pc.in          |   12 -
 version.mak                                        |    2 +-
 123 files changed, 2752 insertions(+), 13723 deletions(-)
 copy pjsip-apps/src/ipjsua/{MainWindow.xib => Resources-iPad/MainWindow-iPad.xib} (71%)
 copy pjsip-apps/src/ipjsua/{SecondView.xib => Resources-iPad/SecondView-iPad.xib} (86%)
 create mode 100644 tests/pjsua/scripts-call/150_srtp_0_3.py
 create mode 100644 tests/pjsua/scripts-call/150_srtp_1_3.py
 create mode 100644 tests/pjsua/scripts-call/150_srtp_2_3.py
 create mode 100644 tests/pjsua/scripts-call/150_srtp_3_0.py
 create mode 100644 tests/pjsua/scripts-call/150_srtp_3_1.py
 create mode 100644 tests/pjsua/scripts-call/150_srtp_3_2.py
 create mode 100644 tests/pjsua/scripts-call/150_srtp_3_3.py
 create mode 100644 tests/pjsua/scripts-call/400_tel_uri.py
 copy tests/pjsua/scripts-recvfrom/{200_reg_good_enocredentiall.py => 235_reg_good_tel_uri_enocredential.py} (57%)
 copy tests/pjsua/scripts-sipp/{uac-inv-two-media-but-one-disabled-no-rtpmap.xml => uac-ticket-1148.xml} (87%)
 copy tests/pjsua/scripts-sipp/{uas-subscribe-refresh-481.xml => uas-subscribe-multipart-notify.xml} (87%)
 delete mode 100644 third_party/portaudio/LICENSE.txt
 delete mode 100644 third_party/portaudio/README.txt
 delete mode 100644 third_party/portaudio/SConstruct
 delete mode 100644 third_party/portaudio/aclocal.m4
 copy {lib => third_party/portaudio/build/dev-cpp}/.gitignore (100%)
 delete mode 100644 third_party/portaudio/build/dev-cpp/Makefile-dll
 delete mode 100644 third_party/portaudio/build/dev-cpp/Makefile-static
 delete mode 100644 third_party/portaudio/build/dev-cpp/portaudio-dll.dev
 delete mode 100644 third_party/portaudio/build/dev-cpp/portaudio-static.dev
 delete mode 100644 third_party/portaudio/build/dev-cpp/readme.txt
 copy {lib => third_party/portaudio/build/msvc}/.gitignore (100%)
 delete mode 100644 third_party/portaudio/build/msvc/portaudio.def
 delete mode 100644 third_party/portaudio/build/msvc/portaudio.dsp
 delete mode 100644 third_party/portaudio/build/msvc/portaudio.dsw
 delete mode 100644 third_party/portaudio/build/msvc/portaudio.sln
 delete mode 100644 third_party/portaudio/build/msvc/portaudio.vcproj
 delete mode 100644 third_party/portaudio/build/msvc/readme.txt
 copy {lib => third_party/portaudio/build/scons}/.gitignore (100%)
 delete mode 100644 third_party/portaudio/build/scons/SConscript_common
 delete mode 100644 third_party/portaudio/build/scons/SConscript_opts
 delete mode 100755 third_party/portaudio/config.sub
 delete mode 100644 third_party/portaudio/index.html
 delete mode 100755 third_party/portaudio/install-sh
 delete mode 100755 third_party/portaudio/missing
 copy {lib => third_party/portaudio/pablio}/.gitignore (100%)
 delete mode 100644 third_party/portaudio/pablio/README.txt
 delete mode 100644 third_party/portaudio/pablio/pablio.c
 delete mode 100644 third_party/portaudio/pablio/pablio.def
 delete mode 100644 third_party/portaudio/pablio/pablio.h
 delete mode 100644 third_party/portaudio/pablio/test_rw.c
 delete mode 100644 third_party/portaudio/pablio/test_rw_echo.c
 delete mode 100644 third_party/portaudio/pablio/test_w_saw.c
 delete mode 100644 third_party/portaudio/pablio/test_w_saw8.c
 delete mode 100644 third_party/portaudio/portaudio-2.0.pc.in


- Log -----------------------------------------------------------------
commit 86617039868afa7561095f997e7bfc4029cb54c7
Author: Kevin P. Fleming <kpfleming at digium.com>
Date:   Thu Nov 18 10:35:03 2010 -0600

    import version 1.8.5

diff --git a/Makefile b/Makefile
index f163403..5145993 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,8 @@
 include build.mak
 include build/host-$(HOST_NAME).mak
+-include user.mak
 
-DIRS = pjlib pjlib-util pjnath third_party pjmedia pjsip pjsip-apps
+DIRS = pjlib/build pjlib-util/build pjnath/build third_party/build pjmedia/build pjsip/build pjsip-apps/build $(EXTRA_DIRS)
 
 ifdef MINSIZE
 MAKE_FLAGS := MINSIZE=1
@@ -9,7 +10,7 @@ endif
 
 all clean dep depend distclean print realclean:
 	for dir in $(DIRS); do \
-		if $(MAKE) $(MAKE_FLAGS) -C $$dir/build $@; then \
+		if $(MAKE) $(MAKE_FLAGS) -C $$dir $@; then \
 		    true; \
 		else \
 		    exit 1; \
diff --git a/configure-iphone b/configure-iphone
index 67d80df..a2fc090 100755
--- a/configure-iphone
+++ b/configure-iphone
@@ -17,6 +17,8 @@ if test "$*" = "--help" -o "$*" = "-h"; then
   echo "  CC         Optionally specify the path of the ARM cross compiler"
   echo "             to use. By default, the compiler is deduced from the"
   echo "             SDK."
+  echo "  ARCH       Optional flags to specify target architecture, e.g."
+  echo "                ARCH='-arch armv6'"
   echo ""
   exit 0
 fi
@@ -104,7 +106,7 @@ export AR="${DEVPATH}/usr/bin/libtool -static -o"
 export RANLIB="echo ranlib"
 # Use gcc -E as preprocessor instead of cpp, since cpp will find the
 # header files in standard /usr/include instead of in isysroot
-export CPP="${CC} -E -isysroot ${SDKPATH}"
+export CPP="${CC} ${ARCH} -E -isysroot ${SDKPATH}"
 
 # Print settings
 if test "1" = "1"; then
diff --git a/pjlib-util/build/Makefile b/pjlib-util/build/Makefile
index 6acea05..69e92b4 100644
--- a/pjlib-util/build/Makefile
+++ b/pjlib-util/build/Makefile
@@ -56,7 +56,7 @@ all: $(TARGETS)
 
 doc:
 	cd .. && rm -rf docs/html docs/latex && doxygen docs/doxygen.cfg
-	@if test ! "$(WWWDIR)" == ""; then \
+	@if [ -n "$(WWWDIR)" ]; then \
 		echo "Copying to $(WWWDIR)/pjlib-util/docs/html.." ; \
 		cp -a ../docs/html/* $(WWWDIR)/pjlib-util/docs/html/ ; \
 	fi
diff --git a/pjlib-util/include/pjlib-util/http_client.h b/pjlib-util/include/pjlib-util/http_client.h
index 095075f..07ca164 100644
--- a/pjlib-util/include/pjlib-util/http_client.h
+++ b/pjlib-util/include/pjlib-util/http_client.h
@@ -1,4 +1,4 @@
-/* $Id: http_client.h 3227 2010-06-29 13:43:05Z ming $ */
+/* $Id: http_client.h 3321 2010-09-27 08:35:08Z bennylp $ */
 /* 
  * Copyright (C) 2008-2010 Teluu Inc. (http://www.teluu.com)
  *
@@ -49,21 +49,78 @@ typedef struct pj_http_req pj_http_req;
 #define PJ_HTTP_HEADER_SIZE 32
 
 /**
+ * HTTP header representation.
+ */
+typedef struct pj_http_header_elmt
+{
+    pj_str_t name;	/**< Header name */
+    pj_str_t value;	/**< Header value */
+} pj_http_header_elmt;
+
+/**
  * This structure describes http request/response headers.
  * Application should call #pj_http_headers_add_elmt() to
  * add a header field.
  */
 typedef struct pj_http_headers
 {
-    unsigned     count;                   /**< Number of header fields */
-    struct pj_http_header_elmt
-    {
-        pj_str_t name;
-        pj_str_t value;
-    } header[PJ_HTTP_HEADER_SIZE];        /**< Header elements/fields */
+    /**< Number of header fields */
+    unsigned     count;
+
+    /** Header elements/fields */
+    pj_http_header_elmt header[PJ_HTTP_HEADER_SIZE];
 } pj_http_headers;
 
 /**
+ * Structure to save HTTP authentication credential.
+ */
+typedef struct pj_http_auth_cred
+{
+    /**
+     * Specify specific authentication schemes to be responded. Valid values
+     * are "basic" and "digest". If this field is not set, any authentication
+     * schemes will be responded.
+     *
+     * Default is empty.
+     */
+    pj_str_t	scheme;
+
+    /**
+     * Specify specific authentication realm to be responded. If this field
+     * is set, only 401/407 response with matching realm will be responded.
+     * If this field is not set, any realms will be responded.
+     *
+     * Default is empty.
+     */
+    pj_str_t	realm;
+
+    /**
+     * Specify authentication username.
+     *
+     * Default is empty.
+     */
+    pj_str_t	username;
+
+    /**
+     * The type of password in \a data field. Currently only 0 is
+     * supported, meaning the \a data contains plain-text password.
+     *
+     * Default is 0.
+     */
+    unsigned	data_type;
+
+    /**
+     * Specify authentication password. The encoding of the password depends
+     * on the value of \a data_type field above.
+     *
+     * Default is empty.
+     */
+    pj_str_t	data;
+
+} pj_http_auth_cred;
+
+
+/**
  * Parameters that can be given during http request creation. Application
  * must initialize this structure with #pj_http_req_param_default().
  */
@@ -125,9 +182,30 @@ typedef struct pj_http_req_param
         pj_size_t  total_size;     /**< If total_size > 0, data */
                                    /**< will be provided later  */
     } reqdata;
+
+    /**
+     * Authentication credential needed to respond to 401/407 response.
+     */
+    pj_http_auth_cred	auth_cred;
+
 } pj_http_req_param;
 
 /**
+ * HTTP authentication challenge, parsed from WWW-Authenticate header.
+ */
+typedef struct pj_http_auth_chal
+{
+    pj_str_t	scheme;		/**< Auth scheme.		*/
+    pj_str_t	realm;		/**< Realm for the challenge.	*/
+    pj_str_t	domain;		/**< Domain.			*/
+    pj_str_t	nonce;		/**< Nonce challenge.		*/
+    pj_str_t	opaque;		/**< Opaque value.		*/
+    int		stale;		/**< Stale parameter.		*/
+    pj_str_t	algorithm;	/**< Algorithm parameter.	*/
+    pj_str_t	qop;		/**< Quality of protection.	*/
+} pj_http_auth_chal;
+
+/**
  * This structure describes HTTP response.
  */
 typedef struct pj_http_resp
@@ -136,11 +214,10 @@ typedef struct pj_http_resp
     pj_uint16_t     status_code;    /**< Status code of the request */
     pj_str_t        reason;         /**< Reason phrase */
     pj_http_headers headers;        /**< Response headers */
-    /**
-     * The value of content-length header field. -1 if not
-     * specified.
-     */
-    pj_int32_t      content_length; 
+    pj_http_auth_chal auth_chal;    /**< Parsed WWW-Authenticate header, if
+				         any. */
+    pj_int32_t      content_length; /**< The value of content-length header
+					 field. -1 if not specified. */
     void            *data;          /**< Data received */
     pj_size_t       size;           /**< Data size */
 } pj_http_resp;
@@ -150,6 +227,8 @@ typedef struct pj_http_resp
  */
 typedef struct pj_http_url
 {
+    pj_str_t	username;	    /**< Username part */
+    pj_str_t	passwd;		    /**< Password part */
     pj_str_t    protocol;           /**< Protocol used */
     pj_str_t    host;               /**< Host name */
     pj_uint16_t port;               /**< Port number */
diff --git a/pjlib-util/src/pjlib-util-test/http_client.c b/pjlib-util/src/pjlib-util-test/http_client.c
index fdf2d83..c7b0bed 100644
--- a/pjlib-util/src/pjlib-util-test/http_client.c
+++ b/pjlib-util/src/pjlib-util-test/http_client.c
@@ -1,4 +1,4 @@
-/* $Id: http_client.c 3262 2010-08-11 06:03:47Z bennylp $ */
+/* $Id: http_client.c 3332 2010-10-01 06:43:17Z bennylp $ */
 /* 
  * Copyright (C) 2008-2010 Teluu Inc. (http://www.teluu.com)
  *
@@ -237,49 +237,137 @@ static void on_response(pj_http_req *hreq, const pj_http_resp *resp)
 }
 
 
-pj_status_t parse_url(const char *url)
+pj_status_t parse_url(const char *url, pj_http_url *hurl)
 {
     pj_str_t surl;
-    pj_http_url hurl;
     pj_status_t status;
 
     pj_cstr(&surl, url);
-    status = pj_http_req_parse_url(&surl, &hurl);
+    status = pj_http_req_parse_url(&surl, hurl);
 #ifdef VERBOSE
     if (!status) {
         printf("URL: %s\nProtocol: %.*s\nHost: %.*s\nPort: %d\nPath: %.*s\n\n",
-               url, STR_PREC(hurl.protocol), STR_PREC(hurl.host), 
-               hurl.port, STR_PREC(hurl.path));
+               url, STR_PREC(hurl->protocol), STR_PREC(hurl->host),
+               hurl->port, STR_PREC(hurl->path));
     } else {
     }
 #endif
     return status;
 }
 
-int parse_url_test()
+static int parse_url_test()
 {
-    /* Simple URL without '/' in the end */
-    if (parse_url("http://www.google.com.sg") != PJ_SUCCESS)
-        return -11;
-    /* Simple URL with port number but without '/' in the end */
-    if (parse_url("http://www.example.com:8080") != PJ_SUCCESS)
-        return -13;
-    /* URL with path */
-    if (parse_url("http://127.0.0.1:280/Joomla/index.php?option=com_content&task=view&id=5&Itemid=6")
-        != PJ_SUCCESS)
-        return -15;
-    /* URL with port and path */
-    if (parse_url("http://teluu.com:81/about-us/") != PJ_SUCCESS)
-        return -17;
-    /* unsupported protocol */
-    if (parse_url("ftp://www.teluu.com") != PJ_ENOTSUP)
-        return -19;
-    /* invalid format */
-    if (parse_url("http:/teluu.com/about-us/") != PJLIB_UTIL_EHTTPINURL)
-        return -21;
-    /* invalid port number */
-    if (parse_url("http://teluu.com:xyz/") != PJLIB_UTIL_EHTTPINPORT)
-        return -23;
+    struct test_data
+    {
+	char *url;
+	pj_status_t result;
+	const char *username;
+	const char *passwd;
+	const char *host;
+	int port;
+	const char *path;
+    } test_data[] =
+    {
+	/* Simple URL without '/' in the end */
+        {"http://www.pjsip.org", PJ_SUCCESS, "", "", "www.pjsip.org", 80, "/"},
+
+        /* Simple URL with port number but without '/' in the end */
+        {"http://pjsip.org:8080", PJ_SUCCESS, "", "", "pjsip.org", 8080, "/"},
+
+        /* URL with path */
+        {"http://127.0.0.1:280/Joomla/index.php?option=com_content&task=view&id=5&Itemid=6",
+        	PJ_SUCCESS, "", "", "127.0.0.1", 280,
+        	"/Joomla/index.php?option=com_content&task=view&id=5&Itemid=6"},
+
+	/* URL with port and path */
+	{"http://pjsip.org:81/about-us/", PJ_SUCCESS, "", "", "pjsip.org", 81, "/about-us/"},
+
+	/* unsupported protocol */
+	{"ftp://www.pjsip.org", PJ_ENOTSUP, "", "", "", 80, ""},
+
+	/* invalid format */
+	{"http:/pjsip.org/about-us/", PJLIB_UTIL_EHTTPINURL, "", "", "", 80, ""},
+
+	/* invalid port number */
+	{"http://pjsip.org:xyz/", PJLIB_UTIL_EHTTPINPORT, "", "", "", 80, ""},
+
+	/* with username and password */
+	{"http://user:pass@pjsip.org", PJ_SUCCESS, "user", "pass", "pjsip.org", 80, "/"},
+
+	/* password only*/
+	{"http://:pass@pjsip.org", PJ_SUCCESS, "", "pass", "pjsip.org", 80, "/"},
+
+	/* user only*/
+	{"http://user:@pjsip.org", PJ_SUCCESS, "user", "", "pjsip.org", 80, "/"},
+
+	/* empty username and passwd*/
+	{"http://:@pjsip.org", PJ_SUCCESS, "", "", "pjsip.org", 80, "/"},
+
+	/* '@' character in username and path */
+	{"http://user@pjsip.org/@", PJ_SUCCESS, "user", "", "pjsip.org", 80, "/@"},
+
+	/* '@' character in path */
+	{"http://pjsip.org/@", PJ_SUCCESS, "", "", "pjsip.org", 80, "/@"},
+
+	/* '@' character in path */
+	{"http://pjsip.org/one@", PJ_SUCCESS, "", "", "pjsip.org", 80, "/one@"},
+
+	/* Invalid URL */
+	{"http://:", PJ_EINVAL, "", "", "", 0, ""},
+
+	/* Invalid URL */
+	{"http://@", PJ_EINVAL, "", "", "", 0, ""},
+
+	/* Invalid URL */
+	{"http", PJ_EINVAL, "", "", "", 0, ""},
+
+	/* Invalid URL */
+	{"http:/", PJ_EINVAL, "", "", "", 0, ""},
+
+	/* Invalid URL */
+	{"http://", PJ_EINVAL, "", "", "", 0, ""},
+
+	/* Invalid URL */
+	{"http:///", PJ_EINVAL, "", "", "", 0, ""},
+
+	/* Invalid URL */
+	{"http://@/", PJ_EINVAL, "", "", "", 0, ""},
+
+	/* Invalid URL */
+	{"http:///@", PJ_EINVAL, "", "", "", 0, ""},
+
+	/* Invalid URL */
+	{"http://:::", PJ_EINVAL, "", "", "", 0, ""},
+    };
+    unsigned i;
+
+    for (i=0; i<PJ_ARRAY_SIZE(test_data); ++i) {
+	struct test_data *ptd;
+	pj_http_url hurl;
+	pj_status_t status;
+
+	ptd = &test_data[i];
+
+	PJ_LOG(3, (THIS_FILE, ".. %s", ptd->url));
+	status = parse_url(ptd->url, &hurl);
+
+	if (status != ptd->result) {
+	    PJ_LOG(3,(THIS_FILE, "%d", status));
+	    return -11;
+	}
+	if (status != PJ_SUCCESS)
+	    continue;
+	if (pj_strcmp2(&hurl.username, ptd->username))
+	    return -12;
+	if (pj_strcmp2(&hurl.passwd, ptd->passwd))
+	    return -13;
+	if (pj_strcmp2(&hurl.host, ptd->host))
+	    return -14;
+	if (hurl.port != ptd->port)
+	    return -15;
+	if (pj_strcmp2(&hurl.path, ptd->path))
+	    return -16;
+    }
 
     return 0;
 }
diff --git a/pjlib-util/src/pjlib-util/http_client.c b/pjlib-util/src/pjlib-util/http_client.c
index 0e21728..4ce3c88 100644
--- a/pjlib-util/src/pjlib-util/http_client.c
+++ b/pjlib-util/src/pjlib-util/http_client.c
@@ -1,4 +1,4 @@
-/* $Id: http_client.c 3236 2010-07-13 13:18:08Z ming $ */
+/* $Id: http_client.c 3333 2010-10-04 01:11:54Z bennylp $ */
 /* 
  * Copyright (C) 2008-2010 Teluu Inc. (http://www.teluu.com)
  *
@@ -20,13 +20,17 @@
 #include <pjlib-util/http_client.h>
 #include <pj/activesock.h>
 #include <pj/assert.h>
+#include <pj/ctype.h>
 #include <pj/errno.h>
 #include <pj/except.h>
 #include <pj/pool.h>
 #include <pj/string.h>
 #include <pj/timer.h>
+#include <pjlib-util/base64.h>
 #include <pjlib-util/errno.h>
+#include <pjlib-util/md5.h>
 #include <pjlib-util/scanner.h>
+#include <pjlib-util/string.h>
 
 #if 0
     /* Enable some tracing */
@@ -39,7 +43,6 @@
 #define NUM_PROTOCOL            2
 #define HTTP_1_0                "1.0"
 #define HTTP_1_1                "1.1"
-#define HTTP_SEPARATOR          "://"
 #define CONTENT_LENGTH          "Content-Length"
 /* Buffer size for sending/receiving messages. */
 #define BUF_SIZE                2048
@@ -95,6 +98,13 @@ enum http_state
     ABORTING,
 };
 
+enum auth_state
+{
+    AUTH_NONE,		/* Not authenticating */
+    AUTH_RETRYING,	/* New request with auth has been submitted */
+    AUTH_DONE		/* Done retrying the request with auth. */
+};
+
 struct pj_http_req
 {
     pj_str_t                url;        /* Request URL */
@@ -109,6 +119,7 @@ struct pj_http_req
     pj_status_t             error;      /* Error status */
     pj_str_t                buffer;     /* Buffer to send/receive msgs */
     enum http_state         state;      /* State of the HTTP request */
+    enum auth_state	    auth_state; /* Authentication state */
     pj_timer_entry          timer_entry;/* Timer entry */
     pj_bool_t               resolved;   /* Whether URL's host is resolved */
     pj_http_resp            response;   /* HTTP response */
@@ -142,6 +153,11 @@ static pj_status_t http_response_parse(pj_pool_t *pool,
                                        pj_http_resp *response,
                                        void *data, pj_size_t size,
                                        pj_size_t *remainder);
+/* Restart the request with authentication */
+static void restart_req_with_auth(pj_http_req *hreq);
+/* Parse authentication challenge */
+static pj_status_t parse_auth_chal(pj_pool_t *pool, pj_str_t *input,
+				   pj_http_auth_chal *chal);
 
 static pj_uint16_t get_http_default_port(const pj_str_t *protocol)
 {
@@ -318,8 +334,59 @@ static pj_bool_t http_on_data_read(pj_activesock_t *asock,
                 hreq->response.data = data;
                 hreq->response.size = size - rem;
             }
+
+            /* If code is 401 or 407, find and parse WWW-Authenticate or
+             * Proxy-Authenticate header
+             */
+            if (hreq->response.status_code == 401 ||
+        	hreq->response.status_code == 407)
+            {
+        	const pj_str_t STR_WWW_AUTH = { "WWW-Authenticate", 16 };
+        	const pj_str_t STR_PROXY_AUTH = { "Proxy-Authenticate", 18 };
+        	pj_http_resp *response = &hreq->response;
+        	pj_http_headers *hdrs = &response->headers;
+        	unsigned i;
+
+        	status = PJ_ENOTFOUND;
+        	for (i = 0; i < hdrs->count; i++) {
+        	    if (!pj_stricmp(&hdrs->header[i].name, &STR_WWW_AUTH) ||
+        		!pj_stricmp(&hdrs->header[i].name, &STR_PROXY_AUTH))
+        	    {
+        		status = parse_auth_chal(hreq->pool,
+        					 &hdrs->header[i].value,
+        					 &response->auth_chal);
+        		break;
+        	    }
+        	}
+
+                /* Check if we should perform authentication */
+                if (status == PJ_SUCCESS &&
+		    hreq->auth_state == AUTH_NONE &&
+		    hreq->response.auth_chal.scheme.slen &&
+		    hreq->param.auth_cred.username.slen &&
+		    (hreq->param.auth_cred.scheme.slen == 0 ||
+		     !pj_stricmp(&hreq->response.auth_chal.scheme,
+				 &hreq->param.auth_cred.scheme)) &&
+		    (hreq->param.auth_cred.realm.slen == 0 ||
+		     !pj_stricmp(&hreq->response.auth_chal.realm,
+				 &hreq->param.auth_cred.realm))
+		    )
+		    {
+		    /* Yes, authentication is required and we have been
+		     * configured with credential.
+		     */
+		    restart_req_with_auth(hreq);
+		    if (hreq->auth_state == AUTH_RETRYING) {
+			/* We'll be resending the request with auth. This
+			 * connection has been closed.
+			 */
+			return PJ_FALSE;
+		    }
+                }
+            }
+
             /* We already received the response header, call the 
-             * appropriate callback. 
+             * appropriate callback.
              */
             if (hreq->cb.on_response)
                 (*hreq->cb.on_response)(hreq, &hreq->response);
@@ -384,7 +451,7 @@ static pj_bool_t http_on_data_read(pj_activesock_t *asock,
         hreq->response.content_length) ||
         (status == PJ_EEOF && hreq->response.content_length == -1)) 
     {
-        /* Finish reading */
+	/* Finish reading */
         http_req_end_request(hreq);
         hreq->response.size = hreq->tcp_state.current_read_size;
 
@@ -433,6 +500,98 @@ static void on_timeout( pj_timer_heap_t *timer_heap,
     pj_http_req_cancel(hreq, PJ_TRUE);
 }
 
+/* Parse authentication challenge */
+static pj_status_t parse_auth_chal(pj_pool_t *pool, pj_str_t *input,
+				   pj_http_auth_chal *chal)
+{
+    pj_scanner scanner;
+    const pj_str_t REALM_STR 	=    { "realm", 5},
+    		NONCE_STR 	=    { "nonce", 5},
+    		ALGORITHM_STR 	=    { "algorithm", 9 },
+    		STALE_STR 	=    { "stale", 5},
+    		QOP_STR 	=    { "qop", 3},
+    		OPAQUE_STR 	=    { "opaque", 6};
+    pj_status_t status = PJ_SUCCESS;
+    PJ_USE_EXCEPTION ;
+
+    pj_scan_init(&scanner, input->ptr, input->slen, PJ_SCAN_AUTOSKIP_WS,
+		 &on_syntax_error);
+    PJ_TRY {
+	/* Get auth scheme */
+	if (*scanner.curptr == '"') {
+	    pj_scan_get_quote(&scanner, '"', '"', &chal->scheme);
+	    chal->scheme.ptr++;
+	    chal->scheme.slen -= 2;
+	} else {
+	    pj_scan_get_until_chr(&scanner, " \t\r\n", &chal->scheme);
+	}
+
+	/* Loop parsing all parameters */
+	for (;;) {
+	    const char *end_param = ", \t\r\n;";
+	    pj_str_t name, value;
+
+	    /* Get pair of parameter name and value */
+	    value.ptr = NULL;
+	    value.slen = 0;
+	    pj_scan_get_until_chr(&scanner, "=, \t\r\n", &name);
+	    if (*scanner.curptr == '=') {
+		pj_scan_get_char(&scanner);
+		if (!pj_scan_is_eof(&scanner)) {
+		    if (*scanner.curptr == '"' || *scanner.curptr == '\'') {
+			int quote_char = *scanner.curptr;
+			pj_scan_get_quote(&scanner, quote_char, quote_char,
+					  &value);
+			value.ptr++;
+			value.slen -= 2;
+		    } else if (!strchr(end_param, *scanner.curptr)) {
+			pj_scan_get_until_chr(&scanner, end_param, &value);
+		    }
+		}
+		value = pj_str_unescape(pool, &value);
+	    }
+
+	    if (!pj_stricmp(&name, &REALM_STR)) {
+		chal->realm = value;
+
+	    } else if (!pj_stricmp(&name, &NONCE_STR)) {
+		chal->nonce = value;
+
+	    } else if (!pj_stricmp(&name, &ALGORITHM_STR)) {
+		chal->algorithm = value;
+
+	    } else if (!pj_stricmp(&name, &OPAQUE_STR)) {
+		chal->opaque = value;
+
+	    } else if (!pj_stricmp(&name, &QOP_STR)) {
+		chal->qop = value;
+
+	    } else if (!pj_stricmp(&name, &STALE_STR)) {
+		chal->stale = value.slen &&
+			      (*value.ptr != '0') &&
+			      (*value.ptr != 'f') &&
+			      (*value.ptr != 'F');
+
+	    }
+
+	    /* Eat comma */
+	    if (!pj_scan_is_eof(&scanner) && *scanner.curptr == ',')
+		pj_scan_get_char(&scanner);
+	    else
+		break;
+	}
+
+    }
+    PJ_CATCH_ANY {
+	status = PJ_GET_EXCEPTION();
+	pj_bzero(chal, sizeof(*chal));
+	TRACE_((THIS_FILE, "Error: parsing of auth header failed"));
+    }
+    PJ_END;
+    pj_scan_fini(&scanner);
+    return status;
+}
+
 /* The same as #pj_http_headers_add_elmt() with char * as
  * its parameters.
  */
@@ -464,9 +623,10 @@ static pj_status_t http_response_parse(pj_pool_t *pool,
 {
     pj_size_t i;
     char *cptr;
-    char *newdata;
+    char *end_status, *newdata;
     pj_scanner scanner;
     pj_str_t s;
+    const pj_str_t STR_CONTENT_LENGTH = { CONTENT_LENGTH, 14 };
     pj_status_t status;
 
     PJ_USE_EXCEPTION;
@@ -517,10 +677,13 @@ static pj_status_t http_response_parse(pj_pool_t *pool,
     }
     PJ_END;
 
+    end_status = scanner.curptr;
+    pj_scan_fini(&scanner);
+
     /* Parse the response headers. */
-    size = i - 2 - (scanner.curptr - newdata);
+    size = i - 2 - (end_status - newdata);
     if (size > 0) {
-        status = http_headers_parse(scanner.curptr + 1, size, 
+        status = http_headers_parse(end_status + 1, size,
                                     &response->headers);
     } else {
         status = PJ_SUCCESS;
@@ -528,8 +691,8 @@ static pj_status_t http_response_parse(pj_pool_t *pool,
 
     /* Find content-length header field. */
     for (i = 0; i < response->headers.count; i++) {
-        if (!pj_stricmp2(&response->headers.header[i].name, 
-                         CONTENT_LENGTH)) 
+        if (!pj_stricmp(&response->headers.header[i].name,
+                        &STR_CONTENT_LENGTH))
         {
             response->content_length = 
                 pj_strtoul(&response->headers.header[i].value);
@@ -545,8 +708,6 @@ static pj_status_t http_response_parse(pj_pool_t *pool,
         }
     }
 
-    pj_scan_fini(&scanner);
-
     return status;
 }
 
@@ -605,6 +766,34 @@ PJ_DEF(void) pj_http_req_param_default(pj_http_req_param *param)
     pj_time_val_normalize(&param->timeout);
 }
 
+/* Get the location of '@' character to indicate the end of
+ * user:passwd part of an URI. If user:passwd part is not
+ * present, NULL will be returned.
+ */
+static char *get_url_at_pos(const char *str, long len)
+{
+    const char *end = str + len;
+    const char *p = str;
+
+    /* skip scheme: */
+    while (p!=end && *p!='/') ++p;
+    if (p!=end && *p=='/') ++p;
+    if (p!=end && *p=='/') ++p;
+    if (p==end) return NULL;
+
+    for (; p!=end; ++p) {
+	switch (*p) {
+	case '/':
+	    return NULL;
+	case '@':
+	    return (char*)p;
+	}
+    }
+
+    return NULL;
+}
+
+
 PJ_DEF(pj_status_t) pj_http_req_parse_url(const pj_str_t *url, 
                                           pj_http_url *hurl)
 {
@@ -614,6 +803,7 @@ PJ_DEF(pj_status_t) pj_http_req_parse_url(const pj_str_t *url,
 
     if (!len) return -1;
     
+    pj_bzero(hurl, sizeof(*hurl));
     pj_scan_init(&scanner, url->ptr, url->slen, 0, &on_syntax_error);
 
     PJ_TRY {
@@ -634,16 +824,28 @@ PJ_DEF(pj_status_t) pj_http_req_parse_url(const pj_str_t *url,
             PJ_THROW(PJ_ENOTSUP); // unsupported protocol
         }
 
-        if (pj_scan_strcmp(&scanner, HTTP_SEPARATOR,
-                           pj_ansi_strlen(HTTP_SEPARATOR))) 
-        {
+        if (pj_scan_strcmp(&scanner, "://", 3)) {
             PJ_THROW(PJLIB_UTIL_EHTTPINURL); // no "://" after protocol name
         }
-        pj_scan_advance_n(&scanner, pj_ansi_strlen(HTTP_SEPARATOR), PJ_FALSE);
+        pj_scan_advance_n(&scanner, 3, PJ_FALSE);
+
+        if (get_url_at_pos(url->ptr, url->slen)) {
+            /* Parse username and password */
+            pj_scan_get_until_chr(&scanner, ":@", &hurl->username);
+            if (*scanner.curptr == ':') {
+        	pj_scan_get_char(&scanner);
+        	pj_scan_get_until_chr(&scanner, "@", &hurl->passwd);
+            } else {
+        	hurl->passwd.slen = 0;
+            }
+            pj_scan_get_char(&scanner);
+        }
 
         /* Parse the host and port number (if any) */
         pj_scan_get_until_chr(&scanner, ":/", &s);
         pj_strassign(&hurl->host, &s);
+        if (hurl->host.slen==0)
+            PJ_THROW(PJ_EINVAL);
         if (pj_scan_is_eof(&scanner) || *scanner.curptr == '/') {
             /* No port number specified */
             /* Assume default http/https port number */
@@ -692,6 +894,7 @@ PJ_DEF(pj_status_t) pj_http_req_create(pj_pool_t *pool,
 {
     pj_pool_t *own_pool;
     pj_http_req *hreq;
+    char *at_pos;
     pj_status_t status;
 
     PJ_ASSERT_RETURN(pool && url && timer && ioqueue && 
@@ -736,11 +939,54 @@ PJ_DEF(pj_status_t) pj_http_req_create(pj_pool_t *pool,
     }
 
     /* Parse the URL */
-    if (!pj_strdup(hreq->pool, &hreq->url, url))
+    if (!pj_strdup_with_null(hreq->pool, &hreq->url, url)) {
+	pj_pool_release(hreq->pool);
         return PJ_ENOMEM;
+    }
     status = pj_http_req_parse_url(&hreq->url, &hreq->hurl);
-    if (status != PJ_SUCCESS)
+    if (status != PJ_SUCCESS) {
+	pj_pool_release(hreq->pool);
         return status; // Invalid URL supplied
+    }
+
+    /* If URL contains username/password, move them to credential and
+     * remove them from the URL.
+     */
+    if ((at_pos=get_url_at_pos(hreq->url.ptr, hreq->url.slen)) != NULL) {
+	pj_str_t tmp;
+	char *user_pos = pj_strchr(&hreq->url, '/');
+	int removed_len;
+
+	/* Save credential first, unescape the string */
+	tmp = pj_str_unescape(hreq->pool, &hreq->hurl.username);;
+	pj_strdup(hreq->pool, &hreq->param.auth_cred.username, &tmp);
+
+	tmp = pj_str_unescape(hreq->pool, &hreq->hurl.passwd);
+	pj_strdup(hreq->pool, &hreq->param.auth_cred.data, &tmp);
+
+	hreq->hurl.username.ptr = hreq->hurl.passwd.ptr = NULL;
+	hreq->hurl.username.slen = hreq->hurl.passwd.slen = 0;
+
+	/* Remove "username:password@" from the URL */
+	pj_assert(user_pos != 0 && user_pos < at_pos);
+	user_pos += 2;
+	removed_len = at_pos + 1 - user_pos;
+	pj_memmove(user_pos, at_pos+1, hreq->url.ptr+hreq->url.slen-at_pos-1);
+	hreq->url.slen -= removed_len;
+
+	/* Need to adjust hostname and path pointers due to memmove*/
+	if (hreq->hurl.host.ptr > user_pos &&
+	    hreq->hurl.host.ptr < user_pos + hreq->url.slen)
+	{
+	    hreq->hurl.host.ptr -= removed_len;
+	}
+	/* path may come from a string constant, don't shift it if so */
+	if (hreq->hurl.path.ptr > user_pos &&
+	    hreq->hurl.path.ptr < user_pos + hreq->url.slen)
+	{
+	    hreq->hurl.path.ptr -= removed_len;
+	}
+    }
 
     *http_req = hreq;
     return PJ_SUCCESS;
@@ -770,7 +1016,10 @@ PJ_DEF(pj_status_t) pj_http_req_start(pj_http_req *http_req)
      */
     PJ_ASSERT_RETURN(http_req->state == IDLE, PJ_EBUSY);
 
+    /* Reset few things to make sure restarting works */
     http_req->error = 0;
+    http_req->response.headers.count = 0;
+    pj_bzero(&http_req->tcp_state, sizeof(http_req->tcp_state));
 
     if (!http_req->resolved) {
         /* Resolve the Internet address of the host */
@@ -837,7 +1086,364 @@ on_return:
     return status;
 }
 
-#define STR_PREC(s) s.slen, s.ptr
+/* Respond to basic authentication challenge */
+static pj_status_t auth_respond_basic(pj_http_req *hreq)
+{
+    /* Basic authentication:
+     *      credentials       = "Basic" basic-credentials
+     *      basic-credentials = base64-user-pass
+     *      base64-user-pass  = <base64 [4] encoding of user-pass>
+     *      user-pass         = userid ":" password
+     *
+     * Sample:
+     *       Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
+     */
+    pj_str_t user_pass;
+    pj_http_header_elmt *phdr;
+    int len;
+
+    /* Use send buffer to store userid ":" password */
+    user_pass.ptr = hreq->buffer.ptr;
+    pj_strcpy(&user_pass, &hreq->param.auth_cred.username);
+    pj_strcat2(&user_pass, ":");
+    pj_strcat(&user_pass, &hreq->param.auth_cred.data);
+
+    /* Create Authorization header */
+    phdr = &hreq->param.headers.header[hreq->param.headers.count++];
+    pj_bzero(phdr, sizeof(*phdr));
+    if (hreq->response.status_code == 401)
+	phdr->name = pj_str("Authorization");
+    else
+	phdr->name = pj_str("Proxy-Authorization");
+
+    len = PJ_BASE256_TO_BASE64_LEN(user_pass.slen) + 10;
+    phdr->value.ptr = (char*)pj_pool_alloc(hreq->pool, len);
+    phdr->value.slen = 0;
+
+    pj_strcpy2(&phdr->value, "Basic ");
+    len -= phdr->value.slen;
+    pj_base64_encode((pj_uint8_t*)user_pass.ptr, (int)user_pass.slen,
+		     phdr->value.ptr + phdr->value.slen, &len);
+    phdr->value.slen += len;
+
+    return PJ_SUCCESS;
+}
+
+/** Length of digest string. */
+#define MD5_STRLEN 32
+/* A macro just to get rid of type mismatch between char and unsigned char */
+#define MD5_APPEND(pms,buf,len)	pj_md5_update(pms, (const pj_uint8_t*)buf, len)
+
+/* Transform digest to string.
+ * output must be at least PJSIP_MD5STRLEN+1 bytes.
+ *
+ * NOTE: THE OUTPUT STRING IS NOT NULL TERMINATED!
+ */
+static void digest2str(const unsigned char digest[], char *output)
+{
+    int i;
+    for (i = 0; i<16; ++i) {
+	pj_val_to_hex_digit(digest[i], output);
+	output += 2;
+    }
+}
+
+static void auth_create_digest_response(pj_str_t *result,
+					const pj_http_auth_cred *cred,
+				        const pj_str_t *nonce,
+				        const pj_str_t *nc,
+				        const pj_str_t *cnonce,
+				        const pj_str_t *qop,
+				        const pj_str_t *uri,
+				        const pj_str_t *realm,
+				        const pj_str_t *method)
+{
+    char ha1[MD5_STRLEN];
+    char ha2[MD5_STRLEN];
+    unsigned char digest[16];
+    pj_md5_context pms;
+
+    pj_assert(result->slen >= MD5_STRLEN);
+
+    TRACE_((THIS_FILE, "Begin creating digest"));
+
+    if (cred->data_type == 0) {
+	/***
+	 *** ha1 = MD5(username ":" realm ":" password)
+	 ***/
+	pj_md5_init(&pms);
+	MD5_APPEND( &pms, cred->username.ptr, cred->username.slen);
+	MD5_APPEND( &pms, ":", 1);
+	MD5_APPEND( &pms, realm->ptr, realm->slen);
+	MD5_APPEND( &pms, ":", 1);
+	MD5_APPEND( &pms, cred->data.ptr, cred->data.slen);
+	pj_md5_final(&pms, digest);
+
+	digest2str(digest, ha1);
+
+    } else if (cred->data_type == 1) {
+	pj_assert(cred->data.slen == 32);
+	pj_memcpy( ha1, cred->data.ptr, cred->data.slen );
+    } else {
+	pj_assert(!"Invalid data_type");
+    }
+
+    TRACE_((THIS_FILE, "  ha1=%.32s", ha1));
+
+    /***
+     *** ha2 = MD5(method ":" req_uri)
+     ***/
+    pj_md5_init(&pms);
+    MD5_APPEND( &pms, method->ptr, method->slen);
+    MD5_APPEND( &pms, ":", 1);
+    MD5_APPEND( &pms, uri->ptr, uri->slen);
+    pj_md5_final(&pms, digest);
+    digest2str(digest, ha2);
+
+    TRACE_((THIS_FILE, "  ha2=%.32s", ha2));
+
+    /***
+     *** When qop is not used:
+     ***    response = MD5(ha1 ":" nonce ":" ha2)
+     ***
+     *** When qop=auth is used:
+     ***    response = MD5(ha1 ":" nonce ":" nc ":" cnonce ":" qop ":" ha2)
+     ***/
+    pj_md5_init(&pms);
+    MD5_APPEND( &pms, ha1, MD5_STRLEN);
+    MD5_APPEND( &pms, ":", 1);
+    MD5_APPEND( &pms, nonce->ptr, nonce->slen);
+    if (qop && qop->slen != 0) {
+	MD5_APPEND( &pms, ":", 1);
+	MD5_APPEND( &pms, nc->ptr, nc->slen);
+	MD5_APPEND( &pms, ":", 1);
+	MD5_APPEND( &pms, cnonce->ptr, cnonce->slen);
+	MD5_APPEND( &pms, ":", 1);
+	MD5_APPEND( &pms, qop->ptr, qop->slen);
+    }
+    MD5_APPEND( &pms, ":", 1);
+    MD5_APPEND( &pms, ha2, MD5_STRLEN);
+
+    /* This is the final response digest. */
+    pj_md5_final(&pms, digest);
+
+    /* Convert digest to string and store in chal->response. */
+    result->slen = MD5_STRLEN;
+    digest2str(digest, result->ptr);
+
+    TRACE_((THIS_FILE, "  digest=%.32s", result->ptr));
+    TRACE_((THIS_FILE, "Digest created"));
+}
+
+/* Find out if qop offer contains "auth" token */
+static pj_bool_t auth_has_qop( pj_pool_t *pool, const pj_str_t *qop_offer)
+{
+    pj_str_t qop;
+    char *p;
+
+    pj_strdup_with_null( pool, &qop, qop_offer);
+    p = qop.ptr;
+    while (*p) {
+	*p = (char)pj_tolower(*p);
+	++p;
+    }
+
+    p = qop.ptr;
+    while (*p) {
+	if (*p=='a' && *(p+1)=='u' && *(p+2)=='t' && *(p+3)=='h') {
+	    int e = *(p+4);
+	    if (e=='"' || e==',' || e==0)
+		return PJ_TRUE;
+	    else
+		p += 4;
+	} else {
+	    ++p;
+	}
+    }
+
+    return PJ_FALSE;
+}
+
+#define STR_PREC(s) (int)(s).slen, (s).ptr
+
+/* Respond to digest authentication */
+static pj_status_t auth_respond_digest(pj_http_req *hreq)
+{
+    const pj_http_auth_chal *chal = &hreq->response.auth_chal;
+    const pj_http_auth_cred *cred = &hreq->param.auth_cred;
+    pj_http_header_elmt *phdr;
+    char digest_response_buf[MD5_STRLEN];
+    int len;
+    pj_str_t digest_response;
+
+    /* Check algorithm is supported. We only support MD5 */
+    if (chal->algorithm.slen!=0 &&
+	pj_stricmp2(&chal->algorithm, "MD5"))
+    {
+	TRACE_((THIS_FILE, "Error: Unsupported digest algorithm \"%.*s\"",
+		  chal->algorithm.slen, chal->algorithm.ptr));
+	return PJ_ENOTSUP;
+    }
+
+    /* Add Authorization header */
+    phdr = &hreq->param.headers.header[hreq->param.headers.count++];
+    pj_bzero(phdr, sizeof(*phdr));
+    if (hreq->response.status_code == 401)
+	phdr->name = pj_str("Authorization");
+    else
+	phdr->name = pj_str("Proxy-Authorization");
+
+    /* Allocate space for the header */
+    len = 8 + /* Digest */
+	  16 + hreq->param.auth_cred.username.slen + /* username= */
+	  12 + chal->realm.slen + /* realm= */
+	  12 + chal->nonce.slen + /* nonce= */
+	  8 + hreq->hurl.path.slen + /* uri= */
+	  16 + /* algorithm=MD5 */
+	  16 + MD5_STRLEN + /* response= */
+	  12 + /* qop=auth */
+	  8 + /* nc=.. */
+	  30 + /* cnonce= */
+	  12 + chal->opaque.slen + /* opaque=".." */
+	  0;
+    phdr->value.ptr = (char*)pj_pool_alloc(hreq->pool, len);
+
+    /* Configure buffer to temporarily store the digest */
+    digest_response.ptr = digest_response_buf;
+    digest_response.slen = MD5_STRLEN;
+
+    if (chal->qop.slen == 0) {
+	const pj_str_t STR_MD5 = { "MD5", 3 };
+
+	/* Server doesn't require quality of protection. */
+	auth_create_digest_response(&digest_response, cred,
+				    &chal->nonce, NULL, NULL,  NULL,
+				    &hreq->hurl.path, &chal->realm,
+				    &hreq->param.method);
+
+	len = pj_ansi_snprintf(
+		phdr->value.ptr, len,
+		"Digest username=\"%.*s\", "
+		"realm=\"%.*s\", "
+		"nonce=\"%.*s\", "
+		"uri=\"%.*s\", "
+		"algorithm=%.*s, "
+		"response=\"%.*s\"",
+		STR_PREC(cred->username),
+		STR_PREC(chal->realm),
+		STR_PREC(chal->nonce),
+		STR_PREC(hreq->hurl.path),
+		STR_PREC(STR_MD5),
+		STR_PREC(digest_response));
+	if (len < 0)
+	    return PJ_ETOOSMALL;
+	phdr->value.slen = len;
+
+    } else if (auth_has_qop(hreq->pool, &chal->qop)) {
+	/* Server requires quality of protection.
+	 * We respond with selecting "qop=auth" protection.
+	 */
+	const pj_str_t STR_MD5 = { "MD5", 3 };
+	const pj_str_t qop = pj_str("auth");
+	const pj_str_t nc = pj_str("1");
+	const pj_str_t cnonce = pj_str("b39971");
+
+	auth_create_digest_response(&digest_response, cred,
+				    &chal->nonce, &nc, &cnonce, &qop,
+				    &hreq->hurl.path, &chal->realm,
+				    &hreq->param.method);
+	len = pj_ansi_snprintf(
+		phdr->value.ptr, len,
+		"Digest username=\"%.*s\", "
+		"realm=\"%.*s\", "
+		"nonce=\"%.*s\", "
+		"uri=\"%.*s\", "
+		"algorithm=%.*s, "
+		"response=\"%.*s\", "
+		"qop=%.*s, "
+		"nc=%.*s, "
+		"cnonce=\"%.*s\"",
+		STR_PREC(cred->username),
+		STR_PREC(chal->realm),
+		STR_PREC(chal->nonce),
+		STR_PREC(hreq->hurl.path),
+		STR_PREC(STR_MD5),
+		STR_PREC(digest_response),
+		STR_PREC(qop),
+		STR_PREC(nc),
+		STR_PREC(cnonce));
+	if (len < 0)
+	    return PJ_ETOOSMALL;
+	phdr->value.slen = len;
+
+	if (chal->opaque.slen) {
+	    pj_strcat2(&phdr->value, ", opaque=\"");
+	    pj_strcat(&phdr->value, &chal->opaque);
+	    pj_strcat2(&phdr->value, "\"");
+	}
+
+    } else {
+	/* Server requires quality protection that we don't support. */
+	TRACE_((THIS_FILE, "Error: Unsupported qop offer %.*s",
+		chal->qop.slen, chal->qop.ptr));
+	return PJ_ENOTSUP;
+    }
+
+    return PJ_SUCCESS;
+}
+
+
+static void restart_req_with_auth(pj_http_req *hreq)
+{
+    pj_http_auth_chal *chal = &hreq->response.auth_chal;
+    pj_http_auth_cred *cred = &hreq->param.auth_cred;
+    pj_status_t status;
+
+    if (hreq->param.headers.count >= PJ_HTTP_HEADER_SIZE) {
+	TRACE_((THIS_FILE, "Error: no place to put Authorization header"));
+	hreq->auth_state = AUTH_DONE;
+	return;
+    }
+
+    /* If credential specifies specific scheme, make sure they match */
+    if (cred->scheme.slen && pj_stricmp(&chal->scheme, &cred->scheme)) {
+	status = PJ_ENOTSUP;
+	TRACE_((THIS_FILE, "Error: auth schemes mismatch"));
+	goto on_error;
+    }
+
+    /* If credential specifies specific realm, make sure they match */
+    if (cred->realm.slen && pj_stricmp(&chal->realm, &cred->realm)) {
+	status = PJ_ENOTSUP;
+	TRACE_((THIS_FILE, "Error: auth realms mismatch"));
+	goto on_error;
+    }
+
+    if (!pj_stricmp2(&chal->scheme, "basic")) {
+	status = auth_respond_basic(hreq);
+    } else if (!pj_stricmp2(&chal->scheme, "digest")) {
+	status = auth_respond_digest(hreq);
+    } else {
+	TRACE_((THIS_FILE, "Error: unsupported HTTP auth scheme"));
+	status = PJ_ENOTSUP;
+    }
+
+    if (status != PJ_SUCCESS)
+	goto on_error;
+
+    http_req_end_request(hreq);
+
+    status = pj_http_req_start(hreq);
+    if (status != PJ_SUCCESS)
+	goto on_error;
+
+    hreq->auth_state = AUTH_RETRYING;
+    return;
+
+on_error:
+    hreq->auth_state = AUTH_DONE;
+}
+
 
 /* snprintf() to a pj_str_t struct with an option to append the 
  * result at the back of the string.
@@ -875,13 +1481,13 @@ static pj_status_t http_req_start_sending(pj_http_req *hreq)
         pj_strassign(&pkt, &hreq->buffer);
         pkt.slen = 0;
         /* Start-line */
-        str_snprintf(&pkt, BUF_SIZE, PJ_TRUE, "%.*s %.*s %s/%.*s\n",
+        str_snprintf(&pkt, BUF_SIZE, PJ_TRUE, "%.*s %.*s %s/%.*s\r\n",
                      STR_PREC(hreq->param.method), 
                      STR_PREC(hreq->hurl.path),
                      get_protocol(&hreq->hurl.protocol), 
                      STR_PREC(hreq->param.version));
         /* Header field "Host" */
-        str_snprintf(&pkt, BUF_SIZE, PJ_TRUE, "Host: %.*s:%d\n",
+        str_snprintf(&pkt, BUF_SIZE, PJ_TRUE, "Host: %.*s:%d\r\n",
                      STR_PREC(hreq->hurl.host), hreq->hurl.port);
         if (!pj_strcmp2(&hreq->param.method, http_method_names[HTTP_PUT])) {
             char buf[16];
@@ -890,13 +1496,13 @@ static pj_status_t http_req_start_sending(pj_http_req *hreq)
             pj_utoa(hreq->param.reqdata.total_size ? 
                     hreq->param.reqdata.total_size: 
                     hreq->param.reqdata.size, buf);
-            str_snprintf(&pkt, BUF_SIZE, PJ_TRUE, "%s: %s\n",
+            str_snprintf(&pkt, BUF_SIZE, PJ_TRUE, "%s: %s\r\n",
                          CONTENT_LENGTH, buf);
         }
 
         /* Append user-specified headers */
         for (i = 0; i < hreq->param.headers.count; i++) {
-            str_snprintf(&pkt, BUF_SIZE, PJ_TRUE, "%.*s: %.*s\n",
+            str_snprintf(&pkt, BUF_SIZE, PJ_TRUE, "%.*s: %.*s\r\n",
                          STR_PREC(hreq->param.headers.header[i].name),
                          STR_PREC(hreq->param.headers.header[i].value));
         }
@@ -905,7 +1511,7 @@ static pj_status_t http_req_start_sending(pj_http_req *hreq)
             goto on_return;
         }
 
-        pj_strcat2(&pkt, "\n");
+        pj_strcat2(&pkt, "\r\n");
         pkt.ptr[pkt.slen] = 0;
         TRACE_((THIS_FILE, "%s", pkt.ptr));
     } else {
diff --git a/pjlib-util/src/pjlib-util/resolver.c b/pjlib-util/src/pjlib-util/resolver.c
index 1b80ffe..e163449 100644
--- a/pjlib-util/src/pjlib-util/resolver.c
+++ b/pjlib-util/src/pjlib-util/resolver.c
@@ -1,4 +1,4 @@
-/* $Id: resolver.c 3298 2010-08-27 03:19:00Z bennylp $ */
+/* $Id: resolver.c 3346 2010-10-14 10:56:02Z bennylp $ */
 /* 
  * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
  * Copyright (C) 2003-2008 Benny Prijono <benny at prijono.org>
@@ -841,10 +841,11 @@ PJ_DEF(pj_status_t) pj_dns_resolver_cancel_query(pj_dns_async_query *query,
 PJ_DEF(pj_status_t) pj_dns_parse_a_response(const pj_dns_parsed_packet *pkt,
 					    pj_dns_a_record *rec)
 {
-    pj_str_t hostname, alias, *res_name;
+    enum { MAX_SEARCH = 20 };
+    pj_str_t hostname, alias = {NULL, 0}, *resname;
     unsigned bufstart = 0;
     unsigned bufleft = sizeof(rec->buf_);
-    unsigned i, ansidx;
+    unsigned i, ansidx, search_cnt=0;
 
     PJ_ASSERT_RETURN(pkt && rec, PJ_EINVAL);
 
@@ -887,18 +888,35 @@ PJ_DEF(pj_status_t) pj_dns_parse_a_response(const pj_dns_parsed_packet *pkt,
     if (ansidx == pkt->hdr.anscount)
 	return PJLIB_UTIL_EDNSNOANSWERREC;
 
-    /* If hostname is a CNAME, get the alias. */
-    if (pkt->ans[ansidx].type == PJ_DNS_TYPE_CNAME) {
-	alias = pkt->ans[ansidx].rdata.cname.name;
-	res_name = &alias;
-    } else if (pkt->ans[ansidx].type == PJ_DNS_TYPE_A) {
-	alias.ptr = NULL;
-	alias.slen = 0;
-	res_name = &hostname;
-    } else {
-	return PJLIB_UTIL_EDNSINANSWER;
+    resname = &hostname;
+
+    /* Keep following CNAME records. */
+    while (pkt->ans[ansidx].type == PJ_DNS_TYPE_CNAME &&
+	   search_cnt++ < MAX_SEARCH)
+    {
+	resname = &pkt->ans[ansidx].rdata.cname.name;
+
+	if (!alias.slen)
+	    alias = *resname;
+
+	for (i=0; i < pkt->hdr.anscount; ++i) {
+	    if (pj_stricmp(resname, &pkt->ans[i].name)==0) {
+		break;
+	    }
+	}
+
+	if (i==pkt->hdr.anscount)
+	    return PJLIB_UTIL_EDNSNOANSWERREC;
+
+	ansidx = i;
     }
 
+    if (search_cnt >= MAX_SEARCH)
+	return PJLIB_UTIL_EDNSINANSWER;
+
+    if (pkt->ans[ansidx].type != PJ_DNS_TYPE_A)
+	return PJLIB_UTIL_EDNSINANSWER;
+
     /* Copy alias to the record, if present. */
     if (alias.slen) {
 	if (alias.slen > (int)bufleft)
@@ -912,17 +930,14 @@ PJ_DEF(pj_status_t) pj_dns_parse_a_response(const pj_dns_parsed_packet *pkt,
 	bufleft -= alias.slen;
     }
 
-    /* Now scan the answer for all type A RRs where the name matches
-     * hostname or alias.
-     */
-    for (i=0; i<pkt->hdr.anscount; ++i) {
+    /* Get the IP addresses. */
+    for (i=0; i < pkt->hdr.anscount; ++i) {
 	if (pkt->ans[i].type == PJ_DNS_TYPE_A &&
-	    pj_stricmp(&pkt->ans[i].name, res_name)==0 &&
+	    pj_stricmp(&pkt->ans[i].name, resname)==0 &&
 	    rec->addr_count < PJ_DNS_MAX_IP_IN_A_REC)
 	{
-	    rec->addr[rec->addr_count].s_addr = 
+	    rec->addr[rec->addr_count++].s_addr =
 		pkt->ans[i].rdata.a.ip_addr.s_addr;
-	    ++rec->addr_count;
 	}
     }
 
diff --git a/pjlib/build/Makefile b/pjlib/build/Makefile
index 1e0e88f..76fece3 100644
--- a/pjlib/build/Makefile
+++ b/pjlib/build/Makefile
@@ -58,7 +58,7 @@ all: $(TARGETS)
 
 doc:
 	cd .. && rm -rf docs/html docs/latex && doxygen docs/doxygen.cfg
-	@if test ! "$(WWWDIR)" == ""; then \
+	@if [ -n "$(WWWDIR)" ]; then \
 		echo "Copying to $(WWWDIR)/pjlib/docs/html.." ; \
 		cp -a ../docs/html/* $(WWWDIR)/pjlib/docs/html/ ; \
 	fi
diff --git a/pjlib/include/pj/activesock.h b/pjlib/include/pj/activesock.h
index 6962b81..2dc3c7f 100644
--- a/pjlib/include/pj/activesock.h
+++ b/pjlib/include/pj/activesock.h
@@ -1,4 +1,4 @@
-/* $Id: activesock.h 3299 2010-08-27 06:46:29Z ming $ */
+/* $Id: activesock.h 3350 2010-10-20 09:54:45Z bennylp $ */
 /* 
  * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
  * Copyright (C) 2003-2008 Benny Prijono <benny at prijono.org>
@@ -302,20 +302,39 @@ PJ_DECL(pj_status_t) pj_activesock_create_udp(pj_pool_t *pool,
  */
 PJ_DECL(pj_status_t) pj_activesock_close(pj_activesock_t *asock);
 
-#if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \
-    PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0
+#if (defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \
+     PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0) || \
+     defined(DOXYGEN)
 /**
  * Set iPhone OS background mode setting. Setting to 1 will enable TCP
  * active socket to receive incoming data when application is in the
  * background. Setting to 0 will disable it. Default value of this
  * setting is PJ_ACTIVESOCK_TCP_IPHONE_OS_BG.
  *
+ * This API is only available if PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT
+ * is set to non-zero.
+ *
  * @param asock	    The active socket.
  * @param val	    The value of background mode setting.
  *
  */
 PJ_DECL(void) pj_activesock_set_iphone_os_bg(pj_activesock_t *asock,
 					     int val);
+
+/**
+ * Enable/disable support for iPhone OS background mode. This setting
+ * will apply globally and will affect any active sockets created
+ * afterwards, if you want to change the setting for a particular
+ * active socket, use #pj_activesock_set_iphone_os_bg() instead.
+ * By default, this setting is enabled.
+ *
+ * This API is only available if PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT
+ * is set to non-zero.
+ *
+ * @param val	    The value of global background mode setting.
+ *
+ */
+PJ_DECL(void) pj_activesock_enable_iphone_os_bg(pj_bool_t val);
 #endif
 
 /**
diff --git a/pjlib/include/pj/config.h b/pjlib/include/pj/config.h
index e831f3c..4ed9d3f 100644
--- a/pjlib/include/pj/config.h
+++ b/pjlib/include/pj/config.h
@@ -1,4 +1,4 @@
-/* $Id: config.h 3182 2010-05-19 06:07:40Z bennylp $ */
+/* $Id: config.h 3316 2010-09-22 13:11:11Z ming $ */
 /* 
  * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
  * Copyright (C) 2003-2008 Benny Prijono <benny at prijono.org>
@@ -507,6 +507,16 @@
 #endif
 
 /**
+ * Maximum consecutive identical error for accept() operation before
+ * activesock stops calling the next ioqueue accept.
+ *
+ * Default: 50
+ */
+#ifndef PJ_ACTIVESOCK_MAX_CONSECUTIVE_ACCEPT_ERROR
+#   define PJ_ACTIVESOCK_MAX_CONSECUTIVE_ACCEPT_ERROR 50
+#endif
+
+/**
  * Constants for declaring the maximum handles that can be supported by
  * a single IOQ framework. This constant might not be relevant to the 
  * underlying I/O queue impelementation, but still, developers should be 
diff --git a/pjlib/include/pj/config_site_sample.h b/pjlib/include/pj/config_site_sample.h
index 2751ab2..0c7832f 100644
--- a/pjlib/include/pj/config_site_sample.h
+++ b/pjlib/include/pj/config_site_sample.h
@@ -373,13 +373,12 @@
  * than native fdset_t and will trigger assertion on sock_select.c.
  */
 #   define PJ_IOQUEUE_MAX_HANDLES	32
+#   define PJ_CRC32_HAS_TABLES		0
 #   define PJSIP_MAX_TSX_COUNT		15
 #   define PJSIP_MAX_DIALOG_COUNT	15
 #   define PJSIP_UDP_SO_SNDBUF_SIZE	4000
 #   define PJSIP_UDP_SO_RCVBUF_SIZE	4000
-#   define PJMEDIA_HAS_LARGE_FILTER	0
-#   define PJMEDIA_HAS_SMALL_FILTER	0
-
+#   define PJMEDIA_HAS_ALAW_ULAW_TABLE	0
 
 #elif defined(PJ_CONFIG_MAXIMUM_SPEED)
 #   define PJ_SCANNER_USE_BITWISE	0
diff --git a/pjlib/src/pj/activesock.c b/pjlib/src/pj/activesock.c
index b13f438..2c491cf 100644
--- a/pjlib/src/pj/activesock.c
+++ b/pjlib/src/pj/activesock.c
@@ -1,4 +1,4 @@
-/* $Id: activesock.c 3299 2010-08-27 06:46:29Z ming $ */
+/* $Id: activesock.c 3336 2010-10-11 10:59:37Z ming $ */
 /* 
  * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
  * Copyright (C) 2003-2008 Benny Prijono <benny at prijono.org>
@@ -29,6 +29,8 @@
 #if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \
     PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0
 #   include <CFNetwork/CFNetwork.h>
+
+    static pj_bool_t ios_bg_support = PJ_TRUE;
 #endif
 
 #define PJ_ACTIVESOCK_MAX_LOOP	    50
@@ -84,6 +86,9 @@ struct pj_activesock_t
     CFReadStreamRef	 readStream;
 #endif
     
+    unsigned		 err_counter;
+    pj_status_t		 last_err;
+
     struct send_data	 send_data;
 
     struct read_op	*read_op;
@@ -130,7 +135,7 @@ static void activesock_destroy_iphone_os_stream(pj_activesock_t *asock)
 
 static void activesock_create_iphone_os_stream(pj_activesock_t *asock)
 {
-    if (asock->bg_setting && asock->stream_oriented) {
+    if (ios_bg_support && asock->bg_setting && asock->stream_oriented) {
 	activesock_destroy_iphone_os_stream(asock);
 
 	CFStreamCreatePairWithSocket(kCFAllocatorDefault, asock->sock,
@@ -161,6 +166,11 @@ PJ_DEF(void) pj_activesock_set_iphone_os_bg(pj_activesock_t *asock,
     else
 	activesock_destroy_iphone_os_stream(asock);
 }
+
+PJ_DEF(void) pj_activesock_enable_iphone_os_bg(pj_bool_t val)
+{
+    ios_bg_support = val;
+}
 #endif
 
 PJ_DEF(pj_status_t) pj_activesock_create( pj_pool_t *pool,
@@ -216,8 +226,7 @@ PJ_DEF(pj_status_t) pj_activesock_create( pj_pool_t *pool,
 #if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \
     PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0
     asock->sock = sock;
-    pj_activesock_set_iphone_os_bg(asock,
-				   PJ_ACTIVESOCK_TCP_IPHONE_OS_BG);
+    asock->bg_setting = PJ_ACTIVESOCK_TCP_IPHONE_OS_BG;
 #endif
 
     *p_asock = asock;
@@ -790,6 +799,19 @@ static void ioqueue_on_accept_complete(pj_ioqueue_key_t *key,
     PJ_UNUSED_ARG(new_sock);
 
     do {
+	if (status == asock->last_err && status != PJ_SUCCESS) {
+	    asock->err_counter++;
+	    if (asock->err_counter >= PJ_ACTIVESOCK_MAX_CONSECUTIVE_ACCEPT_ERROR) {
+		PJ_LOG(3, ("", "Received %d consecutive errors: %d for the accept()"
+			       " operation, stopping further ioqueue accepts.",
+			       asock->err_counter, asock->last_err));
+		return;
+	    }
+	} else {
+	    asock->err_counter = 0;
+	    asock->last_err = status;
+	}
+
 	if (status==PJ_SUCCESS && asock->cb.on_accept_complete) {
 	    pj_bool_t ret;
 
diff --git a/pjlib/src/pj/config.c b/pjlib/src/pj/config.c
index 0596b58..e0e43de 100644
--- a/pjlib/src/pj/config.c
+++ b/pjlib/src/pj/config.c
@@ -1,4 +1,4 @@
-/* $Id: config.c 3308 2010-09-08 17:45:27Z ismangil $ */
+/* $Id: config.c 3353 2010-10-21 03:03:42Z bennylp $ */
 /* 
  * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
  * Copyright (C) 2003-2008 Benny Prijono <benny at prijono.org>
@@ -22,7 +22,7 @@
 #include <pj/ioqueue.h>
 
 static const char *id = "config.c";
-PJ_DEF_DATA(const char*) PJ_VERSION = "1.8";
+PJ_DEF_DATA(const char*) PJ_VERSION = "1.8.5";
 
 /*
  * Get PJLIB version string.
diff --git a/pjlib/src/pj/os_core_unix.c b/pjlib/src/pj/os_core_unix.c
index 709ae5d..694b43c 100644
--- a/pjlib/src/pj/os_core_unix.c
+++ b/pjlib/src/pj/os_core_unix.c
@@ -1,4 +1,4 @@
-/* $Id: os_core_unix.c 3180 2010-05-19 05:50:08Z bennylp $ */
+/* $Id: os_core_unix.c 3320 2010-09-24 07:49:32Z bennylp $ */
 /* 
  * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
  * Copyright (C) 2003-2008 Benny Prijono <benny at prijono.org>
@@ -213,6 +213,9 @@ PJ_DEF(void) pj_shutdown()
 	pj_thread_local_free(thread_tls_id);
 	thread_tls_id = -1;
     }
+
+    /* Ticket #1132: Assertion when (re)starting PJLIB on different thread */
+    pj_bzero(&main_thread, sizeof(main_thread));
 #endif
 
     /* Clear static variables */
@@ -311,7 +314,7 @@ PJ_DEF(int) pj_thread_get_prio_min(pj_thread_t *thread)
 #if defined _POSIX_PRIORITY_SCHEDULING
     return sched_get_priority_min(policy);
 #elif defined __OpenBSD__
-    /* OpenBSD doesn't have sched_get_priority_min/_max */
+    /* Thread prio min/max are declared in OpenBSD private hdr */
     return 0;
 #else
     pj_assert("pj_thread_get_prio_min() not supported!");
@@ -336,8 +339,8 @@ PJ_DEF(int) pj_thread_get_prio_max(pj_thread_t *thread)
 #if defined _POSIX_PRIORITY_SCHEDULING
     return sched_get_priority_max(policy);
 #elif defined __OpenBSD__
-    /* OpenBSD doesn't have sched_get_priority_min/_max */
-    return 0;
+    /* Thread prio min/max are declared in OpenBSD private hdr */
+    return 31;
 #else
     pj_assert("pj_thread_get_prio_max() not supported!");
     return 0;
diff --git a/pjlib/src/pj/os_core_win32.c b/pjlib/src/pj/os_core_win32.c
index 51af335..387d79c 100644
--- a/pjlib/src/pj/os_core_win32.c
+++ b/pjlib/src/pj/os_core_win32.c
@@ -1,4 +1,4 @@
-/* $Id: os_core_win32.c 3023 2009-11-23 15:04:18Z bennylp $ */
+/* $Id: os_core_win32.c 3314 2010-09-22 07:45:26Z bennylp $ */
 /* 
  * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
  * Copyright (C) 2003-2008 Benny Prijono <benny at prijono.org>
@@ -246,6 +246,9 @@ PJ_DEF(void) pj_shutdown()
     /* Clear static variables */
     pj_errno_clear_handlers();
 
+    /* Ticket #1132: Assertion when (re)starting PJLIB on different thread */
+    pj_bzero(main_thread, sizeof(main_thread));
+
     /* Shutdown Winsock */
     WSACleanup();
 }
diff --git a/pjmedia/build/Makefile b/pjmedia/build/Makefile
index 4df6367..b0e2014 100644
--- a/pjmedia/build/Makefile
+++ b/pjmedia/build/Makefile
@@ -123,7 +123,7 @@ all: $(TARGETS)
 
 doc:
 	cd .. && rm -rf docs/html docs/latex && doxygen docs/doxygen.cfg
-	@if test ! "$(WWWDIR)" == ""; then \
+	@if [ -n "$(WWWDIR)" ]; then \
 		echo "Copying to $(WWWDIR)/pjmedia/docs/html.." ; \
 		rm -rf $(WWWDIR)/pjmedia/docs/html/* ; \
 		cp -a ../docs/html/* $(WWWDIR)/pjmedia/docs/html/ ; \
diff --git a/pjmedia/docs/doxygen.cfg b/pjmedia/docs/doxygen.cfg
index 28d4d5e..ecd5f27 100644
--- a/pjmedia/docs/doxygen.cfg
+++ b/pjmedia/docs/doxygen.cfg
@@ -853,7 +853,8 @@ PREDEFINED             = PJ_DECL(x)=x PJ_DEF(x)=x PJ_IDECL(x)=x \
 			 PJ_HAS_SEMAPHORE=1 \
 			 PJ_HAS_EVENT_OBJ=1 \
 			 PJ_HAS_TCP=1 \
-			 PJMEDIA_HAS_SRTP=1
+			 PJMEDIA_HAS_SRTP=1 \
+			 PJMEDIA_STREAM_ENABLE_KA=1
 
 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
 # this tag can be used to specify a list of macro names that should be expanded. 
diff --git a/pjmedia/include/pjmedia-audiodev/audiodev.h b/pjmedia/include/pjmedia-audiodev/audiodev.h
index d0bf79d..8419fd0 100644
--- a/pjmedia/include/pjmedia-audiodev/audiodev.h
+++ b/pjmedia/include/pjmedia-audiodev/audiodev.h
@@ -1,4 +1,4 @@
-/* $Id: audiodev.h 3174 2010-05-17 12:51:06Z ming $ */
+/* $Id: audiodev.h 3327 2010-09-30 04:23:27Z bennylp $ */
 /* 
  * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
  * Copyright (C) 2003-2008 Benny Prijono <benny at prijono.org>
@@ -455,7 +455,7 @@ PJ_DECL(const char*) pjmedia_aud_dev_cap_name(pjmedia_aud_dev_cap cap,
  *
  * @param param		The structure.
  * @param cap		The audio capability which value is to be set.
- * @param value		Pointer to value. Please see the type of value to
+ * @param pval		Pointer to value. Please see the type of value to
  *			be supplied in the pjmedia_aud_dev_cap documentation.
  *
  * @return		PJ_SUCCESS on successful operation or the appropriate
@@ -473,7 +473,7 @@ PJ_DECL(pj_status_t) pjmedia_aud_param_set_cap(pjmedia_aud_param *param,
  *
  * @param param		The structure.
  * @param cap		The audio capability which value is to be retrieved.
- * @param value		Pointer to value. Please see the type of value to
+ * @param pval		Pointer to value. Please see the type of value to
  *			be supplied in the pjmedia_aud_dev_cap documentation.
  *
  * @return		PJ_SUCCESS on successful operation or the appropriate
diff --git a/pjmedia/include/pjmedia-codec/amr_helper.h b/pjmedia/include/pjmedia-codec/amr_helper.h
index 217de0b..a706354 100644
--- a/pjmedia/include/pjmedia-codec/amr_helper.h
+++ b/pjmedia/include/pjmedia-codec/amr_helper.h
@@ -1,4 +1,4 @@
-/* $Id: amr_helper.h 2875 2009-08-13 15:57:26Z bennylp $ */
+/* $Id: amr_helper.h 3327 2010-09-30 04:23:27Z bennylp $ */
 /* 
  * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
  * Copyright (C) 2003-2008 Benny Prijono <benny at prijono.org>
@@ -597,7 +597,7 @@ const pj_uint16_t pjmedia_codec_amrwb_bitrates[9] =
 
 
 /**
- * This structure describes AMR frame info, to be fitted into @pjmedia_frame 
+ * This structure describes AMR frame info, to be fitted into #pjmedia_frame
  * bit info.
  */
 #pragma pack(1)
@@ -712,9 +712,8 @@ PJ_INLINE(pj_int8_t) pjmedia_codec_amr_get_mode2(pj_bool_t amrnb,
  *   'setting' by setting/resetting field 'reorder'.
  * - align left the start bit (make the start_bit to be 0).
  *
- * @param amr_nb    Set PJ_TRUE for AMR-NB and PJ_FALSE for AMR-WB.
  * @param in	    Input frame.
- * @param setting   Settings, see @pjmedia_codec_amr_pack_setting.
+ * @param setting   Settings, see #pjmedia_codec_amr_pack_setting.
  * @param out	    Output frame.
  *
  * @return	    PJ_SUCCESS on success.
@@ -852,7 +851,7 @@ PJ_INLINE(pj_status_t) pjmedia_codec_amr_predecode(
  *
  * @param frames    AMR frames to be packed.
  * @param nframes   Number of frames to be packed.
- * @param setting   Settings, see @pjmedia_codec_amr_pack_setting.
+ * @param setting   Settings, see #pjmedia_codec_amr_pack_setting.
  * @param pkt	    Payload.
  * @param pkt_size  Payload size, as input this specifies payload maximum size,
  *		    as output this specifies payload packed size.
@@ -1069,7 +1068,7 @@ PJ_INLINE (pj_status_t) pjmedia_codec_amr_pack(
  * @param pkt	    Payload.
  * @param pkt_size  Payload size.
  * @param ts	    Base timestamp.
- * @param setting   Settings, see @pjmedia_codec_amr_pack_setting.
+ * @param setting   Settings, see #pjmedia_codec_amr_pack_setting.
  * @param frames    Frames parsed.
  * @param nframes   Number of frames parsed.
  * @param cmr	    Change Mode Request message for local encoder.
diff --git a/pjmedia/include/pjmedia-codec/types.h b/pjmedia/include/pjmedia-codec/types.h
index c5e01f4..e47249c 100644
--- a/pjmedia/include/pjmedia-codec/types.h
+++ b/pjmedia/include/pjmedia-codec/types.h
@@ -1,4 +1,4 @@
-/* $Id: types.h 3146 2010-04-26 13:57:28Z nanang $ */
+/* $Id: types.h 3345 2010-10-14 08:30:57Z bennylp $ */
 /* 
  * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
  * Copyright (C) 2003-2008 Benny Prijono <benny at prijono.org>
@@ -43,13 +43,20 @@
  */
 enum
 {
-    /* PJMEDIA_RTP_PT_TELEPHONE_EVENTS is declared in
-     * <pjmedia/config.h>
+    /* According to IANA specifications, dynamic payload types are to be in
+     * the range 96-127 (inclusive). This enum is structured to place the
+     * values of the payload types specified below into that range.
+     *
+     * PJMEDIA_RTP_PT_DYNAMIC is defined in <pjmedia/codec.h>. It is defined
+     * to be 96.
+     *
+     * PJMEDIA_RTP_PT_TELEPHONE_EVENTS is defined in <pjmedia/config.h>.
+     * The default value is 96.
      */
 #if PJMEDIA_RTP_PT_TELEPHONE_EVENTS
     PJMEDIA_RTP_PT_START = PJMEDIA_RTP_PT_TELEPHONE_EVENTS,
 #else
-    PJMEDIA_RTP_PT_START = 102,
+    PJMEDIA_RTP_PT_START = (PJMEDIA_RTP_PT_DYNAMIC-1),
 #endif
 
     PJMEDIA_RTP_PT_SPEEX_NB,			/**< Speex narrowband/8KHz  */
@@ -83,6 +90,10 @@ enum
     PJMEDIA_RTP_PT_G7221C_48,			/**< G722.1 Annex C (48Kbps)*/
     PJMEDIA_RTP_PT_G7221_RSV1,			/**< G722.1 reserve	    */
     PJMEDIA_RTP_PT_G7221_RSV2,			/**< G722.1 reserve	    */
+
+    /* Caution!
+     * Ensure the value of the last pt above is <= 127.
+     */
 };
 
 /**
diff --git a/pjmedia/include/pjmedia/conference.h b/pjmedia/include/pjmedia/conference.h
index 7f19e4b..63a08a1 100644
--- a/pjmedia/include/pjmedia/conference.h
+++ b/pjmedia/include/pjmedia/conference.h
@@ -1,4 +1,4 @@
-/* $Id: conference.h 2728 2009-06-01 13:56:09Z nanang $ */
+/* $Id: conference.h 3327 2010-09-30 04:23:27Z bennylp $ */
 /* 
  * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
  * Copyright (C) 2003-2008 Benny Prijono <benny at prijono.org>
@@ -239,7 +239,7 @@ PJ_DECL(pj_status_t) pjmedia_conf_add_port( pjmedia_conf *conf,
 
 /**
  * <i><b>Warning:</b> This API has been deprecated since 1.3 and will be
- * removed in the future release, use #PJMEDIA_SPLITCOMB instead.</i>
+ * removed in the future release, use @ref PJMEDIA_SPLITCOMB instead.</i>
  *
  * Create and add a passive media port to the conference bridge. Unlike
  * "normal" media port that is added with #pjmedia_conf_add_port(), media
diff --git a/pjmedia/include/pjmedia/config.h b/pjmedia/include/pjmedia/config.h
index 7f3feb6..461413d 100644
--- a/pjmedia/include/pjmedia/config.h
+++ b/pjmedia/include/pjmedia/config.h
@@ -1,4 +1,4 @@
-/* $Id: config.h 3239 2010-07-15 14:45:47Z nanang $ */
+/* $Id: config.h 3345 2010-10-14 08:30:57Z bennylp $ */
 /* 
  * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
  * Copyright (C) 2003-2008 Benny Prijono <benny at prijono.org>
@@ -623,7 +623,7 @@
  * PJMEDIA_RTP_PT_TELEPHONE_EVENTS_STR too.
  */
 #ifndef PJMEDIA_RTP_PT_TELEPHONE_EVENTS
-#   define PJMEDIA_RTP_PT_TELEPHONE_EVENTS	    101
+#   define PJMEDIA_RTP_PT_TELEPHONE_EVENTS	    96
 #endif
 
 
@@ -632,7 +632,7 @@
  * payload type.
  */
 #ifndef PJMEDIA_RTP_PT_TELEPHONE_EVENTS_STR
-#   define PJMEDIA_RTP_PT_TELEPHONE_EVENTS_STR	    "101"
+#   define PJMEDIA_RTP_PT_TELEPHONE_EVENTS_STR	    "96"
 #endif
 
 
diff --git a/pjmedia/include/pjmedia/delaybuf.h b/pjmedia/include/pjmedia/delaybuf.h
index 1fe4aba..700bc16 100644
--- a/pjmedia/include/pjmedia/delaybuf.h
+++ b/pjmedia/include/pjmedia/delaybuf.h
@@ -1,4 +1,4 @@
-/* $Id: delaybuf.h 2394 2008-12-23 17:27:53Z bennylp $ */
+/* $Id: delaybuf.h 3327 2010-09-30 04:23:27Z bennylp $ */
 /* 
  * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
  * Copyright (C) 2003-2008 Benny Prijono <benny at prijono.org>
@@ -79,7 +79,7 @@ typedef struct pjmedia_delay_buf pjmedia_delay_buf;
  *			    in ms, if this value is negative or less than 
  *			    one frame time, default maximum delay used is
  *			    400 ms.
- * @param option	    Option flags, must be zero for now.
+ * @param options	    Option flags, must be zero for now.
  * @param p_b		    Pointer to receive the delay buffer instance.
  *
  * @return		    PJ_SUCCESS if the delay buffer has been
diff --git a/pjmedia/include/pjmedia/doxygen.h b/pjmedia/include/pjmedia/doxygen.h
index 66704aa..34cdf34 100644
--- a/pjmedia/include/pjmedia/doxygen.h
+++ b/pjmedia/include/pjmedia/doxygen.h
@@ -1,4 +1,4 @@
-/* $Id: doxygen.h 2394 2008-12-23 17:27:53Z bennylp $ */
+/* $Id: doxygen.h 3327 2010-09-30 04:23:27Z bennylp $ */
 /* 
... 18489 lines suppressed ...


-- 
asterisk-scf/release/pjproject.git



More information about the asterisk-scf-commits mailing list