diff options
author | Benny Prijono <bennylp@teluu.com> | 2005-11-11 19:01:31 +0000 |
---|---|---|
committer | Benny Prijono <bennylp@teluu.com> | 2005-11-11 19:01:31 +0000 |
commit | 0b9e388f7f10dac01d5134ed6c1b24695810874e (patch) | |
tree | f01b4f05e8d074a8dba14a96b93803fd6797c105 | |
parent | 0bc0f9112ac6319d7ce8662de86d6c076bd4b1e3 (diff) |
First clean compile of pjsip
git-svn-id: http://svn.pjsip.org/repos/pjproject/main@43 74dad513-b988-da41-8d7b-12977e46ad98
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, ¶m_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); |