summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2005-11-11 19:01:31 +0000
committerBenny Prijono <bennylp@teluu.com>2005-11-11 19:01:31 +0000
commit0b9e388f7f10dac01d5134ed6c1b24695810874e (patch)
treef01b4f05e8d074a8dba14a96b93803fd6797c105
parent0bc0f9112ac6319d7ce8662de86d6c076bd4b1e3 (diff)
First clean compile of pjsip
git-svn-id: http://svn.pjsip.org/repos/pjproject/main@43 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--RELNOTES.txt17
-rw-r--r--pjlib-util/include/pjlib-util/scanner.h235
-rw-r--r--pjlib-util/src/pjlib-util/scanner.c121
-rw-r--r--pjlib/build/pjlib.dsw12
-rw-r--r--pjlib/include/pj++/file.hpp342
-rw-r--r--pjlib/include/pj++/hash.hpp276
-rw-r--r--pjlib/include/pj++/list.hpp619
-rw-r--r--pjlib/include/pj++/lock.hpp263
-rw-r--r--pjlib/include/pj++/os.hpp1573
-rw-r--r--pjlib/include/pj++/pool.hpp505
-rw-r--r--pjlib/include/pj++/proactor.hpp1000
-rw-r--r--pjlib/include/pj++/scanner.hpp344
-rw-r--r--pjlib/include/pj++/sock.hpp851
-rw-r--r--pjlib/include/pj++/string.hpp815
-rw-r--r--pjlib/include/pj++/timer.hpp359
-rw-r--r--pjlib/include/pj++/tree.hpp222
-rw-r--r--pjlib/include/pj++/types.hpp286
-rw-r--r--pjlib/include/pj/compat/string.h9
-rw-r--r--pjlib/include/pj/config.h9
-rw-r--r--pjlib/include/pj/errno.h5
-rw-r--r--pjlib/include/pj/except.h1
-rw-r--r--pjlib/include/pj/hash.h15
-rw-r--r--pjlib/include/pj/ioqueue.h14
-rw-r--r--pjlib/include/pj/string.h3
-rw-r--r--pjlib/src/pj/errno.c3
-rw-r--r--pjlib/src/pj/hash.c14
-rw-r--r--pjlib/src/pj/ioqueue_common_abs.c8
-rw-r--r--pjlib/src/pj/ioqueue_winnt.c5
-rw-r--r--pjsip/build/TODO.txt21
-rw-r--r--pjsip/build/pjsip_core.dsp66
-rw-r--r--pjsip/build/pjsip_ua.dsp10
-rw-r--r--pjsip/build/tounix5
-rw-r--r--pjsip/include/pjsip/print_util.h (renamed from pjsip/src/pjsip/print.h)1
-rw-r--r--pjsip/include/pjsip/sip_auth.h5
-rw-r--r--pjsip/include/pjsip/sip_auth_msg.h5
-rw-r--r--pjsip/include/pjsip/sip_auth_parser.h7
-rw-r--r--pjsip/include/pjsip/sip_config.h2
-rw-r--r--pjsip/include/pjsip/sip_endpoint.h76
-rw-r--r--pjsip/include/pjsip/sip_errno.h86
-rw-r--r--pjsip/include/pjsip/sip_event.h241
-rw-r--r--pjsip/include/pjsip/sip_misc.h58
-rw-r--r--pjsip/include/pjsip/sip_module.h1
-rw-r--r--pjsip/include/pjsip/sip_msg.h35
-rw-r--r--pjsip/include/pjsip/sip_parser.h52
-rw-r--r--pjsip/include/pjsip/sip_private.h11
-rw-r--r--pjsip/include/pjsip/sip_resolve.h1
-rw-r--r--pjsip/include/pjsip/sip_transaction.h175
-rw-r--r--pjsip/include/pjsip/sip_transport.h55
-rw-r--r--pjsip/include/pjsip/sip_types.h27
-rw-r--r--pjsip/include/pjsip/sip_uri.h1
-rw-r--r--pjsip/include/pjsip_core.h1
-rw-r--r--pjsip/src/pjsip/sip_auth.c15
-rw-r--r--pjsip/src/pjsip/sip_auth_msg.c18
-rw-r--r--pjsip/src/pjsip/sip_auth_parser.c137
-rw-r--r--pjsip/src/pjsip/sip_endpoint.c256
-rw-r--r--pjsip/src/pjsip/sip_misc.c184
-rw-r--r--pjsip/src/pjsip/sip_msg.c5
-rw-r--r--pjsip/src/pjsip/sip_parser.c977
-rw-r--r--pjsip/src/pjsip/sip_resolve.c18
-rw-r--r--pjsip/src/pjsip/sip_transaction.c708
-rw-r--r--pjsip/src/pjsip/sip_transport.c679
-rw-r--r--pjsip/src/pjsip/sip_uri.c10
-rw-r--r--pjsip/src/pjsua/getopt.c4
-rw-r--r--pjsip/src/pjsua/main.c8
-rw-r--r--pjsip/src/pjsua/misc.c4
65 files changed, 6418 insertions, 5473 deletions
diff --git a/RELNOTES.txt b/RELNOTES.txt
index 1e884e38..e2baeb97 100644
--- a/RELNOTES.txt
+++ b/RELNOTES.txt
@@ -1,3 +1,20 @@
+Version 0.3
+PJLIB
+ - Correct error reporting in the whole library. No more vague -1 errors!
+ - New super portable socket abstraction.
+ - Other headers were made super portable too.
+ - Ioqueue supports multiple pending operations in a single socket!
+ - No more floating point.
+ - Ported to new platforms:
+ - i386/linux kernel (!)
+ - Sparc/Solaris
+ - Alpha/Linux
+PJSIP
+ - Correct error reporting in the whole library. No more -1 errors!
+ - Rewrote event, now much more readable.
+ - Per object tracing.
+
+
Version 0.2.9 - 2005/06/19
Core:
- Moved authentication stuff to core.
diff --git a/pjlib-util/include/pjlib-util/scanner.h b/pjlib-util/include/pjlib-util/scanner.h
index f1b0b133..711eeed7 100644
--- a/pjlib-util/include/pjlib-util/scanner.h
+++ b/pjlib-util/include/pjlib-util/scanner.h
@@ -1,9 +1,7 @@
/* $Id$
- *
*/
-
-#ifndef __PJ_PARSER_H__
-#define __PJ_PARSER_H__
+#ifndef __PJ_SCANNER_H__
+#define __PJ_SCANNER_H__
/**
* @file scanner.h
@@ -18,115 +16,175 @@ PJ_BEGIN_DECL
* @defgroup PJ_SCAN Text Scanning
* @ingroup PJ_MISC
* @brief
- * Text scanning utility.
- */
-
-/**
- * @defgroup PJ_CHARSPEC Character Filter Specification
- * @ingroup PJ_SCAN
- * @brief
- * The type pj_char_spec is a specification of character set used in
- * scanner. Application can define multiple character specs, such as to
- * scan alpha numerics, numbers, tokens, etc.
+ * Text scanning utility.
+ *
* @{
*/
+/**
+ * This describes the type of individual character specification in
+ * #pj_cis_buf_t. Basicly the number of bits here
+ */
+#ifndef PJ_CIS_ELEM_TYPE
+# define PJ_CIS_ELEM_TYPE pj_uint32_t
+#endif
+
/**
* This describes the type of individual character specification in
- * #pj_char_spec.
+ * #pj_cis_buf_t.
*/
-typedef pj_uint8_t pj_char_spec_element_t;
+typedef PJ_CIS_ELEM_TYPE pj_cis_elem_t;
+
+/**
+ * Maximum number of input specification in a buffer.
+ * Effectively this means the number of bits in pj_cis_elem_t.
+ */
+#define PJ_CIS_MAX_INDEX (sizeof(pj_cis_elem_t) << 3)
/**
- * The character specification is implemented as array of boolean flags. Each
- * flag indicates the membership of the character in the spec. If the flag
- * at one position is non-zero, then the character at that position belongs
- * to the specification, and vice versa.
- */
-typedef pj_char_spec_element_t pj_char_spec[256];
-// Note: it's got to be 256 (not 128) to cater for extended character in input.
+ * The scanner input specification buffer.
+ */
+typedef struct pj_cis_buf_t
+{
+ pj_cis_elem_t cis_buf[256]; /**< Must be 256 (not 128)! */
+ pj_cis_elem_t use_mask; /**< To keep used indexes. */
+} pj_cis_buf_t;
+
+/**
+ * Character input specification.
+ */
+typedef struct pj_cis_t
+{
+ pj_cis_elem_t *cis_buf; /**< Pointer to buffer. */
+ int cis_id; /**< Id. */
+} pj_cis_t;
/**
- * Initialize character spec.
- * @param cs the scanner character specification.
- */
-PJ_DECL(void) pj_cs_init( pj_char_spec cs);
+ * Initialize scanner input specification buffer.
+ *
+ * @param cs_buf The scanner character specification.
+ */
+PJ_DECL(void) pj_cis_buf_init(pj_cis_buf_t *cs_buf);
+
+/**
+ * Create a new input specification.
+ *
+ * @param cs_buf Specification buffer.
+ * @param cis Character input specification to be initialized.
+ *
+ * @return PJ_SUCCESS if new specification has been successfully
+ * created, or PJ_ETOOMANY if there are already too many
+ * specifications in the buffer.
+ */
+PJ_DECL(pj_status_t) pj_cis_init(pj_cis_buf_t *cs_buf, pj_cis_t *cis);
+
+/**
+ * Create a new input specification based on an existing specification.
+ *
+ * @param new_cis The new specification to be initialized.
+ * @param existing The existing specification, from which the input
+ * bitmask will be copied to the new specification.
+ *
+ * @return PJ_SUCCESS if new specification has been successfully
+ * created, or PJ_ETOOMANY if there are already too many
+ * specifications in the buffer.
+ */
+PJ_DECL(pj_status_t) pj_cis_dup(pj_cis_t *new_cis, pj_cis_t *existing);
/**
- * Set the membership of the specified character to TRUE.
- * @param cs the scanner character specification.
- * @param c the character.
- */
-PJ_DECL(void) pj_cs_set( pj_char_spec cs, int c);
+ * Set the membership of the specified character.
+ * Note that this is a macro, and arguments may be evaluated more than once.
+ *
+ * @param cis Pointer to character input specification.
+ * @param c The character.
+ */
+#define PJ_CIS_SET(cis,c) ((cis)->cis_buf[(c)] |= (1 << (cis)->cis_id))
+
+/**
+ * Remove the membership of the specified character.
+ * Note that this is a macro, and arguments may be evaluated more than once.
+ *
+ * @param cis Pointer to character input specification.
+ * @param c The character to be removed from the membership.
+ */
+#define PJ_CIS_CLR(cis,c) ((cis)->cis_buf[c] &= ~(1 << (cis)->cis_id))
+
+/**
+ * Check the membership of the specified character.
+ * Note that this is a macro, and arguments may be evaluated more than once.
+ *
+ * @param cis Pointer to character input specification.
+ * @param c The character.
+ */
+#define PJ_CIS_ISSET(cis,c) ((cis)->cis_buf[c] & (1 << (cis)->cis_id))
/**
* Add the characters in the specified range '[cstart, cend)' to the
- * specification (the last character itself ('cend') is not added).
- * @param cs the scanner character specification.
- * @param cstart the first character in the range.
- * @param cend the next character after the last character in the range.
+ * specification (the last character itself ('cend') is not added).
+ *
+ * @param cis The scanner character specification.
+ * @param cstart The first character in the range.
+ * @param cend The next character after the last character in the range.
*/
-PJ_DECL(void) pj_cs_add_range( pj_char_spec cs, int cstart, int cend);
+PJ_DECL(void) pj_cis_add_range( pj_cis_t *cis, int cstart, int cend);
/**
- * Add alphabetic characters to the specification.
- * @param cs the scanner character specification.
+ * Add alphabetic characters to the specification.
+ *
+ * @param cis The scanner character specification.
*/
-PJ_DECL(void) pj_cs_add_alpha( pj_char_spec cs);
+PJ_DECL(void) pj_cis_add_alpha( pj_cis_t *cis);
/**
- * Add numeric characters to the specification.
- * @param cs the scanner character specification.
+ * Add numeric characters to the specification.
+ *
+ * @param cis The scanner character specification.
*/
-PJ_DECL(void) pj_cs_add_num( pj_char_spec cs);
+PJ_DECL(void) pj_cis_add_num( pj_cis_t *cis);
/**
- * Add the characters in the string to the specification.
- * @param cs the scanner character specification.
- * @param str the string.
+ * Add the characters in the string to the specification.
+ *
+ * @param cis The scanner character specification.
+ * @param str The string.
*/
-PJ_DECL(void) pj_cs_add_str( pj_char_spec cs, const char *str);
+PJ_DECL(void) pj_cis_add_str( pj_cis_t *cis, const char *str);
/**
- * Delete characters in the specified range from the specification.
- * @param cs the scanner character specification.
- * @param cstart the first character in the range.
- * @param cend the next character after the last character in the range.
+ * Delete characters in the specified range from the specification.
+ *
+ * @param cis The scanner character specification.
+ * @param cstart The first character in the range.
+ * @param cend The next character after the last character in the range.
*/
-PJ_DECL(void) pj_cs_del_range( pj_char_spec cs, int cstart, int cend);
+PJ_DECL(void) pj_cis_del_range( pj_cis_t *cis, int cstart, int cend);
/**
- * Delete characters in the specified string from the specification.
- * @param cs the scanner character specification.
- * @param str the string.
+ * Delete characters in the specified string from the specification.
+ *
+ * @param cis The scanner character specification.
+ * @param str The string.
*/
-PJ_DECL(void) pj_cs_del_str( pj_char_spec cs, const char *str);
+PJ_DECL(void) pj_cis_del_str( pj_cis_t *cis, const char *str);
/**
- * Invert specification.
- * @param cs the scanner character specification.
+ * Invert specification.
+ *
+ * @param cis The scanner character specification.
*/
-PJ_DECL(void) pj_cs_invert( pj_char_spec cs );
+PJ_DECL(void) pj_cis_invert( pj_cis_t *cis );
/**
- * Check whether the specified character belongs to the specification.
- * @param cs the scanner character specification.
- * @param c the character to check for matching.
+ * Check whether the specified character belongs to the specification.
+ *
+ * @param cis The scanner character specification.
+ * @param c The character to check for matching.
*/
-PJ_INLINE(int) pj_cs_match( const pj_char_spec cs, int c )
+PJ_INLINE(int) pj_cis_match( const pj_cis_t *cis, int c )
{
- return cs[c];
+ return PJ_CIS_ISSET(cis, c);
}
-/**
- * @}
- */
-
-/**
- * @defgroup PJ_SCANNER Text Scanner
- * @ingroup PJ_SCAN
- * @{
- */
/**
* Flags for scanner.
@@ -155,8 +213,9 @@ struct pj_scanner;
/**
* The callback function type to be called by the scanner when it encounters
- * syntax error.
- * @param scanner The scanner instance that calls the callback .
+ * syntax error.
+ *
+ * @param scanner The scanner instance that calls the callback .
*/
typedef void (*pj_syn_err_func_ptr)(struct pj_scanner *scanner);
@@ -244,7 +303,7 @@ PJ_INLINE(int) pj_scan_is_eof( const pj_scanner *scanner)
* no more characters.
*/
PJ_DECL(int) pj_scan_peek( pj_scanner *scanner,
- const pj_char_spec spec, pj_str_t *out);
+ const pj_cis_t *spec, pj_str_t *out);
/**
@@ -261,7 +320,7 @@ PJ_DECL(int) pj_scan_peek( pj_scanner *scanner,
* no more characters.
*/
PJ_DECL(int) pj_scan_peek_n( pj_scanner *scanner,
- pj_size_t len, pj_str_t *out);
+ pj_size_t len, pj_str_t *out);
/**
@@ -277,8 +336,8 @@ PJ_DECL(int) pj_scan_peek_n( pj_scanner *scanner,
* @return the character right after the peek-ed position.
*/
PJ_DECL(int) pj_scan_peek_until( pj_scanner *scanner,
- const pj_char_spec spec,
- pj_str_t *out);
+ const pj_cis_t *spec,
+ pj_str_t *out);
/**
@@ -293,7 +352,7 @@ PJ_DECL(int) pj_scan_peek_until( pj_scanner *scanner,
* @param out String to store the result.
*/
PJ_DECL(void) pj_scan_get( pj_scanner *scanner,
- const pj_char_spec spec, pj_str_t *out);
+ const pj_cis_t *spec, pj_str_t *out);
/**
@@ -317,7 +376,7 @@ PJ_DECL(void) pj_scan_get_quote( pj_scanner *scanner,
* @param out String to store the result.
*/
PJ_DECL(void) pj_scan_get_n( pj_scanner *scanner,
- unsigned N, pj_str_t *out);
+ unsigned N, pj_str_t *out);
/**
@@ -325,7 +384,7 @@ PJ_DECL(void) pj_scan_get_n( pj_scanner *scanner,
*
* @param scanner The scanner.
*
- * @return (unknown)
+ * @return The character.
*/
PJ_DECL(int) pj_scan_get_char( pj_scanner *scanner );
@@ -348,7 +407,7 @@ PJ_DECL(void) pj_scan_get_newline( pj_scanner *scanner );
* @param out String to store the result.
*/
PJ_DECL(void) pj_scan_get_until( pj_scanner *scanner,
- const pj_char_spec spec, pj_str_t *out);
+ const pj_cis_t *spec, pj_str_t *out);
/**
@@ -360,7 +419,7 @@ PJ_DECL(void) pj_scan_get_until( pj_scanner *scanner,
* @param out String to store the result.
*/
PJ_DECL(void) pj_scan_get_until_ch( pj_scanner *scanner,
- int until_char, pj_str_t *out);
+ int until_char, pj_str_t *out);
/**
@@ -372,7 +431,7 @@ PJ_DECL(void) pj_scan_get_until_ch( pj_scanner *scanner,
* @param out String to store the result.
*/
PJ_DECL(void) pj_scan_get_until_chr( pj_scanner *scanner,
- const char *until_spec, pj_str_t *out);
+ const char *until_spec, pj_str_t *out);
/**
* Advance the scanner N characters, and skip whitespace
@@ -384,7 +443,7 @@ PJ_DECL(void) pj_scan_get_until_chr( pj_scanner *scanner,
* after skipping the characters.
*/
PJ_DECL(void) pj_scan_advance_n( pj_scanner *scanner,
- unsigned N, pj_bool_t skip);
+ unsigned N, pj_bool_t skip);
/**
@@ -445,10 +504,6 @@ PJ_DECL(void) pj_scan_restore_state( pj_scanner *scanner,
* @}
*/
-#if PJ_FUNCTIONS_ARE_INLINED
-# include "scanner_i.h"
-#endif
-
PJ_END_DECL
diff --git a/pjlib-util/src/pjlib-util/scanner.c b/pjlib-util/src/pjlib-util/scanner.c
index 65e3f351..0e753dfb 100644
--- a/pjlib-util/src/pjlib-util/scanner.c
+++ b/pjlib-util/src/pjlib-util/scanner.c
@@ -4,6 +4,7 @@
#include <pj/string.h>
#include <pj/except.h>
#include <pj/os.h>
+#include <pj/errno.h>
#define PJ_SCAN_IS_SPACE(c) ((c)==' ' || (c)=='\t')
#define PJ_SCAN_IS_NEWLINE(c) ((c)=='\r' || (c)=='\n')
@@ -15,67 +16,99 @@ static void pj_scan_syntax_err(pj_scanner *scanner)
(*scanner->callback)(scanner);
}
-PJ_DEF(void) pj_cs_init( pj_char_spec cs)
+PJ_DEF(void) pj_cis_buf_init( pj_cis_buf_t *cis_buf)
{
- PJ_CHECK_STACK();
- memset(cs, 0, sizeof(cs));
+ pj_memset(cis_buf->cis_buf, 0, sizeof(cis_buf->cis_buf));
+ cis_buf->use_mask = 0;
}
-
-PJ_DEF(void) pj_cs_set( pj_char_spec cs, int c)
+
+PJ_DEF(pj_status_t) pj_cis_init(pj_cis_buf_t *cis_buf, pj_cis_t *cis)
+{
+ unsigned i;
+
+ cis->cis_buf = cis_buf->cis_buf;
+
+ for (i=0; i<PJ_CIS_MAX_INDEX; ++i) {
+ if ((cis_buf->use_mask & (1 << i)) == 0) {
+ cis->cis_index = i;
+ return PJ_SUCCESS;
+ }
+ }
+
+ cis->cis_index = PJ_CIS_MAX_INDEX;
+ return PJ_ETOOMANY;
+}
+
+PJ_DEF(pj_status_t) pj_cis_dup( pj_cis_t *new_cis, pj_cis_t *existing)
+{
+ pj_status_t status;
+ unsigned i;
+
+ status = pj_cis_init(existing->cis_buf, new_cis);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ for (i=0; i<256; ++i) {
+ if (PJ_CIS_ISSET(existing, i))
+ PJ_CIS_SET(new_cis, i);
+ else
+ PJ_CIS_CLR(new_cis, i);
+ }
+
+ return PJ_SUCCESS;
+}
+
+PJ_DEF(void) pj_cis_add_range(pj_cis_t *cis, int cstart, int cend)
{
- PJ_CHECK_STACK();
- cs[c] = 1;
-}
-
-PJ_DEF(void) pj_cs_add_range( pj_char_spec cs, int cstart, int cend)
-{
- PJ_CHECK_STACK();
- while (cstart != cend)
- cs[cstart++] = 1;
+ while (cstart != cend) {
+ PJ_CIS_SET(cis, cstart);
+ ++cstart;
+ }
}
-PJ_DEF(void) pj_cs_add_alpha( pj_char_spec cs)
+PJ_DEF(void) pj_cis_add_alpha(pj_cis_t *cis)
{
- pj_cs_add_range( cs, 'a', 'z'+1);
- pj_cs_add_range( cs, 'A', 'Z'+1);
+ pj_cis_add_range( cis, 'a', 'z'+1);
+ pj_cis_add_range( cis, 'A', 'Z'+1);
}
-PJ_DEF(void) pj_cs_add_num( pj_char_spec cs)
+PJ_DEF(void) pj_cis_add_num(pj_cis_t *cis)
{
- pj_cs_add_range( cs, '0', '9'+1);
+ pj_cis_add_range( cis, '0', '9'+1);
}
-PJ_DEF(void) pj_cs_add_str( pj_char_spec cs, const char *str)
+PJ_DEF(void) pj_cis_add_str( pj_cis_t *cis, const char *str)
{
- PJ_CHECK_STACK();
while (*str) {
- cs[(int)*str] = 1;
+ PJ_CIS_SET(cis, *str);
++str;
}
}
-PJ_DEF(void) pj_cs_del_range( pj_char_spec cs, int cstart, int cend)
+PJ_DEF(void) pj_cis_del_range( pj_cis_t *cis, int cstart, int cend)
{
- PJ_CHECK_STACK();
- while (cstart != cend)
- cs[cstart++] = 0;
+ while (cstart != cend) {
+ PJ_CIS_CLR(cis, cstart);
+ cstart++;
+ }
}
-PJ_DEF(void) pj_cs_del_str( pj_char_spec cs, const char *str)
+PJ_DEF(void) pj_cis_del_str( pj_cis_t *cis, const char *str)
{
- PJ_CHECK_STACK();
while (*str) {
- cs[(int)*str] = 0;
+ PJ_CIS_CLR(cis, *str);
++str;
}
}
-PJ_DEF(void) pj_cs_invert( pj_char_spec cs )
+PJ_DEF(void) pj_cis_invert( pj_cis_t *cis )
{
unsigned i;
- PJ_CHECK_STACK();
- for (i=0; i<sizeof(pj_char_spec)/sizeof(cs[0]); ++i) {
- cs[i] = (pj_char_spec_element_t) !cs[i];
+ for (i=0; i<256; ++i) {
+ if (PJ_CIS_ISSET(cis,i))
+ PJ_CIS_CLR(cis,i);
+ else
+ PJ_CIS_SET(cis,i);
}
}
@@ -165,7 +198,7 @@ PJ_DEF(void) pj_scan_skip_whitespace( pj_scanner *scanner )
}
PJ_DEF(int) pj_scan_peek( pj_scanner *scanner,
- const pj_char_spec spec, pj_str_t *out)
+ const pj_cis_t *spec, pj_str_t *out)
{
register char *s = scanner->curptr;
register char *end = scanner->end;
@@ -177,7 +210,7 @@ PJ_DEF(int) pj_scan_peek( pj_scanner *scanner,
return -1;
}
- while (PJ_SCAN_CHECK_EOF(s) && pj_cs_match(spec, *s))
+ while (PJ_SCAN_CHECK_EOF(s) && pj_cis_match(spec, *s))
++s;
pj_strset3(out, scanner->curptr, s);
@@ -203,8 +236,8 @@ PJ_DEF(int) pj_scan_peek_n( pj_scanner *scanner,
PJ_DEF(int) pj_scan_peek_until( pj_scanner *scanner,
- const pj_char_spec spec,
- pj_str_t *out)
+ const pj_cis_t *spec,
+ pj_str_t *out)
{
register char *s = scanner->curptr;
register char *end = scanner->end;
@@ -216,7 +249,7 @@ PJ_DEF(int) pj_scan_peek_until( pj_scanner *scanner,
return -1;
}
- while (PJ_SCAN_CHECK_EOF(s) && !pj_cs_match( spec, *s))
+ while (PJ_SCAN_CHECK_EOF(s) && !pj_cis_match( spec, *s))
++s;
pj_strset3(out, scanner->curptr, s);
@@ -225,7 +258,7 @@ PJ_DEF(int) pj_scan_peek_until( pj_scanner *scanner,
PJ_DEF(void) pj_scan_get( pj_scanner *scanner,
- const pj_char_spec spec, pj_str_t *out)
+ const pj_cis_t *spec, pj_str_t *out)
{
register char *s = scanner->curptr;
register char *end = scanner->end;
@@ -233,14 +266,14 @@ PJ_DEF(void) pj_scan_get( pj_scanner *scanner,
PJ_CHECK_STACK();
- if (pj_scan_is_eof(scanner) || !pj_cs_match(spec, *s)) {
+ if (pj_scan_is_eof(scanner) || !pj_cis_match(spec, *s)) {
pj_scan_syntax_err(scanner);
return;
}
do {
++s;
- } while (PJ_SCAN_CHECK_EOF(s) && pj_cs_match(spec, *s));
+ } while (PJ_SCAN_CHECK_EOF(s) && pj_cis_match(spec, *s));
pj_strset3(out, scanner->curptr, s);
@@ -395,7 +428,7 @@ PJ_DEF(void) pj_scan_get_newline( pj_scanner *scanner )
PJ_DEF(void) pj_scan_get_until( pj_scanner *scanner,
- const pj_char_spec spec, pj_str_t *out)
+ const pj_cis_t *spec, pj_str_t *out)
{
register char *s = scanner->curptr;
register char *end = scanner->end;
@@ -408,7 +441,7 @@ PJ_DEF(void) pj_scan_get_until( pj_scanner *scanner,
return;
}
- while (PJ_SCAN_CHECK_EOF(s) && !pj_cs_match(spec, *s)) {
+ while (PJ_SCAN_CHECK_EOF(s) && !pj_cis_match(spec, *s)) {
++s;
}
@@ -424,7 +457,7 @@ PJ_DEF(void) pj_scan_get_until( pj_scanner *scanner,
PJ_DEF(void) pj_scan_get_until_ch( pj_scanner *scanner,
- int until_char, pj_str_t *out)
+ int until_char, pj_str_t *out)
{
register char *s = scanner->curptr;
register char *end = scanner->end;
diff --git a/pjlib/build/pjlib.dsw b/pjlib/build/pjlib.dsw
index 41d8c9e0..aa45adf6 100644
--- a/pjlib/build/pjlib.dsw
+++ b/pjlib/build/pjlib.dsw
@@ -27,7 +27,7 @@ Package=<4>
###############################################################################
-Project: "pjlib_samples"=.\pjlib_samples.dsp - Package Owner=<4>
+Project: "pjlib++_test"=".\pjlib++-test.dsp" - Package Owner=<4>
Package=<5>
{{{
@@ -38,11 +38,14 @@ Package=<4>
Begin Project Dependency
Project_Dep_Name pjlib
End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name pjlib++
+ End Project Dependency
}}}
###############################################################################
-Project: "pjlib_test"=.\pjlib_test.dsp - Package Owner=<4>
+Project: "pjlib_samples"=.\pjlib_samples.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -57,7 +60,7 @@ Package=<4>
###############################################################################
-Project: "pjlib++_test"=.\pjlib++-test.dsp - Package Owner=<4>
+Project: "pjlib_test"=.\pjlib_test.dsp - Package Owner=<4>
Package=<5>
{{{
@@ -68,9 +71,6 @@ Package=<4>
Begin Project Dependency
Project_Dep_Name pjlib
End Project Dependency
- Begin Project Dependency
- Project_Dep_Name pjlib++
- End Project Dependency
}}}
###############################################################################
diff --git a/pjlib/include/pj++/file.hpp b/pjlib/include/pj++/file.hpp
index dfd78d51..e45810c5 100644
--- a/pjlib/include/pj++/file.hpp
+++ b/pjlib/include/pj++/file.hpp
@@ -1,171 +1,171 @@
-/* $Id$ */
-
-#ifndef __PJPP_FILE_HPP__
-#define __PJPP_FILE_HPP__
-
-#include <pj/file_io.h>
-#include <pj/file_access.h>
-#include <pj++/types.hpp>
-#include <pj++/pool.hpp>
-
-//
-// File API.
-//
-class Pj_File_API
-{
-public:
- //
- // Check file existance.
- //
- static bool file_exists(const char *filename)
- {
- return pj_file_exists(filename) != 0;
- }
-
- //
- // Get file size.
- //
- static pj_off_t file_size(const char *filename)
- {
- return pj_file_size(filename);
- }
-
- //
- // Delete file.
- //
- static pj_status_t file_delete(const char *filename)
- {
- return pj_file_delete(filename);
- }
-
- //
- // Move/rename file.
- //
- static pj_status_t file_move(const char *oldname, const char *newname)
- {
- return pj_file_move(oldname, newname);
- }
-
- //
- // Get stat.
- //
- static pj_status_t file_stat(const char *filename, pj_file_stat *buf)
- {
- return pj_file_getstat(filename, buf);
- }
-};
-
-
-//
-// File.
-//
-class Pj_File : public Pj_Object
-{
-public:
- //
- // Offset type to be used in setpos.
- //
- enum Offset_Type
- {
- SEEK_SET = PJ_SEEK_SET,
- SEEK_CUR = PJ_SEEK_CUR,
- SEEK_END = PJ_SEEK_END,
- };
-
- //
- // Default constructor.
- //
- Pj_File()
- : hnd_(0)
- {
- }
-
- //
- // Construct and open a file.
- //
- Pj_File(Pj_Pool *pool, const char *filename,
- unsigned access = PJ_O_RDONLY)
- : hnd_(NULL)
- {
- open(pool, filename, access);
- }
-
- //
- // Destructor closes the file.
- //
- ~Pj_File()
- {
- close();
- }
-
- //
- // Open a file.
- //
- pj_status_t open(Pj_Pool *pool, const char *filename,
- unsigned access = PJ_O_RDONLY )
- {
- close();
- return pj_file_open(pool->pool_(), filename, access, &hnd_);
- }
-
- //
- // Close a file.
- //
- void close()
- {
- if (hnd_ != 0) {
- pj_file_close(hnd_);
- hnd_ = 0;
- }
- }
-
- //
- // Write data.
- //
- pj_ssize_t write(const void *buff, pj_size_t size)
- {
- pj_ssize_t bytes = size;
- if (pj_file_write(hnd_, buff, &bytes) != PJ_SUCCESS)
- return -1;
- return bytes;
- }
-
- //
- // Read data.
- //
- pj_ssize_t read(void *buf, pj_size_t size)
- {
- pj_ssize_t bytes = size;
- if (pj_file_read(hnd_, buf, &bytes) != PJ_SUCCESS)
- return -1;
- return bytes;
- }
-
- //
- // Set file position.
- //
- pj_status_t setpos(pj_off_t offset, Offset_Type whence)
- {
- return pj_file_setpos(hnd_, offset,
- (enum pj_file_seek_type)whence);
- }
-
- //
- // Get file position.
- //
- pj_off_t getpos()
- {
- pj_off_t pos;
- if (pj_file_getpos(hnd_, &pos) != PJ_SUCCESS)
- return -1;
- return pos;
- }
-
-private:
- pj_oshandle_t hnd_;
-};
-
-
-
-#endif /* __PJPP_FILE_HPP__ */
-
+/* $Id$
+ */
+#ifndef __PJPP_FILE_HPP__
+#define __PJPP_FILE_HPP__
+
+#include <pj/file_io.h>
+#include <pj/file_access.h>
+#include <pj++/types.hpp>
+#include <pj++/pool.hpp>
+
+//
+// File API.
+//
+class Pj_File_API
+{
+public:
+ //
+ // Check file existance.
+ //
+ static bool file_exists(const char *filename)
+ {
+ return pj_file_exists(filename) != 0;
+ }
+
+ //
+ // Get file size.
+ //
+ static pj_off_t file_size(const char *filename)
+ {
+ return pj_file_size(filename);
+ }
+
+ //
+ // Delete file.
+ //
+ static pj_status_t file_delete(const char *filename)
+ {
+ return pj_file_delete(filename);
+ }
+
+ //
+ // Move/rename file.
+ //
+ static pj_status_t file_move(const char *oldname, const char *newname)
+ {
+ return pj_file_move(oldname, newname);
+ }
+
+ //
+ // Get stat.
+ //
+ static pj_status_t file_stat(const char *filename, pj_file_stat *buf)
+ {
+ return pj_file_getstat(filename, buf);
+ }
+};
+
+
+//
+// File.
+//
+class Pj_File : public Pj_Object
+{
+public:
+ //
+ // Offset type to be used in setpos.
+ //
+ enum Offset_Type
+ {
+ SEEK_SET = PJ_SEEK_SET,
+ SEEK_CUR = PJ_SEEK_CUR,
+ SEEK_END = PJ_SEEK_END,
+ };
+
+ //
+ // Default constructor.
+ //
+ Pj_File()
+ : hnd_(0)
+ {
+ }
+
+ //
+ // Construct and open a file.
+ //
+ Pj_File(Pj_Pool *pool, const char *filename,
+ unsigned access = PJ_O_RDONLY)
+ : hnd_(NULL)
+ {
+ open(pool, filename, access);
+ }
+
+ //
+ // Destructor closes the file.
+ //
+ ~Pj_File()
+ {
+ close();
+ }
+
+ //
+ // Open a file.
+ //
+ pj_status_t open(Pj_Pool *pool, const char *filename,
+ unsigned access = PJ_O_RDONLY )
+ {
+ close();
+ return pj_file_open(pool->pool_(), filename, access, &hnd_);
+ }
+
+ //
+ // Close a file.
+ //
+ void close()
+ {
+ if (hnd_ != 0) {
+ pj_file_close(hnd_);
+ hnd_ = 0;
+ }
+ }
+
+ //
+ // Write data.
+ //
+ pj_ssize_t write(const void *buff, pj_size_t size)
+ {
+ pj_ssize_t bytes = size;
+ if (pj_file_write(hnd_, buff, &bytes) != PJ_SUCCESS)
+ return -1;
+ return bytes;
+ }
+
+ //
+ // Read data.
+ //
+ pj_ssize_t read(void *buf, pj_size_t size)
+ {
+ pj_ssize_t bytes = size;
+ if (pj_file_read(hnd_, buf, &bytes) != PJ_SUCCESS)
+ return -1;
+ return bytes;
+ }
+
+ //
+ // Set file position.
+ //
+ pj_status_t setpos(pj_off_t offset, Offset_Type whence)
+ {
+ return pj_file_setpos(hnd_, offset,
+ (enum pj_file_seek_type)whence);
+ }
+
+ //
+ // Get file position.
+ //
+ pj_off_t getpos()
+ {
+ pj_off_t pos;
+ if (pj_file_getpos(hnd_, &pos) != PJ_SUCCESS)
+ return -1;
+ return pos;
+ }
+
+private:
+ pj_oshandle_t hnd_;
+};
+
+
+
+#endif /* __PJPP_FILE_HPP__ */
+
diff --git a/pjlib/include/pj++/hash.hpp b/pjlib/include/pj++/hash.hpp
index 6d4a5e68..691ac3a8 100644
--- a/pjlib/include/pj++/hash.hpp
+++ b/pjlib/include/pj++/hash.hpp
@@ -1,139 +1,139 @@
/* $Id$
- */
-#ifndef __PJPP_HASH_H__
-#define __PJPP_HASH_H__
-
-#include <pj++/types.hpp>
-#include <pj++/pool.hpp>
-#include <pj/hash.h>
-
-//
-// Hash table.
-//
-class Pj_Hash_Table : public Pj_Object
-{
-public:
- //
- // Hash table iterator.
- //
- class iterator
- {
- public:
- iterator()
- {
- }
- explicit iterator(pj_hash_table_t *h, pj_hash_iterator_t *i)
- : ht_(h), it_(i)
- {
- }
- iterator(const iterator &rhs)
- : ht_(rhs.ht_), it_(rhs.it_)
- {
- }
- void operator++()
- {
- it_ = pj_hash_next(ht_, it_);
- }
- bool operator==(const iterator &rhs)
- {
- return ht_ == rhs.ht_ && it_ == rhs.it_;
- }
- iterator & operator=(const iterator &rhs)
- {
- ht_=rhs.ht_; it_=rhs.it_;
- return *this;
- }
- private:
- pj_hash_table_t *ht_;
- pj_hash_iterator_t it_val_;
- pj_hash_iterator_t *it_;
-
- friend class Pj_Hash_Table;
- };
-
- //
- // Construct hash table.
- //
- Pj_Hash_Table(Pj_Pool *pool, unsigned size)
- {
- table_ = pj_hash_create(pool->pool_(), size);
- }
-
- //
- // Destroy hash table.
- //
- ~Pj_Hash_Table()
- {
- }
-
- //
- // Calculate hash value.
- //
- static pj_uint32_t calc( pj_uint32_t initial_hval,
- const void *key,
- unsigned keylen = PJ_HASH_KEY_STRING)
- {
- return pj_hash_calc(initial_hval, key, keylen);
- }
-
- //
- // Return pjlib compatible hash table object.
- //
- pj_hash_table_t *pj_hash_table_t_()
- {
- return table_;
- }
-
- //
- // Get the value associated with the specified key.
- //
- void *get(const void *key, unsigned keylen = PJ_HASH_KEY_STRING)
- {
- return pj_hash_get(table_, key, keylen);
- }
-
- //
- // Associate a value with a key.
- // Set the value to NULL to delete the key from the hash table.
- //
- void set(Pj_Pool *pool,
- const void *key,
- void *value,
- unsigned keylen = PJ_HASH_KEY_STRING)
- {
- pj_hash_set(pool->pool_(), table_, key, keylen, value);
- }
-
- //
- // Get number of items in the hash table.
- //
- unsigned count()
- {
- return pj_hash_count(table_);
- }
-
- //
- // Iterate hash table.
- //
- iterator begin()
- {
- iterator it(table_, NULL);
- it.it_ = pj_hash_first(table_, &it.it_val_);
- return it;
- }
-
- //
- // End of items.
- //
- iterator end()
- {
- return iterator(table_, NULL);
- }
-
-private:
- pj_hash_table_t *table_;
-};
-
-
-#endif /* __PJPP_HASH_H__ */
-
+ */
+#ifndef __PJPP_HASH_HPP__
+#define __PJPP_HASH_HPP__
+
+#include <pj++/types.hpp>
+#include <pj++/pool.hpp>
+#include <pj/hash.h>
+
+//
+// Hash table.
+//
+class Pj_Hash_Table : public Pj_Object
+{
+public:
+ //
+ // Hash table iterator.
+ //
+ class iterator
+ {
+ public:
+ iterator()
+ {
+ }
+ explicit iterator(pj_hash_table_t *h, pj_hash_iterator_t *i)
+ : ht_(h), it_(i)
+ {
+ }
+ iterator(const iterator &rhs)
+ : ht_(rhs.ht_), it_(rhs.it_)
+ {
+ }
+ void operator++()
+ {
+ it_ = pj_hash_next(ht_, it_);
+ }
+ bool operator==(const iterator &rhs)
+ {
+ return ht_ == rhs.ht_ && it_ == rhs.it_;
+ }
+ iterator & operator=(const iterator &rhs)
+ {
+ ht_=rhs.ht_; it_=rhs.it_;
+ return *this;
+ }
+ private:
+ pj_hash_table_t *ht_;
+ pj_hash_iterator_t it_val_;
+ pj_hash_iterator_t *it_;
+
+ friend class Pj_Hash_Table;
+ };
+
+ //
+ // Construct hash table.
+ //
+ Pj_Hash_Table(Pj_Pool *pool, unsigned size)
+ {
+ table_ = pj_hash_create(pool->pool_(), size);
+ }
+
+ //
+ // Destroy hash table.
+ //
+ ~Pj_Hash_Table()
+ {
+ }
+
+ //
+ // Calculate hash value.
+ //
+ static pj_uint32_t calc( pj_uint32_t initial_hval,
+ const void *key,
+ unsigned keylen = PJ_HASH_KEY_STRING)
+ {
+ return pj_hash_calc(initial_hval, key, keylen);
+ }
+
+ //
+ // Return pjlib compatible hash table object.
+ //
+ pj_hash_table_t *pj_hash_table_t_()
+ {
+ return table_;
+ }
+
+ //
+ // Get the value associated with the specified key.
+ //
+ void *get(const void *key, unsigned keylen = PJ_HASH_KEY_STRING)
+ {
+ return pj_hash_get(table_, key, keylen);
+ }
+
+ //
+ // Associate a value with a key.
+ // Set the value to NULL to delete the key from the hash table.
+ //
+ void set(Pj_Pool *pool,
+ const void *key,
+ void *value,
+ unsigned keylen = PJ_HASH_KEY_STRING)
+ {
+ pj_hash_set(pool->pool_(), table_, key, keylen, value);
+ }
+
+ //
+ // Get number of items in the hash table.
+ //
+ unsigned count()
+ {
+ return pj_hash_count(table_);
+ }
+
+ //
+ // Iterate hash table.
+ //
+ iterator begin()
+ {
+ iterator it(table_, NULL);
+ it.it_ = pj_hash_first(table_, &it.it_val_);
+ return it;
+ }
+
+ //
+ // End of items.
+ //
+ iterator end()
+ {
+ return iterator(table_, NULL);
+ }
+
+private:
+ pj_hash_table_t *table_;
+};
+
+
+#endif /* __PJPP_HASH_HPP__ */
+
diff --git a/pjlib/include/pj++/list.hpp b/pjlib/include/pj++/list.hpp
index 9895c1c2..c3a8f386 100644
--- a/pjlib/include/pj++/list.hpp
+++ b/pjlib/include/pj++/list.hpp
@@ -1,310 +1,311 @@
/* $Id$
- */
-#ifndef __PJPP_LIST_H__
-#define __PJPP_LIST_H__
-
-#include <pj/list.h>
-#include <pj++/pool.hpp>
-
-
-//
-// Linked-list.
-//
-// Note:
-// List_Node must have public member next and prev. Normally
-// it will be declared like:
-//
-// struct my_node
-// {
-// PJ_DECL_LIST_MEMBER(struct my_node);
-// ..
-// };
-//
-//
-template <class List_Node>
-class Pj_List : public Pj_Object
-{
-public:
- //
- // List const_iterator.
- //
- class const_iterator
- {
- public:
- const_iterator()
- : node_(NULL)
- {}
- const_iterator(const List_Node *nd)
- : node_((List_Node*)nd)
- {}
- const List_Node * operator *()
- {
- return node_;
- }
- const List_Node * operator -> ()
- {
- return node_;
- }
- const_iterator operator++()
- {
- return const_iterator(node_->next);
- }
- bool operator==(const const_iterator &rhs)
- {
- return node_ == rhs.node_;
- }
- bool operator!=(const const_iterator &rhs)
- {
- return node_ != rhs.node_;
- }
-
- protected:
- List_Node *node_;
- };
-
- //
- // List iterator.
- //
- class iterator : public const_iterator
- {
- public:
- iterator()
- {}
- iterator(List_Node *nd)
- : const_iterator(nd)
- {}
- List_Node * operator *()
- {
- return node_;
- }
- List_Node * operator -> ()
- {
- return node_;
- }
- iterator operator++()
- {
- return iterator(node_->next);
- }
- bool operator==(const iterator &rhs)
- {
- return node_ == rhs.node_;
- }
- bool operator!=(const iterator &rhs)
- {
- return node_ != rhs.node_;
- }
- };
-
- //
- // Default constructor.
- //
- Pj_List()
- {
- pj_list_init(&root_);
- if (0) compiletest();
- }
-
- //
- // Check if list is empty.
- //
- bool empty() const
- {
- return pj_list_empty(&root_);
- }
-
- //
- // Get first element.
- //
- iterator begin()
- {
- return iterator(root_.next);
- }
-
- //
- // Get first element.
- //
- const_iterator begin() const
- {
- return const_iterator(root_.next);
- }
-
- //
- // Get end-of-element
- //
- const_iterator end() const
- {
- return const_iterator((List_Node*)&root_);
- }
-
- //
- // Get end-of-element
- //
- iterator end()
- {
- return iterator((List_Node*)&root_);
- }
-
- //
- // Insert node.
- //
- void insert_before (iterator &pos, List_Node *node)
- {
- pj_list_insert_before( *pos, node );
- }
-
- //
- // Insert node.
- //
- void insert_after(iterator &pos, List_Node *node)
- {
- pj_list_insert_after(*pos, node);
- }
-
- //
- // Merge list.
- //
- void merge_first(List_Node *list2)
- {
- pj_list_merge_first(&root_, list2);
- }
-
- //
- // Merge list.
- //
- void merge_last(Pj_List *list)
- {
- pj_list_merge_last(&root_, &list->root_);
- }
-
- //
- // Insert list.
- //
- void insert_nodes_before(iterator &pos, Pj_List *list2)
- {
- pj_list_insert_nodes_before(*pos, &list2->root_);
- }
-
- //
- // Insert list.
- //
- void insert_nodes_after(iterator &pos, Pj_List *list2)
- {
- pj_list_insert_nodes_after(*pos, &list2->root_);
- }
-
- //
- // Erase an element.
- //
- void erase(iterator &it)
- {
- pj_list_erase(*it);
- }
-
- //
- // Get first element.
- //
- List_Node *front()
- {
- return root_.next;
- }
-
- //
- // Get first element.
- //
- const List_Node *front() const
- {
- return root_.next;
- }
-
- //
- // Remove first element.
- //
- void pop_front()
- {
- pj_list_erase(root_.next);
- }
-
- //
- // Get last element.
- //
- List_Node *back()
- {
- return root_.prev;
- }
-
- //
- // Get last element.
- //
- const List_Node *back() const
- {
- return root_.prev;
- }
-
- //
- // Remove last element.
- //
- void pop_back()
- {
- pj_list_erase(root_.prev);
- }
-
- //
- // Find a node.
- //
- iterator find(List_Node *node)
- {
- List_Node *n = pj_list_find_node(&root_, node);
- return n ? iterator(n) : end();
- }
-
- //
- // Find a node.
- //
- const_iterator find(List_Node *node) const
- {
- List_Node *n = pj_list_find_node(&root_, node);
- return n ? const_iterator(n) : end();
- }
-
- //
- // Insert a node in the back.
- //
- void push_back(List_Node *node)
- {
- pj_list_insert_after(root_.prev, node);
- }
-
- //
- // Insert a node in the front.
- //
- void push_front(List_Node *node)
- {
- pj_list_insert_before(root_.next, node);
- }
-
- //
- // Remove all elements.
- //
- void clear()
- {
- root_.next = &root_;
- root_.prev = &root_;
- }
-
-private:
- struct RootNode
- {
- PJ_DECL_LIST_MEMBER(List_Node);
- } root_;
-
- void compiletest()
- {
- // If you see error in this line,
- // it's because List_Node is not derived from Pj_List_Node.
- List_Node *n = (List_Node*)0;
- n = n->next; n = n->prev;
- }
-};
-
-
-#endif /* __PJPP_LIST_H__ */
+ */
+#ifndef __PJPP_LIST_HPP__
+#define __PJPP_LIST_HPP__
+
+#include <pj/list.h>
+#include <pj++/pool.hpp>
+
+
+//
+// Linked-list.
+//
+// Note:
+// List_Node must have public member next and prev. Normally
+// it will be declared like:
+//
+// struct my_node
+// {
+// PJ_DECL_LIST_MEMBER(struct my_node);
+// ..
+// };
+//
+//
+template <class List_Node>
+class Pj_List : public Pj_Object
+{
+public:
+ //
+ // List const_iterator.
+ //
+ class const_iterator
+ {
+ public:
+ const_iterator()
+ : node_(NULL)
+ {}
+ const_iterator(const List_Node *nd)
+ : node_((List_Node*)nd)
+ {}
+ const List_Node * operator *()
+ {
+ return node_;
+ }
+ const List_Node * operator -> ()
+ {
+ return node_;
+ }
+ const_iterator operator++()
+ {
+ return const_iterator(node_->next);
+ }
+ bool operator==(const const_iterator &rhs)
+ {
+ return node_ == rhs.node_;
+ }
+ bool operator!=(const const_iterator &rhs)
+ {
+ return node_ != rhs.node_;
+ }
+
+ protected:
+ List_Node *node_;
+ };
+
+ //
+ // List iterator.
+ //
+ class iterator : public const_iterator
+ {
+ public:
+ iterator()
+ {}
+ iterator(List_Node *nd)
+ : const_iterator(nd)
+ {}
+ List_Node * operator *()
+ {
+ return node_;
+ }
+ List_Node * operator -> ()
+ {
+ return node_;
+ }
+ iterator operator++()
+ {
+ return iterator(node_->next);
+ }
+ bool operator==(const iterator &rhs)
+ {
+ return node_ == rhs.node_;
+ }
+ bool operator!=(const iterator &rhs)
+ {
+ return node_ != rhs.node_;
+ }
+ };
+
+ //
+ // Default constructor.
+ //
+ Pj_List()
+ {
+ pj_list_init(&root_);
+ if (0) compiletest();
+ }
+
+ //
+ // Check if list is empty.
+ //
+ bool empty() const
+ {
+ return pj_list_empty(&root_);
+ }
+
+ //
+ // Get first element.
+ //
+ iterator begin()
+ {
+ return iterator(root_.next);
+ }
+
+ //
+ // Get first element.
+ //
+ const_iterator begin() const
+ {
+ return const_iterator(root_.next);
+ }
+
+ //
+ // Get end-of-element
+ //
+ const_iterator end() const
+ {
+ return const_iterator((List_Node*)&root_);
+ }
+
+ //
+ // Get end-of-element
+ //
+ iterator end()
+ {
+ return iterator((List_Node*)&root_);
+ }
+
+ //
+ // Insert node.
+ //
+ void insert_before (iterator &pos, List_Node *node)
+ {
+ pj_list_insert_before( *pos, node );
+ }
+
+ //
+ // Insert node.
+ //
+ void insert_after(iterator &pos, List_Node *node)
+ {
+ pj_list_insert_after(*pos, node);
+ }
+
+ //
+ // Merge list.
+ //
+ void merge_first(List_Node *list2)
+ {
+ pj_list_merge_first(&root_, list2);
+ }
+
+ //
+ // Merge list.
+ //
+ void merge_last(Pj_List *list)
+ {
+ pj_list_merge_last(&root_, &list->root_);
+ }
+
+ //
+ // Insert list.
+ //
+ void insert_nodes_before(iterator &pos, Pj_List *list2)
+ {
+ pj_list_insert_nodes_before(*pos, &list2->root_);
+ }
+
+ //
+ // Insert list.
+ //
+ void insert_nodes_after(iterator &pos, Pj_List *list2)
+ {
+ pj_list_insert_nodes_after(*pos, &list2->root_);
+ }
+
+ //
+ // Erase an element.
+ //
+ void erase(iterator &it)
+ {
+ pj_list_erase(*it);
+ }
+
+ //
+ // Get first element.
+ //
+ List_Node *front()
+ {
+ return root_.next;
+ }
+
+ //
+ // Get first element.
+ //
+ const List_Node *front() const
+ {
+ return root_.next;
+ }
+
+ //
+ // Remove first element.
+ //
+ void pop_front()
+ {
+ pj_list_erase(root_.next);
+ }
+
+ //
+ // Get last element.
+ //
+ List_Node *back()
+ {
+ return root_.prev;
+ }
+
+ //
+ // Get last element.
+ //
+ const List_Node *back() const
+ {
+ return root_.prev;
+ }
+
+ //
+ // Remove last element.
+ //
+ void pop_back()
+ {
+ pj_list_erase(root_.prev);
+ }
+
+ //
+ // Find a node.
+ //
+ iterator find(List_Node *node)
+ {
+ List_Node *n = pj_list_find_node(&root_, node);
+ return n ? iterator(n) : end();
+ }
+
+ //
+ // Find a node.
+ //
+ const_iterator find(List_Node *node) const
+ {
+ List_Node *n = pj_list_find_node(&root_, node);
+ return n ? const_iterator(n) : end();
+ }
+
+ //
+ // Insert a node in the back.
+ //
+ void push_back(List_Node *node)
+ {
+ pj_list_insert_after(root_.prev, node);
+ }
+
+ //
+ // Insert a node in the front.
+ //
+ void push_front(List_Node *node)
+ {
+ pj_list_insert_before(root_.next, node);
+ }
+
+ //
+ // Remove all elements.
+ //
+ void clear()
+ {
+ root_.next = &root_;
+ root_.prev = &root_;
+ }
+
+private:
+ struct RootNode
+ {
+ PJ_DECL_LIST_MEMBER(List_Node);
+ } root_;
+
+ void compiletest()
+ {
+ // If you see error in this line,
+ // it's because List_Node is not derived from Pj_List_Node.
+ List_Node *n = (List_Node*)0;
+ n = n->next; n = n->prev;
+ }
+};
+
+
+#endif /* __PJPP_LIST_HPP__ */
+
diff --git a/pjlib/include/pj++/lock.hpp b/pjlib/include/pj++/lock.hpp
index 93a435e6..95ea63b6 100644
--- a/pjlib/include/pj++/lock.hpp
+++ b/pjlib/include/pj++/lock.hpp
@@ -1,131 +1,132 @@
-/* $Id$ */
-#ifndef __PJPP_LOCK_H__
-#define __PJPP_LOCK_H__
-
-#include <pj++/types.hpp>
-#include <pj/lock.h>
-#include <pj++/pool.hpp>
-
-//////////////////////////////////////////////////////////////////////////////
-// Lock object.
-//
-class Pj_Lock : public Pj_Object
-{
-public:
- //
- // Constructor.
- //
- explicit Pj_Lock(pj_lock_t *lock)
- : lock_(lock)
- {
- }
-
- //
- // Destructor.
- //
- ~Pj_Lock()
- {
- if (lock_)
- pj_lock_destroy(lock_);
- }
-
- //
- // Get pjlib compatible lock object.
- //
- pj_lock_t *pj_lock_t_()
- {
- return lock_;
- }
-
- //
- // acquire lock.
- //
- pj_status_t acquire()
- {
- return pj_lock_acquire(lock_);
- }
-
- //
- // release lock,.
- //
- pj_status_t release()
- {
- return pj_lock_release(lock_);
- }
-
-protected:
- pj_lock_t *lock_;
-};
-
-
-//////////////////////////////////////////////////////////////////////////////
-// Null lock object.
-//
-class Pj_Null_Lock : public Pj_Lock
-{
-public:
- //
- // Default constructor.
- //
- explicit Pj_Null_Lock(Pj_Pool *pool, const char *name = NULL)
- : Pj_Lock(NULL)
- {
- pj_lock_create_null_mutex(pool->pool_(), name, &lock_);
- }
-};
-
-//////////////////////////////////////////////////////////////////////////////
-// Simple mutex lock object.
-//
-class Pj_Simple_Mutex_Lock : public Pj_Lock
-{
-public:
- //
- // Default constructor.
- //
- explicit Pj_Simple_Mutex_Lock(Pj_Pool *pool, const char *name = NULL)
- : Pj_Lock(NULL)
- {
- pj_lock_create_simple_mutex(pool->pool_(), name, &lock_);
- }
-};
-
-//////////////////////////////////////////////////////////////////////////////
-// Recursive mutex lock object.
-//
-class Pj_Recursive_Mutex_Lock : public Pj_Lock
-{
-public:
- //
- // Default constructor.
- //
- explicit Pj_Recursive_Mutex_Lock(Pj_Pool *pool, const char *name = NULL)
- : Pj_Lock(NULL)
- {
- pj_lock_create_recursive_mutex(pool->pool_(), name, &lock_);
- }
-};
-
-//////////////////////////////////////////////////////////////////////////////
-// Semaphore lock object.
-//
-class Pj_Semaphore_Lock : public Pj_Lock
-{
-public:
- //
- // Default constructor.
- //
- explicit Pj_Semaphore_Lock(Pj_Pool *pool,
- unsigned max=PJ_MAXINT32,
- unsigned initial=0,
- const char *name=NULL)
- : Pj_Lock(NULL)
- {
- pj_lock_create_semaphore(pool->pool_(), name, initial, max, &lock_);
- }
-};
-
-
-
-#endif /* __PJPP_LOCK_H__ */
-
+/* $Id$
+ */
+#ifndef __PJPP_LOCK_HPP__
+#define __PJPP_LOCK_HPP__
+
+#include <pj++/types.hpp>
+#include <pj/lock.h>
+#include <pj++/pool.hpp>
+
+//////////////////////////////////////////////////////////////////////////////
+// Lock object.
+//
+class Pj_Lock : public Pj_Object
+{
+public:
+ //
+ // Constructor.
+ //
+ explicit Pj_Lock(pj_lock_t *lock)
+ : lock_(lock)
+ {
+ }
+
+ //
+ // Destructor.
+ //
+ ~Pj_Lock()
+ {
+ if (lock_)
+ pj_lock_destroy(lock_);
+ }
+
+ //
+ // Get pjlib compatible lock object.
+ //
+ pj_lock_t *pj_lock_t_()
+ {
+ return lock_;
+ }
+
+ //
+ // acquire lock.
+ //
+ pj_status_t acquire()
+ {
+ return pj_lock_acquire(lock_);
+ }
+
+ //
+ // release lock,.
+ //
+ pj_status_t release()
+ {
+ return pj_lock_release(lock_);
+ }
+
+protected:
+ pj_lock_t *lock_;
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Null lock object.
+//
+class Pj_Null_Lock : public Pj_Lock
+{
+public:
+ //
+ // Default constructor.
+ //
+ explicit Pj_Null_Lock(Pj_Pool *pool, const char *name = NULL)
+ : Pj_Lock(NULL)
+ {
+ pj_lock_create_null_mutex(pool->pool_(), name, &lock_);
+ }
+};
+
+//////////////////////////////////////////////////////////////////////////////
+// Simple mutex lock object.
+//
+class Pj_Simple_Mutex_Lock : public Pj_Lock
+{
+public:
+ //
+ // Default constructor.
+ //
+ explicit Pj_Simple_Mutex_Lock(Pj_Pool *pool, const char *name = NULL)
+ : Pj_Lock(NULL)
+ {
+ pj_lock_create_simple_mutex(pool->pool_(), name, &lock_);
+ }
+};
+
+//////////////////////////////////////////////////////////////////////////////
+// Recursive mutex lock object.
+//
+class Pj_Recursive_Mutex_Lock : public Pj_Lock
+{
+public:
+ //
+ // Default constructor.
+ //
+ explicit Pj_Recursive_Mutex_Lock(Pj_Pool *pool, const char *name = NULL)
+ : Pj_Lock(NULL)
+ {
+ pj_lock_create_recursive_mutex(pool->pool_(), name, &lock_);
+ }
+};
+
+//////////////////////////////////////////////////////////////////////////////
+// Semaphore lock object.
+//
+class Pj_Semaphore_Lock : public Pj_Lock
+{
+public:
+ //
+ // Default constructor.
+ //
+ explicit Pj_Semaphore_Lock(Pj_Pool *pool,
+ unsigned max=PJ_MAXINT32,
+ unsigned initial=0,
+ const char *name=NULL)
+ : Pj_Lock(NULL)
+ {
+ pj_lock_create_semaphore(pool->pool_(), name, initial, max, &lock_);
+ }
+};
+
+
+
+#endif /* __PJPP_LOCK_HPP__ */
+
diff --git a/pjlib/include/pj++/os.hpp b/pjlib/include/pj++/os.hpp
index 1101daea..461a36e8 100644
--- a/pjlib/include/pj++/os.hpp
+++ b/pjlib/include/pj++/os.hpp
@@ -1,787 +1,788 @@
/* $Id$
- */
-#ifndef __PJPP_OS_H__
-#define __PJPP_OS_H__
-
-#include <pj/os.h>
-#include <pj++/types.hpp>
-#include <pj++/pool.hpp>
-
-class Pj_Thread;
-
-//
-// Thread API.
-//
-class Pj_Thread_API
-{
-public:
- //
- // Create a thread.
- //
- static pj_status_t create( Pj_Pool *pool, pj_thread_t **thread,
- pj_thread_proc *proc, void *arg,
- unsigned flags = 0,
- const char *name = NULL,
- pj_size_t stack_size = 0 )
- {
- return pj_thread_create(pool->pool_(), name, proc, arg, stack_size,
- flags, thread);
- }
-
- //
- // Register a thread.
- //
- static pj_status_t register_this_thread( pj_thread_desc desc,
- pj_thread_t **thread,
- const char *name = NULL )
- {
- return pj_thread_register( name, desc, thread );
- }
-
- //
- // Get current thread.
- // Will return pj_thread_t (sorry folks, not Pj_Thread).
- //
- static pj_thread_t *this_thread()
- {
- return pj_thread_this();
- }
-
- //
- // Get thread name.
- //
- static const char *get_name(pj_thread_t *thread)
- {
- return pj_thread_get_name(thread);
- }
-
- //
- // Resume thread.
- //
- static pj_status_t resume(pj_thread_t *thread)
- {
- return pj_thread_resume(thread);
- }
-
- //
- // Sleep.
- //
- static pj_status_t sleep(unsigned msec)
- {
- return pj_thread_sleep(msec);
- }
-
- //
- // Join the specified thread.
- //
- static pj_status_t join(pj_thread_t *thread)
- {
- return pj_thread_join(thread);
- }
-
- //
- // Destroy thread
- //
- static pj_status_t destroy(pj_thread_t *thread)
- {
- return pj_thread_destroy(thread);
- }
-};
-
-
-
-//
-// Thread object.
-//
-// How to use:
-// Derive a class from this class, then override main().
-//
-class Pj_Thread : public Pj_Object
-{
-public:
- enum Flags
- {
- FLAG_SUSPENDED = PJ_THREAD_SUSPENDED
- };
-
- //
- // Default constructor.
- //
- Pj_Thread()
- : thread_(NULL)
- {
- }
-
- //
- // Destroy thread.
- //
- ~Pj_Thread()
- {
- destroy();
- }
-
- //
- // This is the main thread function.
- //
- virtual int main() = 0;
-
- //
- // Start a thread.
- //
- pj_status_t create( Pj_Pool *pool,
- unsigned flags = 0,
- const char *thread_name = NULL,
- pj_size_t stack_size = PJ_THREAD_DEFAULT_STACK_SIZE)
- {
- destroy();
- return Pj_Thread_API::create( pool, &thread_, &thread_proc, this,
- flags, thread_name);
- }
-
- //
- // Get pjlib compatible thread object.
- //
- pj_thread_t *pj_thread_t_()
- {
- return thread_;
- }
-
- //
- // Get thread name.
- //
- const char *get_name()
- {
- return Pj_Thread_API::get_name(thread_);
- }
-
- //
- // Resume a suspended thread.
- //
- pj_status_t resume()
- {
- return Pj_Thread_API::resume(thread_);
- }
-
- //
- // Join this thread.
- //
- pj_status_t join()
- {
- return Pj_Thread_API::join(thread_);
- }
-
- //
- // Destroy thread.
- //
- pj_status_t destroy()
- {
- if (thread_) {
- Pj_Thread_API::destroy(thread_);
- thread_ = NULL;
- }
- }
-
-protected:
- pj_thread_t *thread_;
-
- static int PJ_THREAD_FUNC thread_proc(void *obj)
- {
- Pj_Thread *thread_class = (Pj_Thread*)obj;
- return thread_class->main();
- }
-};
-
-
-//
-// External Thread
-// (threads that were started by external means, i.e. not
-// with Pj_Thread::create).
-//
-// This class will normally be defined as local variable in
-// external thread's stack, normally inside thread's main proc.
-// But be aware that the handle will be destroyed on destructor!
-//
-class Pj_External_Thread : public Pj_Thread
-{
-public:
- Pj_External_Thread()
- {
- }
-
- //
- // Register external thread so that pjlib functions can work
- // in that thread.
- //
- pj_status_t register_this_thread( const char *name=NULL )
- {
- return Pj_Thread_API::register_this_thread(desc_, &thread_,name);
- }
-
-private:
- pj_thread_desc desc_;
-};
-
-
-//
-// Thread specific data/thread local storage/TLS.
-//
-class Pj_Thread_Local_API
-{
-public:
- //
- // Allocate thread local storage (TLS) index.
- //
- static pj_status_t alloc(long *index)
- {
- return pj_thread_local_alloc(index);
- }
-
- //
- // Free TLS index.
- //
- static void free(long index)
- {
- pj_thread_local_free(index);
- }
-
- //
- // Set thread specific data.
- //
- static pj_status_t set(long index, void *value)
- {
- return pj_thread_local_set(index, value);
- }
-
- //
- // Get thread specific data.
- //
- static void *get(long index)
- {
- return pj_thread_local_get(index);
- }
-
-};
-
-//
-// Atomic variable
-//
-// How to use:
-// Pj_Atomic_Var var(pool, 0);
-// var.set(..);
-//
-class Pj_Atomic_Var : public Pj_Object
-{
-public:
- //
- // Default constructor, initialize variable with NULL.
- //
- Pj_Atomic_Var()
- : var_(NULL)
- {
- }
-
- //
- // Construct atomic variable.
- //
- Pj_Atomic_Var(Pj_Pool *pool, pj_atomic_value_t value)
- : var_(NULL)
- {
- create(pool, value);
- }
-
- //
- // Destructor.
- //
- ~Pj_Atomic_Var()
- {
- destroy();
- }
-
- //
- // Create atomic variable.
- //
- pj_status_t create( Pj_Pool *pool, pj_atomic_value_t value)
- {
- destroy();
- return pj_atomic_create(pool->pool_(), value, &var_);
- }
-
- //
- // Destroy.
- //
- void destroy()
- {
- if (var_) {
- pj_atomic_destroy(var_);
- var_ = NULL;
- }
- }
-
- //
- // Get pjlib compatible atomic variable.
- //
- pj_atomic_t *pj_atomic_t_()
- {
- return var_;
- }
-
- //
- // Set the value.
- //
- void set(pj_atomic_value_t val)
- {
- pj_atomic_set(var_, val);
- }
-
- //
- // Get the value.
- //
- pj_atomic_value_t get()
- {
- return pj_atomic_get(var_);
- }
-
- //
- // Increment.
- //
- void inc()
- {
- pj_atomic_inc(var_);
- }
-
- //
- // Increment and get the result.
- //
- pj_atomic_value_t inc_and_get()
- {
- return pj_atomic_inc_and_get(var_);
- }
-
- //
- // Decrement.
- //
- void dec()
- {
- pj_atomic_dec(var_);
- }
-
- //
- // Decrement and get the result.
- //
- pj_atomic_value_t dec_and_get()
- {
- return pj_atomic_dec_and_get(var_);
- }
-
- //
- // Add the variable.
- //
- void add(pj_atomic_value_t value)
- {
- pj_atomic_add(var_, value);
- }
-
- //
- // Add the variable and get the value.
- //
- pj_atomic_value_t add_and_get(pj_atomic_value_t value)
- {
- return pj_atomic_add_and_get(var_, value );
- }
-
-private:
- pj_atomic_t *var_;
-};
-
-
-//
-// Mutex
-//
-class Pj_Mutex : public Pj_Object
-{
-public:
- //
- // Mutex type.
- //
- enum Type
- {
- DEFAULT = PJ_MUTEX_DEFAULT,
- SIMPLE = PJ_MUTEX_SIMPLE,
- RECURSE = PJ_MUTEX_RECURSE,
- };
-
- //
- // Default constructor will create default mutex.
- //
- explicit Pj_Mutex(Pj_Pool *pool, Type type = DEFAULT,
- const char *name = NULL)
- : mutex_(NULL)
- {
- create(pool, type, name);
- }
-
- //
- // Destructor.
- //
- ~Pj_Mutex()
- {
- destroy();
- }
-
- //
- // Create mutex.
- //
- pj_status_t create( Pj_Pool *pool, Type type, const char *name = NULL)
- {
- destroy();
- return pj_mutex_create( pool->pool_(), name, type,
- &mutex_ );
- }
-
- //
- // Create simple mutex.
- //
- pj_status_t create_simple( Pj_Pool *pool,const char *name = NULL)
- {
- return create(pool, SIMPLE, name);
- }
-
- //
- // Create recursive mutex.
- //
- pj_status_t create_recursive( Pj_Pool *pool, const char *name = NULL )
- {
- return create(pool, RECURSE, name);
- }
-
- //
- // Get pjlib compatible mutex object.
- //
- pj_mutex_t *pj_mutex_t_()
- {
- return mutex_;
- }
-
- //
- // Destroy mutex.
- //
- void destroy()
- {
- if (mutex_) {
- pj_mutex_destroy(mutex_);
- mutex_ = NULL;
- }
- }
-
- //
- // Lock mutex.
- //
- pj_status_t acquire()
- {
- return pj_mutex_lock(mutex_);
- }
-
- //
- // Unlock mutex.
- //
- pj_status_t release()
- {
- return pj_mutex_unlock(mutex_);
- }
-
- //
- // Try locking the mutex.
- //
- pj_status_t tryacquire()
- {
- return pj_mutex_trylock(mutex_);
- }
-
-private:
- pj_mutex_t *mutex_;
-};
-
-
-//
-// Semaphore
-//
-class Pj_Semaphore : public Pj_Object
-{
-public:
- //
- // Construct semaphore
- //
- Pj_Semaphore(Pj_Pool *pool, unsigned max,
- unsigned initial = 0, const char *name = NULL)
- : sem_(NULL)
- {
- }
-
- //
- // Destructor.
- //
- ~Pj_Semaphore()
- {
- destroy();
- }
-
- //
- // Create semaphore
- //
- pj_status_t create( Pj_Pool *pool, unsigned max,
- unsigned initial = 0, const char *name = NULL )
- {
- destroy();
- return pj_sem_create( pool->pool_(), name, initial, max, &sem_);
- }
-
- //
- // Destroy semaphore.
- //
- void destroy()
- {
- if (sem_) {
- pj_sem_destroy(sem_);
- sem_ = NULL;
- }
- }
-
- //
- // Get pjlib compatible semaphore object.
- //
- pj_sem_t *pj_sem_t_()
- {
- return (pj_sem_t*)this;
- }
-
- //
- // Wait semaphore.
- //
- pj_status_t wait()
- {
- return pj_sem_wait(this->pj_sem_t_());
- }
-
- //
- // Wait semaphore.
- //
- pj_status_t acquire()
- {
- return wait();
- }
-
- //
- // Try wait semaphore.
- //
- pj_status_t trywait()
- {
- return pj_sem_trywait(this->pj_sem_t_());
- }
-
- //
- // Try wait semaphore.
- //
- pj_status_t tryacquire()
- {
- return trywait();
- }
-
- //
- // Post semaphore.
- //
- pj_status_t post()
- {
- return pj_sem_post(this->pj_sem_t_());
- }
-
- //
- // Post semaphore.
- //
- pj_status_t release()
- {
- return post();
- }
-
-private:
- pj_sem_t *sem_;
-};
-
-
-//
-// Event object.
-//
-class Pj_Event
-{
-public:
- //
- // Construct event object.
- //
- Pj_Event( Pj_Pool *pool, bool manual_reset = false,
- bool initial = false, const char *name = NULL )
- : event_(NULL)
- {
- create(pool, manual_reset, initial, name);
- }
-
- //
- // Destructor.
- //
- ~Pj_Event()
- {
- destroy();
- }
-
- //
- // Create event object.
- //
- pj_status_t create( Pj_Pool *pool, bool manual_reset = false,
- bool initial = false, const char *name = NULL)
- {
- destroy();
- return pj_event_create(pool->pool_(), name, manual_reset, initial,
- &event_);
- }
-
- //
- // Get pjlib compatible event object.
- //
- pj_event_t *pj_event_t_()
- {
- return event_;
- }
-
- //
- // Destroy event object.
- //
- void destroy()
- {
- if (event_) {
- pj_event_destroy(event_);
- event_ = NULL;
- }
- }
-
- //
- // Wait.
- //
- pj_status_t wait()
- {
- return pj_event_wait(event_);
- }
-
- //
- // Try wait.
- //
- pj_status_t trywait()
- {
- return pj_event_trywait(event_);
- }
-
- //
- // Set event state to signalled.
- //
- pj_status_t set()
- {
- return pj_event_set(this->pj_event_t_());
- }
-
- //
- // Release one waiting thread.
- //
- pj_status_t pulse()
- {
- return pj_event_pulse(this->pj_event_t_());
- }
-
- //
- // Set a non-signalled.
- //
- pj_status_t reset()
- {
- return pj_event_reset(this->pj_event_t_());
- }
-
-private:
- pj_event_t *event_;
-};
-
-//
-// OS abstraction.
-//
-class Pj_OS_API
-{
-public:
- //
- // Get current time.
- //
- static pj_status_t gettimeofday( Pj_Time_Val *tv )
- {
- return pj_gettimeofday(tv);
- }
-
- //
- // Parse to time of day.
- //
- static pj_status_t time_decode( const Pj_Time_Val *tv,
- pj_parsed_time *pt )
- {
- return pj_time_decode(tv, pt);
- }
-
- //
- // Parse from time of day.
- //
- static pj_status_t time_encode( const pj_parsed_time *pt,
- Pj_Time_Val *tv)
- {
- return pj_time_encode(pt, tv);
- }
-
- //
- // Convert to GMT.
- //
- static pj_status_t time_local_to_gmt( Pj_Time_Val *tv )
- {
- return pj_time_local_to_gmt( tv );
- }
-
- //
- // Convert time to local.
- //
- static pj_status_t time_gmt_to_local( Pj_Time_Val *tv)
- {
- return pj_time_gmt_to_local( tv );
- }
-};
-
-//
-// Timeval inlines.
-//
-inline pj_status_t Pj_Time_Val::gettimeofday()
-{
- return Pj_OS_API::gettimeofday(this);
-}
-
-inline pj_parsed_time Pj_Time_Val::decode()
-{
- pj_parsed_time pt;
- Pj_OS_API::time_decode(this, &pt);
- return pt;
-}
-
-inline pj_status_t Pj_Time_Val::encode(const pj_parsed_time *pt)
-{
- return Pj_OS_API::time_encode(pt, this);
-}
-
-inline pj_status_t Pj_Time_Val::to_gmt()
-{
- return Pj_OS_API::time_local_to_gmt(this);
-}
-
-inline pj_status_t Pj_Time_Val::to_local()
-{
- return Pj_OS_API::time_gmt_to_local(this);
-}
-
-#endif /* __PJPP_OS_H__ */
+ */
+#ifndef __PJPP_OS_HPP__
+#define __PJPP_OS_HPP__
+
+#include <pj/os.h>
+#include <pj++/types.hpp>
+#include <pj++/pool.hpp>
+
+class Pj_Thread;
+
+//
+// Thread API.
+//
+class Pj_Thread_API
+{
+public:
+ //
+ // Create a thread.
+ //
+ static pj_status_t create( Pj_Pool *pool, pj_thread_t **thread,
+ pj_thread_proc *proc, void *arg,
+ unsigned flags = 0,
+ const char *name = NULL,
+ pj_size_t stack_size = 0 )
+ {
+ return pj_thread_create(pool->pool_(), name, proc, arg, stack_size,
+ flags, thread);
+ }
+
+ //
+ // Register a thread.
+ //
+ static pj_status_t register_this_thread( pj_thread_desc desc,
+ pj_thread_t **thread,
+ const char *name = NULL )
+ {
+ return pj_thread_register( name, desc, thread );
+ }
+
+ //
+ // Get current thread.
+ // Will return pj_thread_t (sorry folks, not Pj_Thread).
+ //
+ static pj_thread_t *this_thread()
+ {
+ return pj_thread_this();
+ }
+
+ //
+ // Get thread name.
+ //
+ static const char *get_name(pj_thread_t *thread)
+ {
+ return pj_thread_get_name(thread);
+ }
+
+ //
+ // Resume thread.
+ //
+ static pj_status_t resume(pj_thread_t *thread)
+ {
+ return pj_thread_resume(thread);
+ }
+
+ //
+ // Sleep.
+ //
+ static pj_status_t sleep(unsigned msec)
+ {
+ return pj_thread_sleep(msec);
+ }
+
+ //
+ // Join the specified thread.
+ //
+ static pj_status_t join(pj_thread_t *thread)
+ {
+ return pj_thread_join(thread);
+ }
+
+ //
+ // Destroy thread
+ //
+ static pj_status_t destroy(pj_thread_t *thread)
+ {
+ return pj_thread_destroy(thread);
+ }
+};
+
+
+
+//
+// Thread object.
+//
+// How to use:
+// Derive a class from this class, then override main().
+//
+class Pj_Thread : public Pj_Object
+{
+public:
+ enum Flags
+ {
+ FLAG_SUSPENDED = PJ_THREAD_SUSPENDED
+ };
+
+ //
+ // Default constructor.
+ //
+ Pj_Thread()
+ : thread_(NULL)
+ {
+ }
+
+ //
+ // Destroy thread.
+ //
+ ~Pj_Thread()
+ {
+ destroy();
+ }
+
+ //
+ // This is the main thread function.
+ //
+ virtual int main() = 0;
+
+ //
+ // Start a thread.
+ //
+ pj_status_t create( Pj_Pool *pool,
+ unsigned flags = 0,
+ const char *thread_name = NULL,
+ pj_size_t stack_size = PJ_THREAD_DEFAULT_STACK_SIZE)
+ {
+ destroy();
+ return Pj_Thread_API::create( pool, &thread_, &thread_proc, this,
+ flags, thread_name);
+ }
+
+ //
+ // Get pjlib compatible thread object.
+ //
+ pj_thread_t *pj_thread_t_()
+ {
+ return thread_;
+ }
+
+ //
+ // Get thread name.
+ //
+ const char *get_name()
+ {
+ return Pj_Thread_API::get_name(thread_);
+ }
+
+ //
+ // Resume a suspended thread.
+ //
+ pj_status_t resume()
+ {
+ return Pj_Thread_API::resume(thread_);
+ }
+
+ //
+ // Join this thread.
+ //
+ pj_status_t join()
+ {
+ return Pj_Thread_API::join(thread_);
+ }
+
+ //
+ // Destroy thread.
+ //
+ pj_status_t destroy()
+ {
+ if (thread_) {
+ Pj_Thread_API::destroy(thread_);
+ thread_ = NULL;
+ }
+ }
+
+protected:
+ pj_thread_t *thread_;
+
+ static int PJ_THREAD_FUNC thread_proc(void *obj)
+ {
+ Pj_Thread *thread_class = (Pj_Thread*)obj;
+ return thread_class->main();
+ }
+};
+
+
+//
+// External Thread
+// (threads that were started by external means, i.e. not
+// with Pj_Thread::create).
+//
+// This class will normally be defined as local variable in
+// external thread's stack, normally inside thread's main proc.
+// But be aware that the handle will be destroyed on destructor!
+//
+class Pj_External_Thread : public Pj_Thread
+{
+public:
+ Pj_External_Thread()
+ {
+ }
+
+ //
+ // Register external thread so that pjlib functions can work
+ // in that thread.
+ //
+ pj_status_t register_this_thread( const char *name=NULL )
+ {
+ return Pj_Thread_API::register_this_thread(desc_, &thread_,name);
+ }
+
+private:
+ pj_thread_desc desc_;
+};
+
+
+//
+// Thread specific data/thread local storage/TLS.
+//
+class Pj_Thread_Local_API
+{
+public:
+ //
+ // Allocate thread local storage (TLS) index.
+ //
+ static pj_status_t alloc(long *index)
+ {
+ return pj_thread_local_alloc(index);
+ }
+
+ //
+ // Free TLS index.
+ //
+ static void free(long index)
+ {
+ pj_thread_local_free(index);
+ }
+
+ //
+ // Set thread specific data.
+ //
+ static pj_status_t set(long index, void *value)
+ {
+ return pj_thread_local_set(index, value);
+ }
+
+ //
+ // Get thread specific data.
+ //
+ static void *get(long index)
+ {
+ return pj_thread_local_get(index);
+ }
+
+};
+
+//
+// Atomic variable
+//
+// How to use:
+// Pj_Atomic_Var var(pool, 0);
+// var.set(..);
+//
+class Pj_Atomic_Var : public Pj_Object
+{
+public:
+ //
+ // Default constructor, initialize variable with NULL.
+ //
+ Pj_Atomic_Var()
+ : var_(NULL)
+ {
+ }
+
+ //
+ // Construct atomic variable.
+ //
+ Pj_Atomic_Var(Pj_Pool *pool, pj_atomic_value_t value)
+ : var_(NULL)
+ {
+ create(pool, value);
+ }
+
+ //
+ // Destructor.
+ //
+ ~Pj_Atomic_Var()
+ {
+ destroy();
+ }
+
+ //
+ // Create atomic variable.
+ //
+ pj_status_t create( Pj_Pool *pool, pj_atomic_value_t value)
+ {
+ destroy();
+ return pj_atomic_create(pool->pool_(), value, &var_);
+ }
+
+ //
+ // Destroy.
+ //
+ void destroy()
+ {
+ if (var_) {
+ pj_atomic_destroy(var_);
+ var_ = NULL;
+ }
+ }
+
+ //
+ // Get pjlib compatible atomic variable.
+ //
+ pj_atomic_t *pj_atomic_t_()
+ {
+ return var_;
+ }
+
+ //
+ // Set the value.
+ //
+ void set(pj_atomic_value_t val)
+ {
+ pj_atomic_set(var_, val);
+ }
+
+ //
+ // Get the value.
+ //
+ pj_atomic_value_t get()
+ {
+ return pj_atomic_get(var_);
+ }
+
+ //
+ // Increment.
+ //
+ void inc()
+ {
+ pj_atomic_inc(var_);
+ }
+
+ //
+ // Increment and get the result.
+ //
+ pj_atomic_value_t inc_and_get()
+ {
+ return pj_atomic_inc_and_get(var_);
+ }
+
+ //
+ // Decrement.
+ //
+ void dec()
+ {
+ pj_atomic_dec(var_);
+ }
+
+ //
+ // Decrement and get the result.
+ //
+ pj_atomic_value_t dec_and_get()
+ {
+ return pj_atomic_dec_and_get(var_);
+ }
+
+ //
+ // Add the variable.
+ //
+ void add(pj_atomic_value_t value)
+ {
+ pj_atomic_add(var_, value);
+ }
+
+ //
+ // Add the variable and get the value.
+ //
+ pj_atomic_value_t add_and_get(pj_atomic_value_t value)
+ {
+ return pj_atomic_add_and_get(var_, value );
+ }
+
+private:
+ pj_atomic_t *var_;
+};
+
+
+//
+// Mutex
+//
+class Pj_Mutex : public Pj_Object
+{
+public:
+ //
+ // Mutex type.
+ //
+ enum Type
+ {
+ DEFAULT = PJ_MUTEX_DEFAULT,
+ SIMPLE = PJ_MUTEX_SIMPLE,
+ RECURSE = PJ_MUTEX_RECURSE,
+ };
+
+ //
+ // Default constructor will create default mutex.
+ //
+ explicit Pj_Mutex(Pj_Pool *pool, Type type = DEFAULT,
+ const char *name = NULL)
+ : mutex_(NULL)
+ {
+ create(pool, type, name);
+ }
+
+ //
+ // Destructor.
+ //
+ ~Pj_Mutex()
+ {
+ destroy();
+ }
+
+ //
+ // Create mutex.
+ //
+ pj_status_t create( Pj_Pool *pool, Type type, const char *name = NULL)
+ {
+ destroy();
+ return pj_mutex_create( pool->pool_(), name, type,
+ &mutex_ );
+ }
+
+ //
+ // Create simple mutex.
+ //
+ pj_status_t create_simple( Pj_Pool *pool,const char *name = NULL)
+ {
+ return create(pool, SIMPLE, name);
+ }
+
+ //
+ // Create recursive mutex.
+ //
+ pj_status_t create_recursive( Pj_Pool *pool, const char *name = NULL )
+ {
+ return create(pool, RECURSE, name);
+ }
+
+ //
+ // Get pjlib compatible mutex object.
+ //
+ pj_mutex_t *pj_mutex_t_()
+ {
+ return mutex_;
+ }
+
+ //
+ // Destroy mutex.
+ //
+ void destroy()
+ {
+ if (mutex_) {
+ pj_mutex_destroy(mutex_);
+ mutex_ = NULL;
+ }
+ }
+
+ //
+ // Lock mutex.
+ //
+ pj_status_t acquire()
+ {
+ return pj_mutex_lock(mutex_);
+ }
+
+ //
+ // Unlock mutex.
+ //
+ pj_status_t release()
+ {
+ return pj_mutex_unlock(mutex_);
+ }
+
+ //
+ // Try locking the mutex.
+ //
+ pj_status_t tryacquire()
+ {
+ return pj_mutex_trylock(mutex_);
+ }
+
+private:
+ pj_mutex_t *mutex_;
+};
+
+
+//
+// Semaphore
+//
+class Pj_Semaphore : public Pj_Object
+{
+public:
+ //
+ // Construct semaphore
+ //
+ Pj_Semaphore(Pj_Pool *pool, unsigned max,
+ unsigned initial = 0, const char *name = NULL)
+ : sem_(NULL)
+ {
+ }
+
+ //
+ // Destructor.
+ //
+ ~Pj_Semaphore()
+ {
+ destroy();
+ }
+
+ //
+ // Create semaphore
+ //
+ pj_status_t create( Pj_Pool *pool, unsigned max,
+ unsigned initial = 0, const char *name = NULL )
+ {
+ destroy();
+ return pj_sem_create( pool->pool_(), name, initial, max, &sem_);
+ }
+
+ //
+ // Destroy semaphore.
+ //
+ void destroy()
+ {
+ if (sem_) {
+ pj_sem_destroy(sem_);
+ sem_ = NULL;
+ }
+ }
+
+ //
+ // Get pjlib compatible semaphore object.
+ //
+ pj_sem_t *pj_sem_t_()
+ {
+ return (pj_sem_t*)this;
+ }
+
+ //
+ // Wait semaphore.
+ //
+ pj_status_t wait()
+ {
+ return pj_sem_wait(this->pj_sem_t_());
+ }
+
+ //
+ // Wait semaphore.
+ //
+ pj_status_t acquire()
+ {
+ return wait();
+ }
+
+ //
+ // Try wait semaphore.
+ //
+ pj_status_t trywait()
+ {
+ return pj_sem_trywait(this->pj_sem_t_());
+ }
+
+ //
+ // Try wait semaphore.
+ //
+ pj_status_t tryacquire()
+ {
+ return trywait();
+ }
+
+ //
+ // Post semaphore.
+ //
+ pj_status_t post()
+ {
+ return pj_sem_post(this->pj_sem_t_());
+ }
+
+ //
+ // Post semaphore.
+ //
+ pj_status_t release()
+ {
+ return post();
+ }
+
+private:
+ pj_sem_t *sem_;
+};
+
+
+//
+// Event object.
+//
+class Pj_Event
+{
+public:
+ //
+ // Construct event object.
+ //
+ Pj_Event( Pj_Pool *pool, bool manual_reset = false,
+ bool initial = false, const char *name = NULL )
+ : event_(NULL)
+ {
+ create(pool, manual_reset, initial, name);
+ }
+
+ //
+ // Destructor.
+ //
+ ~Pj_Event()
+ {
+ destroy();
+ }
+
+ //
+ // Create event object.
+ //
+ pj_status_t create( Pj_Pool *pool, bool manual_reset = false,
+ bool initial = false, const char *name = NULL)
+ {
+ destroy();
+ return pj_event_create(pool->pool_(), name, manual_reset, initial,
+ &event_);
+ }
+
+ //
+ // Get pjlib compatible event object.
+ //
+ pj_event_t *pj_event_t_()
+ {
+ return event_;
+ }
+
+ //
+ // Destroy event object.
+ //
+ void destroy()
+ {
+ if (event_) {
+ pj_event_destroy(event_);
+ event_ = NULL;
+ }
+ }
+
+ //
+ // Wait.
+ //
+ pj_status_t wait()
+ {
+ return pj_event_wait(event_);
+ }
+
+ //
+ // Try wait.
+ //
+ pj_status_t trywait()
+ {
+ return pj_event_trywait(event_);
+ }
+
+ //
+ // Set event state to signalled.
+ //
+ pj_status_t set()
+ {
+ return pj_event_set(this->pj_event_t_());
+ }
+
+ //
+ // Release one waiting thread.
+ //
+ pj_status_t pulse()
+ {
+ return pj_event_pulse(this->pj_event_t_());
+ }
+
+ //
+ // Set a non-signalled.
+ //
+ pj_status_t reset()
+ {
+ return pj_event_reset(this->pj_event_t_());
+ }
+
+private:
+ pj_event_t *event_;
+};
+
+//
+// OS abstraction.
+//
+class Pj_OS_API
+{
+public:
+ //
+ // Get current time.
+ //
+ static pj_status_t gettimeofday( Pj_Time_Val *tv )
+ {
+ return pj_gettimeofday(tv);
+ }
+
+ //
+ // Parse to time of day.
+ //
+ static pj_status_t time_decode( const Pj_Time_Val *tv,
+ pj_parsed_time *pt )
+ {
+ return pj_time_decode(tv, pt);
+ }
+
+ //
+ // Parse from time of day.
+ //
+ static pj_status_t time_encode( const pj_parsed_time *pt,
+ Pj_Time_Val *tv)
+ {
+ return pj_time_encode(pt, tv);
+ }
+
+ //
+ // Convert to GMT.
+ //
+ static pj_status_t time_local_to_gmt( Pj_Time_Val *tv )
+ {
+ return pj_time_local_to_gmt( tv );
+ }
+
+ //
+ // Convert time to local.
+ //
+ static pj_status_t time_gmt_to_local( Pj_Time_Val *tv)
+ {
+ return pj_time_gmt_to_local( tv );
+ }
+};
+
+//
+// Timeval inlines.
+//
+inline pj_status_t Pj_Time_Val::gettimeofday()
+{
+ return Pj_OS_API::gettimeofday(this);
+}
+
+inline pj_parsed_time Pj_Time_Val::decode()
+{
+ pj_parsed_time pt;
+ Pj_OS_API::time_decode(this, &pt);
+ return pt;
+}
+
+inline pj_status_t Pj_Time_Val::encode(const pj_parsed_time *pt)
+{
+ return Pj_OS_API::time_encode(pt, this);
+}
+
+inline pj_status_t Pj_Time_Val::to_gmt()
+{
+ return Pj_OS_API::time_local_to_gmt(this);
+}
+
+inline pj_status_t Pj_Time_Val::to_local()
+{
+ return Pj_OS_API::time_gmt_to_local(this);
+}
+
+#endif /* __PJPP_OS_HPP__ */
+
diff --git a/pjlib/include/pj++/pool.hpp b/pjlib/include/pj++/pool.hpp
index c1991d5b..1fa75759 100644
--- a/pjlib/include/pj++/pool.hpp
+++ b/pjlib/include/pj++/pool.hpp
@@ -1,253 +1,254 @@
/* $Id$
- */
-#ifndef __PJPP_POOL_H__
-#define __PJPP_POOL_H__
-
-#include <pj/pool.h>
-
-class Pj_Pool;
-class Pj_Caching_Pool;
-
-//
-// Base class for all Pjlib objects
-//
-class Pj_Object
-{
-public:
- void *operator new(unsigned int class_size, Pj_Pool *pool);
- void *operator new(unsigned int class_size, Pj_Pool &pool);
-
- void operator delete(void*)
- {
- }
-
- void operator delete(void*, Pj_Pool*)
- {
- }
-
- void operator delete(void*, Pj_Pool&)
- {
- }
-
- //
- // Inline implementations at the end of this file.
- //
-
-private:
- // Can not use normal new operator; must use pool.
- // e.g.:
- // obj = new(pool) Pj_The_Object(pool, ...);
- //
- void *operator new(unsigned int)
- {}
-};
-
-
-//
-// Pool.
-//
-class Pj_Pool : public Pj_Object
-{
-public:
- //
- // Default constructor, initializes internal pool to NULL.
- // Application must call attach() some time later.
- //
- Pj_Pool()
- : p_(NULL)
- {
- }
-
- //
- // Create pool.
- //
- Pj_Pool(Pj_Caching_Pool &caching_pool,
- pj_size_t initial_size,
- pj_size_t increment_size,
- const char *name = NULL,
- pj_pool_callback *callback = NULL);
-
- //
- // Construct from existing pool.
- //
- explicit Pj_Pool(pj_pool_t *pool)
- : p_(pool)
- {
- }
-
- //
- // Attach existing pool.
- //
- void attach(pj_pool_t *pool)
- {
- p_ = pool;
- }
-
- //
- // Destructor.
- //
- // Release pool back to factory. Remember: if you delete pool, then
- // make sure that all objects that have been allocated from this pool
- // have been properly destroyed.
- //
- // This is where C++ is trickier than plain C!!
- //
- ~Pj_Pool()
- {
- if (p_)
- pj_pool_release(p_);
- }
-
- //
- // Get name.
- //
- const char *getobjname() const
- {
- return pj_pool_getobjname(p_);
- }
-
- //
- // Get pjlib compatible pool object.
- //
- pj_pool_t *pool_()
- {
- return p_;
- }
-
- //
- // Get pjlib compatible pool object.
- //
- const pj_pool_t *pool_() const
- {
- return p_;
- }
-
- //
- // Get pjlib compatible pool object.
- //
- pj_pool_t *pj_pool_t_()
- {
- return p_;
- }
-
- //
- // Reset pool.
- //
- void reset()
- {
- pj_pool_reset(p_);
- }
-
- //
- // Get current capacity.
- //
- pj_size_t get_capacity()
- {
- pj_pool_get_capacity(p_);
- }
-
- //
- // Get current total bytes allocated from the pool.
- //
- pj_size_t get_used_size()
- {
- pj_pool_get_used_size(p_);
- }
-
- //
- // Allocate.
- //
- void *alloc(pj_size_t size)
- {
- return pj_pool_alloc(p_, size);
- }
-
- //
- // Allocate elements and zero fill the memory.
- //
- void *calloc(pj_size_t count, pj_size_t elem)
- {
- return pj_pool_calloc(p_, count, elem);
- }
-
- //
- // Allocate and zero fill memory.
- //
- void *zalloc(pj_size_t size)
- {
- return pj_pool_zalloc(p_, size);
- }
-
-private:
- pj_pool_t *p_;
-};
-
-
-//
-// Caching pool.
-//
-class Pj_Caching_Pool
-{
-public:
- //
- // Construct caching pool.
- //
- Pj_Caching_Pool( pj_size_t cache_capacity = 0,
- const pj_pool_factory_policy *pol=&pj_pool_factory_default_policy)
- {
- pj_caching_pool_init(&cp_, pol, cache_capacity);
- }
-
- //
- // Destroy caching pool.
- //
- ~Pj_Caching_Pool()
- {
- pj_caching_pool_destroy(&cp_);
- }
-
- //
- // Create pool.
- //
- pj_pool_t *create_pool( pj_size_t initial_size,
- pj_size_t increment_size,
- const char *name = NULL,
- pj_pool_callback *callback = NULL)
- {
- return (pj_pool_t*)(*cp_.factory.create_pool)(&cp_.factory, name,
- initial_size,
- increment_size,
- callback);
- }
-
-private:
- pj_caching_pool cp_;
-};
-
-//
-// Inlines for Pj_Object
-//
-inline void *Pj_Object::operator new(unsigned int class_size, Pj_Pool *pool)
-{
- return pool->alloc(class_size);
-}
-inline void *Pj_Object::operator new(unsigned int class_size, Pj_Pool &pool)
-{
- return pool.alloc(class_size);
-}
-
-//
-// Inlines for Pj_Pool
-//
-inline Pj_Pool::Pj_Pool( Pj_Caching_Pool &caching_pool,
- pj_size_t initial_size,
- pj_size_t increment_size,
- const char *name,
- pj_pool_callback *callback)
-{
- p_ = caching_pool.create_pool(initial_size, increment_size, name,
- callback);
-}
-
-
-#endif /* __PJPP_POOL_H__ */
+ */
+#ifndef __PJPP_POOL_HPP__
+#define __PJPP_POOL_HPP__
+
+#include <pj/pool.h>
+
+class Pj_Pool;
+class Pj_Caching_Pool;
+
+//
+// Base class for all Pjlib objects
+//
+class Pj_Object
+{
+public:
+ void *operator new(unsigned int class_size, Pj_Pool *pool);
+ void *operator new(unsigned int class_size, Pj_Pool &pool);
+
+ void operator delete(void*)
+ {
+ }
+
+ void operator delete(void*, Pj_Pool*)
+ {
+ }
+
+ void operator delete(void*, Pj_Pool&)
+ {
+ }
+
+ //
+ // Inline implementations at the end of this file.
+ //
+
+private:
+ // Can not use normal new operator; must use pool.
+ // e.g.:
+ // obj = new(pool) Pj_The_Object(pool, ...);
+ //
+ void *operator new(unsigned int)
+ {}
+};
+
+
+//
+// Pool.
+//
+class Pj_Pool : public Pj_Object
+{
+public:
+ //
+ // Default constructor, initializes internal pool to NULL.
+ // Application must call attach() some time later.
+ //
+ Pj_Pool()
+ : p_(NULL)
+ {
+ }
+
+ //
+ // Create pool.
+ //
+ Pj_Pool(Pj_Caching_Pool &caching_pool,
+ pj_size_t initial_size,
+ pj_size_t increment_size,
+ const char *name = NULL,
+ pj_pool_callback *callback = NULL);
+
+ //
+ // Construct from existing pool.
+ //
+ explicit Pj_Pool(pj_pool_t *pool)
+ : p_(pool)
+ {
+ }
+
+ //
+ // Attach existing pool.
+ //
+ void attach(pj_pool_t *pool)
+ {
+ p_ = pool;
+ }
+
+ //
+ // Destructor.
+ //
+ // Release pool back to factory. Remember: if you delete pool, then
+ // make sure that all objects that have been allocated from this pool
+ // have been properly destroyed.
+ //
+ // This is where C++ is trickier than plain C!!
+ //
+ ~Pj_Pool()
+ {
+ if (p_)
+ pj_pool_release(p_);
+ }
+
+ //
+ // Get name.
+ //
+ const char *getobjname() const
+ {
+ return pj_pool_getobjname(p_);
+ }
+
+ //
+ // Get pjlib compatible pool object.
+ //
+ pj_pool_t *pool_()
+ {
+ return p_;
+ }
+
+ //
+ // Get pjlib compatible pool object.
+ //
+ const pj_pool_t *pool_() const
+ {
+ return p_;
+ }
+
+ //
+ // Get pjlib compatible pool object.
+ //
+ pj_pool_t *pj_pool_t_()
+ {
+ return p_;
+ }
+
+ //
+ // Reset pool.
+ //
+ void reset()
+ {
+ pj_pool_reset(p_);
+ }
+
+ //
+ // Get current capacity.
+ //
+ pj_size_t get_capacity()
+ {
+ pj_pool_get_capacity(p_);
+ }
+
+ //
+ // Get current total bytes allocated from the pool.
+ //
+ pj_size_t get_used_size()
+ {
+ pj_pool_get_used_size(p_);
+ }
+
+ //
+ // Allocate.
+ //
+ void *alloc(pj_size_t size)
+ {
+ return pj_pool_alloc(p_, size);
+ }
+
+ //
+ // Allocate elements and zero fill the memory.
+ //
+ void *calloc(pj_size_t count, pj_size_t elem)
+ {
+ return pj_pool_calloc(p_, count, elem);
+ }
+
+ //
+ // Allocate and zero fill memory.
+ //
+ void *zalloc(pj_size_t size)
+ {
+ return pj_pool_zalloc(p_, size);
+ }
+
+private:
+ pj_pool_t *p_;
+};
+
+
+//
+// Caching pool.
+//
+class Pj_Caching_Pool
+{
+public:
+ //
+ // Construct caching pool.
+ //
+ Pj_Caching_Pool( pj_size_t cache_capacity = 0,
+ const pj_pool_factory_policy *pol=&pj_pool_factory_default_policy)
+ {
+ pj_caching_pool_init(&cp_, pol, cache_capacity);
+ }
+
+ //
+ // Destroy caching pool.
+ //
+ ~Pj_Caching_Pool()
+ {
+ pj_caching_pool_destroy(&cp_);
+ }
+
+ //
+ // Create pool.
+ //
+ pj_pool_t *create_pool( pj_size_t initial_size,
+ pj_size_t increment_size,
+ const char *name = NULL,
+ pj_pool_callback *callback = NULL)
+ {
+ return (pj_pool_t*)(*cp_.factory.create_pool)(&cp_.factory, name,
+ initial_size,
+ increment_size,
+ callback);
+ }
+
+private:
+ pj_caching_pool cp_;
+};
+
+//
+// Inlines for Pj_Object
+//
+inline void *Pj_Object::operator new(unsigned int class_size, Pj_Pool *pool)
+{
+ return pool->alloc(class_size);
+}
+inline void *Pj_Object::operator new(unsigned int class_size, Pj_Pool &pool)
+{
+ return pool.alloc(class_size);
+}
+
+//
+// Inlines for Pj_Pool
+//
+inline Pj_Pool::Pj_Pool( Pj_Caching_Pool &caching_pool,
+ pj_size_t initial_size,
+ pj_size_t increment_size,
+ const char *name,
+ pj_pool_callback *callback)
+{
+ p_ = caching_pool.create_pool(initial_size, increment_size, name,
+ callback);
+}
+
+
+#endif /* __PJPP_POOL_HPP__ */
+
diff --git a/pjlib/include/pj++/proactor.hpp b/pjlib/include/pj++/proactor.hpp
index 891dd75d..73be85f4 100644
--- a/pjlib/include/pj++/proactor.hpp
+++ b/pjlib/include/pj++/proactor.hpp
@@ -1,500 +1,502 @@
/* $Id$
- */
-#ifndef __PJPP_PROACTOR_H__
-#define __PJPP_PROACTOR_H__
-
-#include <pj/ioqueue.h>
-#include <pj++/pool.hpp>
-#include <pj++/sock.hpp>
-#include <pj++/timer.hpp>
-#include <pj/errno.h>
-
-class Pj_Proactor;
-class Pj_Event_Handler;
-
-
-//////////////////////////////////////////////////////////////////////////////
-// Asynchronous operation key.
-//
-// Applications may inheric this class to put their application
-// specific data.
-//
-class Pj_Async_Op : public pj_ioqueue_op_key_t
-{
-public:
- //
- // Construct with null handler.
- // App must call set_handler() before use.
- //
- Pj_Async_Op()
- : handler_(NULL)
- {
- }
-
- //
- // Constructor.
- //
- explicit Pj_Async_Op(Pj_Event_Handler *handler)
- : handler_(handler)
- {
- pj_memset(this, 0, sizeof(pj_ioqueue_op_key_t));
- }
-
- //
- // Set handler.
- //
- void set_handler(Pj_Event_Handler *handler)
- {
- handler_ = handler;
- }
-
- //
- // Check whether operation is still pending for this key.
- //
- bool is_pending();
-
- //
- // Cancel the operation.
- //
- bool cancel(pj_ssize_t bytes_status=-PJ_ECANCELLED);
-
-protected:
- Pj_Event_Handler *handler_;
-};
-
-
-//////////////////////////////////////////////////////////////////////////////
-// Event handler.
-//
-// Applications should inherit this class to receive various event
-// notifications.
-//
-// Applications should implement get_socket_handle().
-//
-class Pj_Event_Handler : public Pj_Object
-{
- friend class Pj_Proactor;
-public:
- //
- // Default constructor.
- //
- Pj_Event_Handler()
- : key_(NULL)
- {
- pj_memset(&timer_, 0, sizeof(timer_));
- timer_.user_data = this;
- timer_.cb = &timer_callback;
- }
-
- //
- // Destroy.
- //
- virtual ~Pj_Event_Handler()
- {
- unregister();
- }
-
- //
- // Unregister this handler from the ioqueue.
- //
- void unregister()
- {
- if (key_) {
- pj_ioqueue_unregister(key_);
- key_ = NULL;
- }
- }
-
- //
- // Get socket handle associated with this.
- //
- virtual pj_sock_t get_socket_handle()
- {
- return PJ_INVALID_SOCKET;
- }
-
- //
- // Start async receive.
- //
- pj_status_t recv( Pj_Async_Op *op_key,
- void *buf, pj_ssize_t *len,
- unsigned flags)
- {
- return pj_ioqueue_recv( key_, op_key,
- buf, len, flags);
- }
-
- //
- // Start async recvfrom()
- //
- pj_status_t recvfrom( Pj_Async_Op *op_key,
- void *buf, pj_ssize_t *len, unsigned flags,
- Pj_Inet_Addr *addr)
- {
- addr->addrlen_ = sizeof(Pj_Inet_Addr);
- return pj_ioqueue_recvfrom( key_, op_key, buf, len, flags,
- addr, &addr->addrlen_ );
- }
-
- //
- // Start async send()
- //
- pj_status_t send( Pj_Async_Op *op_key,
- const void *data, pj_ssize_t *len,
- unsigned flags)
- {
- return pj_ioqueue_send( key_, op_key, data, len, flags);
- }
-
- //
- // Start async sendto()
- //
- pj_status_t sendto( Pj_Async_Op *op_key,
- const void *data, pj_ssize_t *len, unsigned flags,
- const Pj_Inet_Addr &addr)
- {
- return pj_ioqueue_sendto(key_, op_key, data, len, flags,
- &addr, sizeof(addr));
- }
-
-#if PJ_HAS_TCP
- //
- // Start async connect()
- //
- pj_status_t connect(const Pj_Inet_Addr &addr)
- {
- return pj_ioqueue_connect(key_, &addr, sizeof(addr));
- }
-
- //
- // Start async accept().
- //
- pj_status_t accept( Pj_Async_Op *op_key,
- Pj_Socket *sock,
- Pj_Inet_Addr *local = NULL,
- Pj_Inet_Addr *remote = NULL)
- {
- int *addrlen = local ? &local->addrlen_ : NULL;
- return pj_ioqueue_accept( key_, op_key, &sock->sock_,
- local, remote, addrlen );
- }
-
-#endif
-
-protected:
- //////////////////
- // Overridables
- //////////////////
-
- //
- // Timeout callback.
- //
- virtual void on_timeout(int data)
- {
- }
-
- //
- // On read complete callback.
- //
- virtual void on_read_complete( Pj_Async_Op *op_key,
- pj_ssize_t bytes_read)
- {
- }
-
- //
- // On write complete callback.
- //
- virtual void on_write_complete( Pj_Async_Op *op_key,
- pj_ssize_t bytes_sent)
- {
- }
-
-#if PJ_HAS_TCP
- //
- // On connect complete callback.
- //
- virtual void on_connect_complete(pj_status_t status)
- {
- }
-
- //
- // On new connection callback.
- //
- virtual void on_accept_complete( Pj_Async_Op *op_key,
- pj_sock_t new_sock,
- pj_status_t status)
- {
- }
-
-#endif
-
-
-private:
- pj_ioqueue_key_t *key_;
- pj_timer_entry timer_;
-
- friend class Pj_Proactor;
- friend class Pj_Async_Op;
-
- //
- // Static timer callback.
- //
- static void timer_callback( pj_timer_heap_t *timer_heap,
- struct pj_timer_entry *entry)
- {
- Pj_Event_Handler *handler =
- (Pj_Event_Handler*) entry->user_data;
-
- handler->on_timeout(entry->id);
- }
-};
-
-inline bool Pj_Async_Op::is_pending()
-{
- return pj_ioqueue_is_pending(handler_->key_, this) != 0;
-}
-
-inline bool Pj_Async_Op::cancel(pj_ssize_t bytes_status)
-{
- return pj_ioqueue_post_completion(handler_->key_, this,
- bytes_status) == PJ_SUCCESS;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Proactor
-//
-class Pj_Proactor : public Pj_Object
-{
-public:
- //
- // Default constructor, initializes to NULL.
- //
- Pj_Proactor()
- : ioq_(NULL), th_(NULL)
- {
- cb_.on_read_complete = &read_complete_cb;
- cb_.on_write_complete = &write_complete_cb;
- cb_.on_accept_complete = &accept_complete_cb;
- cb_.on_connect_complete = &connect_complete_cb;
- }
-
- //
- // Construct proactor.
- //
- Pj_Proactor( Pj_Pool *pool, pj_size_t max_fd,
- pj_size_t max_timer_entries )
- : ioq_(NULL), th_(NULL)
- {
- cb_.on_read_complete = &read_complete_cb;
- cb_.on_write_complete = &write_complete_cb;
- cb_.on_accept_complete = &accept_complete_cb;
- cb_.on_connect_complete = &connect_complete_cb;
-
- create(pool, max_fd, max_timer_entries);
- }
-
- //
- // Destructor.
- //
- ~Pj_Proactor()
- {
- destroy();
- }
-
- //
- // Create proactor.
- //
- pj_status_t create( Pj_Pool *pool, pj_size_t max_fd,
- pj_size_t timer_entry_count)
- {
- pj_status_t status;
-
- destroy();
-
- status = pj_ioqueue_create(pool->pool_(), max_fd, &ioq_);
- if (status != PJ_SUCCESS)
- return status;
-
- status = pj_timer_heap_create(pool->pool_(),
- timer_entry_count, &th_);
- if (status != PJ_SUCCESS) {
- pj_ioqueue_destroy(ioq_);
- ioq_ = NULL;
- return NULL;
- }
-
- return status;
- }
-
- //
- // Destroy proactor.
- //
- void destroy()
- {
- if (ioq_) {
- pj_ioqueue_destroy(ioq_);
- ioq_ = NULL;
- }
- if (th_) {
- pj_timer_heap_destroy(th_);
- th_ = NULL;
- }
- }
-
- //
- // Register handler.
- // This will call handler->get_socket_handle()
- //
- pj_status_t register_socket_handler(Pj_Pool *pool,
- Pj_Event_Handler *handler)
- {
- return pj_ioqueue_register_sock( pool->pool_(), ioq_,
- handler->get_socket_handle(),
- handler, &cb_, &handler->key_ );
- }
-
- //
- // Unregister handler.
- //
- static void unregister_handler(Pj_Event_Handler *handler)
- {
- if (handler->key_) {
- pj_ioqueue_unregister( handler->key_ );
- handler->key_ = NULL;
- }
- }
-
- //
- // Scheduler timer.
- //
- bool schedule_timer( Pj_Event_Handler *handler,
- const Pj_Time_Val &delay,
- int id=-1)
- {
- return schedule_timer(th_, handler, delay, id);
- }
-
- //
- // Cancel timer.
- //
- bool cancel_timer(Pj_Event_Handler *handler)
- {
- return pj_timer_heap_cancel(th_, &handler->timer_) == 1;
- }
-
- //
- // Handle events.
- //
- int handle_events(Pj_Time_Val *max_timeout)
- {
- Pj_Time_Val timeout(0, 0);
- int timer_count;
-
- timer_count = pj_timer_heap_poll( th_, &timeout );
-
- if (timeout.get_sec() < 0)
- timeout.sec = PJ_MAXINT32;
-
- /* If caller specifies maximum time to wait, then compare the value
- * with the timeout to wait from timer, and use the minimum value.
- */
- if (max_timeout && timeout >= *max_timeout) {
- timeout = *max_timeout;
- }
-
- /* Poll events in ioqueue. */
- int ioqueue_count;
-
- ioqueue_count = pj_ioqueue_poll(ioq_, &timeout);
- if (ioqueue_count < 0)
- return ioqueue_count;
-
- return ioqueue_count + timer_count;
- }
-
- //
- // Get the internal ioqueue object.
- //
- pj_ioqueue_t *get_io_queue()
- {
- return ioq_;
- }
-
- //
- // Get the internal timer heap object.
- //
- pj_timer_heap_t *get_timer_heap()
- {
- return th_;
- }
-
-private:
- pj_ioqueue_t *ioq_;
- pj_timer_heap_t *th_;
- pj_ioqueue_callback cb_;
-
- static bool schedule_timer( pj_timer_heap_t *timer,
- Pj_Event_Handler *handler,
- const Pj_Time_Val &delay,
- int id=-1)
- {
- handler->timer_.id = id;
- return pj_timer_heap_schedule(timer, &handler->timer_, &delay) == 0;
- }
-
-
- //
- // Static read completion callback.
- //
- static void read_complete_cb( pj_ioqueue_key_t *key,
- pj_ioqueue_op_key_t *op_key,
- pj_ssize_t bytes_read)
- {
- Pj_Event_Handler *handler =
- (Pj_Event_Handler*) pj_ioqueue_get_user_data(key);
-
- handler->on_read_complete((Pj_Async_Op*)op_key, bytes_read);
- }
-
- //
- // Static write completion callback.
- //
- static void write_complete_cb(pj_ioqueue_key_t *key,
- pj_ioqueue_op_key_t *op_key,
- pj_ssize_t bytes_sent)
- {
- Pj_Event_Handler *handler =
- (Pj_Event_Handler*) pj_ioqueue_get_user_data(key);
-
- handler->on_write_complete((Pj_Async_Op*)op_key, bytes_sent);
- }
-
- //
- // Static accept completion callback.
- //
- static void accept_complete_cb(pj_ioqueue_key_t *key,
- pj_ioqueue_op_key_t *op_key,
- pj_sock_t new_sock,
- pj_status_t status)
- {
- Pj_Event_Handler *handler =
- (Pj_Event_Handler*) pj_ioqueue_get_user_data(key);
-
- handler->on_accept_complete((Pj_Async_Op*)op_key, new_sock, status);
- }
-
- //
- // Static connect completion callback.
- //
- static void connect_complete_cb(pj_ioqueue_key_t *key,
- pj_status_t status)
- {
- Pj_Event_Handler *handler =
- (Pj_Event_Handler*) pj_ioqueue_get_user_data(key);
-
- handler->on_connect_complete(status);
- }
-
-};
-
-#endif /* __PJPP_PROACTOR_H__ */
+ */
+#ifndef __PJPP_PROACTOR_HPP__
+#define __PJPP_PROACTOR_HPP__
+
+#include <pj/ioqueue.h>
+#include <pj++/pool.hpp>
+#include <pj++/sock.hpp>
+#include <pj++/timer.hpp>
+#include <pj/errno.h>
+
+class Pj_Proactor;
+class Pj_Event_Handler;
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Asynchronous operation key.
+//
+// Applications may inheric this class to put their application
+// specific data.
+//
+class Pj_Async_Op : public pj_ioqueue_op_key_t
+{
+public:
+ //
+ // Construct with null handler.
+ // App must call set_handler() before use.
+ //
+ Pj_Async_Op()
+ : handler_(NULL)
+ {
+ pj_ioqueue_op_key_init(this, sizeof(*this));
+ }
+
+ //
+ // Constructor.
+ //
+ explicit Pj_Async_Op(Pj_Event_Handler *handler)
+ : handler_(handler)
+ {
+ pj_ioqueue_op_key_init(this, sizeof(*this));
+ }
+
+ //
+ // Set handler.
+ //
+ void set_handler(Pj_Event_Handler *handler)
+ {
+ handler_ = handler;
+ }
+
+ //
+ // Check whether operation is still pending for this key.
+ //
+ bool is_pending();
+
+ //
+ // Cancel the operation.
+ //
+ bool cancel(pj_ssize_t bytes_status=-PJ_ECANCELLED);
+
+protected:
+ Pj_Event_Handler *handler_;
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Event handler.
+//
+// Applications should inherit this class to receive various event
+// notifications.
+//
+// Applications should implement get_socket_handle().
+//
+class Pj_Event_Handler : public Pj_Object
+{
+ friend class Pj_Proactor;
+public:
+ //
+ // Default constructor.
+ //
+ Pj_Event_Handler()
+ : key_(NULL)
+ {
+ pj_memset(&timer_, 0, sizeof(timer_));
+ timer_.user_data = this;
+ timer_.cb = &timer_callback;
+ }
+
+ //
+ // Destroy.
+ //
+ virtual ~Pj_Event_Handler()
+ {
+ unregister();
+ }
+
+ //
+ // Unregister this handler from the ioqueue.
+ //
+ void unregister()
+ {
+ if (key_) {
+ pj_ioqueue_unregister(key_);
+ key_ = NULL;
+ }
+ }
+
+ //
+ // Get socket handle associated with this.
+ //
+ virtual pj_sock_t get_socket_handle()
+ {
+ return PJ_INVALID_SOCKET;
+ }
+
+ //
+ // Start async receive.
+ //
+ pj_status_t recv( Pj_Async_Op *op_key,
+ void *buf, pj_ssize_t *len,
+ unsigned flags)
+ {
+ return pj_ioqueue_recv( key_, op_key,
+ buf, len, flags);
+ }
+
+ //
+ // Start async recvfrom()
+ //
+ pj_status_t recvfrom( Pj_Async_Op *op_key,
+ void *buf, pj_ssize_t *len, unsigned flags,
+ Pj_Inet_Addr *addr)
+ {
+ addr->addrlen_ = sizeof(Pj_Inet_Addr);
+ return pj_ioqueue_recvfrom( key_, op_key, buf, len, flags,
+ addr, &addr->addrlen_ );
+ }
+
+ //
+ // Start async send()
+ //
+ pj_status_t send( Pj_Async_Op *op_key,
+ const void *data, pj_ssize_t *len,
+ unsigned flags)
+ {
+ return pj_ioqueue_send( key_, op_key, data, len, flags);
+ }
+
+ //
+ // Start async sendto()
+ //
+ pj_status_t sendto( Pj_Async_Op *op_key,
+ const void *data, pj_ssize_t *len, unsigned flags,
+ const Pj_Inet_Addr &addr)
+ {
+ return pj_ioqueue_sendto(key_, op_key, data, len, flags,
+ &addr, sizeof(addr));
+ }
+
+#if PJ_HAS_TCP
+ //
+ // Start async connect()
+ //
+ pj_status_t connect(const Pj_Inet_Addr &addr)
+ {
+ return pj_ioqueue_connect(key_, &addr, sizeof(addr));
+ }
+
+ //
+ // Start async accept().
+ //
+ pj_status_t accept( Pj_Async_Op *op_key,
+ Pj_Socket *sock,
+ Pj_Inet_Addr *local = NULL,
+ Pj_Inet_Addr *remote = NULL)
+ {
+ int *addrlen = local ? &local->addrlen_ : NULL;
+ return pj_ioqueue_accept( key_, op_key, &sock->sock_,
+ local, remote, addrlen );
+ }
+
+#endif
+
+protected:
+ //////////////////
+ // Overridables
+ //////////////////
+
+ //
+ // Timeout callback.
+ //
+ virtual void on_timeout(int data)
+ {
+ }
+
+ //
+ // On read complete callback.
+ //
+ virtual void on_read_complete( Pj_Async_Op *op_key,
+ pj_ssize_t bytes_read)
+ {
+ }
+
+ //
+ // On write complete callback.
+ //
+ virtual void on_write_complete( Pj_Async_Op *op_key,
+ pj_ssize_t bytes_sent)
+ {
+ }
+
+#if PJ_HAS_TCP
+ //
+ // On connect complete callback.
+ //
+ virtual void on_connect_complete(pj_status_t status)
+ {
+ }
+
+ //
+ // On new connection callback.
+ //
+ virtual void on_accept_complete( Pj_Async_Op *op_key,
+ pj_sock_t new_sock,
+ pj_status_t status)
+ {
+ }
+
+#endif
+
+
+private:
+ pj_ioqueue_key_t *key_;
+ pj_timer_entry timer_;
+
+ friend class Pj_Proactor;
+ friend class Pj_Async_Op;
+
+ //
+ // Static timer callback.
+ //
+ static void timer_callback( pj_timer_heap_t *timer_heap,
+ struct pj_timer_entry *entry)
+ {
+ Pj_Event_Handler *handler =
+ (Pj_Event_Handler*) entry->user_data;
+
+ handler->on_timeout(entry->id);
+ }
+};
+
+inline bool Pj_Async_Op::is_pending()
+{
+ return pj_ioqueue_is_pending(handler_->key_, this) != 0;
+}
+
+inline bool Pj_Async_Op::cancel(pj_ssize_t bytes_status)
+{
+ return pj_ioqueue_post_completion(handler_->key_, this,
+ bytes_status) == PJ_SUCCESS;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Proactor
+//
+class Pj_Proactor : public Pj_Object
+{
+public:
+ //
+ // Default constructor, initializes to NULL.
+ //
+ Pj_Proactor()
+ : ioq_(NULL), th_(NULL)
+ {
+ cb_.on_read_complete = &read_complete_cb;
+ cb_.on_write_complete = &write_complete_cb;
+ cb_.on_accept_complete = &accept_complete_cb;
+ cb_.on_connect_complete = &connect_complete_cb;
+ }
+
+ //
+ // Construct proactor.
+ //
+ Pj_Proactor( Pj_Pool *pool, pj_size_t max_fd,
+ pj_size_t max_timer_entries )
+ : ioq_(NULL), th_(NULL)
+ {
+ cb_.on_read_complete = &read_complete_cb;
+ cb_.on_write_complete = &write_complete_cb;
+ cb_.on_accept_complete = &accept_complete_cb;
+ cb_.on_connect_complete = &connect_complete_cb;
+
+ create(pool, max_fd, max_timer_entries);
+ }
+
+ //
+ // Destructor.
+ //
+ ~Pj_Proactor()
+ {
+ destroy();
+ }
+
+ //
+ // Create proactor.
+ //
+ pj_status_t create( Pj_Pool *pool, pj_size_t max_fd,
+ pj_size_t timer_entry_count)
+ {
+ pj_status_t status;
+
+ destroy();
+
+ status = pj_ioqueue_create(pool->pool_(), max_fd, &ioq_);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ status = pj_timer_heap_create(pool->pool_(),
+ timer_entry_count, &th_);
+ if (status != PJ_SUCCESS) {
+ pj_ioqueue_destroy(ioq_);
+ ioq_ = NULL;
+ return NULL;
+ }
+
+ return status;
+ }
+
+ //
+ // Destroy proactor.
+ //
+ void destroy()
+ {
+ if (ioq_) {
+ pj_ioqueue_destroy(ioq_);
+ ioq_ = NULL;
+ }
+ if (th_) {
+ pj_timer_heap_destroy(th_);
+ th_ = NULL;
+ }
+ }
+
+ //
+ // Register handler.
+ // This will call handler->get_socket_handle()
+ //
+ pj_status_t register_socket_handler(Pj_Pool *pool,
+ Pj_Event_Handler *handler)
+ {
+ return pj_ioqueue_register_sock( pool->pool_(), ioq_,
+ handler->get_socket_handle(),
+ handler, &cb_, &handler->key_ );
+ }
+
+ //
+ // Unregister handler.
+ //
+ static void unregister_handler(Pj_Event_Handler *handler)
+ {
+ if (handler->key_) {
+ pj_ioqueue_unregister( handler->key_ );
+ handler->key_ = NULL;
+ }
+ }
+
+ //
+ // Scheduler timer.
+ //
+ bool schedule_timer( Pj_Event_Handler *handler,
+ const Pj_Time_Val &delay,
+ int id=-1)
+ {
+ return schedule_timer(th_, handler, delay, id);
+ }
+
+ //
+ // Cancel timer.
+ //
+ bool cancel_timer(Pj_Event_Handler *handler)
+ {
+ return pj_timer_heap_cancel(th_, &handler->timer_) == 1;
+ }
+
+ //
+ // Handle events.
+ //
+ int handle_events(Pj_Time_Val *max_timeout)
+ {
+ Pj_Time_Val timeout(0, 0);
+ int timer_count;
+
+ timer_count = pj_timer_heap_poll( th_, &timeout );
+
+ if (timeout.get_sec() < 0)
+ timeout.sec = PJ_MAXINT32;
+
+ /* If caller specifies maximum time to wait, then compare the value
+ * with the timeout to wait from timer, and use the minimum value.
+ */
+ if (max_timeout && timeout >= *max_timeout) {
+ timeout = *max_timeout;
+ }
+
+ /* Poll events in ioqueue. */
+ int ioqueue_count;
+
+ ioqueue_count = pj_ioqueue_poll(ioq_, &timeout);
+ if (ioqueue_count < 0)
+ return ioqueue_count;
+
+ return ioqueue_count + timer_count;
+ }
+
+ //
+ // Get the internal ioqueue object.
+ //
+ pj_ioqueue_t *get_io_queue()
+ {
+ return ioq_;
+ }
+
+ //
+ // Get the internal timer heap object.
+ //
+ pj_timer_heap_t *get_timer_heap()
+ {
+ return th_;
+ }
+
+private:
+ pj_ioqueue_t *ioq_;
+ pj_timer_heap_t *th_;
+ pj_ioqueue_callback cb_;
+
+ static bool schedule_timer( pj_timer_heap_t *timer,
+ Pj_Event_Handler *handler,
+ const Pj_Time_Val &delay,
+ int id=-1)
+ {
+ handler->timer_.id = id;
+ return pj_timer_heap_schedule(timer, &handler->timer_, &delay) == 0;
+ }
+
+
+ //
+ // Static read completion callback.
+ //
+ static void read_complete_cb( pj_ioqueue_key_t *key,
+ pj_ioqueue_op_key_t *op_key,
+ pj_ssize_t bytes_read)
+ {
+ Pj_Event_Handler *handler =
+ (Pj_Event_Handler*) pj_ioqueue_get_user_data(key);
+
+ handler->on_read_complete((Pj_Async_Op*)op_key, bytes_read);
+ }
+
+ //
+ // Static write completion callback.
+ //
+ static void write_complete_cb(pj_ioqueue_key_t *key,
+ pj_ioqueue_op_key_t *op_key,
+ pj_ssize_t bytes_sent)
+ {
+ Pj_Event_Handler *handler =
+ (Pj_Event_Handler*) pj_ioqueue_get_user_data(key);
+
+ handler->on_write_complete((Pj_Async_Op*)op_key, bytes_sent);
+ }
+
+ //
+ // Static accept completion callback.
+ //
+ static void accept_complete_cb(pj_ioqueue_key_t *key,
+ pj_ioqueue_op_key_t *op_key,
+ pj_sock_t new_sock,
+ pj_status_t status)
+ {
+ Pj_Event_Handler *handler =
+ (Pj_Event_Handler*) pj_ioqueue_get_user_data(key);
+
+ handler->on_accept_complete((Pj_Async_Op*)op_key, new_sock, status);
+ }
+
+ //
+ // Static connect completion callback.
+ //
+ static void connect_complete_cb(pj_ioqueue_key_t *key,
+ pj_status_t status)
+ {
+ Pj_Event_Handler *handler =
+ (Pj_Event_Handler*) pj_ioqueue_get_user_data(key);
+
+ handler->on_connect_complete(status);
+ }
+
+};
+
+#endif /* __PJPP_PROACTOR_HPP__ */
+
diff --git a/pjlib/include/pj++/scanner.hpp b/pjlib/include/pj++/scanner.hpp
index 9ddac097..8a3d9897 100644
--- a/pjlib/include/pj++/scanner.hpp
+++ b/pjlib/include/pj++/scanner.hpp
@@ -1,173 +1,173 @@
/* $Id$
- *
- */
-#ifndef __PJPP_SCANNER_H__
-#define __PJPP_SCANNER_H__
-
-#include <pjlib-util/scanner.h>
-#include <pj++/string.hpp>
-
-class Pj_Char_Spec
-{
-public:
- Pj_Char_Spec() { pj_cs_init(cs__); }
-
- void set(int c) { pj_cs_set(cs__, c); }
- void add_range(int begin, int end) { pj_cs_add_range(cs__, begin, end); }
- void add_alpha() { pj_cs_add_alpha(cs__); }
- void add_num() { pj_cs_add_num(cs__); }
- void add_str(const char *str) { pj_cs_add_str(cs__, str); }
- void del_range(int begin, int end) { pj_cs_del_range(cs__, begin, end); }
- void del_str(const char *str) { pj_cs_del_str(cs__, str); }
- void invert() { pj_cs_invert(cs__); }
- int match(int c) { return pj_cs_match(cs__, c); }
-
- pj_char_spec_element_t *cs_()
- {
- return cs__;
- }
-
- const pj_char_spec_element_t *cs_() const
- {
- return cs__;
- }
-
-private:
- pj_char_spec cs__;
-};
-
-class Pj_Scanner
-{
-public:
- Pj_Scanner() {}
-
- enum
- {
- SYNTAX_ERROR = 101
- };
- static void syntax_error_handler_throw_pj(pj_scanner *);
-
- typedef pj_scan_state State;
-
- void init(char *buf, int len, unsigned options=PJ_SCAN_AUTOSKIP_WS,
- pj_syn_err_func_ptr callback = &syntax_error_handler_throw_pj)
- {
- pj_scan_init(&scanner_, buf, len, options, callback);
- }
-
- void fini()
- {
- pj_scan_fini(&scanner_);
- }
-
- int eof() const
- {
- return pj_scan_is_eof(&scanner_);
- }
-
- int peek_char() const
- {
- return *scanner_.curptr;
- }
-
- int peek(const Pj_Char_Spec *cs, Pj_String *out)
- {
- return pj_scan_peek(&scanner_, cs->cs_(), out);
- }
-
- int peek_n(pj_size_t len, Pj_String *out)
- {
- return pj_scan_peek_n(&scanner_, len, out);
- }
-
- int peek_until(const Pj_Char_Spec *cs, Pj_String *out)
- {
- return pj_scan_peek_until(&scanner_, cs->cs_(), out);
- }
-
- void get(const Pj_Char_Spec *cs, Pj_String *out)
- {
- pj_scan_get(&scanner_, cs->cs_(), out);
- }
-
- void get_n(unsigned N, Pj_String *out)
- {
- pj_scan_get_n(&scanner_, N, out);
- }
-
- int get_char()
- {
- return pj_scan_get_char(&scanner_);
- }
-
- void get_quote(int begin_quote, int end_quote, Pj_String *out)
- {
- pj_scan_get_quote(&scanner_, begin_quote, end_quote, out);
- }
-
- void get_newline()
- {
- pj_scan_get_newline(&scanner_);
- }
-
- void get_until(const Pj_Char_Spec *cs, Pj_String *out)
- {
- pj_scan_get_until(&scanner_, cs->cs_(), out);
- }
-
- void get_until_ch(int until_ch, Pj_String *out)
- {
- pj_scan_get_until_ch(&scanner_, until_ch, out);
- }
-
- void get_until_chr(const char *spec, Pj_String *out)
- {
- pj_scan_get_until_chr(&scanner_, spec, out);
- }
-
- void advance_n(unsigned N, bool skip_ws=true)
- {
- pj_scan_advance_n(&scanner_, N, skip_ws);
- }
-
- int strcmp(const char *s, int len)
- {
- return pj_scan_strcmp(&scanner_, s, len);
- }
-
- int stricmp(const char *s, int len)
- {
- return pj_scan_stricmp(&scanner_, s, len);
- }
-
- void skip_ws()
- {
- pj_scan_skip_whitespace(&scanner_);
- }
-
- void save_state(State *state)
- {
- pj_scan_save_state(&scanner_, state);
- }
-
- void restore_state(State *state)
- {
- pj_scan_restore_state(&scanner_, state);
- }
-
- int get_pos_line() const
- {
- return scanner_.line;
- }
-
- int get_pos_col() const
- {
- return scanner_.col;
- }
-
-
-private:
- pj_scanner scanner_;
-};
-
-#endif /* __PJPP_SCANNER_H__ */
+ */
+#ifndef __PJPP_SCANNER_HPP__
+#define __PJPP_SCANNER_HPP__
+
+#include <pjlib-util/scanner.h>
+#include <pj++/string.hpp>
+
+class Pj_Char_Spec
+{
+public:
+ Pj_Char_Spec() { pj_cs_init(cs__); }
+
+ void set(int c) { pj_cs_set(cs__, c); }
+ void add_range(int begin, int end) { pj_cs_add_range(cs__, begin, end); }
+ void add_alpha() { pj_cs_add_alpha(cs__); }
+ void add_num() { pj_cs_add_num(cs__); }
+ void add_str(const char *str) { pj_cs_add_str(cs__, str); }
+ void del_range(int begin, int end) { pj_cs_del_range(cs__, begin, end); }
+ void del_str(const char *str) { pj_cs_del_str(cs__, str); }
+ void invert() { pj_cs_invert(cs__); }
+ int match(int c) { return pj_cs_match(cs__, c); }
+
+ pj_char_spec_element_t *cs_()
+ {
+ return cs__;
+ }
+
+ const pj_char_spec_element_t *cs_() const
+ {
+ return cs__;
+ }
+
+private:
+ pj_char_spec cs__;
+};
+
+class Pj_Scanner
+{
+public:
+ Pj_Scanner() {}
+
+ enum
+ {
+ SYNTAX_ERROR = 101
+ };
+ static void syntax_error_handler_throw_pj(pj_scanner *);
+
+ typedef pj_scan_state State;
+
+ void init(char *buf, int len, unsigned options=PJ_SCAN_AUTOSKIP_WS,
+ pj_syn_err_func_ptr callback = &syntax_error_handler_throw_pj)
+ {
+ pj_scan_init(&scanner_, buf, len, options, callback);
+ }
+
+ void fini()
+ {
+ pj_scan_fini(&scanner_);
+ }
+
+ int eof() const
+ {
+ return pj_scan_is_eof(&scanner_);
+ }
+
+ int peek_char() const
+ {
+ return *scanner_.curptr;
+ }
+
+ int peek(const Pj_Char_Spec *cs, Pj_String *out)
+ {
+ return pj_scan_peek(&scanner_, cs->cs_(), out);
+ }
+
+ int peek_n(pj_size_t len, Pj_String *out)
+ {
+ return pj_scan_peek_n(&scanner_, len, out);
+ }
+
+ int peek_until(const Pj_Char_Spec *cs, Pj_String *out)
+ {
+ return pj_scan_peek_until(&scanner_, cs->cs_(), out);
+ }
+
+ void get(const Pj_Char_Spec *cs, Pj_String *out)
+ {
+ pj_scan_get(&scanner_, cs->cs_(), out);
+ }
+
+ void get_n(unsigned N, Pj_String *out)
+ {
+ pj_scan_get_n(&scanner_, N, out);
+ }
+
+ int get_char()
+ {
+ return pj_scan_get_char(&scanner_);
+ }
+
+ void get_quote(int begin_quote, int end_quote, Pj_String *out)
+ {
+ pj_scan_get_quote(&scanner_, begin_quote, end_quote, out);
+ }
+
+ void get_newline()
+ {
+ pj_scan_get_newline(&scanner_);
+ }
+
+ void get_until(const Pj_Char_Spec *cs, Pj_String *out)
+ {
+ pj_scan_get_until(&scanner_, cs->cs_(), out);
+ }
+
+ void get_until_ch(int until_ch, Pj_String *out)
+ {
+ pj_scan_get_until_ch(&scanner_, until_ch, out);
+ }
+
+ void get_until_chr(const char *spec, Pj_String *out)
+ {
+ pj_scan_get_until_chr(&scanner_, spec, out);
+ }
+
+ void advance_n(unsigned N, bool skip_ws=true)
+ {
+ pj_scan_advance_n(&scanner_, N, skip_ws);
+ }
+
+ int strcmp(const char *s, int len)
+ {
+ return pj_scan_strcmp(&scanner_, s, len);
+ }
+
+ int stricmp(const char *s, int len)
+ {
+ return pj_scan_stricmp(&scanner_, s, len);
+ }
+
+ void skip_ws()
+ {
+ pj_scan_skip_whitespace(&scanner_);
+ }
+
+ void save_state(State *state)
+ {
+ pj_scan_save_state(&scanner_, state);
+ }
+
+ void restore_state(State *state)
+ {
+ pj_scan_restore_state(&scanner_, state);
+ }
+
+ int get_pos_line() const
+ {
+ return scanner_.line;
+ }
+
+ int get_pos_col() const
+ {
+ return scanner_.col;
+ }
+
+
+private:
+ pj_scanner scanner_;
+};
+
+#endif /* __PJPP_SCANNER_HPP__ */
+
diff --git a/pjlib/include/pj++/sock.hpp b/pjlib/include/pj++/sock.hpp
index 1c6c2dd9..f1a1e45f 100644
--- a/pjlib/include/pj++/sock.hpp
+++ b/pjlib/include/pj++/sock.hpp
@@ -1,426 +1,427 @@
/* $Id$
- */
-#ifndef __PJPP_SOCK_H__
-#define __PJPP_SOCK_H__
-
-#include <pj/sock.h>
-#include <pj/string.h>
-
-class Pj_Event_Handler;
-
-//
-// Base class for address.
-//
-class Pj_Addr
-{
-};
-
-//
-// Internet address.
-//
-class Pj_Inet_Addr : public pj_sockaddr_in, public Pj_Addr
-{
-public:
- //
- // Get port number.
- //
- pj_uint16_t get_port_number() const
- {
- return pj_sockaddr_in_get_port(this);
- }
-
- //
- // Set port number.
- //
- void set_port_number(pj_uint16_t port)
- {
- sin_family = PJ_AF_INET;
- pj_sockaddr_in_set_port(this, port);
- }
-
- //
- // Get IP address.
- //
- pj_uint32_t get_ip_address() const
- {
- return pj_sockaddr_in_get_addr(this).s_addr;
- }
-
- //
- // Get address string.
- //
- const char *get_address() const
- {
- return pj_inet_ntoa(sin_addr);
- }
-
- //
- // Set IP address.
- //
- void set_ip_address(pj_uint32_t addr)
- {
- sin_family = PJ_AF_INET;
- pj_sockaddr_in_set_addr(this, addr);
- }
-
- //
- // Set address.
- //
- pj_status_t set_address(const pj_str_t *addr)
- {
- return pj_sockaddr_in_set_str_addr(this, addr);
- }
-
- //
- // Set address.
- //
- pj_status_t set_address(const char *addr)
- {
- pj_str_t s;
- return pj_sockaddr_in_set_str_addr(this, pj_cstr(&s, addr));
- }
-
- //
- // Compare for equality.
- //
- bool operator==(const Pj_Inet_Addr &rhs) const
- {
- return sin_family == rhs.sin_family &&
- sin_addr.s_addr == rhs.sin_addr.s_addr &&
- sin_port == rhs.sin_port;
- }
-
-private:
- //
- // Dummy length used in pj_ioqueue_recvfrom() etc
- //
- friend class Pj_Event_Handler;
- friend class Pj_Socket;
- friend class Pj_Sock_Stream;
- friend class Pj_Sock_Dgram;
-
- int addrlen_;
-};
-
-
-//
-// Socket base class.
-//
-// Note:
-// socket will not automatically be closed on destructor.
-//
-class Pj_Socket
-{
-public:
- //
- // Default constructor.
- //
- Pj_Socket()
- : sock_(PJ_INVALID_SOCKET)
- {
- }
-
- //
- // Initialize from a socket handle.
- //
- explicit Pj_Socket(pj_sock_t sock)
- : sock_(sock)
- {
- }
-
- //
- // Copy constructor.
- //
- Pj_Socket(const Pj_Socket &rhs)
- : sock_(rhs.sock_)
- {
- }
-
- //
- // Destructor will not close the socket.
- // You must call close() explicitly.
- //
- ~Pj_Socket()
- {
- }
-
- //
- // Set socket handle.
- //
- void set_handle(pj_sock_t sock)
- {
- sock_ = sock;
- }
-
- //
- // Get socket handle.
- //
- pj_sock_t get_handle() const
- {
- return sock_;
- }
-
- //
- // Get socket handle.
- //
- pj_sock_t& get_handle()
- {
- return sock_;
- }
-
- //
- // See if the socket is valid.
- //
- bool is_valid() const
- {
- return sock_ != PJ_INVALID_SOCKET;
- }
-
- //
- // Create the socket.
- //
- pj_status_t create(int af, int type, int proto)
- {
- return pj_sock_socket(af, type, proto, &sock_);
- }
-
- //
- // Bind socket.
- //
- pj_status_t bind(const Pj_Inet_Addr &addr)
- {
- return pj_sock_bind(sock_, &addr, sizeof(Pj_Inet_Addr));
- }
-
- //
- // Close socket.
- //
- pj_status_t close()
- {
- pj_sock_close(sock_);
- }
-
- //
- // Get peer socket name.
- //
- pj_status_t getpeername(Pj_Inet_Addr *addr)
- {
- return pj_sock_getpeername(sock_, addr, &addr->addrlen_);
- }
-
- //
- // getsockname
- //
- pj_status_t getsockname(Pj_Inet_Addr *addr)
- {
- return pj_sock_getsockname(sock_, addr, &addr->addrlen_);
- }
-
- //
- // getsockopt.
- //
- pj_status_t getsockopt(int level, int optname,
- void *optval, int *optlen)
- {
- return pj_sock_getsockopt(sock_, level, optname, optval, optlen);
- }
-
- //
- // setsockopt
- //
- pj_status_t setsockopt(int level, int optname,
- const void *optval, int optlen)
- {
- return pj_sock_setsockopt(sock_, level, optname, optval, optlen);
- }
-
- //
- // receive data.
- //
- pj_ssize_t recv(void *buf, pj_size_t len, int flag = 0)
- {
- pj_ssize_t bytes = len;
- if (pj_sock_recv(sock_, buf, &bytes, flag) != PJ_SUCCESS)
- return -1;
- return bytes;
- }
-
- //
- // send data.
- //
- pj_ssize_t send(const void *buf, pj_ssize_t len, int flag = 0)
- {
- pj_ssize_t bytes = len;
- if (pj_sock_send(sock_, buf, &bytes, flag) != PJ_SUCCESS)
- return -1;
- return bytes;
- }
-
- //
- // connect.
- //
- pj_status_t connect(const Pj_Inet_Addr &addr)
- {
- return pj_sock_connect(sock_, &addr, sizeof(Pj_Inet_Addr));
- }
-
- //
- // assignment.
- //
- Pj_Socket &operator=(const Pj_Socket &rhs)
- {
- sock_ = rhs.sock_;
- return *this;
- }
-
-protected:
- friend class Pj_Event_Handler;
- pj_sock_t sock_;
-};
-
-
-#if PJ_HAS_TCP
-//
-// Stream socket.
-//
-class Pj_Sock_Stream : public Pj_Socket
-{
-public:
- //
- // Default constructor.
- //
- Pj_Sock_Stream()
- {
- }
-
- //
- // Initialize from a socket handle.
- //
- explicit Pj_Sock_Stream(pj_sock_t sock)
- : Pj_Socket(sock)
- {
- }
-
- //
- // Copy constructor.
- //
- Pj_Sock_Stream(const Pj_Sock_Stream &rhs) : Pj_Socket(rhs)
- {
- }
-
- //
- // Assignment.
- //
- Pj_Sock_Stream &operator=(const Pj_Sock_Stream &rhs)
- {
- sock_ = rhs.sock_;
- return *this;
- }
-
- //
- // listen()
- //
- pj_status_t listen(int backlog = 5)
- {
- return pj_sock_listen(sock_, backlog);
- }
-
- //
- // blocking accept()
- //
- Pj_Sock_Stream accept(Pj_Inet_Addr *remote_addr = NULL)
- {
- pj_sock_t newsock;
- int *addrlen = remote_addr ? &remote_addr->addrlen_ : NULL;
- pj_status_t status;
-
- status = pj_sock_accept(sock_, &newsock, remote_addr, addrlen);
- if (status != PJ_SUCCESS)
- return Pj_Sock_Stream(-1);
-
- return Pj_Sock_Stream(newsock);
- }
-
- //
- // shutdown()
- //
- pj_status_t shutdown(int how = PJ_SHUT_RDWR)
- {
- return pj_sock_shutdown(sock_, how);
- }
-
-};
-#endif
-
-//
-// Datagram socket.
-//
-class Pj_Sock_Dgram : public Pj_Socket
-{
-public:
- //
- // Default constructor.
- //
- Pj_Sock_Dgram()
- {
- }
-
- //
- // Initialize from a socket handle.
- //
- explicit Pj_Sock_Dgram(pj_sock_t sock)
- : Pj_Socket(sock)
- {
- }
-
- //
- // Copy constructor.
- //
- Pj_Sock_Dgram(const Pj_Sock_Dgram &rhs)
- : Pj_Socket(rhs)
- {
- }
-
- //
- // Assignment.
- //
- Pj_Sock_Dgram &operator=(const Pj_Sock_Dgram &rhs)
- {
- Pj_Socket::operator =(rhs);
- return *this;
- }
-
- //
- // recvfrom()
- //
- pj_ssize_t recvfrom( void *buf, pj_size_t len, int flag = 0,
- Pj_Inet_Addr *fromaddr = NULL)
- {
- pj_ssize_t bytes = len;
- int *addrlen = fromaddr ? &fromaddr->addrlen_ : NULL;
- if (pj_sock_recvfrom( sock_, buf, &bytes, flag,
- fromaddr, addrlen) != PJ_SUCCESS)
- {
- return -1;
- }
- return bytes;
- }
-
- //
- // sendto()
- //
- pj_ssize_t sendto( const void *buf, pj_size_t len, int flag,
- const Pj_Inet_Addr &addr)
- {
- pj_ssize_t bytes = len;
- if (pj_sock_sendto( sock_, buf, &bytes, flag,
- &addr, sizeof(pj_sockaddr_in)) != PJ_SUCCESS)
- {
- return -1;
- }
- return bytes;
- }
-};
-
-
-#endif /* __PJPP_SOCK_H__ */
+ */
+#ifndef __PJPP_SOCK_HPP__
+#define __PJPP_SOCK_HPP__
+
+#include <pj/sock.h>
+#include <pj/string.h>
+
+class Pj_Event_Handler;
+
+//
+// Base class for address.
+//
+class Pj_Addr
+{
+};
+
+//
+// Internet address.
+//
+class Pj_Inet_Addr : public pj_sockaddr_in, public Pj_Addr
+{
+public:
+ //
+ // Get port number.
+ //
+ pj_uint16_t get_port_number() const
+ {
+ return pj_sockaddr_in_get_port(this);
+ }
+
+ //
+ // Set port number.
+ //
+ void set_port_number(pj_uint16_t port)
+ {
+ sin_family = PJ_AF_INET;
+ pj_sockaddr_in_set_port(this, port);
+ }
+
+ //
+ // Get IP address.
+ //
+ pj_uint32_t get_ip_address() const
+ {
+ return pj_sockaddr_in_get_addr(this).s_addr;
+ }
+
+ //
+ // Get address string.
+ //
+ const char *get_address() const
+ {
+ return pj_inet_ntoa(sin_addr);
+ }
+
+ //
+ // Set IP address.
+ //
+ void set_ip_address(pj_uint32_t addr)
+ {
+ sin_family = PJ_AF_INET;
+ pj_sockaddr_in_set_addr(this, addr);
+ }
+
+ //
+ // Set address.
+ //
+ pj_status_t set_address(const pj_str_t *addr)
+ {
+ return pj_sockaddr_in_set_str_addr(this, addr);
+ }
+
+ //
+ // Set address.
+ //
+ pj_status_t set_address(const char *addr)
+ {
+ pj_str_t s;
+ return pj_sockaddr_in_set_str_addr(this, pj_cstr(&s, addr));
+ }
+
+ //
+ // Compare for equality.
+ //
+ bool operator==(const Pj_Inet_Addr &rhs) const
+ {
+ return sin_family == rhs.sin_family &&
+ sin_addr.s_addr == rhs.sin_addr.s_addr &&
+ sin_port == rhs.sin_port;
+ }
+
+private:
+ //
+ // Dummy length used in pj_ioqueue_recvfrom() etc
+ //
+ friend class Pj_Event_Handler;
+ friend class Pj_Socket;
+ friend class Pj_Sock_Stream;
+ friend class Pj_Sock_Dgram;
+
+ int addrlen_;
+};
+
+
+//
+// Socket base class.
+//
+// Note:
+// socket will not automatically be closed on destructor.
+//
+class Pj_Socket
+{
+public:
+ //
+ // Default constructor.
+ //
+ Pj_Socket()
+ : sock_(PJ_INVALID_SOCKET)
+ {
+ }
+
+ //
+ // Initialize from a socket handle.
+ //
+ explicit Pj_Socket(pj_sock_t sock)
+ : sock_(sock)
+ {
+ }
+
+ //
+ // Copy constructor.
+ //
+ Pj_Socket(const Pj_Socket &rhs)
+ : sock_(rhs.sock_)
+ {
+ }
+
+ //
+ // Destructor will not close the socket.
+ // You must call close() explicitly.
+ //
+ ~Pj_Socket()
+ {
+ }
+
+ //
+ // Set socket handle.
+ //
+ void set_handle(pj_sock_t sock)
+ {
+ sock_ = sock;
+ }
+
+ //
+ // Get socket handle.
+ //
+ pj_sock_t get_handle() const
+ {
+ return sock_;
+ }
+
+ //
+ // Get socket handle.
+ //
+ pj_sock_t& get_handle()
+ {
+ return sock_;
+ }
+
+ //
+ // See if the socket is valid.
+ //
+ bool is_valid() const
+ {
+ return sock_ != PJ_INVALID_SOCKET;
+ }
+
+ //
+ // Create the socket.
+ //
+ pj_status_t create(int af, int type, int proto)
+ {
+ return pj_sock_socket(af, type, proto, &sock_);
+ }
+
+ //
+ // Bind socket.
+ //
+ pj_status_t bind(const Pj_Inet_Addr &addr)
+ {
+ return pj_sock_bind(sock_, &addr, sizeof(Pj_Inet_Addr));
+ }
+
+ //
+ // Close socket.
+ //
+ pj_status_t close()
+ {
+ pj_sock_close(sock_);
+ }
+
+ //
+ // Get peer socket name.
+ //
+ pj_status_t getpeername(Pj_Inet_Addr *addr)
+ {
+ return pj_sock_getpeername(sock_, addr, &addr->addrlen_);
+ }
+
+ //
+ // getsockname
+ //
+ pj_status_t getsockname(Pj_Inet_Addr *addr)
+ {
+ return pj_sock_getsockname(sock_, addr, &addr->addrlen_);
+ }
+
+ //
+ // getsockopt.
+ //
+ pj_status_t getsockopt(int level, int optname,
+ void *optval, int *optlen)
+ {
+ return pj_sock_getsockopt(sock_, level, optname, optval, optlen);
+ }
+
+ //
+ // setsockopt
+ //
+ pj_status_t setsockopt(int level, int optname,
+ const void *optval, int optlen)
+ {
+ return pj_sock_setsockopt(sock_, level, optname, optval, optlen);
+ }
+
+ //
+ // receive data.
+ //
+ pj_ssize_t recv(void *buf, pj_size_t len, int flag = 0)
+ {
+ pj_ssize_t bytes = len;
+ if (pj_sock_recv(sock_, buf, &bytes, flag) != PJ_SUCCESS)
+ return -1;
+ return bytes;
+ }
+
+ //
+ // send data.
+ //
+ pj_ssize_t send(const void *buf, pj_ssize_t len, int flag = 0)
+ {
+ pj_ssize_t bytes = len;
+ if (pj_sock_send(sock_, buf, &bytes, flag) != PJ_SUCCESS)
+ return -1;
+ return bytes;
+ }
+
+ //
+ // connect.
+ //
+ pj_status_t connect(const Pj_Inet_Addr &addr)
+ {
+ return pj_sock_connect(sock_, &addr, sizeof(Pj_Inet_Addr));
+ }
+
+ //
+ // assignment.
+ //
+ Pj_Socket &operator=(const Pj_Socket &rhs)
+ {
+ sock_ = rhs.sock_;
+ return *this;
+ }
+
+protected:
+ friend class Pj_Event_Handler;
+ pj_sock_t sock_;
+};
+
+
+#if PJ_HAS_TCP
+//
+// Stream socket.
+//
+class Pj_Sock_Stream : public Pj_Socket
+{
+public:
+ //
+ // Default constructor.
+ //
+ Pj_Sock_Stream()
+ {
+ }
+
+ //
+ // Initialize from a socket handle.
+ //
+ explicit Pj_Sock_Stream(pj_sock_t sock)
+ : Pj_Socket(sock)
+ {
+ }
+
+ //
+ // Copy constructor.
+ //
+ Pj_Sock_Stream(const Pj_Sock_Stream &rhs) : Pj_Socket(rhs)
+ {
+ }
+
+ //
+ // Assignment.
+ //
+ Pj_Sock_Stream &operator=(const Pj_Sock_Stream &rhs)
+ {
+ sock_ = rhs.sock_;
+ return *this;
+ }
+
+ //
+ // listen()
+ //
+ pj_status_t listen(int backlog = 5)
+ {
+ return pj_sock_listen(sock_, backlog);
+ }
+
+ //
+ // blocking accept()
+ //
+ Pj_Sock_Stream accept(Pj_Inet_Addr *remote_addr = NULL)
+ {
+ pj_sock_t newsock;
+ int *addrlen = remote_addr ? &remote_addr->addrlen_ : NULL;
+ pj_status_t status;
+
+ status = pj_sock_accept(sock_, &newsock, remote_addr, addrlen);
+ if (status != PJ_SUCCESS)
+ return Pj_Sock_Stream(-1);
+
+ return Pj_Sock_Stream(newsock);
+ }
+
+ //
+ // shutdown()
+ //
+ pj_status_t shutdown(int how = PJ_SHUT_RDWR)
+ {
+ return pj_sock_shutdown(sock_, how);
+ }
+
+};
+#endif
+
+//
+// Datagram socket.
+//
+class Pj_Sock_Dgram : public Pj_Socket
+{
+public:
+ //
+ // Default constructor.
+ //
+ Pj_Sock_Dgram()
+ {
+ }
+
+ //
+ // Initialize from a socket handle.
+ //
+ explicit Pj_Sock_Dgram(pj_sock_t sock)
+ : Pj_Socket(sock)
+ {
+ }
+
+ //
+ // Copy constructor.
+ //
+ Pj_Sock_Dgram(const Pj_Sock_Dgram &rhs)
+ : Pj_Socket(rhs)
+ {
+ }
+
+ //
+ // Assignment.
+ //
+ Pj_Sock_Dgram &operator=(const Pj_Sock_Dgram &rhs)
+ {
+ Pj_Socket::operator =(rhs);
+ return *this;
+ }
+
+ //
+ // recvfrom()
+ //
+ pj_ssize_t recvfrom( void *buf, pj_size_t len, int flag = 0,
+ Pj_Inet_Addr *fromaddr = NULL)
+ {
+ pj_ssize_t bytes = len;
+ int *addrlen = fromaddr ? &fromaddr->addrlen_ : NULL;
+ if (pj_sock_recvfrom( sock_, buf, &bytes, flag,
+ fromaddr, addrlen) != PJ_SUCCESS)
+ {
+ return -1;
+ }
+ return bytes;
+ }
+
+ //
+ // sendto()
+ //
+ pj_ssize_t sendto( const void *buf, pj_size_t len, int flag,
+ const Pj_Inet_Addr &addr)
+ {
+ pj_ssize_t bytes = len;
+ if (pj_sock_sendto( sock_, buf, &bytes, flag,
+ &addr, sizeof(pj_sockaddr_in)) != PJ_SUCCESS)
+ {
+ return -1;
+ }
+ return bytes;
+ }
+};
+
+
+#endif /* __PJPP_SOCK_HPP__ */
+
diff --git a/pjlib/include/pj++/string.hpp b/pjlib/include/pj++/string.hpp
index 456e1ff3..6be1e50a 100644
--- a/pjlib/include/pj++/string.hpp
+++ b/pjlib/include/pj++/string.hpp
@@ -1,408 +1,409 @@
/* $Id$
- */
-#ifndef __PJPP_STRING_H__
-#define __PJPP_STRING_H__
-
-#include <pj/string.h>
-#include <pj++/pool.hpp>
-#include <pj/assert.h>
-
-//
-// String wrapper class for pj_str_t.
-//
-class Pj_String : public pj_str_t
-{
-public:
- //
- // Default constructor.
- //
- Pj_String()
- {
- pj_assert(sizeof(Pj_String) == sizeof(pj_str_t));
- ptr=NULL;
- slen=0;
- }
-
- //
- // Construct the buffer from a char*.
- //
- explicit Pj_String(char *str)
- {
- set(str);
- }
-
- //
- // Construct from a const char*.
- //
- Pj_String(Pj_Pool *pool, const char *src)
- {
- set(pool, src);
- }
-
- //
- // Construct from pj_str_t*.
- //
- explicit Pj_String(pj_str_t *s)
- {
- set(s);
- }
-
- //
- // Construct by copying from const pj_str_t*.
- //
- Pj_String(Pj_Pool *pool, const pj_str_t *s)
- {
- set(pool, s);
- }
-
- //
- // Construct from another Pj_String
- //
- explicit Pj_String(Pj_String &rhs)
- {
- set(rhs);
- }
-
- //
- // Construct by copying from Pj_String
- //
- Pj_String(Pj_Pool *pool, const Pj_String &rhs)
- {
- set(pool, rhs);
- }
-
- //
- // Construct from a char* and a length.
- //
- Pj_String(char *str, pj_size_t len)
- {
- set(str, len);
- }
-
- //
- // Construct from pair of pointer.
- //
- Pj_String(char *begin, char *end)
- {
- pj_strset3(this, begin, end);
- }
-
- //
- // Get the length of the string.
- //
- pj_size_t length() const
- {
- return pj_strlen(this);
- }
-
- //
- // Get the length of the string.
- //
- pj_size_t size() const
- {
- return length();
- }
-
- //
- // Get the string buffer.
- //
- const char *buf() const
- {
- return ptr;
- }
-
- //
- // Initialize buffer from char*.
- //
- void set(char *str)
- {
- pj_strset2(this, str);
- }
-
- //
- // Initialize by copying from a const char*.
- //
- void set(Pj_Pool *pool, const char *s)
- {
- pj_strdup2(pool->pool_(), this, s);
- }
-
- //
- // Initialize from pj_str_t*.
- //
- void set(pj_str_t *s)
- {
- pj_strassign(this, s);
- }
-
- //
- // Initialize by copying from const pj_str_t*.
- //
- void set(Pj_Pool *pool, const pj_str_t *s)
- {
- pj_strdup(pool->pool_(), this, s);
- }
-
- //
- // Initialize from char* and length.
- //
- void set(char *str, pj_size_t len)
- {
- pj_strset(this, str, len);
- }
-
- //
- // Initialize from pair of pointers.
- //
- void set(char *begin, char *end)
- {
- pj_strset3(this, begin, end);
- }
-
- //
- // Initialize from other Pj_String.
- //
- void set(Pj_String &rhs)
- {
- pj_strassign(this, &rhs);
- }
-
- //
- // Initialize by copying from a Pj_String*.
- //
- void set(Pj_Pool *pool, const Pj_String *s)
- {
- pj_strdup(pool->pool_(), this, s);
- }
-
- //
- // Initialize by copying from other Pj_String.
- //
- void set(Pj_Pool *pool, const Pj_String &s)
- {
- pj_strdup(pool->pool_(), this, &s);
- }
-
- //
- // Copy the contents of other string.
- //
- void strcpy(const pj_str_t *s)
- {
- pj_strcpy(this, s);
- }
-
- //
- // Copy the contents of other string.
- //
- void strcpy(const Pj_String &rhs)
- {
- pj_strcpy(this, &rhs);
- }
-
- //
- // Copy the contents of other string.
- //
- void strcpy(const char *s)
- {
- pj_strcpy2(this, s);
- }
-
- //
- // Compare string.
- //
- int strcmp(const char *s) const
- {
- return pj_strcmp2(this, s);
- }
-
- //
- // Compare string.
- //
- int strcmp(const pj_str_t *s) const
- {
- return pj_strcmp(this, s);
- }
-
- //
- // Compare string.
- //
- int strcmp(const Pj_String &rhs) const
- {
- return pj_strcmp(this, &rhs);
- }
-
- //
- // Compare string.
- //
- int strncmp(const char *s, pj_size_t len) const
- {
- return pj_strncmp2(this, s, len);
- }
-
- //
- // Compare string.
- //
- int strncmp(const pj_str_t *s, pj_size_t len) const
- {
- return pj_strncmp(this, s, len);
- }
-
- //
- // Compare string.
- //
- int strncmp(const Pj_String &rhs, pj_size_t len) const
- {
- return pj_strncmp(this, &rhs, len);
- }
-
- //
- // Compare string.
- //
- int stricmp(const char *s) const
- {
- return pj_stricmp2(this, s);
- }
-
- //
- // Compare string.
- //
- int stricmp(const pj_str_t *s) const
- {
- return pj_stricmp(this, s);
- }
-
- //
- // Compare string.
- //
- int stricmp(const Pj_String &rhs) const
- {
- return stricmp(&rhs);
- }
-
- //
- // Compare string.
- //
- int strnicmp(const char *s, pj_size_t len) const
- {
- return pj_strnicmp2(this, s, len);
- }
-
- //
- // Compare string.
- //
- int strnicmp(const pj_str_t *s, pj_size_t len) const
- {
- return pj_strnicmp(this, s, len);
- }
-
- //
- // Compare string.
- //
- int strnicmp(const Pj_String &rhs, pj_size_t len) const
- {
- return strnicmp(&rhs, len);
- }
-
- //
- // Compare contents for equality.
- //
- bool operator==(const char *s) const
- {
- return strcmp(s) == 0;
- }
-
- //
- // Compare contents for equality.
- //
- bool operator==(const pj_str_t *s) const
- {
- return strcmp(s) == 0;
- }
-
- //
- // Compare contents for equality.
- //
- bool operator==(const Pj_String &rhs) const
- {
- return pj_strcmp(this, &rhs) == 0;
- }
-
- //
- // Find a character in the string.
- //
- char *strchr(int chr)
- {
- return pj_strchr(this, chr);
- }
-
- //
- // Find a character in the string.
- //
- char *find(int chr)
- {
- return strchr(chr);
- }
-
- //
- // Concatenate string.
- //
- void strcat(const Pj_String &rhs)
- {
- pj_strcat(this, &rhs);
- }
-
- //
- // Left trim.
- //
- void ltrim()
- {
- pj_strltrim(this);
- }
-
- //
- // Right trim.
- //
- void rtrim()
- {
- pj_strrtrim(this);
- }
-
- //
- // Left and right trim.
- //
- void trim()
- {
- pj_strtrim(this);
- }
-
- //
- // Convert to unsigned long.
- //
- unsigned long to_ulong() const
- {
- return pj_strtoul(this);
- }
-
- //
- // Convert from unsigned long.
- //
- void from_ulong(unsigned long value)
- {
- slen = pj_utoa(value, ptr);
- }
-
- //
- // Convert from unsigned long with padding.
- //
- void from_ulong_with_pad(unsigned long value, int min_dig=0, int pad=' ')
- {
- slen = pj_utoa_pad(value, ptr, min_dig, pad);
- }
-
-
-private:
- //Pj_String(const Pj_String &rhs) {}
- void operator=(const Pj_String &rhs) { pj_assert(false); }
-};
-
-#endif /* __PJPP_STRING_H__ */
+ */
+#ifndef __PJPP_STRING_HPP__
+#define __PJPP_STRING_HPP__
+
+#include <pj/string.h>
+#include <pj++/pool.hpp>
+#include <pj/assert.h>
+
+//
+// String wrapper class for pj_str_t.
+//
+class Pj_String : public pj_str_t
+{
+public:
+ //
+ // Default constructor.
+ //
+ Pj_String()
+ {
+ pj_assert(sizeof(Pj_String) == sizeof(pj_str_t));
+ ptr=NULL;
+ slen=0;
+ }
+
+ //
+ // Construct the buffer from a char*.
+ //
+ explicit Pj_String(char *str)
+ {
+ set(str);
+ }
+
+ //
+ // Construct from a const char*.
+ //
+ Pj_String(Pj_Pool *pool, const char *src)
+ {
+ set(pool, src);
+ }
+
+ //
+ // Construct from pj_str_t*.
+ //
+ explicit Pj_String(pj_str_t *s)
+ {
+ set(s);
+ }
+
+ //
+ // Construct by copying from const pj_str_t*.
+ //
+ Pj_String(Pj_Pool *pool, const pj_str_t *s)
+ {
+ set(pool, s);
+ }
+
+ //
+ // Construct from another Pj_String
+ //
+ explicit Pj_String(Pj_String &rhs)
+ {
+ set(rhs);
+ }
+
+ //
+ // Construct by copying from Pj_String
+ //
+ Pj_String(Pj_Pool *pool, const Pj_String &rhs)
+ {
+ set(pool, rhs);
+ }
+
+ //
+ // Construct from a char* and a length.
+ //
+ Pj_String(char *str, pj_size_t len)
+ {
+ set(str, len);
+ }
+
+ //
+ // Construct from pair of pointer.
+ //
+ Pj_String(char *begin, char *end)
+ {
+ pj_strset3(this, begin, end);
+ }
+
+ //
+ // Get the length of the string.
+ //
+ pj_size_t length() const
+ {
+ return pj_strlen(this);
+ }
+
+ //
+ // Get the length of the string.
+ //
+ pj_size_t size() const
+ {
+ return length();
+ }
+
+ //
+ // Get the string buffer.
+ //
+ const char *buf() const
+ {
+ return ptr;
+ }
+
+ //
+ // Initialize buffer from char*.
+ //
+ void set(char *str)
+ {
+ pj_strset2(this, str);
+ }
+
+ //
+ // Initialize by copying from a const char*.
+ //
+ void set(Pj_Pool *pool, const char *s)
+ {
+ pj_strdup2(pool->pool_(), this, s);
+ }
+
+ //
+ // Initialize from pj_str_t*.
+ //
+ void set(pj_str_t *s)
+ {
+ pj_strassign(this, s);
+ }
+
+ //
+ // Initialize by copying from const pj_str_t*.
+ //
+ void set(Pj_Pool *pool, const pj_str_t *s)
+ {
+ pj_strdup(pool->pool_(), this, s);
+ }
+
+ //
+ // Initialize from char* and length.
+ //
+ void set(char *str, pj_size_t len)
+ {
+ pj_strset(this, str, len);
+ }
+
+ //
+ // Initialize from pair of pointers.
+ //
+ void set(char *begin, char *end)
+ {
+ pj_strset3(this, begin, end);
+ }
+
+ //
+ // Initialize from other Pj_String.
+ //
+ void set(Pj_String &rhs)
+ {
+ pj_strassign(this, &rhs);
+ }
+
+ //
+ // Initialize by copying from a Pj_String*.
+ //
+ void set(Pj_Pool *pool, const Pj_String *s)
+ {
+ pj_strdup(pool->pool_(), this, s);
+ }
+
+ //
+ // Initialize by copying from other Pj_String.
+ //
+ void set(Pj_Pool *pool, const Pj_String &s)
+ {
+ pj_strdup(pool->pool_(), this, &s);
+ }
+
+ //
+ // Copy the contents of other string.
+ //
+ void strcpy(const pj_str_t *s)
+ {
+ pj_strcpy(this, s);
+ }
+
+ //
+ // Copy the contents of other string.
+ //
+ void strcpy(const Pj_String &rhs)
+ {
+ pj_strcpy(this, &rhs);
+ }
+
+ //
+ // Copy the contents of other string.
+ //
+ void strcpy(const char *s)
+ {
+ pj_strcpy2(this, s);
+ }
+
+ //
+ // Compare string.
+ //
+ int strcmp(const char *s) const
+ {
+ return pj_strcmp2(this, s);
+ }
+
+ //
+ // Compare string.
+ //
+ int strcmp(const pj_str_t *s) const
+ {
+ return pj_strcmp(this, s);
+ }
+
+ //
+ // Compare string.
+ //
+ int strcmp(const Pj_String &rhs) const
+ {
+ return pj_strcmp(this, &rhs);
+ }
+
+ //
+ // Compare string.
+ //
+ int strncmp(const char *s, pj_size_t len) const
+ {
+ return pj_strncmp2(this, s, len);
+ }
+
+ //
+ // Compare string.
+ //
+ int strncmp(const pj_str_t *s, pj_size_t len) const
+ {
+ return pj_strncmp(this, s, len);
+ }
+
+ //
+ // Compare string.
+ //
+ int strncmp(const Pj_String &rhs, pj_size_t len) const
+ {
+ return pj_strncmp(this, &rhs, len);
+ }
+
+ //
+ // Compare string.
+ //
+ int stricmp(const char *s) const
+ {
+ return pj_stricmp2(this, s);
+ }
+
+ //
+ // Compare string.
+ //
+ int stricmp(const pj_str_t *s) const
+ {
+ return pj_stricmp(this, s);
+ }
+
+ //
+ // Compare string.
+ //
+ int stricmp(const Pj_String &rhs) const
+ {
+ return stricmp(&rhs);
+ }
+
+ //
+ // Compare string.
+ //
+ int strnicmp(const char *s, pj_size_t len) const
+ {
+ return pj_strnicmp2(this, s, len);
+ }
+
+ //
+ // Compare string.
+ //
+ int strnicmp(const pj_str_t *s, pj_size_t len) const
+ {
+ return pj_strnicmp(this, s, len);
+ }
+
+ //
+ // Compare string.
+ //
+ int strnicmp(const Pj_String &rhs, pj_size_t len) const
+ {
+ return strnicmp(&rhs, len);
+ }
+
+ //
+ // Compare contents for equality.
+ //
+ bool operator==(const char *s) const
+ {
+ return strcmp(s) == 0;
+ }
+
+ //
+ // Compare contents for equality.
+ //
+ bool operator==(const pj_str_t *s) const
+ {
+ return strcmp(s) == 0;
+ }
+
+ //
+ // Compare contents for equality.
+ //
+ bool operator==(const Pj_String &rhs) const
+ {
+ return pj_strcmp(this, &rhs) == 0;
+ }
+
+ //
+ // Find a character in the string.
+ //
+ char *strchr(int chr)
+ {
+ return pj_strchr(this, chr);
+ }
+
+ //
+ // Find a character in the string.
+ //
+ char *find(int chr)
+ {
+ return strchr(chr);
+ }
+
+ //
+ // Concatenate string.
+ //
+ void strcat(const Pj_String &rhs)
+ {
+ pj_strcat(this, &rhs);
+ }
+
+ //
+ // Left trim.
+ //
+ void ltrim()
+ {
+ pj_strltrim(this);
+ }
+
+ //
+ // Right trim.
+ //
+ void rtrim()
+ {
+ pj_strrtrim(this);
+ }
+
+ //
+ // Left and right trim.
+ //
+ void trim()
+ {
+ pj_strtrim(this);
+ }
+
+ //
+ // Convert to unsigned long.
+ //
+ unsigned long to_ulong() const
+ {
+ return pj_strtoul(this);
+ }
+
+ //
+ // Convert from unsigned long.
+ //
+ void from_ulong(unsigned long value)
+ {
+ slen = pj_utoa(value, ptr);
+ }
+
+ //
+ // Convert from unsigned long with padding.
+ //
+ void from_ulong_with_pad(unsigned long value, int min_dig=0, int pad=' ')
+ {
+ slen = pj_utoa_pad(value, ptr, min_dig, pad);
+ }
+
+
+private:
+ //Pj_String(const Pj_String &rhs) {}
+ void operator=(const Pj_String &rhs) { pj_assert(false); }
+};
+
+#endif /* __PJPP_STRING_HPP__ */
+
diff --git a/pjlib/include/pj++/timer.hpp b/pjlib/include/pj++/timer.hpp
index b1070421..fbb15f7a 100644
--- a/pjlib/include/pj++/timer.hpp
+++ b/pjlib/include/pj++/timer.hpp
@@ -1,180 +1,181 @@
/* $Id$
- */
-#ifndef __PJPP_TIMER_H__
-#define __PJPP_TIMER_H__
-
-#include <pj/timer.h>
-#include <pj++/types.hpp>
-#include <pj/assert.h>
-#include <pj++/lock.hpp>
-
-class Pj_Timer_Heap;
-
-//////////////////////////////////////////////////////////////////////////////
-// Timer entry.
-//
-// How to use:
-// Derive class from Pj_Timer_Entry and override on_timeout().
-// Scheduler timer in Pj_Timer_Heap.
-//
-class Pj_Timer_Entry : public Pj_Object
-{
- friend class Pj_Timer_Heap;
-
-public:
- //
- // Default constructor.
- //
- Pj_Timer_Entry()
- {
- entry_.user_data = this;
- entry_.cb = &timer_heap_callback;
- }
-
- //
- // Destructor, do nothing.
- //
- ~Pj_Timer_Entry()
- {
- }
-
- //
- // Override this to get the timeout notification.
- //
- virtual void on_timeout(int id) = 0;
-
-private:
- pj_timer_entry entry_;
-
- static void timer_heap_callback(pj_timer_heap_t *th, pj_timer_entry *e)
- {
- Pj_Timer_Entry *entry = (Pj_Timer_Entry*) e->user_data;
- entry->on_timeout(e->id);
- }
-
-};
-
-//////////////////////////////////////////////////////////////////////////////
-// Timer heap.
-//
-class Pj_Timer_Heap : public Pj_Object
-{
-public:
- //
- // Default constructor.
- //
- Pj_Timer_Heap()
- : ht_(NULL)
- {
- }
-
- //
- // Construct timer heap.
- //
- Pj_Timer_Heap(Pj_Pool *pool, pj_size_t initial_count)
- : ht_(NULL)
- {
- create(pool, initial_count);
- }
-
- //
- // Destructor.
- //
- ~Pj_Timer_Heap()
- {
- destroy();
- }
-
- //
- // Create
- //
- pj_status_t create(Pj_Pool *pool, pj_size_t initial_count)
- {
- destroy();
- return pj_timer_heap_create(pool->pool_(), initial_count, &ht_);
- }
-
- //
- // Destroy
- //
- void destroy()
- {
- if (ht_) {
- pj_timer_heap_destroy(ht_);
- ht_ = NULL;
- }
- }
-
- //
- // Get pjlib compatible timer heap object.
- //
- pj_timer_heap_t *get_timer_heap()
- {
- return ht_;
- }
-
- //
- // Set the lock object.
- //
- void set_lock( Pj_Lock *lock, bool auto_delete )
- {
- pj_timer_heap_set_lock( ht_, lock->pj_lock_t_(), auto_delete);
- }
-
- //
- // Set maximum number of timed out entries to be processed per poll.
- //
- unsigned set_max_timed_out_per_poll(unsigned count)
- {
- return pj_timer_heap_set_max_timed_out_per_poll(ht_, count);
- }
-
- //
- // Schedule a timer.
- //
- bool schedule( Pj_Timer_Entry *ent, const Pj_Time_Val &delay,
- int id)
- {
- ent->entry_.id = id;
- return pj_timer_heap_schedule(ht_, &ent->entry_, &delay) == 0;
- }
-
- //
- // Cancel a timer.
- //
- bool cancel(Pj_Timer_Entry *ent)
- {
- return pj_timer_heap_cancel(ht_, &ent->entry_) == 1;
- }
-
- //
- // Get current number of timers
- //
- pj_size_t count()
- {
- return pj_timer_heap_count(ht_);
- }
-
- //
- // Get the earliest time.
- // Return false if no timer is found.
- //
- bool earliest_time(Pj_Time_Val *t)
- {
- return pj_timer_heap_earliest_time(ht_, t) == PJ_SUCCESS;
- }
-
- //
- // Poll the timer.
- // Return number of timed out entries has been called.
- //
- unsigned poll(Pj_Time_Val *next_delay = NULL)
- {
- return pj_timer_heap_poll(ht_, next_delay);
- }
-
-private:
- pj_timer_heap_t *ht_;
-};
-
-#endif /* __PJPP_TIMER_H__ */
+ */
+#ifndef __PJPP_TIMER_HPP__
+#define __PJPP_TIMER_HPP__
+
+#include <pj/timer.h>
+#include <pj++/types.hpp>
+#include <pj/assert.h>
+#include <pj++/lock.hpp>
+
+class Pj_Timer_Heap;
+
+//////////////////////////////////////////////////////////////////////////////
+// Timer entry.
+//
+// How to use:
+// Derive class from Pj_Timer_Entry and override on_timeout().
+// Scheduler timer in Pj_Timer_Heap.
+//
+class Pj_Timer_Entry : public Pj_Object
+{
+ friend class Pj_Timer_Heap;
+
+public:
+ //
+ // Default constructor.
+ //
+ Pj_Timer_Entry()
+ {
+ entry_.user_data = this;
+ entry_.cb = &timer_heap_callback;
+ }
+
+ //
+ // Destructor, do nothing.
+ //
+ ~Pj_Timer_Entry()
+ {
+ }
+
+ //
+ // Override this to get the timeout notification.
+ //
+ virtual void on_timeout(int id) = 0;
+
+private:
+ pj_timer_entry entry_;
+
+ static void timer_heap_callback(pj_timer_heap_t *th, pj_timer_entry *e)
+ {
+ Pj_Timer_Entry *entry = (Pj_Timer_Entry*) e->user_data;
+ entry->on_timeout(e->id);
+ }
+
+};
+
+//////////////////////////////////////////////////////////////////////////////
+// Timer heap.
+//
+class Pj_Timer_Heap : public Pj_Object
+{
+public:
+ //
+ // Default constructor.
+ //
+ Pj_Timer_Heap()
+ : ht_(NULL)
+ {
+ }
+
+ //
+ // Construct timer heap.
+ //
+ Pj_Timer_Heap(Pj_Pool *pool, pj_size_t initial_count)
+ : ht_(NULL)
+ {
+ create(pool, initial_count);
+ }
+
+ //
+ // Destructor.
+ //
+ ~Pj_Timer_Heap()
+ {
+ destroy();
+ }
+
+ //
+ // Create
+ //
+ pj_status_t create(Pj_Pool *pool, pj_size_t initial_count)
+ {
+ destroy();
+ return pj_timer_heap_create(pool->pool_(), initial_count, &ht_);
+ }
+
+ //
+ // Destroy
+ //
+ void destroy()
+ {
+ if (ht_) {
+ pj_timer_heap_destroy(ht_);
+ ht_ = NULL;
+ }
+ }
+
+ //
+ // Get pjlib compatible timer heap object.
+ //
+ pj_timer_heap_t *get_timer_heap()
+ {
+ return ht_;
+ }
+
+ //
+ // Set the lock object.
+ //
+ void set_lock( Pj_Lock *lock, bool auto_delete )
+ {
+ pj_timer_heap_set_lock( ht_, lock->pj_lock_t_(), auto_delete);
+ }
+
+ //
+ // Set maximum number of timed out entries to be processed per poll.
+ //
+ unsigned set_max_timed_out_per_poll(unsigned count)
+ {
+ return pj_timer_heap_set_max_timed_out_per_poll(ht_, count);
+ }
+
+ //
+ // Schedule a timer.
+ //
+ bool schedule( Pj_Timer_Entry *ent, const Pj_Time_Val &delay,
+ int id)
+ {
+ ent->entry_.id = id;
+ return pj_timer_heap_schedule(ht_, &ent->entry_, &delay) == 0;
+ }
+
+ //
+ // Cancel a timer.
+ //
+ bool cancel(Pj_Timer_Entry *ent)
+ {
+ return pj_timer_heap_cancel(ht_, &ent->entry_) == 1;
+ }
+
+ //
+ // Get current number of timers
+ //
+ pj_size_t count()
+ {
+ return pj_timer_heap_count(ht_);
+ }
+
+ //
+ // Get the earliest time.
+ // Return false if no timer is found.
+ //
+ bool earliest_time(Pj_Time_Val *t)
+ {
+ return pj_timer_heap_earliest_time(ht_, t) == PJ_SUCCESS;
+ }
+
+ //
+ // Poll the timer.
+ // Return number of timed out entries has been called.
+ //
+ unsigned poll(Pj_Time_Val *next_delay = NULL)
+ {
+ return pj_timer_heap_poll(ht_, next_delay);
+ }
+
+private:
+ pj_timer_heap_t *ht_;
+};
+
+#endif /* __PJPP_TIMER_HPP__ */
+
diff --git a/pjlib/include/pj++/tree.hpp b/pjlib/include/pj++/tree.hpp
index 7d30c678..f4fe8fc1 100644
--- a/pjlib/include/pj++/tree.hpp
+++ b/pjlib/include/pj++/tree.hpp
@@ -1,112 +1,112 @@
/* $Id$
- *
- */
-#ifndef __PJPP_TREE_H__
-#define __PJPP_TREE_H__
-
-#include <pj/rbtree.h>
-
-//
-// Tree.
-//
-class PJ_Tree
-{
-public:
- typedef pj_rbtree_comp Comp;
- class iterator;
- class reverse_iterator;
-
- class Node : private pj_rbtree_node
- {
- friend class PJ_Tree;
- friend class iterator;
- friend class reverse_iterator;
-
- public:
- Node() {}
- explicit Node(void *data) { user_data = data; }
- void set_user_data(void *data) { user_data = data; }
- void *get_user_data() const { return user_data; }
- };
-
- class iterator
- {
- public:
- iterator() {}
- iterator(const iterator &rhs) : tr_(rhs.tr_), nd_(rhs.nd_) {}
- iterator(pj_rbtree *tr, pj_rbtree_node *nd) : tr_(tr), nd_(nd) {}
- Node *operator*() { return (Node*)nd_; }
- bool operator==(const iterator &rhs) const { return tr_==rhs.tr_ && nd_==rhs.nd_; }
- iterator &operator=(const iterator &rhs) { tr_=rhs.tr_; nd_=rhs.nd_; return *this; }
- void operator++() { nd_=pj_rbtree_next(tr_, nd_); }
- void operator--() { nd_=pj_rbtree_prev(tr_, nd_); }
- protected:
- pj_rbtree *tr_;
- pj_rbtree_node *nd_;
- };
-
- class reverse_iterator : public iterator
- {
- public:
- reverse_iterator() {}
- reverse_iterator(const reverse_iterator &it) : iterator(it) {}
- reverse_iterator(pj_rbtree *t, pj_rbtree_node *n) : iterator(t, n) {}
- reverse_iterator &operator=(const reverse_iterator &rhs) { iterator::operator=(rhs); return *this; }
- Node *operator*() { return (Node*)nd_; }
- bool operator==(const reverse_iterator &rhs) const { return iterator::operator==(rhs); }
- void operator++() { nd_=pj_rbtree_prev(tr_, nd_); }
- void operator--() { nd_=pj_rbtree_next(tr_, nd_); }
- };
-
- explicit PJ_Tree(Comp *comp) { pj_rbtree_init(&t_, comp); }
-
- iterator begin()
- {
- return iterator(&t_, pj_rbtree_first(&t_));
- }
-
- iterator end()
- {
- return iterator(&t_, NULL);
- }
-
- reverse_iterator rbegin()
- {
- return reverse_iterator(&t_, pj_rbtree_last(&t_));
- }
-
- reverse_iterator rend()
- {
- return reverse_iterator(&t_, NULL);
- }
-
- bool insert(Node *node)
- {
- return pj_rbtree_insert(&t_, node)==0 ? true : false;
- }
-
- Node *find(const void *key)
- {
- return (Node*)pj_rbtree_find(&t_, key);
- }
-
- Node *erase(Node *node)
- {
- return (Node*)pj_rbtree_erase(&t_, node);
- }
-
- unsigned max_height(Node *node=NULL)
- {
- return pj_rbtree_max_height(&t_, node);
- }
-
- unsigned min_height(Node *node=NULL)
- {
- return pj_rbtree_min_height(&t_, node);
- }
-
-private:
- pj_rbtree t_;
-};
-
-#endif /* __PJPP_TREE_H__ */
+ */
+#ifndef __PJPP_TREE_HPP__
+#define __PJPP_TREE_HPP__
+
+#include <pj/rbtree.h>
+
+//
+// Tree.
+//
+class PJ_Tree
+{
+public:
+ typedef pj_rbtree_comp Comp;
+ class iterator;
+ class reverse_iterator;
+
+ class Node : private pj_rbtree_node
+ {
+ friend class PJ_Tree;
+ friend class iterator;
+ friend class reverse_iterator;
+
+ public:
+ Node() {}
+ explicit Node(void *data) { user_data = data; }
+ void set_user_data(void *data) { user_data = data; }
+ void *get_user_data() const { return user_data; }
+ };
+
+ class iterator
+ {
+ public:
+ iterator() {}
+ iterator(const iterator &rhs) : tr_(rhs.tr_), nd_(rhs.nd_) {}
+ iterator(pj_rbtree *tr, pj_rbtree_node *nd) : tr_(tr), nd_(nd) {}
+ Node *operator*() { return (Node*)nd_; }
+ bool operator==(const iterator &rhs) const { return tr_==rhs.tr_ && nd_==rhs.nd_; }
+ iterator &operator=(const iterator &rhs) { tr_=rhs.tr_; nd_=rhs.nd_; return *this; }
+ void operator++() { nd_=pj_rbtree_next(tr_, nd_); }
+ void operator--() { nd_=pj_rbtree_prev(tr_, nd_); }
+ protected:
+ pj_rbtree *tr_;
+ pj_rbtree_node *nd_;
+ };
+
+ class reverse_iterator : public iterator
+ {
+ public:
+ reverse_iterator() {}
+ reverse_iterator(const reverse_iterator &it) : iterator(it) {}
+ reverse_iterator(pj_rbtree *t, pj_rbtree_node *n) : iterator(t, n) {}
+ reverse_iterator &operator=(const reverse_iterator &rhs) { iterator::operator=(rhs); return *this; }
+ Node *operator*() { return (Node*)nd_; }
+ bool operator==(const reverse_iterator &rhs) const { return iterator::operator==(rhs); }
+ void operator++() { nd_=pj_rbtree_prev(tr_, nd_); }
+ void operator--() { nd_=pj_rbtree_next(tr_, nd_); }
+ };
+
+ explicit PJ_Tree(Comp *comp) { pj_rbtree_init(&t_, comp); }
+
+ iterator begin()
+ {
+ return iterator(&t_, pj_rbtree_first(&t_));
+ }
+
+ iterator end()
+ {
+ return iterator(&t_, NULL);
+ }
+
+ reverse_iterator rbegin()
+ {
+ return reverse_iterator(&t_, pj_rbtree_last(&t_));
+ }
+
+ reverse_iterator rend()
+ {
+ return reverse_iterator(&t_, NULL);
+ }
+
+ bool insert(Node *node)
+ {
+ return pj_rbtree_insert(&t_, node)==0 ? true : false;
+ }
+
+ Node *find(const void *key)
+ {
+ return (Node*)pj_rbtree_find(&t_, key);
+ }
+
+ Node *erase(Node *node)
+ {
+ return (Node*)pj_rbtree_erase(&t_, node);
+ }
+
+ unsigned max_height(Node *node=NULL)
+ {
+ return pj_rbtree_max_height(&t_, node);
+ }
+
+ unsigned min_height(Node *node=NULL)
+ {
+ return pj_rbtree_min_height(&t_, node);
+ }
+
+private:
+ pj_rbtree t_;
+};
+
+#endif /* __PJPP_TREE_HPP__ */
+
diff --git a/pjlib/include/pj++/types.hpp b/pjlib/include/pj++/types.hpp
index 637c1222..3155eb02 100644
--- a/pjlib/include/pj++/types.hpp
+++ b/pjlib/include/pj++/types.hpp
@@ -1,144 +1,144 @@
/* $Id$
- *
- */
-#ifndef __PJPP_TYPES_H__
-#define __PJPP_TYPES_H__
-
-#include <pj/types.h>
-
-class Pj_Pool;
-class Pj_Socket ;
-class Pj_Lock;
-
-
-//
-// PJLIB initializer.
-//
-class Pjlib
-{
-public:
- Pjlib()
- {
- pj_init();
- }
-};
-
-//
-// Class Pj_Object is declared in pool.hpp
-//
-
-//
-// Time value wrapper.
-//
-class Pj_Time_Val : public pj_time_val
-{
-public:
- Pj_Time_Val()
- {
- }
-
- Pj_Time_Val(long init_sec, long init_msec)
- {
- sec = init_sec;
- msec = init_msec;
- }
-
- Pj_Time_Val(const Pj_Time_Val &rhs)
- {
- sec=rhs.sec;
- msec=rhs.msec;
- }
-
- explicit Pj_Time_Val(const pj_time_val &tv)
- {
- sec = tv.sec;
- msec = tv.msec;
- }
-
- long get_sec() const
- {
- return sec;
- }
-
- long get_msec() const
- {
- return msec;
- }
-
- void set_sec (long s)
- {
- sec = s;
- }
-
- void set_msec(long ms)
- {
- msec = ms;
- normalize();
- }
-
- long to_msec() const
- {
- return PJ_TIME_VAL_MSEC((*this));
- }
-
- bool operator == (const Pj_Time_Val &rhs) const
- {
- return PJ_TIME_VAL_EQ((*this), rhs);
- }
-
- bool operator > (const Pj_Time_Val &rhs) const
- {
- return PJ_TIME_VAL_GT((*this), rhs);
- }
-
- bool operator >= (const Pj_Time_Val &rhs) const
- {
- return PJ_TIME_VAL_GTE((*this), rhs);
- }
-
- bool operator < (const Pj_Time_Val &rhs) const
- {
- return PJ_TIME_VAL_LT((*this), rhs);
- }
-
- bool operator <= (const Pj_Time_Val &rhs) const
- {
- return PJ_TIME_VAL_LTE((*this), rhs);
- }
-
- Pj_Time_Val & operator = (const Pj_Time_Val &rhs)
- {
- sec = rhs.sec;
- msec = rhs.msec;
- return *this;
- }
-
- Pj_Time_Val & operator += (const Pj_Time_Val &rhs)
- {
- PJ_TIME_VAL_ADD((*this), rhs);
- return *this;
- }
-
- Pj_Time_Val & operator -= (const Pj_Time_Val &rhs)
- {
- PJ_TIME_VAL_SUB((*this), rhs);
- return *this;
- }
-
- /* Must include os.hpp to use these, otherwise unresolved in linking */
- inline pj_status_t gettimeofday();
- inline pj_parsed_time decode();
- inline pj_status_t encode(const pj_parsed_time *pt);
- inline pj_status_t to_gmt();
- inline pj_status_t to_local();
-
-
-private:
- void normalize()
- {
- pj_time_val_normalize(this);
- }
-
-};
-
-#endif /* __PJPP_TYPES_H__ */
+ */
+#ifndef __PJPP_TYPES_HPP__
+#define __PJPP_TYPES_HPP__
+
+#include <pj/types.h>
+
+class Pj_Pool;
+class Pj_Socket ;
+class Pj_Lock;
+
+
+//
+// PJLIB initializer.
+//
+class Pjlib
+{
+public:
+ Pjlib()
+ {
+ pj_init();
+ }
+};
+
+//
+// Class Pj_Object is declared in pool.hpp
+//
+
+//
+// Time value wrapper.
+//
+class Pj_Time_Val : public pj_time_val
+{
+public:
+ Pj_Time_Val()
+ {
+ }
+
+ Pj_Time_Val(long init_sec, long init_msec)
+ {
+ sec = init_sec;
+ msec = init_msec;
+ }
+
+ Pj_Time_Val(const Pj_Time_Val &rhs)
+ {
+ sec=rhs.sec;
+ msec=rhs.msec;
+ }
+
+ explicit Pj_Time_Val(const pj_time_val &tv)
+ {
+ sec = tv.sec;
+ msec = tv.msec;
+ }
+
+ long get_sec() const
+ {
+ return sec;
+ }
+
+ long get_msec() const
+ {
+ return msec;
+ }
+
+ void set_sec (long s)
+ {
+ sec = s;
+ }
+
+ void set_msec(long ms)
+ {
+ msec = ms;
+ normalize();
+ }
+
+ long to_msec() const
+ {
+ return PJ_TIME_VAL_MSEC((*this));
+ }
+
+ bool operator == (const Pj_Time_Val &rhs) const
+ {
+ return PJ_TIME_VAL_EQ((*this), rhs);
+ }
+
+ bool operator > (const Pj_Time_Val &rhs) const
+ {
+ return PJ_TIME_VAL_GT((*this), rhs);
+ }
+
+ bool operator >= (const Pj_Time_Val &rhs) const
+ {
+ return PJ_TIME_VAL_GTE((*this), rhs);
+ }
+
+ bool operator < (const Pj_Time_Val &rhs) const
+ {
+ return PJ_TIME_VAL_LT((*this), rhs);
+ }
+
+ bool operator <= (const Pj_Time_Val &rhs) const
+ {
+ return PJ_TIME_VAL_LTE((*this), rhs);
+ }
+
+ Pj_Time_Val & operator = (const Pj_Time_Val &rhs)
+ {
+ sec = rhs.sec;
+ msec = rhs.msec;
+ return *this;
+ }
+
+ Pj_Time_Val & operator += (const Pj_Time_Val &rhs)
+ {
+ PJ_TIME_VAL_ADD((*this), rhs);
+ return *this;
+ }
+
+ Pj_Time_Val & operator -= (const Pj_Time_Val &rhs)
+ {
+ PJ_TIME_VAL_SUB((*this), rhs);
+ return *this;
+ }
+
+ /* Must include os.hpp to use these, otherwise unresolved in linking */
+ inline pj_status_t gettimeofday();
+ inline pj_parsed_time decode();
+ inline pj_status_t encode(const pj_parsed_time *pt);
+ inline pj_status_t to_gmt();
+ inline pj_status_t to_local();
+
+
+private:
+ void normalize()
+ {
+ pj_time_val_normalize(this);
+ }
+
+};
+
+#endif /* __PJPP_TYPES_HPP__ */
+
diff --git a/pjlib/include/pj/compat/string.h b/pjlib/include/pj/compat/string.h
index f637eb2e..b8917387 100644
--- a/pjlib/include/pj/compat/string.h
+++ b/pjlib/include/pj/compat/string.h
@@ -39,5 +39,14 @@
# define strnicmp strncasecmp
#endif
+
+#define pj_native_strcmp strcmp
+#define pj_native_strlen strlen
+#define pj_native_strcpy strcpy
+#define pj_native_strstr strstr
+#define pj_native_strchr strchr
+#define pj_native_strcasecmp strcasecmp
+#define pj_native_strncasecmp strncasecmp
+
#endif /* __PJ_COMPAT_STRING_H__ */
diff --git a/pjlib/include/pj/config.h b/pjlib/include/pj/config.h
index 597c4d9f..0465ac9a 100644
--- a/pjlib/include/pj/config.h
+++ b/pjlib/include/pj/config.h
@@ -147,7 +147,7 @@
* Default: 4
*/
#ifndef PJ_LOG_MAX_LEVEL
-# define PJ_LOG_MAX_LEVEL 4
+# define PJ_LOG_MAX_LEVEL 5
#endif
/**
@@ -403,6 +403,13 @@
# define PJ_TODO(id) TODO___##id:
#endif
+/**
+ * Function attributes to inform that the function may throw exception.
+ *
+ * @param x The exception list, enclosed in parenthesis.
+ */
+#define __pj_throw__(x)
+
/********************************************************************
* Sanity Checks
diff --git a/pjlib/include/pj/errno.h b/pjlib/include/pj/errno.h
index e7b3ab93..b7c62533 100644
--- a/pjlib/include/pj/errno.h
+++ b/pjlib/include/pj/errno.h
@@ -215,6 +215,11 @@ PJ_DECL(pj_str_t) pj_strerror( pj_status_t statcode,
* Operation is cancelled.
*/
#define PJ_ECANCELLED (PJ_ERRNO_START_STATUS + 14)
+/**
+ * @hideinitializer
+ * Object already exists.
+ */
+#define PJ_EEXISTS (PJ_ERRNO_START_STATUS + 14)
/** @} */ /* pj_errnum */
diff --git a/pjlib/include/pj/except.h b/pjlib/include/pj/except.h
index 3f48abdf..8bdda480 100644
--- a/pjlib/include/pj/except.h
+++ b/pjlib/include/pj/except.h
@@ -182,6 +182,7 @@ PJ_DECL(pj_status_t) pj_exception_id_free(pj_exception_id_t id);
* @return The name associated with the specified ID.
*/
PJ_DECL(const char*) pj_exception_id_name(pj_exception_id_t id);
+
/** @} */
diff --git a/pjlib/include/pj/hash.h b/pjlib/include/pj/hash.h
index 8e39d652..b1eb9d9f 100644
--- a/pjlib/include/pj/hash.h
+++ b/pjlib/include/pj/hash.h
@@ -44,6 +44,21 @@ PJ_BEGIN_DECL
PJ_DECL(pj_uint32_t) pj_hash_calc(pj_uint32_t hval,
const void *key, unsigned keylen);
+
+/**
+ * Convert the key to lowercase and calculate the hash value. The resulting
+ * string is stored in \c result.
+ *
+ * @param hval The initial hash value, normally zero.
+ * @param result Buffer to store the result, which must be enough to hold
+ * the string.
+ * @param key The input key to be converted and calculated.
+ *
+ * @return The hash value.
+ */
+PJ_DECL(pj_uint32_t) pj_hash_calc_tolower(pj_uint32_t hval,
+ char *result,
+ const pj_str_t *key);
/**
* Create a hash table with the specified 'bucket' size.
diff --git a/pjlib/include/pj/ioqueue.h b/pjlib/include/pj/ioqueue.h
index c44b7ced..d1aea694 100644
--- a/pjlib/include/pj/ioqueue.h
+++ b/pjlib/include/pj/ioqueue.h
@@ -341,9 +341,19 @@ PJ_DECL(pj_status_t) pj_ioqueue_set_user_data( pj_ioqueue_key_t *key,
/**
+ * Initialize operation key.
+ *
+ * @param op_key The operation key to be initialied.
+ * @param size The size of the operation key.
+ */
+PJ_DECL(void) pj_ioqueue_op_key_init( pj_ioqueue_op_key_t *op_key,
+ pj_size_t size );
+
+/**
* Check if operation is pending on the specified operation key.
- * The \c op_key must have been submitted as pending operation before,
- * or otherwise the result is undefined.
+ * The \c op_key must have been initialized with #pj_ioqueue_op_key_init()
+ * or submitted as pending operation before, or otherwise the result
+ * is undefined.
*
* @param key The key.
* @param op_key The operation key, previously submitted to any of
diff --git a/pjlib/include/pj/string.h b/pjlib/include/pj/string.h
index 3c7a2ada..5b7ac130 100644
--- a/pjlib/include/pj/string.h
+++ b/pjlib/include/pj/string.h
@@ -12,6 +12,9 @@
#include <pj/types.h>
#include <pj/compat/string.h>
+#include <pj/compat/sprintf.h>
+#include <pj/compat/vsprintf.h>
+
PJ_BEGIN_DECL
diff --git a/pjlib/src/pj/errno.c b/pjlib/src/pj/errno.c
index 25bf5b7f..5a986514 100644
--- a/pjlib/src/pj/errno.c
+++ b/pjlib/src/pj/errno.c
@@ -30,7 +30,8 @@ static const struct
{ PJ_EBUSY, "Object is busy"},
{ PJ_ENOTSUP, "Option/operation is not supported"},
{ PJ_EINVALIDOP, "Invalid operation"},
- { PJ_ECANCELLED, "Operation cancelled"}
+ { PJ_ECANCELLED, "Operation cancelled"},
+ { PJ_EEXISTS, "Object already exists" }
};
/*
diff --git a/pjlib/src/pj/hash.c b/pjlib/src/pj/hash.c
index 0fa95e1b..195c8817 100644
--- a/pjlib/src/pj/hash.c
+++ b/pjlib/src/pj/hash.c
@@ -50,6 +50,20 @@ PJ_DEF(pj_uint32_t) pj_hash_calc(pj_uint32_t hash, const void *key, unsigned key
}
return hash;
}
+
+PJ_DEF(pj_uint32_t) pj_hash_calc_tolower( pj_uint32_t hval,
+ char *result,
+ const pj_str_t *key)
+{
+ long i;
+
+ for (i=0; i<key->slen; ++i) {
+ result[i] = (char)pj_tolower(key->ptr[i]);
+ hval = hval * PJ_HASH_MULTIPLIER + result[i];
+ }
+
+ return hval;
+}
PJ_DEF(pj_hash_table_t*) pj_hash_create(pj_pool_t *pool, unsigned size)
diff --git a/pjlib/src/pj/ioqueue_common_abs.c b/pjlib/src/pj/ioqueue_common_abs.c
index 75774ede..c2e11211 100644
--- a/pjlib/src/pj/ioqueue_common_abs.c
+++ b/pjlib/src/pj/ioqueue_common_abs.c
@@ -832,6 +832,14 @@ PJ_DEF(pj_status_t) pj_ioqueue_connect( pj_ioqueue_key_t *key,
}
}
#endif /* PJ_HAS_TCP */
+
+
+PJ_DEF(void) pj_ioqueue_op_key_init( pj_ioqueue_op_key_t *op_key,
+ pj_size_t size )
+{
+ pj_memset(op_key, 0, size);
+}
+
/*
* pj_ioqueue_is_pending()
diff --git a/pjlib/src/pj/ioqueue_winnt.c b/pjlib/src/pj/ioqueue_winnt.c
index 93cbb6d5..777cb6be 100644
--- a/pjlib/src/pj/ioqueue_winnt.c
+++ b/pjlib/src/pj/ioqueue_winnt.c
@@ -892,6 +892,11 @@ PJ_DEF(pj_status_t) pj_ioqueue_connect( pj_ioqueue_key_t *key,
#endif /* #if PJ_HAS_TCP */
+PJ_DEF(void) pj_ioqueue_op_key_init( pj_ioqueue_op_key_t *op_key,
+ pj_size_t size )
+{
+ pj_memset(op_key, 0, size);
+}
PJ_DEF(pj_bool_t) pj_ioqueue_is_pending( pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key )
diff --git a/pjsip/build/TODO.txt b/pjsip/build/TODO.txt
deleted file mode 100644
index 670e2bff..00000000
--- a/pjsip/build/TODO.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-- regc refresh automatically
-- if dialog CANCEL return 481, disconnect the dialog
-- presence implement callback from event_sub
-- presence supports multiple tuples!
-- implement event headers!
-
-Prio Task
- 10 General authentication framework in pjsua.
- 10 Start on SUBSCRIBE/NOTIFY framework.
- 10 Refactor pjsip_event
----
- 10 Concurrency in pool factory because endpt pool is shared by app.
- Choices:
- - another pool factory (thread safe) for app ==> waste memory.
- - endpt pool is thread safe ==> slow
- 10 Sound in Linux
- 10 Support TCP
- 10 Per instance configuration:
- - max number of tsxs
- - max number of dialogs
- - socket buffer size
diff --git a/pjsip/build/pjsip_core.dsp b/pjsip/build/pjsip_core.dsp
index 0703f914..2204a6f3 100644
--- a/pjsip/build/pjsip_core.dsp
+++ b/pjsip/build/pjsip_core.dsp
@@ -32,16 +32,16 @@ RSC=rc.exe
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Output_Dir ".\output\pjsip-core-i386-win32-vc6-release"
+# PROP BASE Intermediate_Dir ".\output\pjsip-core-i386-win32-vc6-release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
-# PROP Output_Dir ".\output\pjsip_core_vc6_Release"
-# PROP Intermediate_Dir ".\output\pjsip_core_vc6_Release"
+# PROP Output_Dir ".\output\pjsip-core-i386-win32-vc6-release"
+# PROP Intermediate_Dir ".\output\pjsip-core-i386-win32-vc6-release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD CPP /nologo /MD /W4 /Zi /O2 /I "../src" /I "../../pjlib/src" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FR /FD /c
+# ADD CPP /nologo /MD /W4 /Zi /O2 /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
@@ -50,22 +50,22 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo /out:"../lib/pjsip_core_vc6s.lib"
+# ADD LIB32 /nologo /out:"../lib/pjsip-core-i386-win32-vc6-release.lib"
!ELSEIF "$(CFG)" == "pjsip_core - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Output_Dir ".\output\pjsip-core-i386-win32-vc6-debug"
+# PROP BASE Intermediate_Dir ".\output\pjsip-core-i386-win32-vc6-debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
-# PROP Output_Dir ".\output\pjsip_core_vc6_Debug"
-# PROP Intermediate_Dir ".\output\pjsip_core_vc6_Debug"
+# PROP Output_Dir ".\output\pjsip-core-i386-win32-vc6-debug"
+# PROP Intermediate_Dir ".\output\pjsip-core-i386-win32-vc6-debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../src" /I "../../pjlib/src" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /FD /GZ /c
+# ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /GZ /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
@@ -74,7 +74,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo /out:"../lib/pjsip_core_vc6sd.lib"
+# ADD LIB32 /nologo /out:"../lib/pjsip-core-i386-win32-vc6-debug.lib"
!ENDIF
@@ -135,75 +135,79 @@ SOURCE=..\src\pjsip\sip_uri.c
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
-SOURCE=..\src\pjsip_core.h
+SOURCE=..\include\pjsip_core.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\print.h
+SOURCE=..\include\pjsip\print_util.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_auth.h
+SOURCE=..\include\pjsip\sip_auth.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_auth_msg.h
+SOURCE=..\include\pjsip\sip_auth_msg.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_auth_parser.h
+SOURCE=..\include\pjsip\sip_auth_parser.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_config.h
+SOURCE=..\include\pjsip\sip_config.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_endpoint.h
+SOURCE=..\include\pjsip\sip_endpoint.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_event.h
+SOURCE=..\include\pjsip\sip_errno.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_misc.h
+SOURCE=..\include\pjsip\sip_event.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_module.h
+SOURCE=..\include\pjsip\sip_misc.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_msg.h
+SOURCE=..\include\pjsip\sip_module.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_parser.h
+SOURCE=..\include\pjsip\sip_msg.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_private.h
+SOURCE=..\include\pjsip\sip_parser.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_resolve.h
+SOURCE=..\include\pjsip\sip_private.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_transaction.h
+SOURCE=..\include\pjsip\sip_resolve.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_transport.h
+SOURCE=..\include\pjsip\sip_transaction.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_types.h
+SOURCE=..\include\pjsip\sip_transport.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_uri.h
+SOURCE=..\include\pjsip\sip_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\pjsip\sip_uri.h
# End Source File
# End Group
# Begin Group "Inline Files"
@@ -211,7 +215,7 @@ SOURCE=..\src\pjsip\sip_uri.h
# PROP Default_Filter ""
# Begin Source File
-SOURCE=..\src\pjsip\sip_msg_i.h
+SOURCE=..\include\pjsip\sip_msg_i.h
# End Source File
# End Group
# Begin Source File
diff --git a/pjsip/build/pjsip_ua.dsp b/pjsip/build/pjsip_ua.dsp
index efde2534..cd45b10c 100644
--- a/pjsip/build/pjsip_ua.dsp
+++ b/pjsip/build/pjsip_ua.dsp
@@ -87,15 +87,19 @@ LIB32=link.exe -lib
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
-SOURCE=..\src\pjsip_mod_ua\sip_dialog.c
+SOURCE="..\src\pjsip-ua\sip_dialog.c"
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip_mod_ua\sip_reg.c
+SOURCE="..\src\pjsip-ua\sip_reg.c"
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip_mod_ua\sip_ua.c
+SOURCE="..\src\pjsip-ua\sip_ua.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjsip-ua\sip_ua_private.h"
# End Source File
# End Group
# Begin Group "Header Files"
diff --git a/pjsip/build/tounix b/pjsip/build/tounix
deleted file mode 100644
index 82b84c90..00000000
--- a/pjsip/build/tounix
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-name=`basename $1`
-cp $1 /tmp
-cat /tmp/$name | tr -d '\r' > $1
-rm -f /tmp/$name
diff --git a/pjsip/src/pjsip/print.h b/pjsip/include/pjsip/print_util.h
index d1b9850c..b23d45fc 100644
--- a/pjsip/src/pjsip/print.h
+++ b/pjsip/include/pjsip/print_util.h
@@ -1,5 +1,4 @@
/* $Id$
- *
*/
#ifndef __PJSIP_PRINT_H__
#define __PJSIP_PRINT_H__
diff --git a/pjsip/include/pjsip/sip_auth.h b/pjsip/include/pjsip/sip_auth.h
index 3396b669..c34ca030 100644
--- a/pjsip/include/pjsip/sip_auth.h
+++ b/pjsip/include/pjsip/sip_auth.h
@@ -1,5 +1,4 @@
/* $Id$
- *
*/
#ifndef __PJSIP_AUTH_SIP_AUTH_H__
#define __PJSIP_AUTH_SIP_AUTH_H__
@@ -60,7 +59,7 @@ struct pjsip_cred_info
*/
typedef struct pjsip_cached_auth_hdr
{
- PJ_DECL_LIST_MEMBER(struct pjsip_cached_auth_hdr)
+ PJ_DECL_LIST_MEMBER(struct pjsip_cached_auth_hdr);
pjsip_method method;
pjsip_authorization_hdr *hdr;
@@ -80,7 +79,7 @@ typedef struct pjsip_cached_auth_hdr
*/
typedef struct pjsip_auth_session
{
- PJ_DECL_LIST_MEMBER(struct pjsip_auth_session)
+ PJ_DECL_LIST_MEMBER(struct pjsip_auth_session);
pj_str_t realm;
pj_bool_t is_proxy;
diff --git a/pjsip/include/pjsip/sip_auth_msg.h b/pjsip/include/pjsip/sip_auth_msg.h
index ce1ca1e7..8e68331d 100644
--- a/pjsip/include/pjsip/sip_auth_msg.h
+++ b/pjsip/include/pjsip/sip_auth_msg.h
@@ -1,5 +1,4 @@
/* $Id$
- *
*/
#ifndef __PJSIP_AUTH_SIP_AUTH_MSG_H__
#define __PJSIP_AUTH_SIP_AUTH_MSG_H__
@@ -68,7 +67,7 @@ typedef struct pjsip_pgp_credential pjsip_pgp_credential;
*/
struct pjsip_authorization_hdr
{
- PJSIP_DECL_HDR_MEMBER(struct pjsip_authorization_hdr)
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_authorization_hdr);
pj_str_t scheme;
union
{
@@ -157,7 +156,7 @@ typedef struct pjsip_pgp_challenge pjsip_pgp_challenge;
*/
struct pjsip_www_authenticate_hdr
{
- PJSIP_DECL_HDR_MEMBER(struct pjsip_www_authenticate_hdr)
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_www_authenticate_hdr);
pj_str_t scheme;
union
{
diff --git a/pjsip/include/pjsip/sip_auth_parser.h b/pjsip/include/pjsip/sip_auth_parser.h
index 7f280ecd..c1d4f231 100644
--- a/pjsip/include/pjsip/sip_auth_parser.h
+++ b/pjsip/include/pjsip/sip_auth_parser.h
@@ -1,5 +1,4 @@
/* $Id$
- *
*/
#ifndef __PJSIP_AUTH_SIP_AUTH_PARSER_H__
#define __PJSIP_AUTH_SIP_AUTH_PARSER_H__
@@ -23,9 +22,11 @@ PJ_BEGIN_DECL
* Initialize and register authorization parser module.
* This will register parser handler for various Authorization related headers
* such as Authorization, WWW-Authenticate, Proxy-Authorizization, and
- * Proxy-Authenticate headers.
+ * Proxy-Authenticate headers.
+ *
+ * @return PJ_SUCCESS or the appropriate status code.
*/
-PJ_DECL(void) pjsip_auth_init_parser();
+PJ_DECL(pj_status_t) pjsip_auth_init_parser(void);
/**
* DeInitialize authorization parser module.
diff --git a/pjsip/include/pjsip/sip_config.h b/pjsip/include/pjsip/sip_config.h
index a594d488..bba037cb 100644
--- a/pjsip/include/pjsip/sip_config.h
+++ b/pjsip/include/pjsip/sip_config.h
@@ -1,5 +1,4 @@
/* $Id$
- *
*/
#ifndef __PJSIP_SIP_CONFIG_H__
#define __PJSIP_SIP_CONFIG_H__
@@ -133,7 +132,6 @@
#include <pj/config.h>
-#include <pj/compat.h>
#endif /* __PJSIP_SIP_CONFIG_H__ */
diff --git a/pjsip/include/pjsip/sip_endpoint.h b/pjsip/include/pjsip/sip_endpoint.h
index d950657d..e67e2863 100644
--- a/pjsip/include/pjsip/sip_endpoint.h
+++ b/pjsip/include/pjsip/sip_endpoint.h
@@ -1,5 +1,4 @@
/* $Id$
- *
*/
#ifndef __PJSIP_SIP_ENDPOINT_H__
#define __PJSIP_SIP_ENDPOINT_H__
@@ -28,13 +27,15 @@ PJ_BEGIN_DECL
* SIP Endpoint instance (pjsip_endpoint) can be viewed as the master/owner of
* all SIP objects in an application. It performs the following roles:
* - it manages the allocation/deallocation of memory pools for all objects.
- * - it manages listeners and transports, and how they are used by transactions.
+ * - it manages listeners and transports, and how they are used by
+ * transactions.
* - it owns transaction hash table.
* - it receives incoming messages from transport layer and automatically
* dispatches them to the correct transaction (or create a new one).
* - it has a single instance of timer management (timer heap).
* - it manages modules, which is the primary means of extending the library.
- * - it provides single polling function for all objects and distributes events.
+ * - it provides single polling function for all objects and distributes
+ * events.
* - it provides SIP policy such as which outbound proxy to use for all
* outgoing SIP request messages.
* - it automatically handles incoming requests which can not be handled by
@@ -49,15 +50,22 @@ PJ_BEGIN_DECL
/**
* Create an instance of SIP endpoint from the specified pool factory.
- * The pool factory reference then will be kept by the endpoint, so that future
- * memory allocations by SIP components will be taken from the same pool factory.
- *
- * @param pf Pool factory that will be used for the lifetime of endpoint.
- *
- * @return the endpoint instance on success.
+ * The pool factory reference then will be kept by the endpoint, so that
+ * future memory allocations by SIP components will be taken from the same
+ * pool factory.
+ *
+ * @param pf Pool factory that will be used for the lifetime of
+ * endpoint.
+ * @param name Optional name to be specified for the endpoint.
+ * If this parameter is NULL, then the name will use
+ * local host name.
+ * @param endpt Pointer to receive endpoint instance.
+ *
+ * @return PJ_SUCCESS on success.
*/
-PJ_DECL(pjsip_endpoint*) pjsip_endpt_create(pj_pool_factory *pf);
-
+PJ_DECL(pj_status_t) pjsip_endpt_create(pj_pool_factory *pf,
+ pjsip_endpoint **endpt);
+
/**
* Destroy endpoint instance. Application must make sure that all pending
* transactions have been terminated properly, because this function does not
@@ -66,6 +74,16 @@ PJ_DECL(pjsip_endpoint*) pjsip_endpt_create(pj_pool_factory *pf);
* @param endpt The SIP endpoint to be destroyed.
*/
PJ_DECL(void) pjsip_endpt_destroy(pjsip_endpoint *endpt);
+
+/**
+ * Get endpoint name.
+ *
+ * @param endpt The SIP endpoint instance.
+ *
+ * @return Endpoint name, as was registered during endpoint
+ * creation. The string is NULL terminated.
+ */
+PJ_DECL(const pj_str_t*) pjsip_endpt_name(const pjsip_endpoint *endpt);
/**
* Poll for events. Application must call this function periodically to ensure
@@ -153,10 +171,13 @@ PJ_DECL(void) pjsip_endpt_cancel_timer( pjsip_endpoint *endpt,
* transaction to endpoint with #pjsip_endpt_register_tsx.
* This function, like all other endpoint functions, is thread safe.
*
- * @param endpt The SIP endpoint.
- * @return The new transaction, or NULL on failure.
+ * @param endpt The SIP endpoint.
+ * @param p_tsx Pointer to receive the transaction.
+ *
+ * @return PJ_SUCCESS or the appropriate error code.
*/
-PJ_DECL(pjsip_transaction*) pjsip_endpt_create_tsx(pjsip_endpoint *endpt);
+PJ_DECL(pj_status_t) pjsip_endpt_create_tsx(pjsip_endpoint *endpt,
+ pjsip_transaction **p_tsx);
/**
* Register the transaction to the endpoint's transaction table.
@@ -187,10 +208,13 @@ PJ_DECL(void) pjsip_endpt_destroy_tsx( pjsip_endpoint *endpt,
* Create a new transmit data buffer.
* This function, like all other endpoint functions, is thread safe.
*
- * @param endpt the endpoint.
- * @return new transmit data.
+ * @param endpt The endpoint.
+ * @param p_tdata Pointer to receive transmit data buffer.
+ *
+ * @return PJ_SUCCESS or the appropriate error code.
*/
-PJ_DECL(pjsip_tx_data*) pjsip_endpt_create_tdata( pjsip_endpoint *endpt );
+PJ_DECL(pj_status_t) pjsip_endpt_create_tdata( pjsip_endpoint *endpt,
+ pjsip_tx_data **p_tdata);
/**
* Asynchronously resolve a SIP target host or domain according to rule
@@ -330,6 +354,24 @@ PJ_DECL(pj_status_t) pjsip_endpt_set_proxies( pjsip_endpoint *endpt,
* @return List of "Route" header.
*/
PJ_DECL(const pjsip_route_hdr*) pjsip_endpt_get_routing( pjsip_endpoint *endpt );
+
+/**
+ * Log an error.
+ */
+PJ_DECL(void) pjsip_endpt_log_error( pjsip_endpoint *endpt,
+ const char *sender,
+ pj_status_t error_code,
+ const char *format,
+ ... );
+
+#define PJSIP_ENDPT_LOG_ERROR(expr) \
+ pjsip_endpt_log_error expr
+
+#define PJSIP_ENDPT_TRACE(tracing,expr) \
+ do { \
+ if ((tracing)) \
+ PJ_LOG(4,expr); \
+ } while (0)
/**
* @}
diff --git a/pjsip/include/pjsip/sip_errno.h b/pjsip/include/pjsip/sip_errno.h
new file mode 100644
index 00000000..6e4a6f72
--- /dev/null
+++ b/pjsip/include/pjsip/sip_errno.h
@@ -0,0 +1,86 @@
+/* $Id$
+ */
+#ifndef __PJSIP_SIP_ERRNO_H__
+#define __PJSIP_SIP_ERRNO_H__
+
+#include <pj/errno.h>
+
+/**
+ * Start of error code relative to PJ_ERRNO_START_USER.
+ */
+#define PJSIP_ERRNO_START (PJ_ERRNO_START_USER+10000)
+
+/**
+ * Create error value from SIP status code.
+ * @param code SIP status code.
+ * @return Error code in pj_status_t namespace.
+ */
+#define PJSIP_ERRNO_FROM_SIP_STATUS(code) (PJSIP_ERRNO_START+code)
+
+/**
+ * Get SIP status code from error value.
+ * If conversion to SIP status code is not available, a SIP status code
+ * 599 will be returned.
+ *
+ * @param status Error code in pj_status_t namespace.
+ * @return SIP status code.
+ */
+#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(0) : 599)
+
+
+/**
+ * Start of PJSIP generated error code values.
+ */
+#define PJSIP_ERRNO_START_PJSIP (PJSIP_ERRNO_START + 10000)
+
+/**
+ * @hideinitializer
+ * Missing required header(s).
+ */
+#define PJSIP_EMISSINGHDR (PJSIP_ERRNO_START_PJSIP + 1)
+/**
+ * @hideinitializer
+ * Unsupported URL scheme.
+ */
+#define PJSIP_EINVALIDSCHEME (PJSIP_ERRNO_START_PJSIP + 2)
+/**
+ * @hideinitializer
+ * Transaction has just been destroyed.
+ */
+#define PJSIP_ETSXDESTROYED (PJSIP_ERRNO_START_PJSIP + 3)
+/**
+ * @hideinitializer
+ * Buffer overflow. See also PJSIP_EMSGTOOLONG.
+ */
+#define PJSIP_EOVERFLOW (PJSIP_ERRNO_START_PJSIP + 4)
+/**
+ * @hideinitializer
+ * Message not completely received.
+ */
+#define PJSIP_EPARTIALMSG (PJSIP_ERRNO_START_PJSIP + 5)
+/**
+ * @hideinitializer
+ * Message too long. See also PJSIP_EOVERFLOW.
+ */
+#define PJSIP_EMSGTOOLONG (PJSIP_ERRNO_START_PJSIP + 6)
+/**
+ * @hideinitializer
+ * Buffer is being sent, operation still pending.
+ */
+#define PJSIP_EPENDINGTX (PJSIP_ERRNO_START_PJSIP + 7)
+/**
+ * @hideinitializer
+ * Unsupported transport type.
+ */
+#define PJSIP_EUNSUPTRANSPORT (PJSIP_ERRNO_START_PJSIP + 8)
+/**
+ * @hideinitializer
+ * Invalid Via header in response (sent-by, etc).
+ */
+#define PJSIP_EINVALIDVIA (PJSIP_ERRNO_START_PJSIP + 9)
+
+
+#endif /* __PJSIP_SIP_ERRNO_H__ */
diff --git a/pjsip/include/pjsip/sip_event.h b/pjsip/include/pjsip/sip_event.h
index ac7bc691..98ac3850 100644
--- a/pjsip/include/pjsip/sip_event.h
+++ b/pjsip/include/pjsip/sip_event.h
@@ -1,5 +1,4 @@
/* $Id$
- *
*/
#ifndef __PJSIP_SIP_EVENT_H__
#define __PJSIP_SIP_EVENT_H__
@@ -25,7 +24,7 @@ PJ_BEGIN_DECL
typedef enum pjsip_event_id_e
{
/** Unidentified event. */
- PJSIP_EVENT_UNIDENTIFIED,
+ PJSIP_EVENT_UNKNOWN,
/** Timer event, normally only used internally in transaction. */
PJSIP_EVENT_TIMER,
@@ -40,10 +39,10 @@ typedef enum pjsip_event_id_e
PJSIP_EVENT_TRANSPORT_ERROR,
/** Transaction state changed event. */
- PJSIP_EVENT_TSX_STATE_CHANGED,
+ PJSIP_EVENT_TSX_STATE,
/** 2xx response received event. */
- PJSIP_EVENT_RX_200_RESPONSE,
+ PJSIP_EVENT_RX_200_MSG,
/** ACK request received event. */
PJSIP_EVENT_RX_ACK_MSG,
@@ -55,7 +54,7 @@ typedef enum pjsip_event_id_e
PJSIP_EVENT_USER,
/** On before transmitting message. */
- PJSIP_EVENT_BEFORE_TX,
+ PJSIP_EVENT_PRE_TX_MSG,
} pjsip_event_id_e;
@@ -76,46 +75,208 @@ typedef enum pjsip_event_id_e
struct pjsip_event
{
/** This is necessary so that we can put events as a list. */
- PJ_DECL_LIST_MEMBER(struct pjsip_event)
+ PJ_DECL_LIST_MEMBER(struct pjsip_event);
/** The event type, can be any value of \b pjsip_event_id_e.
- * @see pjsip_event_id_e
*/
pjsip_event_id_e type;
-
- /** This field determines what is the content of \b src (source data).
- */
- pjsip_event_id_e src_type;
-
- /** Source data, which content is dependent on \b src_type.
- * - if src_type==PJSIP_EVENT_RX_MSG, src.rdata is valid.
- * - if src_type==PJSIP_EVENT_TX_MSG, src.tdata is valid.
- * - if src_type==PJSIP_EVENT_TIMER, src.timer is valid.
- */
- union
- {
- pjsip_rx_data *rdata;
- pjsip_tx_data *tdata;
- pj_timer_entry *timer;
- void *data;
- unsigned long udata;
- } src;
-
- /** The object that generates this event. */
- union
- {
- pjsip_transaction *tsx;
- void *ptr;
- unsigned long udata;
- } obj;
-
- /** Other data. */
- union
- {
- long long_data;
- void * ptr_data;
- } data;
+
+ /*
+ * The event body.
+ * By convention, the first member of each struct in the union must be
+ * the pointer which is relevant to the event.
+ */
+ union
+ {
+ /** Timer event. */
+ struct
+ {
+ pj_timer_entry *entry; /**< The timer entry. */
+ } timer;
+
+ /** Transaction state has changed event. */
+ struct
+ {
+ union
+ {
+ pjsip_rx_data *rdata; /**< The incoming message. */
+ pjsip_tx_data *tdata; /**< The outgoing message. */
+ pj_timer_entry *timer; /**< The timer. */
+ pj_status_t status;/**< Transport error status. */
+ void *data; /**< Generic data. */
+ } src;
+ pjsip_transaction *tsx; /**< The transaction. */
+ pjsip_event_id_e type; /**< Type of event source:
+ * - PJSIP_EVENT_TX_MSG
+ * - PJSIP_EVENT_RX_MSG,
+ * - PJSIP_EVENT_TRANSPORT_ERROR
+ * - PJSIP_EVENT_TIMER
+ * - PJSIP_EVENT_USER
+ */
+ } tsx_state;
+
+ /** Message transmission event. */
+ struct
+ {
+ pjsip_tx_data *tdata; /**< The transmit data buffer. */
+ pjsip_transaction *tsx; /**< The transaction. */
+
+ } tx_msg;
+
+ /** Pre-transmission event. */
+ struct
+ {
+ pjsip_tx_data *tdata; /**< Msg to be transmitted. */
+ pjsip_transaction *tsx; /**< The transaction. */
+ int retcnt;/**< Retransmission count. */
+ } pre_tx_msg;
+
+ /** Transmission error event. */
+ struct
+ {
+ pjsip_tx_data *tdata; /**< The transmit data. */
+ pjsip_transaction *tsx; /**< The transaction. */
+ } tx_error;
+
+ /** Message arrival event. */
+ struct
+ {
+ pjsip_rx_data *rdata; /**< The receive data buffer. */
+ pjsip_transaction *tsx; /**< The transaction. */
+ } rx_msg;
+
+ /** Receipt of 200/INVITE response. */
+ struct
+ {
+ pjsip_rx_data *rdata; /**< The 200 response msg. */
+ } rx_200_msg;
+
+ /** Receipt of ACK message. */
+ struct
+ {
+ pjsip_rx_data *rdata; /**< The ack message. */
+ } rx_ack_msg;
+
+ /** Notification that endpoint has discarded a message. */
+ struct
+ {
+ pjsip_rx_data *rdata; /**< The discarded message. */
+ pj_status_t reason;/**< The reason. */
+ } discard_msg;
+
+ /** User event. */
+ struct
+ {
+ void *user1; /**< User data 1. */
+ void *user2; /**< User data 2. */
+ void *user3; /**< User data 3. */
+ void *user4; /**< User data 4. */
+ } user;
+
+ } body;
};
+
+/**
+ * Init timer event.
+ */
+#define PJSIP_EVENT_INIT_TIMER(event,pentry) \
+ do { \
+ (event).type = PJSIP_EVENT_TIMER; \
+ (event).body.timer.entry = pentry; \
+ } while (0)
+
+/**
+ * Init tsx state event.
+ */
+#define PJSIP_EVENT_INIT_TSX_STATE(event,ptsx,ptype,pdata) \
+ do { \
+ (event).type = PJSIP_EVENT_TSX_STATE; \
+ (event).body.tsx_state.tsx = ptsx; \
+ (event).body.tsx_state.type = ptype; \
+ (event).body.tsx_state.src.data = pdata; \
+ } while (0)
+
+/**
+ * Init tx msg event.
+ */
+#define PJSIP_EVENT_INIT_TX_MSG(event,ptsx,ptdata) \
+ do { \
+ (event).type = PJSIP_EVENT_TX_MSG; \
+ (event).body.tx_msg.tsx = ptsx; \
+ (event).body.tx_msg.tdata = ptdata; \
+ } while (0)
+
+/**
+ * Init rx msg event.
+ */
+#define PJSIP_EVENT_INIT_RX_MSG(event,ptsx,prdata) \
+ do { \
+ (event).type = PJSIP_EVENT_RX_MSG; \
+ (event).body.rx_msg.tsx = ptsx; \
+ (event).body.rx_msg.rdata = prdata; \
+ } while (0)
+
+/**
+ * Init transport error event.
+ */
+#define PJSIP_EVENT_INIT_TRANSPORT_ERROR(event,ptsx,ptdata) \
+ do { \
+ (event).type = PJSIP_EVENT_TRANSPORT_ERROR; \
+ (event).body.tx_error.tsx = ptsx; \
+ (event).body.tx_error.tdata = ptdata; \
+ } while (0)
+
+/**
+ * Init rx 200/INVITE event.
+ */
+#define PJSIP_EVENT_INIT_RX_200_MSG(event,prdata) \
+ do { \
+ (event).type = PJSIP_EVENT_RX_200_MSG; \
+ (event).body.rx_200_msg.rdata = prdata; \
+ } while (0)
+
+/**
+ * Init rx ack msg event.
+ */
+#define PJSIP_EVENT_INIT_RX_ACK_MSG(event,prdata) \
+ do { \
+ (event).type = PJSIP_EVENT_RX_ACK_MSG; \
+ (event).body.rx_ack_msg.rdata = prdata; \
+ } while (0)
+
+/**
+ * Init discard msg event.
+ */
+#define PJSIP_EVENT_INIT_DISCARD_MSG(event,prdata,preason) \
+ do { \
+ (event).type = PJSIP_EVENT_DISCARD_MSG; \
+ (event).body.discard_msg.rdata = prdata; \
+ (event).body.discard_msg.reason = preason; \
+ } while (0)
+
+/**
+ * Init user event.
+ */
+#define PJSIP_EVENT_INIT_USER(event,u1,u2,u3,u4) \
+ do { \
+ (event).type = PJSIP_EVENT_USER; \
+ (event).body.user.user1 = (void*)u1; \
+ (event).body.user.user2 = (void*)u2; \
+ (event).body.user.user3 = (void*)u3; \
+ (event).body.user.user4 = (void*)u4; \
+ } while (0)
+
+/**
+ * Init pre tx msg event.
+ */
+#define PJSIP_EVENT_INIT_PRE_TX_MSG(event,ptsx,ptdata,pretcnt) \
+ do { \
+ (event).type = PJSIP_EVENT_PRE_TX_MSG; \
+ (event).body.pre_tx_msg.tsx = ptsx; \
+ (event).body.pre_tx_msg.tdata = ptdata; \
+ (event).body.pre_tx_msg.retcnt = pretcnt; \
+ } while (0)
+
/**
* Get the event string from the event ID.
diff --git a/pjsip/include/pjsip/sip_misc.h b/pjsip/include/pjsip/sip_misc.h
index be2ccca9..4101dbc1 100644
--- a/pjsip/include/pjsip/sip_misc.h
+++ b/pjsip/include/pjsip/sip_misc.h
@@ -1,5 +1,4 @@
/* $Id$
- *
*/
#ifndef __PJSIP_SIP_MISC_H__
#define __PJSIP_SIP_MISC_H__
@@ -29,19 +28,21 @@ PJ_BEGIN_DECL
* @param contact URL to put in Contact header.
* @param call_id Optional Call-ID (put NULL to generate unique Call-ID).
* @param cseq Optional CSeq (put -1 to generate random CSeq).
- * @param text Optional text body (put NULL to omit body).
+ * @param text Optional text body (put NULL to omit body).
+ * @param p_tdata Pointer to receive the transmit data.
*
- * @return The transmit data.
+ * @return PJ_SUCCESS, or the appropriate error code.
*/
-PJ_DECL(pjsip_tx_data*) pjsip_endpt_create_request( pjsip_endpoint *endpt,
- const pjsip_method *method,
- const pj_str_t *target,
- const pj_str_t *from,
- const pj_str_t *to,
- const pj_str_t *contact,
- const pj_str_t *call_id,
- int cseq,
- const pj_str_t *text);
+PJ_DECL(pj_status_t) pjsip_endpt_create_request( pjsip_endpoint *endpt,
+ const pjsip_method *method,
+ const pj_str_t *target,
+ const pj_str_t *from,
+ const pj_str_t *to,
+ const pj_str_t *contact,
+ const pj_str_t *call_id,
+ int cseq,
+ const pj_str_t *text,
+ pjsip_tx_data **p_tdata);
/**
* Create an independent request message from the specified headers. This
@@ -57,11 +58,12 @@ PJ_DECL(pjsip_tx_data*) pjsip_endpt_create_request( pjsip_endpoint *endpt,
* @param contact URL to put in Contact header.
* @param call_id Optional Call-ID (put NULL to generate unique Call-ID).
* @param cseq Optional CSeq (put -1 to generate random CSeq).
- * @param text Optional text body (put NULL to omit body).
+ * @param text Optional text body (put NULL to omit body).
+ * @param p_tdata Pointer to receive the transmit data.
*
- * @return The transmit data.
+ * @return PJ_SUCCESS, or the appropriate error code.
*/
-PJ_DECL(pjsip_tx_data*)
+PJ_DECL(pj_status_t)
pjsip_endpt_create_request_from_hdr( pjsip_endpoint *endpt,
const pjsip_method *method,
const pjsip_uri *target,
@@ -70,7 +72,8 @@ pjsip_endpt_create_request_from_hdr( pjsip_endpoint *endpt,
const pjsip_contact_hdr *contact,
const pjsip_cid_hdr *call_id,
int cseq,
- const pj_str_t *text );
+ const pj_str_t *text,
+ pjsip_tx_data **p_tdata);
/**
* Send outgoing request and initiate UAC transaction for the request.
@@ -89,7 +92,7 @@ pjsip_endpt_create_request_from_hdr( pjsip_endpoint *endpt,
* the previously registered token and the event that triggers
* the completion of the transaction.
*
- * @return Zero if transaction is started successfully.
+ * @return PJ_SUCCESS, or the appropriate error code.
*/
PJ_DECL(pj_status_t) pjsip_endpt_send_request( pjsip_endpoint *endpt,
pjsip_tx_data *tdata,
@@ -106,13 +109,15 @@ PJ_DECL(pj_status_t) pjsip_endpt_send_request( pjsip_endpoint *endpt,
*
* @param endpt The endpoint.
* @param rdata The request receive data.
- * @param code Status code to be put in the response.
+ * @param code Status code to be put in the response.
+ * @param p_tdata Pointer to receive the transmit data.
*
- * @return Transmit data.
+ * @return PJ_SUCCESS, or the appropriate error code.
*/
-PJ_DECL(pjsip_tx_data*) pjsip_endpt_create_response(pjsip_endpoint *endpt,
- const pjsip_rx_data *rdata,
- int code);
+PJ_DECL(pj_status_t) pjsip_endpt_create_response( pjsip_endpoint *endpt,
+ const pjsip_rx_data *rdata,
+ int code,
+ pjsip_tx_data **p_tdata);
/**
* Construct a full ACK request for the received non-2xx final response.
@@ -136,11 +141,13 @@ PJ_DECL(void) pjsip_endpt_create_ack( pjsip_endpoint *endpt,
*
* @param endpt The endpoint.
* @param tdata The transmit buffer for the request being cancelled.
+ * @param p_tdata Pointer to receive the transmit data.
*
- * @return Cancel request.
+ * @return PJ_SUCCESS, or the appropriate error code.
*/
-PJ_DECL(pjsip_tx_data*) pjsip_endpt_create_cancel( pjsip_endpoint *endpt,
- pjsip_tx_data *tdata );
+PJ_DECL(pj_status_t) pjsip_endpt_create_cancel( pjsip_endpoint *endpt,
+ pjsip_tx_data *tdata,
+ pjsip_tx_data **p_tdata);
/**
@@ -159,7 +166,6 @@ PJ_DECL(pj_status_t) pjsip_get_response_addr(pj_pool_t *pool,
const pjsip_via_hdr *via,
pjsip_host_port *addr);
-
/**
* @}
*/
diff --git a/pjsip/include/pjsip/sip_module.h b/pjsip/include/pjsip/sip_module.h
index f380b967..7bf53ab4 100644
--- a/pjsip/include/pjsip/sip_module.h
+++ b/pjsip/include/pjsip/sip_module.h
@@ -1,5 +1,4 @@
/* $Id$
- *
*/
#ifndef __PJSIP_SIP_MODULE_H__
#define __PJSIP_SIP_MODULE_H__
diff --git a/pjsip/include/pjsip/sip_msg.h b/pjsip/include/pjsip/sip_msg.h
index 76834c29..ed9450b1 100644
--- a/pjsip/include/pjsip/sip_msg.h
+++ b/pjsip/include/pjsip/sip_msg.h
@@ -1,5 +1,4 @@
/* $Id$
- *
*/
#ifndef __PJSIP_SIP_MSG_H__
#define __PJSIP_SIP_MSG_H__
@@ -260,7 +259,7 @@ typedef struct pjsip_hdr_vptr
*/
#define PJSIP_DECL_HDR_MEMBER(hdr) \
/** List members. */ \
- PJ_DECL_LIST_MEMBER(hdr) \
+ PJ_DECL_LIST_MEMBER(hdr); \
/** Header type */ \
pjsip_hdr_e type; \
/** Header name. */ \
@@ -268,17 +267,17 @@ typedef struct pjsip_hdr_vptr
/** Header short name version. */ \
pj_str_t sname; \
/** Virtual function table. */ \
- pjsip_hdr_vptr *vptr;
+ pjsip_hdr_vptr *vptr
/**
* Generic SIP header structure, for generic manipulation for headers in the
* message. All header fields can be typecasted to this type.
*/
-typedef struct pjsip_hdr
+struct pjsip_hdr
{
- PJSIP_DECL_HDR_MEMBER(struct pjsip_hdr)
-} pjsip_hdr;
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_hdr);
+};
/**
@@ -687,7 +686,7 @@ PJ_IDECL(void) pjsip_msg_insert_first_hdr( pjsip_msg *msg, pjsip_hdr *hdr );
* @return The length of the printed characters (in bytes), or NEGATIVE
* value if the message is too large for the specified buffer.
*/
-PJ_DECL(int) pjsip_msg_print( pjsip_msg *msg, char *buf, pj_size_t size);
+PJ_DECL(pj_ssize_t) pjsip_msg_print(pjsip_msg *msg, char *buf, pj_size_t size);
/**
* @}
@@ -707,7 +706,7 @@ PJ_DECL(int) pjsip_msg_print( pjsip_msg *msg, char *buf, pj_size_t size);
*/
typedef struct pjsip_generic_string_hdr
{
- PJSIP_DECL_HDR_MEMBER(struct pjsip_generic_string_hdr) /**< Standard header field. */
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_generic_string_hdr); /**< Standard header field. */
pj_str_t hvalue; /**< hvalue */
} pjsip_generic_string_hdr;
@@ -756,7 +755,7 @@ pjsip_generic_string_hdr_create_with_text( pj_pool_t *pool,
*/
typedef struct pjsip_generic_int_hdr
{
- PJSIP_DECL_HDR_MEMBER(struct pjsip_generic_int_hdr) /**< Standard header field. */
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_generic_int_hdr); /**< Standard header field. */
pj_int32_t ivalue; /**< ivalue */
} pjsip_generic_int_hdr;
@@ -805,7 +804,7 @@ pjsip_generic_int_hdr_create_with_value( pj_pool_t *pool,
typedef struct pjsip_generic_array_hdr
{
- PJSIP_DECL_HDR_MEMBER(struct pjsip_generic_array_hdr)
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_generic_array_hdr);
unsigned count; /**< Number of elements. */
pj_str_t values[PJSIP_GENERIC_ARRAY_MAX_COUNT]; /**< Elements. */
} pjsip_generic_array_hdr;
@@ -886,7 +885,7 @@ PJ_DECL(pjsip_allow_hdr*) pjsip_allow_hdr_create(pj_pool_t *pool);
*/
typedef struct pjsip_cid_hdr
{
- PJSIP_DECL_HDR_MEMBER(struct pjsip_cid_hdr)
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_cid_hdr);
pj_str_t id; /**< Call-ID string. */
} pjsip_cid_hdr;
@@ -917,7 +916,7 @@ PJ_DECL(pjsip_cid_hdr*) pjsip_cid_hdr_create( pj_pool_t *pool );
*/
typedef struct pjsip_clen_hdr
{
- PJSIP_DECL_HDR_MEMBER(struct pjsip_clen_hdr)
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_clen_hdr);
int len; /**< Content length. */
} pjsip_clen_hdr;
@@ -945,7 +944,7 @@ PJ_DECL(pjsip_clen_hdr*) pjsip_clen_hdr_create( pj_pool_t *pool );
*/
typedef struct pjsip_cseq_hdr
{
- PJSIP_DECL_HDR_MEMBER(struct pjsip_cseq_hdr)
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_cseq_hdr);
int cseq; /**< CSeq number. */
pjsip_method method; /**< CSeq method. */
} pjsip_cseq_hdr;
@@ -977,7 +976,7 @@ PJ_DECL(pjsip_cseq_hdr*) pjsip_cseq_hdr_create( pj_pool_t *pool );
*/
typedef struct pjsip_contact_hdr
{
- PJSIP_DECL_HDR_MEMBER(struct pjsip_contact_hdr)
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_contact_hdr);
int star; /**< The contact contains only a '*' character */
pjsip_uri *uri; /**< URI in the contact. */
int q1000; /**< The "q" value times 1000 (to avoid float) */
@@ -1010,7 +1009,7 @@ PJ_DECL(pjsip_contact_hdr*) pjsip_contact_hdr_create( pj_pool_t *pool );
*/
typedef struct pjsip_ctype_hdr
{
- PJSIP_DECL_HDR_MEMBER(struct pjsip_ctype_hdr)
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_ctype_hdr);
pjsip_media_type media; /**< Media type. */
} pjsip_ctype_hdr;
@@ -1061,7 +1060,7 @@ PJ_DECL(pjsip_expires_hdr*) pjsip_expires_hdr_create( pj_pool_t *pool );
*/
typedef struct pjsip_fromto_hdr
{
- PJSIP_DECL_HDR_MEMBER(struct pjsip_fromto_hdr)
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_fromto_hdr);
pjsip_uri *uri; /**< URI in From/To header. */
pj_str_t tag; /**< Header "tag" parameter. */
pj_str_t other_param; /**< Other params, concatenated as a single string. */
@@ -1170,7 +1169,7 @@ PJ_DECL(pjsip_min_expires_hdr*) pjsip_min_expires_hdr_create(pj_pool_t *pool);
*/
typedef struct pjsip_routing_hdr
{
- PJSIP_DECL_HDR_MEMBER(struct pjsip_routing_hdr) /**< Generic header fields. */
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_routing_hdr); /**< Generic header fields. */
pjsip_name_addr name_addr; /**< The URL in the Route/Record-Route header. */
pj_str_t other_param; /** Other parameter. */
} pjsip_routing_hdr;
@@ -1327,7 +1326,7 @@ PJ_DECL(pjsip_unsupported_hdr*) pjsip_unsupported_hdr_create(pj_pool_t *pool);
*/
typedef struct pjsip_via_hdr
{
- PJSIP_DECL_HDR_MEMBER(struct pjsip_via_hdr)
+ PJSIP_DECL_HDR_MEMBER(struct pjsip_via_hdr);
pj_str_t transport; /**< Transport type. */
pjsip_host_port sent_by; /**< Host and optional port */
int ttl_param; /**< TTL parameter, or -1 if it's not specified. */
diff --git a/pjsip/include/pjsip/sip_parser.h b/pjsip/include/pjsip/sip_parser.h
index 69e4aba7..5ae2f80f 100644
--- a/pjsip/include/pjsip/sip_parser.h
+++ b/pjsip/include/pjsip/sip_parser.h
@@ -1,5 +1,4 @@
/* $Id$
- *
*/
#ifndef __PJSIP_SIP_PARSER_H__
#define __PJSIP_SIP_PARSER_H__
@@ -10,7 +9,7 @@
*/
#include <pjsip/sip_types.h>
-#include <pj/scanner.h>
+#include <pjlib-util/scanner.h>
#include <pj/list.h>
PJ_BEGIN_DECL
@@ -51,13 +50,24 @@ enum
*/
typedef struct pjsip_parser_err_report
{
- PJ_DECL_LIST_MEMBER(struct pjsip_parser_err_report)
+ PJ_DECL_LIST_MEMBER(struct pjsip_parser_err_report);
int exception_code; /**< Error exception (e.g. PJSIP_SYN_ERR_EXCEPTION) */
int line; /**< Line number. */
int col; /**< Column number. */
pj_str_t hname; /**< Header name, if any. */
} pjsip_parser_err_report;
+
+/**
+ * Parsing context, the default argument for parsing functions.
+ */
+typedef struct pjsip_parse_ctx
+{
+ pj_scanner *scanner; /**< The scanner. */
+ pj_pool_t *pool; /**< The pool. */
+ pjsip_rx_data *rdata; /**< Optional rdata. */
+} pjsip_parse_ctx;
+
/**
* Type of function to parse header. The parsing function must follow these
@@ -76,7 +86,7 @@ typedef struct pjsip_parser_err_report
* - for the last header, these separator is optional since parsing
* can be terminated when seeing EOF.
*/
-typedef void* (pjsip_parse_hdr_func)(pj_scanner *scanner, pj_pool_t *pool);
+typedef pjsip_hdr* (pjsip_parse_hdr_func)(pjsip_parse_ctx *context);
/**
* Type of function to parse URI scheme.
@@ -94,8 +104,7 @@ typedef void* (pjsip_parse_uri_func)(pj_scanner *scanner, pj_pool_t *pool);
* @param hshortname The short header name or NULL.
* @param fptr The pointer to function to parser the header.
*
- * @return zero if success.
- * @see pjsip_parse_hdr_func
+ * @return PJ_SUCCESS if success, or the appropriate error code.
*/
PJ_DECL(pj_status_t) pjsip_register_hdr_parser( const char *hname,
const char *hshortname,
@@ -183,6 +192,27 @@ PJ_DECL(pjsip_msg *) pjsip_parse_msg( pj_pool_t *pool,
char *buf, pj_size_t size,
pjsip_parser_err_report *err_list);
+
+/**
+ * Parse a packet buffer and build a rdata. The resulting message will be
+ * stored in \c msg field in the \c rdata. This behaves pretty much like
+ * #pjsip_parse_msg(), except that it will also initialize the header fields
+ * in the \c rdata.
+ *
+ * This function is normally called by the transport layer.
+ *
+ * @param buf The input buffer
+ * @param buf The input buffer, which size must be at least (size+1)
+ * because the function will temporarily put NULL
+ * termination at the end of the buffer during parsing.
+ * @param size The length of the string (not counting NULL terminator).
+ * @param rdata The receive data buffer to store the message and
+ * its elements.
+ *
+ * @return The message inside the rdata if successfull, or NULL.
+ */
+PJ_DECL(pjsip_msg *) pjsip_parse_rdata( char *buf, pj_size_t size,
+ pjsip_rx_data *rdata );
/**
* Check incoming packet to see if a (probably) valid SIP message has been
@@ -193,10 +223,12 @@ PJ_DECL(pjsip_msg *) pjsip_parse_msg( pj_pool_t *pool,
* @param msg_size [out] If message is valid, this parameter will contain
* the size of the SIP message (including body, if any).
*
- * @return PJ_TRUE (1) if a message is found.
+ * @return PJ_SUCCESS if a message is found, or an error code.
*/
-PJ_DECL(pj_bool_t) pjsip_find_msg( const char *buf, pj_size_t size,
- pj_bool_t is_datagram, pj_size_t *msg_size);
+PJ_DECL(pj_status_t) pjsip_find_msg(const char *buf,
+ pj_size_t size,
+ pj_bool_t is_datagram,
+ pj_size_t *msg_size);
/**
* Parse the content of a header and return the header instance.
@@ -247,7 +279,7 @@ PJ_DECL(pj_status_t) pjsip_parse_headers( pj_pool_t *pool,
* parsers.
*/
extern
-pj_char_spec pjsip_HOST_SPEC, /* For scanning host part. */
+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. */
diff --git a/pjsip/include/pjsip/sip_private.h b/pjsip/include/pjsip/sip_private.h
index afcff08b..b2661350 100644
--- a/pjsip/include/pjsip/sip_private.h
+++ b/pjsip/include/pjsip/sip_private.h
@@ -1,5 +1,4 @@
/* $Id$
- *
*/
#ifndef __PJSIP_SIP_PRIVATE_H__
#define __PJSIP_SIP_PRIVATE_H__
@@ -26,16 +25,18 @@ PJ_BEGIN_DECL
* @param endpt The endpoint
* @param cb Callback to be called to receive messages from transport.
*/
-PJ_DECL(pjsip_transport_mgr*) pjsip_transport_mgr_create( pj_pool_t *pool,
- pjsip_endpoint *endpt,
- void (*cb)(pjsip_endpoint *,pjsip_rx_data *));
+PJ_DECL(pj_status_t) pjsip_transport_mgr_create( pj_pool_t *pool,
+ pjsip_endpoint *endpt,
+ void (*cb)(pjsip_endpoint *,
+ pjsip_rx_data *),
+ pjsip_transport_mgr **);
/**
* Destroy transport manager and release all transports.
* @param mgr Transport manager to be destroyed.
*/
-PJ_DECL(void) pjsip_transport_mgr_destroy( pjsip_transport_mgr *mgr );
+PJ_DECL(pj_status_t) pjsip_transport_mgr_destroy( pjsip_transport_mgr *mgr );
/**
* Poll for transport events.
diff --git a/pjsip/include/pjsip/sip_resolve.h b/pjsip/include/pjsip/sip_resolve.h
index 4a47c135..5464db91 100644
--- a/pjsip/include/pjsip/sip_resolve.h
+++ b/pjsip/include/pjsip/sip_resolve.h
@@ -1,5 +1,4 @@
/* $Id$
- *
*/
#ifndef __PJSIP_SIP_RESOLVE_H__
#define __PJSIP_SIP_RESOLVE_H__
diff --git a/pjsip/include/pjsip/sip_transaction.h b/pjsip/include/pjsip/sip_transaction.h
index 3ef6ad14..cdb11235 100644
--- a/pjsip/include/pjsip/sip_transaction.h
+++ b/pjsip/include/pjsip/sip_transaction.h
@@ -1,5 +1,4 @@
/* $Id$
- *
*/
#ifndef __PJSIP_SIP_TRANSACTION_H__
#define __PJSIP_SIP_TRANSACTION_H__
@@ -11,8 +10,6 @@
#include <pjsip/sip_msg.h>
#include <pjsip/sip_resolve.h>
-//#include <pjsip/sip_config.h>
-//#include <pjsip/sip_endpoint.h>
#include <pj/timer.h>
PJ_BEGIN_DECL
@@ -22,7 +19,8 @@ PJ_BEGIN_DECL
* @ingroup PJSIP
* @{
*/
-
+
+/* Forward decl. */
struct pjsip_transaction;
@@ -60,68 +58,111 @@ typedef enum pjsip_tsx_transport_state_e
* Transaction state.
*/
struct pjsip_transaction
-{
- pj_pool_t *pool;
- pjsip_endpoint *endpt;
- char obj_name[PJ_MAX_OBJ_NAME];
- pjsip_role_e role;
- int status_code;
- pjsip_tsx_state_e state;
- int (*state_handler)(struct pjsip_transaction *, pjsip_event *);
-
- pj_mutex_t *mutex;
- pjsip_method method;
- int cseq;
- pj_str_t transaction_key;
- pj_str_t branch;
-
- pjsip_tsx_transport_state_e transport_state;
- pjsip_host_port dest_name;
- int current_addr;
- pjsip_server_addresses remote_addr;
- pjsip_transport_t *transport;
-
- pjsip_tx_data *last_tx;
- int has_unsent_msg;
- int handle_ack;
- int retransmit_count;
-
- pj_timer_entry retransmit_timer;
- pj_timer_entry timeout_timer;
+{
+ /*
+ * Administrivia
+ */
+ pj_pool_t *pool; /**< Pool owned by the tsx. */
+ pjsip_endpoint *endpt; /**< Endpoint instance. */
+ pj_mutex_t *mutex; /**< Mutex for this tsx. */
+ char obj_name[PJ_MAX_OBJ_NAME]; /**< Tsx name. */
+ int tracing; /**< Tracing enabled? */
+
+ /*
+ * Transaction identification.
+ */
+ pjsip_role_e role; /**< Role (UAS or UAC) */
+ pjsip_method method; /**< The method. */
+ int cseq; /**< The CSeq */
+ pj_str_t transaction_key;/**< hash table key. */
+ pj_str_t branch; /**< The branch Id. */
+
+ /*
+ * State and status.
+ */
+ int status_code; /**< Last status code seen. */
+ pjsip_tsx_state_e state; /**< State. */
+ int handle_ack; /**< Should we handle ACK? */
+
+ /** Handler according to current state. */
+ pj_status_t (*state_handler)(struct pjsip_transaction *, pjsip_event *);
+
+ /*
+ * Transport.
+ */
+ pjsip_tsx_transport_state_e transport_state;/**< Transport's state. */
+ pjsip_host_port dest_name; /**< Destination address. */
+ pjsip_server_addresses remote_addr; /**< Addresses resolved. */
+ int current_addr; /**< Address currently used. */
+
+ pjsip_transport_t *transport; /**< Transport to use. */
+
+ /*
+ * Messages and timer.
+ */
+ pjsip_tx_data *last_tx; /**< Msg kept for retrans. */
+ int has_unsent_msg; /**< Non-zero if tsx need to
+ transmit msg once resolver
+ completes. */
+ int retransmit_count;/**< Retransmission count. */
+ pj_timer_entry retransmit_timer;/**< Retransmit timer. */
+ pj_timer_entry timeout_timer; /**< Timeout timer. */
+
+ /** Module specific data. */
void *module_data[PJSIP_MAX_MODULE];
};
/**
- * Init transaction as UAC.
- * @param tsx the transaction.
- * @param tdata the transmit data.
- * @return PJ_SUCCESS if successfull.
+ * 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.
+ * If \c Route headers are present, it will be used to calculate remote
+ * destination.
+ *
+ * If \c Via header does not exist, it will be created along with a unique
+ * \c branch parameter. If it exists and contains branch parameter, then
+ * the \c branch parameter will be used as is as the transaction key.
+ *
+ * The \c Route headers in the transmit data, if present, are used to
+ * calculate remote destination.
+ *
+ * At the end of the function, the transaction will start resolving the
+ * addresses of remote server to contact. Transport will be acquired as soon
+ * as the resolving job completes.
+ *
+ * @param tsx The transaction.
+ * @param tdata The transmit data.
+ *
+ * @return PJ_SUCCESS if successfull.
*/
PJ_DECL(pj_status_t) pjsip_tsx_init_uac( pjsip_transaction *tsx,
pjsip_tx_data *tdata);
/**
- * Init transaction as UAS.
- * @param tsx the transaction to be initialized.
- * @param rdata the received incoming request.
+ * Init transaction as UAS.
+ *
+ * @param tsx The transaction to be initialized.
+ * @param rdata The received incoming request.
+ *
* @return PJ_SUCCESS if successfull.
*/
PJ_DECL(pj_status_t) pjsip_tsx_init_uas( pjsip_transaction *tsx,
pjsip_rx_data *rdata);
/**
- * Process incoming message for this transaction.
- * @param tsx the transaction.
- * @param rdata the incoming message.
+ * Process incoming message for this transaction.
+ *
+ * @param tsx The transaction.
+ * @param rdata The incoming message.
*/
PJ_DECL(void) pjsip_tsx_on_rx_msg( pjsip_transaction *tsx,
pjsip_rx_data *rdata);
/**
- * Transmit message with this transaction.
- * @param tsx the transaction.
- * @param tdata the outgoing message.
+ * Transmit message with this transaction.
+ *
+ * @param tsx The transaction.
+ * @param tdata The outgoing message.
*/
PJ_DECL(void) pjsip_tsx_on_tx_msg( pjsip_transaction *tsx,
pjsip_tx_data *tdata);
@@ -133,35 +174,41 @@ PJ_DECL(void) pjsip_tsx_on_tx_msg( pjsip_transaction *tsx,
* This operation is only valid if the transaction is configured to handle ACK
* (tsx->handle_ack is non-zero). If this attribute is not set, then the
* transaction will comply with RFC-3261, i.e. it will set itself to
- * TERMINATED state when it receives 2xx/INVITE.
- * @param tsx The transaction.
- * @param tdata The ACK request.
+ * TERMINATED state when it receives 2xx/INVITE.
+ *
+ * @param tsx The transaction.
+ * @param tdata The ACK request.
*/
PJ_DECL(void) pjsip_tsx_on_tx_ack( pjsip_transaction *tsx,
pjsip_tx_data *tdata);
/**
- * Forcely terminate transaction.
- * @param tsx the transaction.
- * @param code the status code to report.
+ * Force terminate transaction.
+ *
+ * @param tsx The transaction.
+ * @param code The status code to report.
*/
PJ_DECL(void) pjsip_tsx_terminate( pjsip_transaction *tsx,
int code );
/**
* Create transaction key, which is used to match incoming requests
- * or response (retransmissions) against transactions.
- * @param pool The pool
- * @param key Output key.
- * @param role The role of the transaction.
- * @param method The method to be put as a key.
- * @param rdata The received data to calculate.
- */
-PJ_DECL(void) pjsip_tsx_create_key( pj_pool_t *pool,
- pj_str_t *key,
- pjsip_role_e role,
- const pjsip_method *method,
- const pjsip_rx_data *rdata );
+ * or response (retransmissions) against transactions.
+ *
+ * @param pool The pool
+ * @param key Output key.
+ * @param role The role of the transaction.
+ * @param method The method to be put as a key.
+ * @param rdata The received data to calculate.
+ *
+ * @return PJ_SUCCESS or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_tsx_create_key( pj_pool_t *pool,
+ pj_str_t *key,
+ pjsip_role_e role,
+ const pjsip_method *method,
+ const pjsip_rx_data *rdata );
+
/**
* @}
@@ -183,7 +230,7 @@ PJ_DECL(const char *) pjsip_role_name(pjsip_role_e role);
/* Thread Local Storage ID for transaction lock (initialized by endpoint) */
-extern int pjsip_tsx_lock_tls_id;
+extern long pjsip_tsx_lock_tls_id;
PJ_END_DECL
diff --git a/pjsip/include/pjsip/sip_transport.h b/pjsip/include/pjsip/sip_transport.h
index 29b5d8d1..dd3baea9 100644
--- a/pjsip/include/pjsip/sip_transport.h
+++ b/pjsip/include/pjsip/sip_transport.h
@@ -1,5 +1,4 @@
/* $Id$
- *
*/
#ifndef __PJSIP_SIP_TRANSPORT_H__
#define __PJSIP_SIP_TRANSPORT_H__
@@ -13,6 +12,7 @@
#include <pjsip/sip_parser.h>
#include <pj/sock.h>
#include <pj/list.h>
+#include <pj/ioqueue.h>
PJ_BEGIN_DECL
@@ -36,10 +36,13 @@ PJ_BEGIN_DECL
*/
struct pjsip_rx_data
{
- PJ_DECL_LIST_MEMBER(struct pjsip_rx_data)
+ //PJ_DECL_LIST_MEMBER(struct pjsip_rx_data);
/** Memory pool for this buffer. */
pj_pool_t *pool;
+
+ /** Ioqueue op key. */
+ pj_ioqueue_op_key_t op_key;
/** Time when the message was received. */
pj_time_val timestamp;
@@ -73,21 +76,33 @@ struct pjsip_rx_data
/** The From header as found in the message. */
pjsip_from_hdr *from;
- /** The tag in the From header as found in the message. */
- pj_str_t from_tag;
-
/** The To header as found in the message. */
pjsip_to_hdr *to;
- /** The To tag header as found in the message. */
- pj_str_t to_tag;
-
/** The topmost Via header as found in the message. */
pjsip_via_hdr *via;
/** The CSeq header as found in the message. */
pjsip_cseq_hdr *cseq;
-
+
+ /** Max forwards header. */
+ pjsip_max_forwards_hdr *max_fwd;
+
+ /** The first route header. */
+ pjsip_route_hdr *route;
+
+ /** The first record-route header. */
+ pjsip_rr_hdr *record_route;
+
+ /** Content-type header. */
+ pjsip_ctype_hdr *ctype;
+
+ /** Content-length header. */
+ pjsip_clen_hdr *clen;
+
+ /** The first Require header. */
+ pjsip_require_hdr *require;
+
/** The list of error generated by the parser when parsing this message. */
pjsip_parser_err_report parse_err;
};
@@ -109,7 +124,7 @@ struct pjsip_rx_data
*/
struct pjsip_tx_data
{
- PJ_DECL_LIST_MEMBER(struct pjsip_tx_data)
+ PJ_DECL_LIST_MEMBER(struct pjsip_tx_data);
/** Memory pool for this buffer. */
pj_pool_t *pool;
@@ -126,6 +141,9 @@ struct pjsip_tx_data
/** The transport manager for this buffer. */
pjsip_transport_mgr *mgr;
+
+ /** Ioqueue asynchronous operation key. */
+ pj_ioqueue_op_key_t op_key;
/** The message in this buffer. */
pjsip_msg *msg;
@@ -355,14 +373,16 @@ pjsip_transport_get_remote_addr( const pjsip_transport_t * tr );
*
* @param tr The transport to send the message.
* @param tdata The outgoing message buffer.
- * @param addr The remote address.
+ * @param addr The remote address.
+ * @param sent If not null, it will be filled up with the length of
+ * data sent.
*
- * @return The number of bytes sent, or zero if the connection
- * has closed, or -1 on error.
+ * @return PJ_SUCCESS on success, or the appropriate error code.
*/
-PJ_DECL(int) pjsip_transport_send_msg( pjsip_transport_t *tr,
- pjsip_tx_data *tdata,
- const pj_sockaddr_in *addr);
+PJ_DECL(pj_status_t) pjsip_transport_send_msg( pjsip_transport_t *tr,
+ pjsip_tx_data *tdata,
+ const pj_sockaddr_in *addr,
+ pj_ssize_t *sent);
/**
@@ -386,7 +406,8 @@ PJ_DECL(int) pjsip_transport_send_msg( pjsip_transport_t *tr,
* @param mgr The transport manager.
* @return The transmit buffer data, or NULL on error.
*/
-pjsip_tx_data* pjsip_tx_data_create( pjsip_transport_mgr *mgr );
+pj_status_t pjsip_tx_data_create( pjsip_transport_mgr *mgr,
+ pjsip_tx_data **tdata );
/**
diff --git a/pjsip/include/pjsip/sip_types.h b/pjsip/include/pjsip/sip_types.h
index 33e8ca03..64f5f3ae 100644
--- a/pjsip/include/pjsip/sip_types.h
+++ b/pjsip/include/pjsip/sip_types.h
@@ -1,5 +1,4 @@
/* $Id$
- *
*/
#ifndef __PJSIP_SIP_TYPES_H__
#define __PJSIP_SIP_TYPES_H__
@@ -71,6 +70,11 @@ typedef struct pjsip_rx_data pjsip_rx_data;
* Forward declaration for message (sip_msg.h).
*/
typedef struct pjsip_msg pjsip_msg;
+
+/**
+ * Forward declaration for header field (sip_msg.h).
+ */
+typedef struct pjsip_hdr pjsip_hdr;
/**
* Forward declaration for URI (sip_uri.h).
@@ -132,7 +136,26 @@ typedef struct pjsip_host_port
pj_str_t host; /**< Host part. */
int port; /**< Port number. */
} pjsip_host_port;
-
+
+
+/**
+ * Convert exception ID into pj_status_t status.
+ *
+ * @param exception_id Exception Id.
+ *
+ * @return Error code for the specified exception Id.
+ */
+PJ_DECL(pj_status_t) pjsip_exception_to_status(int exception_id);
+
+/**
+ * Return standard pj_status_t status from current exception.
+ */
+#define PJSIP_RETURN_EXCEPTION() pjsip_exception_to_status(PJ_GET_EXCEPTION())
+
+/**
+ * Attributes to inform that the function may throw exceptions.
+ */
+#define PJSIP_THROW_SPEC(list)
#endif /* __PJSIP_SIP_TYPES_H__ */
diff --git a/pjsip/include/pjsip/sip_uri.h b/pjsip/include/pjsip/sip_uri.h
index c43bc3df..8d72d0ae 100644
--- a/pjsip/include/pjsip/sip_uri.h
+++ b/pjsip/include/pjsip/sip_uri.h
@@ -1,5 +1,4 @@
/* $Id$
- *
*/
#ifndef __PJSIP_SIP_URI_H__
#define __PJSIP_SIP_URI_H__
diff --git a/pjsip/include/pjsip_core.h b/pjsip/include/pjsip_core.h
index acce9cc6..96b39488 100644
--- a/pjsip/include/pjsip_core.h
+++ b/pjsip/include/pjsip_core.h
@@ -1,5 +1,4 @@
/* $Id$
- *
*/
#ifndef __PJSIP_CORE_H__
#define __PJSIP_CORE_H__
diff --git a/pjsip/src/pjsip/sip_auth.c b/pjsip/src/pjsip/sip_auth.c
index 91e91862..030b4a40 100644
--- a/pjsip/src/pjsip/sip_auth.c
+++ b/pjsip/src/pjsip/sip_auth.c
@@ -1,15 +1,16 @@
/* $Id$
- *
*/
#include <pjsip/sip_auth.h>
#include <pjsip/sip_auth_parser.h> /* just to get pjsip_DIGEST_STR */
#include <pjsip/sip_transport.h>
#include <pjsip/sip_endpoint.h>
-#include <pj/md5.h>
+#include <pjlib-util/md5.h>
#include <pj/log.h>
#include <pj/string.h>
#include <pj/pool.h>
-#include <pj/guid.h>
+#include <pj/guid.h>
+#include <pj/assert.h>
+#include <pj/ctype.h>
/* Length of digest string. */
#define MD5STRLEN 32
@@ -146,7 +147,7 @@ static pj_bool_t has_auth_qop( pj_pool_t *pool, const pj_str_t *qop_offer)
pj_strdup_with_null( pool, &qop, qop_offer);
p = qop.ptr;
while (*p) {
- *p = (char)tolower(*p);
+ *p = (char)pj_tolower(*p);
++p;
}
@@ -217,7 +218,7 @@ static pj_status_t respond_digest( pj_pool_t *pool,
*/
cred->qop = pjsip_AUTH_STR;
cred->nc.ptr = pj_pool_alloc(pool, 16);
- sprintf(cred->nc.ptr, "%06u", nc);
+ pj_snprintf(cred->nc.ptr, 16, "%06u", nc);
if (cnonce && cnonce->slen) {
pj_strdup(pool, &cred->cnonce, cnonce);
@@ -484,7 +485,7 @@ PJ_DEF(const pjsip_cred_info*) pjsip_auth_find_cred( unsigned count,
const pj_str_t *scheme)
{
unsigned i;
- PJ_UNUSED_ARG(scheme)
+ PJ_UNUSED_ARG(scheme);
for (i=0; i<count; ++i) {
if (pj_stricmp(&cred[i].realm, realm) == 0)
return &cred[i];
@@ -715,7 +716,7 @@ PJ_DEF(pjsip_tx_data*) pjsip_auth_reinit_req( pjsip_endpoint *endpt,
const pjsip_hdr *hdr;
pjsip_via_hdr *via;
- PJ_UNUSED_ARG(endpt)
+ PJ_UNUSED_ARG(endpt);
pj_assert(rdata->msg->type == PJSIP_RESPONSE_MSG);
pj_assert(rdata->msg->line.status.code == 401 ||
diff --git a/pjsip/src/pjsip/sip_auth_msg.c b/pjsip/src/pjsip/sip_auth_msg.c
index a5d52f10..9e88ef4a 100644
--- a/pjsip/src/pjsip/sip_auth_msg.c
+++ b/pjsip/src/pjsip/sip_auth_msg.c
@@ -1,12 +1,12 @@
/* $Id$
- *
*/
#include <pjsip/sip_auth_msg.h>
#include <pjsip/sip_auth_parser.h>
#include <pj/pool.h>
#include <pj/list.h>
-#include <pj/string.h>
-#include <pjsip/print.h>
+#include <pj/string.h>
+#include <pj/assert.h>
+#include <pjsip/print_util.h>
///////////////////////////////////////////////////////////////////////////////
/*
@@ -67,9 +67,9 @@ static int print_digest_credential(pjsip_digest_credential *cred, char *buf, pj_
static int print_pgp_credential(pjsip_pgp_credential *cred, char *buf, pj_size_t size)
{
- PJ_UNUSED_ARG(cred)
- PJ_UNUSED_ARG(buf)
- PJ_UNUSED_ARG(size)
+ PJ_UNUSED_ARG(cred);
+ PJ_UNUSED_ARG(buf);
+ PJ_UNUSED_ARG(size);
return -1;
}
@@ -212,9 +212,9 @@ static int print_digest_challenge( pjsip_digest_challenge *chal,
static int print_pgp_challenge( pjsip_pgp_challenge *chal,
char *buf, pj_size_t size)
{
- PJ_UNUSED_ARG(chal)
- PJ_UNUSED_ARG(buf)
- PJ_UNUSED_ARG(size)
+ PJ_UNUSED_ARG(chal);
+ PJ_UNUSED_ARG(buf);
+ PJ_UNUSED_ARG(size);
return -1;
}
diff --git a/pjsip/src/pjsip/sip_auth_parser.c b/pjsip/src/pjsip/sip_auth_parser.c
index 2f5a3baf..5e121b50 100644
--- a/pjsip/src/pjsip/sip_auth_parser.c
+++ b/pjsip/src/pjsip/sip_auth_parser.c
@@ -1,21 +1,25 @@
/* $Id$
- *
*/
#include <pjsip/sip_auth_parser.h>
#include <pjsip/sip_auth_msg.h>
-#include <pjsip/sip_parser.h>
+#include <pjsip/sip_parser.h>
+#include <pj/assert.h>
#include <pj/string.h>
#include <pj/except.h>
-static pjsip_authorization_hdr* parse_hdr_authorization( pj_scanner *scanner, pj_pool_t *pool);
-static pjsip_proxy_authorization_hdr* parse_hdr_proxy_authorization( pj_scanner *scanner, pj_pool_t *pool);
-static pjsip_www_authenticate_hdr* parse_hdr_www_authenticate( pj_scanner *scanner, pj_pool_t *pool);
-static pjsip_proxy_authenticate_hdr* parse_hdr_proxy_authenticate( pj_scanner *scanner, pj_pool_t *pool);
+static pjsip_hdr* parse_hdr_authorization ( pjsip_parse_ctx *ctx );
+static pjsip_hdr* parse_hdr_proxy_authorization ( pjsip_parse_ctx *ctx );
+static pjsip_hdr* parse_hdr_www_authenticate ( pjsip_parse_ctx *ctx );
+static pjsip_hdr* parse_hdr_proxy_authenticate ( pjsip_parse_ctx *ctx );
-static void parse_digest_credential( pj_scanner *scanner, pj_pool_t *pool, pjsip_digest_credential *cred);
-static void parse_pgp_credential( pj_scanner *scanner, pj_pool_t *pool, pjsip_pgp_credential *cred);
-static void parse_digest_challenge( pj_scanner *scanner, pj_pool_t *pool, pjsip_digest_challenge *chal);
-static void parse_pgp_challenge( pj_scanner *scanner, pj_pool_t *pool, pjsip_pgp_challenge *chal);
+static void parse_digest_credential ( pj_scanner *scanner, pj_pool_t *pool,
+ pjsip_digest_credential *cred);
+static void parse_pgp_credential ( pj_scanner *scanner, pj_pool_t *pool,
+ pjsip_pgp_credential *cred);
+static void parse_digest_challenge ( pj_scanner *scanner, pj_pool_t *pool,
+ pjsip_digest_challenge *chal);
+static void parse_pgp_challenge ( pj_scanner *scanner, pj_pool_t *pool,
+ pjsip_pgp_challenge *chal);
const pj_str_t pjsip_USERNAME_STR = { "username", 8 },
pjsip_REALM_STR = { "realm", 5},
@@ -43,12 +47,13 @@ const pj_str_t pjsip_USERNAME_STR = { "username", 8 },
pjsip_QUOTED_AUTH_STR = { "\"auth\"", 6 };
-static void parse_digest_credential( pj_scanner *scanner, pj_pool_t *pool, pjsip_digest_credential *cred)
+static void parse_digest_credential( pj_scanner *scanner, pj_pool_t *pool,
+ pjsip_digest_credential *cred)
{
for (;;) {
pj_str_t name, value;
- pjsip_parse_param_imp(scanner, &name, &value, PJSIP_PARSE_REMOVE_QUOTE);
+ pjsip_parse_param_imp(scanner, &name, &value,PJSIP_PARSE_REMOVE_QUOTE);
if (!pj_stricmp(&name, &pjsip_USERNAME_STR)) {
cred->username = value;
@@ -81,32 +86,34 @@ static void parse_digest_credential( pj_scanner *scanner, pj_pool_t *pool, pjsip
cred->nc = value;
} else {
- pjsip_concat_param_imp(&cred->other_param, pool, &name, &value, ',');
+ pjsip_concat_param_imp(&cred->other_param,pool,&name,&value, ',');
}
/* Eat comma */
- if (!pj_scan_is_eof(scanner) && *scanner->current == ',')
+ if (!pj_scan_is_eof(scanner) && *scanner->curptr == ',')
pj_scan_get_char(scanner);
else
break;
}
}
-static void parse_pgp_credential( pj_scanner *scanner, pj_pool_t *pool, pjsip_pgp_credential *cred)
+static void parse_pgp_credential( pj_scanner *scanner, pj_pool_t *pool,
+ pjsip_pgp_credential *cred)
{
- PJ_UNUSED_ARG(scanner)
- PJ_UNUSED_ARG(pool)
- PJ_UNUSED_ARG(cred)
+ PJ_UNUSED_ARG(scanner);
+ PJ_UNUSED_ARG(pool);
+ PJ_UNUSED_ARG(cred);
PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
}
-static void parse_digest_challenge( pj_scanner *scanner, pj_pool_t *pool, pjsip_digest_challenge *chal)
+static void parse_digest_challenge( pj_scanner *scanner, pj_pool_t *pool,
+ pjsip_digest_challenge *chal)
{
for (;;) {
pj_str_t name, value;
- pjsip_parse_param_imp(scanner, &name, &value, PJSIP_PARSE_REMOVE_QUOTE);
+ pjsip_parse_param_imp(scanner, &name, &value,PJSIP_PARSE_REMOVE_QUOTE);
if (!pj_stricmp(&name, &pjsip_REALM_STR)) {
chal->realm = value;
@@ -121,8 +128,11 @@ static void parse_digest_challenge( pj_scanner *scanner, pj_pool_t *pool, pjsip_
chal->opaque = value;
} else if (!pj_stricmp(&name, &pjsip_STALE_STR)) {
- if (!pj_stricmp(&value, &pjsip_TRUE_STR) || !pj_stricmp(&value, &pjsip_QUOTED_TRUE_STR))
- chal->stale = 1;
+ if (!pj_stricmp(&value, &pjsip_TRUE_STR) ||
+ !pj_stricmp(&value, &pjsip_QUOTED_TRUE_STR))
+ {
+ chal->stale = 1;
+ }
} else if (!pj_stricmp(&name, &pjsip_ALGORITHM_STR)) {
chal->algorithm = value;
@@ -132,35 +142,37 @@ static void parse_digest_challenge( pj_scanner *scanner, pj_pool_t *pool, pjsip_
chal->qop = value;
} else {
- pjsip_concat_param_imp(&chal->other_param, pool, &name, &value, ',');
+ pjsip_concat_param_imp(&chal->other_param, pool,
+ &name, &value, ',');
}
/* Eat comma */
- if (!pj_scan_is_eof(scanner) && *scanner->current == ',')
+ if (!pj_scan_is_eof(scanner) && *scanner->curptr == ',')
pj_scan_get_char(scanner);
else
break;
}
}
-static void parse_pgp_challenge( pj_scanner *scanner, pj_pool_t *pool, pjsip_pgp_challenge *chal)
+static void parse_pgp_challenge( pj_scanner *scanner, pj_pool_t *pool,
+ pjsip_pgp_challenge *chal)
{
- PJ_UNUSED_ARG(scanner)
- PJ_UNUSED_ARG(pool)
- PJ_UNUSED_ARG(chal)
+ PJ_UNUSED_ARG(scanner);
+ PJ_UNUSED_ARG(pool);
+ PJ_UNUSED_ARG(chal);
PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
}
-static void int_parse_hdr_authorization( pj_scanner *scanner, pj_pool_t *pool,
+static void int_parse_hdr_authorization( pj_scanner *scanner, pj_pool_t *pool,
pjsip_authorization_hdr *hdr)
{
- if (*scanner->current == '"') {
+ if (*scanner->curptr == '"') {
pj_scan_get_quote(scanner, '"', '"', &hdr->scheme);
hdr->scheme.ptr++;
hdr->scheme.slen -= 2;
} else {
- pj_scan_get(scanner, pjsip_TOKEN_SPEC, &hdr->scheme);
+ pj_scan_get(scanner, &pjsip_TOKEN_SPEC, &hdr->scheme);
}
if (!pj_stricmp(&hdr->scheme, &pjsip_DIGEST_STR)) {
@@ -181,12 +193,12 @@ static void int_parse_hdr_authorization( pj_scanner *scanner, pj_pool_t *pool,
static void int_parse_hdr_authenticate( pj_scanner *scanner, pj_pool_t *pool,
pjsip_www_authenticate_hdr *hdr)
{
- if (*scanner->current == '"') {
+ if (*scanner->curptr == '"') {
pj_scan_get_quote(scanner, '"', '"', &hdr->scheme);
hdr->scheme.ptr++;
hdr->scheme.slen -= 2;
} else {
- pj_scan_get(scanner, pjsip_TOKEN_SPEC, &hdr->scheme);
+ pj_scan_get(scanner, &pjsip_TOKEN_SPEC, &hdr->scheme);
}
if (!pj_stricmp(&hdr->scheme, &pjsip_DIGEST_STR)) {
@@ -205,41 +217,56 @@ static void int_parse_hdr_authenticate( pj_scanner *scanner, pj_pool_t *pool,
}
-static pjsip_authorization_hdr *parse_hdr_authorization( pj_scanner *scanner, pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_authorization( pjsip_parse_ctx *ctx )
{
- pjsip_authorization_hdr *hdr = pjsip_authorization_hdr_create(pool);
- int_parse_hdr_authorization(scanner, pool, hdr);
- return hdr;
+ pjsip_authorization_hdr *hdr = pjsip_authorization_hdr_create(ctx->pool);
+ int_parse_hdr_authorization(ctx->scanner, ctx->pool, hdr);
+ return (pjsip_hdr*)hdr;
}
-static pjsip_proxy_authorization_hdr *parse_hdr_proxy_authorization( pj_scanner *scanner, pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_proxy_authorization( pjsip_parse_ctx *ctx )
{
- pjsip_proxy_authorization_hdr *hdr = pjsip_proxy_authorization_hdr_create(pool);
- int_parse_hdr_authorization(scanner, pool, hdr);
- return hdr;
+ pjsip_proxy_authorization_hdr *hdr =
+ pjsip_proxy_authorization_hdr_create(ctx->pool);
+ int_parse_hdr_authorization(ctx->scanner, ctx->pool, hdr);
+ return (pjsip_hdr*)hdr;
}
-static pjsip_www_authenticate_hdr *parse_hdr_www_authenticate( pj_scanner *scanner, pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_www_authenticate( pjsip_parse_ctx *ctx )
{
- pjsip_www_authenticate_hdr *hdr = pjsip_www_authenticate_hdr_create(pool);
- int_parse_hdr_authenticate(scanner, pool, hdr);
- return hdr;
+ pjsip_www_authenticate_hdr *hdr =
+ pjsip_www_authenticate_hdr_create(ctx->pool);
+ int_parse_hdr_authenticate(ctx->scanner, ctx->pool, hdr);
+ return (pjsip_hdr*)hdr;
}
-static pjsip_proxy_authenticate_hdr *parse_hdr_proxy_authenticate( pj_scanner *scanner, pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_proxy_authenticate( pjsip_parse_ctx *ctx )
{
- pjsip_proxy_authenticate_hdr *hdr = pjsip_proxy_authenticate_hdr_create(pool);
- int_parse_hdr_authenticate(scanner, pool, hdr);
- return hdr;
+ pjsip_proxy_authenticate_hdr *hdr =
+ pjsip_proxy_authenticate_hdr_create(ctx->pool);
+ int_parse_hdr_authenticate(ctx->scanner, ctx->pool, hdr);
+ return (pjsip_hdr*)hdr;
}
-PJ_DEF(void) pjsip_auth_init_parser()
-{
- pjsip_register_hdr_parser( "Authorization", NULL, (pjsip_parse_hdr_func*) &parse_hdr_authorization);
- pjsip_register_hdr_parser( "Proxy-Authorization", NULL, (pjsip_parse_hdr_func*) &parse_hdr_proxy_authorization);
- pjsip_register_hdr_parser( "WWW-Authenticate", NULL, (pjsip_parse_hdr_func*) &parse_hdr_www_authenticate);
- pjsip_register_hdr_parser( "Proxy-Authenticate", NULL, (pjsip_parse_hdr_func*) &parse_hdr_proxy_authenticate);
+PJ_DEF(pj_status_t) pjsip_auth_init_parser()
+{
+ pj_status_t status;
+
+ status = pjsip_register_hdr_parser( "Authorization", NULL,
+ &parse_hdr_authorization);
+ PJ_ASSERT_RETURN(status==PJ_SUCCESS, status);
+ status = pjsip_register_hdr_parser( "Proxy-Authorization", NULL,
+ &parse_hdr_proxy_authorization);
+ PJ_ASSERT_RETURN(status==PJ_SUCCESS, status);
+ status = pjsip_register_hdr_parser( "WWW-Authenticate", NULL,
+ &parse_hdr_www_authenticate);
+ PJ_ASSERT_RETURN(status==PJ_SUCCESS, status);
+ status = pjsip_register_hdr_parser( "Proxy-Authenticate", NULL,
+ &parse_hdr_proxy_authenticate);
+ PJ_ASSERT_RETURN(status==PJ_SUCCESS, status);
+
+ return PJ_SUCCESS;
}
PJ_DEF(void) pjsip_auth_deinit_parser()
diff --git a/pjsip/src/pjsip/sip_endpoint.c b/pjsip/src/pjsip/sip_endpoint.c
index 321d2e34..49c70b1b 100644
--- a/pjsip/src/pjsip/sip_endpoint.c
+++ b/pjsip/src/pjsip/sip_endpoint.c
@@ -1,5 +1,4 @@
/* $Id$
- *
*/
#include <pjsip/sip_endpoint.h>
#include <pjsip/sip_transaction.h>
@@ -7,17 +6,20 @@
#include <pjsip/sip_event.h>
#include <pjsip/sip_resolve.h>
#include <pjsip/sip_module.h>
-#include <pjsip/sip_misc.h>
+#include <pjsip/sip_misc.h>
+#include <pjsip/sip_errno.h>
#include <pj/except.h>
#include <pj/log.h>
#include <pj/string.h>
#include <pj/os.h>
#include <pj/pool.h>
#include <pj/hash.h>
+#include <pj/assert.h>
+#include <pj/errno.h>
#define PJSIP_EX_NO_MEMORY PJ_NO_MEMORY_EXCEPTION
-#define LOG_THIS "endpoint..."
+#define THIS_FILE "endpoint"
#define MAX_METHODS 32
@@ -84,7 +86,8 @@ static void endpt_transport_callback( pjsip_endpoint *, pjsip_rx_data *rdata );
* Create transaction.
* Defined in sip_transaction.c
*/
-pjsip_transaction * pjsip_tsx_create( pj_pool_t *pool, pjsip_endpoint *endpt);
+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
@@ -94,8 +97,8 @@ pjsip_transaction * pjsip_tsx_create( pj_pool_t *pool, pjsip_endpoint *endpt);
*/
static void pool_callback( pj_pool_t *pool, pj_size_t size )
{
- PJ_UNUSED_ARG(pool)
- PJ_UNUSED_ARG(size)
+ PJ_UNUSED_ARG(pool);
+ PJ_UNUSED_ARG(size);
PJ_THROW(PJSIP_EX_NO_MEMORY);
}
@@ -111,7 +114,7 @@ static pj_status_t init_modules( pjsip_endpoint *endpt )
//pj_str_t str_COMMA = { ", ", 2 };
extern pjsip_module aux_tsx_module;
- PJ_LOG(5, (LOG_THIS, "init_modules()"));
+ PJ_LOG(5, (THIS_FILE, "init_modules()"));
/* Load static modules. */
endpt->mod_count = PJSIP_MAX_MODULE;
@@ -164,7 +167,7 @@ static pj_status_t init_modules( pjsip_endpoint *endpt )
if (endpt->method_cnt < MAX_METHODS) {
endpt->methods[endpt->method_cnt++] = mod->methods[j];
} else {
- PJ_LOG(1,(LOG_THIS, "Too many methods"));
+ PJ_LOG(1,(THIS_FILE, "Too many methods"));
return -1;
}
}
@@ -200,7 +203,7 @@ static pj_status_t init_modules( pjsip_endpoint *endpt )
PJ_DEF(void) pjsip_endpt_destroy_tsx( pjsip_endpoint *endpt,
pjsip_transaction *tsx)
{
- PJ_LOG(5, (LOG_THIS, "pjsip_endpt_destroy_tsx(%s)", tsx->obj_name));
+ PJ_LOG(5, (THIS_FILE, "pjsip_endpt_destroy_tsx(%s)", tsx->obj_name));
pj_assert(tsx->state == PJSIP_TSX_STATE_DESTROYED);
@@ -226,7 +229,7 @@ PJ_DEF(void) pjsip_endpt_destroy_tsx( pjsip_endpoint *endpt,
/* Release the pool for the transaction. */
pj_pool_release(tsx->pool);
- PJ_LOG(4, (LOG_THIS, "tsx%p destroyed", tsx));
+ PJ_LOG(4, (THIS_FILE, "tsx%p destroyed", tsx));
}
@@ -247,11 +250,11 @@ static void endpt_do_event( pjsip_endpoint *endpt, pjsip_event *evt)
}
/* Destroy transaction if it is terminated. */
- if (evt->type == PJSIP_EVENT_TSX_STATE_CHANGED &&
- evt->obj.tsx->state == PJSIP_TSX_STATE_DESTROYED)
+ if (evt->type == PJSIP_EVENT_TSX_STATE &&
+ evt->body.tsx_state.tsx->state == PJSIP_TSX_STATE_DESTROYED)
{
/* No need to lock mutex. Mutex is locked inside the destroy function */
- pjsip_endpt_destroy_tsx( endpt, evt->obj.tsx );
+ pjsip_endpt_destroy_tsx( endpt, evt->body.tsx_state.tsx );
}
}
@@ -260,7 +263,8 @@ static void endpt_do_event( pjsip_endpoint *endpt, pjsip_event *evt)
* to be processed later.
*/
void pjsip_endpt_send_tsx_event( pjsip_endpoint *endpt, pjsip_event *evt )
-{
+{
+ // Need to protect this with try/catch?
endpt_do_event(endpt, evt);
}
@@ -301,7 +305,7 @@ PJ_DEF(pj_status_t) pjsip_endpt_set_proxies( pjsip_endpoint *endpt,
hdr = pjsip_parse_hdr(endpt->pool, &str_ROUTE, dup, len, NULL);
if (!hdr) {
pj_mutex_unlock(endpt->mutex);
- PJ_LOG(4,(LOG_THIS, "Invalid URL %s in proxy URL", dup));
+ PJ_LOG(4,(THIS_FILE, "Invalid URL %s in proxy URL", dup));
return -1;
}
@@ -327,21 +331,24 @@ PJ_DEF(const pjsip_route_hdr*) pjsip_endpt_get_routing( pjsip_endpoint *endpt )
/*
* Initialize endpoint.
*/
-PJ_DEF(pjsip_endpoint*) pjsip_endpt_create(pj_pool_factory *pf)
+PJ_DEF(pj_status_t) pjsip_endpt_create(pj_pool_factory *pf,
+ pjsip_endpoint **p_endpt)
{
pj_status_t status;
pj_pool_t *pool;
pjsip_endpoint *endpt;
pjsip_max_forwards_hdr *mf_hdr;
- PJ_LOG(5, (LOG_THIS, "pjsip_endpt_create()"));
+ PJ_LOG(5, (THIS_FILE, "pjsip_endpt_create()"));
+
+ *p_endpt = NULL;
/* Create pool */
pool = pj_pool_create(pf, "pept%p",
PJSIP_POOL_LEN_ENDPT, PJSIP_POOL_INC_ENDPT,
&pool_callback);
if (!pool)
- return NULL;
+ return PJ_ENOMEM;
/* Create endpoint. */
endpt = pj_pool_calloc(pool, 1, sizeof(*endpt));
@@ -349,53 +356,51 @@ PJ_DEF(pjsip_endpoint*) pjsip_endpt_create(pj_pool_factory *pf)
endpt->pf = pf;
/* Create mutex for the events, etc. */
- endpt->mutex = pj_mutex_create( endpt->pool, "ept%p", 0 );
- if (!endpt->mutex) {
- PJ_LOG(4, (LOG_THIS, "pjsip_endpt_init(): error creating endpoint mutex"));
+ status = pj_mutex_create_recursive( endpt->pool, "ept%p", &endpt->mutex );
+ if (status != PJ_SUCCESS) {
goto on_error;
}
/* Create mutex for the transaction table. */
- endpt->tsx_table_mutex = pj_mutex_create( endpt->pool, "mtbl%p", 0);
- if (!endpt->tsx_table_mutex) {
- PJ_LOG(4, (LOG_THIS, "pjsip_endpt_init(): error creating endpoint mutex(2)"));
+ status = pj_mutex_create_recursive( endpt->pool, "mtbl%p",
+ &endpt->tsx_table_mutex);
+ if (status != PJ_SUCCESS) {
goto on_error;
}
/* Create hash table for transaction. */
endpt->tsx_table = pj_hash_create( endpt->pool, PJSIP_MAX_TSX_COUNT );
if (!endpt->tsx_table) {
- PJ_LOG(4, (LOG_THIS, "pjsip_endpt_init(): error creating tsx hash table"));
+ status = PJ_ENOMEM;
goto on_error;
}
/* Create timer heap to manage all timers within this endpoint. */
- endpt->timer_heap = pj_timer_heap_create( endpt->pool, PJSIP_MAX_TIMER_COUNT, 0);
- if (!endpt->timer_heap) {
- PJ_LOG(4, (LOG_THIS, "pjsip_endpt_init(): error creating timer heap"));
+ status = pj_timer_heap_create( endpt->pool, PJSIP_MAX_TIMER_COUNT,
+ &endpt->timer_heap);
+ if (status != PJ_SUCCESS) {
goto on_error;
}
/* Create transport manager. */
- endpt->transport_mgr = pjsip_transport_mgr_create( endpt->pool,
- endpt,
- &endpt_transport_callback);
- if (!endpt->transport_mgr) {
- PJ_LOG(4, (LOG_THIS, "pjsip_endpt_init(): error creating transport mgr"));
+ status = pjsip_transport_mgr_create( endpt->pool,
+ endpt,
+ &endpt_transport_callback,
+ &endpt->transport_mgr);
+ if (status != PJ_SUCCESS) {
goto on_error;
}
/* Create asynchronous DNS resolver. */
endpt->resolver = pjsip_resolver_create(endpt->pool);
if (!endpt->resolver) {
- PJ_LOG(4, (LOG_THIS, "pjsip_endpt_init(): error creating resolver"));
+ PJ_LOG(4, (THIS_FILE, "pjsip_endpt_init(): error creating resolver"));
goto on_error;
}
/* Initialize TLS ID for transaction lock. */
- pjsip_tsx_lock_tls_id = pj_thread_local_alloc();
- if (pjsip_tsx_lock_tls_id == -1) {
- PJ_LOG(4, (LOG_THIS, "pjsip_endpt_init(): error allocating TLS"));
+ status = pj_thread_local_alloc(&pjsip_tsx_lock_tls_id);
+ if (status != PJ_SUCCESS) {
goto on_error;
}
pj_thread_local_set(pjsip_tsx_lock_tls_id, NULL);
@@ -414,12 +419,13 @@ PJ_DEF(pjsip_endpoint*) pjsip_endpt_create(pj_pool_factory *pf)
/* Load and init modules. */
status = init_modules(endpt);
if (status != PJ_SUCCESS) {
- PJ_LOG(4, (LOG_THIS, "pjsip_endpt_init(): error in init_modules()"));
- return NULL;
+ PJ_LOG(4, (THIS_FILE, "pjsip_endpt_init(): error in init_modules()"));
+ return status;
}
- /* Done. */
- return endpt;
+ /* Done. */
+ *p_endpt = endpt;
+ return status;
on_error:
if (endpt->transport_mgr) {
@@ -436,8 +442,8 @@ on_error:
}
pj_pool_release( endpt->pool );
- PJ_LOG(4, (LOG_THIS, "pjsip_endpt_init() failed"));
- return NULL;
+ PJ_LOG(4, (THIS_FILE, "pjsip_endpt_init() failed"));
+ return status;
}
/*
@@ -445,7 +451,7 @@ on_error:
*/
PJ_DEF(void) pjsip_endpt_destroy(pjsip_endpoint *endpt)
{
- PJ_LOG(5, (LOG_THIS, "pjsip_endpt_destroy()"));
+ PJ_LOG(5, (THIS_FILE, "pjsip_endpt_destroy()"));
/* Shutdown and destroy all transports. */
pjsip_transport_mgr_destroy(endpt->transport_mgr);
@@ -470,7 +476,7 @@ PJ_DEF(pj_pool_t*) pjsip_endpt_create_pool( pjsip_endpoint *endpt,
{
pj_pool_t *pool;
- PJ_LOG(5, (LOG_THIS, "pjsip_endpt_create_pool()"));
+ PJ_LOG(5, (THIS_FILE, "pjsip_endpt_create_pool()"));
/* Lock endpoint mutex. */
pj_mutex_lock(endpt->mutex);
@@ -483,9 +489,9 @@ PJ_DEF(pj_pool_t*) pjsip_endpt_create_pool( pjsip_endpoint *endpt,
pj_mutex_unlock(endpt->mutex);
if (pool) {
- PJ_LOG(5, (LOG_THIS, " pool %s created", pj_pool_getobjname(pool)));
+ PJ_LOG(5, (THIS_FILE, " pool %s created", pj_pool_getobjname(pool)));
} else {
- PJ_LOG(4, (LOG_THIS, "Unable to create pool %s!", pool_name));
+ PJ_LOG(4, (THIS_FILE, "Unable to create pool %s!", pool_name));
}
return pool;
@@ -497,7 +503,7 @@ PJ_DEF(pj_pool_t*) pjsip_endpt_create_pool( pjsip_endpoint *endpt,
*/
PJ_DEF(void) pjsip_endpt_destroy_pool( pjsip_endpoint *endpt, pj_pool_t *pool )
{
- PJ_LOG(5, (LOG_THIS, "pjsip_endpt_destroy_pool(%s)", pj_pool_getobjname(pool)));
+ PJ_LOG(5, (THIS_FILE, "pjsip_endpt_destroy_pool(%s)", pj_pool_getobjname(pool)));
pj_mutex_lock(endpt->mutex);
pj_pool_release( pool );
@@ -513,7 +519,7 @@ PJ_DEF(void) pjsip_endpt_handle_events( pjsip_endpoint *endpt,
pj_time_val timeout;
int i;
- PJ_LOG(5, (LOG_THIS, "pjsip_endpt_handle_events()"));
+ PJ_LOG(5, (THIS_FILE, "pjsip_endpt_handle_events()"));
/* Poll the timer. The timer heap has its own mutex for better
* granularity, so we don't need to lock end endpoint. We also keep
@@ -543,7 +549,7 @@ PJ_DEF(pj_status_t) pjsip_endpt_schedule_timer( pjsip_endpoint *endpt,
pj_timer_entry *entry,
const pj_time_val *delay )
{
- PJ_LOG(5, (LOG_THIS, "pjsip_endpt_schedule_timer(entry=%p, delay=%u.%u)",
+ PJ_LOG(5, (THIS_FILE, "pjsip_endpt_schedule_timer(entry=%p, delay=%u.%u)",
entry, delay->sec, delay->msec));
return pj_timer_heap_schedule( endpt->timer_heap, entry, delay );
}
@@ -554,7 +560,7 @@ PJ_DEF(pj_status_t) pjsip_endpt_schedule_timer( pjsip_endpoint *endpt,
PJ_DEF(void) pjsip_endpt_cancel_timer( pjsip_endpoint *endpt,
pj_timer_entry *entry )
{
- PJ_LOG(5, (LOG_THIS, "pjsip_endpt_cancel_timer(entry=%p)", entry));
+ PJ_LOG(5, (THIS_FILE, "pjsip_endpt_cancel_timer(entry=%p)", entry));
pj_timer_heap_cancel( endpt->timer_heap, entry );
}
@@ -563,26 +569,24 @@ PJ_DEF(void) pjsip_endpt_cancel_timer( pjsip_endpoint *endpt,
* Endpoint must then initialize the new transaction as either UAS or UAC, and
* register it to the hash table.
*/
-PJ_DEF(pjsip_transaction*) pjsip_endpt_create_tsx(pjsip_endpoint *endpt)
+PJ_DEF(pj_status_t) pjsip_endpt_create_tsx(pjsip_endpoint *endpt,
+ pjsip_transaction **p_tsx)
{
pj_pool_t *pool;
- pjsip_transaction *tsx;
+
+ PJ_ASSERT_RETURN(endpt && p_tsx, PJ_EINVAL);
- PJ_LOG(5, (LOG_THIS, "pjsip_endpt_create_tsx()"));
+ PJ_LOG(5, (THIS_FILE, "pjsip_endpt_create_tsx()"));
/* Request one pool for the transaction. Mutex is locked there. */
pool = pjsip_endpt_create_pool(endpt, "ptsx%p",
PJSIP_POOL_LEN_TSX, PJSIP_POOL_INC_TSX);
if (pool == NULL) {
- PJ_LOG(2, (LOG_THIS, "failed to create transaction (no pool)"));
- return NULL;
+ return PJ_ENOMEM;
}
/* Create the transaction. */
- tsx = pjsip_tsx_create(pool, endpt);
-
- /* Return */
- return tsx;
+ return pjsip_tsx_create(pool, endpt, p_tsx);
}
/*
@@ -594,7 +598,7 @@ PJ_DEF(pjsip_transaction*) pjsip_endpt_create_tsx(pjsip_endpoint *endpt)
PJ_DEF(void) pjsip_endpt_register_tsx( pjsip_endpoint *endpt,
pjsip_transaction *tsx)
{
- PJ_LOG(5, (LOG_THIS, "pjsip_endpt_register_tsx(%s)", tsx->obj_name));
+ PJ_LOG(5, (THIS_FILE, "pjsip_endpt_register_tsx(%s)", tsx->obj_name));
pj_assert(tsx->transaction_key.slen != 0);
//pj_assert(tsx->state != PJSIP_TSX_STATE_NULL);
@@ -618,7 +622,7 @@ PJ_DECL(pjsip_transaction*) pjsip_endpt_find_tsx( pjsip_endpoint *endpt,
{
pjsip_transaction *tsx;
- PJ_LOG(5, (LOG_THIS, "pjsip_endpt_find_tsx()"));
+ PJ_LOG(5, (THIS_FILE, "pjsip_endpt_find_tsx()"));
/* Start lock mutex in the endpoint. */
pj_mutex_lock(endpt->tsx_table_mutex);
@@ -658,7 +662,7 @@ static void endpt_transport_callback( pjsip_endpoint *endpt,
pjsip_transaction *tsx;
pj_bool_t a_new_transaction_just_been_created = PJ_FALSE;
- PJ_LOG(5, (LOG_THIS, "endpt_transport_callback(rdata=%p)", rdata));
+ PJ_LOG(5, (THIS_FILE, "endpt_transport_callback(rdata=%p)", rdata));
/* For response, check that the value in Via sent-by match the transport.
* If not matched, silently drop the response.
@@ -675,10 +679,10 @@ static void endpt_transport_callback( pjsip_endpoint *endpt,
port = pjsip_transport_get_default_port_for_type(type);
}
addr = pjsip_transport_get_addr_name(rdata->transport);
- addr_addr = pj_sockaddr_get_str_addr(addr);
+ addr_addr = pj_inet_ntoa(addr->sin_addr);
if (pj_strcmp2(&rdata->via->sent_by.host, addr_addr) != 0)
mismatch = PJ_TRUE;
- else if (port != pj_sockaddr_get_port(addr)) {
+ else if (port != pj_ntohs(addr->sin_port)) {
/* Port or address mismatch, we should discard response */
/* But we saw one implementation (we don't want to name it to
* protect the innocence) which put wrong sent-by port although
@@ -686,10 +690,10 @@ static void endpt_transport_callback( pjsip_endpoint *endpt,
* So we discard the response only if the port doesn't match
* both the port in sent-by and rport. We try to be lenient here!
*/
- if (rdata->via->rport_param != pj_sockaddr_get_port(addr))
+ if (rdata->via->rport_param != pj_sockaddr_in_get_port(addr))
mismatch = PJ_TRUE;
else {
- PJ_LOG(4,(LOG_THIS, "Response %p has mismatch port in sent-by"
+ PJ_LOG(4,(THIS_FILE, "Response %p has mismatch port in sent-by"
" but the rport parameter is correct",
rdata));
}
@@ -698,13 +702,7 @@ static void endpt_transport_callback( pjsip_endpoint *endpt,
if (mismatch) {
pjsip_event e;
- PJ_LOG(3, (LOG_THIS, "Response %p discarded: sent-by mismatch",
- rdata));
-
- e.type = PJSIP_EVENT_DISCARD_MSG;
- e.src_type = PJSIP_EVENT_RX_MSG;
- e.src.rdata = rdata;
- e.obj.ptr = NULL;
+ PJSIP_EVENT_INIT_DISCARD_MSG(e, rdata, PJSIP_EINVALIDVIA);
endpt_do_event( endpt, &e );
return;
}
@@ -714,7 +712,7 @@ static void endpt_transport_callback( pjsip_endpoint *endpt,
rdata_create_key( rdata);
/* Find the transaction for the received message. */
- PJ_LOG(5, (LOG_THIS, "finding tsx with key=%.*s",
+ PJ_LOG(5, (THIS_FILE, "finding tsx with key=%.*s",
rdata->key.slen, rdata->key.ptr));
/* Start lock mutex in the endpoint. */
@@ -747,34 +745,32 @@ static void endpt_transport_callback( pjsip_endpoint *endpt,
*/
pj_assert(0);
- e.type = PJSIP_EVENT_RX_200_RESPONSE;
- e.src_type = PJSIP_EVENT_RX_MSG;
- e.src.rdata = rdata;
- e.obj.ptr = NULL;
+ PJSIP_EVENT_INIT_RX_200_MSG(e, rdata);
endpt_do_event( endpt, &e );
} else {
/* Just discard the response, inform TU. */
pjsip_event e;
- PJ_LOG(3, (LOG_THIS, "Response %p discarded: transaction not found",
- rdata));
-
- e.type = PJSIP_EVENT_DISCARD_MSG;
- e.src_type = PJSIP_EVENT_RX_MSG;
- e.src.rdata = rdata;
- e.obj.ptr = NULL;
+ PJSIP_EVENT_INIT_DISCARD_MSG(e, rdata,
+ PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_CALL_TSX_DOES_NOT_EXIST));
endpt_do_event( endpt, &e );
}
/*
* For non-ACK request message, create a new transaction.
*/
- } else if (rdata->msg->line.req.method.id != PJSIP_ACK_METHOD) {
+ } else if (rdata->msg->line.req.method.id != PJSIP_ACK_METHOD) {
+
+ pj_status_t status;
+
/* Create transaction, mutex is locked there. */
- tsx = pjsip_endpt_create_tsx(endpt);
- if (!tsx)
- return;
+ status = pjsip_endpt_create_tsx(endpt, &tsx);
+ if (status != PJ_SUCCESS) {
+ PJSIP_ENDPT_LOG_ERROR((endpt, THIS_FILE, status,
+ "Unable to create transaction"));
+ return;
+ }
/* Initialize transaction as UAS. */
pjsip_tsx_init_uas( tsx, rdata );
@@ -802,10 +798,7 @@ static void endpt_transport_callback( pjsip_endpoint *endpt,
*/
pjsip_event event;
- event.type = PJSIP_EVENT_RX_ACK_MSG;
- event.src_type = PJSIP_EVENT_RX_MSG;
- event.src.rdata = rdata;
- event.obj.ptr = NULL;
+ PJSIP_EVENT_INIT_RX_ACK_MSG(event,rdata);
endpt_do_event( endpt, &event );
}
@@ -833,14 +826,24 @@ static void endpt_transport_callback( pjsip_endpoint *endpt,
/* No modules have attached itself to the transaction.
* Terminate the transaction with 501/Not Implemented.
*/
- pjsip_tx_data *tdata;
+ pjsip_tx_data *tdata;
+ pj_status_t status;
if (tsx->method.id == PJSIP_OPTIONS_METHOD) {
- tdata = pjsip_endpt_create_response(endpt, rdata, 200);
+ status = pjsip_endpt_create_response(endpt, rdata, 200,
+ &tdata);
} else {
- tdata = pjsip_endpt_create_response(endpt, rdata,
- PJSIP_SC_METHOD_NOT_ALLOWED);
- }
+ status = pjsip_endpt_create_response(endpt, rdata,
+ PJSIP_SC_METHOD_NOT_ALLOWED,
+ &tdata);
+ }
+
+ if (status != PJ_SUCCESS) {
+ PJSIP_ENDPT_LOG_ERROR((endpt, THIS_FILE, status,
+ "Unable to create response"));
+ return;
+ }
+
if (endpt->allow_hdr) {
pjsip_msg_add_hdr( tdata->msg,
pjsip_hdr_shallow_clone(tdata->pool, endpt->allow_hdr));
@@ -854,8 +857,16 @@ static void endpt_transport_callback( pjsip_endpoint *endpt,
* respond to the request at all. We terminate the request here
* with 500/Internal Server Error, to be safe.
*/
- pjsip_tx_data *tdata;
- tdata = pjsip_endpt_create_response(endpt, rdata, 500);
+ pjsip_tx_data *tdata;
+ pj_status_t status;
+
+ status = pjsip_endpt_create_response(endpt, rdata, 500, &tdata);
+ if (status != PJ_SUCCESS) {
+ PJSIP_ENDPT_LOG_ERROR((endpt, THIS_FILE, status,
+ "Unable to create response"));
+ return;
+ }
+
pjsip_tsx_on_tx_msg(tsx, tdata);
}
}
@@ -864,10 +875,11 @@ static void endpt_transport_callback( pjsip_endpoint *endpt,
/*
* Create transmit data buffer.
*/
-PJ_DEF(pjsip_tx_data*) pjsip_endpt_create_tdata( pjsip_endpoint *endpt )
+PJ_DEF(pj_status_t) pjsip_endpt_create_tdata( pjsip_endpoint *endpt,
+ pjsip_tx_data **p_tdata)
{
- PJ_LOG(5, (LOG_THIS, "pjsip_endpt_create_tdata()"));
- return pjsip_tx_data_create(endpt->transport_mgr);
+ PJ_LOG(5, (THIS_FILE, "pjsip_endpt_create_tdata()"));
+ return pjsip_tx_data_create(endpt->transport_mgr, p_tdata);
}
/*
@@ -879,7 +891,7 @@ PJ_DEF(void) pjsip_endpt_resolve( pjsip_endpoint *endpt,
void *token,
pjsip_resolver_callback *cb)
{
- PJ_LOG(5, (LOG_THIS, "pjsip_endpt_resolve()"));
+ PJ_LOG(5, (THIS_FILE, "pjsip_endpt_resolve()"));
pjsip_resolve( endpt->resolver, pool, target, token, cb);
}
@@ -893,7 +905,7 @@ PJ_DEF(void) pjsip_endpt_get_transport( pjsip_endpoint *endpt,
void *token,
pjsip_transport_completion_callback *cb)
{
- PJ_LOG(5, (LOG_THIS, "pjsip_endpt_get_transport()"));
+ PJ_LOG(5, (THIS_FILE, "pjsip_endpt_get_transport()"));
pjsip_transport_get( endpt->transport_mgr, pool, type,
remote, token, cb);
}
@@ -904,7 +916,7 @@ PJ_DEF(pj_status_t) pjsip_endpt_create_listener( pjsip_endpoint *endpt,
pj_sockaddr_in *addr,
const pj_sockaddr_in *addr_name)
{
- PJ_LOG(5, (LOG_THIS, "pjsip_endpt_create_listener()"));
+ PJ_LOG(5, (THIS_FILE, "pjsip_endpt_create_listener()"));
return pjsip_create_listener( endpt->transport_mgr, type, addr, addr_name );
}
@@ -912,7 +924,7 @@ PJ_DEF(pj_status_t) pjsip_endpt_create_udp_listener( pjsip_endpoint *endpt,
pj_sock_t sock,
const pj_sockaddr_in *addr_name)
{
- PJ_LOG(5, (LOG_THIS, "pjsip_endpt_create_udp_listener()"));
+ PJ_LOG(5, (THIS_FILE, "pjsip_endpt_create_udp_listener()"));
return pjsip_create_udp_listener( endpt->transport_mgr, sock, addr_name );
}
@@ -923,31 +935,31 @@ PJ_DEF(void) pjsip_endpt_dump( pjsip_endpoint *endpt, pj_bool_t detail )
pj_hash_iterator_t itr_val;
pj_hash_iterator_t *itr;
- PJ_LOG(5, (LOG_THIS, "pjsip_endpt_dump()"));
+ PJ_LOG(5, (THIS_FILE, "pjsip_endpt_dump()"));
/* Lock mutex. */
pj_mutex_lock(endpt->mutex);
- PJ_LOG(3, (LOG_THIS, "Dumping endpoint %p:", endpt));
+ PJ_LOG(3, (THIS_FILE, "Dumping endpoint %p:", endpt));
/* Dumping pool factory. */
(*endpt->pf->dump_status)(endpt->pf, detail);
/* Pool health. */
- PJ_LOG(3, (LOG_THIS," Endpoint pool capacity=%u, used_size=%u",
+ PJ_LOG(3, (THIS_FILE," Endpoint pool capacity=%u, used_size=%u",
pj_pool_get_capacity(endpt->pool),
pj_pool_get_used_size(endpt->pool)));
/* Transaction tables. */
count = pj_hash_count(endpt->tsx_table);
- PJ_LOG(3, (LOG_THIS, " Number of transactions: %u", count));
+ PJ_LOG(3, (THIS_FILE, " Number of transactions: %u", count));
if (count && detail) {
pj_hash_iterator_t it_val;
pj_hash_iterator_t *it;
pj_time_val now;
- PJ_LOG(3, (LOG_THIS, " Dumping transaction tables:"));
+ PJ_LOG(3, (THIS_FILE, " Dumping transaction tables:"));
pj_gettimeofday(&now);
it = pj_hash_first(endpt->tsx_table, &it_val);
@@ -974,7 +986,7 @@ PJ_DEF(void) pjsip_endpt_dump( pjsip_endpoint *endpt, pj_bool_t detail )
timeout_diff = -1;
}
- PJ_LOG(3, (LOG_THIS, " %s %s %10.*s %.9u %s t=%ds",
+ PJ_LOG(3, (THIS_FILE, " %s %s %10.*s %.9u %s t=%ds",
tsx->obj_name, role,
tsx->method.name.slen, tsx->method.name.ptr,
tsx->cseq,
@@ -991,7 +1003,7 @@ PJ_DEF(void) pjsip_endpt_dump( pjsip_endpoint *endpt, pj_bool_t detail )
*/
itr = pjsip_transport_first( endpt->transport_mgr, &itr_val );
if (itr) {
- PJ_LOG(3, (LOG_THIS, " Dumping transports:"));
+ PJ_LOG(3, (THIS_FILE, " Dumping transports:"));
do {
char src_addr[128], dst_addr[128];
@@ -1001,14 +1013,14 @@ PJ_DEF(void) pjsip_endpt_dump( pjsip_endpoint *endpt, pj_bool_t detail )
t = pjsip_transport_this(endpt->transport_mgr, itr);
addr = pjsip_transport_get_local_addr(t);
- strcpy(src_addr, pj_sockaddr_get_str_addr(addr));
- src_port = pj_sockaddr_get_port(addr);
+ pj_native_strcpy(src_addr, pj_inet_ntoa(addr->sin_addr));
+ src_port = pj_ntohs(addr->sin_port);
addr = pjsip_transport_get_remote_addr(t);
- strcpy(dst_addr, pj_sockaddr_get_str_addr(addr));
- dst_port = pj_sockaddr_get_port(addr);
+ pj_native_strcpy(dst_addr, pj_inet_ntoa(addr->sin_addr));
+ dst_port = pj_ntohs(addr->sin_port);
- PJ_LOG(3, (LOG_THIS, " %s %s %s:%d --> %s:%d (refcnt=%d)",
+ PJ_LOG(3, (THIS_FILE, " %s %s %s:%d --> %s:%d (refcnt=%d)",
pjsip_transport_get_type_name(t),
pjsip_transport_get_obj_name(t),
src_addr, src_port,
@@ -1020,13 +1032,13 @@ PJ_DEF(void) pjsip_endpt_dump( pjsip_endpoint *endpt, pj_bool_t detail )
}
/* Timer. */
- PJ_LOG(3,(LOG_THIS, " Timer heap has %u entries",
+ PJ_LOG(3,(THIS_FILE, " Timer heap has %u entries",
pj_timer_heap_count(endpt->timer_heap)));
/* Unlock mutex. */
pj_mutex_unlock(endpt->mutex);
#else
- PJ_LOG(3,(LOG_THIS, "pjsip_end_dump: can't dump because it's disabled."));
+ PJ_LOG(3,(THIS_FILE, "pjsip_end_dump: can't dump because it's disabled."));
#endif
}
diff --git a/pjsip/src/pjsip/sip_misc.c b/pjsip/src/pjsip/sip_misc.c
index 38a2e95c..a9562397 100644
--- a/pjsip/src/pjsip/sip_misc.c
+++ b/pjsip/src/pjsip/sip_misc.c
@@ -1,5 +1,4 @@
/* $Id$
- *
*/
#include <pjsip/sip_misc.h>
#include <pjsip/sip_transport.h>
@@ -13,8 +12,11 @@
#include <pj/guid.h>
#include <pj/pool.h>
#include <pj/except.h>
+#include <pj/rand.h>
+#include <pj/assert.h>
+#include <pj/errno.h>
-#define LOG_THIS "endpoint..."
+#define THIS_FILE "endpoint"
static const char *event_str[] =
{
@@ -44,8 +46,8 @@ struct aux_tsx_data
static pj_status_t aux_tsx_init( pjsip_endpoint *endpt,
struct pjsip_module *mod, pj_uint32_t id )
{
- PJ_UNUSED_ARG(endpt)
- PJ_UNUSED_ARG(mod)
+ PJ_UNUSED_ARG(endpt);
+ PJ_UNUSED_ARG(mod);
aux_mod_id = id;
return 0;
@@ -53,13 +55,16 @@ static pj_status_t aux_tsx_init( pjsip_endpoint *endpt,
static void aux_tsx_handler( struct pjsip_module *mod, pjsip_event *event )
{
- pjsip_transaction *tsx = event->obj.tsx;
+ pjsip_transaction *tsx;
struct aux_tsx_data *tsx_data;
- PJ_UNUSED_ARG(mod)
+ PJ_UNUSED_ARG(mod);
- if (event->type != PJSIP_EVENT_TSX_STATE_CHANGED)
- return;
+ if (event->type != PJSIP_EVENT_TSX_STATE)
+ return;
+
+ pj_assert(event->body.tsx_state.tsx != NULL);
+ tsx = event->body.tsx_state.tsx;
if (tsx == NULL)
return;
if (tsx->module_data[aux_mod_id] == NULL)
@@ -99,9 +104,10 @@ PJ_DEF(pj_status_t) pjsip_endpt_send_request( pjsip_endpoint *endpt,
void (*cb)(void*,pjsip_event*))
{
pjsip_transaction *tsx;
- struct aux_tsx_data *tsx_data;
+ struct aux_tsx_data *tsx_data;
+ pj_status_t status;
- tsx = pjsip_endpt_create_tsx(endpt);
+ status = pjsip_endpt_create_tsx(endpt, &tsx);
if (!tsx) {
pjsip_tx_data_dec_ref(tdata);
return -1;
@@ -134,7 +140,8 @@ PJ_DEF(pj_status_t) pjsip_endpt_send_request( pjsip_endpoint *endpt,
* That's why the session will shallow_clone it's headers before calling
* this function.
*/
-static void init_request_throw( pjsip_tx_data *tdata,
+static void init_request_throw( pjsip_endpoint *endpt,
+ pjsip_tx_data *tdata,
pjsip_method *method,
pjsip_uri *param_target,
pjsip_from_hdr *param_from,
@@ -146,6 +153,7 @@ static void init_request_throw( pjsip_tx_data *tdata,
{
pjsip_msg *msg;
pjsip_msg_body *body;
+ const pjsip_hdr *endpt_hdr;
/* Create the message. */
msg = tdata->msg = pjsip_msg_create(tdata->pool, PJSIP_REQUEST_MSG);
@@ -153,7 +161,15 @@ static void init_request_throw( pjsip_tx_data *tdata,
/* Init request URI. */
pj_memcpy(&msg->line.req.method, method, sizeof(*method));
msg->line.req.uri = param_target;
-
+
+ /* Add additional request headers from endpoint. */
+ endpt_hdr = pjsip_endpt_get_request_headers(endpt)->next;
+ while (endpt_hdr != pjsip_endpt_get_request_headers(endpt)) {
+ pjsip_hdr *hdr = pjsip_hdr_shallow_clone(tdata->pool, endpt_hdr);
+ pjsip_msg_add_hdr( tdata->msg, hdr );
+ endpt_hdr = endpt_hdr->next;
+ }
+
/* Add From header. */
if (param_from->tag.slen == 0)
pj_create_unique_string(tdata->pool, &param_from->tag);
@@ -189,15 +205,16 @@ static void init_request_throw( pjsip_tx_data *tdata,
/*
* Create arbitrary request.
*/
-PJ_DEF(pjsip_tx_data*) pjsip_endpt_create_request( pjsip_endpoint *endpt,
- const pjsip_method *method,
- const pj_str_t *param_target,
- const pj_str_t *param_from,
- const pj_str_t *param_to,
- const pj_str_t *param_contact,
- const pj_str_t *param_call_id,
- int param_cseq,
- const pj_str_t *param_text)
+PJ_DEF(pj_status_t) pjsip_endpt_create_request( pjsip_endpoint *endpt,
+ const pjsip_method *method,
+ const pj_str_t *param_target,
+ const pj_str_t *param_from,
+ const pj_str_t *param_to,
+ const pj_str_t *param_contact,
+ const pj_str_t *param_call_id,
+ int param_cseq,
+ const pj_str_t *param_text,
+ pjsip_tx_data **p_tdata)
{
pjsip_uri *target;
pjsip_tx_data *tdata;
@@ -206,14 +223,15 @@ PJ_DEF(pjsip_tx_data*) pjsip_endpt_create_request( pjsip_endpoint *endpt,
pjsip_contact_hdr *contact;
pjsip_cseq_hdr *cseq = NULL; /* = NULL, warning in VC6 */
pjsip_cid_hdr *call_id;
- pj_str_t tmp;
+ pj_str_t tmp;
+ pj_status_t status;
PJ_USE_EXCEPTION;
- PJ_LOG(5,(LOG_THIS, "Entering pjsip_endpt_create_request()"));
+ PJ_LOG(5,(THIS_FILE, "Entering pjsip_endpt_create_request()"));
- tdata = pjsip_endpt_create_tdata(endpt);
- if (!tdata)
- return NULL;
+ status = pjsip_endpt_create_tdata(endpt, &tdata);
+ if (status != PJ_SUCCESS)
+ return status;
/* Init reference counter to 1. */
pjsip_tx_data_add_ref(tdata);
@@ -223,7 +241,7 @@ PJ_DEF(pjsip_tx_data*) pjsip_endpt_create_request( pjsip_endpoint *endpt,
pj_strdup_with_null(tdata->pool, &tmp, param_target);
target = pjsip_parse_uri( tdata->pool, tmp.ptr, tmp.slen, 0);
if (target == NULL) {
- PJ_LOG(4,(LOG_THIS, "Error creating request: invalid target %s",
+ PJ_LOG(4,(THIS_FILE, "Error creating request: invalid target %s",
tmp.ptr));
goto on_error;
}
@@ -234,7 +252,7 @@ PJ_DEF(pjsip_tx_data*) pjsip_endpt_create_request( pjsip_endpoint *endpt,
from->uri = pjsip_parse_uri( tdata->pool, tmp.ptr, tmp.slen,
PJSIP_PARSE_URI_AS_NAMEADDR);
if (from->uri == NULL) {
- PJ_LOG(4,(LOG_THIS, "Error creating request: invalid 'From' URI '%s'",
+ PJ_LOG(4,(THIS_FILE, "Error creating request: invalid 'From' URI '%s'",
tmp.ptr));
goto on_error;
}
@@ -246,7 +264,7 @@ PJ_DEF(pjsip_tx_data*) pjsip_endpt_create_request( pjsip_endpoint *endpt,
to->uri = pjsip_parse_uri( tdata->pool, tmp.ptr, tmp.slen,
PJSIP_PARSE_URI_AS_NAMEADDR);
if (to->uri == NULL) {
- PJ_LOG(4,(LOG_THIS, "Error creating request: invalid 'To' URI '%s'",
+ PJ_LOG(4,(THIS_FILE, "Error creating request: invalid 'To' URI '%s'",
tmp.ptr));
goto on_error;
}
@@ -258,7 +276,7 @@ PJ_DEF(pjsip_tx_data*) pjsip_endpt_create_request( pjsip_endpoint *endpt,
contact->uri = pjsip_parse_uri( tdata->pool, tmp.ptr, tmp.slen,
PJSIP_PARSE_URI_AS_NAMEADDR);
if (contact->uri == NULL) {
- PJ_LOG(4,(LOG_THIS,
+ PJ_LOG(4,(THIS_FILE,
"Error creating request: invalid 'Contact' URI '%s'",
tmp.ptr));
goto on_error;
@@ -285,30 +303,30 @@ PJ_DEF(pjsip_tx_data*) pjsip_endpt_create_request( pjsip_endpoint *endpt,
pjsip_method_copy(tdata->pool, &cseq->method, method);
/* Create the request. */
- init_request_throw( tdata, &cseq->method, target, from, to, contact,
- call_id, cseq, param_text);
+ init_request_throw( endpt, tdata, &cseq->method, target, from, to,
+ contact, call_id, cseq, param_text);
}
PJ_DEFAULT {
- PJ_LOG(4,(LOG_THIS, "Caught exception %d when creating request",
- PJ_GET_EXCEPTION()));
+ status = PJ_ENOMEM;
goto on_error;
}
PJ_END
- PJ_LOG(4,(LOG_THIS, "Request %s (%d %.*s) created.",
+ PJ_LOG(4,(THIS_FILE, "Request %s (%d %.*s) created.",
tdata->obj_name,
cseq->cseq,
cseq->method.name.slen,
cseq->method.name.ptr));
-
- return tdata;
+
+ *p_tdata = tdata;
+ return PJ_SUCCESS;
on_error:
pjsip_tx_data_dec_ref(tdata);
- return NULL;
+ return status;
}
-PJ_DEF(pjsip_tx_data*)
+PJ_DEF(pj_status_t)
pjsip_endpt_create_request_from_hdr( pjsip_endpoint *endpt,
const pjsip_method *method,
const pjsip_uri *param_target,
@@ -317,7 +335,8 @@ pjsip_endpt_create_request_from_hdr( pjsip_endpoint *endpt,
const pjsip_contact_hdr *param_contact,
const pjsip_cid_hdr *param_call_id,
int param_cseq,
- const pj_str_t *param_text )
+ const pj_str_t *param_text,
+ pjsip_tx_data **p_tdata)
{
pjsip_uri *target;
pjsip_tx_data *tdata;
@@ -325,14 +344,15 @@ pjsip_endpt_create_request_from_hdr( pjsip_endpoint *endpt,
pjsip_to_hdr *to;
pjsip_contact_hdr *contact;
pjsip_cid_hdr *call_id;
- pjsip_cseq_hdr *cseq = NULL; /* The NULL because warning in VC6 */
+ pjsip_cseq_hdr *cseq = NULL; /* The NULL because warning in VC6 */
+ pj_status_t status;
PJ_USE_EXCEPTION;
- PJ_LOG(5,(LOG_THIS, "Entering pjsip_endpt_create_request_from_hdr()"));
+ PJ_LOG(5,(THIS_FILE, "Entering pjsip_endpt_create_request_from_hdr()"));
- tdata = pjsip_endpt_create_tdata(endpt);
- if (!tdata)
- return NULL;
+ status = pjsip_endpt_create_tdata(endpt, &tdata);
+ if (status != PJ_SUCCESS)
+ return status;
pjsip_tx_data_add_ref(tdata);
@@ -354,53 +374,56 @@ pjsip_endpt_create_request_from_hdr( pjsip_endpoint *endpt,
cseq->cseq = pj_rand() % 0xFFFF;
pjsip_method_copy(tdata->pool, &cseq->method, method);
- init_request_throw(tdata, &cseq->method, target, from, to, contact,
- call_id, cseq, param_text);
+ init_request_throw(endpt, tdata, &cseq->method, target, from, to,
+ contact, call_id, cseq, param_text);
}
PJ_DEFAULT {
- PJ_LOG(4,(LOG_THIS, "Caught exception %d when creating request",
- PJ_GET_EXCEPTION()));
+ status = PJ_ENOMEM;
goto on_error;
}
PJ_END;
- PJ_LOG(4,(LOG_THIS, "Request %s (%d %.*s) created.",
+ PJ_LOG(4,(THIS_FILE, "Request %s (%d %.*s) created.",
tdata->obj_name,
cseq->cseq,
cseq->method.name.slen,
- cseq->method.name.ptr));
- return tdata;
+ cseq->method.name.ptr));
+
+ *p_tdata = tdata;
+ return PJ_SUCCESS;
on_error:
pjsip_tx_data_dec_ref(tdata);
- return NULL;
+ return status;
}
/*
* Construct a minimal response message for the received request.
*/
-PJ_DEF(pjsip_tx_data*) pjsip_endpt_create_response( pjsip_endpoint *endpt,
- const pjsip_rx_data *rdata,
- int code)
+PJ_DEF(pj_status_t) pjsip_endpt_create_response( pjsip_endpoint *endpt,
+ const pjsip_rx_data *rdata,
+ int code,
+ pjsip_tx_data **p_tdata)
{
pjsip_tx_data *tdata;
pjsip_msg *msg, *req_msg;
pjsip_hdr *hdr;
pjsip_via_hdr *via;
- pjsip_rr_hdr *rr;
+ pjsip_rr_hdr *rr;
+ pj_status_t status;
/* rdata must be a request message. */
req_msg = rdata->msg;
pj_assert(req_msg->type == PJSIP_REQUEST_MSG);
/* Log this action. */
- PJ_LOG(5,(LOG_THIS, "pjsip_endpt_create_response(rdata=%p, code=%d)",
+ PJ_LOG(5,(THIS_FILE, "pjsip_endpt_create_response(rdata=%p, code=%d)",
rdata, code));
/* Create a new transmit buffer. */
- tdata = pjsip_endpt_create_tdata( endpt );
- if (!tdata)
- return NULL;
+ status = pjsip_endpt_create_tdata( endpt, &tdata);
+ if (status != PJ_SUCCESS)
+ return status;
/* Create new response message. */
tdata->msg = msg = pjsip_msg_create(tdata->pool, PJSIP_RESPONSE_MSG);
@@ -450,8 +473,9 @@ PJ_DEF(pjsip_tx_data*) pjsip_endpt_create_response( pjsip_endpoint *endpt,
hdr = pjsip_hdr_clone(tdata->pool, rdata->cseq);
pjsip_msg_add_hdr( msg, hdr);
- /* All done. */
- return tdata;
+ /* All done. */
+ *p_tdata = tdata;
+ return PJ_SUCCESS;
}
@@ -478,7 +502,7 @@ PJ_DEF(void) pjsip_endpt_create_ack(pjsip_endpoint *endpt,
rdata->msg->line.status.code >= 300);
/* Log this action. */
- PJ_LOG(5,(LOG_THIS, "pjsip_endpt_create_ack(rdata=%p)", rdata));
+ PJ_LOG(5,(THIS_FILE, "pjsip_endpt_create_ack(rdata=%p)", rdata));
/* Create new request message. */
ack_msg = pjsip_msg_create(tdata->pool, PJSIP_REQUEST_MSG);
@@ -502,7 +526,7 @@ PJ_DEF(void) pjsip_endpt_create_ack(pjsip_endpoint *endpt,
/* Copy To header from the original INVITE. */
to = (pjsip_to_hdr*)pjsip_msg_find_remove_hdr( invite_msg,
PJSIP_H_TO, NULL);
- pj_strdup(tdata->pool, &to->tag, &rdata->to_tag);
+ pj_strdup(tdata->pool, &to->tag, &rdata->to->tag);
pjsip_msg_add_hdr( ack_msg, (pjsip_hdr*)to );
/* Must contain single Via, just as the original INVITE. */
@@ -542,30 +566,33 @@ PJ_DEF(void) pjsip_endpt_create_ack(pjsip_endpoint *endpt,
* Construct CANCEL request for the previously sent request, according to
* chapter 9.1 of RFC3261.
*/
-PJ_DEF(pjsip_tx_data*) pjsip_endpt_create_cancel( pjsip_endpoint *endpt,
- pjsip_tx_data *req_tdata )
+PJ_DEF(pj_status_t) pjsip_endpt_create_cancel( pjsip_endpoint *endpt,
+ pjsip_tx_data *req_tdata,
+ pjsip_tx_data **p_tdata)
{
pjsip_msg *req_msg; /* the original request. */
pjsip_tx_data *cancel_tdata;
pjsip_msg *cancel_msg;
pjsip_hdr *hdr;
pjsip_cseq_hdr *req_cseq, *cseq;
- pjsip_uri *req_uri;
+ pjsip_uri *req_uri;
+ pj_status_t status;
/* Log this action. */
- PJ_LOG(5,(LOG_THIS, "pjsip_endpt_create_cancel(tdata=%p)", req_tdata));
+ PJ_LOG(5,(THIS_FILE, "pjsip_endpt_create_cancel(tdata=%p)", req_tdata));
/* Get the original request. */
req_msg = req_tdata->msg;
/* The transmit buffer must INVITE request. */
- pj_assert(req_msg->type == PJSIP_REQUEST_MSG &&
- req_msg->line.req.method.id == PJSIP_INVITE_METHOD );
+ PJ_ASSERT_RETURN(req_msg->type == PJSIP_REQUEST_MSG &&
+ req_msg->line.req.method.id == PJSIP_INVITE_METHOD,
+ PJ_EINVAL);
/* Create new transmit buffer. */
- cancel_tdata = pjsip_endpt_create_tdata( endpt );
- if (!cancel_tdata) {
- return NULL;
+ status = pjsip_endpt_create_tdata( endpt, &cancel_tdata);
+ if (status != PJ_SUCCESS) {
+ return status;
}
/* Create CANCEL request message. */
@@ -622,8 +649,9 @@ PJ_DEF(pjsip_tx_data*) pjsip_endpt_create_cancel( pjsip_endpoint *endpt,
/* Done.
* Return the transmit buffer containing the CANCEL request.
- */
- return cancel_tdata;
+ */
+ *p_tdata = cancel_tdata;
+ return PJ_SUCCESS;
}
/* Get the address parameters (host, port, flag, TTL, etc) to send the
@@ -650,8 +678,8 @@ PJ_DEF(pj_status_t) pjsip_get_response_addr(pj_pool_t *pool,
const pj_sockaddr_in *remote_addr;
remote_addr = pjsip_transport_get_remote_addr(req_transport);
pj_strdup2(pool, &send_addr->host,
- pj_sockaddr_get_str_addr(remote_addr));
- send_addr->port = pj_sockaddr_get_port(remote_addr);
+ pj_inet_ntoa(remote_addr->sin_addr));
+ send_addr->port = pj_sockaddr_in_get_port(remote_addr);
} else {
/* Set the host part */
diff --git a/pjsip/src/pjsip/sip_msg.c b/pjsip/src/pjsip/sip_msg.c
index fff7bacc..587df864 100644
--- a/pjsip/src/pjsip/sip_msg.c
+++ b/pjsip/src/pjsip/sip_msg.c
@@ -1,8 +1,7 @@
/* $Id$
- *
*/
#include <pjsip/sip_msg.h>
-#include <pjsip/print.h>
+#include <pjsip/print_util.h>
#include <pj/string.h>
#include <pj/pool.h>
@@ -264,7 +263,7 @@ PJ_DEF(void*) pjsip_msg_find_remove_hdr( pjsip_msg *msg,
return hdr;
}
-PJ_DEF(int) pjsip_msg_print( pjsip_msg *msg, char *buf, pj_size_t size)
+PJ_DEF(pj_ssize_t) pjsip_msg_print( pjsip_msg *msg, char *buf, pj_size_t size)
{
char *p=buf, *end=buf+size;
int len;
diff --git a/pjsip/src/pjsip/sip_parser.c b/pjsip/src/pjsip/sip_parser.c
index 4d439120..63cc3b53 100644
--- a/pjsip/src/pjsip/sip_parser.c
+++ b/pjsip/src/pjsip/sip_parser.c
@@ -1,25 +1,28 @@
/* $Id$
- *
*/
#include <pjsip/sip_parser.h>
#include <pjsip/sip_uri.h>
#include <pjsip/sip_msg.h>
-#include <pjsip/sip_auth_parser.h>
-#include <pj/scanner.h>
+#include <pjsip/sip_auth_parser.h>
+#include <pjsip/sip_errno.h>
+#include <pjsip/sip_transport.h> /* rdata structure */
+#include <pjlib-util/scanner.h>
#include <pj/except.h>
#include <pj/log.h>
#include <pj/hash.h>
#include <pj/os.h>
#include <pj/pool.h>
#include <pj/string.h>
-#include <ctype.h> /* tolower() */
+#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 TOKEN "-.!%*_=`'~+" /* '+' is because of application/pidf+xml
+ * in Content-Type! */
#define HOST "_-."
#define HEX_DIGIT "abcdefABCDEF"
#define PARAM_CHAR "[]/:&+$" MARK "%"
@@ -45,109 +48,98 @@ static int parser_is_initialized;
/*
* Global vars (also extern).
*/
-const pj_str_t pjsip_USER_STR = { "user", 4};
-const pj_str_t pjsip_METHOD_STR = { "method", 6};
+const pj_str_t pjsip_USER_STR = { "user", 4};
+const pj_str_t pjsip_METHOD_STR = { "method", 6};
const pj_str_t pjsip_TRANSPORT_STR = { "transport", 9};
-const pj_str_t pjsip_MADDR_STR = { "maddr", 5 };
-const pj_str_t pjsip_LR_STR = { "lr", 2 };
-const pj_str_t pjsip_SIP_STR = { "sip", 3 };
-const pj_str_t pjsip_SIPS_STR = { "sips", 4 };
-const pj_str_t pjsip_TEL_STR = { "tel", 3 };
-const pj_str_t pjsip_BRANCH_STR = { "branch", 6 };
-const pj_str_t pjsip_TTL_STR = { "ttl", 3 };
-const pj_str_t pjsip_PNAME_STR = { "received", 8 };
-const pj_str_t pjsip_Q_STR = { "q", 1 };
-const pj_str_t pjsip_EXPIRES_STR = { "expires", 7 };
-const pj_str_t pjsip_TAG_STR = { "tag", 3 };
-const pj_str_t pjsip_RPORT_STR = { "rport", 5};
-
-pj_char_spec 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_ARRAY_ELEMENTS, /* Array separator. */
- pjsip_NEWLINE_OR_EOF_SPEC, /* For eating up header.*/
- pjsip_DISPLAY_SCAN_SPEC; /* Used when searching for display name in URL. */
+const pj_str_t pjsip_MADDR_STR = { "maddr", 5 };
+const pj_str_t pjsip_LR_STR = { "lr", 2 };
+const pj_str_t pjsip_SIP_STR = { "sip", 3 };
+const pj_str_t pjsip_SIPS_STR = { "sips", 4 };
+const pj_str_t pjsip_TEL_STR = { "tel", 3 };
+const pj_str_t pjsip_BRANCH_STR = { "branch", 6 };
+const pj_str_t pjsip_TTL_STR = { "ttl", 3 };
+const pj_str_t pjsip_PNAME_STR = { "received", 8 };
+const pj_str_t pjsip_Q_STR = { "q", 1 };
+const pj_str_t pjsip_EXPIRES_STR = { "expires", 7 };
+const pj_str_t pjsip_TAG_STR = { "tag", 3 };
+const pj_str_t pjsip_RPORT_STR = { "rport", 5};
+
+/* Character Input Specification buffer. */
+static pj_cis_buf_t cis_buf;
+
+/* Character Input Specifications. */
+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_ARRAY_ELEMENTS, /* Array separator. */
+ pjsip_NEWLINE_OR_EOF_SPEC, /* For eating up header.*/
+ pjsip_DISPLAY_SCAN_SPEC; /* Used when searching for display name
+ * in URL. */
/*
* Forward decl.
*/
-static pjsip_msg * int_parse_msg( pj_scanner *scanner,
- pj_pool_t *pool,
- pjsip_parser_err_report *err_list);
-static void int_parse_param( pj_scanner *scanner,
- pj_str_t *pname,
- pj_str_t *pvalue);
-static void int_parse_req_line( pj_scanner *scanner,
- pj_pool_t *pool,
- pjsip_request_line *req_line);
-static int int_is_next_user( pj_scanner *scanner);
-static void int_parse_status_line( pj_scanner *scanner,
- pjsip_status_line *line);
-static void int_parse_user_pass( pj_scanner *scanner,
- pj_str_t *user,
- pj_str_t *pass);
-static void int_parse_uri_host_port( pj_scanner *scanner,
- pj_str_t *p_host,
- int *p_port);
-static pjsip_uri * int_parse_uri_or_name_addr( pj_scanner *scanner,
- pj_pool_t *pool, unsigned option);
-static pjsip_url * int_parse_sip_url( pj_scanner *scanner,
- pj_pool_t *pool,
- pj_bool_t parse_params);
-static pjsip_name_addr* int_parse_name_addr( pj_scanner *scanner,
- pj_pool_t *pool );
-static void parse_hdr_end( pj_scanner *scanner );
-static pjsip_accept_hdr* parse_hdr_accept( pj_scanner *scanner,
- pj_pool_t *pool);
-static pjsip_allow_hdr* parse_hdr_allow( pj_scanner *scanner,
- pj_pool_t *pool);
-static pjsip_cid_hdr* parse_hdr_call_id( pj_scanner *scanner,
- pj_pool_t *pool);
-static pjsip_contact_hdr* parse_hdr_contact( pj_scanner *scanner,
- pj_pool_t *pool);
-static pjsip_clen_hdr* parse_hdr_content_length( pj_scanner *scanner,
- pj_pool_t *pool);
-static pjsip_ctype_hdr* parse_hdr_content_type( pj_scanner *scanner,
- pj_pool_t *pool);
-static pjsip_cseq_hdr* parse_hdr_cseq( pj_scanner *scanner,
- pj_pool_t *pool);
-static pjsip_expires_hdr* parse_hdr_expires( pj_scanner *scanner,
- pj_pool_t *pool);
-static pjsip_from_hdr* parse_hdr_from( pj_scanner *scanner,
- pj_pool_t *pool);
-static pjsip_max_forwards_hdr* parse_hdr_max_forwards( pj_scanner *scanner,
- pj_pool_t *pool);
-static pjsip_min_expires_hdr* parse_hdr_min_expires( pj_scanner *scanner,
- pj_pool_t *pool);
-static pjsip_rr_hdr* parse_hdr_rr( pj_scanner *scanner,
- pj_pool_t *pool);
-static pjsip_route_hdr* parse_hdr_route( pj_scanner *scanner,
- pj_pool_t *pool);
-static pjsip_require_hdr* parse_hdr_require( pj_scanner *scanner,
- pj_pool_t *pool);
-static pjsip_retry_after_hdr* parse_hdr_retry_after( pj_scanner *scanner,
- pj_pool_t *pool);
-static pjsip_supported_hdr* parse_hdr_supported( pj_scanner *scanner,
- pj_pool_t *pool);
-static pjsip_to_hdr* parse_hdr_to( pj_scanner *scanner,
- pj_pool_t *pool);
-static pjsip_unsupported_hdr* parse_hdr_unsupported( pj_scanner *scanner,
- pj_pool_t *pool);
-static pjsip_via_hdr* parse_hdr_via( pj_scanner *scanner,
- pj_pool_t *pool);
-static pjsip_generic_string_hdr* parse_hdr_generic_string( pj_scanner *scanner,
- pj_pool_t *pool);
+static pjsip_msg * int_parse_msg( pjsip_parse_ctx *ctx,
+ pjsip_parser_err_report *err_list);
+static void int_parse_param( pj_scanner *scanner,
+ pj_str_t *pname,
+ pj_str_t *pvalue);
+static void int_parse_req_line( pj_scanner *scanner,
+ pj_pool_t *pool,
+ pjsip_request_line *req_line);
+static int int_is_next_user( pj_scanner *scanner);
+static void int_parse_status_line( pj_scanner *scanner,
+ pjsip_status_line *line);
+static void int_parse_user_pass( pj_scanner *scanner,
+ pj_str_t *user,
+ pj_str_t *pass);
+static void int_parse_uri_host_port( pj_scanner *scanner,
+ pj_str_t *p_host,
+ int *p_port);
+static pjsip_uri * int_parse_uri_or_name_addr( pj_scanner *scanner,
+ pj_pool_t *pool,
+ unsigned option);
+static pjsip_url * int_parse_sip_url( pj_scanner *scanner,
+ pj_pool_t *pool,
+ pj_bool_t parse_params);
+static pjsip_name_addr *
+ int_parse_name_addr( pj_scanner *scanner,
+ pj_pool_t *pool );
+static void parse_hdr_end( pj_scanner *scanner );
+
+static pjsip_hdr* parse_hdr_accept( pjsip_parse_ctx *ctx );
+static pjsip_hdr* parse_hdr_allow( pjsip_parse_ctx *ctx );
+static pjsip_hdr* parse_hdr_call_id( pjsip_parse_ctx *ctx);
+static pjsip_hdr* parse_hdr_contact( pjsip_parse_ctx *ctx);
+static pjsip_hdr* parse_hdr_content_len( pjsip_parse_ctx *ctx );
+static pjsip_hdr* parse_hdr_content_type( pjsip_parse_ctx *ctx );
+static pjsip_hdr* parse_hdr_cseq( pjsip_parse_ctx *ctx );
+static pjsip_hdr* parse_hdr_expires( pjsip_parse_ctx *ctx );
+static pjsip_hdr* parse_hdr_from( pjsip_parse_ctx *ctx );
+static pjsip_hdr* parse_hdr_max_forwards( pjsip_parse_ctx *ctx);
+static pjsip_hdr* parse_hdr_min_expires( pjsip_parse_ctx *ctx );
+static pjsip_hdr* parse_hdr_rr( pjsip_parse_ctx *ctx );
+static pjsip_hdr* parse_hdr_route( pjsip_parse_ctx *ctx );
+static pjsip_hdr* parse_hdr_require( pjsip_parse_ctx *ctx );
+static pjsip_hdr* parse_hdr_retry_after( pjsip_parse_ctx *ctx );
+static pjsip_hdr* parse_hdr_supported( pjsip_parse_ctx *ctx );
+static pjsip_hdr* parse_hdr_to( pjsip_parse_ctx *ctx );
+static pjsip_hdr* parse_hdr_unsupported( pjsip_parse_ctx *ctx );
+static pjsip_hdr* parse_hdr_via( pjsip_parse_ctx *ctx );
+static pjsip_hdr* parse_hdr_generic_string( pjsip_parse_ctx *ctx);
/* Convert non NULL terminated string to integer. */
-static unsigned long pj_strtoul_mindigit(const pj_str_t *str, unsigned mindig)
+static unsigned long pj_strtoul_mindigit(const pj_str_t *str,
+ unsigned mindig)
{
unsigned long value;
unsigned i;
@@ -163,20 +155,20 @@ static unsigned long pj_strtoul_mindigit(const pj_str_t *str, unsigned mindig)
}
/* Case insensitive comparison */
-#define parser_stricmp(str1, str2) \
- (str1.slen != str2.slen ? -1 : \
- !(memcmp(str1.ptr, str2.ptr, str1.slen)==0 || stricmp(str1.ptr, str2.ptr)==0))
+#define parser_stricmp(str1, str2) pj_stricmp(&str1, &str2)
+
/* Syntax error handler for parser. */
static void on_syntax_error(pj_scanner *scanner)
{
- PJ_UNUSED_ARG(scanner)
+ PJ_UNUSED_ARG(scanner);
PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
}
/* Concatenate unrecognized params into single string. */
void pjsip_concat_param_imp( pj_str_t *param, pj_pool_t *pool,
- const pj_str_t *pname, const pj_str_t *pvalue, int sepchar)
+ const pj_str_t *pname, const pj_str_t *pvalue,
+ int sepchar)
{
char *new_param, *p;
int len;
@@ -213,75 +205,144 @@ static void concat_param( pj_str_t *param, pj_pool_t *pool,
}
/* Initialize static properties of the parser. */
-static void init_parser()
+static pj_status_t init_parser()
{
- static int initialized;
-
+ static int initialized;
+ pj_status_t status;
+
if (initialized)
- return;
+ return PJ_SUCCESS;
initialized = 1;
-
- pj_cs_add_num( pjsip_DIGIT_SPEC );
- pj_cs_add_alpha( pjsip_ALPHA_SPEC );
-
- pj_cs_add_alpha( pjsip_ALNUM_SPEC );
- pj_cs_add_num( pjsip_ALNUM_SPEC );
-
- pj_cs_add_str(pjsip_NEWLINE_OR_EOF_SPEC, "\r\n");
+
+ pj_cis_buf_init(&cis_buf);
+
+ status = pj_cis_init(&cis_buf, &pjsip_DIGIT_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ pj_cis_add_num(&pjsip_DIGIT_SPEC);
+
+ status = pj_cis_init(&cis_buf, &pjsip_ALPHA_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ pj_cis_add_alpha( &pjsip_ALPHA_SPEC );
+
+ status = pj_cis_init(&cis_buf, &pjsip_ALNUM_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ pj_cis_add_alpha( &pjsip_ALNUM_SPEC );
+ pj_cis_add_num( &pjsip_ALNUM_SPEC );
+
+ status = pj_cis_init(&cis_buf, &pjsip_NEWLINE_OR_EOF_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ pj_cis_add_str(&pjsip_NEWLINE_OR_EOF_SPEC, "\r\n");
//pj_cs_set(pjsip_NEWLINE_OR_EOF_SPEC, 0);
-
- pj_cs_add_str( pjsip_ARRAY_ELEMENTS, ",\r\n");
-
- pj_memcpy(pjsip_TOKEN_SPEC, pjsip_ALNUM_SPEC, sizeof(pj_char_spec));
- pj_cs_add_str( pjsip_TOKEN_SPEC, TOKEN);
-
- pj_memcpy(pjsip_HOST_SPEC, pjsip_ALNUM_SPEC, sizeof(pj_char_spec));
- pj_cs_add_str( pjsip_HOST_SPEC, HOST);
-
- pj_memcpy(pjsip_HEX_SPEC, pjsip_DIGIT_SPEC, sizeof(pj_char_spec));
- pj_cs_add_str( pjsip_HEX_SPEC, HEX_DIGIT);
-
- pj_memcpy(pjsip_PARAM_CHAR_SPEC, pjsip_ALNUM_SPEC, sizeof(pj_char_spec));
- pj_cs_add_str( pjsip_PARAM_CHAR_SPEC, PARAM_CHAR);
-
- pj_memcpy(pjsip_USER_SPEC, pjsip_ALNUM_SPEC, sizeof(pj_char_spec));
- pj_cs_add_str( pjsip_USER_SPEC, MARK ESCAPED USER );
-
- pj_memcpy(pjsip_PASSWD_SPEC, pjsip_ALNUM_SPEC, sizeof(pj_char_spec));
- pj_cs_add_str( pjsip_PASSWD_SPEC, MARK ESCAPED PASS);
-
- pj_cs_add_str( pjsip_PROBE_USER_HOST_SPEC, "@ \n>");
- pj_cs_invert( pjsip_PROBE_USER_HOST_SPEC );
-
- pj_cs_add_str( pjsip_DISPLAY_SCAN_SPEC, ":\r\n<");
-
- pjsip_register_hdr_parser( "Accept", NULL, (pjsip_parse_hdr_func*) &parse_hdr_accept);
- pjsip_register_hdr_parser( "Allow", NULL, (pjsip_parse_hdr_func*) &parse_hdr_allow);
- pjsip_register_hdr_parser( "Call-ID", NULL, (pjsip_parse_hdr_func*) &parse_hdr_call_id);
- pjsip_register_hdr_parser( "Contact", "m", (pjsip_parse_hdr_func*) &parse_hdr_contact);
- pjsip_register_hdr_parser( "Content-Length", NULL, (pjsip_parse_hdr_func*) &parse_hdr_content_length);
- pjsip_register_hdr_parser( "Content-Type", NULL, (pjsip_parse_hdr_func*) &parse_hdr_content_type);
- pjsip_register_hdr_parser( "CSeq", NULL, (pjsip_parse_hdr_func*) &parse_hdr_cseq);
- pjsip_register_hdr_parser( "Expires", NULL, (pjsip_parse_hdr_func*) &parse_hdr_expires);
- pjsip_register_hdr_parser( "From", "f", (pjsip_parse_hdr_func*) &parse_hdr_from);
- pjsip_register_hdr_parser( "Max-Forwards", NULL, (pjsip_parse_hdr_func*) &parse_hdr_max_forwards);
- pjsip_register_hdr_parser( "Min-Expires", NULL, (pjsip_parse_hdr_func*) &parse_hdr_min_expires);
- pjsip_register_hdr_parser( "Record-Route", NULL, (pjsip_parse_hdr_func*) &parse_hdr_rr);
- pjsip_register_hdr_parser( "Route", NULL, (pjsip_parse_hdr_func*) &parse_hdr_route);
- pjsip_register_hdr_parser( "Require", NULL, (pjsip_parse_hdr_func*) &parse_hdr_require);
- pjsip_register_hdr_parser( "Retry-After", NULL, (pjsip_parse_hdr_func*) &parse_hdr_retry_after);
- pjsip_register_hdr_parser( "Supported", "k", (pjsip_parse_hdr_func*) &parse_hdr_supported);
- pjsip_register_hdr_parser( "To", "t", (pjsip_parse_hdr_func*) &parse_hdr_to);
- pjsip_register_hdr_parser( "Unsupported", NULL, (pjsip_parse_hdr_func*) &parse_hdr_unsupported);
- pjsip_register_hdr_parser( "Via", NULL, (pjsip_parse_hdr_func*) &parse_hdr_via);
+
+ status = pj_cis_init(&cis_buf, &pjsip_ARRAY_ELEMENTS);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ pj_cis_add_str( &pjsip_ARRAY_ELEMENTS, ",\r\n");
+
+ status = pj_cis_dup(&pjsip_TOKEN_SPEC, &pjsip_ALNUM_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ pj_cis_add_str( &pjsip_TOKEN_SPEC, TOKEN);
+
+ status = pj_cis_dup(&pjsip_HOST_SPEC, &pjsip_ALNUM_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ pj_cis_add_str( &pjsip_HOST_SPEC, HOST);
+
+ status = pj_cis_dup(&pjsip_HEX_SPEC, &pjsip_DIGIT_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ pj_cis_add_str( &pjsip_HEX_SPEC, HEX_DIGIT);
+
+ status = pj_cis_dup(&pjsip_PARAM_CHAR_SPEC, &pjsip_ALNUM_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ pj_cis_add_str(&pjsip_PARAM_CHAR_SPEC, PARAM_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 );
+
+ status = pj_cis_dup(&pjsip_PASSWD_SPEC, &pjsip_ALNUM_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ pj_cis_add_str( &pjsip_PASSWD_SPEC, MARK ESCAPED PASS);
+
+ status = pj_cis_init(&cis_buf, &pjsip_PROBE_USER_HOST_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ pj_cis_add_str( &pjsip_PROBE_USER_HOST_SPEC, "@ \n>");
+ pj_cis_invert( &pjsip_PROBE_USER_HOST_SPEC );
+
+ status = pj_cis_init(&cis_buf, &pjsip_DISPLAY_SCAN_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ pj_cis_add_str( &pjsip_DISPLAY_SCAN_SPEC, ":\r\n<");
+
+ status = pjsip_register_hdr_parser( "Accept", NULL, &parse_hdr_accept);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ status = pjsip_register_hdr_parser( "Allow", NULL, &parse_hdr_allow);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ status = pjsip_register_hdr_parser( "Call-ID", NULL, &parse_hdr_call_id);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ status = pjsip_register_hdr_parser( "Contact", "m", &parse_hdr_contact);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ status = pjsip_register_hdr_parser( "Content-Length", NULL,
+ &parse_hdr_content_len);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ status = pjsip_register_hdr_parser( "Content-Type", NULL,
+ &parse_hdr_content_type);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ status = pjsip_register_hdr_parser( "CSeq", NULL, &parse_hdr_cseq);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ status = pjsip_register_hdr_parser( "Expires", NULL, &parse_hdr_expires);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ status = pjsip_register_hdr_parser( "From", "f", &parse_hdr_from);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ status = pjsip_register_hdr_parser( "Max-Forwards", NULL,
+ &parse_hdr_max_forwards);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ status = pjsip_register_hdr_parser( "Min-Expires", NULL,
+ &parse_hdr_min_expires);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ status = pjsip_register_hdr_parser( "Record-Route", NULL, &parse_hdr_rr);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ status = pjsip_register_hdr_parser( "Route", NULL, &parse_hdr_route);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ status = pjsip_register_hdr_parser( "Require", NULL, &parse_hdr_require);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ status = pjsip_register_hdr_parser( "Retry-After", NULL,
+ &parse_hdr_retry_after);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ status = pjsip_register_hdr_parser( "Supported", "k",
+ &parse_hdr_supported);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ status = pjsip_register_hdr_parser( "To", "t", &parse_hdr_to);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ status = pjsip_register_hdr_parser( "Unsupported", NULL,
+ &parse_hdr_unsupported);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+
+ status = pjsip_register_hdr_parser( "Via", NULL, &parse_hdr_via);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
/* Register auth parser. */
- pjsip_auth_init_parser();
-
+ status = pjsip_auth_init_parser();
+
+ return status;
}
-static void init_sip_parser()
+static void init_sip_parser(void)
{
if (!parser_is_initialized) {
/* Prevent race cond. */
@@ -317,29 +378,30 @@ static int compare_handler( const handler_rec *r1,
return 1;
/* Equal length and equal hash. compare the strings. */
- return strcmp(r1->hname, name);
+ return pj_native_strcmp(r1->hname, name);
}
/* Register one handler for one header name. */
-static int int_register_parser( const char *name, pjsip_parse_hdr_func *fptr )
+static pj_status_t int_register_parser( const char *name,
+ pjsip_parse_hdr_func *fptr )
{
unsigned pos;
handler_rec rec;
unsigned i;
if (handler_count >= PJ_ARRAY_SIZE(handler)) {
- return -1;
+ return PJ_ETOOMANY;
}
/* Initialize temporary handler. */
rec.handler = fptr;
rec.hname_len = strlen(name);
if (rec.hname_len >= sizeof(rec.hname)) {
- return -1;
+ return PJ_ENAMETOOLONG;
}
/* Name is copied in lowercase. */
for (i=0; i<rec.hname_len; ++i) {
- rec.hname[i] = (char)tolower(name[i]);
+ rec.hname[i] = (char)pj_tolower(name[i]);
}
rec.hname[i] = '\0';
/* Hash value is calculated from the lowercase name. */
@@ -348,10 +410,11 @@ static int int_register_parser( const char *name, pjsip_parse_hdr_func *fptr )
/* Get the pos to insert the new handler. */
for (pos=0; pos < handler_count; ++pos) {
int d;
- d = compare_handler(&handler[pos], rec.hname, rec.hname_len, rec.hname_hash);
+ d = compare_handler(&handler[pos], rec.hname, rec.hname_len,
+ rec.hname_hash);
if (d == 0) {
pj_assert(0);
- return -1;
+ return PJ_EEXISTS;
}
if (d > 0) {
break;
@@ -360,13 +423,14 @@ static int int_register_parser( const char *name, pjsip_parse_hdr_func *fptr )
/* Shift handlers. */
if (pos != handler_count) {
- pj_memmove( &handler[pos+1], &handler[pos], (handler_count-pos)*sizeof(handler_rec));
+ pj_memmove( &handler[pos+1], &handler[pos],
+ (handler_count-pos)*sizeof(handler_rec));
}
/* Add new handler. */
pj_memcpy( &handler[pos], &rec, sizeof(handler_rec));
++handler_count;
- return 0;
+ return PJ_SUCCESS;
}
/* Register parser handler. If both header name and short name are valid,
@@ -375,14 +439,19 @@ static int int_register_parser( const char *name, pjsip_parse_hdr_func *fptr )
PJ_DEF(pj_status_t) pjsip_register_hdr_parser( const char *hname,
const char *hshortname,
pjsip_parse_hdr_func *fptr)
-{
- if (int_register_parser(hname, fptr)) {
- return -1;
+{
+ pj_status_t status;
+
+ status = int_register_parser(hname, fptr);
+ if (status != PJ_SUCCESS) {
+ return status;
}
- if (hshortname && int_register_parser(hshortname, fptr)) {
- return -1;
+ if (hshortname) {
+ status = int_register_parser(hshortname, fptr);
+ if (status != PJ_SUCCESS)
+ return status;
}
- return 0;
+ return PJ_SUCCESS;
}
/* Find handler to parse the header name. */
@@ -392,17 +461,18 @@ static pjsip_parse_hdr_func * find_handler(const pj_str_t *hname)
char hname_copy[PJSIP_MAX_HNAME_LEN];
pj_uint32_t hash;
int comp;
- unsigned i, n;
+ unsigned n;
+
+ if (hname->slen >= PJSIP_MAX_HNAME_LEN) {
+ pj_assert(!"Header name is too long!");
+ return NULL;
+ }
/* Calculate hash value while converting the header to lowercase.
* Don't assume that 'hname' is NULL terminated.
*/
- hash = 0;
- for (i=0; i<(unsigned)hname->slen; ++i) {
- hname_copy[i] = (char)tolower(hname->ptr[i]);
- hash = hash * PJ_HASH_MULTIPLIER + hname_copy[i];
- }
- hname_copy[i] = '\0';
+ hash = pj_hash_calc_tolower(0, hname_copy, hname);
+ hname_copy[hname->slen] = '\0';
/* Binary search for the handler. */
comp = -1;
@@ -428,19 +498,26 @@ static pjsip_parse_hdr_func * find_handler(const pj_str_t *hname)
}
/* Public function to parse SIP message. */
-PJ_DEF(pjsip_msg*) pjsip_parse_msg( pj_pool_t *pool, char *buf, pj_size_t size,
+PJ_DEF(pjsip_msg*) pjsip_parse_msg( pj_pool_t *pool,
+ char *buf, pj_size_t size,
pjsip_parser_err_report *err_list)
{
pjsip_msg *msg = NULL;
- pj_scanner scanner;
+ pj_scanner scanner;
+ pjsip_parse_ctx context;
PJ_USE_EXCEPTION;
init_sip_parser();
- pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER, &on_syntax_error);
+ pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER,
+ &on_syntax_error);
+
+ context.scanner = &scanner;
+ context.pool = pool;
+ context.rdata = NULL;
PJ_TRY {
- msg = int_parse_msg(&scanner, pool, err_list);
+ msg = int_parse_msg(&context, err_list);
}
PJ_DEFAULT {
msg = NULL;
@@ -450,6 +527,35 @@ PJ_DEF(pjsip_msg*) pjsip_parse_msg( pj_pool_t *pool, char *buf, pj_size_t size,
pj_scan_fini(&scanner);
return msg;
}
+
+/* Public function to parse as rdata.*/
+PJ_DEF(pjsip_msg *) pjsip_parse_rdata( char *buf, pj_size_t size,
+ pjsip_rx_data *rdata )
+{
+ pj_scanner scanner;
+ pjsip_parse_ctx context;
+ PJ_USE_EXCEPTION;
+
+ init_sip_parser();
+
+ pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER,
+ &on_syntax_error);
+
+ context.scanner = &scanner;
+ context.pool = rdata->pool;
+ context.rdata = rdata;
+
+ PJ_TRY {
+ rdata->msg = int_parse_msg(&context, &rdata->parse_err);
+ }
+ PJ_DEFAULT {
+ rdata->msg = NULL;
+ }
+ PJ_END
+
+ pj_scan_fini(&scanner);
+ return rdata->msg;
+}
/* Determine if a message has been received. */
PJ_DEF(pj_bool_t) pjsip_find_msg( const char *buf, pj_size_t size,
@@ -466,24 +572,26 @@ PJ_DEF(pj_bool_t) pjsip_find_msg( const char *buf, pj_size_t size,
/* For datagram, the whole datagram IS the message. */
if (is_datagram) {
- return PJ_TRUE;
+ return PJ_SUCCESS;
}
/* Find the end of header area by finding an empty line. */
- if ((pos = strstr(buf, "\n\r\n")) == NULL) {
- return PJ_FALSE;
+ if ((pos = pj_native_strstr(buf, "\n\r\n")) == NULL) {
+ return PJSIP_EPARTIALMSG;
}
hdr_end = pos+1;
body_start = pos+3;
/* Find "Content-Length" header the hard way. */
- line = strchr(buf, '\n');
+ line = pj_native_strchr(buf, '\n');
while (line && line < hdr_end-14) {
++line;
- if ( ((*line=='C' || *line=='c') && strncasecmp(line, "Content-Length", 14) == 0) ||
- ((*line=='l' || *line=='L') && (*(line+1)==' ' || *(line+1)=='\t' || *(line+1)==':')))
+ if ( ((*line=='C' || *line=='c') &&
+ pj_native_strncasecmp(line, "Content-Length", 14) == 0) ||
+ ((*line=='l' || *line=='L') &&
+ (*(line+1)==' ' || *(line+1)=='\t' || *(line+1)==':')))
{
/* Try to parse the header. */
pj_scanner scanner;
@@ -509,7 +617,7 @@ PJ_DEF(pj_bool_t) pjsip_find_msg( const char *buf, pj_size_t size,
}
/* Get number */
- pj_scan_get(&scanner, pjsip_DIGIT_SPEC, &str_clen);
+ pj_scan_get(&scanner, &pjsip_DIGIT_SPEC, &str_clen);
/* Get newline. */
pj_scan_get_newline(&scanner);
@@ -527,24 +635,22 @@ PJ_DEF(pj_bool_t) pjsip_find_msg( const char *buf, pj_size_t size,
break;
/* Go to next line. */
- line = strchr(line, '\n');
+ line = pj_native_strchr(line, '\n');
}
/* Found Content-Length? */
if (content_length == -1) {
- PJ_LOG(4, ("sipparser", "pjsip_find_msg: incoming TCP packet has missing "
- "Content-Length header, treated as incomplete."));
- return PJ_FALSE;
+ return PJSIP_EMISSINGHDR;
}
/* Enough packet received? */
*msg_size = (body_start - buf) + content_length;
- return (*msg_size) <= size;
+ return (*msg_size) <= size ? PJ_SUCCESS : PJSIP_EPARTIALMSG;
#else
- PJ_UNUSED_ARG(buf)
- PJ_UNUSED_ARG(is_datagram)
+ PJ_UNUSED_ARG(buf);
+ PJ_UNUSED_ARG(is_datagram);
*msg_size = size;
- return 1;
+ return PJ_SUCCESS;
#endif
}
@@ -557,10 +663,7 @@ PJ_DEF(pjsip_uri*) pjsip_parse_uri( pj_pool_t *pool,
pj_scanner scanner;
pjsip_uri *uri = NULL;
- if (!parser_is_initialized) {
- init_parser();
- parser_is_initialized = 1;
- }
+ init_sip_parser();
pj_scan_init(&scanner, buf, size, 0, &on_syntax_error);
@@ -571,7 +674,9 @@ PJ_DEF(pjsip_uri*) pjsip_parse_uri( pj_pool_t *pool,
PJ_END;
/* Must have exhausted all inputs. */
- if (pj_scan_is_eof(&scanner) || *scanner.current=='\r' || *scanner.current=='\n') {
+ if (pj_scan_is_eof(&scanner) || *scanner.curptr=='\r' ||
+ *scanner.curptr=='\n')
+ {
/* Success. */
pj_scan_fini(&scanner);
return uri;
@@ -586,7 +691,8 @@ PJ_DEF(pjsip_uri*) pjsip_parse_uri( pj_pool_t *pool,
* This assumes that the 'data' member points to a contigous memory where the
* actual body is laid.
*/
-static int generic_print_body (pjsip_msg_body *msg_body, char *buf, pj_size_t size)
+static int generic_print_body (pjsip_msg_body *msg_body,
+ char *buf, pj_size_t size)
{
pjsip_msg_body *body = msg_body;
if (size < body->len)
@@ -597,19 +703,21 @@ static int generic_print_body (pjsip_msg_body *msg_body, char *buf, pj_size_t si
}
/* Internal function to parse SIP message */
-static pjsip_msg *int_parse_msg( pj_scanner *scanner, pj_pool_t *pool,
+static pjsip_msg *int_parse_msg( pjsip_parse_ctx *ctx,
pjsip_parser_err_report *err_list)
{
PJ_USE_EXCEPTION;
int ch;
pjsip_msg *msg;
pjsip_ctype_hdr *ctype_hdr = NULL;
+ pj_scanner *scanner = ctx->scanner;
+ pj_pool_t *pool = ctx->pool;
/* Skip leading newlines. */
- ch = *scanner->current;
+ ch = *scanner->curptr;
while (ch=='\r' || ch=='\n') {
pj_scan_get_char(scanner);
- ch = *scanner->current;
+ ch = *scanner->curptr;
}
msg = pjsip_msg_create(pool, PJSIP_REQUEST_MSG);
@@ -630,7 +738,7 @@ static pjsip_msg *int_parse_msg( pj_scanner *scanner, pj_pool_t *pool,
pjsip_hdr *hdr = NULL;
/* Get hname. */
- pj_scan_get( scanner, pjsip_TOKEN_SPEC, &hname);
+ pj_scan_get( scanner, &pjsip_TOKEN_SPEC, &hname);
ch = pj_scan_get_char( scanner );
if (ch != ':') {
PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
@@ -645,12 +753,11 @@ static pjsip_msg *int_parse_msg( pj_scanner *scanner, pj_pool_t *pool,
* hname/hvalue pair.
*/
if (handler) {
- hdr = (*handler)(scanner, pool);
+ hdr = (*handler)(ctx);
} else {
- pjsip_generic_string_hdr *ghdr = parse_hdr_generic_string(scanner, pool);
- ghdr->type = PJSIP_H_OTHER;
- ghdr->name = ghdr->sname = hname;
- hdr = (pjsip_hdr*)ghdr;
+ hdr = parse_hdr_generic_string(ctx);
+ hdr->type = PJSIP_H_OTHER;
+ hdr->name = hdr->sname = hname;
}
/* Check if we've just parsed a Content-Type header.
@@ -668,8 +775,9 @@ static pjsip_msg *int_parse_msg( pj_scanner *scanner, pj_pool_t *pool,
pj_str_t token;
hdr = NULL;
- PJ_LOG(4,("sipparser", "Syntax error in line %d col %d (hname=%.*s)",
- scanner->line, scanner->col, hname.slen, hname.ptr));
+ //PJ_LOG(4,("sipparser",
+ // "Syntax error in line %d col %d (hname=%.*s)",
+ // scanner->line, scanner->col, hname.slen, hname.ptr));
if (err_list) {
pjsip_parser_err_report *err_info;
@@ -684,7 +792,7 @@ static pjsip_msg *int_parse_msg( pj_scanner *scanner, pj_pool_t *pool,
}
if (!pj_scan_is_eof(scanner)) {
- pj_scan_get_until(scanner, pjsip_NEWLINE_OR_EOF_SPEC, &token);
+ pj_scan_get_until(scanner, &pjsip_NEWLINE_OR_EOF_SPEC, &token);
parse_hdr_end(scanner);
}
}
@@ -702,23 +810,23 @@ static pjsip_msg *int_parse_msg( pj_scanner *scanner, pj_pool_t *pool,
/* Parse until EOF or an empty line is found. */
} while (!pj_scan_is_eof(scanner) &&
- *scanner->current != '\r' && *scanner->current != '\n');
+ *scanner->curptr != '\r' && *scanner->curptr != '\n');
/* If empty line is found, eat it. */
if (!pj_scan_is_eof(scanner)) {
- if (*scanner->current=='\r' || *scanner->current=='\n') {
+ if (*scanner->curptr=='\r' || *scanner->curptr=='\n') {
pj_scan_get_newline(scanner);
}
}
- /* If we have Content-Type header, treat the rest of the message as body. */
+ /* If we have Content-Type header, treat the rest of the message as body.*/
if (ctype_hdr) {
pjsip_msg_body *body = pj_pool_alloc(pool, sizeof(pjsip_msg_body));
- pj_strdup (pool, &body->content_type.type, &ctype_hdr->media.type);
- pj_strdup (pool, &body->content_type.subtype, &ctype_hdr->media.subtype);
- pj_strdup (pool, &body->content_type.param, &ctype_hdr->media.param);
- body->data = scanner->current;
- body->len = scanner->end - scanner->current;
+ pj_strdup(pool, &body->content_type.type, &ctype_hdr->media.type);
+ pj_strdup(pool, &body->content_type.subtype, &ctype_hdr->media.subtype);
+ pj_strdup(pool, &body->content_type.param, &ctype_hdr->media.param);
+ body->data = scanner->curptr;
+ body->len = scanner->end - scanner->curptr;
body->print_body = &generic_print_body;
msg->body = body;
@@ -733,20 +841,20 @@ void pjsip_parse_param_imp( pj_scanner *scanner,
unsigned option)
{
/* pname */
- pj_scan_get(scanner, pjsip_PARAM_CHAR_SPEC, pname);
+ pj_scan_get(scanner, &pjsip_PARAM_CHAR_SPEC, pname);
/* pvalue, if any */
- if (*scanner->current == '=') {
+ if (*scanner->curptr == '=') {
pj_scan_get_char(scanner);
/* pvalue can be a quoted string. */
- if (*scanner->current == '"') {
+ if (*scanner->curptr == '"') {
pj_scan_get_quote( scanner, '"', '"', pvalue);
if (option & PJSIP_PARSE_REMOVE_QUOTE) {
pvalue->ptr++;
pvalue->slen -= 2;
}
} else {
- pj_scan_get(scanner, pjsip_PARAM_CHAR_SPEC, pvalue);
+ pj_scan_get(scanner, &pjsip_PARAM_CHAR_SPEC, pvalue);
}
} else {
pvalue->ptr = NULL;
@@ -769,11 +877,11 @@ static void int_parse_param( pj_scanner *scanner,
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);
- if (*scanner->current == ':') {
+ pj_scan_get( scanner, &pjsip_HOST_SPEC, host);
+ if (*scanner->curptr == ':') {
pj_str_t port;
pj_scan_get_char(scanner);
- pj_scan_get(scanner, pjsip_DIGIT_SPEC, &port);
+ pj_scan_get(scanner, &pjsip_DIGIT_SPEC, &port);
*p_port = pj_strtoul(&port);
} else {
*p_port = 0;
@@ -789,7 +897,7 @@ static int int_is_next_user(pj_scanner *scanner)
/* Find character '@'. If this character exist, then the token
* must be a username.
*/
- if (pj_scan_peek( scanner, pjsip_PROBE_USER_HOST_SPEC, &dummy) == '@')
+ if (pj_scan_peek( scanner, &pjsip_PROBE_USER_HOST_SPEC, &dummy) == '@')
is_user = 1;
else
is_user = 0;
@@ -801,10 +909,10 @@ static int int_is_next_user(pj_scanner *scanner)
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);
- if ( *scanner->current == ':') {
+ pj_scan_get( scanner, &pjsip_USER_SPEC, user);
+ if ( *scanner->curptr == ':') {
pj_scan_get_char( scanner );
- pj_scan_get( scanner, pjsip_PASSWD_SPEC, pass);
+ pj_scan_get( scanner, &pjsip_PASSWD_SPEC, pass);
} else {
pass->ptr = NULL;
pass->slen = 0;
@@ -815,13 +923,13 @@ static void int_parse_user_pass( pj_scanner *scanner,
}
/* Parse all types of URI. */
-static pjsip_uri *int_parse_uri_or_name_addr(pj_scanner *scanner, pj_pool_t *pool,
- unsigned option)
+static pjsip_uri *int_parse_uri_or_name_addr( pj_scanner *scanner, pj_pool_t *pool,
+ unsigned opt)
{
pjsip_uri *uri;
int is_name_addr = 0;
- if (*scanner->current=='"' || *scanner->current=='<') {
+ if (*scanner->curptr=='"' || *scanner->curptr=='<') {
uri = (pjsip_uri*)int_parse_name_addr( scanner, pool );
is_name_addr = 1;
} else {
@@ -830,14 +938,17 @@ static pjsip_uri *int_parse_uri_or_name_addr(pj_scanner *scanner, pj_pool_t *poo
int colon;
pj_scan_save_state( scanner, &backtrack);
- pj_scan_get( scanner, pjsip_TOKEN_SPEC, &scheme);
+ pj_scan_get( scanner, &pjsip_TOKEN_SPEC, &scheme);
colon = pj_scan_get_char( scanner );
pj_scan_restore_state( scanner, &backtrack);
- if (colon==':' && (parser_stricmp(scheme, pjsip_SIP_STR)==0 || parser_stricmp(scheme, pjsip_SIPS_STR)==0))
+ if (colon==':' &&
+ (parser_stricmp(scheme, pjsip_SIP_STR)==0 ||
+ parser_stricmp(scheme, pjsip_SIPS_STR)==0))
{
- uri = (pjsip_uri*)int_parse_sip_url( scanner, pool,
- (option & PJSIP_PARSE_URI_IN_FROM_TO_HDR) == 0 );
+ uri = (pjsip_uri*)
+ int_parse_sip_url( scanner, pool,
+ (opt & PJSIP_PARSE_URI_IN_FROM_TO_HDR)== 0);
} else if (colon==':' && parser_stricmp( scheme, pjsip_TEL_STR)==0) {
@@ -852,7 +963,7 @@ static pjsip_uri *int_parse_uri_or_name_addr(pj_scanner *scanner, pj_pool_t *poo
}
/* Should we return the URI object as name address? */
- if (option & PJSIP_PARSE_URI_AS_NAMEADDR) {
+ if (opt & PJSIP_PARSE_URI_AS_NAMEADDR) {
if (is_name_addr == 0) {
pjsip_name_addr *name_addr;
@@ -870,21 +981,22 @@ static pjsip_uri *int_parse_uri_or_name_addr(pj_scanner *scanner, pj_pool_t *poo
static pjsip_uri *int_parse_uri(pj_scanner *scanner, pj_pool_t *pool,
pj_bool_t parse_params)
{
- if (*scanner->current=='"' || *scanner->current=='<') {
+ if (*scanner->curptr=='"' || *scanner->curptr=='<') {
return (pjsip_uri*)int_parse_name_addr( scanner, pool );
} else {
pj_str_t scheme;
int colon;
/* Get scheme. */
- colon = pj_scan_peek(scanner, pjsip_TOKEN_SPEC, &scheme);
+ colon = pj_scan_peek(scanner, &pjsip_TOKEN_SPEC, &scheme);
if (colon != ':') {
PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
}
- if ((parser_stricmp(scheme, pjsip_SIP_STR)==0 || parser_stricmp(scheme, pjsip_SIPS_STR)==0))
+ if ((parser_stricmp(scheme, pjsip_SIP_STR)==0 ||
+ parser_stricmp(scheme, pjsip_SIPS_STR)==0))
{
- return (pjsip_uri*)int_parse_sip_url( scanner, pool, parse_params );
+ return (pjsip_uri*)int_parse_sip_url( scanner, pool, parse_params);
} else if (parser_stricmp(scheme, pjsip_TEL_STR)==0) {
PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
@@ -908,7 +1020,7 @@ static pjsip_url *int_parse_sip_url( pj_scanner *scanner,
int skip_ws = scanner->skip_ws;
scanner->skip_ws = 0;
- pj_scan_get(scanner, pjsip_TOKEN_SPEC, &scheme);
+ pj_scan_get(scanner, &pjsip_TOKEN_SPEC, &scheme);
colon = pj_scan_get_char(scanner);
if (colon != ':') {
PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
@@ -937,7 +1049,7 @@ static pjsip_url *int_parse_sip_url( pj_scanner *scanner,
int_parse_uri_host_port(scanner, &url->host, &url->port);
/* Get URL parameters. */
- while ( parse_params && *scanner->current == ';' ) {
+ while ( parse_params && *scanner->curptr == ';' ) {
pj_str_t pname, pvalue;
int_parse_param( scanner, &pname, &pvalue);
@@ -948,7 +1060,7 @@ static pjsip_url *int_parse_sip_url( pj_scanner *scanner,
} else if (!parser_stricmp(pname, pjsip_METHOD_STR) && pvalue.slen) {
url->method_param = pvalue;
- } else if (!parser_stricmp(pname, pjsip_TRANSPORT_STR) && pvalue.slen) {
+ } else if (!parser_stricmp(pname,pjsip_TRANSPORT_STR) && pvalue.slen) {
url->transport_param = pvalue;
} else if (!parser_stricmp(pname, pjsip_TTL_STR) && pvalue.slen) {
@@ -966,8 +1078,9 @@ static pjsip_url *int_parse_sip_url( pj_scanner *scanner,
}
/* Get header params. */
- if (parse_params && *scanner->current == '?') {
- pj_scan_get_until(scanner, pjsip_NEWLINE_OR_EOF_SPEC, &url->header_param);
+ if (parse_params && *scanner->curptr == '?') {
+ pj_scan_get_until(scanner, &pjsip_NEWLINE_OR_EOF_SPEC,
+ &url->header_param);
}
scanner->skip_ws = skip_ws;
@@ -984,10 +1097,10 @@ static pjsip_name_addr *int_parse_name_addr( pj_scanner *scanner,
name_addr = pjsip_name_addr_create(pool);
- if (*scanner->current == '"') {
+ if (*scanner->curptr == '"') {
pj_scan_get_quote( scanner, '"', '"', &name_addr->display);
- } else if (*scanner->current != '<') {
+ } else if (*scanner->curptr != '<') {
int next;
pj_str_t dummy;
@@ -996,7 +1109,7 @@ static pjsip_name_addr *int_parse_name_addr( pj_scanner *scanner,
* We're only interested in display name, because SIP URL
* will be parser later.
*/
- next = pj_scan_peek_until(scanner, pjsip_DISPLAY_SCAN_SPEC, &dummy);
+ next = pj_scan_peek_until(scanner, &pjsip_DISPLAY_SCAN_SPEC, &dummy);
if (next == '<') {
/* Ok, this is what we're looking for, a display name. */
pj_scan_get_until_ch( scanner, '<', &name_addr->display);
@@ -1008,7 +1121,7 @@ static pjsip_name_addr *int_parse_name_addr( pj_scanner *scanner,
pj_scan_skip_whitespace(scanner);
/* Get the SIP-URL */
- has_bracket = (*scanner->current == '<');
+ has_bracket = (*scanner->curptr == '<');
if (has_bracket)
pj_scan_get_char(scanner);
name_addr->uri = int_parse_uri( scanner, pool, PJ_TRUE );
@@ -1025,7 +1138,7 @@ static void int_parse_req_line( pj_scanner *scanner, pj_pool_t *pool,
{
pj_str_t token;
- pj_scan_get( scanner, pjsip_TOKEN_SPEC, &token);
+ pj_scan_get( scanner, &pjsip_TOKEN_SPEC, &token);
pjsip_method_init_np( &req_line->method, &token);
req_line->uri = int_parse_uri(scanner, pool, PJ_TRUE);
@@ -1045,9 +1158,10 @@ static void int_parse_status_line( pj_scanner *scanner,
PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
pj_scan_advance_n( scanner, 7, 1);
- pj_scan_get( scanner, pjsip_DIGIT_SPEC, &token);
+ pj_scan_get( scanner, &pjsip_DIGIT_SPEC, &token);
status_line->code = pj_strtoul(&token);
- pj_scan_get_until( scanner, pjsip_NEWLINE_OR_EOF_SPEC, &status_line->reason);
+ pj_scan_get_until( scanner, &pjsip_NEWLINE_OR_EOF_SPEC,
+ &status_line->reason);
pj_scan_get_newline( scanner );
}
@@ -1056,7 +1170,7 @@ static void parse_hdr_end( pj_scanner *scanner )
{
if (pj_scan_is_eof(scanner)) {
; /* Do nothing. */
- } else if (*scanner->current == '&') {
+ } else if (*scanner->curptr == '&') {
pj_scan_get_char(scanner);
} else {
pj_scan_get_newline(scanner);
@@ -1073,12 +1187,13 @@ void pjsip_parse_end_hdr_imp( pj_scanner *scanner )
static void parse_generic_array_hdr( pjsip_generic_array_hdr *hdr,
pj_scanner *scanner)
{
- pj_scan_get_until( scanner, pjsip_ARRAY_ELEMENTS, &hdr->values[0]);
+ pj_scan_get_until( scanner, &pjsip_ARRAY_ELEMENTS, &hdr->values[0]);
hdr->count++;
- while (*scanner->current == ',') {
+ while (*scanner->curptr == ',') {
pj_scan_get_char(scanner);
- pj_scan_get_until( scanner, pjsip_ARRAY_ELEMENTS, &hdr->values[hdr->count]);
+ pj_scan_get_until( scanner, &pjsip_ARRAY_ELEMENTS,
+ &hdr->values[hdr->count]);
hdr->count++;
}
parse_hdr_end(scanner);
@@ -1088,7 +1203,7 @@ static void parse_generic_array_hdr( pjsip_generic_array_hdr *hdr,
static void parse_generic_string_hdr( pjsip_generic_string_hdr *hdr,
pj_scanner *scanner )
{
- pj_scan_get_until( scanner, pjsip_NEWLINE_OR_EOF_SPEC, &hdr->hvalue);
+ pj_scan_get_until( scanner, &pjsip_NEWLINE_OR_EOF_SPEC, &hdr->hvalue);
parse_hdr_end(scanner);
}
@@ -1097,38 +1212,39 @@ static void parse_generic_int_hdr( pjsip_generic_int_hdr *hdr,
pj_scanner *scanner )
{
pj_str_t tmp;
- pj_scan_get_until( scanner, pjsip_NEWLINE_OR_EOF_SPEC, &tmp);
+ pj_scan_get_until( scanner, &pjsip_NEWLINE_OR_EOF_SPEC, &tmp);
hdr->ivalue = pj_strtoul(&tmp);
parse_hdr_end(scanner);
}
/* Parse Accept header. */
-static pjsip_accept_hdr* parse_hdr_accept( pj_scanner *scanner,
- pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_accept(pjsip_parse_ctx *ctx)
{
- pjsip_accept_hdr *accept = pjsip_accept_hdr_create(pool);
- parse_generic_array_hdr(accept, scanner);
- return accept;
+ pjsip_accept_hdr *accept = pjsip_accept_hdr_create(ctx->pool);
+ parse_generic_array_hdr(accept, ctx->scanner);
+ return (pjsip_hdr*)accept;
}
/* Parse Allow header. */
-static pjsip_allow_hdr* parse_hdr_allow( pj_scanner *scanner,
- pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_allow(pjsip_parse_ctx *ctx)
{
- pjsip_allow_hdr *allow = pjsip_allow_hdr_create(pool);
- parse_generic_array_hdr(allow, scanner);
- return allow;
+ pjsip_allow_hdr *allow = pjsip_allow_hdr_create(ctx->pool);
+ parse_generic_array_hdr(allow, ctx->scanner);
+ return (pjsip_hdr*)allow;
}
/* Parse Call-ID header. */
-static pjsip_cid_hdr* parse_hdr_call_id( pj_scanner *scanner,
- pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_call_id(pjsip_parse_ctx *ctx)
{
- pjsip_cid_hdr *hdr = pjsip_cid_hdr_create(pool);
- pj_scan_get_until( scanner, pjsip_NEWLINE_OR_EOF_SPEC, &hdr->id);
- parse_hdr_end(scanner);
- return hdr;
+ pjsip_cid_hdr *hdr = pjsip_cid_hdr_create(ctx->pool);
+ pj_scan_get_until( ctx->scanner, &pjsip_NEWLINE_OR_EOF_SPEC, &hdr->id);
+ parse_hdr_end(ctx->scanner);
+
+ if (ctx->rdata)
+ ctx->rdata->call_id = hdr->id;
+
+ return (pjsip_hdr*)hdr;
}
/* Parse and interpret Contact param. */
@@ -1136,7 +1252,7 @@ static void int_parse_contact_param( pjsip_contact_hdr *hdr,
pj_scanner *scanner,
pj_pool_t *pool)
{
- while ( *scanner->current == ';' ) {
+ while ( *scanner->curptr == ';' ) {
pj_str_t pname, pvalue;
int_parse_param( scanner, &pname, &pvalue);
@@ -1159,103 +1275,114 @@ static void int_parse_contact_param( pjsip_contact_hdr *hdr,
}
/* Parse Contact header. */
-PJ_DEF(pjsip_contact_hdr*) parse_hdr_contact( pj_scanner *scanner,
- pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_contact( pjsip_parse_ctx *ctx )
{
- pjsip_contact_hdr *first = NULL;
+ pjsip_contact_hdr *first = NULL;
+ pj_scanner *scanner = ctx->scanner;
do {
- pjsip_contact_hdr *hdr = pjsip_contact_hdr_create(pool);
+ pjsip_contact_hdr *hdr = pjsip_contact_hdr_create(ctx->pool);
if (first == NULL)
first = hdr;
else
pj_list_insert_before(first, hdr);
- if (*scanner->current == '*') {
+ if (*scanner->curptr == '*') {
pj_scan_get_char(scanner);
hdr->star = 1;
} else {
hdr->star = 0;
- hdr->uri = int_parse_uri_or_name_addr(scanner, pool, PJSIP_PARSE_URI_AS_NAMEADDR);
+ hdr->uri = int_parse_uri_or_name_addr(scanner, ctx->pool,
+ PJSIP_PARSE_URI_AS_NAMEADDR);
- int_parse_contact_param(hdr, scanner, pool);
+ int_parse_contact_param(hdr, scanner, ctx->pool);
}
- if (*scanner->current != ',')
+ if (*scanner->curptr != ',')
break;
pj_scan_get_char(scanner);
} while (1);
- parse_hdr_end(scanner);
- return first;
+ parse_hdr_end(scanner);
+
+ return (pjsip_hdr*)first;
}
/* Parse Content-Length header. */
-PJ_DEF(pjsip_clen_hdr*) parse_hdr_content_length( pj_scanner *scanner,
- pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_content_len( pjsip_parse_ctx *ctx )
{
pj_str_t digit;
pjsip_clen_hdr *hdr;
- hdr = pjsip_clen_hdr_create(pool);
- pj_scan_get(scanner, pjsip_DIGIT_SPEC, &digit);
+ hdr = pjsip_clen_hdr_create(ctx->pool);
+ pj_scan_get(ctx->scanner, &pjsip_DIGIT_SPEC, &digit);
hdr->len = pj_strtoul(&digit);
- parse_hdr_end(scanner);
- return hdr;
+ parse_hdr_end(ctx->scanner);
+
+ if (ctx->rdata)
+ ctx->rdata->clen = hdr;
+
+ return (pjsip_hdr*)hdr;
}
/* Parse Content-Type header. */
-PJ_DEF(pjsip_ctype_hdr*) parse_hdr_content_type( pj_scanner *scanner,
- pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_content_type( pjsip_parse_ctx *ctx )
{
pjsip_ctype_hdr *hdr;
+ pj_scanner *scanner = ctx->scanner;
- hdr = pjsip_ctype_hdr_create(pool);
+ hdr = pjsip_ctype_hdr_create(ctx->pool);
/* Parse media type and subtype. */
- pj_scan_get(scanner, pjsip_TOKEN_SPEC, &hdr->media.type);
+ pj_scan_get(scanner, &pjsip_TOKEN_SPEC, &hdr->media.type);
pj_scan_get_char(scanner);
- pj_scan_get(scanner, pjsip_TOKEN_SPEC, &hdr->media.subtype);
+ pj_scan_get(scanner, &pjsip_TOKEN_SPEC, &hdr->media.subtype);
/* Parse media parameters */
- while (*scanner->current == ';') {
+ while (*scanner->curptr == ';') {
pj_str_t pname, pvalue;
int_parse_param(scanner, &pname, &pvalue);
- concat_param(&hdr->media.param, pool, &pname, &pvalue);
+ concat_param(&hdr->media.param, ctx->pool, &pname, &pvalue);
}
- parse_hdr_end(scanner);
- return hdr;
+ parse_hdr_end(ctx->scanner);
+
+ if (ctx->rdata)
+ ctx->rdata->ctype = hdr;
+
+ return (pjsip_hdr*)hdr;
}
/* Parse CSeq header. */
-PJ_DEF(pjsip_cseq_hdr*) parse_hdr_cseq( pj_scanner *scanner,
- pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_cseq( pjsip_parse_ctx *ctx )
{
pj_str_t cseq, method;
pjsip_cseq_hdr *hdr;
- hdr = pjsip_cseq_hdr_create(pool);
- pj_scan_get( scanner, pjsip_DIGIT_SPEC, &cseq);
+ hdr = pjsip_cseq_hdr_create(ctx->pool);
+ pj_scan_get( ctx->scanner, &pjsip_DIGIT_SPEC, &cseq);
hdr->cseq = pj_strtoul(&cseq);
- pj_scan_get( scanner, pjsip_TOKEN_SPEC, &method);
+ pj_scan_get( ctx->scanner, &pjsip_TOKEN_SPEC, &method);
pjsip_method_init_np(&hdr->method, &method);
- parse_hdr_end( scanner );
- return hdr;
+ parse_hdr_end( ctx->scanner );
+
+ if (ctx->rdata)
+ ctx->rdata->cseq = hdr;
+
+ return (pjsip_hdr*)hdr;
}
/* Parse Expires header. */
-static pjsip_expires_hdr* parse_hdr_expires(pj_scanner *scanner,
- pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_expires(pjsip_parse_ctx *ctx)
{
- pjsip_expires_hdr *hdr = pjsip_expires_hdr_create(pool);
- parse_generic_int_hdr(hdr, scanner);
- return hdr;
+ pjsip_expires_hdr *hdr = pjsip_expires_hdr_create(ctx->pool);
+ parse_generic_int_hdr(hdr, ctx->scanner);
+ return (pjsip_hdr*)hdr;
}
/* Parse From: or To: header. */
@@ -1267,7 +1394,7 @@ static void parse_hdr_fromto( pj_scanner *scanner,
PJSIP_PARSE_URI_AS_NAMEADDR |
PJSIP_PARSE_URI_IN_FROM_TO_HDR);
- while ( *scanner->current == ';' ) {
+ while ( *scanner->curptr == ';' ) {
pj_str_t pname, pvalue;
int_parse_param( scanner, &pname, &pvalue);
@@ -1284,66 +1411,71 @@ static void parse_hdr_fromto( pj_scanner *scanner,
}
/* Parse From: header. */
-PJ_DEF(pjsip_from_hdr*) parse_hdr_from( pj_scanner *scanner,
- pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_from( pjsip_parse_ctx *ctx )
{
- pjsip_from_hdr *hdr = pjsip_from_hdr_create(pool);
- parse_hdr_fromto(scanner, pool, hdr);
- return hdr;
+ pjsip_from_hdr *hdr = pjsip_from_hdr_create(ctx->pool);
+ parse_hdr_fromto(ctx->scanner, ctx->pool, hdr);
+ if (ctx->rdata)
+ ctx->rdata->from = hdr;
+
+ return (pjsip_hdr*)hdr;
}
/* Parse Require: header. */
-static pjsip_require_hdr* parse_hdr_require( pj_scanner *scanner,
- pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_require( pjsip_parse_ctx *ctx )
{
- pjsip_require_hdr *hdr = pjsip_require_hdr_create(pool);
- parse_generic_array_hdr(hdr, scanner);
- return hdr;
+ pjsip_require_hdr *hdr = pjsip_require_hdr_create(ctx->pool);
+ parse_generic_array_hdr(hdr, ctx->scanner);
+
+ if (ctx->rdata && ctx->rdata->require == NULL)
+ ctx->rdata->require = hdr;
+
+ return (pjsip_hdr*)hdr;
}
/* Parse Retry-After: header. */
-static pjsip_retry_after_hdr* parse_hdr_retry_after(pj_scanner *scanner,
- pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_retry_after(pjsip_parse_ctx *ctx)
{
pjsip_retry_after_hdr *hdr;
- hdr = pjsip_retry_after_hdr_create(pool);
- parse_generic_int_hdr(hdr, scanner);
- return hdr;
+ hdr = pjsip_retry_after_hdr_create(ctx->pool);
+ parse_generic_int_hdr(hdr, ctx->scanner);
+ return (pjsip_hdr*)hdr;
}
/* Parse Supported: header. */
-static pjsip_supported_hdr* parse_hdr_supported(pj_scanner *scanner,
- pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_supported(pjsip_parse_ctx *ctx)
{
- pjsip_supported_hdr *hdr = pjsip_supported_hdr_create(pool);
- parse_generic_array_hdr(hdr, scanner);
- return hdr;
+ pjsip_supported_hdr *hdr = pjsip_supported_hdr_create(ctx->pool);
+ parse_generic_array_hdr(hdr, ctx->scanner);
+ return (pjsip_hdr*)hdr;
}
/* Parse To: header. */
-PJ_DEF(pjsip_to_hdr*) parse_hdr_to( pj_scanner *scanner,
- pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_to( pjsip_parse_ctx *ctx )
{
- pjsip_to_hdr *hdr = pjsip_to_hdr_create(pool);
- parse_hdr_fromto(scanner, pool, hdr);
- return hdr;
+ pjsip_to_hdr *hdr = pjsip_to_hdr_create(ctx->pool);
+ parse_hdr_fromto(ctx->scanner, ctx->pool, hdr);
+
+ if (ctx->rdata)
+ ctx->rdata->to = hdr;
+
+ return (pjsip_hdr*)hdr;
}
/* Parse Unsupported: header. */
-static pjsip_unsupported_hdr* parse_hdr_unsupported(pj_scanner *scanner,
- pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_unsupported(pjsip_parse_ctx *ctx)
{
- pjsip_unsupported_hdr *hdr = pjsip_unsupported_hdr_create(pool);
- parse_generic_array_hdr(hdr, scanner);
- return hdr;
+ pjsip_unsupported_hdr *hdr = pjsip_unsupported_hdr_create(ctx->pool);
+ parse_generic_array_hdr(hdr, ctx->scanner);
+ return (pjsip_hdr*)hdr;
}
/* Parse and interpret Via parameters. */
static void int_parse_via_param( pjsip_via_hdr *hdr, pj_scanner *scanner,
pj_pool_t *pool)
{
- while ( *scanner->current == ';' ) {
+ while ( *scanner->curptr == ';' ) {
pj_str_t pname, pvalue;
int_parse_param( scanner, &pname, &pvalue);
@@ -1373,23 +1505,25 @@ static void int_parse_via_param( pjsip_via_hdr *hdr, pj_scanner *scanner,
}
/* Parse Max-Forwards header. */
-static pjsip_max_forwards_hdr* parse_hdr_max_forwards( pj_scanner *scanner,
- pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_max_forwards( pjsip_parse_ctx *ctx )
{
pjsip_max_forwards_hdr *hdr;
- hdr = pjsip_max_forwards_hdr_create(pool);
- parse_generic_int_hdr(hdr, scanner);
- return hdr;
+ hdr = pjsip_max_forwards_hdr_create(ctx->pool);
+ parse_generic_int_hdr(hdr, ctx->scanner);
+
+ if (ctx->rdata)
+ ctx->rdata->max_fwd = hdr;
+
+ return (pjsip_hdr*)hdr;
}
/* Parse Min-Expires header. */
-static pjsip_min_expires_hdr* parse_hdr_min_expires(pj_scanner *scanner,
- pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_min_expires(pjsip_parse_ctx *ctx)
{
pjsip_min_expires_hdr *hdr;
- hdr = pjsip_min_expires_hdr_create(pool);
- parse_generic_int_hdr(hdr, scanner);
- return hdr;
+ hdr = pjsip_min_expires_hdr_create(ctx->pool);
+ parse_generic_int_hdr(hdr, ctx->scanner);
+ return (pjsip_hdr*)hdr;
}
@@ -1400,65 +1534,76 @@ static void parse_hdr_rr_route( pj_scanner *scanner, pj_pool_t *pool,
pjsip_name_addr *temp=int_parse_name_addr(scanner, pool);
pj_memcpy(&hdr->name_addr, temp, sizeof(*temp));
- if (*scanner->current == ';') {
- pj_scan_get_until(scanner, pjsip_NEWLINE_OR_EOF_SPEC, &hdr->other_param);
+ if (*scanner->curptr == ';') {
+ pj_scan_get_until(scanner, &pjsip_NEWLINE_OR_EOF_SPEC,
+ &hdr->other_param);
}
}
/* Parse Record-Route header. */
-PJ_DEF(pjsip_rr_hdr*) parse_hdr_rr( pj_scanner *scanner, pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_rr( pjsip_parse_ctx *ctx)
{
- pjsip_rr_hdr *first = NULL;
+ pjsip_rr_hdr *first = NULL;
+ pj_scanner *scanner = ctx->scanner;
do {
- pjsip_rr_hdr *hdr = pjsip_rr_hdr_create(pool);
+ pjsip_rr_hdr *hdr = pjsip_rr_hdr_create(ctx->pool);
if (!first) {
first = hdr;
} else {
pj_list_insert_before(first, hdr);
}
- parse_hdr_rr_route(scanner, pool, hdr);
- if (*scanner->current == ',') {
+ parse_hdr_rr_route(scanner, ctx->pool, hdr);
+ if (*scanner->curptr == ',') {
pj_scan_get_char(scanner);
} else {
break;
}
} while (1);
- parse_hdr_end(scanner);
- return first;
+ parse_hdr_end(scanner);
+
+ if (ctx->rdata && ctx->rdata->record_route==NULL)
+ ctx->rdata->record_route = first;
+
+ return (pjsip_hdr*)first;
}
/* Parse Route: header. */
-PJ_DEF(pjsip_route_hdr*) parse_hdr_route( pj_scanner *scanner,
- pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_route( pjsip_parse_ctx *ctx )
{
- pjsip_route_hdr *first = NULL;
+ pjsip_route_hdr *first = NULL;
+ pj_scanner *scanner = ctx->scanner;
do {
- pjsip_route_hdr *hdr = pjsip_route_hdr_create(pool);
+ pjsip_route_hdr *hdr = pjsip_route_hdr_create(ctx->pool);
if (!first) {
first = hdr;
} else {
pj_list_insert_before(first, hdr);
}
- parse_hdr_rr_route(scanner, pool, hdr);
- if (*scanner->current == ',') {
+ parse_hdr_rr_route(scanner, ctx->pool, hdr);
+ if (*scanner->curptr == ',') {
pj_scan_get_char(scanner);
} else {
break;
}
} while (1);
- parse_hdr_end(scanner);
- return first;
+ parse_hdr_end(scanner);
+
+ if (ctx->rdata && ctx->rdata->route==NULL)
+ ctx->rdata->route = first;
+
+ return (pjsip_hdr*)first;
}
/* Parse Via: header. */
-PJ_DEF(pjsip_via_hdr*) parse_hdr_via( pj_scanner *scanner, pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_via( pjsip_parse_ctx *ctx )
{
- pjsip_via_hdr *first = NULL;
+ pjsip_via_hdr *first = NULL;
+ pj_scanner *scanner = ctx->scanner;
do {
- pjsip_via_hdr *hdr = pjsip_via_hdr_create(pool);
+ pjsip_via_hdr *hdr = pjsip_via_hdr_create(ctx->pool);
if (!first)
first = hdr;
else
@@ -1469,46 +1614,49 @@ PJ_DEF(pjsip_via_hdr*) parse_hdr_via( pj_scanner *scanner, pj_pool_t *pool)
pj_scan_advance_n( scanner, 8, 1);
- pj_scan_get( scanner, pjsip_TOKEN_SPEC, &hdr->transport);
- pj_scan_get( scanner, pjsip_HOST_SPEC, &hdr->sent_by.host);
+ pj_scan_get( scanner, &pjsip_TOKEN_SPEC, &hdr->transport);
+ pj_scan_get( scanner, &pjsip_HOST_SPEC, &hdr->sent_by.host);
- if (*scanner->current==':') {
+ if (*scanner->curptr==':') {
pj_str_t digit;
pj_scan_get_char(scanner);
- pj_scan_get(scanner, pjsip_DIGIT_SPEC, &digit);
+ pj_scan_get(scanner, &pjsip_DIGIT_SPEC, &digit);
hdr->sent_by.port = pj_strtoul(&digit);
} else {
hdr->sent_by.port = 5060;
}
- int_parse_via_param(hdr, scanner, pool);
+ int_parse_via_param(hdr, scanner, ctx->pool);
- if (*scanner->current == '(') {
+ if (*scanner->curptr == '(') {
pj_scan_get_char(scanner);
pj_scan_get_until_ch( scanner, ')', &hdr->comment);
pj_scan_get_char( scanner );
}
- if (*scanner->current != ',')
+ if (*scanner->curptr != ',')
break;
pj_scan_get_char(scanner);
} while (1);
- parse_hdr_end(scanner);
- return first;
+ parse_hdr_end(scanner);
+
+ if (ctx->rdata && ctx->rdata->via == NULL)
+ ctx->rdata->via = first;
+
+ return (pjsip_hdr*)first;
}
/* Parse generic header. */
-PJ_DEF(pjsip_generic_string_hdr*) parse_hdr_generic_string( pj_scanner *scanner,
- pj_pool_t *pool)
+static pjsip_hdr* parse_hdr_generic_string( pjsip_parse_ctx *ctx )
{
pjsip_generic_string_hdr *hdr;
- hdr = pjsip_generic_string_hdr_create(pool, NULL);
- parse_generic_string_hdr(hdr, scanner);
- return hdr;
+ hdr = pjsip_generic_string_hdr_create(ctx->pool, NULL);
+ parse_generic_string_hdr(hdr, ctx->scanner);
+ return (pjsip_hdr*)hdr;
}
@@ -1517,23 +1665,28 @@ PJ_DEF(void*) pjsip_parse_hdr( pj_pool_t *pool, const pj_str_t *hname,
char *buf, pj_size_t size, int *parsed_len )
{
pj_scanner scanner;
- pjsip_hdr *hdr = NULL;
+ pjsip_hdr *hdr = NULL;
+ pjsip_parse_ctx context;
PJ_USE_EXCEPTION;
init_sip_parser();
- pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER, &on_syntax_error);
+ pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER,
+ &on_syntax_error);
+
+ context.scanner = &scanner;
+ context.pool = pool;
+ context.rdata = NULL;
PJ_TRY {
pjsip_parse_hdr_func *handler = find_handler(hname);
if (handler) {
- hdr = (*handler)(&scanner, pool);
+ hdr = (*handler)(&context);
} else {
- pjsip_generic_string_hdr *ghdr = parse_hdr_generic_string(&scanner, pool);
- ghdr->type = PJSIP_H_OTHER;
- pj_strdup(pool, &ghdr->name, hname);
- ghdr->sname = ghdr->name;
- hdr = (pjsip_hdr*)ghdr;
+ hdr = parse_hdr_generic_string(&context);
+ hdr->type = PJSIP_H_OTHER;
+ pj_strdup(pool, &hdr->name, hname);
+ hdr->sname = hdr->name;
}
}
@@ -1543,7 +1696,7 @@ PJ_DEF(void*) pjsip_parse_hdr( pj_pool_t *pool, const pj_str_t *hname,
PJ_END
if (parsed_len) {
- *parsed_len = (scanner.current - scanner.begin);
+ *parsed_len = (scanner.curptr - scanner.begin);
}
pj_scan_fini(&scanner);
diff --git a/pjsip/src/pjsip/sip_resolve.c b/pjsip/src/pjsip/sip_resolve.c
index 1267b8b4..b199eaba 100644
--- a/pjsip/src/pjsip/sip_resolve.c
+++ b/pjsip/src/pjsip/sip_resolve.c
@@ -1,11 +1,11 @@
/* $Id$
- *
*/
#include <pjsip/sip_resolve.h>
#include <pjsip/sip_transport.h>
#include <pj/pool.h>
-#include <ctype.h>
+#include <pj/ctype.h>
+#include <pj/assert.h>
struct pjsip_resolver_t
{
@@ -21,7 +21,7 @@ PJ_DEF(pjsip_resolver_t*) pjsip_resolver_create(pj_pool_t *pool)
PJ_DEF(void) pjsip_resolver_destroy(pjsip_resolver_t *resolver)
{
- PJ_UNUSED_ARG(resolver)
+ PJ_UNUSED_ARG(resolver);
}
static int is_str_ip(const pj_str_t *host)
@@ -30,7 +30,7 @@ static int is_str_ip(const pj_str_t *host)
const char *end = ((const char*)host->ptr) + host->slen;
while (p != end) {
- if (isdigit(*p) || *p=='.') {
+ if (pj_isdigit(*p) || *p=='.') {
++p;
} else {
return 0;
@@ -50,8 +50,8 @@ PJ_DEF(void) pjsip_resolve( pjsip_resolver_t *resolver,
int is_ip_addr;
pjsip_transport_type_e type = target->type;
- PJ_UNUSED_ARG(resolver)
- PJ_UNUSED_ARG(pool)
+ PJ_UNUSED_ARG(resolver);
+ PJ_UNUSED_ARG(pool);
/* We only do synchronous resolving at this moment. */
PJ_TODO(SUPPORT_RFC3263_SERVER_RESOLUTION)
@@ -94,9 +94,11 @@ PJ_DEF(void) pjsip_resolve( pjsip_resolver_t *resolver,
/* Resolve hostname. */
if (!is_ip_addr) {
- status = pj_sockaddr_init(&svr_addr.entry[0].addr, &target->host, target->port);
+ status = pj_sockaddr_in_init(&svr_addr.entry[0].addr, &target->host,
+ (pj_uint16_t)target->port);
} else {
- status = pj_sockaddr_init(&svr_addr.entry[0].addr, &target->host, target->port);
+ status = pj_sockaddr_in_init(&svr_addr.entry[0].addr, &target->host,
+ (pj_uint16_t)target->port);
pj_assert(status == PJ_SUCCESS);
}
diff --git a/pjsip/src/pjsip/sip_transaction.c b/pjsip/src/pjsip/sip_transaction.c
index cdb20626..ebc0a803 100644
--- a/pjsip/src/pjsip/sip_transaction.c
+++ b/pjsip/src/pjsip/sip_transaction.c
@@ -1,5 +1,4 @@
/* $Id$
- *
*/
#include <pjsip/sip_transaction.h>
#include <pjsip/sip_transport.h>
@@ -7,14 +6,16 @@
#include <pjsip/sip_misc.h>
#include <pjsip/sip_event.h>
#include <pjsip/sip_endpoint.h>
+#include <pjsip/sip_errno.h>
#include <pj/log.h>
#include <pj/string.h>
#include <pj/os.h>
#include <pj/guid.h>
#include <pj/pool.h>
+#include <pj/assert.h>
/* Thread Local Storage ID for transaction lock (initialized by endpoint) */
-int pjsip_tsx_lock_tls_id;
+long pjsip_tsx_lock_tls_id;
/* State names */
static const char *state_str[] =
@@ -43,10 +44,14 @@ typedef struct tsx_lock_data {
int is_alive;
} tsx_lock_data;
+
/* Timer timeout value constants */
-static const pj_time_val t1_timer_val = { PJSIP_T1_TIMEOUT/1000, PJSIP_T1_TIMEOUT%1000 };
-static const pj_time_val t4_timer_val = { PJSIP_T4_TIMEOUT/1000, PJSIP_T4_TIMEOUT%1000 };
-static const pj_time_val td_timer_val = { PJSIP_TD_TIMEOUT/1000, PJSIP_TD_TIMEOUT%1000 };
+static const pj_time_val t1_timer_val = { PJSIP_T1_TIMEOUT/1000,
+ PJSIP_T1_TIMEOUT%1000 };
+static const pj_time_val t4_timer_val = { PJSIP_T4_TIMEOUT/1000,
+ PJSIP_T4_TIMEOUT%1000 };
+static const pj_time_val td_timer_val = { PJSIP_TD_TIMEOUT/1000,
+ PJSIP_TD_TIMEOUT%1000 };
static const pj_time_val timeout_timer_val = { (64*PJSIP_T1_TIMEOUT)/1000,
(64*PJSIP_T1_TIMEOUT)%1000 };
@@ -58,35 +63,39 @@ enum Transaction_Timer_Id
};
/* Function Prototypes */
-static int pjsip_tsx_on_state_null( pjsip_transaction *tsx,
- pjsip_event *event);
-static int pjsip_tsx_on_state_calling( pjsip_transaction *tsx,
- pjsip_event *event);
-static int pjsip_tsx_on_state_trying( pjsip_transaction *tsx,
- pjsip_event *event);
-static int pjsip_tsx_on_state_proceeding_uas( pjsip_transaction *tsx,
- pjsip_event *event);
-static int pjsip_tsx_on_state_proceeding_uac( pjsip_transaction *tsx,
- pjsip_event *event);
-static int pjsip_tsx_on_state_completed_uas( pjsip_transaction *tsx,
- pjsip_event *event);
-static int pjsip_tsx_on_state_completed_uac( pjsip_transaction *tsx,
- pjsip_event *event);
-static int pjsip_tsx_on_state_confirmed( pjsip_transaction *tsx,
- pjsip_event *event);
-static int pjsip_tsx_on_state_terminated( pjsip_transaction *tsx,
- pjsip_event *event);
-static int pjsip_tsx_on_state_destroyed( pjsip_transaction *tsx,
- pjsip_event *event);
-static void tsx_timer_callback( pj_timer_heap_t *theap,
- pj_timer_entry *entry);
-static int tsx_send_msg( pjsip_transaction *tsx, pjsip_tx_data *tdata);
-static void lock_tsx( pjsip_transaction *tsx, struct tsx_lock_data *lck );
-static pj_status_t unlock_tsx( pjsip_transaction *tsx, struct tsx_lock_data *lck );
+static pj_status_t pjsip_tsx_on_state_null( pjsip_transaction *tsx,
+ pjsip_event *event);
+static pj_status_t pjsip_tsx_on_state_calling( pjsip_transaction *tsx,
+ pjsip_event *event);
+static pj_status_t pjsip_tsx_on_state_trying( pjsip_transaction *tsx,
+ pjsip_event *event);
+static pj_status_t pjsip_tsx_on_state_proceeding_uas( pjsip_transaction *tsx,
+ pjsip_event *event);
+static pj_status_t pjsip_tsx_on_state_proceeding_uac( pjsip_transaction *tsx,
+ pjsip_event *event);
+static pj_status_t pjsip_tsx_on_state_completed_uas( pjsip_transaction *tsx,
+ pjsip_event *event);
+static pj_status_t pjsip_tsx_on_state_completed_uac( pjsip_transaction *tsx,
+ pjsip_event *event);
+static pj_status_t pjsip_tsx_on_state_confirmed(pjsip_transaction *tsx,
+ pjsip_event *event);
+static pj_status_t pjsip_tsx_on_state_terminated(pjsip_transaction *tsx,
+ pjsip_event *event);
+static pj_status_t pjsip_tsx_on_state_destroyed(pjsip_transaction *tsx,
+ pjsip_event *event);
+
+static void tsx_timer_callback( pj_timer_heap_t *theap,
+ pj_timer_entry *entry);
+static int tsx_send_msg( pjsip_transaction *tsx,
+ pjsip_tx_data *tdata);
+static void lock_tsx( pjsip_transaction *tsx, struct
+ tsx_lock_data *lck );
+static pj_status_t unlock_tsx( pjsip_transaction *tsx,
+ struct tsx_lock_data *lck );
/* State handlers for UAC, indexed by state */
-static int (*tsx_state_handler_uac[PJSIP_TSX_STATE_MAX])(pjsip_transaction *tsx,
- pjsip_event *event ) =
+static int (*tsx_state_handler_uac[PJSIP_TSX_STATE_MAX])(pjsip_transaction *,
+ pjsip_event *) =
{
&pjsip_tsx_on_state_null,
&pjsip_tsx_on_state_calling,
@@ -99,8 +108,8 @@ static int (*tsx_state_handler_uac[PJSIP_TSX_STATE_MAX])(pjsip_transaction *tsx
};
/* State handlers for UAS */
-static int (*tsx_state_handler_uas[PJSIP_TSX_STATE_MAX])(pjsip_transaction *tsx,
- pjsip_event *event ) =
+static int (*tsx_state_handler_uas[PJSIP_TSX_STATE_MAX])(pjsip_transaction *,
+ pjsip_event *) =
{
&pjsip_tsx_on_state_null,
&pjsip_tsx_on_state_calling,
@@ -153,11 +162,11 @@ PJ_DEF(const char *) pjsip_role_name(pjsip_role_e role)
* The transaction key is constructed from the common components of above
* components. Additional comparison is needed to fully match a transaction.
*/
-void create_tsx_key_2543( pj_pool_t *pool,
- pj_str_t *str,
- pjsip_role_e role,
- const pjsip_method *method,
- const pjsip_rx_data *rdata )
+static pj_status_t create_tsx_key_2543( pj_pool_t *pool,
+ pj_str_t *str,
+ pjsip_role_e role,
+ const pjsip_method *method,
+ const pjsip_rx_data *rdata )
{
#define SEPARATOR '$'
char *key, *p, *end;
@@ -166,17 +175,22 @@ void create_tsx_key_2543( pj_pool_t *pool,
pjsip_uri *req_uri;
pj_str_t *host;
+ PJ_ASSERT_RETURN(pool && str && method && rdata, PJ_EINVAL);
+ PJ_ASSERT_RETURN(rdata->msg, PJ_EINVAL);
+ PJ_ASSERT_RETURN(rdata->via, PJSIP_EMISSINGHDR);
+ PJ_ASSERT_RETURN(rdata->cseq, PJSIP_EMISSINGHDR);
+ PJ_ASSERT_RETURN(rdata->from, PJSIP_EMISSINGHDR);
+
host = &rdata->via->sent_by.host;
req_uri = (pjsip_uri*)rdata->msg->line.req.uri;
/* Calculate length required. */
- len_required = PJSIP_MAX_URL_SIZE + /* URI */
- 9 + /* CSeq number */
- rdata->from_tag.slen + /* From tag. */
+ len_required = 9 + /* CSeq number */
+ rdata->from->tag.slen + /* From tag. */
rdata->call_id.slen + /* Call-ID */
host->slen + /* Via host. */
9 + /* Via port. */
- 32; /* Separator+Allowance. */
+ 16; /* Separator+Allowance. */
key = p = pj_pool_alloc(pool, len_required);
end = p + len_required;
@@ -223,9 +237,6 @@ void create_tsx_key_2543( pj_pool_t *pool,
* only used to match request retransmission, and we expect that the
* request retransmissions will contain the same port.
*/
- if ((end-p) < host->slen + 12) {
- goto on_error;
- }
pj_memcpy(p, host->ptr, host->slen);
p += host->slen;
*p++ = ':';
@@ -240,27 +251,22 @@ void create_tsx_key_2543( pj_pool_t *pool,
str->ptr = key;
str->slen = p-key;
- return;
-
-on_error:
- PJ_LOG(2,("tsx........", "Not enough buffer (%d) for transaction key",
- len_required));
- pj_assert(0);
- str->ptr = NULL;
- str->slen = 0;
+ return PJ_SUCCESS;
}
/*
* Create transaction key for RFC3161 compliant system.
*/
-void create_tsx_key_3261( pj_pool_t *pool,
- pj_str_t *key,
- pjsip_role_e role,
- const pjsip_method *method,
- const pj_str_t *branch )
+static pj_status_t create_tsx_key_3261( pj_pool_t *pool,
+ pj_str_t *key,
+ pjsip_role_e role,
+ const pjsip_method *method,
+ const pj_str_t *branch)
{
char *p;
+ PJ_ASSERT_RETURN(pool && key && method && branch, PJ_EINVAL);
+
p = key->ptr = pj_pool_alloc(pool, branch->slen + method->name.slen + 4 );
/* Add role. */
@@ -280,18 +286,22 @@ void create_tsx_key_3261( pj_pool_t *pool,
/* Set length */
key->slen = p - key->ptr;
+
+ return PJ_SUCCESS;
}
/*
* Create key from the incoming data, to be used to search the transaction
* in the transaction hash table.
*/
-PJ_DEF(void) pjsip_tsx_create_key( pj_pool_t *pool, pj_str_t *key,
- pjsip_role_e role,
- const pjsip_method *method,
- const pjsip_rx_data *rdata )
+PJ_DEF(pj_status_t) pjsip_tsx_create_key( pj_pool_t *pool, pj_str_t *key,
+ pjsip_role_e role,
+ const pjsip_method *method,
+ const pjsip_rx_data *rdata)
{
- pj_str_t rfc3261_branch = {PJSIP_RFC3261_BRANCH_ID, PJSIP_RFC3261_BRANCH_LEN};
+ pj_str_t rfc3261_branch = {PJSIP_RFC3261_BRANCH_ID,
+ PJSIP_RFC3261_BRANCH_LEN};
+
/* Get the branch parameter in the top-most Via.
* If branch parameter is started with "z9hG4bK", then the message was
@@ -300,17 +310,18 @@ PJ_DEF(void) pjsip_tsx_create_key( pj_pool_t *pool, pj_str_t *key,
*/
const pj_str_t *branch = &rdata->via->branch_param;
- if (pj_strncmp(branch, &rfc3261_branch, PJSIP_RFC3261_BRANCH_LEN) == 0) {
+ if (pj_strncmp(branch,&rfc3261_branch,PJSIP_RFC3261_BRANCH_LEN)==0) {
/* Create transaction key. */
- create_tsx_key_3261(pool, key, role, method, branch);
+ return create_tsx_key_3261(pool, key, role, method, branch);
} else {
- /* Create the key for the message. This key will be matched up with the
- * transaction key. For RFC2563 transactions, the transaction key
- * was created by the same function, so it will match the message.
+ /* Create the key for the message. This key will be matched up
+ * with the transaction key. For RFC2563 transactions, the
+ * transaction key was created by the same function, so it will
+ * match the message.
*/
- create_tsx_key_2543( pool, key, role, method, rdata );
+ return create_tsx_key_2543( pool, key, role, method, rdata );
}
}
@@ -318,10 +329,12 @@ PJ_DEF(void) pjsip_tsx_create_key( pj_pool_t *pool, pj_str_t *key,
/*
* Create new transaction.
*/
-PJ_DEF(pjsip_transaction *) pjsip_tsx_create(pj_pool_t *pool,
- pjsip_endpoint *endpt)
+pj_status_t pjsip_tsx_create( pj_pool_t *pool,
+ pjsip_endpoint *endpt,
+ pjsip_transaction **p_tsx)
{
pjsip_transaction *tsx;
+ pj_status_t status;
tsx = pj_pool_calloc(pool, 1, sizeof(pjsip_transaction));
@@ -335,13 +348,14 @@ PJ_DEF(pjsip_transaction *) pjsip_tsx_create(pj_pool_t *pool,
tsx->timeout_timer._timer_id = -1;
tsx->timeout_timer.user_data = tsx;
tsx->timeout_timer.cb = &tsx_timer_callback;
- sprintf(tsx->obj_name, "tsx%p", tsx);
- tsx->mutex = pj_mutex_create(pool, "mtsx%p", 0);
- if (!tsx->mutex) {
- return NULL;
+ pj_sprintf(tsx->obj_name, "tsx%p", tsx);
+ status = pj_mutex_create_recursive(pool, "mtsx%p", &tsx->mutex);
+ if (status != PJ_SUCCESS) {
+ return status;
}
- return tsx;
+ *p_tsx = tsx;
+ return PJ_SUCCESS;
}
/*
@@ -352,7 +366,8 @@ static void lock_tsx(pjsip_transaction *tsx, struct tsx_lock_data *lck)
struct tsx_lock_data *prev_data;
pj_mutex_lock(tsx->mutex);
- prev_data = (struct tsx_lock_data *) pj_thread_local_get(pjsip_tsx_lock_tls_id);
+ prev_data = (struct tsx_lock_data *)
+ pj_thread_local_get(pjsip_tsx_lock_tls_id);
lck->prev = prev_data;
lck->tsx = tsx;
lck->is_alive = 1;
@@ -367,7 +382,8 @@ static void lock_tsx(pjsip_transaction *tsx, struct tsx_lock_data *lck)
* because when transaction is destroyed the is_alive flag for the transaction
* will be set to zero.
*/
-static pj_status_t unlock_tsx(pjsip_transaction *tsx, struct tsx_lock_data *lck)
+static pj_status_t unlock_tsx( pjsip_transaction *tsx,
+ struct tsx_lock_data *lck)
{
pj_assert( (void*)pj_thread_local_get(pjsip_tsx_lock_tls_id) == lck);
pj_assert( lck->tsx == tsx );
@@ -375,7 +391,7 @@ static pj_status_t unlock_tsx(pjsip_transaction *tsx, struct tsx_lock_data *lck)
if (lck->is_alive)
pj_mutex_unlock(tsx->mutex);
- return lck->is_alive ? 0 : -1;
+ return lck->is_alive ? PJ_SUCCESS : PJSIP_ETSXDESTROYED;
}
/*
@@ -383,13 +399,14 @@ static pj_status_t unlock_tsx(pjsip_transaction *tsx, struct tsx_lock_data *lck)
*/
static void tsx_set_state( pjsip_transaction *tsx,
pjsip_tsx_state_e state,
- const pjsip_event *event )
+ pjsip_event_id_e event_src_type,
+ void *event_src )
{
pjsip_event e;
- PJ_LOG(4, (tsx->obj_name, "STATE %s-->%s, ev=%s (src:%s)",
- state_str[tsx->state], state_str[state], pjsip_event_str(event->type),
- pjsip_event_str(event->src_type)));
+ PJ_LOG(4, (tsx->obj_name, "STATE %s-->%s, cause = %s",
+ state_str[tsx->state], state_str[state],
+ pjsip_event_str(event_src_type)));
/* Change state. */
tsx->state = state;
@@ -402,9 +419,7 @@ static void tsx_set_state( pjsip_transaction *tsx,
}
/* Inform TU */
- pj_memcpy(&e, event, sizeof(*event));
- e.type = PJSIP_EVENT_TSX_STATE_CHANGED;
- e.obj.tsx = tsx;
+ PJSIP_EVENT_INIT_TSX_STATE(e, tsx, event_src_type, event_src);
pjsip_endpt_send_tsx_event( tsx->endpt, &e );
/* When the transaction is terminated, release transport, and free the
@@ -413,7 +428,9 @@ static void tsx_set_state( pjsip_transaction *tsx,
if (state == PJSIP_TSX_STATE_TERMINATED) {
/* Decrement transport reference counter. */
- if (tsx->transport && tsx->transport_state == PJSIP_TSX_TRANSPORT_STATE_FINAL) {
+ if (tsx->transport &&
+ tsx->transport_state == PJSIP_TSX_TRANSPORT_STATE_FINAL)
+ {
pjsip_transport_dec_ref( tsx->transport );
tsx->transport = NULL;
}
@@ -483,7 +500,8 @@ static pj_status_t tsx_process_route( pjsip_transaction *tsx,
topmost_route_uri = &first_route_hdr->name_addr;
while (last_route_hdr->next != (void*)&tdata->msg->hdr) {
pjsip_route_hdr *hdr;
- hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE, last_route_hdr->next);
+ hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE,
+ last_route_hdr->next);
if (!hdr)
break;
last_route_hdr = hdr;
@@ -563,14 +581,16 @@ static pj_status_t tsx_process_route( pjsip_transaction *tsx,
send_addr->flag |= (PJSIP_TRANSPORT_SECURE | PJSIP_TRANSPORT_RELIABLE);
pj_strdup(tdata->pool, &send_addr->host, &url->host);
send_addr->port = url->port;
- send_addr->type = pjsip_transport_get_type_from_name(&url->transport_param);
+ send_addr->type =
+ pjsip_transport_get_type_from_name(&url->transport_param);
} else if (PJSIP_URI_SCHEME_IS_SIP(target_uri)) {
pjsip_uri *uri = (pjsip_uri*) target_uri;
const pjsip_url *url = (const pjsip_url*)pjsip_uri_get_uri(uri);
pj_strdup(tdata->pool, &send_addr->host, &url->host);
send_addr->port = url->port;
- send_addr->type = pjsip_transport_get_type_from_name(&url->transport_param);
+ send_addr->type =
+ pjsip_transport_get_type_from_name(&url->transport_param);
#if PJ_HAS_TCP
if (send_addr->type == PJSIP_TRANSPORT_TCP ||
send_addr->type == PJSIP_TRANSPORT_SCTP)
@@ -579,9 +599,8 @@ static pj_status_t tsx_process_route( pjsip_transaction *tsx,
}
#endif
} else {
- PJ_LOG(2, (tsx->obj_name, "Unable to lookup destination address for "
- "non SIP-URL"));
- return -1;
+ pj_assert(!"Unsupported URI scheme!");
+ return PJSIP_EINVALIDSCHEME;
}
/* If target URI is different than request URI, replace
@@ -598,7 +617,7 @@ static pj_status_t tsx_process_route( pjsip_transaction *tsx,
}
/* Success. */
- return 0;
+ return PJ_SUCCESS;
}
@@ -624,7 +643,7 @@ static void tsx_transport_callback(pjsip_transport_t *tr,
pjsip_transport_get_type_name(tr),
addr, tsx->dest_name.port));
} else {
- PJ_LOG(3, (tsx->obj_name, "%s unable to connect to %s:%d, status=%d",
+ PJ_LOG(4, (tsx->obj_name, "%s unable to connect to %s:%d, status=%d",
pjsip_transport_get_type_name(tr),
addr, tsx->dest_name.port, status));
}
@@ -633,23 +652,19 @@ static void tsx_transport_callback(pjsip_transport_t *tr,
lock_tsx(tsx, &lck);
if (status != PJ_SUCCESS) {
- pjsip_event event;
-
- event.type = PJSIP_EVENT_TRANSPORT_ERROR;
- event.src_type = PJSIP_EVENT_TX_MSG;
- event.src.tdata = tsx->last_tx;
-
tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_FINAL;
tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR;
- tsx_set_state(tsx, PJSIP_TSX_STATE_TERMINATED, &event);
+
+ tsx_set_state(tsx, PJSIP_TSX_STATE_TERMINATED,
+ PJSIP_EVENT_TRANSPORT_ERROR, (void*)status);
/* Unlock transaction. */
unlock_tsx(tsx, &lck);
return;
}
- /* See if transaction has already been terminated. If so, schedule to destroy
- * the transaction.
+ /* See if transaction has already been terminated.
+ * If so, schedule to destroy the transaction.
*/
if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
pj_time_val timeout = {0, 0};
@@ -690,15 +705,10 @@ static void tsx_resolver_callback(pj_status_t status,
PJ_LOG(4, (tsx->obj_name, "resolver job complete, status=%d", status));
if (status != PJ_SUCCESS || addr->count == 0) {
- pjsip_event event;
-
- event.type = PJSIP_EVENT_TRANSPORT_ERROR;
- event.src_type = PJSIP_EVENT_TX_MSG;
- event.src.tdata = tsx->last_tx;
-
lock_tsx(tsx, &lck);
tsx->status_code = PJSIP_SC_TSX_RESOLVE_ERROR;
- tsx_set_state(tsx, PJSIP_TSX_STATE_TERMINATED, &event);
+ tsx_set_state(tsx, PJSIP_TSX_STATE_TERMINATED,
+ PJSIP_EVENT_TRANSPORT_ERROR, (void*)status);
unlock_tsx(tsx, &lck);
return;
}
@@ -711,8 +721,8 @@ static void tsx_resolver_callback(pj_status_t status,
/* Create/find the transport for the remote address. */
PJ_LOG(5,(tsx->obj_name, "tsx getting transport for %s:%d",
- pj_sockaddr_get_str_addr(&addr->entry[0].addr),
- pj_sockaddr_get_port(&addr->entry[0].addr)));
+ pj_inet_ntoa(addr->entry[0].addr.sin_addr),
+ pj_ntohs(addr->entry[0].addr.sin_port)));
tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_CONNECTING;
pjsip_endpt_get_transport(tsx->endpt, tsx->pool,
@@ -738,8 +748,8 @@ PJ_DEF(pj_status_t) pjsip_tsx_init_uac( pjsip_transaction *tsx,
pjsip_msg *msg;
pjsip_cseq_hdr *cseq;
pjsip_via_hdr *via;
+ pj_status_t status;
struct tsx_lock_data lck;
- const pjsip_hdr *endpt_hdr;
PJ_LOG(4,(tsx->obj_name, "initializing tsx as UAC (tdata=%p)", tdata));
@@ -755,7 +765,7 @@ PJ_DEF(pj_status_t) pjsip_tsx_init_uac( pjsip_transaction *tsx,
/* Save method. */
pjsip_method_copy( tsx->pool, &tsx->method, &msg->line.req.method);
- /* Generate branch parameter if it doesn't exist. */
+ /* Generate Via header if it doesn't exist. */
via = pjsip_msg_find_hdr(msg, PJSIP_H_VIA, NULL);
if (via == NULL) {
via = pjsip_via_hdr_create(tdata->pool);
@@ -771,23 +781,23 @@ PJ_DEF(pj_status_t) pjsip_tsx_init_uac( pjsip_transaction *tsx,
tmp.ptr = via->branch_param.ptr + PJSIP_RFC3261_BRANCH_LEN;
pj_generate_unique_string( &tmp );
- }
- /* Copy branch parameter. */
- tsx->branch = via->branch_param;
-
- /* Add additional request headers from endpoint. */
- endpt_hdr = pjsip_endpt_get_request_headers(tsx->endpt)->next;
- while (endpt_hdr != pjsip_endpt_get_request_headers(tsx->endpt)) {
- pjsip_hdr *hdr = pjsip_hdr_shallow_clone(tdata->pool, endpt_hdr);
- pjsip_msg_add_hdr( tdata->msg, hdr );
- endpt_hdr = endpt_hdr->next;
+ /* Save branch parameter. */
+ tsx->branch = via->branch_param;
+ } else {
+ /* Copy branch parameter. */
+ pj_strdup(tsx->pool, &tsx->branch, &via->branch_param);
}
+
/* Generate transaction key. */
- create_tsx_key_3261( tsx->pool, &tsx->transaction_key,
- PJSIP_ROLE_UAC, &tsx->method,
- &via->branch_param);
+ status = create_tsx_key_3261( tsx->pool, &tsx->transaction_key,
+ PJSIP_ROLE_UAC, &tsx->method,
+ &via->branch_param);
+ if (status != PJ_SUCCESS) {
+ unlock_tsx(tsx, &lck);
+ return status;
+ }
PJ_LOG(6, (tsx->obj_name, "tsx_key=%.*s", tsx->transaction_key.slen,
tsx->transaction_key.ptr));
@@ -795,8 +805,9 @@ PJ_DEF(pj_status_t) pjsip_tsx_init_uac( pjsip_transaction *tsx,
/* Save CSeq. */
cseq = pjsip_msg_find_hdr(msg, PJSIP_H_CSEQ, NULL);
if (!cseq) {
- PJ_LOG(4,(tsx->obj_name, "CSeq header not present in outgoing message!"));
- return -1;
+ pj_assert(!"CSeq header not present in outgoing message!");
+ unlock_tsx(tsx, &lck);
+ return PJSIP_EMISSINGHDR;
}
tsx->cseq = cseq->cseq;
@@ -805,22 +816,17 @@ PJ_DEF(pj_status_t) pjsip_tsx_init_uac( pjsip_transaction *tsx,
* Manually set-up the state becase we don't want to call the callback.
*/
tsx->state = PJSIP_TSX_STATE_NULL;
- tsx->state_handler = pjsip_tsx_on_state_null;
+ tsx->state_handler = &pjsip_tsx_on_state_null;
/* Get destination name from the message. */
- if (tsx_process_route(tsx, tdata, &tsx->dest_name) != 0) {
- pjsip_event event;
- PJ_LOG(3,(tsx->obj_name, "Error: unable to get destination address for request"));
-
- event.type = PJSIP_EVENT_TRANSPORT_ERROR;
- event.src_type = PJSIP_EVENT_TX_MSG;
- event.src.tdata = tsx->last_tx;
-
+ status = tsx_process_route(tsx, tdata, &tsx->dest_name);
+ if (status != PJ_SUCCESS) {
tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_FINAL;
tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR;
- tsx_set_state(tsx, PJSIP_TSX_STATE_TERMINATED, &event);
+ tsx_set_state(tsx, PJSIP_TSX_STATE_TERMINATED,
+ PJSIP_EVENT_TRANSPORT_ERROR, (void*)status);
unlock_tsx(tsx, &lck);
- return -1;
+ return status;
}
/* Resolve destination.
@@ -858,6 +864,7 @@ PJ_DEF(pj_status_t) pjsip_tsx_init_uas( pjsip_transaction *tsx,
pjsip_msg *msg = rdata->msg;
pj_str_t *branch;
pjsip_cseq_hdr *cseq;
+ pj_status_t status;
struct tsx_lock_data lck;
PJ_LOG(4,(tsx->obj_name, "initializing tsx as UAS (rdata=%p)", rdata));
@@ -877,8 +884,12 @@ PJ_DEF(pj_status_t) pjsip_tsx_init_uas( pjsip_transaction *tsx,
/* Get transaction key either from branch for RFC3261 message, or
* create transaction key.
*/
- pjsip_tsx_create_key(tsx->pool, &tsx->transaction_key, PJSIP_ROLE_UAS,
- &tsx->method, rdata);
+ status = pjsip_tsx_create_key(tsx->pool, &tsx->transaction_key,
+ PJSIP_ROLE_UAS, &tsx->method, rdata);
+ if (status != PJ_SUCCESS) {
+ unlock_tsx(tsx, &lck);
+ return status;
+ }
/* Duplicate branch parameter for transaction. */
branch = &rdata->via->branch_param;
@@ -913,7 +924,8 @@ PJ_DEF(pj_status_t) pjsip_tsx_init_uas( pjsip_transaction *tsx,
tsx->current_addr = 0;
tsx->remote_addr.count = 1;
- tsx->remote_addr.entry[0].type = pjsip_transport_get_type(tsx->transport);
+ tsx->remote_addr.entry[0].type =
+ pjsip_transport_get_type(tsx->transport);
pj_memcpy(&tsx->remote_addr.entry[0].addr,
&rdata->addr, rdata->addr_len);
@@ -923,17 +935,10 @@ PJ_DEF(pj_status_t) pjsip_tsx_init_uas( pjsip_transaction *tsx,
status = pjsip_get_response_addr(tsx->pool, rdata->transport,
rdata->via, &tsx->dest_name);
if (status != PJ_SUCCESS) {
- pjsip_event event;
- PJ_LOG(2,(tsx->obj_name, "Unable to get destination address "
- "for response"));
-
- event.type = PJSIP_EVENT_TRANSPORT_ERROR;
- event.src_type = PJSIP_EVENT_TX_MSG;
- event.src.tdata = tsx->last_tx;
-
tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_FINAL;
tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR;
- tsx_set_state(tsx, PJSIP_TSX_STATE_TERMINATED, &event);
+ tsx_set_state(tsx, PJSIP_TSX_STATE_TERMINATED,
+ PJSIP_EVENT_TRANSPORT_ERROR, (void*)status);
unlock_tsx(tsx, &lck);
return status;
}
@@ -943,7 +948,8 @@ PJ_DEF(pj_status_t) pjsip_tsx_init_uas( pjsip_transaction *tsx,
* the callback will be called.
*/
PJ_LOG(5,(tsx->obj_name, "tsx resolving destination %.*s:%d",
- tsx->dest_name.host.slen, tsx->dest_name.host.ptr,
+ tsx->dest_name.host.slen,
+ tsx->dest_name.host.ptr,
tsx->dest_name.port));
tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_RESOLVING;
@@ -975,11 +981,14 @@ static void tsx_timer_callback( pj_timer_heap_t *theap, pj_timer_entry *entry)
PJ_UNUSED_ARG(theap);
PJ_LOG(5,(tsx->obj_name, "got timer event (%s timer)",
- (entry->id == TSX_TIMER_RETRANSMISSION ? "Retransmit" : "Timeout")));
+ (entry->id==TSX_TIMER_RETRANSMISSION ? "Retransmit" : "Timeout")));
- event.type = event.src_type = PJSIP_EVENT_TIMER;
- event.src.timer = (entry->id == TSX_TIMER_RETRANSMISSION ?
- &tsx->retransmit_timer : &tsx->timeout_timer);
+
+ if (entry->id == TSX_TIMER_RETRANSMISSION) {
+ PJSIP_EVENT_INIT_TIMER(event, &tsx->retransmit_timer);
+ } else {
+ PJSIP_EVENT_INIT_TIMER(event, &tsx->timeout_timer);
+ }
/* Dispatch event to transaction. */
lock_tsx(tsx, &lck);
@@ -999,10 +1008,11 @@ PJ_DEF(void) pjsip_tsx_on_tx_ack( pjsip_transaction *tsx, pjsip_tx_data *tdata)
{
pjsip_msg *msg;
pjsip_host_port dest_addr;
- pjsip_event event;
pjsip_via_hdr *via;
struct tsx_lock_data lck;
+ pj_status_t status = PJ_SUCCESS;
+ /* Lock tsx. */
lock_tsx(tsx, &lck);
pj_assert(tsx->handle_ack != 0);
@@ -1023,8 +1033,8 @@ PJ_DEF(void) pjsip_tsx_on_tx_ack( pjsip_transaction *tsx, pjsip_tx_data *tdata)
}
/* Get destination name from the message. */
- if (tsx_process_route(tsx, tdata, &dest_addr) != 0){
- PJ_LOG(2,(tsx->obj_name, "Unable to get destination address for request"));
+ status = tsx_process_route(tsx, tdata, &dest_addr);
+ if (status != 0){
goto on_error;
}
@@ -1088,10 +1098,9 @@ on_error:
* Send TERMINATED event.
*/
tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR;
- event.type = PJSIP_EVENT_TRANSPORT_ERROR;
- event.src_type = PJSIP_EVENT_TX_MSG;
- event.src.tdata = tdata;
- tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, &event);
+
+ tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,
+ PJSIP_EVENT_TRANSPORT_ERROR, (void*)status);
unlock_tsx(tsx, &lck);
}
@@ -1105,19 +1114,16 @@ PJ_DEF(void) pjsip_tsx_on_tx_msg( pjsip_transaction *tsx,
{
pjsip_event event;
struct tsx_lock_data lck;
+ pj_status_t status;
- PJ_LOG(5,(tsx->obj_name, "on transmit msg (tdata=%p)", tdata));
-
- event.type = event.src_type = PJSIP_EVENT_TX_MSG;
- event.src.tdata = tdata;
+ PJ_LOG(5,(tsx->obj_name, "Request to transmit msg on state %s (tdata=%p)",
+ state_str[tsx->state], tdata));
- PJ_LOG(5,(tsx->obj_name, "on state %s (ev=%s, src=%s, data=%p)",
- state_str[tsx->state], pjsip_event_str(event.type),
- pjsip_event_str(event.src_type), event.src.data));
+ PJSIP_EVENT_INIT_TX_MSG(event, tsx, tdata);
/* Dispatch to transaction. */
lock_tsx(tsx, &lck);
- (*tsx->state_handler)(tsx, &event);
+ status = (*tsx->state_handler)(tsx, &event);
unlock_tsx(tsx, &lck);
}
@@ -1130,17 +1136,16 @@ PJ_DEF(void) pjsip_tsx_on_rx_msg( pjsip_transaction *tsx,
{
pjsip_event event;
struct tsx_lock_data lck;
+ pj_status_t status;
- event.type = event.src_type = PJSIP_EVENT_RX_MSG;
- event.src.rdata = rdata;
+ PJ_LOG(5,(tsx->obj_name, "Incoming msg on state %s (rdata=%p)",
+ state_str[tsx->state], rdata));
- PJ_LOG(5,(tsx->obj_name, "on state %s (ev=%s, src=%s, data=%p)",
- state_str[tsx->state], pjsip_event_str(event.type),
- pjsip_event_str(event.src_type), event.src.data));
+ PJSIP_EVENT_INIT_RX_MSG(event, tsx, rdata);
/* Dispatch to transaction. */
lock_tsx(tsx, &lck);
- (*tsx->state_handler)(tsx, &event);
+ status = (*tsx->state_handler)(tsx, &event);
unlock_tsx(tsx, &lck);
}
@@ -1149,17 +1154,12 @@ PJ_DEF(void) pjsip_tsx_on_rx_msg( pjsip_transaction *tsx,
*/
PJ_DEF(void) pjsip_tsx_terminate( pjsip_transaction *tsx, int code )
{
- pjsip_event event;
struct tsx_lock_data lck;
lock_tsx(tsx, &lck);
-
tsx->status_code = code;
- event.type = PJSIP_EVENT_USER;
- event.src_type = PJSIP_EVENT_USER;
- event.src.data = 0;
- event.obj.tsx = tsx;
- tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, &event);
+ tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,
+ PJSIP_EVENT_USER, NULL);
unlock_tsx(tsx, &lck);
}
@@ -1169,14 +1169,15 @@ PJ_DEF(void) pjsip_tsx_terminate( pjsip_transaction *tsx, int code )
* If transport is not yet available, then do nothing. The message will be
* transmitted when transport connection completion callback is called.
*/
-static int tsx_send_msg( pjsip_transaction *tsx, pjsip_tx_data *tdata)
+static pj_status_t tsx_send_msg( pjsip_transaction *tsx,
+ pjsip_tx_data *tdata)
{
- pjsip_event event;
+ pj_status_t status = PJ_SUCCESS;
PJ_LOG(5,(tsx->obj_name, "sending msg (tdata=%p)", tdata));
if (tsx->transport_state == PJSIP_TSX_TRANSPORT_STATE_FINAL) {
- int sent;
+ pj_ssize_t sent;
pjsip_event before_tx_event;
pj_assert(tsx->transport != NULL);
@@ -1199,25 +1200,22 @@ static int tsx_send_msg( pjsip_transaction *tsx, pjsip_tx_data *tdata)
pj_strdup2(tdata->pool, &via->transport,
pjsip_transport_get_type_name(tsx->transport));
pj_strdup2(tdata->pool, &via->sent_by.host,
- pj_sockaddr_get_str_addr(addr_name));
- via->sent_by.port = pj_sockaddr_get_port(addr_name);
+ pj_inet_ntoa(addr_name->sin_addr));
+ via->sent_by.port = pj_ntohs(addr_name->sin_port);
}
}
/* Notify everybody we're about to send message. */
- before_tx_event.type = PJSIP_EVENT_BEFORE_TX;
- before_tx_event.src_type = PJSIP_EVENT_TX_MSG;
- before_tx_event.obj.tsx = tsx;
- before_tx_event.src.tdata = tdata;
- before_tx_event.data.long_data = tsx->retransmit_count;
- pjsip_endpt_send_tsx_event( tsx->endpt, &before_tx_event );
+ PJSIP_EVENT_INIT_PRE_TX_MSG(before_tx_event, tsx, tdata,
+ tsx->retransmit_count);
+ pjsip_endpt_send_tsx_event( tsx->endpt, &before_tx_event );
tsx->has_unsent_msg = 0;
- sent = pjsip_transport_send_msg(
- tsx->transport, tdata,
- &tsx->remote_addr.entry[tsx->current_addr].addr
- );
- if (sent < 1) {
+ status = pjsip_transport_send_msg(
+ tsx->transport, tdata,
+ &tsx->remote_addr.entry[tsx->current_addr].addr,
+ &sent);
+ if (status != PJ_SUCCESS) {
goto on_error;
}
} else {
@@ -1228,11 +1226,9 @@ static int tsx_send_msg( pjsip_transaction *tsx, pjsip_tx_data *tdata)
on_error:
tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR;
- event.type = PJSIP_EVENT_TRANSPORT_ERROR;
- event.src_type = PJSIP_EVENT_TX_MSG;
- event.src.tdata = tdata;
- tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, &event);
- return -1;
+ tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,
+ PJSIP_EVENT_TRANSPORT_ERROR, (void*)status);
+ return status;
}
/*
@@ -1241,6 +1237,8 @@ on_error:
static pj_status_t pjsip_tsx_retransmit( pjsip_transaction *tsx,
int should_restart_timer)
{
+ pj_status_t status;
+
PJ_LOG(4,(tsx->obj_name, "retransmiting (tdata=%p, count=%d, restart?=%d)",
tsx->last_tx, tsx->retransmit_count, should_restart_timer));
@@ -1248,8 +1246,9 @@ static pj_status_t pjsip_tsx_retransmit( pjsip_transaction *tsx,
++tsx->retransmit_count;
- if (tsx_send_msg( tsx, tsx->last_tx) != 0) {
- return -1;
+ status = tsx_send_msg( tsx, tsx->last_tx);
+ if (status != PJ_SUCCESS) {
+ return status;
}
/* Restart timer T1. */
@@ -1257,12 +1256,13 @@ static pj_status_t pjsip_tsx_retransmit( pjsip_transaction *tsx,
pj_time_val timeout;
int msec_time = (1 << (tsx->retransmit_count)) * PJSIP_T1_TIMEOUT;
- if (tsx->method.id != PJSIP_INVITE_METHOD && msec_time > PJSIP_T2_TIMEOUT)
+ if (tsx->method.id!=PJSIP_INVITE_METHOD && msec_time>PJSIP_T2_TIMEOUT)
msec_time = PJSIP_T2_TIMEOUT;
timeout.sec = msec_time / 1000;
timeout.msec = msec_time % 1000;
- pjsip_endpt_schedule_timer( tsx->endpt, &tsx->retransmit_timer, &timeout);
+ pjsip_endpt_schedule_timer( tsx->endpt, &tsx->retransmit_timer,
+ &timeout);
}
return PJ_SUCCESS;
@@ -1271,8 +1271,11 @@ static pj_status_t pjsip_tsx_retransmit( pjsip_transaction *tsx,
/*
* Handler for events in state Null.
*/
-static int pjsip_tsx_on_state_null( pjsip_transaction *tsx, pjsip_event *event )
+static pj_status_t pjsip_tsx_on_state_null( pjsip_transaction *tsx,
+ pjsip_event *event )
{
+ pj_status_t status;
+
pj_assert( tsx->state == PJSIP_TSX_STATE_NULL);
pj_assert( tsx->last_tx == NULL );
pj_assert( tsx->has_unsent_msg == 0);
@@ -1281,24 +1284,27 @@ static int pjsip_tsx_on_state_null( pjsip_transaction *tsx, pjsip_event *event
/* Set state to Trying. */
pj_assert(event->type == PJSIP_EVENT_RX_MSG);
- tsx_set_state( tsx, PJSIP_TSX_STATE_TRYING, event);
+ tsx_set_state( tsx, PJSIP_TSX_STATE_TRYING,
+ PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata );
} else {
- pjsip_tx_data *tdata = event->src.tdata;
+ pjsip_tx_data *tdata = event->body.tx_msg.tdata;
/* Save the message for retransmission. */
tsx->last_tx = tdata;
pjsip_tx_data_add_ref(tdata);
/* Send the message. */
- if (tsx_send_msg( tsx, tdata) != 0) {
- return -1;
+ status = tsx_send_msg( tsx, tdata);
+ if (status != PJ_SUCCESS) {
+ return status;
}
/* Start Timer B (or called timer F for non-INVITE) for transaction
* timeout.
*/
- pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer, &timeout_timer_val);
+ pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer,
+ &timeout_timer_val);
/* Start Timer A (or timer E) for retransmission only if unreliable
* transport is being used.
@@ -1306,12 +1312,14 @@ static int pjsip_tsx_on_state_null( pjsip_transaction *tsx, pjsip_event *event
if (tsx->transport_state == PJSIP_TSX_TRANSPORT_STATE_FINAL &&
PJSIP_TRANSPORT_IS_RELIABLE(tsx->transport)==0)
{
- pjsip_endpt_schedule_timer(tsx->endpt, &tsx->retransmit_timer, &t1_timer_val);
+ pjsip_endpt_schedule_timer(tsx->endpt, &tsx->retransmit_timer,
+ &t1_timer_val);
tsx->retransmit_count = 0;
}
/* Move state. */
- tsx_set_state( tsx, PJSIP_TSX_STATE_CALLING, event);
+ tsx_set_state( tsx, PJSIP_TSX_STATE_CALLING,
+ PJSIP_EVENT_TX_MSG, tdata);
}
return PJ_SUCCESS;
@@ -1321,23 +1329,25 @@ static int pjsip_tsx_on_state_null( pjsip_transaction *tsx, pjsip_event *event
* State Calling is for UAC after it sends request but before any responses
* is received.
*/
-static int pjsip_tsx_on_state_calling( pjsip_transaction *tsx,
- pjsip_event *event)
+static pj_status_t pjsip_tsx_on_state_calling( pjsip_transaction *tsx,
+ pjsip_event *event )
{
pj_assert(tsx->state == PJSIP_TSX_STATE_CALLING);
pj_assert(tsx->role == PJSIP_ROLE_UAC);
if (event->type == PJSIP_EVENT_TIMER &&
- event->src.timer == &tsx->retransmit_timer)
+ event->body.timer.entry == &tsx->retransmit_timer)
{
+ pj_status_t status;
/* Retransmit the request. */
- if (pjsip_tsx_retransmit( tsx, 1 ) != 0) {
- return -1;
+ status = pjsip_tsx_retransmit( tsx, 1 );
+ if (status != PJ_SUCCESS) {
+ return status;
}
} else if (event->type == PJSIP_EVENT_TIMER &&
- event->src.timer == &tsx->timeout_timer)
+ event->body.timer.entry == &tsx->timeout_timer)
{
/* Cancel retransmission timer. */
@@ -1349,10 +1359,11 @@ static int pjsip_tsx_on_state_calling( pjsip_transaction *tsx,
tsx->status_code = PJSIP_SC_TSX_TIMEOUT;
/* Inform TU. */
- tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, event );
+ tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,
+ PJSIP_EVENT_TIMER, &tsx->timeout_timer);
/* Transaction is destroyed */
- return -1;
+ return PJSIP_ETSXDESTROYED;
} else if (event->type == PJSIP_EVENT_RX_MSG) {
int code;
@@ -1369,7 +1380,7 @@ static int pjsip_tsx_on_state_calling( pjsip_transaction *tsx,
* the final response.
*/
/* Keep last_tx for authorization. */
- code = event->src.rdata->msg->line.status.code;
+ code = event->body.rx_msg.rdata->msg->line.status.code;
if (tsx->method.id != PJSIP_INVITE_METHOD && code!=401 && code!=407) {
pjsip_tx_data_dec_ref(tsx->last_tx);
tsx->last_tx = NULL;
@@ -1380,6 +1391,7 @@ static int pjsip_tsx_on_state_calling( pjsip_transaction *tsx,
} else {
pj_assert(0);
+ return PJ_EBUG;
}
return PJ_SUCCESS;
@@ -1391,9 +1403,10 @@ static int pjsip_tsx_on_state_calling( pjsip_transaction *tsx,
* Note: this is different than RFC3261, which can use Trying state for
* non-INVITE client transaction (bug in RFC?).
*/
-static int pjsip_tsx_on_state_trying( pjsip_transaction *tsx, pjsip_event *event)
+static pj_status_t pjsip_tsx_on_state_trying( pjsip_transaction *tsx,
+ pjsip_event *event)
{
- int result;
+ pj_status_t status;
pj_assert(tsx->state == PJSIP_TSX_STATE_TRYING);
@@ -1414,21 +1427,23 @@ static int pjsip_tsx_on_state_trying( pjsip_transaction *tsx, pjsip_event *even
/* The rest of the processing of the event is exactly the same as in
* "Proceeding" state.
*/
- result = pjsip_tsx_on_state_proceeding_uas( tsx, event);
+ status = pjsip_tsx_on_state_proceeding_uas( tsx, event);
/* Inform the TU of the state transision if state is still State_Trying */
- if (result==0 && tsx->state == PJSIP_TSX_STATE_TRYING) {
- tsx_set_state( tsx, PJSIP_TSX_STATE_PROCEEDING, event);
+ if (status==PJ_SUCCESS && tsx->state == PJSIP_TSX_STATE_TRYING) {
+ tsx_set_state( tsx, PJSIP_TSX_STATE_PROCEEDING,
+ PJSIP_EVENT_TX_MSG, event->body.tx_msg.tdata);
}
- return result;
+ return status;
}
/*
* Handler for events in Proceeding for UAS
* This state happens after the TU sends provisional response.
*/
-static int pjsip_tsx_on_state_proceeding_uas( pjsip_transaction *tsx, pjsip_event *event)
+static pj_status_t pjsip_tsx_on_state_proceeding_uas( pjsip_transaction *tsx,
+ pjsip_event *event)
{
pj_assert(tsx->state == PJSIP_TSX_STATE_PROCEEDING ||
tsx->state == PJSIP_TSX_STATE_TRYING);
@@ -1439,13 +1454,17 @@ static int pjsip_tsx_on_state_proceeding_uas( pjsip_transaction *tsx, pjsip_even
/* Receive request retransmission. */
if (event->type == PJSIP_EVENT_RX_MSG) {
+ pj_status_t status;
+
/* Send last response. */
- if (pjsip_tsx_retransmit( tsx, 0 ) != 0) {
- return -1;
+ status = pjsip_tsx_retransmit( tsx, 0 );
+ if (status != PJ_SUCCESS) {
+ return status;
}
} else if (event->type == PJSIP_EVENT_TX_MSG ) {
- pjsip_tx_data *tdata = event->src.tdata;
+ pjsip_tx_data *tdata = event->body.tx_msg.tdata;
+ pj_status_t status;
/* The TU sends response message to the request. Save this message so
* that we can retransmit the last response in case we receive request
@@ -1471,8 +1490,9 @@ static int pjsip_tsx_on_state_proceeding_uas( pjsip_transaction *tsx, pjsip_even
}
/* Send the message. */
- if (tsx_send_msg(tsx, tdata) != 0) {
- return -1;
+ status = tsx_send_msg(tsx, tdata);
+ if (status != PJ_SUCCESS) {
+ return status;
}
// Update To tag header for RFC2543 transaction.
@@ -1485,26 +1505,29 @@ static int pjsip_tsx_on_state_proceeding_uas( pjsip_transaction *tsx, pjsip_even
tsx->last_tx = tdata;
pjsip_tx_data_add_ref( tdata );
}
- tsx_set_state( tsx, PJSIP_TSX_STATE_PROCEEDING, event);
+ tsx_set_state( tsx, PJSIP_TSX_STATE_PROCEEDING,
+ PJSIP_EVENT_TX_MSG, tdata );
} else if (PJSIP_IS_STATUS_IN_CLASS(tsx->status_code, 200)) {
if (tsx->method.id == PJSIP_INVITE_METHOD && tsx->handle_ack==0) {
- /* 2xx class message is not saved, because retransmission is handled
- * by the TU.
+ /* 2xx class message is not saved, because retransmission
+ * is handled by TU.
*/
- tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, event);
+ tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,
+ PJSIP_EVENT_TX_MSG, tdata );
/* Transaction is destroyed. */
- return -1;
+ return PJSIP_ETSXDESTROYED;
} else {
pj_time_val timeout;
if (tsx->method.id == PJSIP_INVITE_METHOD) {
tsx->retransmit_count = 0;
- pjsip_endpt_schedule_timer( tsx->endpt, &tsx->retransmit_timer,
+ pjsip_endpt_schedule_timer( tsx->endpt,
+ &tsx->retransmit_timer,
&t1_timer_val);
}
@@ -1525,37 +1548,45 @@ static int pjsip_tsx_on_state_proceeding_uas( pjsip_transaction *tsx, pjsip_even
timeout.sec = timeout.msec = 0;
}
- pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer, &timeout);
+ pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer,
+ &timeout);
/* Set state to "Completed" */
- tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED, event);
+ tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED,
+ PJSIP_EVENT_TX_MSG, tdata );
}
} else if (tsx->status_code >= 300) {
- /* 3xx-6xx class message causes transaction to move to "Completed" state. */
+ /* 3xx-6xx class message causes transaction to move to
+ * "Completed" state.
+ */
if (tsx->last_tx != tdata) {
tsx->last_tx = tdata;
pjsip_tx_data_add_ref( tdata );
}
/* Start timer H for transaction termination */
- pjsip_endpt_schedule_timer(tsx->endpt,&tsx->timeout_timer,&timeout_timer_val);
+ pjsip_endpt_schedule_timer(tsx->endpt,&tsx->timeout_timer,
+ &timeout_timer_val);
/* For INVITE, if unreliable transport is used, retransmission
* timer G will be scheduled (retransmission).
*/
if (PJSIP_TRANSPORT_IS_RELIABLE(tsx->transport)==0) {
- pjsip_cseq_hdr *cseq = pjsip_msg_find_hdr( msg, PJSIP_H_CSEQ, NULL);
+ pjsip_cseq_hdr *cseq = pjsip_msg_find_hdr( msg, PJSIP_H_CSEQ,
+ NULL);
if (cseq->method.id == PJSIP_INVITE_METHOD) {
tsx->retransmit_count = 0;
- pjsip_endpt_schedule_timer(tsx->endpt, &tsx->retransmit_timer,
+ pjsip_endpt_schedule_timer(tsx->endpt,
+ &tsx->retransmit_timer,
&t1_timer_val);
}
}
/* Inform TU */
- tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED, event);
+ tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED,
+ PJSIP_EVENT_TX_MSG, tdata );
} else {
pj_assert(0);
@@ -1563,34 +1594,38 @@ static int pjsip_tsx_on_state_proceeding_uas( pjsip_transaction *tsx, pjsip_even
} else if (event->type == PJSIP_EVENT_TIMER &&
- event->src.timer == &tsx->retransmit_timer) {
+ event->body.timer.entry == &tsx->retransmit_timer) {
/* Retransmission timer elapsed. */
+ pj_status_t status;
/* Must have last response to retransmit. */
pj_assert(tsx->last_tx != NULL);
/* Retransmit the last response. */
- if (pjsip_tsx_retransmit( tsx, 1 ) != 0) {
- return -1;
+ status = pjsip_tsx_retransmit( tsx, 1 );
+ if (status != PJ_SUCCESS) {
+ return status;
}
} else if (event->type == PJSIP_EVENT_TIMER &&
- event->src.timer == &tsx->timeout_timer) {
+ event->body.timer.entry == &tsx->timeout_timer) {
/* Timeout timer. should not happen? */
pj_assert(0);
tsx->status_code = PJSIP_SC_TSX_TIMEOUT;
- tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, event);
+ tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,
+ PJSIP_EVENT_TIMER, &tsx->timeout_timer);
- return -1;
+ return PJ_EBUG;
} else {
pj_assert(0);
+ return PJ_EBUG;
}
- return 0;
+ return PJ_SUCCESS;
}
/*
@@ -1598,7 +1633,8 @@ static int pjsip_tsx_on_state_proceeding_uas( pjsip_transaction *tsx, pjsip_even
* This state happens after provisional response(s) has been received from
* UAS.
*/
-static int pjsip_tsx_on_state_proceeding_uac( pjsip_transaction *tsx, pjsip_event *event)
+static pj_status_t pjsip_tsx_on_state_proceeding_uac(pjsip_transaction *tsx,
+ pjsip_event *event)
{
pj_assert(tsx->state == PJSIP_TSX_STATE_PROCEEDING ||
@@ -1610,10 +1646,10 @@ static int pjsip_tsx_on_state_proceeding_uac( pjsip_transaction *tsx, pjsip_even
*/
pj_assert(event->type == PJSIP_EVENT_RX_MSG);
if (event->type != PJSIP_EVENT_RX_MSG) {
- return 0;
+ return PJ_EINVALIDOP;
}
- tsx->status_code = event->src.rdata->msg->line.status.code;
+ tsx->status_code = event->body.rx_msg.rdata->msg->line.status.code;
} else {
tsx->status_code = PJSIP_SC_TSX_TIMEOUT;
}
@@ -1621,7 +1657,8 @@ static int pjsip_tsx_on_state_proceeding_uac( pjsip_transaction *tsx, pjsip_even
if (PJSIP_IS_STATUS_IN_CLASS(tsx->status_code, 100)) {
/* Inform the message to TU. */
- tsx_set_state( tsx, PJSIP_TSX_STATE_PROCEEDING, event);
+ tsx_set_state( tsx, PJSIP_TSX_STATE_PROCEEDING,
+ PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata );
} else if (PJSIP_IS_STATUS_IN_CLASS(tsx->status_code,200)) {
@@ -1632,8 +1669,9 @@ static int pjsip_tsx_on_state_proceeding_uac( pjsip_transaction *tsx, pjsip_even
* handled in TU). For non-INVITE, state moves to Completed.
*/
if (tsx->method.id == PJSIP_INVITE_METHOD && tsx->handle_ack == 0) {
- tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, event);
- return -1;
+ tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,
+ PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata );
+ return PJSIP_ETSXDESTROYED;
} else {
pj_time_val timeout;
@@ -1649,23 +1687,28 @@ static int pjsip_tsx_on_state_proceeding_uac( pjsip_transaction *tsx, pjsip_even
} else {
timeout.sec = timeout.msec = 0;
}
- pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer, &timeout);
+ pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer,
+ &timeout);
/* Move state to Completed, inform TU. */
- tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED, event);
+ tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED,
+ PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata );
}
} else if (tsx->status_code >= 300 && tsx->status_code <= 699) {
pj_time_val timeout;
+ pj_status_t status;
/* Stop timer B. */
pjsip_endpt_cancel_timer( tsx->endpt, &tsx->timeout_timer );
/* Generate and send ACK for INVITE. */
if (tsx->method.id == PJSIP_INVITE_METHOD) {
- pjsip_endpt_create_ack( tsx->endpt, tsx->last_tx, event->src.rdata );
- if (tsx_send_msg( tsx, tsx->last_tx) != 0) {
- return -1;
+ pjsip_endpt_create_ack( tsx->endpt, tsx->last_tx,
+ event->body.rx_msg.rdata );
+ status = tsx_send_msg( tsx, tsx->last_tx);
+ if (status != PJ_SUCCESS) {
+ return status;
}
}
@@ -1682,11 +1725,13 @@ static int pjsip_tsx_on_state_proceeding_uac( pjsip_transaction *tsx, pjsip_even
pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer, &timeout);
/* Inform TU. */
- tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED, event);
+ tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED,
+ PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata );
} else {
// Shouldn't happen because there's no timer for this state.
pj_assert(0);
+ return PJ_EBUG;
}
return PJ_SUCCESS;
@@ -1695,18 +1740,22 @@ static int pjsip_tsx_on_state_proceeding_uac( pjsip_transaction *tsx, pjsip_even
/*
* Handler for events in Completed state for UAS
*/
-static int pjsip_tsx_on_state_completed_uas( pjsip_transaction *tsx, pjsip_event *event)
+static pj_status_t pjsip_tsx_on_state_completed_uas( pjsip_transaction *tsx,
+ pjsip_event *event)
{
pj_assert(tsx->state == PJSIP_TSX_STATE_COMPLETED);
if (event->type == PJSIP_EVENT_RX_MSG) {
- pjsip_msg *msg = event->src.rdata->msg;
+ pjsip_msg *msg = event->body.rx_msg.rdata->msg;
pjsip_cseq_hdr *cseq = pjsip_msg_find_hdr( msg, PJSIP_H_CSEQ, NULL );
/* On receive request retransmission, retransmit last response. */
if (cseq->method.id != PJSIP_ACK_METHOD) {
- if (pjsip_tsx_retransmit( tsx, 0 ) != 0) {
- return -1;
+ pj_status_t status;
+
+ status = pjsip_tsx_retransmit( tsx, 0 );
+ if (status != PJ_SUCCESS) {
+ return status;
}
} else {
@@ -1717,18 +1766,23 @@ static int pjsip_tsx_on_state_completed_uas( pjsip_transaction *tsx, pjsip_event
/* Start timer I in T4 interval (transaction termination). */
pjsip_endpt_cancel_timer( tsx->endpt, &tsx->timeout_timer );
- pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer, &t4_timer_val);
+ pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer,
+ &t4_timer_val);
/* Move state to "Confirmed" */
- tsx_set_state( tsx, PJSIP_TSX_STATE_CONFIRMED, event);
+ tsx_set_state( tsx, PJSIP_TSX_STATE_CONFIRMED,
+ PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata );
}
} else if (event->type == PJSIP_EVENT_TIMER) {
- if (event->src.timer == &tsx->retransmit_timer) {
+ if (event->body.timer.entry == &tsx->retransmit_timer) {
/* Retransmit message. */
- if (pjsip_tsx_retransmit( tsx, 1 ) != 0) {
- return -1;
+ pj_status_t status;
+
+ status = pjsip_tsx_retransmit( tsx, 1 );
+ if (status != PJ_SUCCESS) {
+ return status;
}
} else {
@@ -1740,20 +1794,22 @@ static int pjsip_tsx_on_state_completed_uas( pjsip_transaction *tsx, pjsip_event
tsx->status_code = PJSIP_SC_TSX_TIMEOUT;
- tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, event);
+ tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,
+ PJSIP_EVENT_TIMER, &tsx->timeout_timer );
- return -1;
+ return PJSIP_ETSXDESTROYED;
} else {
/* Transaction terminated, it can now be deleted. */
- tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, event);
- return -1;
+ tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,
+ PJSIP_EVENT_TIMER, &tsx->timeout_timer );
+ return PJSIP_ETSXDESTROYED;
}
}
} else {
/* Ignore request to transmit. */
- pj_assert(event->src.tdata == tsx->last_tx);
+ pj_assert(event->body.tx_msg.tdata == tsx->last_tx);
}
return PJ_SUCCESS;
@@ -1762,32 +1818,37 @@ static int pjsip_tsx_on_state_completed_uas( pjsip_transaction *tsx, pjsip_event
/*
* Handler for events in Completed state for UAC transaction.
*/
-static int pjsip_tsx_on_state_completed_uac( pjsip_transaction *tsx, pjsip_event *event)
+static pj_status_t pjsip_tsx_on_state_completed_uac( pjsip_transaction *tsx,
+ pjsip_event *event)
{
pj_assert(tsx->state == PJSIP_TSX_STATE_COMPLETED);
if (event->type == PJSIP_EVENT_TIMER) {
/* Must be the timeout timer. */
- pj_assert(event->src.timer == &tsx->timeout_timer);
+ pj_assert(event->body.timer.entry == &tsx->timeout_timer);
/* Move to Terminated state. */
- tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, event);
+ tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,
+ PJSIP_EVENT_TIMER, event->body.timer.entry );
/* Transaction has been destroyed. */
- return -1;
+ return PJSIP_ETSXDESTROYED;
} else if (event->type == PJSIP_EVENT_RX_MSG) {
if (tsx->method.id == PJSIP_INVITE_METHOD) {
/* On received of final response retransmission, retransmit the ACK.
* TU doesn't need to be informed.
*/
- pjsip_msg *msg = event->src.rdata->msg;
+ pjsip_msg *msg = event->body.rx_msg.rdata->msg;
pj_assert(msg->type == PJSIP_RESPONSE_MSG);
if (msg->type==PJSIP_RESPONSE_MSG &&
msg->line.status.code >= 200)
{
- if (pjsip_tsx_retransmit( tsx, 0 ) != 0) {
- return -1;
+ pj_status_t status;
+
+ status = pjsip_tsx_retransmit( tsx, 0 );
+ if (status != PJ_SUCCESS) {
+ return status;
}
} else {
/* Very late retransmission of privisional response. */
@@ -1798,34 +1859,41 @@ static int pjsip_tsx_on_state_completed_uac( pjsip_transaction *tsx, pjsip_event
}
} else if (tsx->method.id == PJSIP_INVITE_METHOD &&
event->type == PJSIP_EVENT_TX_MSG &&
- event->src.tdata->msg->line.req.method.id == PJSIP_ACK_METHOD) {
+ event->body.tx_msg.tdata->msg->line.req.method.id==PJSIP_ACK_METHOD) {
+
+ pj_status_t status;
/* Set last transmitted message. */
- if (tsx->last_tx != event->src.tdata) {
+ if (tsx->last_tx != event->body.tx_msg.tdata) {
pjsip_tx_data_dec_ref( tsx->last_tx );
- tsx->last_tx = event->src.tdata;
+ tsx->last_tx = event->body.tx_msg.tdata;
pjsip_tx_data_add_ref( tsx->last_tx );
}
/* No state changed, but notify app.
* Must notify now, so app has chance to put SDP in outgoing ACK msg.
*/
- tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED, event );
+ tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED,
+ PJSIP_EVENT_TX_MSG, event->body.tx_msg.tdata );
/* Send msg */
- tsx_send_msg(tsx, event->src.tdata);
+ status = tsx_send_msg(tsx, event->body.tx_msg.tdata);
+ if (status != PJ_SUCCESS)
+ return status;
} else {
pj_assert(0);
+ return PJ_EBUG;
}
- return 0;
+ return PJ_SUCCESS;
}
/*
* Handler for events in state Confirmed.
*/
-static int pjsip_tsx_on_state_confirmed( pjsip_transaction *tsx, pjsip_event *event)
+static pj_status_t pjsip_tsx_on_state_confirmed( pjsip_transaction *tsx,
+ pjsip_event *event)
{
pj_assert(tsx->state == PJSIP_TSX_STATE_CONFIRMED);
@@ -1835,25 +1903,36 @@ static int pjsip_tsx_on_state_confirmed( pjsip_transaction *tsx, pjsip_event *ev
/* Absorb any ACK received. */
if (event->type == PJSIP_EVENT_RX_MSG) {
+
+ pjsip_method_e method_id =
+ event->body.rx_msg.rdata->msg->line.req.method.id;
+
/* Must be a request message. */
- pj_assert(event->src.rdata->msg->type == PJSIP_REQUEST_MSG);
+ pj_assert(event->body.rx_msg.rdata->msg->type == PJSIP_REQUEST_MSG);
/* Must be an ACK request or a late INVITE retransmission. */
- pj_assert(event->src.rdata->msg->line.req.method.id == PJSIP_ACK_METHOD ||
- event->src.rdata->msg->line.req.method.id == PJSIP_INVITE_METHOD);
+ pj_assert(method_id == PJSIP_ACK_METHOD ||
+ method_id == PJSIP_INVITE_METHOD);
+
+ /* Just so that compiler won't complain about unused vars when
+ * building release code.
+ */
+ PJ_UNUSED_ARG(method_id);
} else if (event->type == PJSIP_EVENT_TIMER) {
/* Must be from timeout_timer_. */
- pj_assert(event->src.timer == &tsx->timeout_timer);
+ pj_assert(event->body.timer.entry == &tsx->timeout_timer);
/* Move to Terminated state. */
- tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, event);
+ tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,
+ PJSIP_EVENT_TIMER, &tsx->timeout_timer );
/* Transaction has been destroyed. */
- return -1;
+ return PJSIP_ETSXDESTROYED;
} else {
pj_assert(0);
+ return PJ_EBUG;
}
return PJ_SUCCESS;
@@ -1862,23 +1941,26 @@ static int pjsip_tsx_on_state_confirmed( pjsip_transaction *tsx, pjsip_event *ev
/*
* Handler for events in state Terminated.
*/
-static int pjsip_tsx_on_state_terminated( pjsip_transaction *tsx, pjsip_event *event)
+static pj_status_t pjsip_tsx_on_state_terminated( pjsip_transaction *tsx,
+ pjsip_event *event)
{
pj_assert(tsx->state == PJSIP_TSX_STATE_TERMINATED);
- PJ_UNUSED_ARG(event)
+ PJ_UNUSED_ARG(event);
/* Destroy this transaction */
- tsx_set_state(tsx, PJSIP_TSX_STATE_DESTROYED, event);
+ tsx_set_state(tsx, PJSIP_TSX_STATE_DESTROYED,
+ event->type, event->body.user.user1 );
return PJ_SUCCESS;
}
-static int pjsip_tsx_on_state_destroyed( pjsip_transaction *tsx, pjsip_event *event)
+static pj_status_t pjsip_tsx_on_state_destroyed(pjsip_transaction *tsx,
+ pjsip_event *event)
{
- PJ_UNUSED_ARG(tsx)
- PJ_UNUSED_ARG(event)
+ PJ_UNUSED_ARG(tsx);
+ PJ_UNUSED_ARG(event);
return PJ_SUCCESS;
}
diff --git a/pjsip/src/pjsip/sip_transport.c b/pjsip/src/pjsip/sip_transport.c
index 65b8ec45..09eb6cfb 100644
--- a/pjsip/src/pjsip/sip_transport.c
+++ b/pjsip/src/pjsip/sip_transport.c
@@ -1,17 +1,18 @@
/* $Id$
- *
*/
#include <pjsip/sip_transport.h>
#include <pjsip/sip_endpoint.h>
#include <pjsip/sip_parser.h>
#include <pjsip/sip_msg.h>
#include <pjsip/sip_private.h>
+#include <pjsip/sip_errno.h>
#include <pj/os.h>
#include <pj/log.h>
#include <pj/ioqueue.h>
#include <pj/hash.h>
#include <pj/string.h>
#include <pj/pool.h>
+#include <pj/assert.h>
#define MGR_IDLE_CHECK_INTERVAL 30
#define MGR_HASH_TABLE_SIZE PJSIP_MAX_DIALOG_COUNT
@@ -44,7 +45,7 @@ struct pjsip_transport_t
/** Standard list members, for chaining the transport in the
* listener list.
*/
- PJ_DECL_LIST_MEMBER(struct pjsip_transport_t)
+ PJ_DECL_LIST_MEMBER(struct pjsip_transport_t);
/** Transport's pool. */
pj_pool_t *pool;
@@ -66,10 +67,13 @@ struct pjsip_transport_t
/** I/O Queue key */
pj_ioqueue_key_t *key;
-
+
+ /** Accept key. */
+ pj_ioqueue_op_key_t accept_op;
+
/** Receive data buffer */
pjsip_rx_data *rdata;
-
+
/** Pointer to transport manager */
pjsip_transport_mgr *mgr;
@@ -114,7 +118,9 @@ struct pjsip_transport_mgr
pj_mutex_t *mutex;
pjsip_endpoint *endpt;
pj_ioqueue_t *ioqueue;
- pj_time_val next_idle_check;
+ pj_time_val next_idle_check;
+ pj_size_t send_buf_size;
+ pj_size_t recv_buf_size;
void (*message_callback)(pjsip_endpoint*, pjsip_rx_data *rdata);
};
@@ -144,7 +150,7 @@ typedef struct transport_key
*/
struct transport_callback
{
- PJ_DECL_LIST_MEMBER(struct transport_callback)
+ PJ_DECL_LIST_MEMBER(struct transport_callback);
/** User defined token to be passed to the callback. */
void *token;
@@ -173,10 +179,18 @@ const struct
#endif
};
-static void on_ioqueue_read(pj_ioqueue_key_t *key, pj_ssize_t bytes_read);
-static void on_ioqueue_write(pj_ioqueue_key_t *key, pj_ssize_t bytes_sent);
-static void on_ioqueue_accept(pj_ioqueue_key_t *key, int status);
-static void on_ioqueue_connect(pj_ioqueue_key_t *key, int status);
+static void on_ioqueue_read(pj_ioqueue_key_t *key,
+ pj_ioqueue_op_key_t *op_key,
+ pj_ssize_t bytes_read);
+static void on_ioqueue_write(pj_ioqueue_key_t *key,
+ pj_ioqueue_op_key_t *op_key,
+ pj_ssize_t bytes_sent);
+static void on_ioqueue_accept(pj_ioqueue_key_t *key,
+ pj_ioqueue_op_key_t *op_key,
+ pj_sock_t newsock,
+ int status);
+static void on_ioqueue_connect(pj_ioqueue_key_t *key,
+ int status);
static pj_ioqueue_callback ioqueue_transport_callback =
{
@@ -194,11 +208,11 @@ static void init_key_from_transport(transport_key *key,
key->type = (pj_uint8_t)tr->type;
key->zero = 0;
- key->addr = pj_sockaddr_get_addr(&tr->remote_addr);
- key->port = pj_sockaddr_get_port(&tr->remote_addr);
+ key->addr = pj_sockaddr_in_get_addr(&tr->remote_addr).s_addr;
+ key->port = pj_sockaddr_in_get_port(&tr->remote_addr);
/*
if (key->port == 0) {
- key->port = pj_sockaddr_get_port(&tr->local_addr);
+ key->port = pj_sockaddr_in_get_port(&tr->local_addr);
}
*/
}
@@ -212,15 +226,15 @@ static void init_tcp_key(transport_key *key, pjsip_transport_type_e type,
key->type = (pj_uint8_t)type;
key->zero = 0;
- key->addr = pj_sockaddr_get_addr(addr);
- key->port = pj_sockaddr_get_port(addr);
+ key->addr = pj_sockaddr_in_get_addr(addr).s_addr;
+ key->port = pj_sockaddr_in_get_port(addr);
}
#endif
static void init_udp_key(transport_key *key, pjsip_transport_type_e type,
const pj_sockaddr_in *addr)
{
- PJ_UNUSED_ARG(addr)
+ PJ_UNUSED_ARG(addr);
/* This is to detect alignment problems. */
pj_assert(sizeof(transport_key) == 8);
@@ -236,7 +250,7 @@ static void init_udp_key(transport_key *key, pjsip_transport_type_e type,
pj_str_t localaddr = pj_str("127.0.0.1");
pj_sockaddr_in addr;
pj_sockaddr_set_str_addr(&addr, &localaddr);
- key->addr = pj_sockaddr_get_addr(&addr);
+ key->addr = pj_sockaddr_in_get_addr(&addr);
}
#endif
}
@@ -297,31 +311,36 @@ pjsip_transport_get_type_from_name(const pj_str_t *name)
/*
* Create new transmit buffer.
*/
-pjsip_tx_data* pjsip_tx_data_create( pjsip_transport_mgr *mgr )
+pj_status_t pjsip_tx_data_create( pjsip_transport_mgr *mgr,
+ pjsip_tx_data **p_tdata )
{
pj_pool_t *pool;
pjsip_tx_data *tdata;
+ pj_status_t status;
PJ_LOG(5, ("", "pjsip_tx_data_create"));
+
+ PJ_ASSERT_RETURN(mgr && p_tdata, PJ_EINVAL);
pool = pjsip_endpt_create_pool( mgr->endpt, "ptdt%p",
PJSIP_POOL_LEN_TDATA,
PJSIP_POOL_INC_TDATA );
if (!pool) {
- return NULL;
+ return PJ_ENOMEM;
}
tdata = pj_pool_calloc(pool, 1, sizeof(pjsip_tx_data));
tdata->pool = pool;
tdata->mgr = mgr;
- sprintf(tdata->obj_name,"txd%p", tdata);
+ pj_sprintf(tdata->obj_name,"txd%p", tdata);
- tdata->ref_cnt = pj_atomic_create(tdata->pool, 0);
- if (!tdata->ref_cnt) {
+ status = pj_atomic_create(tdata->pool, 0, &tdata->ref_cnt);
+ if (status != PJ_SUCCESS) {
pjsip_endpt_destroy_pool( mgr->endpt, tdata->pool );
- return NULL;
+ return status;
}
-
- return tdata;
+
+ *p_tdata = tdata;
+ return PJ_SUCCESS;
}
/*
@@ -339,7 +358,7 @@ PJ_DEF(void) pjsip_tx_data_add_ref( pjsip_tx_data *tdata )
PJ_DEF(void) pjsip_tx_data_dec_ref( pjsip_tx_data *tdata )
{
pj_assert( pj_atomic_get(tdata->ref_cnt) > 0);
- if (pj_atomic_dec(tdata->ref_cnt) <= 0) {
+ if (pj_atomic_dec_and_get(tdata->ref_cnt) <= 0) {
PJ_LOG(6,(tdata->obj_name, "destroying txdata"));
pj_atomic_destroy( tdata->ref_cnt );
pjsip_endpt_destroy_pool( tdata->mgr->endpt, tdata->pool );
@@ -375,7 +394,7 @@ PJ_DEF(pjsip_transport_type_e) pjsip_get_transport_type_from_flag(unsigned flag)
return PJSIP_TRANSPORT_TCP;
} else
#else
- PJ_UNUSED_ARG(flag)
+ PJ_UNUSED_ARG(flag);
#endif
{
return PJSIP_TRANSPORT_UDP;
@@ -452,7 +471,7 @@ PJ_DEF(void) pjsip_transport_add_ref( pjsip_transport_t * tr )
PJ_DEF(void) pjsip_transport_dec_ref( pjsip_transport_t *tr )
{
pj_assert(tr->ref_cnt > 0);
- if (pj_atomic_dec(tr->ref_cnt) == 0) {
+ if (pj_atomic_dec_and_get(tr->ref_cnt) == 0) {
pj_gettimeofday(&tr->close_time);
tr->close_time.sec += PJSIP_TRANSPORT_CLOSE_TIMEOUT;
}
@@ -461,13 +480,15 @@ PJ_DEF(void) pjsip_transport_dec_ref( pjsip_transport_t *tr )
/*
* Open the underlying transport.
*/
-static pj_sock_t create_socket( pjsip_transport_type_e type,
- pj_sockaddr_in *local )
+static pj_status_t create_socket( pjsip_transport_type_e type,
+ pj_sockaddr_in *local,
+ pj_sock_t *p_sock)
{
int sock_family;
int sock_type;
int sock_proto;
- int len;
+ int len;
+ pj_status_t status;
pj_sock_t sock;
/* Set socket parameters */
@@ -483,30 +504,23 @@ static pj_sock_t create_socket( pjsip_transport_type_e type,
sock_proto = 0;
#endif
} else {
- PJ_LOG(2,("", "create_socket: unsupported transport type %s",
- get_type_name(type)));
- return PJ_INVALID_SOCKET;
+ return PJ_EINVAL;
}
/* Create socket. */
- sock = pj_sock_socket( sock_family, sock_type, sock_proto, PJ_SOCK_ASYNC);
- if (sock == PJ_INVALID_SOCKET) {
- PJ_PERROR((THIS_FILE, "%s socket()", get_type_name(type)));
- return PJ_INVALID_SOCKET;
- }
+ status = pj_sock_socket( sock_family, sock_type, sock_proto, &sock);
+ if (status != PJ_SUCCESS)
+ return status;
/* Bind the socket to the requested address, or if no address is
* specified, let the operating system chooses the address.
*/
if (/*local->sin_addr.s_addr != 0 &&*/ local->sin_port != 0) {
- /* Bind to the requested address. */
- if (pj_sock_bind(sock, local, sizeof(*local)) != 0) {
- PJ_PERROR((THIS_FILE, "bind() to %s %s:%d",
- get_type_name(type),
- pj_sockaddr_get_str_addr(local),
- pj_sockaddr_get_port(local)));
+ /* Bind to the requested address. */
+ status = pj_sock_bind(sock, local, sizeof(*local));
+ if (status != PJ_SUCCESS) {
pj_sock_close(sock);
- return PJ_INVALID_SOCKET;
+ return status;
}
} else if (type == PJSIP_TRANSPORT_UDP) {
/* Only for UDP sockets: bind to any address so that the operating
@@ -515,23 +529,24 @@ static pj_sock_t create_socket( pjsip_transport_type_e type,
* get 0.0.0.0 as local address).
*/
pj_memset(local, 0, sizeof(*local));
- local->sin_family = PJ_AF_INET;
- if (pj_sock_bind(sock, local, sizeof(*local)) != 0) {
- PJ_PERROR((THIS_FILE, "bind() to %s 0.0.0.0:0", get_type_name(type)));
+ local->sin_family = PJ_AF_INET;
+ status = pj_sock_bind(sock, local, sizeof(*local));
+ if (status != PJ_SUCCESS) {
pj_sock_close(sock);
- return PJ_INVALID_SOCKET;
+ return status;
}
/* Get the local address. */
- len = sizeof(pj_sockaddr_in);
- if (pj_sock_getsockname(sock, local, &len)) {
- PJ_PERROR((THIS_FILE, "getsockname()"));
+ len = sizeof(pj_sockaddr_in);
+ status = pj_sock_getsockname(sock, local, &len);
+ if (status != PJ_SUCCESS) {
pj_sock_close(sock);
- return -1;
+ return status;
}
}
-
- return sock;
+
+ *p_sock = sock;
+ return PJ_SUCCESS;
}
/*
@@ -547,21 +562,24 @@ static void destroy_socket( pjsip_transport_t * tr)
/*
* Create a new transport object.
*/
-static pjsip_transport_t* create_transport( pjsip_transport_mgr *mgr,
- pjsip_transport_type_e type,
- pj_sock_t sock_hnd,
- const pj_sockaddr_in *local_addr,
- const pj_sockaddr_in *addr_name)
+static pj_status_t create_transport( pjsip_transport_mgr *mgr,
+ pjsip_transport_type_e type,
+ pj_sock_t sock_hnd,
+ const pj_sockaddr_in *local_addr,
+ const pj_sockaddr_in *addr_name,
+ pjsip_transport_t **p_transport )
{
pj_pool_t *tr_pool=NULL, *rdata_pool=NULL;
- pjsip_transport_t *tr = NULL;
+ pjsip_transport_t *tr = NULL;
+ pj_status_t status;
/* Allocate pool for transport from endpoint. */
tr_pool = pjsip_endpt_create_pool( mgr->endpt,
transport_get_name_format(type),
PJSIP_POOL_LEN_TRANSPORT,
PJSIP_POOL_INC_TRANSPORT );
- if (!tr_pool) {
+ if (!tr_pool) {
+ status = PJ_ENOMEM;
goto on_error;
}
@@ -570,7 +588,8 @@ static pjsip_transport_t* create_transport( pjsip_transport_mgr *mgr,
"prdt%p",
PJSIP_POOL_LEN_RDATA,
PJSIP_POOL_INC_RDATA );
- if (!rdata_pool) {
+ if (!rdata_pool) {
+ status = PJ_ENOMEM;
goto on_error;
}
@@ -582,7 +601,7 @@ static pjsip_transport_t* create_transport( pjsip_transport_mgr *mgr,
tr->sock = sock_hnd;
pj_memcpy(&tr->local_addr, local_addr, sizeof(pj_sockaddr_in));
pj_list_init(&tr->cb_list);
- sprintf(tr->obj_name, transport_get_name_format(type), tr);
+ pj_sprintf(tr->obj_name, transport_get_name_format(type), tr);
if (type != PJSIP_TRANSPORT_UDP) {
tr->flag |= PJSIP_TRANSPORT_RELIABLE;
@@ -594,11 +613,10 @@ static pjsip_transport_t* create_transport( pjsip_transport_mgr *mgr,
}
pj_memcpy(&tr->addr_name, addr_name, sizeof(*addr_name));
- /* Create atomic */
- tr->ref_cnt = pj_atomic_create(tr_pool, 0);
- if (!tr->ref_cnt) {
+ /* Create atomic */
+ status = pj_atomic_create(tr_pool, 0, &tr->ref_cnt);
+ if (status != PJ_SUCCESS)
goto on_error;
- }
/* Init rdata in the transport. */
tr->rdata = pj_pool_alloc(rdata_pool, sizeof(*tr->rdata));
@@ -607,22 +625,20 @@ static pjsip_transport_t* create_transport( pjsip_transport_mgr *mgr,
tr->rdata->transport = tr;
/* Init transport mutex. */
- tr->tr_mutex = pj_mutex_create(tr_pool, "mtr%p", 0);
- if (!tr->tr_mutex) {
- PJ_PERROR((tr->obj_name, "pj_mutex_create()"));
+ status = pj_mutex_create_recursive(tr_pool, "mtr%p", &tr->tr_mutex);
+ if (status != PJ_SUCCESS)
goto on_error;
- }
/* Register to I/O Queue */
- tr->key = pj_ioqueue_register(tr_pool, mgr->ioqueue,
- (pj_oshandle_t)tr->sock, tr,
- &ioqueue_transport_callback);
- if (tr->key == NULL) {
- PJ_PERROR((tr->obj_name, "pj_ioqueue_register()"));
+ status = pj_ioqueue_register_sock( tr_pool, mgr->ioqueue,
+ tr->sock, tr,
+ &ioqueue_transport_callback,
+ &tr->key);
+ if (status != PJ_SUCCESS)
goto on_error;
- }
-
- return tr;
+
+ *p_transport = tr;
+ return PJ_SUCCESS;
on_error:
if (tr && tr->tr_mutex) {
@@ -634,18 +650,18 @@ on_error:
if (rdata_pool) {
pjsip_endpt_destroy_pool(mgr->endpt, rdata_pool);
}
- return NULL;
+ return status;
}
/*
* Destroy transport.
*/
-static void destroy_transport( pjsip_transport_mgr *mgr, pjsip_transport_t *tr )
+static void destroy_transport( pjsip_transport_mgr *mgr, pjsip_transport_t *tr)
{
transport_key hash_key;
/* Remove from I/O queue. */
- pj_ioqueue_unregister( mgr->ioqueue, tr->key );
+ pj_ioqueue_unregister( tr->key );
/* Remove from hash table */
init_key_from_transport(&hash_key, tr);
@@ -668,12 +684,18 @@ static void destroy_transport( pjsip_transport_mgr *mgr, pjsip_transport_t *tr )
}
-static int transport_send_msg( pjsip_transport_t *tr, pjsip_tx_data *tdata,
- const pj_sockaddr_in *addr)
+static pj_status_t transport_send_msg( pjsip_transport_t *tr,
+ pjsip_tx_data *tdata,
+ const pj_sockaddr_in *addr,
+ pj_ssize_t *p_sent)
{
const char *buf = tdata->buf.start;
- int sent;
- int len;
+ pj_ssize_t size;
+ pj_status_t status;
+
+ /* Can only send if tdata is not being sent! */
+ if (pj_ioqueue_is_pending(tr->key, &tdata->op_key))
+ return PJSIP_EPENDINGTX;
/* Allocate buffer if necessary. */
if (tdata->buf.start == NULL) {
@@ -684,34 +706,31 @@ static int transport_send_msg( pjsip_transport_t *tr, pjsip_tx_data *tdata,
/* Print the message if it's not printed */
if (tdata->buf.cur <= tdata->buf.start) {
- len = pjsip_msg_print(tdata->msg, tdata->buf.start,
- tdata->buf.end - tdata->buf.start);
- if (len < 1) {
- return len;
- }
- tdata->buf.cur += len;
- tdata->buf.cur[len] = '\0';
+ size = pjsip_msg_print( tdata->msg, tdata->buf.start,
+ tdata->buf.end - tdata->buf.start);
+ if (size < 0) {
+ return PJSIP_EMSGTOOLONG;
+ }
+ pj_assert(size != 0);
+ tdata->buf.cur += size;
+ tdata->buf.cur[size] = '\0';
}
- /* BUG BUG BUG */
- /* MUST CHECK THAT THE SOCKET IS READY TO SEND (IOQueue)! */
- PJ_TODO(BUG_BUG_BUG___SENDING_DATAGRAM_WHILE_SOCKET_IS_PENDING__)
-
/* Send the message. */
buf = tdata->buf.start;
- len = tdata->buf.cur - tdata->buf.start;
+ size = tdata->buf.cur - tdata->buf.start;
if (tr->type == PJSIP_TRANSPORT_UDP) {
PJ_LOG(4,(tr->obj_name, "sendto %s:%d, %d bytes, data:\n"
"----------- begin msg ------------\n"
"%s"
"------------ end msg -------------",
- pj_sockaddr_get_str_addr(addr),
- pj_sockaddr_get_port(addr),
- len, buf));
-
- sent = pj_ioqueue_sendto( tr->mgr->ioqueue, tr->key,
- buf, len, addr, sizeof(*addr));
+ pj_inet_ntoa(addr->sin_addr),
+ pj_sockaddr_in_get_port(addr),
+ size, buf));
+
+ status = pj_ioqueue_sendto( tr->key, &tdata->op_key,
+ buf, &size, 0, addr, sizeof(*addr));
}
#if PJ_HAS_TCP
else {
@@ -719,40 +738,33 @@ static int transport_send_msg( pjsip_transport_t *tr, pjsip_tx_data *tdata,
"----------- begin msg ------------\n"
"%s"
"------------ end msg -------------",
- len, buf));
+ size, buf));
- sent = pj_ioqueue_write (tr->mgr->ioqueue, tr->key, buf, len);
+ status = pj_ioqueue_send(tr->key, &tdata->op_key, buf, &size, 0);
}
#else
else {
- pj_assert(0);
- sent = -1;
+ pj_assert(!"Unsupported transport");
+ status = PJSIP_EUNSUPTRANSPORT;
}
#endif
-
- if (sent == len || sent == PJ_IOQUEUE_PENDING) {
- return len;
- }
-
- /* On error, clear the flag. */
- PJ_PERROR((tr->obj_name, tr->type == PJSIP_TRANSPORT_UDP ? "pj_ioqueue_sendto()" : "pj_ioqueue_write()"));
- return -1;
+
+ *p_sent = size;
+ return status;
}
/*
* Send a SIP message using the specified transport, to the address specified
* in the outgoing data.
*/
-PJ_DEF(int) pjsip_transport_send_msg( pjsip_transport_t *tr,
- pjsip_tx_data *tdata,
- const pj_sockaddr_in *addr)
+PJ_DEF(pj_status_t) pjsip_transport_send_msg( pjsip_transport_t *tr,
+ pjsip_tx_data *tdata,
+ const pj_sockaddr_in *addr,
+ pj_ssize_t *sent)
{
- int sent;
-
PJ_LOG(5, (tr->obj_name, "pjsip_transport_send_msg(tdata=%s)", tdata->obj_name));
- sent = transport_send_msg(tr, tdata, addr );
- return sent;
+ return transport_send_msg(tr, tdata, addr, sent );
}
///////////////////////////////////////////////////////////////////////////////
@@ -760,44 +772,47 @@ PJ_DEF(int) pjsip_transport_send_msg( pjsip_transport_t *tr,
/*
* Create a new transport manager.
*/
-PJ_DEF(pjsip_transport_mgr*)
-pjsip_transport_mgr_create( pj_pool_t *pool,
- pjsip_endpoint * endpt,
- void (*cb)(pjsip_endpoint*,pjsip_rx_data *) )
+PJ_DEF(pj_status_t) pjsip_transport_mgr_create( pj_pool_t *pool,
+ pjsip_endpoint * endpt,
+ void (*cb)(pjsip_endpoint*,
+ pjsip_rx_data *),
+ pjsip_transport_mgr **p_mgr)
{
pjsip_transport_mgr *mgr;
+ pj_status_t status;
PJ_LOG(5, (LOG_TRANSPORT_MGR, "pjsip_transport_mgr_create()"));
mgr = pj_pool_alloc(pool, sizeof(*mgr));
mgr->endpt = endpt;
mgr->message_callback = cb;
-
+ mgr->send_buf_size = DEFAULT_SO_SNDBUF;
+ mgr->recv_buf_size = DEFAULT_SO_RCVBUF;
+
mgr->transport_table = pj_hash_create(pool, MGR_HASH_TABLE_SIZE);
if (!mgr->transport_table) {
- PJ_LOG(3, (LOG_TRANSPORT_MGR, "error creating transport manager hash table"));
- return NULL;
+ return PJ_ENOMEM;
}
- mgr->ioqueue = pj_ioqueue_create(pool, PJSIP_MAX_TRANSPORTS);
- if (!mgr->ioqueue) {
- PJ_LOG(3, (LOG_TRANSPORT_MGR, "error creating IO queue"));
- return NULL;
+ status = pj_ioqueue_create(pool, PJSIP_MAX_TRANSPORTS, &mgr->ioqueue);
+ if (status != PJ_SUCCESS) {
+ return status;
}
- mgr->mutex = pj_mutex_create(pool, "tmgr%p", 0);
- if (!mgr->mutex) {
- PJ_LOG(3, (LOG_TRANSPORT_MGR, "error creating mutex"));
+ status = pj_mutex_create_recursive(pool, "tmgr%p", &mgr->mutex);
+ if (status != PJ_SUCCESS) {
pj_ioqueue_destroy(mgr->ioqueue);
- return NULL;
+ return status;
}
pj_gettimeofday(&mgr->next_idle_check);
- mgr->next_idle_check.sec += MGR_IDLE_CHECK_INTERVAL;
- return mgr;
+ mgr->next_idle_check.sec += MGR_IDLE_CHECK_INTERVAL;
+
+ *p_mgr = mgr;
+ return status;
}
/*
* Destroy transport manager.
*/
-PJ_DEF(void) pjsip_transport_mgr_destroy( pjsip_transport_mgr *mgr )
+PJ_DEF(pj_status_t) pjsip_transport_mgr_destroy( pjsip_transport_mgr *mgr )
{
pj_hash_iterator_t itr_val;
pj_hash_iterator_t *itr;
@@ -822,7 +837,9 @@ PJ_DEF(void) pjsip_transport_mgr_destroy( pjsip_transport_mgr *mgr )
}
pj_ioqueue_destroy(mgr->ioqueue);
- pj_mutex_unlock(mgr->mutex);
+ pj_mutex_unlock(mgr->mutex);
+
+ return PJ_SUCCESS;
}
/*
@@ -835,62 +852,81 @@ static pj_status_t create_listener( pjsip_transport_mgr *mgr,
const pj_sockaddr_in *addr_name)
{
pjsip_transport_t *tr;
- struct transport_key *hash_key;
- int opt_val;
-
- opt_val = DEFAULT_SO_SNDBUF;
- if (pj_sock_setsockopt( sock_hnd, SOL_SOCKET, SO_SNDBUF, &opt_val, sizeof(opt_val)) != PJ_SUCCESS) {
- PJ_LOG(3, (LOG_TRANSPORT_MGR, "create listener: error setting SNDBUF to %d", DEFAULT_SO_SNDBUF));
- // Just ignore the error.
+ struct transport_key *hash_key;
+ const pj_str_t loopback_addr = { "127.0.0.1", 9 };
+ pj_status_t status;
+
+ if (mgr->send_buf_size != 0) {
+ int opt_val = mgr->send_buf_size;
+ status = pj_sock_setsockopt( sock_hnd, PJ_SOL_SOCKET,
+ PJ_SO_SNDBUF,
+ &opt_val, sizeof(opt_val));
+
+ if (status != PJ_SUCCESS) {
+ return status;
+ }
}
-
- opt_val = DEFAULT_SO_RCVBUF;
- if (pj_sock_setsockopt( sock_hnd, SOL_SOCKET, SO_RCVBUF, &opt_val, sizeof(opt_val)) != PJ_SUCCESS) {
- PJ_LOG(3, (LOG_TRANSPORT_MGR, "create listener: error setting RCVBUF to %d", DEFAULT_SO_SNDBUF));
- // Just ignore the error
+
+ if (mgr->recv_buf_size != 0) {
+ int opt_val = mgr->recv_buf_size;
+ status = pj_sock_setsockopt( sock_hnd, PJ_SOL_SOCKET,
+ PJ_SO_RCVBUF,
+ &opt_val, sizeof(opt_val));
+ if (status != PJ_SUCCESS) {
+ return status;
+ }
}
- tr = create_transport(mgr, type, sock_hnd, local_addr, addr_name);
- if (!tr) {
+ status = create_transport(mgr, type, sock_hnd, local_addr, addr_name, &tr);
+ if (status != PJ_SUCCESS) {
pj_sock_close(sock_hnd);
- return -1;
+ return status;
}
#if PJ_HAS_TCP
if (type == PJSIP_TRANSPORT_TCP) {
- pj_status_t status;
-
- if (pj_sock_listen(tr->sock, BACKLOG) != 0) {
- PJ_PERROR((tr->obj_name, "listen()"));
- destroy_transport(mgr, tr);
- return -1;
- }
- tr->accept_data.addrlen = sizeof(tr->accept_data.local);
- status = pj_ioqueue_accept(mgr->ioqueue, tr->key,
- &tr->accept_data.sock,
- &tr->accept_data.local,
- &tr->accept_data.remote,
- &tr->accept_data.addrlen);
- if (status != PJ_IOQUEUE_PENDING) {
- PJ_PERROR((tr->obj_name, "pj_ioqueue_accept()"));
+
+ status = pj_sock_listen(tr->sock, BACKLOG);
+ if (status != 0) {
destroy_transport(mgr, tr);
- return -1;
+ return status;
}
+
+ /* Discard immediate connections. */
+ do {
+ tr->accept_data.addrlen = sizeof(tr->accept_data.local);
+ status = pj_ioqueue_accept(tr->key, &tr->accept_op,
+ &tr->accept_data.sock,
+ &tr->accept_data.local,
+ &tr->accept_data.remote,
+ &tr->accept_data.addrlen);
+ if (status==PJ_SUCCESS) {
+ pj_sock_close(tr->accept_data.sock);
+ } else if (status != PJ_EPENDING) {
+ destroy_transport(mgr, tr);
+ return status;
+ }
+ } while (status==PJ_SUCCESS);
} else
#endif
- if (type == PJSIP_TRANSPORT_UDP) {
- pj_status_t status;
-
- tr->rdata->addr_len = sizeof(tr->rdata->addr);
- status = pj_ioqueue_recvfrom( mgr->ioqueue, tr->key,
- tr->rdata->packet, PJSIP_MAX_PKT_LEN,
- &tr->rdata->addr,
- &tr->rdata->addr_len);
- if (status != PJ_IOQUEUE_PENDING) {
- PJ_PERROR((tr->obj_name, "pj_ioqueue_recvfrom()"));
- destroy_transport(mgr, tr);
- return -1;
- }
+ if (type == PJSIP_TRANSPORT_UDP) {
+ pj_ssize_t bytes;
+
+ /* Discard immediate data. */
+ do {
+ tr->rdata->addr_len = sizeof(tr->rdata->addr);
+ bytes = PJSIP_MAX_PKT_LEN;
+ status = pj_ioqueue_recvfrom( tr->key, &tr->rdata->op_key,
+ tr->rdata->packet, &bytes, 0,
+ &tr->rdata->addr,
+ &tr->rdata->addr_len);
+ if (status == PJ_SUCCESS) {
+ ;
+ } else if (status != PJ_EPENDING) {
+ destroy_transport(mgr, tr);
+ return status;
+ }
+ } while (status == PJ_SUCCESS);
}
pj_atomic_set(tr->ref_cnt, 1);
@@ -900,26 +936,29 @@ static pj_status_t create_listener( pjsip_transport_mgr *mgr,
/* Set remote address to 127.0.0.1 for UDP socket bound to 127.0.0.1.
* See further comments on struct pjsip_transport_t definition.
- */
- if (type == PJSIP_TRANSPORT_UDP && local_addr->sin_addr.s_addr == inet_addr("127.0.0.1")) {
+ */
+ if (type == PJSIP_TRANSPORT_UDP &&
+ local_addr->sin_addr.s_addr == pj_inet_addr(&loopback_addr).s_addr)
+ {
pj_str_t localaddr = pj_str("127.0.0.1");
- pj_sockaddr_set_str_addr( &tr->remote_addr, &localaddr);
+ pj_sockaddr_in_set_str_addr( &tr->remote_addr, &localaddr);
}
hash_key = pj_pool_alloc(tr->pool, sizeof(transport_key));
init_key_from_transport(hash_key, tr);
pj_mutex_lock(mgr->mutex);
- pj_hash_set(tr->pool, mgr->transport_table, hash_key, sizeof(transport_key), tr);
+ pj_hash_set(tr->pool, mgr->transport_table,
+ hash_key, sizeof(transport_key), tr);
pj_mutex_unlock(mgr->mutex);
PJ_LOG(4,(tr->obj_name, "Listening at %s %s:%d",
get_type_name(tr->type),
- pj_sockaddr_get_str_addr(&tr->local_addr),
- pj_sockaddr_get_port(&tr->local_addr)));
+ pj_inet_ntoa(tr->local_addr.sin_addr),
+ pj_sockaddr_in_get_port(&tr->local_addr)));
PJ_LOG(4,(tr->obj_name, "Listener public address is at %s %s:%d",
get_type_name(tr->type),
- pj_sockaddr_get_str_addr(&tr->addr_name),
- pj_sockaddr_get_port(&tr->addr_name)));
+ pj_inet_ntoa(tr->addr_name.sin_addr),
+ pj_sockaddr_in_get_port(&tr->addr_name)));
return PJ_SUCCESS;
}
@@ -932,12 +971,13 @@ PJ_DEF(pj_status_t) pjsip_create_listener( pjsip_transport_mgr *mgr,
const pj_sockaddr_in *addr_name)
{
pj_sock_t sock_hnd;
+ pj_status_t status;
PJ_LOG(5, (LOG_TRANSPORT_MGR, "pjsip_create_listener(type=%d)", type));
- sock_hnd = create_socket(type, local_addr);
- if (sock_hnd == PJ_INVALID_SOCKET) {
- return -1;
+ status = create_socket(type, local_addr, &sock_hnd);
+ if (status != PJ_SUCCESS) {
+ return status;
}
return create_listener(mgr, type, sock_hnd, local_addr, addr_name);
@@ -950,13 +990,16 @@ PJ_DEF(pj_status_t) pjsip_create_udp_listener( pjsip_transport_mgr *mgr,
pj_sock_t sock,
const pj_sockaddr_in *addr_name)
{
- pj_sockaddr_in local_addr;
+ pj_sockaddr_in local_addr;
+ pj_status_t status;
int addrlen = sizeof(local_addr);
+
+ status = pj_sock_getsockname(sock, (pj_sockaddr_t*)&local_addr, &addrlen);
+ if (status != PJ_SUCCESS)
+ return status;
- if (pj_sock_getsockname(sock, (pj_sockaddr_t*)&local_addr, &addrlen) != 0)
- return -1;
-
- return create_listener(mgr, PJSIP_TRANSPORT_UDP, sock, &local_addr, addr_name);
+ return create_listener(mgr, PJSIP_TRANSPORT_UDP, sock,
+ &local_addr, addr_name);
}
/*
@@ -973,7 +1016,7 @@ PJ_DEF(void) pjsip_transport_get( pjsip_transport_mgr *mgr,
transport_key search_key, *hash_key;
pjsip_transport_t *tr;
pj_sockaddr_in local;
- int sock_hnd;
+ pj_sock_t sock_hnd;
pj_status_t status;
struct transport_callback *cb_rec;
@@ -1029,49 +1072,50 @@ PJ_DEF(void) pjsip_transport_get( pjsip_transport_mgr *mgr,
/* Transport not found. Create new one. */
pj_memset(&local, 0, sizeof(local));
local.sin_family = PJ_AF_INET;
- sock_hnd = create_socket(type, &local);
- if (sock_hnd == PJ_INVALID_SOCKET) {
+ status = create_socket(type, &local, &sock_hnd);
+ if (status != PJ_SUCCESS) {
pj_mutex_unlock(mgr->mutex);
- (*cb_rec->cb)(NULL, cb_rec->token, -1);
+ (*cb_rec->cb)(NULL, cb_rec->token, status);
return;
}
- tr = create_transport(mgr, type, sock_hnd, &local, NULL);
- if (!tr) {
+ status = create_transport(mgr, type, sock_hnd, &local, NULL, &tr);
+ if (status != PJ_SUCCESS) {
pj_mutex_unlock(mgr->mutex);
- (*cb_rec->cb)(NULL, cb_rec->token, -1);
+ (*cb_rec->cb)(NULL, cb_rec->token, status);
return;
}
#if PJ_HAS_TCP
if (type == PJSIP_TRANSPORT_TCP) {
pj_memcpy(&tr->remote_addr, remote, sizeof(pj_sockaddr_in));
- status = pj_ioqueue_connect(mgr->ioqueue, tr->key,
- &tr->remote_addr, sizeof(pj_sockaddr_in));
+ status = pj_ioqueue_connect(tr->key, &tr->remote_addr,
+ sizeof(pj_sockaddr_in));
pj_assert(status != 0);
- if (status != PJ_IOQUEUE_PENDING) {
- PJ_PERROR((tr->obj_name, "pj_ioqueue_connect()"));
+ if (status != PJ_EPENDING) {
+ PJ_TODO(HANDLE_IMMEDIATE_CONNECT);
destroy_transport(mgr, tr);
pj_mutex_unlock(mgr->mutex);
- (*cb_rec->cb)(NULL, cb_rec->token, -1);
+ (*cb_rec->cb)(NULL, cb_rec->token, status);
return;
}
} else
#endif
if (type == PJSIP_TRANSPORT_UDP) {
- int len;
+ pj_ssize_t size;
do {
- tr->rdata->addr_len = sizeof(tr->rdata->addr);
- len = pj_ioqueue_recvfrom( mgr->ioqueue, tr->key,
- tr->rdata->packet, PJSIP_MAX_PKT_LEN,
- &tr->rdata->addr,
- &tr->rdata->addr_len);
- pj_assert(len < 0);
- if (len != PJ_IOQUEUE_PENDING) {
- PJ_PERROR((tr->obj_name, "pj_ioqueue_recvfrom()"));
+ tr->rdata->addr_len = sizeof(tr->rdata->addr);
+ size = PJSIP_MAX_PKT_LEN;
+ status = pj_ioqueue_recvfrom( tr->key, &tr->rdata->op_key,
+ tr->rdata->packet, &size, 0,
+ &tr->rdata->addr,
+ &tr->rdata->addr_len);
+ if (status == PJ_SUCCESS)
+ ;
+ else if (status != PJ_EPENDING) {
destroy_transport(mgr, tr);
pj_mutex_unlock(mgr->mutex);
- (*cb_rec->cb)(NULL, cb_rec->token, -1);
+ (*cb_rec->cb)(NULL, cb_rec->token, status);
return;
}
@@ -1082,7 +1126,7 @@ PJ_DEF(void) pjsip_transport_get( pjsip_transport_mgr *mgr,
*/
PJ_TODO(FIXED_BUG_ON_IMMEDIATE_TRANSPORT_DATA);
- } while (len != PJ_IOQUEUE_PENDING);
+ } while (status == PJ_SUCCESS);
//Bug: cb will never be called!
// Must force status to PJ_SUCCESS;
@@ -1092,15 +1136,16 @@ PJ_DEF(void) pjsip_transport_get( pjsip_transport_mgr *mgr,
} else {
pj_mutex_unlock(mgr->mutex);
- (*cb_rec->cb)(NULL, cb_rec->token, -1);
+ (*cb_rec->cb)(NULL, cb_rec->token, PJSIP_EUNSUPTRANSPORT);
return;
}
- pj_assert(status==PJ_IOQUEUE_PENDING || status==PJ_SUCCESS);
+ pj_assert(status==PJ_EPENDING || status==PJ_SUCCESS);
pj_mutex_lock(tr->tr_mutex);
hash_key = pj_pool_alloc(tr->pool, sizeof(transport_key));
pj_memcpy(hash_key, &search_key, sizeof(transport_key));
- pj_hash_set(tr->pool, mgr->transport_table, hash_key, sizeof(transport_key), tr);
+ pj_hash_set(tr->pool, mgr->transport_table,
+ hash_key, sizeof(transport_key), tr);
if (status == PJ_SUCCESS) {
pj_mutex_unlock(tr->tr_mutex);
pj_mutex_unlock(mgr->mutex);
@@ -1123,24 +1168,28 @@ static void handle_new_connection( pjsip_transport_mgr *mgr,
pj_status_t status )
{
pjsip_transport_t *tr;
- transport_key *hash_key;
+ transport_key *hash_key;
+ pj_ssize_t size;
pj_assert (listener->type == PJSIP_TRANSPORT_TCP);
if (status != PJ_SUCCESS) {
- PJ_PERROR((listener->obj_name, "accept() returned error"));
- return;
+ PJSIP_ENDPT_LOG_ERROR((mgr->endpt, listener->obj_name, status,
+ "Error in accept() completion"));
+ goto on_return;
}
PJ_LOG(4,(listener->obj_name, "incoming tcp connection from %s:%d",
- pj_sockaddr_get_str_addr(&listener->accept_data.remote),
- pj_sockaddr_get_port(&listener->accept_data.remote)));
-
- tr = create_transport(mgr, listener->type,
- listener->accept_data.sock,
- &listener->accept_data.local,
- NULL);
- if (!tr) {
+ pj_inet_ntoa(listener->accept_data.remote.sin_addr),
+ pj_sockaddr_in_get_port(&listener->accept_data.remote)));
+
+ status = create_transport(mgr, listener->type,
+ listener->accept_data.sock,
+ &listener->accept_data.local,
+ NULL, &tr);
+ if (status != PJ_SUCCESS) {
+ PJSIP_ENDPT_LOG_ERROR((mgr->endpt, listener->obj_name, status,
+ "Error in creating new incoming TCP"));
goto on_return;
}
@@ -1153,32 +1202,40 @@ static void handle_new_connection( pjsip_transport_mgr *mgr,
*/
tr->rdata->addr = listener->accept_data.remote;
tr->rdata->addr_len = listener->accept_data.addrlen;
-
- status = pj_ioqueue_read (mgr->ioqueue, tr->key, tr->rdata->packet, PJSIP_MAX_PKT_LEN);
- if (status != PJ_IOQUEUE_PENDING) {
- PJ_PERROR((tr->obj_name, "pj_ioqueue_read()"));
+
+ size = PJSIP_MAX_PKT_LEN;
+ status = pj_ioqueue_recv(tr->key, &tr->rdata->op_key,
+ tr->rdata->packet, &size, 0);
+ if (status != PJ_EPENDING) {
+ PJSIP_ENDPT_LOG_ERROR((mgr->endpt, listener->obj_name, status,
+ "Error in receiving data"));
+ PJ_TODO(IMMEDIATE_DATA);
destroy_transport(mgr, tr);
goto on_return;
}
- pj_memcpy(&tr->remote_addr, &listener->accept_data.remote, listener->accept_data.addrlen);
+ pj_memcpy(&tr->remote_addr, &listener->accept_data.remote,
+ listener->accept_data.addrlen);
hash_key = pj_pool_alloc(tr->pool, sizeof(transport_key));
init_key_from_transport(hash_key, tr);
pj_mutex_lock(mgr->mutex);
- pj_hash_set(tr->pool, mgr->transport_table, hash_key, sizeof(transport_key), tr);
+ pj_hash_set(tr->pool, mgr->transport_table, hash_key,
+ sizeof(transport_key), tr);
pj_mutex_unlock(mgr->mutex);
on_return:
/* Re-initiate asynchronous accept() */
listener->accept_data.addrlen = sizeof(listener->accept_data.local);
- status = pj_ioqueue_accept(mgr->ioqueue, listener->key,
+ status = pj_ioqueue_accept(listener->key, &listener->accept_op,
&listener->accept_data.sock,
&listener->accept_data.local,
&listener->accept_data.remote,
&listener->accept_data.addrlen);
- if (status != PJ_IOQUEUE_PENDING) {
- PJ_PERROR((listener->obj_name, "pj_ioqueue_accept()"));
+ if (status != PJ_EPENDING) {
+ PJSIP_ENDPT_LOG_ERROR((mgr->endpt, listener->obj_name, status,
+ "Error in receiving data"));
+ PJ_TODO(IMMEDIATE_ACCEPT);
return;
}
}
@@ -1193,8 +1250,9 @@ static void handle_connect_completion( pjsip_transport_mgr *mgr,
{
struct transport_callback new_list;
struct transport_callback *cb_rec;
+ pj_ssize_t recv_size;
- PJ_UNUSED_ARG(mgr)
+ PJ_UNUSED_ARG(mgr);
/* On connect completion, we must call all registered callbacks in
* the transport.
@@ -1221,11 +1279,12 @@ static void handle_connect_completion( pjsip_transport_mgr *mgr,
*/
if (status == PJ_SUCCESS) {
int addrlen = sizeof(tr->local_addr);
- int rc;
- if ((rc=pj_sock_getsockname(tr->sock, (pj_sockaddr_t*)&tr->local_addr, &addrlen)) == 0) {
+
+ status = pj_sock_getsockname(tr->sock,
+ (pj_sockaddr_t*)&tr->local_addr,
+ &addrlen);
+ if (status == PJ_SUCCESS) {
pj_memcpy(&tr->addr_name, &tr->local_addr, sizeof(tr->addr_name));
- } else {
- PJ_LOG(4,(tr->obj_name, "Unable to get local address (getsockname=%d)", rc));
}
}
@@ -1243,15 +1302,18 @@ static void handle_connect_completion( pjsip_transport_mgr *mgr,
/* Success? */
if (status != PJ_SUCCESS) {
- destroy_transport(mgr, tr);
+ destroy_transport(mgr, tr);
+ PJ_TODO(WTF);
return;
}
- /* Initiate read operation to socket. */
- status = pj_ioqueue_read (mgr->ioqueue, tr->key, tr->rdata->packet, PJSIP_MAX_PKT_LEN);
- if (status != PJ_IOQUEUE_PENDING) {
- PJ_PERROR((tr->obj_name, "pj_ioqueue_read()"));
- destroy_transport(mgr, tr);
+ /* Initiate read operation to socket. */
+ recv_size = PJSIP_MAX_PKT_LEN;
+ status = pj_ioqueue_recv( tr->key, &tr->rdata->op_key, tr->rdata->packet,
+ &recv_size, 0);
+ if (status != PJ_EPENDING) {
+ destroy_transport(mgr, tr);
+ PJ_TODO(IMMEDIATE_DATA);
return;
}
}
@@ -1269,7 +1331,6 @@ static void handle_received_data( pjsip_transport_mgr *mgr,
pj_ssize_t size )
{
pjsip_msg *msg;
- pjsip_cid_hdr *call_id;
pjsip_rx_data *rdata = tr->rdata;
pj_pool_t *rdata_pool;
pjsip_hdr *hdr;
@@ -1315,8 +1376,8 @@ static void handle_received_data( pjsip_transport_mgr *mgr,
rdata->packet[rdata->len] = '\0';
/* Get source address and port for logging purpose. */
- src_addr = pj_sockaddr_get_str_addr(&rdata->addr);
- src_port = pj_sockaddr_get_port(&rdata->addr);
+ src_addr = pj_inet_ntoa(rdata->addr.sin_addr);
+ src_port = pj_sockaddr_in_get_port(&rdata->addr);
/* Print the whole data to the log. */
PJ_LOG(4,(tr->obj_name, "%d bytes recvfrom %s:%d:\n"
@@ -1333,15 +1394,15 @@ static void handle_received_data( pjsip_transport_mgr *mgr,
#if PJ_HAS_TCP
/* For TCP transport, check if the whole message has been received. */
if (tr->type != PJSIP_TRANSPORT_UDP) {
- pj_bool_t is_complete;
- is_complete = pjsip_find_msg(rdata->packet, rdata->len, PJ_FALSE, &msg_fragment_size);
- if (!is_complete) {
- if (rdata->len == PJSIP_MAX_PKT_LEN) {
- PJ_LOG(1,(tr->obj_name,
- "Transport buffer full (%d bytes) for TCP socket %s:%d "
- "(probably too many invalid fragments received). "
- "Buffer will be discarded.",
- PJSIP_MAX_PKT_LEN, src_addr, src_port));
+ pj_status_t msg_status;
+ msg_status = pjsip_find_msg(rdata->packet, rdata->len, PJ_FALSE,
+ &msg_fragment_size);
+ if (msg_status != PJ_SUCCESS) {
+ if (rdata->len == PJSIP_MAX_PKT_LEN) {
+ PJSIP_ENDPT_LOG_ERROR((mgr->endpt, tr->obj_name,
+ PJSIP_EOVERFLOW,
+ "Buffer discarded for %s:%d",
+ src_addr, src_port));
goto on_return;
} else {
goto tcp_read_packet;
@@ -1357,36 +1418,21 @@ static void handle_received_data( pjsip_transport_mgr *mgr,
PJ_LOG(5,(tr->obj_name, "Parsing %d bytes from %s:%d", msg_fragment_size,
src_addr, src_port));
- msg = pjsip_parse_msg( rdata->pool, rdata->packet, msg_fragment_size,
- &rdata->parse_err);
+ msg = pjsip_parse_rdata( rdata->packet, msg_fragment_size, rdata);
if (msg == NULL) {
PJ_LOG(3,(tr->obj_name, "Bad message (%d bytes from %s:%d)", msg_fragment_size,
src_addr, src_port));
goto finish_process_fragment;
}
-
- /* Attach newly created message to rdata. */
- rdata->msg = msg;
-
- /* Extract Call-ID, From and To header and tags, topmost Via, and CSeq
- * header from the message.
- */
- call_id = pjsip_msg_find_hdr( msg, PJSIP_H_CALL_ID, NULL);
- rdata->from = pjsip_msg_find_hdr( msg, PJSIP_H_FROM, NULL);
- rdata->to = pjsip_msg_find_hdr( msg, PJSIP_H_TO, NULL);
- rdata->via = pjsip_msg_find_hdr( msg, PJSIP_H_VIA, NULL);
- rdata->cseq = pjsip_msg_find_hdr( msg, PJSIP_H_CSEQ, NULL);
-
- if (call_id == NULL || rdata->from == NULL || rdata->to == NULL ||
- rdata->via == NULL || rdata->cseq == NULL)
+
+ /* Perform basic header checking. */
+ if (rdata->call_id.ptr == NULL || rdata->from == NULL ||
+ rdata->to == NULL || rdata->via == NULL || rdata->cseq == NULL)
{
PJ_LOG(3,(tr->obj_name, "Bad message from %s:%d: missing some header",
src_addr, src_port));
goto finish_process_fragment;
}
- rdata->call_id = call_id->id;
- rdata->from_tag = rdata->from->tag;
- rdata->to_tag = rdata->to->tag;
/* If message is received from address that's different from the sent-by,
* MUST add received parameter to the via.
@@ -1401,14 +1447,14 @@ static void handle_received_data( pjsip_transport_mgr *mgr,
* If message contains "rport" param, put the received port there.
*/
if (rdata->via->rport_param == 0) {
- rdata->via->rport_param = pj_sockaddr_get_port(&rdata->addr);
+ rdata->via->rport_param = pj_sockaddr_in_get_port(&rdata->addr);
}
/* Drop response message if it has more than one Via.
*/
if (msg->type == PJSIP_RESPONSE_MSG) {
hdr = (pjsip_hdr*)rdata->via->next;
- if (hdr) {
+ if (hdr != &rdata->msg->hdr) {
hdr = pjsip_msg_find_hdr(msg, PJSIP_H_VIA, hdr);
if (hdr) {
PJ_LOG(3,(tr->obj_name, "Bad message from %s:%d: "
@@ -1444,10 +1490,12 @@ on_return:
/* Read the next packet. */
rdata->addr_len = sizeof(rdata->addr);
- if (tr->type == PJSIP_TRANSPORT_UDP) {
- pj_ioqueue_recvfrom( tr->mgr->ioqueue, tr->key,
- tr->rdata->packet, PJSIP_MAX_PKT_LEN,
- &rdata->addr, &rdata->addr_len);
+ if (tr->type == PJSIP_TRANSPORT_UDP) {
+ pj_ssize_t size = PJSIP_MAX_PKT_LEN;
+ pj_ioqueue_recvfrom(tr->key, &tr->rdata->op_key,
+ tr->rdata->packet, &size, 0,
+ &rdata->addr, &rdata->addr_len);
+ PJ_TODO(HANDLE_IMMEDIATE_DATA);
}
#if PJ_HAS_TCP
@@ -1455,10 +1503,12 @@ on_return:
label inside the '#if PJ_HAS_TCP' block to avoid 'unreferenced label' warning.
*/
tcp_read_packet:
- if (tr->type == PJSIP_TRANSPORT_TCP) {
- pj_ioqueue_read( tr->mgr->ioqueue, tr->key,
+ if (tr->type == PJSIP_TRANSPORT_TCP) {
+ pj_ssize_t size = PJSIP_MAX_PKT_LEN - tr->rdata->len;
+ pj_ioqueue_recv( tr->key, &tr->rdata->op_key,
tr->rdata->packet + tr->rdata->len,
- PJSIP_MAX_PKT_LEN - tr->rdata->len);
+ &size, 0);
+ PJ_TODO(HANDLE_IMMEDIATE_DATA_1);
}
#endif
}
@@ -1507,7 +1557,9 @@ static void transport_mgr_on_idle( pjsip_transport_mgr *mgr )
pj_mutex_unlock(mgr->mutex);
}
-static void on_ioqueue_read(pj_ioqueue_key_t *key, pj_ssize_t bytes_read)
+static void on_ioqueue_read(pj_ioqueue_key_t *key,
+ pj_ioqueue_op_key_t *op_key,
+ pj_ssize_t bytes_read)
{
pjsip_transport_t *t;
t = pj_ioqueue_get_user_data(key);
@@ -1515,17 +1567,22 @@ static void on_ioqueue_read(pj_ioqueue_key_t *key, pj_ssize_t bytes_read)
handle_received_data( t->mgr, t, bytes_read );
}
-static void on_ioqueue_write(pj_ioqueue_key_t *key, pj_ssize_t bytes_sent)
+static void on_ioqueue_write(pj_ioqueue_key_t *key,
+ pj_ioqueue_op_key_t *op_key,
+ pj_ssize_t bytes_sent)
{
- PJ_UNUSED_ARG(key)
- PJ_UNUSED_ARG(bytes_sent)
+ PJ_UNUSED_ARG(key);
+ PJ_UNUSED_ARG(bytes_sent);
/* Completion of write operation.
* Do nothing.
*/
}
-static void on_ioqueue_accept(pj_ioqueue_key_t *key, int status)
+static void on_ioqueue_accept(pj_ioqueue_key_t *key,
+ pj_ioqueue_op_key_t *op_key,
+ pj_sock_t newsock,
+ int status)
{
#if PJ_HAS_TCP
pjsip_transport_t *t;
@@ -1533,8 +1590,8 @@ static void on_ioqueue_accept(pj_ioqueue_key_t *key, int status)
handle_new_connection( t->mgr, t, status );
#else
- PJ_UNUSED_ARG(key)
- PJ_UNUSED_ARG(status)
+ PJ_UNUSED_ARG(key);
+ PJ_UNUSED_ARG(status);
#endif
}
@@ -1546,8 +1603,8 @@ static void on_ioqueue_connect(pj_ioqueue_key_t *key, int status)
handle_connect_completion( t->mgr, t, status);
#else
- PJ_UNUSED_ARG(key)
- PJ_UNUSED_ARG(status)
+ PJ_UNUSED_ARG(key);
+ PJ_UNUSED_ARG(status);
#endif
}
diff --git a/pjsip/src/pjsip/sip_uri.c b/pjsip/src/pjsip/sip_uri.c
index 516b78c9..8085f7fc 100644
--- a/pjsip/src/pjsip/sip_uri.c
+++ b/pjsip/src/pjsip/sip_uri.c
@@ -1,11 +1,11 @@
/* $Id$
- *
*/
#include <pjsip/sip_uri.h>
#include <pjsip/sip_msg.h>
-#include <pjsip/print.h>
+#include <pjsip/print_util.h>
#include <pj/string.h>
#include <pj/pool.h>
+#include <pj/assert.h>
#define IS_SIPS(url) ((url)->vptr==&sips_url_vptr)
@@ -68,13 +68,13 @@ static pjsip_uri_vptr name_addr_vptr =
static const pj_str_t *pjsip_url_get_scheme(const pjsip_url *url)
{
- PJ_UNUSED_ARG(url)
+ PJ_UNUSED_ARG(url);
return &sip_str;
}
static const pj_str_t *pjsips_url_get_scheme(const pjsip_url *url)
{
- PJ_UNUSED_ARG(url)
+ PJ_UNUSED_ARG(url);
return &sips_str;
}
@@ -253,7 +253,7 @@ static int pjsip_url_compare( pjsip_uri_context_e context,
return -1;
}
- if (strcmp(str_url1, str_url2)) {
+ if (pj_native_strcmp(str_url1, str_url2)) {
/* Not equal */
return -1;
}
diff --git a/pjsip/src/pjsua/getopt.c b/pjsip/src/pjsua/getopt.c
index caa8920f..5d4689cf 100644
--- a/pjsip/src/pjsua/getopt.c
+++ b/pjsip/src/pjsua/getopt.c
@@ -278,7 +278,7 @@ static char *posixly_correct;
On some systems, it contains special magic macros that don't work
in GCC. */
#include <string.h>
-#define my_index strchr
+#define my_index pj_native_strchr
#else
static char *
@@ -644,7 +644,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
then exchange with previous non-options as if it were an option,
then skip everything else like a non-option. */
- if (optind != argc && !strcmp (argv[optind], "--"))
+ if (optind != argc && !pj_native_strcmp(argv[optind], "--"))
{
optind++;
diff --git a/pjsip/src/pjsua/main.c b/pjsip/src/pjsua/main.c
index c04d1a22..a8a0f49a 100644
--- a/pjsip/src/pjsua/main.c
+++ b/pjsip/src/pjsua/main.c
@@ -250,7 +250,7 @@ static void pres_on_received_request(pjsip_presentity *pres, pjsip_rx_data *rdat
urllen = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, rdata->from->uri, url, sizeof(url)-1);
if (urllen < 1) {
- strcpy(url, "<unknown>");
+ pj_native_strcpy(url, "<unknown>");
} else {
url[urllen] = '\0';
}
@@ -1103,7 +1103,7 @@ static pj_status_t init_stack()
}
if (global.user_id[0]=='\0') {
- strcpy(global.user_id, "user");
+ pj_native_strcpy(global.user_id, "user");
}
/* build contact */
@@ -1233,12 +1233,12 @@ static int on_incoming_im_msg(pjsip_rx_data *rdata)
len = pjsip_uri_print( PJSIP_URI_IN_CONTACT_HDR,
rdata->from->uri, from, sizeof(from));
if (len > 0) from[len] = '\0';
- else strcpy(from, "<URL too long..>");
+ else pj_native_strcpy(from, "<URL too long..>");
len = pjsip_uri_print( PJSIP_URI_IN_CONTACT_HDR,
rdata->to->uri, to, sizeof(to));
if (len > 0) to[len] = '\0';
- else strcpy(to, "<URL too long..>");
+ else pj_native_strcpy(to, "<URL too long..>");
PJ_LOG(3,(THIS_FILE, "Incoming instant message:"));
diff --git a/pjsip/src/pjsua/misc.c b/pjsip/src/pjsua/misc.c
index 36439ccc..58cc795f 100644
--- a/pjsip/src/pjsua/misc.c
+++ b/pjsip/src/pjsua/misc.c
@@ -341,7 +341,7 @@ static int parse_args(pj_pool_t *pool, int argc, char *argv[])
global.cred_info[0].data = pj_str(optarg);
break;
case OPT_USE_STUN1: /* STUN server 1 */
- p = strchr(optarg, ':');
+ p = pj_native_strchr(optarg, ':');
if (p) {
*p = '\0';
global.stun_srv1 = pj_str(optarg);
@@ -356,7 +356,7 @@ static int parse_args(pj_pool_t *pool, int argc, char *argv[])
}
break;
case OPT_USE_STUN2: /* STUN server 2 */
- p = strchr(optarg, ':');
+ p = pj_native_strchr(optarg, ':');
if (p) {
*p = '\0';
global.stun_srv2 = pj_str(optarg);