[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(¶m->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