summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2005-11-20 19:58:10 +0000
committerBenny Prijono <bennylp@teluu.com>2005-11-20 19:58:10 +0000
commit9f4da35e676737f830a90a18de08440cf0f6cdf9 (patch)
tree5485d610d1c65f3d0be067794c81ba02c33a1bd4
parent37e8cb76f7b1f6e5dada1f8a06be4b963ee71be3 (diff)
More compliant URI parser, comparison, etc.
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@64 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjsip/build/pjsip.dsw30
-rw-r--r--pjsip/build/pjsip_core.dsp14
-rw-r--r--pjsip/build/test_pjsip.dsp12
-rw-r--r--pjsip/docs/PJSIP-Testing.docbin330240 -> 332288 bytes
-rw-r--r--pjsip/include/pjsip/print_util.h41
-rw-r--r--pjsip/include/pjsip/sip_errno.h157
-rw-r--r--pjsip/include/pjsip/sip_event.h2
-rw-r--r--pjsip/include/pjsip/sip_parser.h28
-rw-r--r--pjsip/include/pjsip/sip_transaction.h17
-rw-r--r--pjsip/include/pjsip/sip_uri.h67
-rw-r--r--pjsip/include/pjsip/sip_util.h (renamed from pjsip/include/pjsip/sip_misc.h)0
-rw-r--r--pjsip/include/pjsip_core.h5
-rw-r--r--pjsip/src/pjsip-simple/event_notify.c2
-rw-r--r--pjsip/src/pjsip-simple/messaging.c2
-rw-r--r--pjsip/src/pjsip-ua/sip_dialog.c2
-rw-r--r--pjsip/src/pjsip-ua/sip_reg.c2
-rw-r--r--pjsip/src/pjsip-ua/sip_ua.c2
-rw-r--r--pjsip/src/pjsip/sip_endpoint.c59
-rw-r--r--pjsip/src/pjsip/sip_errno.c125
-rw-r--r--pjsip/src/pjsip/sip_parser.c82
-rw-r--r--pjsip/src/pjsip/sip_transaction.c8
-rw-r--r--pjsip/src/pjsip/sip_transport.c2
-rw-r--r--pjsip/src/pjsip/sip_uri.c289
-rw-r--r--pjsip/src/pjsip/sip_util.c (renamed from pjsip/src/pjsip/sip_misc.c)2
-rw-r--r--pjsip/src/test-pjsip/main.c6
-rw-r--r--pjsip/src/test-pjsip/msg.c (renamed from pjsip/src/test-pjsip/parse_msg.c)117
-rw-r--r--pjsip/src/test-pjsip/test.c47
-rw-r--r--pjsip/src/test-pjsip/test.h9
-rw-r--r--pjsip/src/test-pjsip/uri.c (renamed from pjsip/src/test-pjsip/parse_uri.c)162
29 files changed, 857 insertions, 434 deletions
diff --git a/pjsip/build/pjsip.dsw b/pjsip/build/pjsip.dsw
index 562d33eb..5e6dfe03 100644
--- a/pjsip/build/pjsip.dsw
+++ b/pjsip/build/pjsip.dsw
@@ -57,18 +57,6 @@ Package=<4>
###############################################################################
-Project: "test_pjsip"=.\test_pjsip.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
Project: "pjsip_ua"=.\pjsip_ua.dsp - Package Owner=<4>
Package=<5>
@@ -108,6 +96,24 @@ Package=<4>
###############################################################################
+Project: "test_pjsip"=.\test_pjsip.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name pjlib
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjsip_core
+ End Project Dependency
+}}}
+
+###############################################################################
+
Global:
Package=<5>
diff --git a/pjsip/build/pjsip_core.dsp b/pjsip/build/pjsip_core.dsp
index cacb9b5d..11de7fd3 100644
--- a/pjsip/build/pjsip_core.dsp
+++ b/pjsip/build/pjsip_core.dsp
@@ -103,7 +103,7 @@ SOURCE=..\src\pjsip\sip_endpoint.c
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_misc.c
+SOURCE=..\src\pjsip\sip_errno.c
# End Source File
# Begin Source File
@@ -133,6 +133,10 @@ SOURCE=..\src\pjsip\sip_transport_udp.c
SOURCE=..\src\pjsip\sip_uri.c
# End Source File
+# Begin Source File
+
+SOURCE=..\src\pjsip\sip_util.c
+# End Source File
# End Group
# Begin Group "Header Files"
@@ -175,10 +179,6 @@ SOURCE=..\include\pjsip\sip_event.h
# End Source File
# Begin Source File
-SOURCE=..\include\pjsip\sip_misc.h
-# End Source File
-# Begin Source File
-
SOURCE=..\include\pjsip\sip_module.h
# End Source File
# Begin Source File
@@ -217,6 +217,10 @@ SOURCE=..\include\pjsip\sip_types.h
SOURCE=..\include\pjsip\sip_uri.h
# End Source File
+# Begin Source File
+
+SOURCE=..\include\pjsip\sip_util.h
+# End Source File
# End Group
# Begin Group "Inline Files"
diff --git a/pjsip/build/test_pjsip.dsp b/pjsip/build/test_pjsip.dsp
index c01f737b..2d58318d 100644
--- a/pjsip/build/test_pjsip.dsp
+++ b/pjsip/build/test_pjsip.dsp
@@ -51,7 +51,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 wsock32.lib kernel32.lib netapi32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /profile /map /debug /machine:I386 /out:"..\bin\test-pjsip-i386-win32-vc6-release.exe"
+# ADD LINK32 dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib kernel32.lib netapi32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /profile /map /debug /machine:I386 /out:"..\bin\test-pjsip-i386-win32-vc6-release.exe"
!ELSEIF "$(CFG)" == "test_pjsip - Win32 Debug"
@@ -76,7 +76,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 wsock32.lib kernel32.lib netapi32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\test-pjsip-i386-win32-vc6-debug.exe" /pdbtype:sept
+# ADD LINK32 dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib kernel32.lib netapi32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\test-pjsip-i386-win32-vc6-debug.exe" /pdbtype:sept
!ENDIF
@@ -93,11 +93,15 @@ SOURCE="..\src\test-pjsip\main.c"
# End Source File
# Begin Source File
-SOURCE="..\src\test-pjsip\test_msg.c"
+SOURCE="..\src\test-pjsip\msg.c"
# End Source File
# Begin Source File
-SOURCE="..\src\test-pjsip\test_uri.c"
+SOURCE="..\src\test-pjsip\test.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\test-pjsip\uri.c"
# End Source File
# End Group
# Begin Group "Header Files"
diff --git a/pjsip/docs/PJSIP-Testing.doc b/pjsip/docs/PJSIP-Testing.doc
index 59822a9f..26d98a35 100644
--- a/pjsip/docs/PJSIP-Testing.doc
+++ b/pjsip/docs/PJSIP-Testing.doc
Binary files differ
diff --git a/pjsip/include/pjsip/print_util.h b/pjsip/include/pjsip/print_util.h
index 340984ce..56f05851 100644
--- a/pjsip/include/pjsip/print_util.h
+++ b/pjsip/include/pjsip/print_util.h
@@ -19,9 +19,12 @@
#ifndef __PJSIP_PRINT_H__
#define __PJSIP_PRINT_H__
+/* Minimum space left in the buffer */
+#define MIN_SPACE 10
+
#define copy_advance_check(buf,str) \
do { \
- if ((str).slen+10 >= (endbuf-buf)) return -1; \
+ if ((str).slen+MIN_SPACE >= (endbuf-buf)) return -1; \
pj_memcpy(buf, (str).ptr, (str).slen); \
buf += (str).slen; \
} while (0)
@@ -31,7 +34,7 @@ static char *imp_copy_advance_pair(char *buf, char *endbuf, const char *str1, in
{
if (str2->slen) {
int printed = len1+str2->slen;
- if (printed+10 >= (endbuf-buf)) return NULL;
+ if (printed+MIN_SPACE >= (endbuf-buf)) return NULL;
pj_memcpy(buf,str1,len1);
pj_memcpy(buf+len1, str2->ptr, str2->slen);
return buf + printed;
@@ -44,7 +47,7 @@ static char *imp_copy_advance_pair(char *buf, char *endbuf, const char *str1, in
do { \
if (str2.slen) { \
printed = len1+str2.slen; \
- if (printed+10 >= (endbuf-buf)) return -1; \
+ if (printed+MIN_SPACE >= (endbuf-buf)) return -1; \
pj_memcpy(buf,str1,len1); \
pj_memcpy(buf+len1, str2.ptr, str2.slen); \
buf += printed; \
@@ -62,7 +65,7 @@ static char *imp_copy_advance_pair(char *buf, char *endbuf, const char *str1, in
do { \
if (str2.slen) { \
printed = len1+str2.slen+2; \
- if (printed+10 >= (endbuf-buf)) return -1; \
+ if (printed+MIN_SPACE >= (endbuf-buf)) return -1; \
pj_memcpy(buf,str1,len1); \
*(buf+len1)=quotebegin; \
pj_memcpy(buf+len1+1, str2.ptr, str2.slen); \
@@ -71,9 +74,35 @@ static char *imp_copy_advance_pair(char *buf, char *endbuf, const char *str1, in
} \
} while (0)
+#define copy_advance_pair_escape(buf,str1,len1,str2,unres) \
+ do { \
+ if (str2.slen) { \
+ pj_ssize_t esc_len; \
+ if (len1+str2.slen+MIN_SPACE >= (endbuf-buf)) return -1; \
+ pj_memcpy(buf,str1,len1); \
+ buf += len1; \
+ esc_len=pj_strncpy2_escape(buf, &str2, (endbuf-buf), &unres); \
+ if (esc_len < 0) return -1; \
+ buf += esc_len; \
+ if (endbuf-buf < MIN_SPACE) return -1; \
+ } \
+ } while (0)
+
+
#define copy_advance_no_check(buf,str) \
- pj_memcpy(buf, (str).ptr, (str).slen); \
- buf += (str).slen;
+ do { \
+ pj_memcpy(buf, (str).ptr, (str).slen); \
+ buf += (str).slen; \
+ } while (0)
+
+#define copy_advance_escape(buf,str,unres) \
+ do { \
+ pj_ssize_t len = \
+ pj_strncpy2_escape(buf, &(str), (endbuf-buf), &(unres)); \
+ if (len < 0) return -1; \
+ buf += len; \
+ if (endbuf-buf < MIN_SPACE) return -1; \
+ } while (0)
#define copy_advance_pair_no_check(buf,str1,len1,str2) \
if (str2.slen) { \
diff --git a/pjsip/include/pjsip/sip_errno.h b/pjsip/include/pjsip/sip_errno.h
index 5473f362..2c8e6764 100644
--- a/pjsip/include/pjsip/sip_errno.h
+++ b/pjsip/include/pjsip/sip_errno.h
@@ -21,10 +21,31 @@
#include <pj/errno.h>
+PJ_BEGIN_DECL
+
+/*
+ * PJSIP error codes occupies 170000 - 219000, and mapped as follows:
+ * - 170100 - 170799: mapped to SIP status code in response msg.
+ * - 171000 - 171999: mapped to errors generated from PJSIP core.
+ */
+
+/**
+ * Get error message for the specified error code.
+ *
+ * @param status The error code.
+ * @param buffer The buffer where to put the error message.
+ * @param bufsize Size of the buffer.
+ *
+ * @return The error message as NULL terminated string,
+ * wrapped with pj_str_t.
+ */
+PJ_DECL(pj_str_t) pjsip_strerror( pj_status_t status, char *buffer,
+ pj_size_t bufsize);
+
/**
* Start of error code relative to PJ_ERRNO_START_USER.
*/
-#define PJSIP_ERRNO_START (PJ_ERRNO_START_USER+10000)
+#define PJSIP_ERRNO_START (PJ_ERRNO_START_USER)
/**
* Create error value from SIP status code.
@@ -43,81 +64,165 @@
*/
#define PJSIP_ERRNO_TO_SIP_STATUS(status) \
((status>=PJSIP_ERRNO_FROM_SIP_STATUS(100) && \
- status<PJSIP_ERRNO_FROM_SIP_STATUS(999)) ? \
+ status<PJSIP_ERRNO_FROM_SIP_STATUS(800)) ? \
status-PJSIP_ERRNO_FROM_SIP_STATUS(0) : 599)
/**
* Start of PJSIP generated error code values.
*/
-#define PJSIP_ERRNO_START_PJSIP (PJSIP_ERRNO_START + 10000)
+#define PJSIP_ERRNO_START_PJSIP (PJSIP_ERRNO_START + 1000)
+
+/************************************************************
+ * GENERIC SIP ERRORS
+ ***********************************************************/
+/**
+ * @hideinitializer
+ * SIP object is busy.
+ */
+#define PJSIP_EBUSY (PJSIP_ERRNO_START_PJSIP + 1) /* 171001 */
+/**
+ * @hideinitializer
+ * SIP object with the same type already exists.
+ */
+#define PJSIP_ETYPEEXISTS (PJSIP_ERRNO_START_PJSIP + 2) /* 171002 */
+
+/************************************************************
+ * MESSAGING ERRORS
+ ***********************************************************/
/**
* @hideinitializer
* Invalid message (syntax error)
*/
-#define PJSIP_EINVALIDMSG (PJSIP_ERRNO_START_PJSIP + 0)
+#define PJSIP_EINVALIDMSG (PJSIP_ERRNO_START_PJSIP + 20) /* 171020 */
+/**
+ * @hideinitializer
+ * Unsupported URL scheme.
+ */
+#define PJSIP_EINVALIDSCHEME (PJSIP_ERRNO_START_PJSIP + 21) /* 171021 */
+/**
+ * @hideinitializer
+ * Message too long. See also PJSIP_ERXOVERFLOW.
+ */
+#define PJSIP_EMSGTOOLONG (PJSIP_ERRNO_START_PJSIP + 22) /* 171022 */
+/**
+ * @hideinitializer
+ * Message not completely received.
+ */
+#define PJSIP_EPARTIALMSG (PJSIP_ERRNO_START_PJSIP + 23) /* 171023 */
/**
* @hideinitializer
* Missing required header(s).
*/
-#define PJSIP_EMISSINGHDR (PJSIP_ERRNO_START_PJSIP + 1)
+#define PJSIP_EMISSINGHDR (PJSIP_ERRNO_START_PJSIP + 24) /* 171024 */
/**
* @hideinitializer
- * Unsupported URL scheme.
+ * Invalid Via header in response (sent-by, etc).
+ */
+#define PJSIP_EINVALIDVIA (PJSIP_ERRNO_START_PJSIP + 25) /* 171025 */
+/**
+ * @hideinitializer
+ * Multiple Via headers in response.
*/
-#define PJSIP_EINVALIDSCHEME (PJSIP_ERRNO_START_PJSIP + 2)
+#define PJSIP_EMULTIPLEVIA (PJSIP_ERRNO_START_PJSIP + 26) /* 171026 */
+
+/************************************************************
+ * TRANSPORT ERRORS
+ ***********************************************************/
+/**
+ * @hideinitializer
+ * Unsupported transport type.
+ */
+#define PJSIP_EUNSUPTRANSPORT (PJSIP_ERRNO_START_PJSIP + 40) /* 171040 */
+/**
+ * @hideinitializer
+ * Buffer is being sent, operation still pending.
+ */
+#define PJSIP_EPENDINGTX (PJSIP_ERRNO_START_PJSIP + 41) /* 171041 */
+/**
+ * @hideinitializer
+ * Rx buffer overflow. See also PJSIP_EMSGTOOLONG.
+ */
+#define PJSIP_ERXOVERFLOW (PJSIP_ERRNO_START_PJSIP + 42)/* 171042 */
+
+
+/************************************************************
+ * TRANSACTION ERRORS
+ ***********************************************************/
/**
* @hideinitializer
* Transaction has just been destroyed.
*/
-#define PJSIP_ETSXDESTROYED (PJSIP_ERRNO_START_PJSIP + 3)
+#define PJSIP_ETSXDESTROYED (PJSIP_ERRNO_START_PJSIP + 60) /* 171060 */
+
+
+/************************************************************
+ * URI COMPARISON RESULTS
+ ***********************************************************/
+/**
+ * @hideinitializer
+ * Scheme mismatch.
+ */
+#define PJSIP_ECMPSCHEME (PJSIP_ERRNO_START_PJSIP + 80) /* 171080 */
/**
* @hideinitializer
- * Buffer overflow. See also PJSIP_EMSGTOOLONG.
+ * User part mismatch.
*/
-#define PJSIP_EOVERFLOW (PJSIP_ERRNO_START_PJSIP + 4)
+#define PJSIP_ECMPUSER (PJSIP_ERRNO_START_PJSIP + 81) /* 171081 */
/**
* @hideinitializer
- * Message not completely received.
+ * Password part mismatch.
*/
-#define PJSIP_EPARTIALMSG (PJSIP_ERRNO_START_PJSIP + 5)
+#define PJSIP_ECMPPASSWD (PJSIP_ERRNO_START_PJSIP + 82) /* 171082 */
/**
* @hideinitializer
- * Message too long. See also PJSIP_EOVERFLOW.
+ * Host part mismatch.
*/
-#define PJSIP_EMSGTOOLONG (PJSIP_ERRNO_START_PJSIP + 6)
+#define PJSIP_ECMPHOST (PJSIP_ERRNO_START_PJSIP + 83) /* 171083 */
/**
* @hideinitializer
- * Buffer is being sent, operation still pending.
+ * Port part mismatch.
*/
-#define PJSIP_EPENDINGTX (PJSIP_ERRNO_START_PJSIP + 7)
+#define PJSIP_ECMPPORT (PJSIP_ERRNO_START_PJSIP + 84) /* 171084 */
/**
* @hideinitializer
- * Unsupported transport type.
+ * Transport parameter part mismatch.
*/
-#define PJSIP_EUNSUPTRANSPORT (PJSIP_ERRNO_START_PJSIP + 8)
+#define PJSIP_ECMPTRANSPORTPRM (PJSIP_ERRNO_START_PJSIP + 85) /* 171085 */
/**
* @hideinitializer
- * Invalid Via header in response (sent-by, etc).
+ * TTL parameter part mismatch.
*/
-#define PJSIP_EINVALIDVIA (PJSIP_ERRNO_START_PJSIP + 9)
+#define PJSIP_ECMPTTLPARAM (PJSIP_ERRNO_START_PJSIP + 86) /* 171086 */
/**
* @hideinitializer
- * Multiple Via headers in response.
+ * User parameter part mismatch.
*/
-#define PJSIP_EMULTIPLEVIA (PJSIP_ERRNO_START_PJSIP + 9)
+#define PJSIP_ECMPUSERPARAM (PJSIP_ERRNO_START_PJSIP + 87) /* 171087 */
/**
* @hideinitializer
- * SIP object is busy.
+ * Method parameter part mismatch.
*/
-#define PJSIP_EBUSY (PJSIP_ERRNO_START_PJSIP + 10)
+#define PJSIP_ECMPMETHODPARAM (PJSIP_ERRNO_START_PJSIP + 88) /* 171088 */
/**
* @hideinitializer
- * SIP object with the same type already exists.
+ * Maddr parameter part mismatch.
+ */
+#define PJSIP_ECMPMADDRPARAM (PJSIP_ERRNO_START_PJSIP + 89) /* 171089 */
+/**
+ * @hideinitializer
+ * Parameter part in other_param mismatch.
*/
-#define PJSIP_ETYPEEXISTS (PJSIP_ERRNO_START_PJSIP + 11)
+#define PJSIP_ECMPOTHERPARAM (PJSIP_ERRNO_START_PJSIP + 90) /* 171090 */
+/**
+ * @hideinitializer
+ * Parameter part in header_param mismatch.
+ */
+#define PJSIP_ECMPHEADERPARAM (PJSIP_ERRNO_START_PJSIP + 91) /* 171091 */
+
+PJ_END_DECL
#endif /* __PJSIP_SIP_ERRNO_H__ */
diff --git a/pjsip/include/pjsip/sip_event.h b/pjsip/include/pjsip/sip_event.h
index 595f5445..e828ae96 100644
--- a/pjsip/include/pjsip/sip_event.h
+++ b/pjsip/include/pjsip/sip_event.h
@@ -297,7 +297,7 @@ struct pjsip_event
/**
* Get the event string from the event ID.
* @param e the event ID.
- * @notes defined in sip_misc.c
+ * @notes defined in sip_util.c
*/
PJ_DEF(const char *) pjsip_event_str(pjsip_event_id_e e);
diff --git a/pjsip/include/pjsip/sip_parser.h b/pjsip/include/pjsip/sip_parser.h
index 3cc690a6..6c30e837 100644
--- a/pjsip/include/pjsip/sip_parser.h
+++ b/pjsip/include/pjsip/sip_parser.h
@@ -294,19 +294,21 @@ PJ_DECL(pj_status_t) pjsip_parse_headers( pj_pool_t *pool,
* Various specification used in parsing, exported here as extern for other
* parsers.
*/
-extern
-pj_cis_t pjsip_HOST_SPEC, /* For scanning host part. */
- pjsip_DIGIT_SPEC, /* Decimal digits */
- pjsip_ALPHA_SPEC, /* Alpha (A-Z, a-z) */
- pjsip_ALNUM_SPEC, /* Decimal + Alpha. */
- pjsip_TOKEN_SPEC, /* Token. */
- pjsip_HEX_SPEC, /* Hexadecimal digits. */
- pjsip_PARAM_CHAR_SPEC, /* For scanning pname (or pvalue when it's not quoted.) */
- pjsip_PROBE_USER_HOST_SPEC, /* Hostname characters. */
- pjsip_PASSWD_SPEC, /* Password. */
- pjsip_USER_SPEC, /* User */
- pjsip_NEWLINE_OR_EOF_SPEC, /* For eating up header.*/
- pjsip_DISPLAY_SCAN_SPEC; /* Used when searching for display name in URL. */
+extern pj_cis_t
+ pjsip_HOST_SPEC, /**< For scanning host part. */
+ pjsip_DIGIT_SPEC, /**< Decimal digits */
+ pjsip_ALPHA_SPEC, /**< Alpha (A-Z, a-z) */
+ pjsip_ALNUM_SPEC, /**< Decimal + Alpha. */
+ pjsip_TOKEN_SPEC, /**< Token. */
+ pjsip_HEX_SPEC, /**< Hexadecimal digits. */
+ pjsip_PARAM_CHAR_SPEC, /**< For scanning pname (or pvalue when it's
+ not quoted.) */
+ pjsip_HDR_CHAR_SPEC, /**< Chars in hname/havalue in URL. */
+ pjsip_PROBE_USER_HOST_SPEC, /**< Hostname characters. */
+ pjsip_PASSWD_SPEC, /**< Password. */
+ pjsip_USER_SPEC, /**< User */
+ pjsip_NEWLINE_OR_EOF_SPEC, /**< For eating up header.*/
+ pjsip_DISPLAY_SCAN_SPEC; /**< Used when searching for display name. */
/*
* Various string constants.
diff --git a/pjsip/include/pjsip/sip_transaction.h b/pjsip/include/pjsip/sip_transaction.h
index 4090ca4c..e7edceef 100644
--- a/pjsip/include/pjsip/sip_transaction.h
+++ b/pjsip/include/pjsip/sip_transaction.h
@@ -129,6 +129,23 @@ struct pjsip_transaction
};
+/**
+ * Create new transaction. Application would normally use
+ * #pjsip_endpt_create_tsx rather than this function.
+ *
+ * @param pool Pool to use by the transaction.
+ * @param endpt Endpoint.
+ * @param p_tsx Pointer to return the transaction.
+ *
+ * @return PJ_SUCCESS or the appropriate error code.
+ *
+ * @see pjsip_endpt_create_tsx
+ *
+ */
+PJ_DEF(pj_status_t) pjsip_tsx_create( pj_pool_t *pool,
+ pjsip_endpoint *endpt,
+ pjsip_transaction **p_tsx);
+
/**
* Init transaction as UAC from the specified transmit data (\c tdata).
* The transmit data must have a valid \c Request-Line and \c CSeq header.
diff --git a/pjsip/include/pjsip/sip_uri.h b/pjsip/include/pjsip/sip_uri.h
index f73207da..b72721f2 100644
--- a/pjsip/include/pjsip/sip_uri.h
+++ b/pjsip/include/pjsip/sip_uri.h
@@ -26,6 +26,7 @@
#include <pjsip/sip_types.h>
#include <pjsip/sip_config.h>
+#include <pj/list.h>
PJ_BEGIN_DECL
@@ -38,6 +39,53 @@ PJ_BEGIN_DECL
*/
/**
+ * Generic parameter, normally used in other_param or header_param.
+ */
+typedef struct pjsip_param
+{
+ PJ_DECL_LIST_MEMBER(struct pjsip_param); /**< Generic list member. */
+ pj_str_t name; /**< Param/header name. */
+ pj_str_t value; /**< Param/header value. */
+} pjsip_param;
+
+
+/**
+ * Find the specified parameter name in the list. The name will be compared
+ * in case-insensitive comparison.
+ *
+ * @param param_list List of parameters to find.
+ * @param name Parameter/header name to find.
+ *
+ * @return The parameter if found, or NULL.
+ */
+PJ_DECL(pjsip_param*) pjsip_param_find( pjsip_param *param_list,
+ const pj_str_t *name );
+
+
+/**
+ * Find the specified parameter name in the list. The name will be compared
+ * in case-insensitive comparison.
+ *
+ * @param param_list List of parameters to find.
+ * @param name Parameter/header name to find.
+ *
+ * @return The parameter if found, or NULL.
+ */
+PJ_DECL(const pjsip_param*) pjsip_param_cfind(const pjsip_param *param_list,
+ const pj_str_t *name );
+
+
+/**
+ * Duplicate the parameters.
+ *
+ * @param pool Pool to allocate memory from.
+ * @param dst_list Destination list.
+ * @param src_list Source list.
+ */
+PJ_DECL(void) pjsip_param_clone(pj_pool_t *pool, pjsip_param *dst_list,
+ const pjsip_param *src_list);
+
+/**
* URI context.
*/
typedef enum pjsip_uri_context_e
@@ -89,10 +137,11 @@ typedef struct pjsip_uri_vptr
* @param context the context.
* @param uri1 the first URI (self).
* @param uri2 the second URI.
- * @return zero if equal.
+ * @return PJ_SUCCESS if equal, or otherwise the error status which
+ * should point to the mismatch part.
*/
- int (*p_compare)(pjsip_uri_context_e context,
- const void *uri1, const void *uri2);
+ pj_status_t (*p_compare)(pjsip_uri_context_e context,
+ const void *uri1, const void *uri2);
/**
* Clone URI.
@@ -139,7 +188,6 @@ struct pjsip_uri
(pj_strnicmp2(pjsip_uri_get_scheme(url), "tel", 3)==0)
-
/**
* SIP and SIPS URL scheme.
*/
@@ -156,8 +204,8 @@ typedef struct pjsip_url
int ttl_param; /**< Optional TTL param, or -1. */
int lr_param; /**< Optional loose routing param, or zero */
pj_str_t maddr_param; /**< Optional maddr param */
- pj_str_t other_param; /**< Other parameters grouped together. */
- pj_str_t header_param; /**< Optional header parameter. */
+ pjsip_param other_param; /**< Other parameters grouped together. */
+ pjsip_param header_param; /**< Optional header parameter. */
} pjsip_url;
@@ -207,10 +255,11 @@ PJ_INLINE(void*) pjsip_uri_get_uri(void *uri)
* @param context Comparison context.
* @param uri1 The first URI.
* @param uri2 The second URI.
- * @return Zero if equal.
+ * @return PJ_SUCCESS if equal, or otherwise the error status which
+ * should point to the mismatch part.
*/
-PJ_INLINE(int) pjsip_uri_cmp(pjsip_uri_context_e context,
- const void *uri1, const void *uri2)
+PJ_INLINE(pj_status_t) pjsip_uri_cmp(pjsip_uri_context_e context,
+ const void *uri1, const void *uri2)
{
return (*((const pjsip_uri*)uri1)->vptr->p_compare)(context, uri1, uri2);
}
diff --git a/pjsip/include/pjsip/sip_misc.h b/pjsip/include/pjsip/sip_util.h
index f8685e54..f8685e54 100644
--- a/pjsip/include/pjsip/sip_misc.h
+++ b/pjsip/include/pjsip/sip_util.h
diff --git a/pjsip/include/pjsip_core.h b/pjsip/include/pjsip_core.h
index f2af3964..6edfda89 100644
--- a/pjsip/include/pjsip_core.h
+++ b/pjsip/include/pjsip_core.h
@@ -20,9 +20,10 @@
#define __PJSIP_CORE_H__
#include <pjsip/sip_types.h>
+#include <pjsip/sip_auth.h>
#include <pjsip/sip_endpoint.h>
+#include <pjsip/sip_errno.h>
#include <pjsip/sip_event.h>
-#include <pjsip/sip_misc.h>
#include <pjsip/sip_module.h>
#include <pjsip/sip_msg.h>
#include <pjsip/sip_parser.h>
@@ -30,7 +31,7 @@
#include <pjsip/sip_transaction.h>
#include <pjsip/sip_transport.h>
#include <pjsip/sip_uri.h>
-#include <pjsip/sip_auth.h>
+#include <pjsip/sip_util.h>
#endif /* __PJSIP_CORE_H__ */
diff --git a/pjsip/src/pjsip-simple/event_notify.c b/pjsip/src/pjsip-simple/event_notify.c
index 004a37df..4879f884 100644
--- a/pjsip/src/pjsip-simple/event_notify.c
+++ b/pjsip/src/pjsip-simple/event_notify.c
@@ -18,7 +18,7 @@
*/
#include <pjsip_simple/event_notify.h>
#include <pjsip/sip_msg.h>
-#include <pjsip/sip_misc.h>
+#include <pjsip/sip_util.h>
#include <pjsip/sip_endpoint.h>
#include <pjsip/sip_module.h>
#include <pjsip/sip_transaction.h>
diff --git a/pjsip/src/pjsip-simple/messaging.c b/pjsip/src/pjsip-simple/messaging.c
index 9668f42f..d43acc0c 100644
--- a/pjsip/src/pjsip-simple/messaging.c
+++ b/pjsip/src/pjsip-simple/messaging.c
@@ -22,7 +22,7 @@
#include <pjsip/sip_transaction.h>
#include <pjsip/sip_event.h>
#include <pjsip/sip_module.h>
-#include <pjsip/sip_misc.h>
+#include <pjsip/sip_util.h>
#include <pj/string.h>
#include <pj/pool.h>
#include <pj/guid.h>
diff --git a/pjsip/src/pjsip-ua/sip_dialog.c b/pjsip/src/pjsip-ua/sip_dialog.c
index 1b23bc42..ac110412 100644
--- a/pjsip/src/pjsip-ua/sip_dialog.c
+++ b/pjsip/src/pjsip-ua/sip_dialog.c
@@ -24,7 +24,7 @@
#include <pjsip/sip_types.h>
#include <pjsip/sip_endpoint.h>
#include <pjsip/sip_uri.h>
-#include <pjsip/sip_misc.h>
+#include <pjsip/sip_util.h>
#include <pjsip/sip_module.h>
#include <pjsip/sip_event.h>
#include <pjsip/sip_parser.h>
diff --git a/pjsip/src/pjsip-ua/sip_reg.c b/pjsip/src/pjsip-ua/sip_reg.c
index 12a670c5..e7bf9bd6 100644
--- a/pjsip/src/pjsip-ua/sip_reg.c
+++ b/pjsip/src/pjsip-ua/sip_reg.c
@@ -22,7 +22,7 @@
#include <pjsip/sip_module.h>
#include <pjsip/sip_transaction.h>
#include <pjsip/sip_event.h>
-#include <pjsip/sip_misc.h>
+#include <pjsip/sip_util.h>
#include <pjsip/sip_auth_msg.h>
#include <pj/pool.h>
#include <pj/string.h>
diff --git a/pjsip/src/pjsip-ua/sip_ua.c b/pjsip/src/pjsip-ua/sip_ua.c
index bbe362a6..11f7670c 100644
--- a/pjsip/src/pjsip-ua/sip_ua.c
+++ b/pjsip/src/pjsip-ua/sip_ua.c
@@ -21,7 +21,7 @@
#include <pjsip_mod_ua/sip_ua_private.h>
#include <pjsip/sip_module.h>
#include <pjsip/sip_event.h>
-#include <pjsip/sip_misc.h>
+#include <pjsip/sip_util.h>
#include <pjsip/sip_endpoint.h>
#include <pjsip/sip_transaction.h>
#include <pj/list.h>
diff --git a/pjsip/src/pjsip/sip_endpoint.c b/pjsip/src/pjsip/sip_endpoint.c
index 0d80b994..d68d35d0 100644
--- a/pjsip/src/pjsip/sip_endpoint.c
+++ b/pjsip/src/pjsip/sip_endpoint.c
@@ -22,7 +22,7 @@
#include <pjsip/sip_event.h>
#include <pjsip/sip_resolve.h>
#include <pjsip/sip_module.h>
-#include <pjsip/sip_misc.h>
+#include <pjsip/sip_util.h>
#include <pjsip/sip_errno.h>
#include <pj/except.h>
#include <pj/log.h>
@@ -106,13 +106,6 @@ static void endpt_transport_callback(pjsip_endpoint*,
/*
- * Create transaction.
- * Defined in sip_transaction.c
- */
-pj_status_t pjsip_tsx_create( pj_pool_t *pool, pjsip_endpoint *endpt,
- pjsip_transaction **tsx );
-
-/*
* This is the global handler for memory allocation failure, for pools that
* are created by the endpoint (by default, all pools ARE allocated by
* endpoint). The error is handled by throwing exception, and hopefully,
@@ -294,7 +287,7 @@ void pjsip_endpt_send_tsx_event( pjsip_endpoint *endpt, pjsip_event *evt )
/*
* Get "Allow" header.
*/
-PJ_DECL(const pjsip_allow_hdr*) pjsip_endpt_get_allow_hdr( pjsip_endpoint *endpt )
+PJ_DEF(const pjsip_allow_hdr*) pjsip_endpt_get_allow_hdr( pjsip_endpoint *endpt )
{
return endpt->allow_hdr;
}
@@ -671,7 +664,7 @@ PJ_DEF(void) pjsip_endpt_register_tsx( pjsip_endpoint *endpt,
/*
* Find transaction by the key.
*/
-PJ_DECL(pjsip_transaction*) pjsip_endpt_find_tsx( pjsip_endpoint *endpt,
+PJ_DEF(pjsip_transaction*) pjsip_endpt_find_tsx( pjsip_endpoint *endpt,
const pj_str_t *key )
{
pjsip_transaction *tsx;
@@ -980,7 +973,7 @@ PJ_DEF(pj_ioqueue_t*) pjsip_endpt_get_ioqueue(pjsip_endpoint *endpt)
/*
* Find/create transport.
*/
-PJ_DECL(pj_status_t) pjsip_endpt_alloc_transport( pjsip_endpoint *endpt,
+PJ_DEF(pj_status_t) pjsip_endpt_alloc_transport( pjsip_endpoint *endpt,
pjsip_transport_type_e type,
const pj_sockaddr_in *remote,
pjsip_transport **p_transport)
@@ -991,6 +984,50 @@ PJ_DECL(pj_status_t) pjsip_endpt_alloc_transport( pjsip_endpoint *endpt,
}
+/*
+ * Report error.
+ */
+PJ_DEF(void) pjsip_endpt_log_error( pjsip_endpoint *endpt,
+ const char *sender,
+ pj_status_t error_code,
+ const char *format,
+ ... )
+{
+ char newformat[256];
+ int len;
+ va_list marker;
+
+ va_start(marker, format);
+
+ PJ_UNUSED_ARG(endpt);
+
+ len = pj_native_strlen(format);
+ if (len < sizeof(newformat)-30) {
+ pj_str_t errstr;
+
+ pj_native_strcpy(newformat, format);
+ pj_snprintf(newformat+len, sizeof(newformat)-len-1,
+ ": [err %d] ", error_code);
+ len += pj_native_strlen(newformat+len);
+
+ errstr = pjsip_strerror(error_code, newformat+len,
+ sizeof(newformat)-len-1);
+
+ len += errstr.slen;
+ newformat[len] = '\0';
+
+ pj_log(sender, 1, newformat, marker);
+ } else {
+ pj_log(sender, 1, format, marker);
+ }
+
+ va_end(marker);
+}
+
+
+/*
+ * Dump endpoint.
+ */
PJ_DEF(void) pjsip_endpt_dump( pjsip_endpoint *endpt, pj_bool_t detail )
{
#if PJ_LOG_MAX_LEVEL >= 3
diff --git a/pjsip/src/pjsip/sip_errno.c b/pjsip/src/pjsip/sip_errno.c
new file mode 100644
index 00000000..7e24f3ee
--- /dev/null
+++ b/pjsip/src/pjsip/sip_errno.c
@@ -0,0 +1,125 @@
+/* $Id: $ */
+/*
+ * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <pjsip/sip_errno.h>
+#include <pjsip/sip_msg.h>
+#include <pj/string.h>
+#include <pj/errno.h>
+
+/* PJSIP's own error codes/messages
+ * MUST KEEP THIS ARRAY SORTED!!
+ */
+static const struct
+{
+ int code;
+ const char *msg;
+} err_str[] =
+{
+ /* Generic SIP errors */
+ { PJSIP_EBUSY, "Object is busy" },
+ { PJSIP_ETYPEEXISTS , "Object with the same type exists" },
+
+ /* Messaging errors */
+ { PJSIP_EINVALIDMSG, "Invalid message/syntax error" },
+ { PJSIP_EINVALIDSCHEME, "Invalid URI scheme" },
+ { PJSIP_EMSGTOOLONG, "Message too long" },
+ { PJSIP_EPARTIALMSG, "Partial message" },
+ { PJSIP_EMISSINGHDR, "Missing required header(s)" },
+ { PJSIP_EINVALIDVIA, "Invalid Via header" },
+ { PJSIP_EMULTIPLEVIA, "Multiple Via headers in response" },
+
+ /* Transport errors */
+ { PJSIP_EUNSUPTRANSPORT, "Unsupported transport"},
+ { PJSIP_EPENDINGTX, "Transmit buffer already pending"},
+ { PJSIP_ERXOVERFLOW, "Rx buffer overflow"},
+
+ /* Transaction errors */
+ { PJSIP_ETSXDESTROYED, "Transaction has been destroyed"},
+};
+
+
+/*
+ * pjsip_strerror()
+ */
+PJ_DEF(pj_str_t) pjsip_strerror( pj_status_t statcode,
+ char *buf, pj_size_t bufsize )
+{
+ pj_str_t errstr;
+
+ if (statcode >= PJSIP_ERRNO_START && statcode < PJSIP_ERRNO_START+800)
+ {
+ /* Status code. */
+ const pj_str_t *status_text =
+ pjsip_get_status_text(PJSIP_ERRNO_TO_SIP_STATUS(statcode));
+
+ errstr.ptr = buf;
+ pj_strncpy_with_null(&errstr, status_text, bufsize);
+ return errstr;
+ }
+ else if (statcode >= PJSIP_ERRNO_START_PJSIP &&
+ statcode < PJSIP_ERRNO_START_PJSIP + 1000)
+ {
+ /* Find the error in the table.
+ * Use binary search!
+ */
+ int first = 0;
+ int n = PJ_ARRAY_SIZE(err_str);
+
+ while (n > 0) {
+ int half = n/2;
+ int mid = first + half;
+
+ if (err_str[mid].code < statcode) {
+ first = mid+1;
+ n -= (half+1);
+ } else if (err_str[mid].code > statcode) {
+ n = half;
+ } else {
+ first = mid;
+ break;
+ }
+ }
+
+
+ if (PJ_ARRAY_SIZE(err_str) && err_str[first].code == statcode) {
+ pj_str_t msg;
+
+ msg.ptr = (char*)err_str[first].msg;
+ msg.slen = pj_native_strlen(err_str[first].msg);
+
+ errstr.ptr = buf;
+ pj_strncpy_with_null(&errstr, &msg, bufsize);
+ return errstr;
+
+ } else {
+ /* Error not found. */
+ errstr.ptr = buf;
+ errstr.slen = pj_snprintf(buf, bufsize,
+ "Unknown error %d",
+ statcode);
+
+ return errstr;
+ }
+ }
+ else {
+ /* Not our code. Give it to PJLIB. */
+ return pj_strerror(statcode, buf, bufsize);
+ }
+
+}
+
diff --git a/pjsip/src/pjsip/sip_parser.c b/pjsip/src/pjsip/sip_parser.c
index 01013363..7b869492 100644
--- a/pjsip/src/pjsip/sip_parser.c
+++ b/pjsip/src/pjsip/sip_parser.c
@@ -23,6 +23,7 @@
#include <pjsip/sip_errno.h>
#include <pjsip/sip_transport.h> /* rdata structure */
#include <pjlib-util/scanner.h>
+#include <pjlib-util/string.h>
#include <pj/except.h>
#include <pj/log.h>
#include <pj/hash.h>
@@ -32,16 +33,20 @@
#include <pj/ctype.h>
#include <pj/assert.h>
-#define RESERVED ";/?:@&=+$,"
-#define MARK "-_.!~*'()"
-#define ESCAPED "%"
-#define USER "&=+$,;?/"
-#define PASS "&=+$,"
-#define TOKEN "-.!%*_=`'~+" /* '+' is because of application/pidf+xml
- * in Content-Type! */
-#define HOST "_-."
-#define HEX_DIGIT "abcdefABCDEF"
-#define PARAM_CHAR "[]/:&+$" MARK "%"
+#define ALNUM
+#define RESERVED ";/?:@&=+$,"
+#define MARK "-_.!~*'()"
+#define UNRESERVED ALNUM MARK
+#define ESCAPED "%"
+#define USER_UNRESERVED "&=+$,;?/"
+#define PASS "&=+$,"
+#define TOKEN "-.!%*_=`'~+" /* '+' is because of app/pidf+xml
+ * in Content-Type! */
+#define HOST "_-."
+#define HEX_DIGIT "abcdefABCDEF"
+#define PARAM_CHAR "[]/:&+$" UNRESERVED ESCAPED
+#define HNV_UNRESERVED "[]/?:+$"
+#define HDR_CHAR HNV_UNRESERVED UNRESERVED ESCAPED
#define PJSIP_VERSION "SIP/2.0"
#define PJSIP_SYN_ERR_EXCEPTION 1
@@ -92,6 +97,7 @@ pj_cis_t pjsip_HOST_SPEC, /* For scanning host part. */
pjsip_HEX_SPEC, /* Hexadecimal digits. */
pjsip_PARAM_CHAR_SPEC, /* For scanning pname (or pvalue when
* it's not quoted.) */
+ pjsip_HDR_CHAR_SPEC, /* Chars in hname or hvalue */
pjsip_PROBE_USER_HOST_SPEC, /* Hostname characters. */
pjsip_PASSWD_SPEC, /* Password. */
pjsip_USER_SPEC, /* User */
@@ -109,6 +115,9 @@ static pjsip_msg * int_parse_msg( pjsip_parse_ctx *ctx,
static void int_parse_param( pj_scanner *scanner,
pj_str_t *pname,
pj_str_t *pvalue);
+static void int_parse_hparam( pj_scanner *scanner,
+ pj_str_t *hname,
+ pj_str_t *hvalue );
static void int_parse_req_line( pj_scanner *scanner,
pj_pool_t *pool,
pjsip_request_line *req_line);
@@ -271,9 +280,13 @@ static pj_status_t init_parser()
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
pj_cis_add_str(&pjsip_PARAM_CHAR_SPEC, PARAM_CHAR);
+ status = pj_cis_dup(&pjsip_HDR_CHAR_SPEC, &pjsip_ALNUM_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ pj_cis_add_str(&pjsip_HDR_CHAR_SPEC, HDR_CHAR);
+
status = pj_cis_dup(&pjsip_USER_SPEC, &pjsip_ALNUM_SPEC);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
- pj_cis_add_str( &pjsip_USER_SPEC, MARK ESCAPED USER );
+ pj_cis_add_str( &pjsip_USER_SPEC, ESCAPED USER_UNRESERVED );
status = pj_cis_dup(&pjsip_PASSWD_SPEC, &pjsip_ALNUM_SPEC);
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
@@ -858,6 +871,7 @@ void pjsip_parse_param_imp( pj_scanner *scanner,
{
/* pname */
pj_scan_get(scanner, &pjsip_PARAM_CHAR_SPEC, pname);
+ pj_str_unescape(pname);
/* pvalue, if any */
if (*scanner->curptr == '=') {
@@ -871,6 +885,7 @@ void pjsip_parse_param_imp( pj_scanner *scanner,
}
} else {
pj_scan_get(scanner, &pjsip_PARAM_CHAR_SPEC, pvalue);
+ pj_str_unescape(pvalue);
}
} else {
pvalue->ptr = NULL;
@@ -889,15 +904,39 @@ static void int_parse_param( pj_scanner *scanner,
pjsip_parse_param_imp(scanner, pname, pvalue, 0);
}
+/* Parse header parameter. */
+static void int_parse_hparam( pj_scanner *scanner,
+ pj_str_t *hname, pj_str_t *hvalue )
+{
+ /* Get '?' or '&' character. */
+ pj_scan_get_char(scanner);
+
+ /* hname */
+ pj_scan_get(scanner, &pjsip_HDR_CHAR_SPEC, hname);
+ pj_str_unescape(hname);
+
+ /* pvalue, if any */
+ if (*scanner->curptr == '=') {
+ pj_scan_get_char(scanner);
+ pj_scan_get(scanner, &pjsip_HDR_CHAR_SPEC, hvalue);
+ pj_str_unescape(hvalue);
+ } else {
+ hvalue->ptr = NULL;
+ hvalue->slen = 0;
+ }
+}
+
/* Parse host:port in URI. */
static void int_parse_uri_host_port( pj_scanner *scanner,
pj_str_t *host, int *p_port)
{
pj_scan_get( scanner, &pjsip_HOST_SPEC, host);
+ /* RFC3261 section 19.1.2: host don't need to be unescaped */
if (*scanner->curptr == ':') {
pj_str_t port;
pj_scan_get_char(scanner);
pj_scan_get(scanner, &pjsip_DIGIT_SPEC, &port);
+ pj_str_unescape(&port);
*p_port = pj_strtoul(&port);
} else {
*p_port = 0;
@@ -926,9 +965,12 @@ static void int_parse_user_pass( pj_scanner *scanner,
pj_str_t *user, pj_str_t *pass)
{
pj_scan_get( scanner, &pjsip_USER_SPEC, user);
+ pj_str_unescape(user);
+
if ( *scanner->curptr == ':') {
pj_scan_get_char( scanner );
pj_scan_get( scanner, &pjsip_PASSWD_SPEC, pass);
+ pj_str_unescape(pass);
} else {
pass->ptr = NULL;
pass->slen = 0;
@@ -945,6 +987,9 @@ static pjsip_uri *int_parse_uri_or_name_addr( pj_scanner *scanner, pj_pool_t *po
pjsip_uri *uri;
int is_name_addr = 0;
+ /* Exhaust any whitespaces. */
+ pj_scan_skip_whitespace(scanner);
+
if (*scanner->curptr=='"' || *scanner->curptr=='<') {
uri = (pjsip_uri*)int_parse_name_addr( scanner, pool );
is_name_addr = 1;
@@ -1034,6 +1079,7 @@ static pjsip_url *int_parse_sip_url( pj_scanner *scanner,
pjsip_url *url;
int colon;
int skip_ws = scanner->skip_ws;
+ int hsep = '?';
scanner->skip_ws = 0;
pj_scan_get(scanner, &pjsip_TOKEN_SPEC, &scheme);
@@ -1089,14 +1135,20 @@ static pjsip_url *int_parse_sip_url( pj_scanner *scanner,
url->lr_param = 1;
} else {
- concat_param(&url->other_param, pool, &pname, &pvalue);
+ pjsip_param *p = pj_pool_alloc(pool, sizeof(pjsip_param));
+ p->name = pname;
+ p->value = pvalue;
+ pj_list_insert_before(&url->other_param, p);
}
}
/* Get header params. */
- if (parse_params && *scanner->curptr == '?') {
- pj_scan_get_until(scanner, &pjsip_NEWLINE_OR_EOF_SPEC,
- &url->header_param);
+ while (parse_params && *scanner->curptr == hsep) {
+ pjsip_param *param;
+ param = pj_pool_alloc(pool, sizeof(pjsip_param));
+ int_parse_hparam(scanner, &param->name, &param->value);
+ pj_list_insert_before(&url->header_param, param);
+ hsep = '&';
}
scanner->skip_ws = skip_ws;
diff --git a/pjsip/src/pjsip/sip_transaction.c b/pjsip/src/pjsip/sip_transaction.c
index f4818817..bc4f21ff 100644
--- a/pjsip/src/pjsip/sip_transaction.c
+++ b/pjsip/src/pjsip/sip_transaction.c
@@ -19,7 +19,7 @@
#include <pjsip/sip_transaction.h>
#include <pjsip/sip_transport.h>
#include <pjsip/sip_config.h>
-#include <pjsip/sip_misc.h>
+#include <pjsip/sip_util.h>
#include <pjsip/sip_event.h>
#include <pjsip/sip_endpoint.h>
#include <pjsip/sip_errno.h>
@@ -345,9 +345,9 @@ PJ_DEF(pj_status_t) pjsip_tsx_create_key( pj_pool_t *pool, pj_str_t *key,
/*
* Create new transaction.
*/
-pj_status_t pjsip_tsx_create( pj_pool_t *pool,
- pjsip_endpoint *endpt,
- pjsip_transaction **p_tsx)
+PJ_DEF(pj_status_t) pjsip_tsx_create( pj_pool_t *pool,
+ pjsip_endpoint *endpt,
+ pjsip_transaction **p_tsx)
{
pjsip_transaction *tsx;
pj_status_t status;
diff --git a/pjsip/src/pjsip/sip_transport.c b/pjsip/src/pjsip/sip_transport.c
index 307f9e5e..a32fb683 100644
--- a/pjsip/src/pjsip/sip_transport.c
+++ b/pjsip/src/pjsip/sip_transport.c
@@ -647,7 +647,7 @@ PJ_DEF(pj_ssize_t) pjsip_tpmgr_receive_packet( pjsip_tpmgr *mgr,
&msg_fragment_size);
if (msg_status != PJ_SUCCESS) {
if (remaining_len == PJSIP_MAX_PKT_LEN) {
- mgr->msg_cb(mgr->endpt, PJSIP_EOVERFLOW, rdata);
+ mgr->msg_cb(mgr->endpt, PJSIP_ERXOVERFLOW, rdata);
/* Exhaust all data. */
return rdata->pkt_info.len;
} else {
diff --git a/pjsip/src/pjsip/sip_uri.c b/pjsip/src/pjsip/sip_uri.c
index bd49db97..b292fea0 100644
--- a/pjsip/src/pjsip/sip_uri.c
+++ b/pjsip/src/pjsip/sip_uri.c
@@ -18,11 +18,59 @@
*/
#include <pjsip/sip_uri.h>
#include <pjsip/sip_msg.h>
+#include <pjsip/sip_parser.h>
#include <pjsip/print_util.h>
+#include <pjsip/sip_errno.h>
+#include <pjlib-util/string.h>
#include <pj/string.h>
#include <pj/pool.h>
#include <pj/assert.h>
+/*
+ * Generic parameter manipulation.
+ */
+PJ_DEF(pjsip_param*) pjsip_param_find( pjsip_param *param_list,
+ const pj_str_t *name )
+{
+ pjsip_param *p = param_list->next;
+ while (p != param_list) {
+ if (pj_stricmp(&p->name, name)==0)
+ return p;
+ p = p->next;
+ }
+ return NULL;
+}
+
+PJ_DEF(const pjsip_param*) pjsip_param_cfind( const pjsip_param *param_list,
+ const pj_str_t *name )
+{
+ const pjsip_param *p = param_list->next;
+ while (p != param_list) {
+ if (pj_stricmp(&p->name, name)==0)
+ return p;
+ p = p->next;
+ }
+ return NULL;
+}
+
+PJ_DEF(void) pjsip_param_clone( pj_pool_t *pool, pjsip_param *dst_list,
+ const pjsip_param *src_list)
+{
+ const pjsip_param *p = src_list->next;
+
+ pj_list_init(dst_list);
+ while (p != src_list) {
+ pjsip_param *new_param = pj_pool_alloc(pool, sizeof(pjsip_param));
+ pj_strdup(pool, &new_param->name, &p->name);
+ pj_strdup(pool, &new_param->value, &p->value);
+ pj_list_insert_before(dst_list, new_param);
+ p = p->next;
+ }
+}
+
+/*
+ * URI stuffs
+ */
#define IS_SIPS(url) ((url)->vptr==&sips_url_vptr)
static const pj_str_t *pjsip_url_get_scheme( const pjsip_url* );
@@ -109,6 +157,8 @@ PJ_DEF(void) pjsip_url_init(pjsip_url *url, int secure)
pj_memset(url, 0, sizeof(*url));
url->ttl_param = -1;
url->vptr = secure ? &sips_url_vptr : &sip_url_vptr;
+ pj_list_init(&url->other_param);
+ pj_list_init(&url->header_param);
}
PJ_DEF(pjsip_url*) pjsip_url_create( pj_pool_t *pool, int secure )
@@ -123,37 +173,25 @@ static int pjsip_url_print( pjsip_uri_context_e context,
char *buf, pj_size_t size)
{
int printed;
- pj_size_t size_required;
char *startbuf = buf;
+ char *endbuf = buf+size;
const pj_str_t *scheme;
- *buf = '\0';
+ pjsip_param *param;
+ char hparam_char = '?';
- /* Check the buffer length. */
- size_required = 6 + url->host.slen + 10 +
- url->user.slen + url->passwd.slen + 2 +
- url->user_param.slen + 6 +
- url->method_param.slen + 8 +
- url->transport_param.slen + 11 +
- 9 + 5 +
- url->maddr_param.slen + 7 +
- 3 +
- url->other_param.slen +
- url->header_param.slen;
- if (size < size_required) {
- return -1;
- }
+ *buf = '\0';
/* Print scheme ("sip:" or "sips:") */
scheme = pjsip_uri_get_scheme(url);
- copy_advance_no_check(buf, *scheme);
+ copy_advance_check(buf, *scheme);
*buf++ = ':';
/* Print "user:password@", if any. */
if (url->user.slen) {
- copy_advance_no_check(buf, url->user);
+ copy_advance_escape(buf, url->user, pjsip_USER_SPEC);
if (url->passwd.slen) {
*buf++ = ':';
- copy_advance_no_check(buf, url->passwd);
+ copy_advance_escape(buf, url->passwd, pjsip_PASSWD_SPEC);
}
*buf++ = '@';
@@ -161,7 +199,7 @@ static int pjsip_url_print( pjsip_uri_context_e context,
/* Print host. */
pj_assert(url->host.slen != 0);
- copy_advance_no_check(buf, url->host);
+ copy_advance_check(buf, url->host);
/* Only print port if it is explicitly specified.
* Port is not allowed in To and From header.
@@ -170,29 +208,31 @@ static int pjsip_url_print( pjsip_uri_context_e context,
* number exactly as it was sent. We don't remember whether an
* UA has sent us port, so we'll just send the port indiscrimately
*/
- PJ_TODO(SHOULD_DISALLOW_URI_PORT_IN_FROM_TO_HEADER)
- if (url->port /*&& context != PJSIP_URI_IN_FROMTO_HDR*/) {
+ //PJ_TODO(SHOULD_DISALLOW_URI_PORT_IN_FROM_TO_HEADER)
+ if (url->port && context != PJSIP_URI_IN_FROMTO_HDR) {
*buf++ = ':';
printed = pj_utoa(url->port, buf);
buf += printed;
}
/* User param is allowed in all contexes */
- copy_advance_pair_no_check(buf, ";user=", 6, url->user_param);
+ copy_advance_pair_check(buf, ";user=", 6, url->user_param);
/* Method param is only allowed in external/other context. */
if (context == PJSIP_URI_IN_OTHER) {
- copy_advance_pair_no_check(buf, ";method=", 8, url->method_param);
+ copy_advance_pair_escape(buf, ";method=", 8, url->method_param,
+ pjsip_PARAM_CHAR_SPEC);
}
/* Transport is not allowed in From/To header. */
if (context != PJSIP_URI_IN_FROMTO_HDR) {
- copy_advance_pair_no_check(buf, ";transport=", 11, url->transport_param);
+ copy_advance_pair_escape(buf, ";transport=", 11, url->transport_param,
+ pjsip_PARAM_CHAR_SPEC);
}
/* TTL param is not allowed in From, To, Route, and Record-Route header. */
if (url->ttl_param >= 0 && context != PJSIP_URI_IN_FROMTO_HDR &&
- context != PJSIP_URI_IN_ROUTING_HDR)
+ context != PJSIP_URI_IN_ROUTING_HDR && (endbuf-buf) > 15)
{
pj_memcpy(buf, ";ttl=", 5);
printed = pj_utoa(url->ttl_param, buf+5);
@@ -201,7 +241,8 @@ static int pjsip_url_print( pjsip_uri_context_e context,
/* maddr param is not allowed in From and To header. */
if (context != PJSIP_URI_IN_FROMTO_HDR) {
- copy_advance_pair_no_check(buf, ";maddr=", 7, url->maddr_param);
+ copy_advance_pair_escape(buf, ";maddr=", 7, url->maddr_param,
+ pjsip_PARAM_CHAR_SPEC);
}
/* lr param is not allowed in From, To, and Contact header. */
@@ -209,86 +250,166 @@ static int pjsip_url_print( pjsip_uri_context_e context,
context != PJSIP_URI_IN_CONTACT_HDR)
{
pj_str_t lr = { ";lr", 3 };
- copy_advance_no_check(buf, lr);
+ copy_advance_check(buf, lr);
}
/* Other param. */
- if (url->other_param.slen) {
- copy_advance_no_check(buf, url->other_param);
+ param = url->other_param.next;
+ while (param != &url->other_param) {
+ *buf++ = ';';
+ copy_advance_escape(buf, param->name, pjsip_PARAM_CHAR_SPEC);
+ if (param->value.slen) {
+ *buf++ = '=';
+ copy_advance_escape(buf, param->value, pjsip_PARAM_CHAR_SPEC);
+ }
+ param = param->next;
}
/* Header param. */
- if (url->header_param.slen) {
- copy_advance_no_check(buf, url->header_param);
+ param = url->header_param.next;
+ while (param != &url->header_param) {
+ *buf++ = hparam_char;
+ copy_advance_escape(buf, param->name, pjsip_HDR_CHAR_SPEC);
+ if (param->value.slen) {
+ *buf++ = '=';
+ copy_advance_escape(buf, param->value, pjsip_HDR_CHAR_SPEC);
+ }
+ param = param->next;
+ hparam_char = '&';
}
*buf = '\0';
return buf-startbuf;
}
-static int pjsip_url_compare( pjsip_uri_context_e context,
- const pjsip_url *url1, const pjsip_url *url2)
+static pj_status_t pjsip_url_compare( pjsip_uri_context_e context,
+ const pjsip_url *url1,
+ const pjsip_url *url2)
{
- /* The easiest (and probably the most efficient) way to compare two URLs
- are to print them, and compare them bytes per bytes. This technique
- works quite well with RFC3261, as the RFC (unlike RFC2543) defines that
- components specified in one URL does NOT match its default value if
- it is not specified in the second URL. For example, parameter "user=ip"
- does NOT match if it is omited in second URL.
-
- HOWEVER, THE SAME CAN NOT BE APPLIED FOR other-param NOR header-param.
- For these, each of the parameters must be compared one by one. Parameter
- that exists in one URL will match the comparison. But parameter that
- exists in both URLs and doesn't match wont match the URL comparison.
-
- The solution for this is to compare 'standard' URL components with
- bytes-to-bytes comparison, and compare other-param and header-param with
- more intelligent comparison.
+ const pjsip_param *p1;
+
+ /*
+ * Compare two SIP URL's according to Section 19.1.4 of RFC 3261.
*/
- char str_url1[PJSIP_MAX_URL_SIZE];
- char str_url2[PJSIP_MAX_URL_SIZE];
- int len1, len2;
- /* Must compare scheme first, as the second URI may not be SIP URL. */
- if (pj_stricmp(pjsip_uri_get_scheme(url1), pjsip_uri_get_scheme(url2)))
- return -1;
+ /* SIP and SIPS URI are never equivalent.
+ * Note: just compare the vptr to avoid string comparison.
+ * Pretty neat huh!!
+ */
+ if (url1->vptr != url2->vptr)
+ return PJSIP_ECMPSCHEME;
- len1 = pjsip_url_print(context, url1, str_url1, sizeof(str_url1));
- if (len1 < 1) {
- pj_assert(0);
- return -1;
+ /* Comparison of the userinfo of SIP and SIPS URIs is case-sensitive.
+ * This includes userinfo containing passwords or formatted as
+ * telephone-subscribers.
+ */
+ if (pj_strcmp(&url1->user, &url2->user) != 0)
+ return PJSIP_ECMPUSER;
+ if (pj_strcmp(&url1->passwd, &url2->passwd) != 0)
+ return PJSIP_ECMPPASSWD;
+
+ /* Comparison of all other components of the URI is
+ * case-insensitive unless explicitly defined otherwise.
+ */
+
+ /* The ordering of parameters and header fields is not significant
+ * in comparing SIP and SIPS URIs.
+ */
+
+ /* Characters other than those in the “reserved” set (see RFC 2396 [5])
+ * are equivalent to their “encoding.
+ */
+
+ /* An IP address that is the result of a DNS lookup of a host name
+ * does not match that host name.
+ */
+ if (pj_stricmp(&url1->host, &url2->host) != 0)
+ return PJSIP_ECMPHOST;
+
+ /* A URI omitting any component with a default value will not match a URI
+ * explicitly containing that component with its default value.
+ * For instance, a URI omitting the optional port component will not match
+ * a URI explicitly declaring port 5060.
+ * The same is true for the transport-parameter, ttl-parameter,
+ * user-parameter, and method components.
+ */
+
+ /* Port is not allowed in To and From header.
+ */
+ if (context != PJSIP_URI_IN_FROMTO_HDR) {
+ if (url1->port != url2->port)
+ return PJSIP_ECMPPORT;
}
- len2 = pjsip_url_print(context, url2, str_url2, sizeof(str_url2));
- if (len2 < 1) {
- pj_assert(0);
- return -1;
+ /* Transport is not allowed in From/To header. */
+ if (context != PJSIP_URI_IN_FROMTO_HDR) {
+ if (pj_stricmp(&url1->transport_param, &url2->transport_param) != 0)
+ return PJSIP_ECMPTRANSPORTPRM;
}
-
- if (len1 != len2) {
- /* Not equal. */
- return -1;
+ /* TTL param is not allowed in From, To, Route, and Record-Route header. */
+ if (context != PJSIP_URI_IN_FROMTO_HDR &&
+ context != PJSIP_URI_IN_ROUTING_HDR)
+ {
+ if (url1->ttl_param != url2->ttl_param)
+ return PJSIP_ECMPTTLPARAM;
}
-
- if (pj_native_strcmp(str_url1, str_url2)) {
- /* Not equal */
- return -1;
+ /* User param is allowed in all contexes */
+ if (pj_stricmp(&url1->user_param, &url2->user_param) != 0)
+ return PJSIP_ECMPUSERPARAM;
+ /* Method param is only allowed in external/other context. */
+ if (context == PJSIP_URI_IN_OTHER) {
+ if (pj_stricmp(&url1->method_param, &url2->method_param) != 0)
+ return PJSIP_ECMPMETHODPARAM;
+ }
+ /* maddr param is not allowed in From and To header. */
+ if (context != PJSIP_URI_IN_FROMTO_HDR) {
+ if (pj_stricmp(&url1->maddr_param, &url2->maddr_param) != 0)
+ return PJSIP_ECMPMADDRPARAM;
}
- /* TODO: compare other-param and header-param in more intelligent manner. */
- PJ_TODO(HPARAM_AND_OTHER_PARAM_COMPARISON_IN_URL_COMPARISON)
+ /* lr parameter is ignored (?) */
+ /* lr param is not allowed in From, To, and Contact header. */
- if (pj_strcmp(&url1->other_param, &url2->other_param)) {
- /* Not equal. */
- return -1;
+
+ /* All other uri-parameters appearing in only one URI are ignored when
+ * comparing the URIs.
+ */
+ p1 = url1->other_param.next;
+ while (p1 != &url1->other_param) {
+ const pjsip_param *p2;
+ p2 = pjsip_param_cfind(&url2->other_param, &p1->name);
+ if (p2 ) {
+ if (pj_stricmp(&p1->value, &p2->value) != 0)
+ return PJSIP_ECMPOTHERPARAM;
+ }
+
+ p1 = p1->next;
}
- if (pj_strcmp(&url1->header_param, &url2->header_param)) {
- /* Not equal. */
- return -1;
+
+ /* URI header components are never ignored. Any present header component
+ * MUST be present in both URIs and match for the URIs to match.
+ * The matching rules are defined for each header field in Section 20.
+ */
+ p1 = url1->header_param.next;
+ while (p1 != &url1->header_param) {
+ const pjsip_param *p2;
+ p2 = pjsip_param_cfind(&url2->header_param, &p1->name);
+ if (p2) {
+ /* It seems too much to compare two header params according to
+ * the rule of each header. We'll just compare them string to
+ * string..
+ */
+ PJ_TODO(MORE_COMPLIANT_HEADER_PARAM_COMPARISON_IN_URL);
+
+ if (pj_stricmp(&p1->value, &p2->value) != 0)
+ return PJSIP_ECMPHEADERPARAM;
+ } else {
+ return PJSIP_ECMPHEADERPARAM;
+ }
+ p1 = p1->next;
}
- /* Seems to be equal, isn't it. */
- return 0;
-
+ /* Equal!! Pheuww.. */
+ return PJ_SUCCESS;
}
@@ -304,8 +425,8 @@ PJ_DEF(void) pjsip_url_assign(pj_pool_t *pool, pjsip_url *url,
pj_strdup( pool, &url->transport_param, &rhs->transport_param);
url->ttl_param = rhs->ttl_param;
pj_strdup( pool, &url->maddr_param, &rhs->maddr_param);
- pj_strdup( pool, &url->other_param, &rhs->other_param);
- pj_strdup( pool, &url->header_param, &rhs->header_param);
+ pjsip_param_clone(pool, &url->other_param, &rhs->other_param);
+ pjsip_param_clone(pool, &url->header_param, &rhs->header_param);
url->lr_param = rhs->lr_param;
}
diff --git a/pjsip/src/pjsip/sip_misc.c b/pjsip/src/pjsip/sip_util.c
index c134da88..5f59a12e 100644
--- a/pjsip/src/pjsip/sip_misc.c
+++ b/pjsip/src/pjsip/sip_util.c
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <pjsip/sip_misc.h>
+#include <pjsip/sip_util.h>
#include <pjsip/sip_transport.h>
#include <pjsip/sip_msg.h>
#include <pjsip/sip_endpoint.h>
diff --git a/pjsip/src/test-pjsip/main.c b/pjsip/src/test-pjsip/main.c
index 75b3792e..3c819be8 100644
--- a/pjsip/src/test-pjsip/main.c
+++ b/pjsip/src/test-pjsip/main.c
@@ -16,3 +16,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include "test.h"
+
+int main(void)
+{
+ return test_main();
+}
diff --git a/pjsip/src/test-pjsip/parse_msg.c b/pjsip/src/test-pjsip/msg.c
index 94ac25ce..b546a756 100644
--- a/pjsip/src/test-pjsip/parse_msg.c
+++ b/pjsip/src/test-pjsip/msg.c
@@ -16,19 +16,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <pjsip/sip_msg.h>
-#include <pjsip/sip_parser.h>
-#include <pj/os.h>
-#include <pj/pool.h>
-#include <pj/string.h>
-#include <stdlib.h>
-#include <stdio.h>
#include "test.h"
-
-#define ERR_SYNTAX_ERR (-2)
-#define ERR_NOT_EQUAL (-3)
-#define ERR_SYSTEM (-4)
-
+#include <pjsip_core.h>
+#include <pjlib.h>
static pjsip_msg *create_msg0(pj_pool_t *pool);
@@ -66,66 +56,31 @@ struct test_msg
}
};
-static pj_caching_pool cp;
-static pj_pool_factory *pf = &cp.factory;
static pj_uint32_t parse_len, parse_time, print_time;
-static void pool_error(pj_pool_t *pool, pj_size_t sz)
-{
- PJ_UNUSED_ARG(pool)
- PJ_UNUSED_ARG(sz)
-
- pj_assert(0);
- exit(1);
-}
-
-static const char *STATUS_STR(pj_status_t status)
-{
- switch (status) {
- case 0: return "OK";
- case ERR_SYNTAX_ERR: return "Syntax Error";
- case ERR_NOT_EQUAL: return "Not Equal";
- case ERR_SYSTEM: return "System Error";
- }
- return "???";
-}
-
-static pj_status_t test_entry( struct test_msg *entry )
+static pj_status_t test_entry( pj_pool_t *pool, struct test_msg *entry )
{
pjsip_msg *parsed_msg, *ref_msg;
- pj_pool_t *pool;
pj_status_t status = PJ_SUCCESS;
int len;
pj_str_t str1, str2;
pjsip_hdr *hdr1, *hdr2;
- pj_hr_timestamp t1, t2;
+ pj_timestamp t1, t2;
char *msgbuf;
enum { BUFLEN = 512 };
- pool = pj_pool_create( pf, "",
- PJSIP_POOL_LEN_RDATA*2, PJSIP_POOL_INC_RDATA,
- &pool_error);
-
- if (entry->len == 0) {
- entry->len = strlen(entry->msg);
- }
-
/* Parse message. */
parse_len += entry->len;
- pj_hr_gettimestamp(&t1);
+ pj_get_timestamp(&t1);
parsed_msg = pjsip_parse_msg(pool, entry->msg, entry->len, NULL);
if (parsed_msg == NULL) {
- status = ERR_SYNTAX_ERR;
+ status = -10;
goto on_return;
}
- pj_hr_gettimestamp(&t2);
+ pj_get_timestamp(&t2);
parse_time += t2.u32.lo - t1.u32.lo;
-#if IS_PROFILING
- goto print_msg;
-#endif
-
/* Create reference message. */
ref_msg = entry->creator(pool);
@@ -135,7 +90,7 @@ static pj_status_t test_entry( struct test_msg *entry )
/* Compare message type. */
if (parsed_msg->type != ref_msg->type) {
- status = ERR_NOT_EQUAL;
+ status = -20;
goto on_return;
}
@@ -145,7 +100,7 @@ static pj_status_t test_entry( struct test_msg *entry )
pjsip_method *m2 = &ref_msg->line.req.method;
if (m1->id != m2->id || pj_strcmp(&m1->name, &m2->name)) {
- status = ERR_NOT_EQUAL;
+ status = -30;
goto on_return;
}
} else {
@@ -159,26 +114,20 @@ static pj_status_t test_entry( struct test_msg *entry )
while (hdr1 != &parsed_msg->hdr && hdr2 != &ref_msg->hdr) {
len = hdr1->vptr->print_on(hdr1, str1.ptr, BUFLEN);
if (len < 1) {
- status = ERR_SYSTEM;
+ status = -40;
goto on_return;
}
str1.slen = len;
len = hdr2->vptr->print_on(hdr2, str2.ptr, BUFLEN);
if (len < 1) {
- status = ERR_SYSTEM;
+ status = -50;
goto on_return;
}
str2.slen = len;
- if (!SILENT) {
- printf("hdr1='%.*s'\n"
- "hdr2='%.*s'\n\n",
- str1.slen, str1.ptr,
- str2.slen, str2.ptr);
- }
if (pj_strcmp(&str1, &str2) != 0) {
- status = ERR_NOT_EQUAL;
+ status = -60;
goto on_return;
}
@@ -187,62 +136,42 @@ static pj_status_t test_entry( struct test_msg *entry )
}
if (hdr1 != &parsed_msg->hdr || hdr2 != &ref_msg->hdr) {
- status = ERR_NOT_EQUAL;
+ status = -70;
goto on_return;
}
/* Print message. */
-#if IS_PROFILING
-print_msg:
-#endif
msgbuf = pj_pool_alloc(pool, PJSIP_MAX_PKT_LEN);
if (msgbuf == NULL) {
- status = ERR_SYSTEM;
+ status = -80;
goto on_return;
}
- pj_hr_gettimestamp(&t1);
+ pj_get_timestamp(&t1);
len = pjsip_msg_print(parsed_msg, msgbuf, PJSIP_MAX_PKT_LEN);
if (len < 1) {
- status = ERR_SYSTEM;
+ status = -90;
goto on_return;
}
- pj_hr_gettimestamp(&t2);
+ pj_get_timestamp(&t2);
print_time += t2.u32.lo - t1.u32.lo;
status = PJ_SUCCESS;
on_return:
- pj_pool_release(pool);
return status;
}
-static void warm_up()
-{
- pj_pool_t *pool;
- pool = pj_pool_create( pf, "",
- PJSIP_POOL_LEN_RDATA*2, PJSIP_POOL_INC_RDATA,
- &pool_error);
- pj_pool_release(pool);
-}
-
-pj_status_t test_msg(void)
+pj_status_t msg_test(void)
{
pj_status_t status;
- unsigned i;
+ pj_pool_t *pool;
- pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
- warm_up();
+ pool = pjsip_endpt_create_pool(endpt, NULL, 4000, 4000);
- for (i=0; i<LOOP; ++i) {
- status = test_entry( &test_array[0] );
- }
- printf("%s\n", STATUS_STR(status));
+ status = test_entry( pool, &test_array[0] );
- printf("Total bytes: %u, parse time=%f/char, print time=%f/char\n",
- parse_len,
- parse_time*1.0/parse_len,
- print_time*1.0/parse_len);
- return PJ_SUCCESS;
+ pjsip_endpt_destroy(endpt);
+ return status;
}
/*****************************************************************************/
diff --git a/pjsip/src/test-pjsip/test.c b/pjsip/src/test-pjsip/test.c
index 4a69b582..80d08881 100644
--- a/pjsip/src/test-pjsip/test.c
+++ b/pjsip/src/test-pjsip/test.c
@@ -46,20 +46,59 @@ void app_perror(const char *msg, pj_status_t rc)
}
+pj_status_t register_static_modules(pj_size_t *count, pjsip_module **modules)
+{
+ *count = 0;
+ return PJ_SUCCESS;
+}
-
-int main()
+int test_main(void)
{
pj_status_t rc;
+ pj_caching_pool caching_pool;
+ const char *filename;
+ int line;
+
+ pj_log_set_level(3);
+ pj_log_set_decor(PJ_LOG_HAS_NEWLINE | PJ_LOG_HAS_TIME |
+ PJ_LOG_HAS_MICRO_SEC);
if ((rc=pj_init()) != PJ_SUCCESS) {
app_perror("pj_init", rc);
+ return rc;
+ }
+
+ pj_dump_config();
+
+ pj_caching_pool_init( &caching_pool, &pj_pool_factory_default_policy, 0 );
+
+ rc = pjsip_endpt_create(&caching_pool.factory, "endpt", &endpt);
+ if (rc != PJ_SUCCESS) {
+ app_perror("pjsip_endpt_create", rc);
+ pj_caching_pool_destroy(&caching_pool);
+ return rc;
}
- DO_TEST(parse_uri());
- DO_TEST(parse_msg());
+ PJ_LOG(3,("",""));
+
+ DO_TEST(uri_test());
on_return:
+
+ pjsip_endpt_destroy(endpt);
+ pj_caching_pool_destroy(&caching_pool);
+
+ PJ_LOG(3,("test", ""));
+
+ pj_thread_get_stack_info(pj_thread_this(), &filename, &line);
+ PJ_LOG(3,("test", "Stack max usage: %u, deepest: %s:%u",
+ pj_thread_get_stack_max_usage(pj_thread_this()),
+ filename, line));
+ if (rc == 0)
+ PJ_LOG(3,("test", "Looks like everything is okay!.."));
+ else
+ PJ_LOG(3,("test", "Test completed with error(s)"));
+
return 0;
}
diff --git a/pjsip/src/test-pjsip/test.h b/pjsip/src/test-pjsip/test.h
index 225c8be7..60b67c5e 100644
--- a/pjsip/src/test-pjsip/test.h
+++ b/pjsip/src/test-pjsip/test.h
@@ -21,15 +21,12 @@
#include <pjsip/sip_types.h>
-#define SILENT 1
-#define IS_PROFILING 1
-#define LOOP 2000
-
extern pjsip_endpoint *endpt;
-pj_status_t parse_uri(void);
-pj_status_t parse_msg(void);
+pj_status_t uri_test(void);
+pj_status_t msg_test(void);
+int test_main(void);
void app_perror(const char *msg, pj_status_t status);
diff --git a/pjsip/src/test-pjsip/parse_uri.c b/pjsip/src/test-pjsip/uri.c
index cfb3afd7..a61382f0 100644
--- a/pjsip/src/test-pjsip/parse_uri.c
+++ b/pjsip/src/test-pjsip/uri.c
@@ -16,17 +16,10 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <pjsip/sip_parser.h>
-#include <pjsip/sip_uri.h>
-#include <pj/os.h>
-#include <pj/pool.h>
-#include <pj/string.h>
-#include <stdlib.h>
-#include <stdio.h>
#include "test.h"
+#include <pjsip_core.h>
+#include <pjlib.h>
-#define ERR_SYNTAX_ERR (-2)
-#define ERR_NOT_EQUAL (-3)
#define ALPHANUM "abcdefghijklmnopqrstuvwxyz" \
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
@@ -38,18 +31,7 @@
#define POOL_SIZE 4096
-static const char *STATUS_STR(pj_status_t status)
-{
- switch (status) {
- case 0: return "OK";
- case ERR_SYNTAX_ERR: return "Syntax Error";
- case ERR_NOT_EQUAL: return "Not Equal";
- }
- return "???";
-}
-
static pj_uint32_t parse_len, parse_time, print_time;
-static pj_caching_pool cp;
/* URI creator functions. */
@@ -74,6 +56,9 @@ static pjsip_uri *create_uri18( pj_pool_t *pool );
static pjsip_uri *create_uri19( pj_pool_t *pool );
static pjsip_uri *create_dummy( pj_pool_t *pool );
+#define ERR_NOT_EQUAL -1001
+#define ERR_SYNTAX_ERR -1002
+
struct uri_test
{
pj_status_t status;
@@ -239,12 +224,7 @@ struct uri_test
ERR_SYNTAX_ERR,
"",
&create_dummy,
- },
- {
- PJ_SUCCESS,
- "",
- NULL,
- },
+ }
};
static pjsip_uri *create_uri1(pj_pool_t *pool)
@@ -476,47 +456,37 @@ static pjsip_uri *create_uri18(pj_pool_t *pool)
static pjsip_uri *create_dummy(pj_pool_t *pool)
{
- PJ_UNUSED_ARG(pool)
+ PJ_UNUSED_ARG(pool);
return NULL;
}
/*****************************************************************************/
-static void pool_error(pj_pool_t *pool, pj_size_t sz)
-{
- PJ_UNUSED_ARG(pool)
- PJ_UNUSED_ARG(sz)
-
- pj_assert(0);
- exit(1);
-}
-
/*
* Test one test entry.
*/
-static pj_status_t test_entry(struct uri_test *entry)
+static pj_status_t do_uri_test(pj_pool_t *pool, struct uri_test *entry)
{
pj_status_t status;
- pj_pool_t *pool;
int len;
pjsip_uri *parsed_uri, *ref_uri;
pj_str_t s1 = {NULL, 0}, s2 = {NULL, 0};
- pj_hr_timestamp t1, t2;
+ pj_timestamp t1, t2;
- pool = (*cp.factory.create_pool)( &cp.factory, "", POOL_SIZE, 0, &pool_error);
+ entry->len = pj_native_strlen(entry->str);
/* Parse URI text. */
- pj_hr_gettimestamp(&t1);
+ pj_get_timestamp(&t1);
parse_len += entry->len;
parsed_uri = pjsip_parse_uri(pool, entry->str, entry->len, 0);
if (!parsed_uri) {
/* Parsing failed. If the entry says that this is expected, then
* return OK.
*/
- status = entry->status==ERR_SYNTAX_ERR ? PJ_SUCCESS : ERR_SYNTAX_ERR;
+ status = entry->status==ERR_SYNTAX_ERR ? PJ_SUCCESS : -10;
goto on_return;
}
- pj_hr_gettimestamp(&t2);
+ pj_get_timestamp(&t2);
parse_time += t2.u32.lo - t1.u32.lo;
/* Create the reference URI. */
@@ -526,32 +496,32 @@ static pj_status_t test_entry(struct uri_test *entry)
s1.ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
s2.ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
- pj_hr_gettimestamp(&t1);
+ pj_get_timestamp(&t1);
len = pjsip_uri_print( PJSIP_URI_IN_OTHER, parsed_uri, s1.ptr, PJSIP_MAX_URL_SIZE);
if (len < 1) {
- status = -1;
+ status = -20;
goto on_return;
}
s1.slen = len;
len = pjsip_uri_print( PJSIP_URI_IN_OTHER, ref_uri, s2.ptr, PJSIP_MAX_URL_SIZE);
if (len < 1) {
- status = -1;
+ status = -30;
goto on_return;
}
s2.slen = len;
- pj_hr_gettimestamp(&t2);
+ pj_get_timestamp(&t2);
print_time += t2.u32.lo - t1.u32.lo;
/* Full comparison of parsed URI with reference URI. */
if (pjsip_uri_cmp(PJSIP_URI_IN_OTHER, parsed_uri, ref_uri) != 0) {
/* Not equal. See if this is the expected status. */
- status = entry->status==ERR_NOT_EQUAL ? PJ_SUCCESS : ERR_NOT_EQUAL;
+ status = entry->status==ERR_NOT_EQUAL ? PJ_SUCCESS : -40;
goto on_return;
} else {
/* Equal. See if this is the expected status. */
- status = entry->status==PJ_SUCCESS ? PJ_SUCCESS : -1;
+ status = entry->status==PJ_SUCCESS ? PJ_SUCCESS : -50;
if (status != PJ_SUCCESS) {
goto on_return;
}
@@ -560,101 +530,31 @@ static pj_status_t test_entry(struct uri_test *entry)
/* Compare text. */
if (pj_strcmp(&s1, &s2) != 0) {
/* Not equal. */
- status = ERR_NOT_EQUAL;
+ status = -60;
}
on_return:
- if (!SILENT) {
- printf("%.2d %s (expected status=%s)\n"
- " str=%s\n"
- " uri=%.*s\n"
- " ref=%.*s\n\n",
- entry-uri_test_array,
- STATUS_STR(status),
- STATUS_STR(entry->status),
- entry->str,
- (int)s1.slen, s1.ptr, (int)s2.slen, s2.ptr);
- }
-
- pj_pool_release(pool);
return status;
}
-static void warm_up(pj_pool_factory *pf)
+pj_status_t uri_test()
{
+ unsigned i;
pj_pool_t *pool;
- struct uri_test *entry;
-
- pool = pj_pool_create(pf, "", POOL_SIZE, 0, &pool_error);
- pjsip_parse_uri(pool, "sip:host", 8, 0);
- entry = &uri_test_array[0];
- while (entry->creator) {
- entry->len = strlen(entry->str);
- ++entry;
- }
- pj_pool_release(pool);
-}
-
-//#if !IS_PROFILING
-#if 1
-pj_status_t test_uri()
-{
- struct uri_test *entry;
- int i=0, err=0;
pj_status_t status;
- pj_hr_timestamp t1, t2;
- pj_uint32_t total_time;
-
- pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
- warm_up(&cp.factory);
-
- pj_hr_gettimestamp(&t1);
- for (i=0; i<LOOP; ++i) {
- entry = &uri_test_array[0];
- while (entry->creator) {
- status = test_entry(entry);
- if (status != PJ_SUCCESS) {
- ++err;
- }
- ++entry;
- }
- }
- pj_hr_gettimestamp(&t2);
- total_time = t2.u32.lo - t1.u32.lo;
-
- printf("Error=%d\n", err);
- printf("Total parse len: %u bytes\n", parse_len);
- printf("Total parse time: %u (%f/char), print time: %u (%f/char)\n",
- parse_time, parse_time*1.0/parse_len,
- print_time, print_time*1.0/parse_len);
- printf("Total time: %u (%f/char)\n", total_time, total_time*1.0/parse_len);
- return err;
-}
-
-#else
-
-pj_status_t test_uri()
-{
- struct uri_test *entry;
- unsigned i;
-
- warm_up();
- pj_caching_pool_init(&cp, 1024*1024);
- for (i=0; i<LOOP; ++i) {
- entry = &uri_test_array[0];
- while (entry->creator) {
- pj_pool_t *pool;
- pjsip_uri *uri1, *uri2;
+ pool = pjsip_endpt_create_pool(endpt, "", 4000, 4000);
- pool = pj_pool_create( &cp.factory, "", POOL_SIZE, 0, &pool_error);
- uri1 = pjsip_parse_uri(pool, entry->str, strlen(entry->str));
- pj_pool_release(pool);
- ++entry;
+ for (i=0; i<PJ_ARRAY_SIZE(uri_test_array); ++i) {
+ status = do_uri_test(pool, &uri_test_array[i]);
+ if (status != PJ_SUCCESS) {
+ PJ_LOG(3,("uri_test", " error %d when testing entry %d",
+ status, i));
+ break;
}
}
- return 0;
+ pjsip_endpt_destroy_pool(endpt, pool);
+ return status;
}
-#endif