initial import

git-svn-id: https://svn.pjsip.org/repos/pjproject/main@1 74dad513-b988-da41-8d7b-12977e46ad98
diff --git a/pjlib/include/pj/addr_resolv.h b/pjlib/include/pj/addr_resolv.h
new file mode 100644
index 0000000..2daf073
--- /dev/null
+++ b/pjlib/include/pj/addr_resolv.h
@@ -0,0 +1,76 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/addr_resolv.h 2     10/14/05 12:25a Bennylp $ */

+

+#ifndef __PJ_ADDR_RESOLV_H__

+#define __PJ_ADDR_RESOLV_H__

+

+/**

+ * @file addr_resolv.h

+ * @brief Address resolve (pj_gethostbyname()).

+ */

+

+#include <pj/types.h>

+

+PJ_BEGIN_DECL

+

+/**

+ * @defgroup pj_addr_resolve Address Resolution

+ * @ingroup PJ_IO

+ * @{

+ *

+ * This module provides function to resolve Internet address of the

+ * specified host name. To resolve a particular host name, application

+ * can just call #pj_gethostbyname().

+ *

+ * Example:

+ * <pre>

+ *   ...

+ *   pj_hostent he;

+ *   pj_status_t rc;

+ *   pj_str_t host = pj_str("host.example.com");

+ *   

+ *   rc = pj_gethostbyname( &host, &he);

+ *   if (rc != PJ_SUCCESS) {

+ *      char errbuf[80];

+ *      pj_strerror( rc, errbuf, sizeof(errbuf));

+ *      PJ_LOG(2,("sample", "Unable to resolve host, error=%s", errbuf));

+ *      return rc;

+ *   }

+ *

+ *   // process address...

+ *   addr.sin_addr.s_addr = *(pj_uint32_t*)he.h_addr;

+ *   ...

+ * </pre>

+ *

+ * It's pretty simple really...

+ */

+

+/** This structure describes an Internet host address. */

+typedef struct pj_hostent

+{

+    char    *h_name;		/**< The official name of the host. */

+    char   **h_aliases;		/**< Aliases list. */

+    int	     h_addrtype;	/**< Host address type. */

+    int	     h_length;		/**< Length of address. */

+    char   **h_addr_list;	/**< List of addresses. */

+} pj_hostent;

+

+/** Shortcut to h_addr_list[0] */

+#define h_addr h_addr_list[0]

+

+/**

+ * This function fills the structure of type pj_hostent for a given host name.

+ *

+ * @param name	    Host name, or IPv4 or IPv6 address in standard dot notation.

+ * @param he	    The pj_hostent structure to be filled.

+ *

+ * @return	    PJ_SUCCESS, or the appropriate error codes.

+ */ 

+PJ_DECL(pj_status_t) pj_gethostbyname(const pj_str_t *name, pj_hostent *he);

+

+

+/** @} */

+

+PJ_END_DECL

+

+#endif	/* __PJ_ADDR_RESOLV_H__ */

+

diff --git a/pjlib/include/pj/array.h b/pjlib/include/pj/array.h
new file mode 100644
index 0000000..bdc83d9
--- /dev/null
+++ b/pjlib/include/pj/array.h
@@ -0,0 +1,78 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/array.h 7     10/14/05 12:25a Bennylp $ */

+#ifndef __PJ_ARRAY_H__

+#define __PJ_ARRAY_H__

+

+/**

+ * @file array.h

+ * @brief PJLIB Array helper.

+ */

+#include <pj/types.h>

+

+PJ_BEGIN_DECL

+

+/**

+ * @defgroup PJ_ARRAY Array helper.

+ * @ingroup PJ_DS

+ * @{

+ *

+ * This module provides helper to manipulate array of elements of any size.

+ * It provides most used array operations such as insert, erase, and search.

+ */

+

+/**

+ * Insert value to the array at the given position, and rearrange the

+ * remaining nodes after the position.

+ *

+ * @param array	    the array.

+ * @param elem_size the size of the individual element.

+ * @param count	    the current number of elements in the array.

+ * @param pos	    the position where the new element is put.

+ * @param value	    the value to copy to the new element.

+ */

+PJ_DECL(void) pj_array_insert( void *array,

+			       unsigned elem_size,

+			       unsigned count,

+			       unsigned pos,

+			       const void *value);

+

+/**

+ * Erase a value from the array at given position, and rearrange the remaining

+ * elements post the erased element.

+ *

+ * @param array	    the array.

+ * @param elem_size the size of the individual element.

+ * @param count	    the current number of elements in the array.

+ * @param pos	    the index/position to delete.

+ */

+PJ_DECL(void) pj_array_erase( void *array,

+			      unsigned elem_size,

+			      unsigned count,

+			      unsigned pos);

+

+/**

+ * Search the first value in the array according to matching function.

+ *

+ * @param array	    the array.

+ * @param elem_size the individual size of the element.

+ * @param count	    the number of elements.

+ * @param matching  the matching function, which MUST return PJ_SUCCESS if 

+ *		    the specified element match.

+ * @param result    the pointer to the value found.

+ *

+ * @return	    PJ_SUCCESS if value is found, otherwise the error code.

+ */

+PJ_DECL(pj_status_t) pj_array_find(   const void *array, 

+				      unsigned elem_size, 

+				      unsigned count, 

+				      pj_status_t (*matching)(const void *value),

+				      void **result);

+

+/**

+ * @}

+ */

+

+PJ_END_DECL

+

+

+#endif	/* __PJ_ARRAY_H__ */

+

diff --git a/pjlib/include/pj/assert.h b/pjlib/include/pj/assert.h
new file mode 100644
index 0000000..7470550
--- /dev/null
+++ b/pjlib/include/pj/assert.h
@@ -0,0 +1,56 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/assert.h 4     10/14/05 12:25a Bennylp $ */

+#ifndef __PJ_ASSERT_H__

+#define __PJ_ASSERT_H__

+

+/**

+ * @file assert.h

+ * @brief Assertion macro pj_assert().

+ */

+

+#include <pj/config.h>

+#include <pj/compat/assert.h>

+

+/**

+ * @defgroup pj_assert Assertion Macro

+ * @ingroup PJ_MISC

+ * @{

+ *

+ * Assertion and other helper macros for sanity checking.

+ */

+

+/**

+ * @hideinitializer

+ * Check during debug build that an expression is true. If the expression

+ * computes to false during run-time, then the program will stop at the

+ * offending statements.

+ * For release build, this macro will not do anything.

+ *

+ * @param expr	    The expression to be evaluated.

+ */

+#define pj_assert(expr)   assert(expr)

+

+

+/**

+ * @hideinitializer

+ * If #PJ_ENABLE_EXTRA_CHECK is declared and non-zero, then 

+ * #PJ_ASSERT_RETURN macro will evaluate the expression in @a expr during

+ * run-time. If the expression yields false, assertion will be triggered

+ * and the current function will return with the specified return value.

+ *

+ * If #PJ_ENABLE_EXTRA_CHECK is not declared or is zero, then no run-time

+ * checking will be performed. The macro simply evaluates to pj_assert(expr).

+ */

+#if defined(PJ_ENABLE_EXTRA_CHECK) && PJ_ENABLE_EXTRA_CHECK != 0

+#   define PJ_ASSERT_RETURN(expr,retval)    \

+	    do { \

+		pj_assert(expr); \

+		if (!(expr)) return retval; \

+	    } while (0)

+#else

+#   define PJ_ASSERT_RETURN(expr,retval)    pj_assert(expr)

+#endif

+

+/** @} */

+

+#endif	/* __PJ_ASSERT_H__ */

+

diff --git a/pjlib/include/pj/compat/assert.h b/pjlib/include/pj/compat/assert.h
new file mode 100644
index 0000000..c3df94e
--- /dev/null
+++ b/pjlib/include/pj/compat/assert.h
@@ -0,0 +1,38 @@
+/* $Header: /pjproject-0.3/pjlib/src/pj/compat/assert.h 3     9/22/05 10:31a Bennylp $ */

+/* $Log: /pjproject-0.3/pjlib/src/pj/compat/assert.h $

+ * 

+ * 3     9/22/05 10:31a Bennylp

+ * Moving all *.h files to include/.

+ * 

+ * 2     9/21/05 1:39p Bennylp

+ * Periodic checkin for backup.

+ * 

+ * 1     9/17/05 10:36a Bennylp

+ * Created.

+ * 

+ */

+#ifndef __PJ_COMPAT_ASSERT_H__

+#define __PJ_COMPAT_ASSERT_H__

+

+/**

+ * @file assert.h

+ * @brief Provides assert() macro.

+ */

+

+#if defined(PJ_HAS_ASSERT_H) && PJ_HAS_ASSERT_H != 0

+#  include <assert.h>

+

+#elif defined(PJ_LINUX_KERNEL) && PJ_LINUX_KERNEL != 0

+#  define assert(expr) do { \

+			if (!(expr)) \

+			  printk("!!ASSERTION FAILED: [%s:%d] \"" #expr "\"\n",\

+				 __FILE__, __LINE__); \

+		       } while (0)

+

+#else

+#  warning "assert() is not implemented"

+#  define assert(expr)

+#endif

+

+#endif	/* __PJ_COMPAT_ASSERT_H__ */

+

diff --git a/pjlib/include/pj/compat/cc_gcc.h b/pjlib/include/pj/compat/cc_gcc.h
new file mode 100644
index 0000000..dcae099
--- /dev/null
+++ b/pjlib/include/pj/compat/cc_gcc.h
@@ -0,0 +1,32 @@
+/* $Header: /pjproject-0.3/pjlib/src/pj/compat/cc_gcc.h 2     9/17/05 10:37a Bennylp $ */

+/* $Log: /pjproject-0.3/pjlib/src/pj/compat/cc_gcc.h $

+ * 

+ * 2     9/17/05 10:37a Bennylp

+ * Major reorganization towards version 0.3.

+ * 

+ */

+#ifndef __PJ_COMPAT_CC_GCC_H__

+#define __PJ_COMPAT_CC_GCC_H__

+

+/**

+ * @file cc_gcc.h

+ * @brief Describes GCC compiler specifics.

+ */

+

+#ifndef __GNUC__

+#  error "This file is only for gcc!"

+#endif

+

+#define PJ_INLINE_SPECIFIER	static inline

+#define PJ_THREAD_FUNC	

+#define PJ_NORETURN		

+#define PJ_ATTR_NORETURN	__attribute__ ((noreturn))

+

+#define PJ_HAS_INT64		1

+

+typedef long long pj_int64_t;

+typedef unsigned long long pj_uint64_t;

+

+

+#endif	/* __PJ_COMPAT_CC_GCC_H__ */

+

diff --git a/pjlib/include/pj/compat/cc_msvc.h b/pjlib/include/pj/compat/cc_msvc.h
new file mode 100644
index 0000000..39f0acd
--- /dev/null
+++ b/pjlib/include/pj/compat/cc_msvc.h
@@ -0,0 +1,40 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/compat/cc_msvc.h 3     10/14/05 12:26a Bennylp $ */

+/* $Log: /pjproject-0.3/pjlib/include/pj/compat/cc_msvc.h $

+ * 

+ * 3     10/14/05 12:26a Bennylp

+ * Finished error code framework, some fixes in ioqueue, etc. Pretty

+ * major.

+ * 

+ * 2     9/17/05 10:37a Bennylp

+ * Major reorganization towards version 0.3.

+ * 

+ */

+#ifndef __PJ_COMPAT_CC_MSVC_H__

+#define __PJ_COMPAT_CC_MSVC_H__

+

+/**

+ * @file cc_msvc.h

+ * @brief Describes Microsoft Visual C compiler specifics.

+ */

+

+#ifndef _MSC_VER

+#  error "This header file is only for Visual C compiler!"

+#endif

+

+#  pragma warning(disable: 4127)	// conditional expression is constant

+#  pragma warning(disable: 4611)	// not wise to mix setjmp with C++

+#  pragma warning(disable: 4514)	// unreferenced inline function has been removed

+#  ifdef __cplusplus

+#    define PJ_INLINE_SPECIFIER	inline

+#  else

+#    define PJ_INLINE_SPECIFIER	static __inline

+#  endif

+#  define PJ_THREAD_FUNC	

+#  define PJ_NORETURN		__declspec(noreturn)

+#  define PJ_ATTR_NORETURN	

+

+#  define PJ_HAS_INT64	1

+typedef __int64 pj_int64_t;

+typedef unsigned __int64 pj_uint64_t;

+

+#endif	/* __PJ_COMPAT_CC_MSVC_H__ */

diff --git a/pjlib/include/pj/compat/ctype.h b/pjlib/include/pj/compat/ctype.h
new file mode 100644
index 0000000..18e8d47
--- /dev/null
+++ b/pjlib/include/pj/compat/ctype.h
@@ -0,0 +1,42 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/compat/ctype.h 3     10/14/05 12:26a Bennylp $ */

+/* $Log: /pjproject-0.3/pjlib/include/pj/compat/ctype.h $

+ * 

+ * 3     10/14/05 12:26a Bennylp

+ * Finished error code framework, some fixes in ioqueue, etc. Pretty

+ * major.

+ * 

+ * 2     9/22/05 10:31a Bennylp

+ * Moving all *.h files to include/.

+ * 

+ * 1     9/17/05 10:36a Bennylp

+ * Created.

+ * 

+ */

+#ifndef __PJ_COMPAT_CTYPE_H__

+#define __PJ_COMPAT_CTYPE_H__

+

+/**

+ * @file ctype.h

+ * @brief Provides ctype function family.

+ */

+

+#if defined(PJ_HAS_CTYPE_H) && PJ_HAS_CTYPE_H != 0

+#  include <ctype.h>

+#else

+#  define isalnum(c)	    (isalpha(c) || isdigit(c))

+#  define isalpha(c)	    (islower(c) || isupper(c))

+#  define isascii(c)	    (((unsigned char)(c))<=0x7f)

+#  define isdigit(c)	    ((c)>='0' && (c)<='9')

+#  define isspace(c)	    ((c)==' '  || (c)=='\t' ||\

+			     (c)=='\n' || (c)=='\r' || (c)=='\v')

+#  define islower(c)	    ((c)>='a' && (c)<='z')

+#  define isupper(c)	    ((c)>='A' && (c)<='Z')

+#  define isxdigit(c)	    (isdigit(c) || (tolower(c)>='a'&&tolower(c)<='f'))

+#  define tolower(c)	    (((c) >= 'A' && (c) <= 'Z') ? (c)+('a'-'A') : (c))

+#  define toupper(c)	    (((c) >= 'a' && (c) <= 'z') ? (c)-('a'-'A') : (c))

+#endif

+

+#define isblank(c)	    (c==' ' || c=='\t')

+

+

+#endif	/* __PJ_COMPAT_CTYPE_H__ */

diff --git a/pjlib/include/pj/compat/errno.h b/pjlib/include/pj/compat/errno.h
new file mode 100644
index 0000000..a0ea2ea
--- /dev/null
+++ b/pjlib/include/pj/compat/errno.h
@@ -0,0 +1,26 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/compat/errno.h 2     10/14/05 12:26a Bennylp $ */

+#ifndef __PJ_COMPAT_ERRNO_H__

+#define __PJ_COMPAT_ERRNO_H__

+

+#if defined(PJ_WIN32) && PJ_WIN32 != 0

+

+    typedef unsigned long pj_os_err_type;

+#   define pj_get_native_os_error()	    GetLastError()

+#   define pj_get_native_netos_error()	    WSAGetLastError()

+

+#elif (defined(PJ_LINUX) && PJ_LINUX != 0) || \

+      (defined(PJ_LINUX_KERNEL) && PJ_LINUX_KERNEL != 0)

+

+    typedef int pj_os_err_type;

+#   define pj_get_native_os_error()	    (errno)

+#   define pj_get_native_netos_error()	    (errno)

+

+#else

+

+#   error "Please define pj_os_err_type for this platform here!"

+

+#endif

+

+

+#endif	/* __PJ_COMPAT_ERRNO_H__ */

+

diff --git a/pjlib/include/pj/compat/high_precision.h b/pjlib/include/pj/compat/high_precision.h
new file mode 100644
index 0000000..2004fb2
--- /dev/null
+++ b/pjlib/include/pj/compat/high_precision.h
@@ -0,0 +1,83 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/compat/high_precision.h 3     10/29/05 11:51a Bennylp $ */

+#ifndef __PJ_COMPAT_HIGH_PRECISION_H__

+#define __PJ_COMPAT_HIGH_PRECISION_H__

+

+

+#if defined(PJ_HAS_FLOATING_POINT) && PJ_HAS_FLOATING_POINT != 0

+    /*

+     * The first choice for high precision math is to use double.

+     */

+#   include <math.h>

+    typedef double pj_highprec_t;

+

+#   define PJ_HIGHPREC_VALUE_IS_ZERO(a)     (a==0)

+#   define pj_highprec_mod(a,b)             (a=fmod(a,b))

+

+#elif defined(PJ_LINUX_KERNEL) && PJ_LINUX_KERNEL != 0

+

+#   include <asm/div64.h>

+    

+    typedef pj_int64_t pj_highprec_t;

+

+#   define pj_highprec_div(a1,a2)   do_div(a1,a2)

+#   define pj_highprec_mod(a1,a2)   (a1=do_mod(a1, a2))

+

+    PJ_INLINE(pj_int64_t) do_mod( pj_int64_t a1, pj_int64_t a2)

+    {

+	return do_div(a1,a2);

+    }

+    

+    

+#elif defined(PJ_HAS_INT64) && PJ_HAS_INT64 != 0

+    /*

+     * Next choice is to use 64-bit arithmatics.

+     */

+    typedef pj_int64_t pj_highprec_t;

+

+#else

+    /*

+     * Last, fallback to 32-bit arithmetics.

+     */

+    typedef pj_int32_t pj_highprec_t;

+

+#endif

+

+/**

+ * @def pj_highprec_mul

+ * pj_highprec_mul(a1, a2) - High Precision Multiplication

+ * Multiply a1 and a2, and store the result in a1.

+ */

+#ifndef pj_highprec_mul

+#   define pj_highprec_mul(a1,a2)   (a1 = a1 * a2)

+#endif

+

+/**

+ * @def pj_highprec_div

+ * pj_highprec_div(a1, a2) - High Precision Division

+ * Divide a2 from a1, and store the result in a1.

+ */

+#ifndef pj_highprec_div

+#   define pj_highprec_div(a1,a2)   (a1 = a1 / a2)

+#endif

+

+/**

+ * @def pj_highprec_mod

+ * pj_highprec_mod(a1, a2) - High Precision Modulus

+ * Get the modulus a2 from a1, and store the result in a1.

+ */

+#ifndef pj_highprec_mod

+#   define pj_highprec_mod(a1,a2)   (a1 = a1 % a2)

+#endif

+

+

+/**

+ * @def PJ_HIGHPREC_VALUE_IS_ZERO(a)

+ * Test if the specified high precision value is zero.

+ */

+#ifndef PJ_HIGHPREC_VALUE_IS_ZERO

+#   define PJ_HIGHPREC_VALUE_IS_ZERO(a)     (a==0)

+#endif

+

+

+#endif	/* __PJ_COMPAT_HIGH_PRECISION_H__ */

+

diff --git a/pjlib/include/pj/compat/m_alpha.h b/pjlib/include/pj/compat/m_alpha.h
new file mode 100644
index 0000000..a112e0c
--- /dev/null
+++ b/pjlib/include/pj/compat/m_alpha.h
@@ -0,0 +1,23 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/compat/m_alpha.h 1     10/29/05 5:23p Bennylp $ */

+/* 

+ * $Log: /pjproject-0.3/pjlib/include/pj/compat/m_alpha.h $

+ * 

+ * 1     10/29/05 5:23p Bennylp

+ * Created.

+ * 

+ */

+#ifndef __PJ_COMPAT_M_ALPHA_H__

+#define __PJ_COMPAT_M_ALPHA_H__

+

+/**

+ * @file m_alpha.h

+ * @brief Describes Alpha processor family specifics.

+ */

+

+#define PJ_HAS_PENTIUM		0

+#define PJ_IS_LITTLE_ENDIAN	1

+#define PJ_IS_BIG_ENDIAN	0

+

+

+#endif	/* __PJ_COMPAT_M_ALPHA_H__ */

+

diff --git a/pjlib/include/pj/compat/m_i386.h b/pjlib/include/pj/compat/m_i386.h
new file mode 100644
index 0000000..2c9ef26
--- /dev/null
+++ b/pjlib/include/pj/compat/m_i386.h
@@ -0,0 +1,26 @@
+/* $Header: /pjproject-0.3/pjlib/src/pj/compat/m_i386.h 3     9/21/05 1:39p Bennylp $ */

+/* $Log: /pjproject-0.3/pjlib/src/pj/compat/m_i386.h $

+ * 

+ * 3     9/21/05 1:39p Bennylp

+ * Periodic checkin for backup.

+ * 

+ * 2     9/17/05 10:37a Bennylp

+ * Major reorganization towards version 0.3.

+ * 

+ */

+#ifndef __PJ_COMPAT_M_i386_H__

+#define __PJ_COMPAT_M_i386_H__

+

+/**

+ * @file m_i386.h

+ * @brief Describes Intel i386 family processor specifics.

+ */

+

+#define PJ_M_I386		1

+

+#define PJ_HAS_PENTIUM		1

+#define PJ_IS_LITTLE_ENDIAN	1

+#define PJ_IS_BIG_ENDIAN	0

+

+

+#endif	/* __PJ_COMPAT_M_i386_H__ */

diff --git a/pjlib/include/pj/compat/m_m68k.h b/pjlib/include/pj/compat/m_m68k.h
new file mode 100644
index 0000000..5cdcde5
--- /dev/null
+++ b/pjlib/include/pj/compat/m_m68k.h
@@ -0,0 +1,21 @@
+/* $Header: /pjproject-0.3/pjlib/src/pj/compat/m_m68k.h 2     9/17/05 10:37a Bennylp $ */

+/* $Log: /pjproject-0.3/pjlib/src/pj/compat/m_m68k.h $

+ * 

+ * 2     9/17/05 10:37a Bennylp

+ * Major reorganization towards version 0.3.

+ * 

+ */

+#ifndef __PJ_COMPAT_M_M68K_H__

+#define __PJ_COMPAT_M_M68K_H__

+

+/**

+ * @file m_m68k.h

+ * @brief Describes Motorola m68k family processor specifics.

+ */

+

+#define PJ_HAS_PENTIUM		0

+#define PJ_IS_LITTLE_ENDIAN	1

+#define PJ_IS_BIG_ENDIAN	0

+

+

+#endif	/* __PJ_COMPAT_M_M68K_H__ */

diff --git a/pjlib/include/pj/compat/malloc.h b/pjlib/include/pj/compat/malloc.h
new file mode 100644
index 0000000..b5a8126
--- /dev/null
+++ b/pjlib/include/pj/compat/malloc.h
@@ -0,0 +1,25 @@
+/* $Header: /pjproject-0.3/pjlib/src/pj/compat/malloc.h 2     9/17/05 10:37a Bennylp $ */

+/* $Log: /pjproject-0.3/pjlib/src/pj/compat/malloc.h $

+ * 

+ * 2     9/17/05 10:37a Bennylp

+ * Major reorganization towards version 0.3.

+ * 

+ * 1     9/16/05 10:02p Bennylp

+ * Created.

+ * 

+ */

+#ifndef __PJ_COMPAT_MALLOC_H__

+#define __PJ_COMPAT_MALLOC_H__

+

+/**

+ * @file malloc.h

+ * @brief Provides malloc() and free() functions.

+ */

+

+#if defined(PJ_HAS_MALLOC_H) && PJ_HAS_MALLOC_H != 0

+#  include <malloc.h>

+#elif defined(PJ_HAS_STDLIB_H) && PJ_HAS_STDLIB_H != 0

+#  include <stdlib.h>

+#endif

+

+#endif	/* __PJ_COMPAT_MALLOC_H__ */

diff --git a/pjlib/include/pj/compat/os_linux.h b/pjlib/include/pj/compat/os_linux.h
new file mode 100644
index 0000000..2f5e65a
--- /dev/null
+++ b/pjlib/include/pj/compat/os_linux.h
@@ -0,0 +1,69 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/compat/os_linux.h 6     10/29/05 11:51a Bennylp $ */

+/* $Log: /pjproject-0.3/pjlib/include/pj/compat/os_linux.h $

+ * 

+ * 6     10/29/05 11:51a Bennylp

+ * Version 0.3-pre2.

+ * 

+ * 5     10/14/05 12:26a Bennylp

+ * Finished error code framework, some fixes in ioqueue, etc. Pretty

+ * major.

+ * 

+ * 4     9/22/05 10:31a Bennylp

+ * Moving all *.h files to include/.

+ * 

+ * 3     9/21/05 1:39p Bennylp

+ * Periodic checkin for backup.

+ * 

+ * 2     9/17/05 10:37a Bennylp

+ * Major reorganization towards version 0.3.

+ * 

+ */

+#ifndef __PJ_COMPAT_OS_LINUX_H__

+#define __PJ_COMPAT_OS_LINUX_H__

+

+/**

+ * @file os_linux.h

+ * @brief Describes Linux operating system specifics.

+ */

+

+#define PJ_HAS_ARPA_INET_H	    1

+#define PJ_HAS_ASSERT_H		    1

+#define PJ_HAS_CTYPE_H		    1

+#define PJ_HAS_ERRNO_H		    1

+#define PJ_HAS_LINUX_SOCKET_H	    0

+#define PJ_HAS_MALLOC_H		    1

+#define PJ_HAS_NETDB_H		    1

+#define PJ_HAS_NETINET_IN_H	    1

+#define PJ_HAS_SETJMP_H		    1

+#define PJ_HAS_STDARG_H		    1

+#define PJ_HAS_STDDEF_H		    1

+#define PJ_HAS_STDIO_H		    1

+#define PJ_HAS_STDLIB_H		    1

+#define PJ_HAS_STRING_H		    1

+#define PJ_HAS_SYS_IOCTL_H	    1

+#define PJ_HAS_SYS_SELECT_H	    1

+#define PJ_HAS_SYS_SOCKET_H	    1

+#define PJ_HAS_SYS_TIMEB_H	    1

+#define PJ_HAS_SYS_TYPES_H	    1

+#define PJ_HAS_TIME_H		    1

+#define PJ_HAS_UNISTD_H		    1

+

+#define PJ_HAS_MSWSOCK_H	    0

+#define PJ_HAS_WINSOCK_H	    0

+#define PJ_HAS_WINSOCK2_H	    0

+

+#define PJ_SOCK_HAS_INET_ATON	    1

+

+/* Default threading is enabled, unless it's overridden. */

+#ifndef PJ_HAS_THREADS

+#  define PJ_HAS_THREADS	    (1)

+#endif

+

+#define PJ_HAS_HIGH_RES_TIMER	    1

+#define PJ_HAS_MALLOC               1

+#define PJ_OS_HAS_CHECK_STACK	    0

+

+#define PJ_ATOMIC_VALUE_TYPE	    long

+

+#endif	/* __PJ_COMPAT_OS_LINUX_H__ */

+

diff --git a/pjlib/include/pj/compat/os_linux_kernel.h b/pjlib/include/pj/compat/os_linux_kernel.h
new file mode 100644
index 0000000..2ebbb32
--- /dev/null
+++ b/pjlib/include/pj/compat/os_linux_kernel.h
@@ -0,0 +1,86 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/compat/os_linux_kernel.h 4     10/29/05 11:51a Bennylp $ */

+/* $Log: /pjproject-0.3/pjlib/include/pj/compat/os_linux_kernel.h $

+ * 

+ * 4     10/29/05 11:51a Bennylp

+ * Version 0.3-pre2.

+ * 

+ * 3     10/14/05 12:26a Bennylp

+ * Finished error code framework, some fixes in ioqueue, etc. Pretty

+ * major.

+ * 

+ * 2     9/22/05 10:31a Bennylp

+ * Moving all *.h files to include/.

+ * 

+ * 1     9/21/05 1:38p Bennylp

+ * Created.

+ * 

+ */

+#ifndef __PJ_COMPAT_OS_LINUX_KERNEL_H__

+#define __PJ_COMPAT_OS_LINUX_KERNEL_H__

+

+/**

+ * @file os_linux.h

+ * @brief Describes Linux operating system specifics.

+ */

+

+#define PJ_HAS_ARPA_INET_H	    0

+#define PJ_HAS_ASSERT_H		    0

+#define PJ_HAS_CTYPE_H		    0

+#define PJ_HAS_ERRNO_H		    0

+#define PJ_HAS_LINUX_SOCKET_H	    1

+#define PJ_HAS_MALLOC_H		    0

+#define PJ_HAS_NETDB_H		    0

+#define PJ_HAS_NETINET_IN_H	    0

+#define PJ_HAS_SETJMP_H		    0

+#define PJ_HAS_STDARG_H		    1

+#define PJ_HAS_STDDEF_H		    0

+#define PJ_HAS_STDIO_H		    0

+#define PJ_HAS_STDLIB_H		    0

+#define PJ_HAS_STRING_H		    0

+#define PJ_HAS_SYS_IOCTL_H	    0

+#define PJ_HAS_SYS_SELECT_H	    0

+#define PJ_HAS_SYS_SOCKET_H	    0

+#define PJ_HAS_SYS_TIMEB_H	    0

+#define PJ_HAS_SYS_TYPES_H	    0

+#define PJ_HAS_TIME_H		    0

+#define PJ_HAS_UNISTD_H		    0

+

+#define PJ_HAS_MSWSOCK_H	    0

+#define PJ_HAS_WINSOCK_H	    0

+#define PJ_HAS_WINSOCK2_H	    0

+

+#define PJ_SOCK_HAS_INET_ATON	    0

+

+#ifndef PJ_HAS_THREADS

+#  define PJ_HAS_THREADS	    (1)

+#endif

+

+

+/*

+ * Declare __FD_SETSIZE now before including <linux*>.

+ */

+#define __FD_SETSIZE		    PJ_IOQUEUE_MAX_HANDLES

+

+#define NULL			    ((void*)0)

+

+#include <linux/module.h>	/* Needed by all modules */

+#include <linux/kernel.h>	/* Needed for KERN_INFO */

+

+#define __PJ_EXPORT_SYMBOL(a)	    EXPORT_SYMBOL(a);

+

+/*

+ * Override features.

+ */

+#define PJ_HAS_FLOATING_POINT	    0

+#define PJ_HAS_MALLOC               0

+#define PJ_HAS_SEMAPHORE	    0

+#define PJ_HAS_EVENT_OBJ	    0

+#define PJ_HAS_HIGH_RES_TIMER	    1

+#define PJ_OS_HAS_CHECK_STACK	    0

+#define PJ_TERM_HAS_COLOR	    0

+

+#define PJ_ATOMIC_VALUE_TYPE	    int

+#define PJ_THREAD_DESC_SIZE	    128

+

+#endif	/* __PJ_COMPAT_OS_LINUX_KERNEL_H__ */

+

diff --git a/pjlib/include/pj/compat/os_palmos.h b/pjlib/include/pj/compat/os_palmos.h
new file mode 100644
index 0000000..1242bec
--- /dev/null
+++ b/pjlib/include/pj/compat/os_palmos.h
@@ -0,0 +1,54 @@
+/* $Header: /pjproject-0.3/pjlib/src/pj/compat/os_palmos.h 3     9/21/05 1:39p Bennylp $ */

+/* $Log: /pjproject-0.3/pjlib/src/pj/compat/os_palmos.h $

+ * 

+ * 3     9/21/05 1:39p Bennylp

+ * Periodic checkin for backup.

+ * 

+ * 2     9/17/05 10:37a Bennylp

+ * Major reorganization towards version 0.3.

+ * 

+ */

+#ifndef __PJ_COMPAT_OS_PALMOS_H__

+#define __PJ_COMPAT_OS_PALMOS_H__

+

+/**

+ * @file os_palmos.h

+ * @brief Describes PalmOS operating system specifics.

+ */

+

+#define PJ_HAS_ARPA_INET_H	    0

+#define PJ_HAS_ASSERT_H		    1

+#define PJ_HAS_CTYPE_H		    1

+#define PJ_HAS_ERRNO_H		    0

+#define PJ_HAS_MALLOC_H		    1

+#define PJ_HAS_NETDB_H		    0

+#define PJ_HAS_NETINET_IN_H	    0

+#define PJ_HAS_SETJMP_H		    1

+#define PJ_HAS_STDARG_H		    1

+#define PJ_HAS_STDDEF_H		    1

+#define PJ_HAS_STDIO_H		    1

+#define PJ_HAS_STDLIB_H		    1

+#define PJ_HAS_STRING_H		    1

+#define PJ_HAS_SYS_IOCTL_H	    0

+#define PJ_HAS_SYS_SELECT_H	    0

+#define PJ_HAS_SYS_SOCKET_H	    0

+#define PJ_HAS_SYS_TIMEB_H	    0

+#define PJ_HAS_SYS_TYPES_H	    1

+#define PJ_HAS_TIME_H		    1

+#define PJ_HAS_UNISTD_H		    0

+

+#define PJ_HAS_MSWSOCK_H	    0

+#define PJ_HAS_WINSOCK_H	    0

+#define PJ_HAS_WINSOCK2_H	    0

+

+#define PJ_SOCK_HAS_INET_ATON	    0

+

+/* Default threading is enabled, unless it's overridden. */

+#ifndef PJ_HAS_THREADS

+#  define PJ_HAS_THREADS	    (1)

+#endif

+

+#define PJ_HAS_HIGH_RES_TIMER	    1

+#define PJ_OS_HAS_CHECK_STACK	    0

+

+#endif	/* __PJ_COMPAT_OS_PALMOS_H__ */

diff --git a/pjlib/include/pj/compat/os_win32.h b/pjlib/include/pj/compat/os_win32.h
new file mode 100644
index 0000000..d7a92c9
--- /dev/null
+++ b/pjlib/include/pj/compat/os_win32.h
@@ -0,0 +1,72 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/compat/os_win32.h 6     10/29/05 11:51a Bennylp $ */

+/* $Log: /pjproject-0.3/pjlib/include/pj/compat/os_win32.h $

+ * 

+ * 6     10/29/05 11:51a Bennylp

+ * Version 0.3-pre2.

+ * 

+ * 5     10/14/05 12:26a Bennylp

+ * Finished error code framework, some fixes in ioqueue, etc. Pretty

+ * major.

+ * 

+ * 4     9/22/05 10:31a Bennylp

+ * Moving all *.h files to include/.

+ * 

+ * 3     9/21/05 1:39p Bennylp

+ * Periodic checkin for backup.

+ * 

+ * 2     9/17/05 10:37a Bennylp

+ * Major reorganization towards version 0.3.

+ * 

+ */

+#ifndef __PJ_COMPAT_OS_WIN32_H__

+#define __PJ_COMPAT_OS_WIN32_H__

+

+/**

+ * @file os_win32.h

+ * @brief Describes Win32 operating system family specifics.

+ */

+

+#define WIN32_LEAN_AND_MEAN

+#define PJ_WIN32_WINNT		    0x0400

+#define _WIN32_WINNT		    PJ_WIN32_WINNT

+

+#define PJ_HAS_ARPA_INET_H	    0

+#define PJ_HAS_ASSERT_H		    1

+#define PJ_HAS_CTYPE_H		    1

+#define PJ_HAS_ERRNO_H		    0   /* Must be zero, otherwise errno_test() fails. */

+#define PJ_HAS_LINUX_SOCKET_H	    0

+#define PJ_HAS_MALLOC_H		    1

+#define PJ_HAS_NETDB_H		    0

+#define PJ_HAS_NETINET_IN_H	    0

+#define PJ_HAS_SETJMP_H		    1

+#define PJ_HAS_STDARG_H		    1

+#define PJ_HAS_STDDEF_H		    1

+#define PJ_HAS_STDIO_H		    1

+#define PJ_HAS_STDLIB_H		    1

+#define PJ_HAS_STRING_H		    1

+#define PJ_HAS_SYS_IOCTL_H	    0

+#define PJ_HAS_SYS_SELECT_H	    0

+#define PJ_HAS_SYS_SOCKET_H	    0

+#define PJ_HAS_SYS_TIMEB_H	    1

+#define PJ_HAS_SYS_TYPES_H	    1

+#define PJ_HAS_TIME_H		    1

+#define PJ_HAS_UNISTD_H		    0

+

+#define PJ_HAS_MSWSOCK_H	    1

+#define PJ_HAS_WINSOCK_H	    0

+#define PJ_HAS_WINSOCK2_H	    1

+

+#define PJ_SOCK_HAS_INET_ATON	    0

+

+/* Default threading is enabled, unless it's overridden. */

+#ifndef PJ_HAS_THREADS

+#  define PJ_HAS_THREADS	    (1)

+#endif

+

+#define PJ_HAS_HIGH_RES_TIMER	    1

+#define PJ_HAS_MALLOC               1

+#define PJ_OS_HAS_CHECK_STACK	    1

+

+#define PJ_ATOMIC_VALUE_TYPE	    long

+

+#endif	/* __PJ_COMPAT_OS_WIN32_H__ */

diff --git a/pjlib/include/pj/compat/rand.h b/pjlib/include/pj/compat/rand.h
new file mode 100644
index 0000000..31461b3
--- /dev/null
+++ b/pjlib/include/pj/compat/rand.h
@@ -0,0 +1,65 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/compat/rand.h 3     10/14/05 12:26a Bennylp $ */

+/* $Log: /pjproject-0.3/pjlib/include/pj/compat/rand.h $

+ * 

+ * 3     10/14/05 12:26a Bennylp

+ * Finished error code framework, some fixes in ioqueue, etc. Pretty

+ * major.

+ * 

+ * 2     9/21/05 1:39p Bennylp

+ * Periodic checkin for backup.

+ * 

+ * 1     9/17/05 10:36a Bennylp

+ * Created.

+ * 

+ */

+#ifndef __PJ_COMPAT_RAND_H__

+#define __PJ_COMPAT_RAND_H__

+

+/**

+ * @file rand.h

+ * @brief Provides platform_rand() and platform_srand() functions.

+ */

+

+#if defined(PJ_HAS_STDLIB_H) && PJ_HAS_STDLIB_H != 0

+   /*

+    * Use stdlib based rand() and srand().

+    */

+#  include <stdlib.h>

+#  define platform_srand    srand

+#  if defined(RAND_MAX) && RAND_MAX <= 0xFFFF

+       /*

+        * When rand() is only 16 bit strong, double the strength

+	* by calling it twice!

+	*/

+       PJ_INLINE(int) platform_rand(void)

+       {

+	   return ((rand() & 0xFFFF) << 16) | (rand() & 0xFFFF);

+       }

+#  else

+#      define platform_rand rand

+#  endif

+

+#elif defined(PJ_LINUX_KERNEL) && PJ_LINUX_KERNEL != 0

+   /*

+    * Linux kernel mode random number generator.

+    */

+#  include <linux/random.h>

+#  define platform_srand(seed)

+

+   PJ_INLINE(int) platform_rand(void)

+   {

+     int value;

+     get_random_bytes((void*)&value, sizeof(value));

+     return value;

+   }

+

+#else

+#  warning "platform_rand() is not implemented"

+#  define platform_rand()	1

+#  define platform_srand(seed)

+

+#endif

+

+

+#endif	/* __PJ_COMPAT_RAND_H__ */

+

diff --git a/pjlib/include/pj/compat/setjmp.h b/pjlib/include/pj/compat/setjmp.h
new file mode 100644
index 0000000..2bbd0cd
--- /dev/null
+++ b/pjlib/include/pj/compat/setjmp.h
@@ -0,0 +1,89 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/compat/setjmp.h 4     10/14/05 12:26a Bennylp $ */

+/* $Log: /pjproject-0.3/pjlib/include/pj/compat/setjmp.h $

+ * 

+ * 4     10/14/05 12:26a Bennylp

+ * Finished error code framework, some fixes in ioqueue, etc. Pretty

+ * major.

+ * 

+ * 3     9/22/05 10:31a Bennylp

+ * Moving all *.h files to include/.

+ * 

+ * 2     9/21/05 1:39p Bennylp

+ * Periodic checkin for backup.

+ * 

+ * 1     9/17/05 10:36a Bennylp

+ * Created.

+ * 

+ */

+#ifndef __PJ_COMPAT_SETJMP_H__

+#define __PJ_COMPAT_SETJMP_H__

+

+/**

+ * @file setjmp.h

+ * @brief Provides setjmp.h functionality.

+ */

+

+#if defined(PJ_HAS_SETJMP_H) && PJ_HAS_SETJMP_H != 0

+#  include <setjmp.h>

+   typedef jmp_buf pj_jmp_buf;

+#  define pj_setjmp(buf)	setjmp(buf)

+#  define pj_longjmp(buf,d)	longjmp(buf,d)

+

+#elif defined(PJ_LINUX_KERNEL) && PJ_LINUX_KERNEL != 0 && \

+      defined(PJ_M_I386) && PJ_M_I386 != 0

+

+    /*

+     * These are taken from uClibc.

+     * Copyright (C) 2000-2003 Erik Andersen <andersen@uclibc.org>

+     */

+#   if defined __USE_MISC || defined _ASM

+#	define JB_BX	0

+#	define JB_SI	1

+#	define JB_DI	2

+#	define JB_BP	3

+#	define JB_SP	4

+#	define JB_PC	5

+#	define JB_SIZE 24

+#   endif

+

+# ifndef _ASM

+	typedef int __jmp_buf[6];

+

+    /* A `sigset_t' has a bit for each signal.  */

+#   define _SIGSET_NWORDS	(1024 / (8 * sizeof (unsigned long int)))

+    typedef struct __sigset_t_tag

+    {

+	unsigned long int __val[_SIGSET_NWORDS];

+    } __sigset_t;

+

+    /* Calling environment, plus possibly a saved signal mask.  */

+    typedef struct __jmp_buf_tag    /* C++ doesn't like tagless structs.  */

+    {

+	/* NOTE: The machine-dependent definitions of `__sigsetjmp'

+	   assume that a `jmp_buf' begins with a `__jmp_buf' and that

+	   `__mask_was_saved' follows it.  Do not move these members

+	   or add others before it.  */

+	__jmp_buf __jmpbuf;		/* Calling environment.  */

+	int __mask_was_saved;		/* Saved the signal mask?  */

+	// we never saved the mask.

+	__sigset_t __saved_mask;	/* Saved signal mask.  */

+    } jmp_buf[1];

+

+    typedef jmp_buf sigjmp_buf;

+    typedef jmp_buf pj_jmp_buf;

+

+    PJ_DECL(int) pj_setjmp(pj_jmp_buf env);

+    PJ_DECL(void) pj_longjmp(pj_jmp_buf env, int val) __attribute__((noreturn));

+

+# endif   /* _ASM */

+

+#else

+#  warning "setjmp()/longjmp() is not implemented"

+   typedef int pj_jmp_buf[1];

+#  define pj_setjmp(buf)	0

+#  define pj_longjmp(buf,d)	0

+#endif

+

+

+#endif	/* __PJ_COMPAT_SETJMP_H__ */

+

diff --git a/pjlib/include/pj/compat/size_t.h b/pjlib/include/pj/compat/size_t.h
new file mode 100644
index 0000000..39b4166
--- /dev/null
+++ b/pjlib/include/pj/compat/size_t.h
@@ -0,0 +1,23 @@
+/* $Header: /pjproject-0.3/pjlib/src/pj/compat/size_t.h 2     9/21/05 1:39p Bennylp $ */

+/* $Log: /pjproject-0.3/pjlib/src/pj/compat/size_t.h $

+ * 

+ * 2     9/21/05 1:39p Bennylp

+ * Periodic checkin for backup.

+ * 

+ * 1     9/17/05 10:36a Bennylp

+ * Created.

+ * 

+ */

+#ifndef __PJ_COMPAT_SIZE_T_H__

+#define __PJ_COMPAT_SIZE_T_H__

+

+/**

+ * @file size_t.h

+ * @brief Provides size_t type.

+ */

+#if PJ_HAS_STDDEF_H

+# include <stddef.h>

+#endif

+

+#endif	/* __PJ_COMPAT_SIZE_T_H__ */

+

diff --git a/pjlib/include/pj/compat/socket.h b/pjlib/include/pj/compat/socket.h
new file mode 100644
index 0000000..35befae
--- /dev/null
+++ b/pjlib/include/pj/compat/socket.h
@@ -0,0 +1,129 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/compat/socket.h 5     10/29/05 11:51a Bennylp $*/

+/* $Log: /pjproject-0.3/pjlib/include/pj/compat/socket.h $

+ * 

+ * 5     10/29/05 11:51a Bennylp

+ * Version 0.3-pre2.

+ * 

+ * 4     10/14/05 12:26a Bennylp

+ * Finished error code framework, some fixes in ioqueue, etc. Pretty

+ * major.

+ * 

+ * 3     9/21/05 1:39p Bennylp

+ * Periodic checkin for backup.

+ * 

+ * 2     9/17/05 10:37a Bennylp

+ * Major reorganization towards version 0.3.

+ * 

+ */

+#ifndef __PJ_COMPAT_SOCKET_H__

+#define __PJ_COMPAT_SOCKET_H__

+

+/**

+ * @file socket.h

+ * @brief Provides all socket related functions,data types, error codes, etc.

+ */

+

+#if defined(PJ_HAS_WINSOCK_H) && PJ_HAS_WINSOCK_H != 0

+#  include <winsock.h>

+#endif

+

+#if defined(PJ_HAS_WINSOCK2_H) && PJ_HAS_WINSOCK2_H != 0

+#  include <winsock2.h>

+#endif

+

+#if defined(PJ_HAS_SYS_TYPES_H) && PJ_HAS_SYS_TYPES_H != 0

+#  include <sys/types.h>

+#endif

+

+#if defined(PJ_HAS_SYS_SOCKET_H) && PJ_HAS_SYS_SOCKET_H != 0

+#  include <sys/socket.h>

+#endif

+

+#if defined(PJ_HAS_LINUX_SOCKET_H) && PJ_HAS_LINUX_SOCKET_H != 0

+#  include <linux/socket.h>

+#endif

+

+#if defined(PJ_HAS_SYS_SELECT_H) && PJ_HAS_SYS_SELECT_H != 0

+#  include <sys/select.h>

+#endif

+

+#if defined(PJ_HAS_NETINET_IN_H) && PJ_HAS_NETINET_IN_H != 0

+#  include <netinet/in.h>

+#endif

+

+#if defined(PJ_HAS_ARPA_INET_H) && PJ_HAS_ARPA_INET_H != 0

+#  include <arpa/inet.h>

+#endif

+

+#if defined(PJ_HAS_SYS_IOCTL_H) && PJ_HAS_SYS_IOCTL_H != 0

+#  include <sys/ioctl.h>	/* FBIONBIO */

+#endif

+

+#if defined(PJ_HAS_ERRNO_H) && PJ_HAS_ERRNO_H != 0

+#  include <errno.h>

+#endif

+

+#if defined(PJ_HAS_NETDB_H) && PJ_HAS_NETDB_H != 0

+#  include <netdb.h>

+#endif

+

+#if defined(PJ_HAS_UNISTD_H) && PJ_HAS_UNISTD_H != 0

+#  include <unistd.h>

+#endif

+

+

+/*

+ * Define common errors.

+ */

+#ifdef PJ_WIN32

+#  define OSERR_EWOULDBLOCK    WSAEWOULDBLOCK

+#  define OSERR_EINPROGRESS    WSAEINPROGRESS

+#else

+#  define OSERR_EWOULDBLOCK    EWOULDBLOCK

+#  define OSERR_EINPROGRESS    EINPROGRESS

+#endif

+

+

+/*

+ * And undefine this..

+ */

+#undef s_addr

+

+/*

+ * Linux kernel specifics

+ */

+#ifdef PJ_LINUX_KERNEL

+#   include <linux/net.h>

+#   include <asm/ioctls.h>		/* FIONBIO	*/

+#   include <linux/syscalls.h>	/* sys_select() */

+#   include <asm/uaccess.h>	/* set/get_fs()	*/

+

+    typedef int socklen_t;

+#   define getsockopt  sys_getsockopt

+

+    /*

+     * Wrapper for select() in Linux kernel.

+     */

+    PJ_INLINE(int) select(int n, fd_set *inp, fd_set *outp, fd_set *exp,

+		          struct timeval *tvp)

+    {

+        int count;

+        mm_segment_t oldfs = get_fs();

+        set_fs(KERNEL_DS);

+        count = sys_select(n, inp, outp, exp, tvp);

+        set_fs(oldfs);

+        return count;

+    }

+#endif	/* PJ_LINUX_KERNEL */

+

+

+/*

+ * Windows specific

+ */

+#ifdef PJ_WIN32

+    typedef int socklen_t;;

+#endif

+

+

+#endif	/* __PJ_COMPAT_SOCKET_H__ */

+

diff --git a/pjlib/include/pj/compat/sprintf.h b/pjlib/include/pj/compat/sprintf.h
new file mode 100644
index 0000000..7ecc929
--- /dev/null
+++ b/pjlib/include/pj/compat/sprintf.h
@@ -0,0 +1,31 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/compat/sprintf.h 2     10/14/05 12:26a Bennylp $ */

+/* $Log: /pjproject-0.3/pjlib/include/pj/compat/sprintf.h $

+ * 

+ * 2     10/14/05 12:26a Bennylp

+ * Finished error code framework, some fixes in ioqueue, etc. Pretty

+ * major.

+ * 

+ * 1     9/17/05 10:36a Bennylp

+ * Created.

+ * 

+ */

+#ifndef __PJ_COMPAT_SPRINTF_H__

+#define __PJ_COMPAT_SPRINTF_H__

+

+/**

+ * @file sprintf.h

+ * @brief Provides sprintf() and snprintf() functions.

+ */

+

+#if defined(PJ_HAS_STDIO_H) && PJ_HAS_STDIO_H != 0

+#  include <stdio.h>

+#endif

+

+#if defined(_MSC_VER)

+#  define snprintf	_snprintf

+#endif

+

+#define pj_sprintf      sprintf

+#define pj_snprintf	snprintf

+

+#endif	/* __PJ_COMPAT_SPRINTF_H__ */

diff --git a/pjlib/include/pj/compat/stdarg.h b/pjlib/include/pj/compat/stdarg.h
new file mode 100644
index 0000000..574cabb
--- /dev/null
+++ b/pjlib/include/pj/compat/stdarg.h
@@ -0,0 +1,20 @@
+/* $Header: /pjproject-0.3/pjlib/src/pj/compat/stdarg.h 1     9/17/05 10:36a Bennylp $ */

+/* $Log: /pjproject-0.3/pjlib/src/pj/compat/stdarg.h $

+ * 

+ * 1     9/17/05 10:36a Bennylp

+ * Created.

+ * 

+ */

+#ifndef __PJ_COMPAT_STDARG_H__

+#define __PJ_COMPAT_STDARG_H__

+

+/**

+ * @file stdarg.h

+ * @brief Provides stdarg functionality.

+ */

+

+#if defined(PJ_HAS_STDARG_H) && PJ_HAS_STDARG_H != 0

+#  include <stdarg.h>

+#endif

+

+#endif	/* __PJ_COMPAT_STDARG_H__ */

diff --git a/pjlib/include/pj/compat/stdfileio.h b/pjlib/include/pj/compat/stdfileio.h
new file mode 100644
index 0000000..40b0c34
--- /dev/null
+++ b/pjlib/include/pj/compat/stdfileio.h
@@ -0,0 +1,20 @@
+/* $Header: /pjproject-0.3/pjlib/src/pj/compat/stdfileio.h 1     9/17/05 10:36a Bennylp $ */

+/* $Log: /pjproject-0.3/pjlib/src/pj/compat/stdfileio.h $

+ * 

+ * 1     9/17/05 10:36a Bennylp

+ * Created.

+ * 

+ */

+#ifndef __PJ_COMPAT_STDFILEIO_H__

+#define __PJ_COMPAT_STDFILEIO_H__

+

+/**

+ * @file stdfileio.h

+ * @brief Compatibility for ANSI file I/O like fputs, fflush, etc.

+ */

+

+#if defined(PJ_HAS_STDIO_H) && PJ_HAS_STDIO_H != 0

+#  include <stdio.h>

+#endif

+

+#endif	/* __PJ_COMPAT_STDFILEIO_H__ */

diff --git a/pjlib/include/pj/compat/string.h b/pjlib/include/pj/compat/string.h
new file mode 100644
index 0000000..86c8bd6
--- /dev/null
+++ b/pjlib/include/pj/compat/string.h
@@ -0,0 +1,41 @@
+/* $Header: /pjproject-0.3/pjlib/src/pj/compat/string.h 3     9/22/05 10:31a Bennylp $ */

+/* $Log: /pjproject-0.3/pjlib/src/pj/compat/string.h $

+ * 

+ * 3     9/22/05 10:31a Bennylp

+ * Moving all *.h files to include/.

+ * 

+ * 2     9/21/05 1:39p Bennylp

+ * Periodic checkin for backup.

+ * 

+ * 1     9/17/05 10:36a Bennylp

+ * Created.

+ * 

+ */

+#ifndef __PJ_COMPAT_STRING_H__

+#define __PJ_COMPAT_STRING_H__

+

+/**

+ * @file string.h

+ * @brief Provides string manipulation functions found in ANSI string.h.

+ */

+

+#if defined(PJ_HAS_STRING_H) && PJ_HAS_STRING_H != 0

+#  include <string.h>

+#else

+

+    PJ_DECL(int) strcasecmp(const char *s1, const char *s2);

+    PJ_DECL(int) strncasecmp(const char *s1, const char *s2, int len);

+

+#endif

+

+#if defined(_MSC_VER)

+#  define strcasecmp	stricmp

+#  define strncasecmp	strnicmp

+#  define snprintf	_snprintf

+#else

+#  define stricmp	strcasecmp

+#  define strnicmp	strncasecmp

+#endif

+

+

+#endif	/* __PJ_COMPAT_STRING_H__ */

diff --git a/pjlib/include/pj/compat/time.h b/pjlib/include/pj/compat/time.h
new file mode 100644
index 0000000..45585cb
--- /dev/null
+++ b/pjlib/include/pj/compat/time.h
@@ -0,0 +1,25 @@
+/* $Header: /pjproject-0.3/pjlib/src/pj/compat/time.h 1     9/17/05 10:36a Bennylp $ */

+/* $Log: /pjproject-0.3/pjlib/src/pj/compat/time.h $

+ * 

+ * 1     9/17/05 10:36a Bennylp

+ * Created.

+ * 

+ */

+#ifndef __PJ_COMPAT_TIME_H__

+#define __PJ_COMPAT_TIME_H__

+

+/**

+ * @file time.h

+ * @brief Provides ftime() and localtime() etc functions.

+ */

+

+#if defined(PJ_HAS_TIME_H) && PJ_HAS_TIME_H != 0

+#  include <time.h>

+#endif

+

+#if defined(PJ_HAS_SYS_TIMEB_H) && PJ_HAS_SYS_TIMEB_H != 0

+#  include <sys/timeb.h>

+#endif

+

+

+#endif	/* __PJ_COMPAT_TIME_H__ */

diff --git a/pjlib/include/pj/compat/vsprintf.h b/pjlib/include/pj/compat/vsprintf.h
new file mode 100644
index 0000000..3d2bd34
--- /dev/null
+++ b/pjlib/include/pj/compat/vsprintf.h
@@ -0,0 +1,26 @@
+/* $Header: /pjproject-0.3/pjlib/src/pj/compat/vsprintf.h 1     9/17/05 10:36a Bennylp $ */

+/* $Log: /pjproject-0.3/pjlib/src/pj/compat/vsprintf.h $

+ * 

+ * 1     9/17/05 10:36a Bennylp

+ * Created.

+ * 

+ */

+#ifndef __PJ_COMPAT_VSPRINTF_H__

+#define __PJ_COMPAT_VSPRINTF_H__

+

+/**

+ * @file vsprintf.h

+ * @brief Provides vsprintf and vsnprintf function.

+ */

+

+#if defined(PJ_HAS_STDIO_H) && PJ_HAS_STDIO_H != 0

+#  include <stdio.h>

+#endif

+

+#if defined(_MSC_VER)

+#  define vsnprintf	_vsnprintf	

+#endif

+

+#define pj_vsnprintf	vsnprintf

+

+#endif	/* __PJ_COMPAT_VSPRINTF_H__ */

diff --git a/pjlib/include/pj/config.h b/pjlib/include/pj/config.h
new file mode 100644
index 0000000..3c093b8
--- /dev/null
+++ b/pjlib/include/pj/config.h
@@ -0,0 +1,438 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/config.h 12    10/29/05 10:25p Bennylp $ */

+

+#ifndef __PJ_CONFIG_H__

+#define __PJ_CONFIG_H__

+

+/**

+ * @file config.h

+ * @brief PJLIB Main configuration settings.

+ */

+

+/********************************************************************

+ * Include compiler specific configuration.

+ */

+#if defined(_MSC_VER)

+#  include <pj/compat/cc_msvc.h>

+#elif defined(__GNUC__)

+#  include <pj/compat/cc_gcc.h>

+#else

+#  error "Unknown compiler."

+#endif

+

+

+/********************************************************************

+ * Include target specific configuration.

+ */

+#if defined(PJ_WIN32)

+#  include <pj/compat/os_win32.h>

+#elif defined(PJ_LINUX)

+#  include <pj/compat/os_linux.h>

+#elif defined(PJ_LINUX_KERNEL)

+#  include <pj/compat/os_linux_kernel.h>

+#elif defined(PJ_PALMOS)

+#  include <pj/compat/os_palmos.h>

+#else

+#  error "Please specify target os."

+#endif

+

+

+/********************************************************************

+ * Target machine specific configuration.

+ */

+#if defined (PJ_M_I386) && PJ_M_I386 != 0

+#  include <pj/compat/m_i386.h>

+#elif defined (PJ_M_M68K) && PJ_M_M68K != 0

+#   include <pj/compat/m_m68k.h>

+#elif defined (PJ_M_ALPHA) && PJ_M_ALPHA != 0

+#   include <pj/compat/m_alpha.h>

+#else

+#  error "Please specify target machine."

+#endif

+

+/* Include size_t definition. */

+#include <pj/compat/size_t.h>

+

+/* Include site/user specific configuration to control PJLIB features.

+ * YOU MUST CREATE THIS FILE YOURSELF!!

+ */

+#include <pj/config_site.h>

+

+/********************************************************************

+ * PJLIB Features.

+ */

+

+/* Overrides for DOXYGEN */

+#ifdef DOXYGEN

+#   undef PJ_FUNCTIONS_ARE_INLINED

+#   undef PJ_HAS_FLOATING_POINT

+#   undef PJ_LOG_MAX_LEVEL

+#   undef PJ_LOG_MAX_SIZE

+#   undef PJ_LOG_USE_STACK_BUFFER

+#   undef PJ_TERM_HAS_COLOR

+#   undef PJ_POOL_DEBUG

+#   undef PJ_HAS_TCP

+#   undef PJ_MAX_HOSTNAME

+#   undef PJ_IOQUEUE_MAX_HANDLES

+#   undef FD_SETSIZE

+#   undef PJ_HAS_SEMAPHORE

+#   undef PJ_HAS_EVENT_OBJ

+#   undef PJ_ENABLE_EXTRA_CHECK

+#endif

+

+/**

+ * @defgroup pj_config Build Configuration

+ * @ingroup PJ

+ * @{

+ *

+ * This section contains macros that can set during PJLIB build process

+ * to controll various aspects of the library.

+ *

+ * <b>Note</b>: the values in this page does NOT necessarily reflect to the

+ * macro values during the build process.

+ */

+

+/**

+ * If this macro is set to 1, it will enable some debugging checking

+ * in the library.

+ *

+ * Default: equal to (NOT NDEBUG).

+ */

+#ifndef PJ_DEBUG

+#  ifndef NDEBUG

+#    define PJ_DEBUG		    1

+#  else

+#    define PJ_DEBUG		    0

+#  endif

+#endif

+

+/**

+ * Expand functions in *_i.h header files as inline.

+ *

+ * Default: 0.

+ */

+#ifndef PJ_FUNCTIONS_ARE_INLINED

+#  define PJ_FUNCTIONS_ARE_INLINED  0

+#endif

+

+/**

+ * Use floating point computations in the library.

+ *

+ * Default: 1.

+ */

+#ifndef PJ_HAS_FLOATING_POINT

+#  define PJ_HAS_FLOATING_POINT	    1

+#endif

+

+/**

+ * Declare maximum logging level/verbosity. Lower number indicates higher

+ * importance, with the highest importance has level zero. The least

+ * important level is five in this implementation, but this can be extended

+ * by supplying the appropriate implementation.

+ *

+ * The level conventions:

+ *  - 0: fatal error

+ *  - 1: error

+ *  - 2: warning

+ *  - 3: info

+ *  - 4: debug

+ *  - 5: trace

+ *  - 6: more detailed trace

+ *

+ * Default: 4

+ */

+#ifndef PJ_LOG_MAX_LEVEL

+#  define PJ_LOG_MAX_LEVEL   4

+#endif

+

+/**

+ * Maximum message size that can be sent to output device for each call

+ * to PJ_LOG(). If the message size is longer than this value, it will be cut.

+ * This may affect the stack usage, depending whether PJ_LOG_USE_STACK_BUFFER

+ * flag is set.

+ *

+ * Default: 800

+ */

+#ifndef PJ_LOG_MAX_SIZE

+#  define PJ_LOG_MAX_SIZE	    800

+#endif

+

+/**

+ * Log buffer.

+ * Does the log get the buffer from the stack? (default is yes).

+ * If the value is set to NO, then the buffer will be taken from static

+ * buffer, which in this case will make the log function non-reentrant.

+ *

+ * Default: 1

+ */

+#ifndef PJ_LOG_USE_STACK_BUFFER

+#  define PJ_LOG_USE_STACK_BUFFER   1

+#endif

+

+

+/**

+ * Colorfull terminal (for logging etc).

+ *

+ * Default: 1

+ */

+#ifndef PJ_TERM_HAS_COLOR

+#  define PJ_TERM_HAS_COLOR	    1

+#endif

+

+/**

+ * Pool debugging.

+ *

+ * Default: 0

+ */

+#ifndef PJ_POOL_DEBUG

+#  define PJ_POOL_DEBUG		    0

+#endif

+

+/**

+ * \def PJ_HAS_TCP

+ * Support TCP in the library.

+ * Disabling TCP will reduce the footprint slightly (about 6KB).

+ *

+ * Default: 1

+ */

+#ifndef PJ_HAS_TCP

+#  define PJ_HAS_TCP		    1

+#endif

+

+/**

+ * Maximum hostname length.

+ * Libraries sometimes needs to make copy of an address to stack buffer;

+ * the value here affects the stack usage.

+ *

+ * Default: 128

+ */

+#ifndef PJ_MAX_HOSTNAME

+#  define PJ_MAX_HOSTNAME	    (128)

+#endif

+

+/**

+ * Constants for declaring the maximum handles that can be supported by

+ * a single IOQ framework. This constant might not be relevant to the 

+ * underlying I/O queue impelementation, but still, developers should be 

+ * aware of this constant, to make sure that the program will not break when

+ * the underlying implementation changes.

+ *

+ * For implementation based on select(), the value here will be used as the

+ * maximum number of socket handles passed to select() (i.e. FD_SETSIZE will 

+ * be set to this value).

+ *

+ * Default: 64

+ */

+#ifndef PJ_IOQUEUE_MAX_HANDLES

+#  define PJ_IOQUEUE_MAX_HANDLES    (64)

+#endif

+

+/**

+ * Overrides FD_SETSIZE so it is consistent throughout the library.

+ * OS specific configuration header (compat/os_*) might have declared

+ * FD_SETSIZE, thus we only set if it hasn't been declared.

+ *

+ * Default: #PJ_IOQUEUE_MAX_HANDLES

+ */

+#ifndef FD_SETSIZE

+#  define FD_SETSIZE		    PJ_IOQUEUE_MAX_HANDLES

+#endif

+

+/**

+ * Has semaphore functionality?

+ *

+ * Default: 1

+ */

+#ifndef PJ_HAS_SEMAPHORE

+#  define PJ_HAS_SEMAPHORE	    1

+#endif

+

+

+/**

+ * Event object (for synchronization, e.g. in Win32)

+ *

+ * Default: 1

+ */

+#ifndef PJ_HAS_EVENT_OBJ

+#  define PJ_HAS_EVENT_OBJ	    1

+#endif

+

+

+/**

+ * Enable library's extra check.

+ * If this macro is enabled, #PJ_ASSERT_RETURN macro will expand to

+ * run-time checking. If this macro is disabled, #PJ_ASSERT_RETURN

+ * will simply evaluate to #pj_assert().

+ *

+ * You can disable this macro to reduce size, at the risk of crashes

+ * if invalid value (e.g. NULL) is passed to the library.

+ *

+ * Default: 1

+ */

+#ifndef PJ_ENABLE_EXTRA_CHECK

+#   define PJ_ENABLE_EXTRA_CHECK    1

+#endif

+

+

+/**

+ * Enable name registration for exceptions with #pj_exception_id_alloc().

+ * If this feature is enabled, then the library will keep track of

+ * names associated with each exception ID requested by application via

+ * #pj_exception_id_alloc().

+ *

+ * Disabling this macro will reduce the code and .bss size by a tad bit.

+ * See also #PJ_MAX_EXCEPTION_ID.

+ *

+ * Default: 1

+ */

+#ifndef PJ_HAS_EXCEPTION_NAMES

+#   define PJ_HAS_EXCEPTION_NAMES   1

+#endif

+

+/**

+ * Maximum number of unique exception IDs that can be requested

+ * with #pj_exception_id_alloc(). For each entry, a small record will

+ * be allocated in the .bss segment.

+ *

+ * Default: 16

+ */

+#ifndef PJ_MAX_EXCEPTION_ID

+#   define PJ_MAX_EXCEPTION_ID      16

+#endif

+

+/** @} */

+

+/********************************************************************

+ * General macros.

+ */

+

+/**

+ * @def PJ_INLINE(type)

+ * @param type The return type of the function.

+ * Expand the function as inline.

+ */

+#define PJ_INLINE(type)	  PJ_INLINE_SPECIFIER type

+

+/**

+ * @def PJ_DECL(type)

+ * @param type The return type of the function.

+ * Declare a function.

+ */

+/**

+ * @def PJ_DECL_NO_RETURN(type)

+ * @param type The return type of the function.

+ * Declare a function that will not return.

+ */

+/**

+ * @def PJ_BEGIN_DECL

+ * Mark beginning of declaration section in a header file.

+ */

+/**

+ * @def PJ_END_DECL

+ * Mark end of declaration section in a header file.

+ */

+#ifdef __cplusplus

+#  define PJ_DECL(type)		    type

+#  define PJ_DECL_NO_RETURN(type)   type PJ_NORETURN

+#  define PJ_BEGIN_DECL		    extern "C" {

+#  define PJ_END_DECL		    }

+#else

+#  define PJ_DECL(type)		    extern type

+#  define PJ_DECL_NO_RETURN(type)   PJ_NORETURN type

+#  define PJ_BEGIN_DECL

+#  define PJ_END_DECL

+#endif

+

+/**

+ * @def PJ_DEF(type)

+ * @param type The return type of the function.

+ * Define a function.

+ */

+#define PJ_DEF(type)	  type

+

+/**

+ * @def PJ_EXPORT_SYMBOL(sym)

+ * @param sym The symbol to export.

+ * Export the specified symbol in compilation type that requires export

+ * (e.g. Linux kernel).

+ */

+#ifdef __PJ_EXPORT_SYMBOL

+#  define PJ_EXPORT_SYMBOL(sym)	    __PJ_EXPORT_SYMBOL(sym)

+#else

+#  define PJ_EXPORT_SYMBOL(sym)

+#endif

+

+/**

+ * @def PJ_IDECL(type)

+ * @param type  The function's return type.

+ * Declare a function that may be expanded as inline.

+ */

+/**

+ * @def PJ_IDEF(type)

+ * @param type  The function's return type.

+ * Define a function that may be expanded as inline.

+ */

+

+#if PJ_FUNCTIONS_ARE_INLINED

+#  define PJ_IDECL(type)  PJ_INLINE(type)

+#  define PJ_IDEF(type)   PJ_INLINE(type)

+#else

+#  define PJ_IDECL(type)  PJ_DECL(type)

+#  define PJ_IDEF(type)   PJ_DEF(type)

+#endif

+

+/**

+ * @def PJ_UNUSED_ARG(arg)

+ * @param arg   The argument name.

+ * PJ_UNUSED_ARG prevents warning about unused argument in a function.

+ */

+#define PJ_UNUSED_ARG(arg)  (void)arg

+

+/**

+ * @def PJ_TODO(id)

+ * @param id    Any identifier that will be printed as TODO message.

+ * PJ_TODO macro will display TODO message as warning during compilation.

+ * Example: PJ_TODO(CLEAN_UP_ERROR);

+ */

+#ifndef PJ_TODO

+#  define PJ_TODO(id)	    TODO___##id:

+#endif

+

+

+/********************************************************************

+ * Sanity Checks

+ */

+#ifndef PJ_HAS_HIGH_RES_TIMER

+#  error "PJ_HAS_HIGH_RES_TIMER is not defined!"

+#endif

+

+#if !defined(PJ_HAS_PENTIUM)

+#  error "PJ_HAS_PENTIUM is not defined!"

+#endif

+

+#if !defined(PJ_IS_LITTLE_ENDIAN)

+#  error "PJ_IS_LITTLE_ENDIAN is not defined!"

+#endif

+

+#if !defined(PJ_IS_BIG_ENDIAN)

+#  error "PJ_IS_BIG_ENDIAN is not defined!"

+#endif

+

+

+

+PJ_BEGIN_DECL

+

+/**

+ * PJLIB version string.

+ */

+extern const char *PJ_VERSION;

+

+/**

+ * Dump configuration to log with verbosity equal to info(3).

+ */

+PJ_DECL(void) pj_dump_config(void);

+

+PJ_END_DECL

+

+

+#endif	/* __PJ_CONFIG_H__ */

+

diff --git a/pjlib/include/pj/ctype.h b/pjlib/include/pj/ctype.h
new file mode 100644
index 0000000..943034f
--- /dev/null
+++ b/pjlib/include/pj/ctype.h
@@ -0,0 +1,119 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/ctype.h 4     10/14/05 12:26a Bennylp $ */

+#ifndef __PJ_CTYPE_H__

+#define __PJ_CTYPE_H__

+

+/**

+ * @file ctype.h

+ * @brief C type helper macros.

+ */

+

+#include <pj/compat/ctype.h>

+

+/**

+ * @defgroup pj_ctype ctype - Character Type

+ * @ingroup PJ_MISC

+ * @{

+ *

+ * This module contains several inline functions/macros for testing or

+ * manipulating character types. It is provided in PJLIB because PJLIB

+ * must not depend to LIBC.

+ */

+

+/** 

+ * Returns a non-zero value if either isalpha or isdigit is true for c.

+ * @param c     The integer character to test.

+ * @return      Non-zero value if either isalpha or isdigit is true for c.

+ */

+PJ_INLINE(int) pj_isalnum(int c) { return isalnum(c); }

+

+/** 

+ * Returns a non-zero value if c is a particular representation of an 

+ * alphabetic character.

+ * @param c     The integer character to test.

+ * @return      Non-zero value if c is a particular representation of an 

+ *              alphabetic character.

+ */

+PJ_INLINE(int) pj_isalpha(int c) { return isalpha(c); }

+

+/** 

+ * Returns a non-zero value if c is a particular representation of an 

+ * ASCII character.

+ * @param c     The integer character to test.

+ * @return      Non-zero value if c is a particular representation of 

+ *              an ASCII character.

+ */

+PJ_INLINE(int) pj_isascii(int c) { return isascii(c); }

+

+/** 

+ * Returns a non-zero value if c is a particular representation of 

+ * a decimal-digit character.

+ * @param c     The integer character to test.

+ * @return      Non-zero value if c is a particular representation of 

+ *              a decimal-digit character.

+ */

+PJ_INLINE(int) pj_isdigit(int c) { return isdigit(c); }

+

+/** 

+ * Returns a non-zero value if c is a particular representation of 

+ * a space character (0x09 - 0x0D or 0x20).

+ * @param c     The integer character to test.

+ * @return      Non-zero value if c is a particular representation of 

+ *              a space character (0x09 - 0x0D or 0x20).

+ */

+PJ_INLINE(int) pj_isspace(int c) { return isspace(c); }

+

+/** 

+ * Returns a non-zero value if c is a particular representation of 

+ * a lowercase character.

+ * @param c     The integer character to test.

+ * @return      Non-zero value if c is a particular representation of 

+ *              a lowercase character.

+ */

+PJ_INLINE(int) pj_islower(int c) { return islower(c); }

+

+

+/** 

+ * Returns a non-zero value if c is a particular representation of 

+ * a uppercase character.

+ * @param c     The integer character to test.

+ * @return      Non-zero value if c is a particular representation of 

+ *              a uppercase character.

+ */

+PJ_INLINE(int) pj_isupper(int c) { return isupper(c); }

+

+/**

+ * Returns a non-zero value if c is a particular representation of 

+ * an hexadecimal digit character.

+ * @param c     The integer character to test.

+ * @return      Non-zero value if c is a particular representation of 

+ *              an hexadecimal digit character.

+ */

+PJ_INLINE(int) pj_isxdigit(int c){ return isxdigit(c); }

+

+/**

+ * Returns a non-zero value if c is a either a space (' ') or horizontal

+ * tab ('\\t') character.

+ * @param c     The integer character to test.

+ * @return      Non-zero value if c is a either a space (' ') or horizontal

+ *              tab ('\\t') character.

+ */

+PJ_INLINE(int) pj_isblank(int c) { return isblank(c); }

+

+/**

+ * Converts character to lowercase.

+ * @param c     The integer character to convert.

+ * @return      Lowercase character of c.

+ */

+PJ_INLINE(int) pj_tolower(int c) { return tolower(c); }

+

+/**

+ * Converts character to uppercase.

+ * @param c     The integer character to convert.

+ * @return      Uppercase character of c.

+ */

+PJ_INLINE(int) pj_toupper(int c) { return toupper(c); }

+

+/** @} */

+

+#endif	/* __PJ_CTYPE_H__ */

+

diff --git a/pjlib/include/pj/doxygen.h b/pjlib/include/pj/doxygen.h
new file mode 100644
index 0000000..c673265
--- /dev/null
+++ b/pjlib/include/pj/doxygen.h
@@ -0,0 +1,880 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/doxygen.h 5     10/29/05 10:27p Bennylp $ */

+#ifndef __PJ_DOXYGEN_H__

+#define __PJ_DOXYGEN_H__

+

+/**

+ * @file doxygen.h

+ * @brief Doxygen's mainpage.

+ */

+

+/*//////////////////////////////////////////////////////////////////////////*/

+/*

+	INTRODUCTION PAGE

+ */

+

+/**

+ * @mainpage Welcome to PJLIB!

+ *

+ * @section intro_sec What is PJLIB

+ *

+ * PJLIB is a small foundation library written in C for making scalable 

+ * applications. Because of its small footprint, it can be used in embedded 

+ * applications (we hope so!), but yet the library is also aimed for 

+ * facilitating high performance protocol stacks.

+ *

+ * PJLIB is released under LGPL terms.

+ *

+ * @section download_sec Download

+ *

+ * PJLIB and all documentation can be downloaded from 

+ * http://www.bulukucing.org.

+ *

+ *

+ * @section how_to_use_sec About This Documentation

+ *

+ * This document is generated directly from PJLIB source file using

+ * \a doxygen (http://www.doxygen.org). Doxygen is a great (and free!) 

+ * tools for generating such documentation.

+ *

+ * @subsection doc_ver_subsec Version

+ *

+ * This document corresponds to PJLIB version 0.3-pre2.

+ *

+ *

+ * @subsection find_samples_subsec How to Read This Document

+ *

+ * This documentation is laid out more to be a reference guide instead

+ * of tutorial, therefore first time users may find it difficult to

+ * grasp PJLIB by reading this document alone.

+ *

+ * However, we've tried our best to make this document easy to follow.

+ * For first time users, we would suggest that you follow these steps

+ * when reading this documentation:

+ *

+ *  - continue reading this introduction chapter. At the end of this

+ *    chapter, you'll find section called \ref pjlib_fundamentals_sec

+ *    which should guide you to understand basic things about PJLIB.

+ *

+ *  - find information about specific features that you want to use

+ *    in PJLIB. Use the <b>Module Index</b> to find out about all 

+ *    features in PJLIB (if you're browsing the HTML documentation,

+ *    click on the \a Module link on top of the page, or if you're

+ *    reading the PDF documentation, click on \a Module \a Documentation

+ *    on the navigation pane on the left).

+ *

+ * @subsection doc_organize_sec How To's

+ *

+ * Please find below links to specific tasks that you probably

+ * want to do:

+ *

+ *  - <b>How to Build PJLIB</b>

+ *\n

+ * Please refer to \ref pjlib_build_sys_pg page for more information.

+ *

+ *  - <b>How to Use PJLIB in My Application</b>

+ *\n

+ * Please refer to \ref configure_app_sec for more information.

+ *

+ *  - <b>How to Port PJLIB</b>

+ *\n

+ * Please refer to \ref porting_pjlib_pg page.

+ *

+ *  - <b>Where to Read Samples Documentation</b>

+ *\n

+ * Most of the modules provide link to the corresponding sample file.

+ * Alternatively, to get the list of all examples, you can click on 

+ * <b>Related Pages</b> on the top of HTML document or on 

+ * <b>PJLIB Page Documentation</b> on navigation pane of your PDF reader.

+ *

+ *

+ *

+ *

+ *

+ * @section features_sec Features

+ *

+ * @subsection open_source_feat It's Open Source!

+ *

+ * PJLIB is currently released on LGPL license. We may release PJLIB under

+ * additional schemes in the future (such as GPL or MPL) to incorporate

+ * linking with specific application, however, one thing for sure is

+ * we will NEVER be able to make PJLIB a proprietary software.

+ *

+ * @subsection extreme_portable_feat Extreme Portability

+ *

+ * PJLIB is designed to be extremely portable. It can run on any kind

+ * of processors (16-bit, 32-bit, or 64-bit, big or little endian, single

+ * or multi-processors) and operating systems. Floating point or no

+ * floating point. Multi-threading or not.

+ * It can even run in environment where no ANSI LIBC is available. 

+ *

+ * Currently PJLIB is being ported to:

+ *  - x86, Win32 (Win95/98/ME, NT/2000/XP/2003, mingw).

+ *  - x86, Linux (user mode and as <b>kernel module</b>(!)).

+ *  - alpha, Linux

+ * And coming up:

+ *  - x86, eCos

+ *  - ultra-II, Solaris.

+ *  - powerpc, MacOS

+ *  - m68k, PalmOS.

+ *  - arm, PocketPC

+ *

+ * No other library is known to have this extreme portability!

+ *

+ * @subsection small_size_feat Small in Size

+ *

+ * One of the primary objectives is to have library that is small in size for

+ * typical embedded applications. As a rough guidance, we aim to keep the 

+ * library size below 100KB for it to be considered as small.

+ * As the result, most of the functionalities in the library can be tailored

+ * to meet the requirements; user can enable/disable specific functionalities

+ * to get the desired size/performance/functionality balance.

+ *

+ * For more info, please see @ref pj_config.

+ *

+ * @subsection no_dyn_mem No Dynamic Memory Allocations

+ *

+ * The central idea of PJLIB is that for applications to run as fast as it can,

+ * it should not use \a malloc() at all, but instead should get the memory 

+ * from a preallocated storage pool. There are few things that can be 

+ * optimized with this approach:

+ *

+ *  - \a alloc() is a O(1) operation.

+ *  - no mutex is used inside alloc(). It is assumed that synchronization 

+ *    will be used in higher abstraction by application anyway.

+ *  - no \a free() is required. All chunks will be deleted when the pool is 

+ *    destroyed.

+ *

+ * The performance gained on some systems can be as high as 10x speed up

+ * against \a malloc() and \a free().

+ *

+ * For more information, see \ref PJ_POOL_GROUP

+ *

+ * 

+ * @subsection os_abstract_feat Operating System Abstraction

+ *

+ * PJLIB has abstractions for features that are normally not portable 

+ * across operating systems: 

+ *  - @ref PJ_THREAD

+ *\n

+ *    Portable thread manipulation.

+ *  - @ref PJ_TLS

+ *\n

+ *    Storing data in thread's private data.

+ *  - @ref PJ_MUTEX

+ *\n

+ *    Mutual exclusion protection.

+ *  - @ref PJ_SEM

+ *\n

+ *    Semaphores.

+ *  - @ref PJ_ATOMIC

+ *\n

+ *    Atomic variables and their operations.

+ *  - @ref PJ_CRIT_SEC

+ *\n

+ *    Fast locking of critical sections.

+ *  - @ref PJ_LOCK

+ *\n

+ *    High level abstraction for lock objects.

+ *  - @ref PJ_EVENT

+ *\n

+ *    Event object.

+ *  - @ref PJ_TIME

+ *\n

+ *    Portable time manipulation.

+ *  - @ref PJ_TIMESTAMP

+ *\n

+ *    High resolution time value.

+ *  - etc.

+ *

+ *

+ * @subsection ll_network_io_sec Low-Level Network I/O

+ *

+ * PJLIB has very portable abstraction and fairly complete set of API for

+ * doing network I/O communications. At the lowest level, PJLIB provides:

+ *

+ *  - @ref PJ_SOCK

+ *\n

+ *    A highly portable socket abstraction, runs on all kind of

+ *    network APIs such as standard BSD socket, Windows socket, Linux

+ *    \b kernel socket, PalmOS networking API, etc.

+ *

+ *  - @ref pj_addr_resolve

+ *\n

+ *    Portable address resolution, which implements #pj_gethostbyname().

+ *

+ *  - @ref PJ_SOCK_SELECT

+ *\n

+ *    A portable \a select() like API (#pj_sock_select()) which can be

+ *    implemented with various back-end.

+ *

+ *

+ * @subsection hl_network_io_sec High-Level Network I/O

+ *

+ * At higher abstraction, PJLIB provides @ref PJ_IOQUEUE, 

+ * which promotes creating high performance network

+ * applications by managing asynchronous I/O. This is a passive framework

+ * that utilizes the most effective way to manage asynchronous I/O

+ * on a given platform, such as:

+ *  - IoCompletionPort on WinNT,

+ *  - on Linux it can use either /dev/epoll or aio.

+ *  - or to fall back to use @a select()

+ *

+ * At even a higher abstraction, PJLIB provides @ref PJ_EQUEUE, which

+ * combines asynchronous I/O with timer management and thread management 

+ * to fasilitate creating trully high performance, event driven

+ * application.

+ * 

+ *

+ * @subsection timer_mgmt_sec Timer Management

+ *

+ * A passive framework for managing timer, see @ref PJ_TIMER for more info.

+ * There is also function to retrieve high resolution timestamp

+ * from the system (see @ref PJ_TIMESTAMP).

+ *

+ *

+ * @subsection lexical_scanner_sec Lexical Scanner

+ *

+ * A fast, small, top-down lexical scanner to create fully optimized

+ * hand-written parser. See @ref PJ_SCAN for more info.

+ *

+ * @subsection data_struct_sec Various Data Structures

+ *

+ * Various data structures are provided in the library:

+ *

+ *  - @ref PJ_PSTR

+ *  - @ref PJ_ARRAY

+ *  - @ref PJ_HASH

+ *  - @ref PJ_LIST

+ *  - @ref PJ_RBTREE

+ *

+ *

+ * @subsection exception_sec Exception Construct

+ *

+ * A convenient TRY/CATCH like construct to propagate errors, which by

+ * default are used by the @ref PJ_POOL_GROUP "memory pool" and 

+ * the @ref PJ_SCAN "scanner". The exception

+ * construct can be used to write programs like below:

+ *

+ * <pre>

+ *    #define SYNTAX_ERROR  1

+ *

+ *    PJ_TRY {

+ *       msg = NULL;

+ *       msg = parse_msg(buf, len);

+ *    }

+ *    PJ_CATCH ( SYNTAX_ERROR ) {

+ *       .. handle error ..

+ *    }

+ *    PJ_END;

+ * </pre>

+ *

+ * Please see @ref PJ_EXCEPT for more information.

+ *

+ *

+ * @subsection logging_sec Logging Facility

+ *

+ * PJLIB @ref PJ_LOG consists of macros to write logging information to

+ * some output device. Some of the features of the logging facility:

+ *

+ *  - the verbosity can be fine-tuned both at compile time (to control

+ *    the library size) or run-time (to control the verbosity of the

+ *    information).

+ *  - output device is configurable (e.g. stdout, printk, file, etc.)

+ *  - log decoration is configurable.

+ *

+ * See @ref PJ_LOG for more information.

+ *

+ *

+ * @subsection guid_gen_sec Random and GUID Generation

+ *

+ * PJLIB provides facility to create random string 

+ * (#pj_create_random_string()) or globally unique identifier

+ * (see @ref PJ_GUID).

+ *

+ *

+ *

+ * @section configure_app_sec Configuring Application to use PJLIB

+ *

+ * @subsection pjlib_compil_sec Building PJLIB

+ *

+ * Follow the instructions in \ref pjlib_build_sys_pg to build

+ * PJLIB.

+ *

+ * @subsection pjlib_compil_app_sec Building Applications with PJLIB

+ *

+ * Use the following settings when building applications with PJLIB.

+ *

+ * @subsubsection compil_inc_dir_sec Include Search Path

+ *

+ * Add this to your include search path ($PJLIB is PJLIB root directory):

+ * <pre>

+ *   $PJLIB/include

+ * </pre>

+ *

+ * @subsubsection compil_inc_file_sec Include PJLIB Header

+ *

+ * To include all PJLIB headers:

+ * \verbatim

+    #include <pjlib.h>

+   \endverbatim

+ *

+ * Alternatively, you can include individual PJLIB headers like this:

+ * \verbatim

+     #include <pj/log.h>

+     #include <pj/os.h>

+  \endverbatim

+ *

+ *

+ * @subsubsection compil_lib_dir_sec Library Path

+ *

+ * Add this to your library search path:

+ * <pre>

+ *   $PJLIB/lib

+ * </pre>

+ *

+ * Then add the appropriate PJLIB library to your link specification. For

+ * example, you would add \c libpj-i386-linux-gcc.a when you're building

+ * applications in Linux.

+ *

+ *

+ * @subsection pjlib_fundamentals_sec Principles in Using PJLIB

+ *

+ * Few things that you \b MUST do when using PJLIB, to make sure that

+ * you create trully portable applications.

+ *

+ * @subsubsection call_pjlib_init_sec Call pj_init()

+ *

+ * Before you do anything else, call \c pj_init(). This would make sure that

+ * PJLIB system is properly set up.

+ *

+ * @subsubsection no_ansi_subsec Do NOT Use ANSI C

+ *

+ * Contrary to popular teaching, ANSI C (and LIBC) is not the most portable

+ * library in the world, nor it's the most ubiquitous. For example, LIBC

+ * is not available in Linux kernel. Also normally LIBC will be excluded

+ * from compilation of RTOSes to reduce size.

+ *

+ * So for maximum portability, do NOT use ANSI C. Do not even try to include

+ * any other header files outside <include/pj>. Stick with the functionalities

+ * provided by PJLIB. 

+ *

+ *

+ * @subsubsection string_rep_subsubsec Use pj_str_t instead of C Strings

+ *

+ * PJLIB uses pj_str_t instead of normal C strings. You SHOULD follow this

+ * convention too. Remember, ANSI string-h is not always available. And

+ * PJLIB string is faster!

+ *

+ * @subsubsection mem_alloc_subsubsec Use Pool for Memory Allocations

+ *

+ * You MUST NOT use \a malloc() or any other memory allocation functions.

+ * Use PJLIB pool instead! It's faster and most portable.

+ *

+ * @subsection logging_subsubsec Use Logging for Text Display

+ *

+ * DO NOT use <stdio.h> for text output. Use PJLIB logging instead.

+ *

+ *

+ * @section porting_pjlib_sec0 Porting PJLIB

+ *

+ * Please see \ref porting_pjlib_pg page on more information to port

+ * PJLIB to new target.

+ *

+ * @section enjoy_sec Enjoy Using PJLIB!

+ *

+ * We hope that you find PJLIB usefull for your application. If you

+ * have any questions, suggestions, critics, bug fixes, or anything

+ * else, we would be happy to hear it.

+ *

+ * Enjoy using PJLIB!

+ *

+ * Benny Prijono < bennylp at bulukucing dot org >

+ */

+

+

+

+

+/*////////////////////////////////////////////////////////////////////////// */

+/*

+	BUILDING AND INSTALLING PJLIB

+ */

+

+

+

+/**

+ * @page pjlib_build_sys_pg Building, and Installing PJLIB

+ *

+ * @section build_sys_install_sec Build and Installation

+ *

+ * @subsection build_sys_install_win32_sec Visual Studio

+ *

+ * The PJLIB Visual Studio workspace supports the building of PJLIB

+ * for Win32 target. Although currently only the Visual Studio 6 Workspace is

+ * actively maintained, developers with later version of Visual Studio

+ * can easily imports VS6 workspace into their IDE.

+ *

+ * To start building PJLIB projects with Visual Studio 6 or later, open

+ * the \a workspace file in the corresponding \b \c build directory. You have

+ * several choices on which \a dsw file to open:

+ \verbatim

+ $PJPROJECT/build/pjproject.dsw

+ $PJPROJECT/pjlib/build/pjlib.dsw

+ $PJPROJECT/pjsip/build/pjsip.dsw

+ ..etc

+ \endverbatim

+ *

+ * The easiest way is to open <tt>pjproject.dsw</tt> file in \b \c $PJPROJECT/build

+ * directory. However this will only build the required projects, not

+ * the complete projects. For example, the PJLIB test and samples projects 

+ * are not included in this workspace. To build the complete projects, you must

+ * open and build each \a dsw file in \c build directory in each

+ * subprojects. For example, to open the complete PJLIB workspace, open

+ * <tt>pjlib.dsw</tt> in <tt>$PJPROJECT/pjlib/build</tt> directory.

+ *

+ * @subsection build_sys_install_unix_sec Make System

+ *

+ * For other targets, PJLIB provides a rather comprehensive build system

+ * that uses GNU \a make (and only GNU \a make will work). 

+ * Currently, the build system supports building * PJLIB for these targets:

+ *  - i386/Win32/mingw

+ *  - i386/Linux

+ *  - i386/Linux (kernel)

+ *

+ * Generally, steps required to build the projects are:

+ *

+ \verbatim

+   $ cd /home/user/pjproject-0.3     # <-- go to $PJPROJECT\n

+   $ vi build.mak                    # <-- set build target etc\n

+   $ cd pjlib/build                  # <-- go to projet's build dir\n

+   $ make                            # <-- build the project\n

+ \endverbatim

+ *

+ * For other project, \a cd to <tt>build</tt> directory in the project

+ * and execute \a make from there.

+ *

+ * \note For Linux kernel target, there are additional steps required, which

+ * will be explained in section \ref linux_kern_target_subsec.

+ *

+ * @subsubsection build_mak_sec Editing build.mak

+ * 

+ * The \c build.mak file in \c $PJPROJECT root directory is used to

+ * specify the build configuration. This file is expected to export

+ * the following \a make variables:

+ *

+ *  - \c MACHINE_NAME

+ *\n

+ *    Target machine/processor, one of: <b>{ i386 }</b>.

+ *

+ *  - \c OS_NAME

+ *\n

+ *    Target operating system, one of: <b>{ win32 | linux | linux-kernel }</b>.

+ *

+ *  - \c CC_NAME

+ *\n

+ *    Compiler name: <b>{ gcc | vc }</b>

+ *

+ *  - \c HOST_NAME

+ *\n

+ *    Build host: <b>{ unix | mingw }</b>

+ *

+ * These variables will cause the correct configuration file in 

+ * \c $PJPROJECT/build directory to be executed by \a make. For 

+ * example, specifying \c OS_NAME=linux will cause file \c os-linux.mak

+ * in \c build directory to be executed. These files contain specific

+ * configuration for the option that is selected.

+ *

+ * For Linux kernel target, you are also required to declare the following

+ * variables in this file:

+ *	- \c KERNEL_DIR: full path of kernel source tree.

+ *	- \c KERNEL_ARCH: kernel ARCH options (e.g. "ARCH=um"), or leave blank

+ * 	     for default.

+ *	- \c PJPROJECT_DIR: full path of PJPROJECT source tree.

+ *

+ * Apart from these, there are also additional steps required to build

+ * Linux kernel target, which will be explained in \ref linux_kern_target_subsec.

+ *

+ * @subsubsection build_dir_sec Files in "build" Directory

+ *

+ * The <tt>*.mak</tt> files in \c $PJPROJECT/build directory are used to specify

+ * the configuration for the specified compiler, target machine target 

+ * operating system, and host options. These files will be executed

+ * (included) by \a make during building process, depending on the values

+ * specified in <b>$PJPROJECT/build.mak</b> file.

+ *

+ * Normally you don't need to edit these files, except when you're porting

+ * PJLIB to new target.

+ *

+ * Below are the description of some files in this directory:

+ *

+ *  - <tt>rules.mak</tt>: contains generic rules always included during make.

+ *  - <tt>cc-gcc.mak</tt>: rules when gcc is used for compiler.

+ *  - <tt>cc-vc.mak</tt>: rules when MSVC compiler is used.

+ *  - <tt>host-mingw.mak</tt>: rules for building in mingw host.

+ *  - <tt>host-unix.mak</tt>: rules for building in Unix/Posix host.

+ *  - <tt>host-win32.mak</tt>: rules for building in Win32 command console

+ *    (only valid when VC is used).

+ *  - <tt>m-i386.mak</tt>: rules when target machine is an i386 processor.

+ *  - <tt>m-m68k.mak</tt>: rules when target machine is an m68k processor.

+ *  - <tt>os-linux.mak</tt>: rules when target OS is Linux.

+ *  - <tt>os-linux-kernel.mak</tt>: rules when PJLIB is to be build as

+ *    part of Linux kernel.

+ *  - <tt>os-win32.mak</tt>: rules when target OS is Win32.

+ *

+ * @subsubsection invoking_make_sec Invoking make

+ *

+ * Normally, \a make is invoked in \c build directory under each project.

+ * For example, to build PJLIB, you would invoke \a make in

+ * \c $PJPROJECT/pjlib/build directory like below:

+ *

+ \verbatim

+   $ cd pjlib/build

+   $ make

+ \endverbatim

+ *

+ *

+ *

+ * @subsubsection linux_kern_target_subsec Linux Kernel Target

+ *

+ * \note

+ * <b>BUILDING APPLICATIONS IN LINUX KERNEL MODE IS A VERY DANGEROUS BUSINESS.

+ * YOU MAY CRASH THE WHOLE OF YOUR SYSTEM, CORRUPT YOUR HARDISK, ETC. PJLIB

+ * KERNEL MODULES ARE STILL IN EXPERIMENTAL PHASE. DO NOT RUN IT IN PRODUCTION

+ * SYSTEMS OR OTHER SYSTEMS WHERE RISK OF LOSS OF DATA IS NOT ACCEPTABLE.

+ * YOU HAVE BEEN WARNED.</b>

+ *

+ * \note

+ * <b>User Mode Linux (UML)</b> provides excellent way to experiment with Linux

+ * kernel without risking the stability of the host system. See

+ * http://user-mode-linux.sourceforge.net for details.

+ *

+ * \note

+ * I only use <b>UML</b> to experiment with PJLIB kernel modules.

+ * <b>I wouldn't be so foolish to use my host Linux machine to experiment

+ * with this.</b> 

+ *

+ * \note

+ * You have been warned.

+ *

+ * For building PJLIB for Linux kernel target, there are additional steps required.

+ * In general, the additional tasks are:

+ *	- Declare some more variables in <b><tt>build.mak</tt></b> file (this

+ *        has been explained in \ref build_mak_sec above).

+ *      - Perform these two small modifications in kernel source tree.

+ *

+ * There are two small modification need to be applied to the kernel tree.

+ *

+ * <b>1. Edit <tt>Makefile</tt> in kernel root source tree.</b>

+ *

+ * Add the following lines at the end of the <tt>Makefile</tt> in your 

+ * <tt>$KERNEL_SRC</tt> dir:

+ \verbatim

+script:

+       $(SCRIPT)

+ \endverbatim

+ *

+ * \note Remember to replace spaces with <b>tab</b> in the Makefile.

+ *

+ * The modification above is needed to capture kernel's \c $CFLAGS and 

+ * \c $CFLAGS_MODULE which will be used for PJLIB's compilation.

+ *

+ * <b>2. Add Additional Exports.</b>

+ *

+ * We need the kernel to export some more symbols for our use. So we declare

+ * the additional symbols to be exported in <tt>extra-exports.c</tt> file, and add

+ * a this file to be compiled into the kernel:

+ *

+ *	- Copy the file <tt>extra-exports.c</tt> from <tt>pjlib/src/pj</tt> 

+ *	  directory to <tt>$KERNEL_SRC/kernel/</tt> directory.

+ *	- Edit <tt>Makefile</tt> in that directory, and add this line

+ *        somewhere after the declaration of that variable:

+ \verbatim

+obj-y   += extra-exports.o

+ \endverbatim

+ *

+ * To illustrate what have been done in your kernel source tree, below

+ * is screenshot of my kernel source tree _after_ the modification.

+ *

+ \verbatim

+[root@vpc-linux linux-2.6.7]# pwd

+/usr/src/linux-2.6.7

+[root@vpc-linux linux-2.6.7]# 

+[root@vpc-linux linux-2.6.7]# 

+[root@vpc-linux linux-2.6.7]# tail Makefile 

+

+endif   # skip-makefile

+

+FORCE:

+

+.PHONY: script

+

+script:

+        $(SCRIPT)

+

+[root@vpc-linux linux-2.6.7]# 

+[root@vpc-linux linux-2.6.7]# 

+[root@vpc-linux linux-2.6.7]# head kernel/extra-exports.c 

+#include <linux/module.h>

+#include <linux/syscalls.h>

+

+EXPORT_SYMBOL(sys_select);

+

+EXPORT_SYMBOL(sys_epoll_create);

+EXPORT_SYMBOL(sys_epoll_ctl);

+EXPORT_SYMBOL(sys_epoll_wait);

+

+EXPORT_SYMBOL(sys_socket);

+[root@vpc-linux linux-2.6.7]# 

+[root@vpc-linux linux-2.6.7]# 

+[root@vpc-linux linux-2.6.7]# head -15 kernel/Makefile 

+#

+# Makefile for the linux kernel.

+#

+

+obj-y     = sched.o fork.o exec_domain.o panic.o printk.o profile.o \

+            exit.o itimer.o time.o softirq.o resource.o \

+            sysctl.o capability.o ptrace.o timer.o user.o \

+            signal.o sys.o kmod.o workqueue.o pid.o \

+            rcupdate.o intermodule.o extable.o params.o posix-timers.o \

+            kthread.o

+

+obj-y   +=  extra-exports.o

+

+obj-$(CONFIG_FUTEX) += futex.o

+obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o

+[root@vpc-linux linux-2.6.7]# 

+

+ \endverbatim

+ *

+ * Then you must rebuild the kernel.

+ * If you fail to do this, you won't be able to <b>insmod</b> pjlib.

+ *

+ * \note You will see a lots of warning messages during pjlib-test compilation.

+ * The warning messages complain about unresolved symbols which are defined

+ * in pjlib module. You can safely ignore these warnings. However, you can not

+ * ignore warnings about non-pjlib unresolved symbols.

+ *

+ * 

+ * @subsection makefile_explained_sec Makefile Explained

+ *

+ * The \a Makefile for each project (e.g. PJLIB, PJSIP, etc) should be

+ * very similar in the contents. The Makefile is located under \c build

+ * directory in each project subdir.

+ *

+ * @subsubsection pjlib_makefile_subsec PJLIB Makefile.

+ *

+ * Below is PJLIB's Makefile:

+ *

+ * \include build/Makefile

+ *

+ * @subsubsection pjlib_os_makefile_subsec PJLIB os-linux.mak.

+ *

+ * Below is file <tt><b>os-linux.mak</b></tt> file in 

+ * <tt>$PJPROJECT/pjlib/build</tt> directory,

+ * which is OS specific configuration file for Linux target that is specific 

+ * for PJLIB project. For \b global OS specific configuration, please see

+ * <tt>$PJPROJECT/build/os-*.mak</tt>.

+ *

+ * \include build/os-linux.mak

+ *

+ */

+

+

+/*////////////////////////////////////////////////////////////////////////// */

+/*

+         PORTING PJLIB

+ */

+

+

+

+/**

+ * @page porting_pjlib_pg Porting PJLIB

+ *

+ *

+ * @section new_arch_sec Porting to New CPU Architecture

+ *

+ * Below is step-by-step guide to add support for new CPU architecture.

+ * This sample is based on porting to Alpha architecture; however steps for 

+ * porting to other CPU architectures should be pretty similar. 

+ *

+ * Also note that in this example, the operating system used is <b>Linux</b>.

+ * Should you wish to add support for new operating system, then follow

+ * the next section \ref porting_os_sec.

+ *

+ * Step-by-step guide to port to new CPU architecture:

+ *  - decide the name for the new architecture. In this case, we choose

+ *    <tt><b>alpha</b></tt>.

+ *  - edit file <tt>$PJPROJECT/build.mak</tt>, and add new section for

+ *    the new target:

+ *    <pre>

+ *      #

+ *      # Linux alpha, gcc

+ *      #

+ *      export MACHINE_NAME := <b>alpha</b>

+ *      export OS_NAME := linux

+ *      export CC_NAME := gcc

+ *      export HOST_NAME := unix

+ *    </pre>

+ *

+ *  - create a new file <tt>$PJPROJECT/build/<b>m-alpha</b>.mak</tt>.

+ *    Alternatively create a copy from other file in this directory.

+ *    The contents of this file will look something like:

+ *    <pre>

+ *      export M_CFLAGS := $(CC_DEF)<b>PJ_M_ALPHA=1</b>

+ *      export M_CXXFLAGS :=

+ *      export M_LDFLAGS :=

+ *      export M_SOURCES :=

+ *    </pre>

+ *  - create a new file <tt>$PJPROJECT/pjlib/include/pj/compat/<b>m_alpha.h</b></tt>.

+ *    Alternatively create a copy from other header file in this directory.

+ *    The contents of this file will look something like:

+ *    <pre>

+ *      #define PJ_HAS_PENTIUM          0

+ *      #define PJ_IS_LITTLE_ENDIAN     1

+ *      #define PJ_IS_BIG_ENDIAN        0

+ *    </pre>

+ *  - edit <tt>pjlib/include/pj/<b>config.h</b></tt>. Add new processor

+ *    configuration in this header file, like follows:

+ *    <pre>

+ *      ...

+ *      #elif defined (PJ_M_ALPHA) && PJ_M_ALPHA != 0

+ *      #   include <pj/compat/m_alpha.h>

+ *      ...

+ *    </pre>

+ *  - done. Build PJLIB with:

+ *    <pre>

+ *      $ cd $PJPROJECT/pjlib/build

+ *      $ make dep

+ *      $ make clean

+ *      $ make

+ *    </pre>

+ *

+ * @section porting_os_sec Porting to New Operating System Target

+ *

+ * This section will try to give you rough guideline on how to

+ * port PJLIB to a new target. As a sample, we give the target a name tag, 

+ * for example <tt><b>xos</b></tt> (for X OS). 

+ *

+ * @subsection new_compat_os_h_file_sec Create New Compat Header File

+ *

+ * You'll need to create a new header file 

+ * <b><tt>include/pj/compat/os_xos.h</tt></b>. You can copy as a 

+ * template other header file and edit it accordingly.

+ *

+ * @subsection modify_config_h_file_sec Modify config.h

+ *

+ * Then modify file <b><tt>include/pj/config.h</tt></b> to include

+ * this file accordingly (e.g. when macro <tt><b>PJ_XOS</b></tt> is

+ * defined):

+ *

+ \verbatim

+ ...

+ #elif defined(PJ_XOS)

+ #  include <pj/compat/os_xos.h>

+ #else

+ #...

+ \endverbatim

+ * 

+ * @subsection new_target_mak_file_sec Create New Global Make Config File

+ *

+ * Then you'll need to create global configuration file that

+ * is specific for this OS, i.e. <tt><b>os-xos.mak</b></tt> in 

+ * <tt><b>$PJPROJECT/build</b></tt> directory.

+ *

+ * At very minimum, the file will normally need to define

+ * <tt><b>PJ_XOS=1</b></tt> in the \c CFLAGS section:

+ *

+ \verbatim

+#

+# $PJPROJECT/build/os-xos.mak:

+#

+export OS_CFLAGS   := $(CC_DEF)PJ_XOS=1

+export OS_CXXFLAGS := 

+export OS_LDFLAGS  :=

+export OS_SOURCES  := 

+ \endverbatim

+ *

+ *

+ * @subsection new_target_prj_mak_file_sec Create New Project's Make Config File

+ *

+ * Then you'll need to create xos-specific configuration file

+ * for PJLIB. This file is also named <tt><b>os-xos.mak</b></tt>,

+ * but its located in <tt><b>pjlib/build</b></tt> directory.

+ * This file will specify source files that are specific to

+ * this OS to be included in the build process.

+ *

+ * Below is a sample:

+ \verbatim

+#

+# pjlib/build/os-xos.mak:

+#  XOS specific configuration for PJLIB.

+#

+export PJLIB_OBJS += 	os_core_xos.o \

+                        os_error_unix.o \

+                        os_time_ansi.o

+export TEST_OBJS +=	main.o

+export TARGETS	    =	pjlib pjlib-test

+ \endverbatim

+ *

+ * @subsection new_target_src_sec Create and Edit Source Files

+ *

+ * You'll normally need to create at least these files:

+ *  - <tt><b>os_core_xos.c</b></tt>: core OS specific

+ *    functionality.

+ *  - <tt><b>os_timestamp_xos.c</b></tt>: how to get timestamp

+ *    in this OS.

+ *

+ * Depending on how things are done in your OS, you may need

+ * to create these files:

+ *  - <tt><b>os_error_*.c</b></tt>: how to manipulate

+ *    OS error codes. Alternatively you may use existing

+ *    <tt>os_error_unix.c</tt> if the OS has \c errno and

+ *    \c strerror() function.

+ *  - <tt><b>ioqueue_*.c</b></tt>: if the OS has specific method

+ *    to perform asynchronous I/O. Alternatively you may

+ *    use existing <tt>ioqueue_select.c</tt> if the OS supports

+ *    \c select() function call.

+ *  - <tt><b>sock_*.c</b></tt>: if the OS has specific method

+ *    to perform socket communication. Alternatively you may

+ *    use existing <tt>sock_bsd.c</tt> if the OS supports

+ *    BSD socket API, and edit <tt>include/pj/compat/socket.h</tt>

+ *    file accordingly.

+ *

+ * You will also need to check various files in 

+ * <tt><b>include/pj/compat/*.h</b></tt>, to see if they're 

+ * compatible with your OS.

+ *

+ * @subsection new_target_build_file_sec Build The Project

+ *

+ * After basic building blocks have been created for the OS, then

+ * the easiest way to see which parts need to be fixed is by building

+ * the project and see the error messages.

+ *

+ * @subsection new_target_edit_vs_new_file_sec Editing Existing Files vs Creating New File

+ *

+ * When you encounter compatibility errors in PJLIB during porting,

+ * you have three options on how to fix the error:

+ *  - edit the existing <tt>*.c</tt> file, and give it <tt>#ifdef</tt>

+ *    switch for the new OS, or

+ *  - edit <tt>include/pj/compat/*.h</tt> instead, or

+ *  - create a totally new file.

+ *

+ * Basicly there is no strict rule on which approach is the best

+ * to use, however the following guidelines may be used:

+ *  - if the file is expected to be completely different than

+ *    any existing file, then perhaps you should create a completely

+ *    new file. For example, file <tt>os_core_xxx.c</tt> will 

+ *    normally be different for each OS flavour.

+ *  - if the difference can be localized in <tt>include/compat</tt>

+ *    header file, and existing <tt>#ifdef</tt> switch is there,

+ *    then preferably you should edit this <tt>include/compat</tt>

+ *    header file.

+ *  - if the existing <tt>*.c</tt> file has <tt>#ifdef</tt> switch,

+ *    then you may add another <tt>#elif</tt> switch there. This

+ *    normally is used for behaviors that are not totally

+ *    different on each platform.

+ *  - other than that above, use your own judgement on whether

+ *    to edit the file or create new file etc.

+ */

+

+#endif	/* __PJ_DOXYGEN_H__ */

+

diff --git a/pjlib/include/pj/equeue.h b/pjlib/include/pj/equeue.h
new file mode 100644
index 0000000..294304d
--- /dev/null
+++ b/pjlib/include/pj/equeue.h
@@ -0,0 +1,319 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/equeue.h 2     10/14/05 12:26a Bennylp $ */

+#ifndef __PJ_EQUEUE_H__

+#define __PJ_EQUEUE_H__

+

+/**

+ * @file equeue.h

+ * @brief Event Queue

+ */

+#include <pj/types.h>

+

+

+PJ_BEGIN_DECL

+

+/**

+ * @defgroup PJ_EQUEUE Event Queue

+ * @brief Event Queue

+ * @ingroup PJ_OS

+ * @{

+ */

+

+

+/**

+ * Opaque data type for Event Queue.

+ */

+typedef struct pj_equeue_t pj_equeue_t;

+

+/**

+ * Opaque data type for Event Queue key.

+ */

+typedef struct pj_equeue_key_t pj_equeue_key_t;

+

+

+/**

+ * This structure describes the callbacks to be called when I/O operation

+ * completes.

+ */

+typedef struct pj_io_callback

+{

+    /**

+     * This callback is called when #pj_equeue_read, #pj_equeue_recv or 

+     * #pj_equeue_recvfrom completes.

+     *

+     * @param key	    The key.

+     * @param bytes_read    The size of data that has just been read.

+     */

+    void (*on_read_complete)(pj_equeue_key_t *key, pj_ssize_t bytes_read);

+

+    /**

+     * This callback is called when #pj_equeue_write, #pj_equeue_send, or

+     * #pj_equeue_sendto completes.

+     *

+     * @param key	    The key.

+     * @param bytes_read    The size of data that has just been written.

+     */

+    void (*on_write_complete)(pj_equeue_key_t *key, pj_ssize_t bytes_sent);

+

+    /**

+     * This callback is called when #pj_equeue_accept completes.

+     *

+     * @param key	    The key.

+     * @param status	    Zero if the operation completes successfully.

+     */

+    void (*on_accept_complete)(pj_equeue_key_t *key, int status);

+

+    /**

+     * This callback is called when #pj_equeue_connect completes.

+     *

+     * @param key	    The key.

+     * @param status	    Zero if the operation completes successfully.

+     */

+    void (*on_connect_complete)(pj_equeue_key_t *key, int status);

+

+} pj_io_callback;

+

+/**

+ * Event Queue options.

+ */

+typedef struct pj_equeue_options

+{

+    /** Maximum number of threads that are allowed to access Event Queue

+     *  simulteneously.

+     */

+    unsigned	nb_threads;

+

+    /** If non-zero, then no mutex protection will be used. */

+    pj_bool_t	no_lock;

+

+    /** Interval of the busy loop inside the event queue.

+     *  The time resolution here determines the accuracy of the

+     *  timer in the Event Queue.

+     */

+    pj_time_val	poll_interval;

+

+} pj_equeue_options;

+

+

+/**

+ * Error value returned by I/O operations to indicate that the operation

+ * can't complete immediately and will complete later.

+ */

+#define PJ_EQUEUE_PENDING   (-2)

+

+/**

+ * Types of Event Queue operation.

+ */

+typedef enum pj_equeue_op

+{

+    PJ_EQUEUE_OP_NONE		= 0,	/**< No operation.	    */

+    PJ_EQUEUE_OP_READ		= 1,	/**< read() operation.	    */

+    PJ_EQUEUE_OP_RECV_FROM	= 2,	/**< recvfrom() operation.  */

+    PJ_EQUEUE_OP_WRITE		= 4,	/**< write() operation.	    */

+    PJ_EQUEUE_OP_SEND_TO	= 8,	/**< sendto() operation.    */

+#if defined(PJ_HAS_TCP) && PJ_HAS_TCP != 0

+    PJ_EQUEUE_OP_ACCEPT		= 16,	/**< accept() operation.    */

+    PJ_EQUEUE_OP_CONNECT	= 32,	/**< connect() operation.   */

+#endif	/* PJ_HAS_TCP */

+} pj_equeue_op;

+

+

+

+/**

+ * Initialize Event Queue options with default values.

+ *

+ * @param options   Event Queue options.

+ */

+PJ_DECL(void) pj_equeue_options_init(pj_equeue_options *options);

+

+/**

+ * Create a new Event Queue framework.

+ *

+ * @param pool	    The pool to allocate the event queue structure.

+ * @param options   Event queue options, or if NULL is given, then

+ *		    default options will be used.

+ * @param equeue    Pointer to receive event queue structure.

+ *

+ * @return	    zero on success.

+ */

+PJ_DECL(pj_status_t) pj_equeue_create( pj_pool_t *pool, 

+				       const pj_equeue_options *options,

+				       pj_equeue_t **equeue);

+

+/**

+ * Get the first instance of Event Queue, or NULL if no Event Queue

+ * instance has been created in the application.

+ *

+ * @return	    The first instance of Event Queue created, or NULL.

+ */

+PJ_DECL(pj_equeue_t*) pj_equeue_instance(void);

+

+/**

+ * Destroy the Event Queue.

+ *

+ * @param equeue    The Event Queue instance to be destroyed.

+ */

+PJ_DECL(pj_status_t) pj_equeue_destroy( pj_equeue_t *equeue );

+

+/**

+ * Customize the lock object that is used by the Event Queue.

+ *

+ * @param equeue    The Event Queue instance.

+ * @param lock	    The lock object.

+ * @param auto_del  If non-zero, the lock will be destroyed by

+ *		    Event Queue.

+ *

+ * @return	    Zero on success.

+ */

+PJ_DECL(pj_status_t) pj_equeue_set_lock( pj_equeue_t *equeue,

+					 pj_lock_t *lock, 

+					 pj_bool_t auto_del);

+

+/**

+ * Associate an Event Queue key to particular handle. The key is also

+ * associated with the callback and user data, which will be used by

+ * the Event Queue framework when signalling event back to application.

+ *

+ * @param pool	    To allocate the resource for the specified handle, which

+ *		    must be valid until the handle/key is unregistered

+ *		    from Event Queue.

+ * @param equeue    The Event Queue.

+ * @param hnd	    The OS handle to be registered, which can be a socket

+ *		    descriptor (pj_sock_t), file descriptor, etc.

+ * @param cb	    Callback to be called when I/O operation completes. 

+ * @param user_data User data to be associated with the key.

+ * @param key	    Pointer to receive the key.

+ *

+ * @return	    Zero on success.

+ */

+PJ_DECL(pj_status_t) pj_equeue_register( pj_pool_t *pool,

+					 pj_equeue_t *equeue,

+					 pj_oshandle_t hnd,

+					 pj_io_callback *cb,

+					 void *user_data,

+					 pj_equeue_key_t **key);

+

+/**

+ * Retrieve user data associated with a key.

+ *

+ * @param key	    The Event Queue key.

+ *

+ * @return	    User data associated with the key.

+ */

+PJ_DECL(void*) pj_equeue_get_user_data( pj_equeue_key_t *key );

+

+

+/**

+ * Unregister Event Queue key from the Event Queue.

+ *

+ * @param equeue    The Event Queue.

+ * @param key	    The key.

+ *

+ * @return	    Zero on success.

+ */

+PJ_DECL(pj_status_t) pj_equeue_unregister( pj_equeue_t *equeue,

+					   pj_equeue_key_t *key);

+

+/**

+ * Instruct the Event Queue to read from the specified handle. This function

+ * returns immediately (i.e. non-blocking) regardless whether some data has 

+ * been transfered. If the operation can't complete immediately, caller will 

+ * be notified about the completion when it calls pj_equeue_poll().

+ *

+ * @param key	    The key that uniquely identifies the handle.

+ * @param buffer    The buffer to hold the read data. The caller MUST make sure

+ *		    that this buffer remain valid until the framework completes

+ *		    reading the handle.

+ * @param size	    The maximum size to be read.

+ *

+ * @return

+ *  - zero or positive number to indicate the number of bytes has been

+ *		    read, and in this case the operation was not queued.

+ *  - (-1) on error, which in this case operation was not queued.

+ *  - PJ_EQUEUE_PENDING if the operation has been queued.

+ */

+PJ_DECL(pj_ssize_t) pj_equeue_read( pj_equeue_key_t *key,

+				    void *buffer,

+				    pj_size_t size);

+

+/**

+ * Start recv() operation on the specified handle.

+ *

+ * @see ::pj_ioqueue_read

+ */

+PJ_DECL(pj_ssize_t) pj_equeue_recv( pj_equeue_key_t *key,

+				    void *buf,

+				    pj_size_t size,

+				    unsigned flags);

+

+/**

+ * Start recvfrom() operation on the specified handle.

+ *

+ * @see ::pj_equeue_read

+ */

+PJ_DECL(pj_ssize_t) pj_equeue_recvfrom( pj_equeue_key_t *key,

+					void *buf,

+					pj_size_t size,

+					unsigned flags,

+					pj_sockaddr_t *addr,

+					int *addrlen );

+

+/**

+ * Write.

+ */

+PJ_DECL(pj_ssize_t) pj_equeue_write( pj_equeue_key_t *key,

+				     const void *buf,

+				     pj_size_t size);

+

+/**

+ * Send.

+ */

+PJ_DECL(pj_ssize_t) pj_equeue_send( pj_equeue_key_t *key,

+				    const void *buf,

+				    pj_size_t size,

+				    unsigned flags);

+

+/**

+ * Sendto.

+ */

+PJ_DECL(pj_ssize_t) pj_equeue_sendto( pj_equeue_key_t *key,

+				      const void *buf,

+				      pj_size_t size,

+				      unsigned flags,

+				      const pj_sockaddr_t *addr,

+				      int addrlen);

+

+/**

+ * Schedule timer.

+ */

+PJ_DECL(pj_status_t) pj_equeue_schedule_timer( pj_equeue_t *equeue,

+					       const pj_time_val *timeout,

+					       pj_timer_entry *entry);

+

+/**

+ * Cancel timer.

+ */

+PJ_DECL(pj_status_t) pj_equeue_cancel_timer( pj_equeue_t *equeue,

+					     pj_timer_entry *entry);

+

+/**

+ * Poll for events.

+ */

+PJ_DECL(pj_status_t) pj_equeue_poll( pj_equeue_t *equeue,

+				     const pj_time_val *timeout );

+

+/**

+ * Run.

+ */

+PJ_DECL(pj_status_t) pj_equeue_run( pj_equeue_t *equeue );

+

+/**

+ * Stop all running threads.

+ */

+PJ_DECL(pj_status_t) pj_equeue_stop( pj_equeue_t *equeue );

+

+

+/** @} */

+

+PJ_END_DECL

+

+#endif	/* __PJ_EQUEUE_H__ */

diff --git a/pjlib/include/pj/errno.h b/pjlib/include/pj/errno.h
new file mode 100644
index 0000000..9cc9328
--- /dev/null
+++ b/pjlib/include/pj/errno.h
@@ -0,0 +1,249 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/errno.h 2     10/14/05 12:26a Bennylp $ */

+#ifndef __PJ_ERRNO_H__

+#define __PJ_ERRNO_H__

+

+/**

+ * @file errno.h

+ * @brief PJLIB Error Codes

+ */

+#include <pj/types.h>

+#include <pj/compat/errno.h>

+

+PJ_BEGIN_DECL

+

+/**

+ * @defgroup pj_errno Error Codes

+ * @ingroup PJ

+ * @{

+ *

+ * In PJLIB, error/status codes from operating system are translated

+ * into PJLIB error namespace, and stored in @a pj_status_t. All functions

+ * that work with @a pj_status_t expect to get PJLIB error code instead

+ * of native codes.

+ *

+ * @section pj_errno_retval Return Values

+ *

+ * All functions that returns @a pj_status_t returns @a PJ_SUCCESS if the

+ * operation was completed successfully, or non-zero value to indicate 

+ * error. If the error came from operating system, then the native error

+ * code is translated/folded into PJLIB's error namespace by using

+ * #PJ_STATUS_FROM_OS() macro. The function will do this automatically

+ * before returning the error to caller.

+ *

+ * @section pj_errno_errmsg Error Message

+ *

+ * To get the error message corresponding to a particular code, use function

+ * #pj_strerror(). This function expects error code in PJLIB error namespace,

+ * not the native error code. Application can pass the value from the 

+ * following sources to this function:

+ *  - #pj_get_os_error()

+ *  - #pj_get_netos_error()

+ *  - any return value from function returning @a pj_status_t.

+ *

+ * Application MUST NOT pass native error code (such as error code from

+ * functions like GetLastError() or errno) to PJLIB functions expecting

+ * @a pj_status_t.

+ *

+ */

+

+/**

+ * Get the last platform error/status, folded into pj_status_t.

+ * @return	OS dependent error code, folded into pj_status_t.

+ * @remark	This function gets errno, or calls GetLastError() function and

+ *		convert the code into pj_status_t with PJ_STATUS_FROM_OS. Do

+ *		not call this for socket functions!

+ * @see	pj_get_netos_error()

+ */

+PJ_DECL(pj_status_t) pj_get_os_error(void);

+

+/**

+ * Set last error.

+ * @param code	pj_status_t

+ */

+PJ_DECL(void) pj_set_os_error(pj_status_t code);

+

+/**

+ * Get the last error from socket operations.

+ * @return	Last socket error, folded into pj_status_t.

+ */

+PJ_DECL(pj_status_t) pj_get_netos_error(void);

+

+/**

+ * Set error code.

+ * @param code	pj_status_t.

+ */

+PJ_DECL(void) pj_set_netos_error(pj_status_t code);

+

+

+/**

+ * Get the error message for the specified error code. The message

+ * string will be NULL terminated.

+ *

+ * @param statcode  The error code.

+ * @param buf	    Buffer to hold the error message string.

+ * @param bufsize   Size of the buffer.

+ *

+ * @return	    The error message as NULL terminated string,

+ *                  wrapped with pj_str_t.

+ */

+PJ_DECL(pj_str_t) pj_strerror( pj_status_t statcode, 

+			       char *buf, pj_size_t bufsize);

+

+

+/**

+ * @hideinitializer

+ * Return platform os error code folded into pj_status_t code. This is

+ * the macro that is used throughout the library for all PJLIB's functions

+ * that returns error from operating system. Application may override

+ * this macro to reduce size (e.g. by defining it to always return 

+ * #PJ_EUNKNOWN).

+ *

+ * Note:

+ *  This macro MUST return non-zero value regardless whether zero is

+ *  passed as the argument. The reason is to protect logic error when

+ *  the operating system doesn't report error codes properly.

+ *

+ * @param os_code   Platform OS error code. This value may be evaluated

+ *		    more than once.

+ * @return	    The platform os error code folded into pj_status_t.

+ */

+#ifndef PJ_RETURN_OS_ERROR

+#   define PJ_RETURN_OS_ERROR(os_code)   (os_code ? \

+					    PJ_STATUS_FROM_OS(os_code) : -1)

+#endif

+

+

+/**

+ * @hideinitializer

+ * Fold a platform specific error into an pj_status_t code.

+ *

+ * @param e	The platform os error code.

+ * @return	pj_status_t

+ * @warning	Macro implementation; the syserr argument may be evaluated

+ *		multiple times.

+ */

+#define PJ_STATUS_FROM_OS(e) (e == 0 ? PJ_SUCCESS : e + PJ_ERRNO_START_SYS)

+

+/**

+ * @hideinitializer

+ * Fold an pj_status_t code back to the native platform defined error.

+ *

+ * @param e	The pj_status_t folded platform os error code.

+ * @return	pj_os_err_type

+ * @warning	macro implementation; the statcode argument may be evaluated

+ *		multiple times.  If the statcode was not created by 

+ *		pj_get_os_error or PJ_STATUS_FROM_OS, the results are undefined.

+ */

+#define PJ_STATUS_TO_OS(e) (e == 0 ? PJ_SUCCESS : e - PJ_ERRNO_START_SYS)

+

+

+/**

+ * @defgroup pj_errnum PJLIB's Own Error Codes

+ * @ingroup pj_errno

+ * @{

+ */

+

+/**

+ * @hideinitializer

+ * Unknown error has been reported.

+ */

+#define PJ_EUNKNOWN	    (PJ_ERRNO_START_STATUS + 1)

+/**

+ * @hideinitializer

+ * The operation is pending and will be completed later.

+ */

+#define PJ_EPENDING	    (PJ_ERRNO_START_STATUS + 2)

+/**

+ * @hideinitializer

+ * Too many connecting sockets.

+ */

+#define PJ_ETOOMANYCONN	    (PJ_ERRNO_START_STATUS + 3)

+/**

+ * @hideinitializer

+ * Invalid argument.

+ */

+#define PJ_EINVAL	    (PJ_ERRNO_START_STATUS + 4)

+/**

+ * @hideinitializer

+ * Name too long (eg. hostname too long).

+ */

+#define PJ_ENAMETOOLONG	    (PJ_ERRNO_START_STATUS + 5)

+/**

+ * @hideinitializer

+ * Not found.

+ */

+#define PJ_ENOTFOUND	    (PJ_ERRNO_START_STATUS + 6)

+/**

+ * @hideinitializer

+ * Not enough memory.

+ */

+#define PJ_ENOMEM	    (PJ_ERRNO_START_STATUS + 7)

+/**

+ * @hideinitializer

+ * Bug detected!

+ */

+#define PJ_EBUG             (PJ_ERRNO_START_STATUS + 8)

+/**

+ * @hideinitializer

+ * Operation timed out.

+ */

+#define PJ_ETIMEDOUT        (PJ_ERRNO_START_STATUS + 9)

+/**

+ * @hideinitializer

+ * Too many objects.

+ */

+#define PJ_ETOOMANY         (PJ_ERRNO_START_STATUS + 10)

+/**

+ * @hideinitializer

+ * Object is busy.

+ */

+#define PJ_EBUSY            (PJ_ERRNO_START_STATUS + 11)

+/**

+ * @hideinitializer

+ * The specified option is not supported.

+ */

+#define PJ_ENOTSUP	    (PJ_ERRNO_START_STATUS + 12)

+/**

+ * @hideinitializer

+ * Invalid operation.

+ */

+#define PJ_EINVALIDOP	    (PJ_ERRNO_START_STATUS + 13)

+

+/** @} */   /* pj_errnum */

+

+/** @} */   /* pj_errno */

+

+

+/**

+ * PJ_ERRNO_START is where PJLIB specific error values start.

+ */

+#define PJ_ERRNO_START		20000

+

+/**

+ * PJ_ERRNO_SPACE_SIZE is the maximum number of errors in one of 

+ * the error/status range below.

+ */

+#define PJ_ERRNO_SPACE_SIZE	50000

+

+/**

+ * PJ_ERRNO_START_STATUS is where PJLIB specific status codes start.

+ */

+#define PJ_ERRNO_START_STATUS	(PJ_ERRNO_START + PJ_ERRNO_SPACE_SIZE)

+

+/**

+ * PJ_ERRNO_START_SYS converts platform specific error codes into

+ * pj_status_t values.

+ */

+#define PJ_ERRNO_START_SYS	(PJ_ERRNO_START_STATUS + PJ_ERRNO_SPACE_SIZE)

+

+/**

+ * PJ_ERRNO_START_USER are reserved for applications that use error

+ * codes along with PJLIB codes.

+ */

+#define PJ_ERRNO_START_USER	(PJ_ERRNO_START_SYS + PJ_ERRNO_SPACE_SIZE)

+

+

+PJ_END_DECL

+

+#endif	/* __PJ_ERRNO_H__ */

+

diff --git a/pjlib/include/pj/except.h b/pjlib/include/pj/except.h
new file mode 100644
index 0000000..b325b47
--- /dev/null
+++ b/pjlib/include/pj/except.h
@@ -0,0 +1,267 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/except.h 9     10/14/05 12:26a Bennylp $ */

+

+#ifndef __PJ_EXCEPTION_H__

+#define __PJ_EXCEPTION_H__

+

+/**

+ * @file except.h

+ * @brief Exception Handling in C.

+ */

+

+#include <pj/types.h>

+#include <pj/compat/setjmp.h>

+

+

+PJ_BEGIN_DECL

+

+

+/**

+ * @defgroup PJ_EXCEPT Exception Handling

+ * @ingroup PJ_MISC

+ * @{

+ *

+ * \section pj_except_sample_sec Quick Example

+ *

+ * For the impatient, take a look at some examples:

+ *  - @ref page_pjlib_samples_except_c

+ *  - @ref page_pjlib_exception_test

+ *

+ * \section pj_except_except Exception Handling

+ *

+ * This module provides exception handling syntactically similar to C++ in

+ * C language. The underlying mechanism use setjmp() and longjmp(), and since

+ * these constructs are ANSI standard, the mechanism here should be available

+ * on most platforms/compilers which are ANSI compliant.

+ *

+ * If ANSI libc is not available, then setjmp()/longjmp() implementation will

+ * be provided. See <pj/compat/setjmp.h> for compatibility.

+ *

+ * The exception handling mechanism is completely thread safe, so the exception

+ * thrown by one thread will not interfere with other thread.

+ *

+ * CAVEATS:

+ *  - unlike C++ exception, the scheme here won't call destructors of local

+ *    objects if exception is thrown. Care must be taken when a function

+ *    hold some resorce such as pool or mutex etc.

+ *  - You CAN NOT make nested exception in one single function without using

+ *    a nested PJ_USE_EXCEPTION.

+ *  - Exceptions will always be caught by the first handle (unlike C++ where

+ *    exception is only caught if the type matches.

+ *

+ * The exception handling constructs are similar to C++. The blocks will be

+ * constructed similar to the following sample:

+ *

+ * \verbatim

+   #define NO_MEMORY     1

+   #define SYNTAX_ERROR  2

+  

+   int main()

+   {

+      PJ_USE_EXCEPTION;  // declare local exception stack.

+  

+      PJ_TRY {

+        ...// do something..

+      }

+      PJ_CATCH(NO_MEMORY) {

+        ... // handle exception 1

+      }

+      PJ_CATCH(SYNTAX_ERROR) {

+        ... // handle exception 2

+      }

+      PJ_DEFAULT {

+        ... // handle other exceptions.

+      }

+      PJ_END;

+   }

+   \endverbatim

+ *

+ * The above sample uses hard coded exception ID. It is @b strongly

+ * recommended that applications request a unique exception ID instead

+ * of hard coded value like above.

+ *

+ * \section pj_except_reg Exception ID Allocation

+ *

+ * To ensure that exception ID (number) are used consistently and to

+ * prevent ID collisions in an application, it is strongly suggested that 

+ * applications allocate an exception ID for each possible exception

+ * type. As a bonus of this process, the application can identify

+ * the name of the exception when the particular exception is thrown.

+ *

+ * Exception ID management are performed with the following APIs:

+ *  - #pj_exception_id_alloc().

+ *  - #pj_exception_id_free().

+ *  - #pj_exception_id_name().

+ *

+ *

+ * PJLIB itself automatically allocates one exception id, i.e.

+ * #PJ_NO_MEMORY_EXCEPTION which is declared in <pj/pool.h>. This exception

+ * ID is raised by default pool policy when it fails to allocate memory.

+ *

+ * \section PJ_EX_KEYWORDS Keywords

+ *

+ * \subsection PJ_THROW PJ_THROW(expression)

+ * Throw an exception. The expression thrown is an integer as the result of

+ * the \a expression. This keyword can be specified anywhere within the 

+ * program.

+ *

+ * \subsection PJ_USE_EXCEPTION PJ_USE_EXCEPTION

+ * Specify this in the variable definition section of the function block 

+ * (or any blocks) to specify that the block has \a PJ_TRY/PJ_CATCH exception 

+ * block. 

+ * Actually, this is just a macro to declare local variable which is used to

+ * push the exception state to the exception stack.

+ *

+ * \subsection PJ_TRY PJ_TRY

+ * The \a PJ_TRY keyword is typically followed by a block. If an exception is

+ * thrown in this block, then the execution will resume to the \a PJ_CATCH 

+ * handler.

+ *

+ * \subsection PJ_CATCH PJ_CATCH(expression)

+ * The \a PJ_CATCH is normally followed by a block. This block will be executed

+ * if the exception being thrown is equal to the expression specified in the

+ * \a PJ_CATCH.

+ *

+ * \subsection PJ_DEFAULT PJ_DEFAULT

+ * The \a PJ_DEFAULT keyword is normally followed by a block. This block will

+ * be executed if the exception being thrown doesn't match any of the \a

+ * PJ_CATCH specification. The \a PJ_DEFAULT block \b MUST be placed as the

+ * last block of the handlers.

+ *

+ * \subsection PJ_END PJ_END

+ * Specify this keyword to mark the end of \a PJ_TRY / \a PJ_CATCH blocks.

+ *

+ * \subsection PJ_GET_EXCEPTION PJ_GET_EXCEPTION(void)

+ * Get the last exception thrown. This macro is normally called inside the

+ * \a PJ_CATCH or \a PJ_DEFAULT block, altough it can be used anywhere where

+ * the \a PJ_USE_EXCEPTION definition is in scope.

+ *

+ * 

+ * \section pj_except_examples_sec Examples

+ *

+ * For some examples on how to use the exception construct, please see:

+ *  - @ref page_pjlib_samples_except_c

+ *  - @ref page_pjlib_exception_test

+ */

+

+/**

+ * Allocate a unique exception id.

+ * Applications don't have to allocate a unique exception ID before using

+ * the exception construct. However, by doing so it ensures that there is

+ * no collisions of exception ID.

+ *

+ * As a bonus, when exception number is acquired through this function,

+ * the library can assign name to the exception (only if 

+ * PJ_HAS_EXCEPTION_NAMES is enabled (default is yes)) and find out the

+ * exception name when it catches an exception.

+ *

+ * @param name      Name to be associated with the exception ID.

+ * @param id        Pointer to receive the ID.

+ *

+ * @return          PJ_SUCCESS on success or PJ_ETOOMANY if the library 

+ *                  is running out out ids.

+ */

+PJ_DECL(pj_status_t) pj_exception_id_alloc(const char *name,

+                                           pj_exception_id_t *id);

+

+/**

+ * Free an exception id.

+ *

+ * @param id        The exception ID.

+ *

+ * @return          PJ_SUCCESS or the appropriate error code.

+ */

+PJ_DECL(pj_status_t) pj_exception_id_free(pj_exception_id_t id);

+

+/**

+ * Retrieve name associated with the exception id.

+ *

+ * @param id        The exception ID.

+ *

+ * @return          The name associated with the specified ID.

+ */

+PJ_DECL(const char*) pj_exception_id_name(pj_exception_id_t id);

+

+/** @} */

+

+/**

+ * This structure (which should be invisible to user) manages the TRY handler

+ * stack.

+ */

+struct pj_exception_state_t

+{

+    struct pj_exception_state_t *prev;  /**< Previous state in the list. */

+    pj_jmp_buf state;                   /**< jmp_buf.                    */

+};

+

+/**

+ * Throw exception.

+ * @param id    Exception Id.

+ */

+PJ_DECL_NO_RETURN(void) 

+pj_throw_exception_(pj_exception_id_t id) PJ_ATTR_NORETURN;

+

+/**

+ * Push exception handler.

+ */

+PJ_DECL(void) pj_push_exception_handler_(struct pj_exception_state_t *rec);

+

+/**

+ * Pop exception handler.

+ */

+PJ_DECL(void) pj_pop_exception_handler_(void);

+

+/**

+ * Declare that the function will use exception.

+ * @hideinitializer

+ */

+#define PJ_USE_EXCEPTION    struct pj_exception_state_t pj_x_except__; int pj_x_code__

+

+/**

+ * Start exception specification block.

+ * @hideinitializer

+ */

+#define PJ_TRY		    if (1) { \

+				pj_push_exception_handler_(&pj_x_except__); \

+				pj_x_code__ = pj_setjmp(pj_x_except__.state); \

+				if (pj_x_code__ == 0)

+/**

+ * Catch the specified exception Id.

+ * @param id    The exception number to catch.

+ * @hideinitializer

+ */

+#define PJ_CATCH(id)	    else if (pj_x_code__ == (id))

+

+/**

+ * Catch any exception number.

+ * @hideinitializer

+ */

+#define PJ_DEFAULT	    else

+

+/**

+ * End of exception specification block.

+ * @hideinitializer

+ */

+#define PJ_END			pj_pop_exception_handler_(); \

+			    } else {}

+

+/**

+ * Throw exception.

+ * @param exception_id  The exception number.

+ * @hideinitializer

+ */

+#define PJ_THROW(exception_id)	pj_throw_exception_(exception_id)

+

+/**

+ * Get current exception.

+ * @return      Current exception code.

+ * @hideinitializer

+ */

+#define PJ_GET_EXCEPTION()	(pj_x_code__)

+

+PJ_END_DECL

+

+

+

+#endif	/* __PJ_EXCEPTION_H__ */

+

+

diff --git a/pjlib/include/pj/fifobuf.h b/pjlib/include/pj/fifobuf.h
new file mode 100644
index 0000000..45f91b1
--- /dev/null
+++ b/pjlib/include/pj/fifobuf.h
@@ -0,0 +1,27 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/fifobuf.h 4     10/14/05 12:26a Bennylp $ */

+

+#ifndef __PJ_FIFOBUF_H__

+#define __PJ_FIFOBUF_H__

+

+#include <pj/types.h>

+

+PJ_BEGIN_DECL

+

+typedef struct pj_fifobuf_t pj_fifobuf_t;

+struct pj_fifobuf_t

+{

+    char *first, *last;

+    char *ubegin, *uend;

+    int full;

+};

+

+PJ_DECL(void)	     pj_fifobuf_init (pj_fifobuf_t *fb, void *buffer, unsigned size);

+PJ_DECL(unsigned)    pj_fifobuf_max_size (pj_fifobuf_t *fb);

+PJ_DECL(void*)	     pj_fifobuf_alloc (pj_fifobuf_t *fb, unsigned size);

+PJ_DECL(pj_status_t) pj_fifobuf_unalloc (pj_fifobuf_t *fb, void *buf);

+PJ_DECL(pj_status_t) pj_fifobuf_free (pj_fifobuf_t *fb, void *buf);

+

+PJ_END_DECL

+

+#endif	/* __PJ_FIFOBUF_H__ */

+

diff --git a/pjlib/include/pj/guid.h b/pjlib/include/pj/guid.h
new file mode 100644
index 0000000..7dccf7f
--- /dev/null
+++ b/pjlib/include/pj/guid.h
@@ -0,0 +1,75 @@
+/* $header: $ */

+

+#ifndef __PJ_GUID_H__

+#define __PJ_GUID_H__

+

+

+/**

+ * @file guid.h

+ * @brief GUID Globally Unique Identifier.

+ */

+#include <pj/types.h>

+

+

+PJ_BEGIN_DECL

+

+

+/**

+ * @defgroup PJ_DS Data Structure.

+ * @ingroup PJ

+ */

+/**

+ * @defgroup PJ_GUID Globally Unique Identifier

+ * @ingroup PJ_DS

+ * @{

+ *

+ * This module provides API to create string that is globally unique.

+ * If application doesn't require that strong requirement, it can just

+ * use #pj_create_random_string() instead.

+ */

+

+

+/**

+ * PJ_GUID_STRING_LENGTH specifies length of GUID string. The value is

+ * dependent on the algorithm used internally to generate the GUID string.

+ * If real GUID generator is used, then the length will be 128bit or 

+ * 32 bytes. If shadow GUID generator is used, then the length

+ * will be 20 bytes. Application should not assume which algorithm will

+ * be used by GUID generator.

+ */

+extern const unsigned PJ_GUID_STRING_LENGTH;

+

+/**

+ * PJ_GUID_MAX_LENGTH specifies the maximum length of GUID string,

+ * regardless of which algorithm to use.

+ */

+#define PJ_GUID_MAX_LENGTH  32

+

+/**

+ * Create a globally unique string, which length is PJ_GUID_STRING_LENGTH

+ * characters. Caller is responsible for preallocating the storage used

+ * in the string.

+ *

+ * @param str       The string to store the result.

+ *

+ * @return          The string.

+ */

+PJ_DECL(pj_str_t*) pj_generate_unique_string(pj_str_t *str);

+

+/**

+ * Generate a unique string.

+ *

+ * @param pool	    Pool to allocate memory from.

+ * @param str	    The string.

+ */

+PJ_DECL(void) pj_create_unique_string(pj_pool_t *pool, pj_str_t *str);

+

+

+/**

+ * @}

+ */

+

+PJ_END_DECL

+

+#endif/* __PJ_GUID_H__ */

+

diff --git a/pjlib/include/pj/hash.h b/pjlib/include/pj/hash.h
new file mode 100644
index 0000000..f475dcc
--- /dev/null
+++ b/pjlib/include/pj/hash.h
@@ -0,0 +1,140 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/hash.h 6     10/14/05 12:26a Bennylp $ */

+

+#ifndef __PJ_HASH_H__

+#define __PJ_HASH_H__

+

+/**

+ * @file hash.h

+ * @brief Hash Table.

+ */

+

+#include <pj/types.h>

+

+PJ_BEGIN_DECL

+

+/**

+ * @defgroup PJ_HASH Hash Table

+ * @ingroup PJ_DS

+ * @{

+ * A hash table is a dictionary in which keys are mapped to array positions by

+ * hash functions. Having the keys of more than one item map to the same 

+ * position is called a collision. In this library, we will chain the nodes

+ * that have the same key in a list.

+ */

+

+/**

+ * If this constant is used as keylen, then the key is interpreted as

+ * NULL terminated string.

+ */

+#define PJ_HASH_KEY_STRING	((unsigned)-1)

+

+/**

+ * This is the function that is used by the hash table to calculate hash value

+ * of the specified key.

+ *

+ * @param hval	    the initial hash value, or zero.

+ * @param key	    the key to calculate.

+ * @param keylen    the length of the key, or PJ_HASH_KEY_STRING to treat 

+ *		    the key as null terminated string.

+ *

+ * @return          the hash value.

+ */

+PJ_DECL(pj_uint32_t) pj_hash_calc(pj_uint32_t hval, 

+				  const void *key, unsigned keylen);

+

+

+/**

+ * Create a hash table with the specified 'bucket' size.

+ *

+ * @param pool	the pool from which the hash table will be allocated from.

+ * @param size	the bucket size, which will be round-up to the nearest 2^n+1

+ *

+ * @return the hash table.

+ */

+PJ_DECL(pj_hash_table_t*) pj_hash_create(pj_pool_t *pool, unsigned size);

+

+

+/**

+ * Get the value associated with the specified key.

+ *

+ * @param ht	    the hash table.

+ * @param key	    the key to look for.

+ * @param keylen    the length of the key, or PJ_HASH_KEY_STRING to use the

+ *		    string length of the key.

+ *

+ * @return the value associated with the key, or NULL if the key is not found.

+ */

+PJ_DECL(void *) pj_hash_get( pj_hash_table_t *ht,

+			     const void *key, unsigned keylen );

+

+

+/**

+ * Associate/disassociate a value with the specified key.

+ *

+ * @param pool	    the pool to allocate the new entry if a new entry has to be

+ *		    created.

+ * @param ht	    the hash table.

+ * @param key	    the key.

+ * @param keylen    the length of the key, or PJ_HASH_KEY_STRING to use the 

+ *		    string length of the key.

+ * @param value	    value to be associated, or NULL to delete the entry with

+ *		    the specified key.

+ */

+PJ_DECL(void) pj_hash_set( pj_pool_t *pool, pj_hash_table_t *ht,

+			   const void *key, unsigned keylen,

+			   void *value );

+

+/**

+ * Get the total number of entries in the hash table.

+ *

+ * @param ht	the hash table.

+ *

+ * @return the number of entries in the hash table.

+ */

+PJ_DECL(unsigned) pj_hash_count( pj_hash_table_t *ht );

+

+

+/**

+ * Get the iterator to the first element in the hash table. 

+ *

+ * @param ht	the hash table.

+ * @param it	the iterator for iterating hash elements.

+ *

+ * @return the iterator to the hash element, or NULL if no element presents.

+ */

+PJ_DECL(pj_hash_iterator_t*) pj_hash_first( pj_hash_table_t *ht,

+					    pj_hash_iterator_t *it );

+

+

+/**

+ * Get the next element from the iterator.

+ *

+ * @param ht	the hash table.

+ * @param it	the hash iterator.

+ *

+ * @return the next iterator, or NULL if there's no more element.

+ */

+PJ_DECL(pj_hash_iterator_t*) pj_hash_next( pj_hash_table_t *ht, 

+					   pj_hash_iterator_t *it );

+

+/**

+ * Get the value associated with a hash iterator.

+ *

+ * @param ht	the hash table.

+ * @param it	the hash iterator.

+ *

+ * @return the value associated with the current element in iterator.

+ */

+PJ_DECL(void*) pj_hash_this( pj_hash_table_t *ht,

+			     pj_hash_iterator_t *it );

+

+

+/**

+ * @}

+ */

+

+PJ_END_DECL

+

+#endif

+

+

diff --git a/pjlib/include/pj/ioqueue.h b/pjlib/include/pj/ioqueue.h
new file mode 100644
index 0000000..4262ac7
--- /dev/null
+++ b/pjlib/include/pj/ioqueue.h
@@ -0,0 +1,473 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/ioqueue.h 10    10/29/05 11:29a Bennylp $ */

+

+#ifndef __PJ_IOQUEUE_H__

+#define __PJ_IOQUEUE_H__

+

+/**

+ * @file ioqueue.h

+ * @brief I/O Dispatching Mechanism

+ */

+

+#include <pj/types.h>

+

+PJ_BEGIN_DECL

+

+/**

+ * @defgroup PJ_IO Network I/O

+ * @brief Network I/O

+ * @ingroup PJ_OS

+ *

+ * This section contains API building blocks to perform network I/O and 

+ * communications. If provides:

+ *  - @ref PJ_SOCK

+ *\n

+ *    A highly portable socket abstraction, runs on all kind of

+ *    network APIs such as standard BSD socket, Windows socket, Linux

+ *    \b kernel socket, PalmOS networking API, etc.

+ *

+ *  - @ref pj_addr_resolve

+ *\n

+ *    Portable address resolution, which implements #pj_gethostbyname().

+ *

+ *  - @ref PJ_SOCK_SELECT

+ *\n

+ *    A portable \a select() like API (#pj_sock_select()) which can be

+ *    implemented with various back-ends.

+ *

+ *  - @ref PJ_IOQUEUE

+ *\n

+ *    Framework for dispatching network events.

+ *

+ * For more information see the modules below.

+ */

+

+/**

+ * @defgroup PJ_IOQUEUE I/O Event Dispatching Queue

+ * @ingroup PJ_IO

+ * @{

+ *

+ * This file provides abstraction for various event dispatching mechanisms. 

+ * The interfaces for event dispatching vary alot, even in a single

+ * operating system. The abstraction here hopefully is suitable for most of

+ * the event dispatching available.

+ *

+ * Currently, the I/O Queue supports:

+ * - select(), as the common denominator, but the least efficient.

+ * - I/O Completion ports in Windows NT/2000/XP, which is the most efficient

+ *      way to dispatch events in Windows NT based OSes, and most importantly,

+ *      it doesn't have the limit on how many handles to monitor. And it works

+ *      with files (not only sockets) as well.

+ *

+ * \section pj_ioqeuue_examples_sec Examples

+ *

+ * For some examples on how to use the I/O Queue, please see:

+ *

+ *  - \ref page_pjlib_ioqueue_tcp_test

+ *  - \ref page_pjlib_ioqueue_udp_test

+ *  - \ref page_pjlib_ioqueue_perf_test

+ */

+

+ /**

+  * This structure describes the callbacks to be called when I/O operation

+  * completes.

+  */

+typedef struct pj_ioqueue_callback

+{

+    /**

+     * This callback is called when #pj_ioqueue_read or #pj_ioqueue_recvfrom

+     * completes.

+     *

+     * @param key	    The key.

+     * @param bytes_read    The size of data that has just been read.

+     */

+    void (*on_read_complete)(pj_ioqueue_key_t *key, pj_ssize_t bytes_read);

+

+    /**

+     * This callback is called when #pj_ioqueue_write or #pj_ioqueue_sendto

+     * completes.

+     *

+     * @param key	    The key.

+     * @param bytes_read    The size of data that has just been read.

+     */

+    void (*on_write_complete)(pj_ioqueue_key_t *key, pj_ssize_t bytes_sent);

+

+    /**

+     * This callback is called when #pj_ioqueue_accept completes.

+     *

+     * @param key	    The key.

+     * @param sock          Newly connected socket.

+     * @param status	    Zero if the operation completes successfully.

+     */

+    void (*on_accept_complete)(pj_ioqueue_key_t *key, pj_sock_t sock, 

+                               int status);

+

+    /**

+     * This callback is called when #pj_ioqueue_connect completes.

+     *

+     * @param key	    The key.

+     * @param status	    Zero if the operation completes successfully.

+     */

+    void (*on_connect_complete)(pj_ioqueue_key_t *key, int status);

+} pj_ioqueue_callback;

+

+

+/**

+ * Types of I/O Queue operation.

+ */

+typedef enum pj_ioqueue_operation_e

+{

+    PJ_IOQUEUE_OP_NONE		= 0,	/**< No operation.          */

+    PJ_IOQUEUE_OP_READ		= 1,	/**< read() operation.      */

+    PJ_IOQUEUE_OP_RECV          = 2,    /**< recv() operation.      */

+    PJ_IOQUEUE_OP_RECV_FROM	= 4,	/**< recvfrom() operation.  */

+    PJ_IOQUEUE_OP_WRITE		= 8,	/**< write() operation.     */

+    PJ_IOQUEUE_OP_SEND          = 16,   /**< send() operation.      */

+    PJ_IOQUEUE_OP_SEND_TO	= 32,	/**< sendto() operation.    */

+#if defined(PJ_HAS_TCP) && PJ_HAS_TCP != 0

+    PJ_IOQUEUE_OP_ACCEPT	= 64,	/**< accept() operation.    */

+    PJ_IOQUEUE_OP_CONNECT	= 128,	/**< connect() operation.   */

+#endif	/* PJ_HAS_TCP */

+} pj_ioqueue_operation_e;

+

+

+/**

+ * Indicates that the I/O Queue should be created to handle reasonable

+ * number of threads.

+ */

+#define PJ_IOQUEUE_DEFAULT_THREADS  0

+

+

+/**

+ * Create a new I/O Queue framework.

+ *

+ * @param pool		The pool to allocate the I/O queue structure. 

+ * @param max_fd	The maximum number of handles to be supported, which 

+ *			should not exceed PJ_IOQUEUE_MAX_HANDLES.

+ * @param max_threads	The maximum number of threads that are allowed to

+ *			operate on a single descriptor simultaneously. If

+ *                      the value is zero, the framework will set it

+ *                      to a reasonable value.

+ * @param ioqueue	Pointer to hold the newly created I/O Queue.

+ *

+ * @return		PJ_SUCCESS on success.

+ */

+PJ_DECL(pj_status_t) pj_ioqueue_create( pj_pool_t *pool, 

+					pj_size_t max_fd,

+					int max_threads,

+					pj_ioqueue_t **ioqueue);

+

+/**

+ * Destroy the I/O queue.

+ *

+ * @param ioque	        The I/O Queue to be destroyed.

+ *

+ * @return              PJ_SUCCESS if success.

+ */

+PJ_DECL(pj_status_t) pj_ioqueue_destroy( pj_ioqueue_t *ioque );

+

+/**

+ * Set the lock object to be used by the I/O Queue. This function can only

+ * be called right after the I/O queue is created, before any handle is

+ * registered to the I/O queue.

+ *

+ * Initially the I/O queue is created with non-recursive mutex protection. 

+ * Applications can supply alternative lock to be used by calling this 

+ * function.

+ *

+ * @param ioque         The ioqueue instance.

+ * @param lock          The lock to be used by the ioqueue.

+ * @param auto_delete   In non-zero, the lock will be deleted by the ioqueue.

+ *

+ * @return              PJ_SUCCESS or the appropriate error code.

+ */

+PJ_DECL(pj_status_t) pj_ioqueue_set_lock( pj_ioqueue_t *ioque, 

+					  pj_lock_t *lock,

+					  pj_bool_t auto_delete );

+

+/**

+ * Register a socket to the I/O queue framework. 

+ * When a socket is registered to the IOQueue, it may be modified to use

+ * non-blocking IO. If it is modified, there is no guarantee that this 

+ * modification will be restored after the socket is unregistered.

+ *

+ * @param pool	    To allocate the resource for the specified handle, 

+ *		    which must be valid until the handle/key is unregistered 

+ *		    from I/O Queue.

+ * @param ioque	    The I/O Queue.

+ * @param sock	    The socket.

+ * @param user_data User data to be associated with the key, which can be

+ *		    retrieved later.

+ * @param cb	    Callback to be called when I/O operation completes. 

+ * @param key	    Pointer to receive the returned key.

+ *

+ * @return	    PJ_SUCCESS on success, or the error code.

+ */

+PJ_DECL(pj_status_t) pj_ioqueue_register_sock( pj_pool_t *pool,

+					       pj_ioqueue_t *ioque,

+					       pj_sock_t sock,

+					       void *user_data,

+					       const pj_ioqueue_callback *cb,

+					       pj_ioqueue_key_t **key);

+

+/**

+ * Unregister a handle from the I/O Queue framework.

+ *

+ * @param ioque     The I/O Queue.

+ * @param key	    The key that uniquely identifies the handle, which is 

+ *                  returned from the function #pj_ioqueue_register_sock()

+ *                  or other registration functions.

+ *

+ * @return          PJ_SUCCESS on success or the error code.

+ */

+PJ_DECL(pj_status_t) pj_ioqueue_unregister( pj_ioqueue_t *ioque,

+					    pj_ioqueue_key_t *key );

+

+

+/**

+ * Get user data associated with the I/O Queue key.

+ *

+ * @param key	    The key previously associated with the socket/handle with

+ *		    #pj_ioqueue_register_sock() (or other registration 

+ *                  functions).

+ *

+ * @return          The user data associated with the key, or NULL on error

+ *                  of if no data is associated with the key during 

+ *                  registration.

+ */

+PJ_DECL(void*) pj_ioqueue_get_user_data( pj_ioqueue_key_t *key );

+

+

+#if defined(PJ_HAS_TCP) && PJ_HAS_TCP != 0

+/**

+ * Instruct I/O Queue to wait for incoming connections on the specified 

+ * listening socket. This function will return

+ * immediately (i.e. non-blocking) regardless whether some data has been 

+ * transfered. If the function can't complete immediately, and the caller will

+ * be notified about the completion when it calls pj_ioqueue_poll().

+ *

+ * @param ioqueue   The I/O Queue

+ * @param key	    The key which registered to the server socket.

+ * @param sock	    Argument which contain pointer to receive 

+ *                  the socket for the incoming connection.

+ * @param local	    Optional argument which contain pointer to variable to 

+ *                  receive local address.

+ * @param remote    Optional argument which contain pointer to variable to 

+ *                  receive the remote address.

+ * @param addrlen   On input, contains the length of the buffer for the

+ *		    address, and on output, contains the actual length of the

+ *		    address. This argument is optional.

+ * @return

+ *  - PJ_SUCCESS    If there's a connection available immediately, which 

+ *                  in this case the callback should have been called before 

+ *                  the function returns.

+ *  - PJ_EPENDING   If accept is queued, or 

+ *  - non-zero      which indicates the appropriate error code.

+ */

+PJ_DECL(pj_status_t) pj_ioqueue_accept( pj_ioqueue_t *ioqueue,

+					pj_ioqueue_key_t *key,

+					pj_sock_t *sock,

+					pj_sockaddr_t *local,

+					pj_sockaddr_t *remote,

+					int *addrlen );

+

+/**

+ * Initiate non-blocking socket connect. If the socket can NOT be connected

+ * immediately, the result will be reported during poll.

+ *

+ * @param ioqueue   The ioqueue

+ * @param key	    The key associated with TCP socket

+ * @param addr	    The remote address.

+ * @param addrlen   The remote address length.

+ *

+ * @return

+ *  - PJ_SUCCESS    If socket is connected immediately, which in this case 

+ *                  the callback should have been called.

+ *  - PJ_EPENDING   If operation is queued, or 

+ *  - non-zero      Indicates the error code.

+ */

+PJ_DECL(pj_status_t) pj_ioqueue_connect( pj_ioqueue_t *ioqueue,

+					 pj_ioqueue_key_t *key,

+					 const pj_sockaddr_t *addr,

+					 int addrlen );

+

+#endif	/* PJ_HAS_TCP */

+

+/**

+ * Poll the I/O Queue for completed events.

+ *

+ * @param ioque		the I/O Queue.

+ * @param timeout	polling timeout, or NULL if the thread wishes to wait

+ *			indefinetely for the event.

+ *

+ * @return 

+ *  - zero if timed out (no event).

+ *  - (<0) if error occured during polling. Callback will NOT be called.

+ *  - (>1) to indicate numbers of events. Callbacks have been called.

+ */

+PJ_DECL(int) pj_ioqueue_poll( pj_ioqueue_t *ioque,

+			      const pj_time_val *timeout);

+

+/**

+ * Instruct the I/O Queue to read from the specified handle. This function

+ * returns immediately (i.e. non-blocking) regardless whether some data has 

+ * been transfered. If the operation can't complete immediately, caller will 

+ * be notified about the completion when it calls pj_ioqueue_poll().

+ *

+ * @param ioque	    The I/O Queue.

+ * @param key	    The key that uniquely identifies the handle.

+ * @param buffer    The buffer to hold the read data. The caller MUST make sure

+ *		    that this buffer remain valid until the framework completes

+ *		    reading the handle.

+ * @param buflen    The maximum size to be read.

+ *

+ * @return

+ *  - PJ_SUCCESS    If immediate data has been received. In this case, the 

+ *		    callback must have been called before this function 

+ *		    returns, and no pending operation is scheduled.

+ *  - PJ_EPENDING   If the operation has been queued.

+ *  - non-zero      The return value indicates the error code.

+ */

+PJ_DECL(pj_status_t) pj_ioqueue_read( pj_ioqueue_t *ioque,

+				      pj_ioqueue_key_t *key,

+				      void *buffer,

+				      pj_size_t buflen);

+

+

+/**

+ * This function behaves similarly as #pj_ioqueue_read(), except that it is

+ * normally called for socket.

+ *

+ * @param ioque	    The I/O Queue.

+ * @param key	    The key that uniquely identifies the handle.

+ * @param buffer    The buffer to hold the read data. The caller MUST make sure

+ *		    that this buffer remain valid until the framework completes

+ *		    reading the handle.

+ * @param buflen    The maximum size to be read.

+ * @param flags     Recv flag.

+ *

+ * @return

+ *  - PJ_SUCCESS    If immediate data has been received. In this case, the 

+ *		    callback must have been called before this function 

+ *		    returns, and no pending operation is scheduled.

+ *  - PJ_EPENDING   If the operation has been queued.

+ *  - non-zero      The return value indicates the error code.

+ */

+PJ_DECL(pj_status_t) pj_ioqueue_recv( pj_ioqueue_t *ioque,

+				      pj_ioqueue_key_t *key,

+				      void *buffer,

+				      pj_size_t buflen,

+				      unsigned flags );

+

+/**

+ * This function behaves similarly as #pj_ioqueue_read(), except that it is

+ * normally called for socket, and the remote address will also be returned

+ * along with the data. Caller MUST make sure that both buffer and addr

+ * remain valid until the framework completes reading the data.

+ *

+ * @param ioque	    The I/O Queue.

+ * @param key	    The key that uniquely identifies the handle.

+ * @param buffer    The buffer to hold the read data. The caller MUST make sure

+ *		    that this buffer remain valid until the framework completes

+ *		    reading the handle.

+ * @param buflen    The maximum size to be read.

+ * @param flags     Recv flag.

+ * @param addr      Pointer to buffer to receive the address, or NULL.

+ * @param addrlen   On input, specifies the length of the address buffer.

+ *                  On output, it will be filled with the actual length of

+ *                  the address.

+ *

+ * @return

+ *  - PJ_SUCCESS    If immediate data has been received. In this case, the 

+ *		    callback must have been called before this function 

+ *		    returns, and no pending operation is scheduled.

+ *  - PJ_EPENDING   If the operation has been queued.

+ *  - non-zero      The return value indicates the error code.

+ */

+PJ_DECL(pj_status_t) pj_ioqueue_recvfrom( pj_ioqueue_t *ioque,

+					  pj_ioqueue_key_t *key,

+					  void *buffer,

+					  pj_size_t buflen,

+                                          unsigned flags,

+					  pj_sockaddr_t *addr,

+					  int *addrlen);

+

+/**

+ * Instruct the I/O Queue to write to the handle. This function will return

+ * immediately (i.e. non-blocking) regardless whether some data has been 

+ * transfered. If the function can't complete immediately, and the caller will

+ * be notified about the completion when it calls pj_ioqueue_poll().

+ *

+ * @param ioque	    the I/O Queue.

+ * @param key	    the key that identifies the handle.

+ * @param data	    the data to send. Caller MUST make sure that this buffer 

+ *		    remains valid until the write operation completes.

+ * @param datalen   the length of the data.

+ *

+ * @return

+ *  - PJ_SUCCESS    If data was immediately written.

+ *  - PJ_EPENDING   If the operation has been queued.

+ *  - non-zero      The return value indicates the error code.

+ */

+PJ_DECL(pj_status_t) pj_ioqueue_write( pj_ioqueue_t *ioque,

+				       pj_ioqueue_key_t *key,

+				       const void *data,

+				       pj_size_t datalen);

+

+/**

+ * This function behaves similarly as #pj_ioqueue_write(), except that

+ * pj_sock_send() (or equivalent) will be called to send the data.

+ *

+ * @param ioque	    the I/O Queue.

+ * @param key	    the key that identifies the handle.

+ * @param data	    the data to send. Caller MUST make sure that this buffer 

+ *		    remains valid until the write operation completes.

+ * @param datalen   the length of the data.

+ * @param flags     send flags.

+ *

+ * @return

+ *  - PJ_SUCCESS    If data was immediately written.

+ *  - PJ_EPENDING   If the operation has been queued.

+ *  - non-zero      The return value indicates the error code.

+ */

+PJ_DECL(pj_status_t) pj_ioqueue_send( pj_ioqueue_t *ioque,

+				      pj_ioqueue_key_t *key,

+				      const void *data,

+				      pj_size_t datalen,

+				      unsigned flags );

+

+

+/**

+ * This function behaves similarly as #pj_ioqueue_write(), except that

+ * pj_sock_sendto() (or equivalent) will be called to send the data.

+ *

+ * @param ioque	    the I/O Queue.

+ * @param key	    the key that identifies the handle.

+ * @param data	    the data to send. Caller MUST make sure that this buffer 

+ *		    remains valid until the write operation completes.

+ * @param datalen   the length of the data.

+ * @param flags     send flags.

+ * @param addr      remote address.

+ * @param addrlen   remote address length.

+ *

+ * @return

+ *  - PJ_SUCCESS    If data was immediately written.

+ *  - PJ_EPENDING   If the operation has been queued.

+ *  - non-zero      The return value indicates the error code.

+ */

+PJ_DECL(pj_status_t) pj_ioqueue_sendto( pj_ioqueue_t *ioque,

+					pj_ioqueue_key_t *key,

+					const void *data,

+					pj_size_t datalen,

+                                        unsigned flags,

+					const pj_sockaddr_t *addr,

+					int addrlen);

+

+

+/**

+ * !}

+ */

+

+PJ_END_DECL

+

+#endif	/* __PJ_IOQUEUE_H__ */

+

diff --git a/pjlib/include/pj/list.h b/pjlib/include/pj/list.h
new file mode 100644
index 0000000..0b18f89
--- /dev/null
+++ b/pjlib/include/pj/list.h
@@ -0,0 +1,217 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/list.h 8     10/14/05 12:26a Bennylp $ */

+

+#ifndef __PJ_LIST_H__

+#define __PJ_LIST_H__

+

+/**

+ * @file list.h

+ * @brief Linked List data structure.

+ */

+

+#include <pj/types.h>

+

+PJ_BEGIN_DECL

+

+/*

+ * @defgroup PJ_DS Data Structure.

+ * @ingroup PJ

+ */

+

+/**

+ * @defgroup PJ_LIST Linked List

+ * @ingroup PJ_DS

+ * @{

+ *

+ * List in PJLIB is implemented as doubly-linked list, and it won't require

+ * dynamic memory allocation (just as all PJLIB data structures). The list here

+ * should be viewed more like a low level C list instead of high level C++ list

+ * (which normally are easier to use but require dynamic memory allocations),

+ * therefore all caveats with C list apply here too (such as you can NOT put

+ * a node in more than one lists).

+ *

+ * \section pj_list_example_sec Examples

+ *

+ * See below for examples on how to manipulate linked list:

+ *  - @ref page_pjlib_samples_list_c

+ *  - @ref page_pjlib_list_test

+ */

+

+

+/**

+ * Use this macro in the start of the structure declaration to declare that

+ * the structure can be used in the linked list operation. This macro simply

+ * declares additional member @a prev and @a next to the structure.

+ * @hideinitializer

+ */

+#define PJ_DECL_LIST_MEMBER(type)  type *prev; /** List @a prev. */ \

+                                   type *next; /** List @a next. */ 

+

+

+/**

+ * This structure describes generic list node and list. The owner of this list

+ * must initialize the 'value' member to an appropriate value (typically the

+ * owner itself).

+ */

+struct pj_list

+{

+    PJ_DECL_LIST_MEMBER(void)

+};

+

+

+/**

+ * Initialize the list.

+ * Initially, the list will have no member, and function pj_list_empty() will

+ * always return nonzero (which indicates TRUE) for the newly initialized 

+ * list.

+ *

+ * @param node The list head.

+ */

+PJ_INLINE(void) pj_list_init(pj_list_type * node)

+{

+    ((pj_list*)node)->next = ((pj_list*)node)->prev = node;

+}

+

+

+/**

+ * Check that the list is empty.

+ *

+ * @param node	The list head.

+ *

+ * @return Non-zero if the list is not-empty, or zero if it is empty.

+ *

+ */

+PJ_INLINE(int) pj_list_empty(const pj_list_type * node)

+{

+    return ((pj_list*)node)->next == node;

+}

+

+

+/**

+ * Insert the node to the list before the specified element position.

+ *

+ * @param pos	The element to which the node will be inserted before. 

+ * @param node	The element to be inserted.

+ *

+ * @return void.

+ */

+PJ_IDECL(void)	pj_list_insert_before(pj_list_type *pos, pj_list_type *node);

+

+

+/**

+ * Inserts all nodes in \a nodes to the target list.

+ *

+ * @param lst	    The target list.

+ * @param nodes	    Nodes list.

+ */

+PJ_IDECL(void) pj_list_insert_nodes_before(pj_list_type *lst,

+					   pj_list_type *nodes);

+

+/**

+ * Insert a node to the list after the specified element position.

+ *

+ * @param pos	    The element in the list which will precede the inserted 

+ *		    element.

+ * @param node	    The element to be inserted after the position element.

+ *

+ * @return void.

+ */

+PJ_IDECL(void) pj_list_insert_after(pj_list_type *pos, pj_list_type *node);

+

+/**

+ * Insert all nodes in \a nodes to the target list.

+ *

+ * @param lst	    The target list.

+ * @param nodes	    Nodes list.

+ */

+PJ_IDECL(void) pj_list_insert_nodes_after(pj_list_type *lst,

+					  pj_list_type *nodes);

+

+

+/**

+ * Remove elements from the source list, and insert them to the destination

+ * list. The elements of the source list will occupy the

+ * front elements of the target list. Note that the node pointed by \a list2

+ * itself is not considered as a node, but rather as the list descriptor, so

+ * it will not be inserted to the \a list1. The elements to be inserted starts

+ * at \a list2->next. If \a list2 is to be included in the operation, use

+ * \a pj_list_insert_nodes_before.

+ *

+ * @param list1	The destination list.

+ * @param list2	The source list.

+ *

+ * @return void.

+ */

+PJ_IDECL(void) pj_list_merge_first(pj_list_type *list1, pj_list_type *list2);

+

+

+/**

+ * Remove elements from the second list argument, and insert them to the list 

+ * in the first argument. The elements from the second list will be appended

+ * to the first list. Note that the node pointed by \a list2

+ * itself is not considered as a node, but rather as the list descriptor, so

+ * it will not be inserted to the \a list1. The elements to be inserted starts

+ * at \a list2->next. If \a list2 is to be included in the operation, use

+ * \a pj_list_insert_nodes_before.

+ *

+ * @param list1	    The element in the list which will precede the inserted 

+ *		    element.

+ * @param list2	    The element in the list to be inserted.

+ *

+ * @return void.

+ */

+PJ_IDECL(void) pj_list_merge_last( pj_list_type *list1, pj_list_type *list2);

+

+

+/**

+ * Erase the node from the list it currently belongs.

+ *

+ * @param node	    The element to be erased.

+ */

+PJ_IDECL(void) pj_list_erase(pj_list_type *node);

+

+

+/**

+ * Find node in the list.

+ *

+ * @param list	    The list head.

+ * @param node	    The node element to be searched.

+ *

+ * @return The node itself if it is found in the list, or NULL if it is not 

+ *         found in the list.

+ */

+PJ_IDECL(pj_list_type*) pj_list_find_node(pj_list_type *list, 

+					  pj_list_type *node);

+

+

+/**

+ * Search the list for the specified value, using the specified comparison

+ * function. This function iterates on nodes in the list, started with the

+ * first node, and call the user supplied comparison function until the

+ * comparison function returns ZERO.

+ *

+ * @param list	    The list head.

+ * @param value	    The user defined value to be passed in the comparison 

+ *		    function

+ * @param comp	    The comparison function, which should return ZERO to 

+ *		    indicate that the searched value is found.

+ *

+ * @return The first node that matched, or NULL if it is not found.

+ */

+PJ_IDECL(pj_list_type*) pj_list_search(pj_list_type *list, void *value,

+				       int (*comp)(void *value, 

+						   const pj_list_type *node)

+				       );

+

+

+/**

+ * @}

+ */

+

+#if PJ_FUNCTIONS_ARE_INLINED

+#  include "list_i.h"

+#endif

+

+PJ_END_DECL

+

+#endif	/* __PJ_LIST_H__ */

+

diff --git a/pjlib/include/pj/list_i.h b/pjlib/include/pj/list_i.h
new file mode 100644
index 0000000..5f99597
--- /dev/null
+++ b/pjlib/include/pj/list_i.h
@@ -0,0 +1,101 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/list_i.h 4     10/14/05 12:26a Bennylp $ */

+

+

+/* Internal */

+PJ_IDEF(void) pj_link_node(pj_list_type *prev, pj_list_type *next)

+{

+    ((pj_list*)prev)->next = next;

+    ((pj_list*)next)->prev = prev;

+}

+

+/*

+PJ_IDEF(void) 

+pj_list_init(pj_list_type * node)

+{

+    ((pj_list*)node)->next = ((pj_list*)node)->prev = node;

+}

+

+PJ_IDEF(int) pj_list_empty(const pj_list_type * node)

+{

+    return ((pj_list*)node)->next == node;

+}

+*/

+

+PJ_IDEF(void) 

+pj_list_insert_after(pj_list_type *pos, pj_list_type *node)

+{

+    ((pj_list*)node)->prev = pos;

+    ((pj_list*)node)->next = ((pj_list*)pos)->next;

+    ((pj_list*) ((pj_list*)pos)->next) ->prev = node;

+    ((pj_list*)pos)->next = node;

+}

+

+

+PJ_IDEF(void) 

+pj_list_insert_before(pj_list_type *pos, pj_list_type *node)

+{

+    pj_list_insert_after(((pj_list*)pos)->prev, node);

+}

+

+

+PJ_IDEF(void)	    

+pj_list_insert_nodes_after(pj_list_type *pos, pj_list_type *lst)

+{

+    pj_list *lst_last = (pj_list *) ((pj_list*)lst)->prev;

+    pj_list *pos_next = (pj_list *) ((pj_list*)pos)->next;

+

+    pj_link_node(pos, lst);

+    pj_link_node(lst_last, pos_next);

+}

+

+PJ_IDEF(void) 

+pj_list_insert_nodes_before(pj_list_type *pos, pj_list_type *lst)

+{

+    pj_list_insert_nodes_after(((pj_list*)pos)->prev, lst);

+}

+

+PJ_IDEF(void)

+pj_list_merge_last(pj_list_type *lst1, pj_list_type *lst2)

+{

+    pj_link_node(((pj_list*)lst1)->prev, ((pj_list*)lst2)->next);

+    pj_link_node(((pj_list*)lst2)->prev, lst1);

+    pj_list_init(lst2);

+}

+

+PJ_IDEF(void)

+pj_list_merge_first(pj_list_type *lst1, pj_list_type *lst2)

+{

+    pj_link_node(((pj_list*)lst2)->prev, ((pj_list*)lst1)->next);

+    pj_link_node(((pj_list*)lst1), ((pj_list*)lst2)->next);

+    pj_list_init(lst2);

+}

+

+PJ_IDEF(void) 

+pj_list_erase(pj_list_type *node)

+{

+    pj_link_node( ((pj_list*)node)->prev, ((pj_list*)node)->next);

+}

+

+

+PJ_IDEF(pj_list_type*) 

+pj_list_find_node(pj_list_type *list, pj_list_type *node)

+{

+    pj_list *p = (pj_list *) ((pj_list*)list)->next;

+    while (p != list && p != node)

+	p = (pj_list *) p->next;

+

+    return p==node ? p : NULL;

+}

+

+

+PJ_IDEF(pj_list_type*) 

+pj_list_search(pj_list_type *list, void *value,

+	       int (*comp)(void *value, const pj_list_type *node))

+{

+    pj_list *p = (pj_list *) ((pj_list*)list)->next;

+    while (p != list && (*comp)(value, p) != 0)

+	p = (pj_list *) p->next;

+

+    return p==list ? NULL : p;

+}

+

diff --git a/pjlib/include/pj/lock.h b/pjlib/include/pj/lock.h
new file mode 100644
index 0000000..c487019
--- /dev/null
+++ b/pjlib/include/pj/lock.h
@@ -0,0 +1,136 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/lock.h 2     10/14/05 12:26a Bennylp $ */

+#ifndef __PJ_LOCK_H__

+#define __PJ_LOCK_H__

+

+/**

+ * @file lock.h

+ * @brief Higher abstraction for locking objects.

+ */

+#include <pj/types.h>

+

+PJ_BEGIN_DECL

+

+/**

+ * @defgroup PJ_LOCK Lock Objects

+ * @ingroup PJ_OS

+ * @{

+ *

+ * <b>Lock Objects</b> are higher abstraction for different lock mechanisms.

+ * It offers the same API for manipulating different lock types (e.g.

+ * @ref PJ_MUTEX "mutex", @ref PJ_SEM "semaphores", or null locks).

+ * Because Lock Objects have the same API for different types of lock

+ * implementation, it can be passed around in function arguments. As the

+ * result, it can be used to control locking policy for  a particular

+ * feature.

+ */

+

+

+/**

+ * Create simple, non recursive mutex lock object.

+ *

+ * @param pool	    Memory pool.

+ * @param name	    Lock object's name.

+ * @param lock	    Pointer to store the returned handle.

+ *

+ * @return	    PJ_SUCCESS or the appropriate error code.

+ */

+PJ_DECL(pj_status_t) pj_lock_create_simple_mutex( pj_pool_t *pool,

+						  const char *name,

+						  pj_lock_t **lock );

+

+/**

+ * Create recursive mutex lock object.

+ *

+ * @param pool	    Memory pool.

+ * @param name	    Lock object's name.

+ * @param lock	    Pointer to store the returned handle.

+ *

+ * @return	    PJ_SUCCESS or the appropriate error code.

+ */

+PJ_DECL(pj_status_t) pj_lock_create_recursive_mutex( pj_pool_t *pool,

+						     const char *name,

+						     pj_lock_t **lock );

+

+

+/**

+ * Create NULL mutex. A NULL mutex doesn't actually have any synchronization

+ * object attached to it.

+ *

+ * @param pool	    Memory pool.

+ * @param name	    Lock object's name.

+ * @param lock	    Pointer to store the returned handle.

+ *

+ * @return	    PJ_SUCCESS or the appropriate error code.

+ */

+PJ_DECL(pj_status_t) pj_lock_create_null_mutex( pj_pool_t *pool,

+						const char *name,

+						pj_lock_t **lock );

+

+

+#if defined(PJ_HAS_SEMAPHORE) && PJ_HAS_SEMAPHORE != 0

+/**

+ * Create semaphore lock object.

+ *

+ * @param pool	    Memory pool.

+ * @param name	    Lock object's name.

+ * @param initial   Initial value of the semaphore.

+ * @param max	    Maximum value of the semaphore.

+ * @param lock	    Pointer to store the returned handle.

+ *

+ * @return	    PJ_SUCCESS or the appropriate error code.

+ */

+PJ_DECL(pj_status_t) pj_lock_create_semaphore( pj_pool_t *pool,

+					       const char *name,

+					       unsigned initial,

+					       unsigned max,

+					       pj_lock_t **lock );

+

+#endif	/* PJ_HAS_SEMAPHORE */

+

+/**

+ * Acquire lock on the specified lock object.

+ *

+ * @param lock	    The lock object.

+ *

+ * @return	    PJ_SUCCESS or the appropriate error code.

+ */

+PJ_DECL(pj_status_t) pj_lock_acquire( pj_lock_t *lock );

+

+

+/**

+ * Try to acquire lock on the specified lock object.

+ *

+ * @param lock	    The lock object.

+ *

+ * @return	    PJ_SUCCESS or the appropriate error code.

+ */

+PJ_DECL(pj_status_t) pj_lock_tryacquire( pj_lock_t *lock );

+

+

+/**

+ * Release lock on the specified lock object.

+ *

+ * @param lock	    The lock object.

+ *

+ * @return	    PJ_SUCCESS or the appropriate error code.

+ */

+PJ_DECL(pj_status_t) pj_lock_release( pj_lock_t *lock );

+

+

+/**

+ * Destroy the lock object.

+ *

+ * @param lock	    The lock object.

+ *

+ * @return	    PJ_SUCCESS or the appropriate error code.

+ */

+PJ_DECL(pj_status_t) pj_lock_destroy( pj_lock_t *lock );

+

+

+/** @} */

+

+PJ_END_DECL

+

+

+#endif	/* __PJ_LOCK_H__ */

+

diff --git a/pjlib/include/pj/log.h b/pjlib/include/pj/log.h
new file mode 100644
index 0000000..5d24f56
--- /dev/null
+++ b/pjlib/include/pj/log.h
@@ -0,0 +1,304 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/log.h 7     10/14/05 12:26a Bennylp $ */

+

+#ifndef __PJ_LOG_H__

+#define __PJ_LOG_H__

+

+/**

+ * @file log.h

+ * @brief Logging Utility.

+ */

+

+#include <pj/types.h>

+

+

+PJ_BEGIN_DECL

+

+/**

+ * @defgroup PJ_MISC Miscelaneous

+ * @ingroup PJ

+ */

+

+/**

+ * @defgroup PJ_LOG Logging Facility

+ * @ingroup PJ_MISC

+ * @{

+ *

+ * The PJLIB logging facility is a configurable, flexible, and convenient

+ * way to write logging or trace information.

+ *

+ * To write to the log, one uses construct like below:

+ *

+ * <pre>

+ *   ...

+ *   PJ_LOG(3, ("main.c", "Starting hello..."));

+ *   ...

+ *   PJ_LOG(3, ("main.c", "Hello world from process %d", pj_getpid()));

+ *   ...

+ * </pre>

+ *

+ * In the above example, the number @b 3 controls the verbosity level of

+ * the information (which means "information", by convention). The string

+ * "main.c" specifies the source or sender of the message.

+ *

+ *

+ * \section pj_log_quick_sample_sec Examples

+ *

+ * For examples, see:

+ *  - @ref page_pjlib_samples_log_c.

+ *

+ */

+

+/**

+ * Log decoration flag, to be specified with #pj_log_set_decor().

+ */

+enum pj_log_decoration

+{

+    PJ_LOG_HAS_DAY_NAME   =   1, /**< Include day name [default: no].	     */

+    PJ_LOG_HAS_YEAR       =   2, /**< Include year digit [default: no]	     */

+    PJ_LOG_HAS_MONTH	  =   4, /**< Include month [default: no]	     */

+    PJ_LOG_HAS_DAY_OF_MON =   8, /**< Include day of month [default: no]     */

+    PJ_LOG_HAS_TIME	  =  16, /**< Include time [default: yes].	     */

+    PJ_LOG_HAS_MICRO_SEC  =  32, /**< Include microseconds [yes]             */

+    PJ_LOG_HAS_SENDER	  =  64, /**< Include sender in the log [yes].	     */

+    PJ_LOG_HAS_NEWLINE	  = 128, /**< Terminate each call with newline [yes].*/

+};

+

+/**

+ * Write log message.

+ * This is the main macro used to write text to the logging backend. 

+ *

+ * @param level	    The logging verbosity level. Lower number indicates higher

+ *		    importance, with level zero indicates fatal error. Only

+ *		    numeral argument is permitted (e.g. not variable).

+ * @param arg	    Enclosed 'printf' like arguments, with the first 

+ *		    argument is the sender, the second argument is format 

+ *		    string and the following arguments are variable number of 

+ *		    arguments suitable for the format string.

+ *

+ * Sample:

+ * \verbatim

+   PJ_LOG(2, (__FILE__, "current value is %d", value));

+   \endverbatim

+ * @hideinitializer

+ */

+#define PJ_LOG(level,arg)	pj_log_wrapper_##level(arg)

+

+/**

+ * Signature for function to be registered to the logging subsystem to

+ * write the actual log message to some output device.

+ *

+ * @param level	    Log level.

+ * @param data	    Log message.

+ * @param len	    Message length.

+ */

+typedef void pj_log_func(int level, const char *data, int len);

+

+/**

+ * Default logging writer function used by front end logger function.

+ * Application normally should NOT need to call this function, but

+ * rather use the PJ_LOG macro.

+ *

+ * @param level	    Log level.

+ * @param buffer    Log message.

+ * @param len	    Message length.

+ */

+PJ_DECL(void) pj_log_write(int level, const char *buffer, int len);

+

+

+#if PJ_LOG_MAX_LEVEL >= 1

+

+/**

+ * Change log output function. The front-end logging functions will call

+ * this function to write the actual message to the desired device. 

+ * By default, the front-end functions use pj_log_write() to write

+ * the messages, unless it's changed by calling this function.

+ *

+ * @param func	    The function that will be called to write the log

+ *		    messages to the desired device.

+ */

+PJ_DECL(void) pj_log_set_log_func( pj_log_func *func );

+

+/**

+ * Get the current log output function that is used to write log messages.

+ *

+ * @return	    Current log output function.

+ */

+PJ_DECL(pj_log_func*) pj_log_get_log_func(void);

+

+/**

+ * Set maximum log level. Application can call this function to set 

+ * the desired level of verbosity of the logging messages. The bigger the

+ * value, the more verbose the logging messages will be printed. However,

+ * the maximum level of verbosity can not exceed compile time value of

+ * PJ_LOG_MAX_LEVEL.

+ *

+ * @param level	    The maximum level of verbosity of the logging

+ *		    messages (6=very detailed..1=error only, 0=disabled)

+ */

+PJ_DECL(void) pj_log_set_level(int level);

+

+/**

+ * Get current maximum log verbositylevel.

+ *

+ * @return	    Current log maximum level.

+ */

+PJ_DECL(int) pj_log_get_level(void);

+

+/**

+ * Set log decoration. The log decoration flag controls what are printed

+ * to output device alongside the actual message. For example, application

+ * can specify that date/time information should be displayed with each

+ * log message.

+ *

+ * @param decor	    Bitmask combination of #pj_log_decoration to control

+ *		    the layout of the log message.

+ */

+PJ_DECL(void) pj_log_set_decor(unsigned decor);

+

+/**

+ * Get current log decoration flag.

+ *

+ * @return	    Log decoration flag.

+ */

+PJ_DECL(unsigned) pj_log_get_decor(void);

+

+

+#else	/* #if PJ_LOG_MAX_LEVEL >= 1 */

+

+/**

+ * Change log output function. The front-end logging functions will call

+ * this function to write the actual message to the desired device. 

+ * By default, the front-end functions use pj_log_write() to write

+ * the messages, unless it's changed by calling this function.

+ *

+ * @param func	    The function that will be called to write the log

+ *		    messages to the desired device.

+ */

+#  define pj_log_set_log_func(func)

+

+/**

+ * Set maximum log level. Application can call this function to set 

+ * the desired level of verbosity of the logging messages. The bigger the

+ * value, the more verbose the logging messages will be printed. However,

+ * the maximum level of verbosity can not exceed compile time value of

+ * PJ_LOG_MAX_LEVEL.

+ *

+ * @param level	    The maximum level of verbosity of the logging

+ *		    messages (6=very detailed..1=error only, 0=disabled)

+ */

+#  define pj_log_set_level(level)

+

+/**

+ * Set log decoration. The log decoration flag controls what are printed

+ * to output device alongside the actual message. For example, application

+ * can specify that date/time information should be displayed with each

+ * log message.

+ *

+ * @param decor	    Bitmask combination of #pj_log_decoration to control

+ *		    the layout of the log message.

+ */

+#  define pj_log_set_decor(decor)

+

+#endif	/* #if PJ_LOG_MAX_LEVEL >= 1 */

+

+/** 

+ * @}

+ */

+

+///////////////////////////////////////////////////////////////////////////////

+/*

+ * Log functions implementation prototypes.

+ * These functions are called by PJ_LOG macros according to verbosity

+ * level specified when calling the macro. Applications should not normally

+ * need to call these functions directly.

+ */

+

+/**

+ * @def pj_log_wrapper_1(arg)

+ * Internal function to write log with verbosity 1. Will evaluate to

+ * empty expression if PJ_LOG_MAX_LEVEL is below 1.

+ * @param arg       Log expression.

+ */

+#if PJ_LOG_MAX_LEVEL >= 1

+    #define pj_log_wrapper_1(arg)	pj_log_1 arg

+    /** Internal function. */

+    PJ_DECL(void) pj_log_1(const char *src, const char *format, ...);

+#else

+    #define pj_log_wrapper_1(arg)

+#endif

+

+/**

+ * @def pj_log_wrapper_2(arg)

+ * Internal function to write log with verbosity 2. Will evaluate to

+ * empty expression if PJ_LOG_MAX_LEVEL is below 2.

+ * @param arg       Log expression.

+ */

+#if PJ_LOG_MAX_LEVEL >= 2

+    #define pj_log_wrapper_2(arg)	pj_log_2 arg

+    /** Internal function. */

+    PJ_DECL(void) pj_log_2(const char *src, const char *format, ...);

+#else

+    #define pj_log_wrapper_2(arg)

+#endif

+

+/**

+ * @def pj_log_wrapper_3(arg)

+ * Internal function to write log with verbosity 3. Will evaluate to

+ * empty expression if PJ_LOG_MAX_LEVEL is below 3.

+ * @param arg       Log expression.

+ */

+#if PJ_LOG_MAX_LEVEL >= 3

+    #define pj_log_wrapper_3(arg)	pj_log_3 arg

+    /** Internal function. */

+    PJ_DECL(void) pj_log_3(const char *src, const char *format, ...);

+#else

+    #define pj_log_wrapper_3(arg)

+#endif

+

+/**

+ * @def pj_log_wrapper_4(arg)

+ * Internal function to write log with verbosity 4. Will evaluate to

+ * empty expression if PJ_LOG_MAX_LEVEL is below 4.

+ * @param arg       Log expression.

+ */

+#if PJ_LOG_MAX_LEVEL >= 4

+    #define pj_log_wrapper_4(arg)	pj_log_4 arg

+    /** Internal function. */

+    PJ_DECL(void) pj_log_4(const char *src, const char *format, ...);

+#else

+    #define pj_log_wrapper_4(arg)

+#endif

+

+/**

+ * @def pj_log_wrapper_5(arg)

+ * Internal function to write log with verbosity 5. Will evaluate to

+ * empty expression if PJ_LOG_MAX_LEVEL is below 5.

+ * @param arg       Log expression.

+ */

+#if PJ_LOG_MAX_LEVEL >= 5

+    #define pj_log_wrapper_5(arg)	pj_log_5 arg

+    /** Internal function. */

+    PJ_DECL(void) pj_log_5(const char *src, const char *format, ...);

+#else

+    #define pj_log_wrapper_5(arg)

+#endif

+

+/**

+ * @def pj_log_wrapper_6(arg)

+ * Internal function to write log with verbosity 6. Will evaluate to

+ * empty expression if PJ_LOG_MAX_LEVEL is below 6.

+ * @param arg       Log expression.

+ */

+#if PJ_LOG_MAX_LEVEL >= 6

+    #define pj_log_wrapper_6(arg)	pj_log_6 arg

+    /** Internal function. */

+    PJ_DECL(void) pj_log_6(const char *src, const char *format, ...);

+#else

+    #define pj_log_wrapper_6(arg)

+#endif

+

+

+PJ_END_DECL 

+

+#endif  /* __PJ_LOG_H__ */

+

diff --git a/pjlib/include/pj/md5.h b/pjlib/include/pj/md5.h
new file mode 100644
index 0000000..979d858
--- /dev/null
+++ b/pjlib/include/pj/md5.h
@@ -0,0 +1,92 @@
+/* $Header: /pjproject-0.3/pjlib/src/pj/md5.h 5     9/17/05 10:37a Bennylp $ */

+/*

+  Copyright (C) 1999, 2002 Aladdin Enterprises.  All rights reserved.

+

+  This software is provided 'as-is', without any express or implied

+  warranty.  In no event will the authors be held liable for any damages

+  arising from the use of this software.

+

+  Permission is granted to anyone to use this software for any purpose,

+  including commercial applications, and to alter it and redistribute it

+  freely, subject to the following restrictions:

+

+  1. The origin of this software must not be misrepresented; you must not

+     claim that you wrote the original software. If you use this software

+     in a product, an acknowledgment in the product documentation would be

+     appreciated but is not required.

+  2. Altered source versions must be plainly marked as such, and must not be

+     misrepresented as being the original software.

+  3. This notice may not be removed or altered from any source distribution.

+

+  L. Peter Deutsch

+  ghost@aladdin.com

+

+ */

+/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */

+/*

+  Independent implementation of MD5 (RFC 1321).

+

+  This code implements the MD5 Algorithm defined in RFC 1321, whose

+  text is available at

+	http://www.ietf.org/rfc/rfc1321.txt

+  The code is derived from the text of the RFC, including the test suite

+  (section A.5) but excluding the rest of Appendix A.  It does not include

+  any code or documentation that is identified in the RFC as being

+  copyrighted.

+

+  The original and principal author of md5.h is L. Peter Deutsch

+  <ghost@aladdin.com>.  Other authors are noted in the change history

+  that follows (in reverse chronological order):

+

+  2002-04-13 lpd Removed support for non-ANSI compilers; removed

+	references to Ghostscript; clarified derivation from RFC 1321;

+	now handles byte order either statically or dynamically.

+  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.

+  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);

+	added conditionalization for C++ compilation from Martin

+	Purschke <purschke@bnl.gov>.

+  1999-05-03 lpd Original version.

+ */

+

+#ifndef md5_INCLUDED

+#  define md5_INCLUDED

+

+/*

+ * This package supports both compile-time and run-time determination of CPU

+ * byte order.  If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be

+ * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is

+ * defined as non-zero, the code will be compiled to run only on big-endian

+ * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to

+ * run on either big- or little-endian CPUs, but will run slightly less

+ * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.

+ */

+

+typedef unsigned char md5_byte_t; /* 8-bit byte */

+typedef unsigned long md5_word_t; /* 32-bit word */

+

+/** Define the state of the MD5 Algorithm. */

+typedef struct md5_state_s {

+    md5_word_t count[2];	/**< message length in bits, lsw first */

+    md5_word_t abcd[4];		/**< digest buffer */

+    md5_byte_t buf[64];		/**< accumulate block */

+} md5_state_t;

+

+#ifdef __cplusplus

+extern "C" 

+{

+#endif

+

+/** Initialize the algorithm. */

+void md5_init(md5_state_t *pms);

+

+/** Append a string to the message. */

+void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);

+

+/** Finish the message and return the digest. */

+void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);

+

+#ifdef __cplusplus

+}  /* end extern "C" */

+#endif

+

+#endif /* md5_INCLUDED */

diff --git a/pjlib/include/pj/os.h b/pjlib/include/pj/os.h
new file mode 100644
index 0000000..845a26b
--- /dev/null
+++ b/pjlib/include/pj/os.h
@@ -0,0 +1,904 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/os.h 12    10/29/05 11:30a Bennylp $ */

+

+#ifndef __PJ_OS_H__

+#define __PJ_OS_H__

+

+/**

+ * @file os.h

+ * @brief OS dependent functions

+ */

+#include <pj/types.h>

+

+PJ_BEGIN_DECL

+

+/**

+ * @defgroup PJ_OS Operating System Dependent Functionality.

+ * @ingroup PJ

+ */

+

+

+///////////////////////////////////////////////////////////////////////////////

+/**

+ * @defgroup PJ_THREAD Threads

+ * @ingroup PJ_OS

+ * @{

+ * This module provides multithreading API.

+ *

+ * \section pj_thread_examples_sec Examples

+ *

+ * For examples, please see:

+ *  - \ref page_pjlib_thread_test

+ *  - \ref page_pjlib_sleep_test

+ *

+ */

+

+/**

+ * Thread creation flags:

+ * - PJ_THREAD_SUSPENDED: specify that the thread should be created suspended.

+ */

+typedef enum pj_thread_create_flags

+{

+    PJ_THREAD_SUSPENDED = 1

+} pj_thread_create_flags;

+

+

+/**

+ * Specify this as \a stack_size argument in #pj_thread_create() to specify

+ * that thread should use default stack size for the current platform.

+ */

+#define PJ_THREAD_DEFAULT_STACK_SIZE    0

+

+/**

+ * Type of thread entry function.

+ */

+typedef int (PJ_THREAD_FUNC pj_thread_proc)(void*);

+

+/**

+ * Size of thread struct.

+ */

+#if !defined(PJ_THREAD_DESC_SIZE)

+#   define PJ_THREAD_DESC_SIZE	    (PJ_MAX_OBJ_NAME + 10*sizeof(long))

+#endif

+

+/**

+ * Thread structure, to thread's state when the thread is created by external

+ * or native API. 

+ */

+typedef pj_uint8_t pj_thread_desc[PJ_THREAD_DESC_SIZE];

+

+/**

+ * Get process ID.

+ * @return process ID.

+ */

+PJ_DECL(pj_uint32_t) pj_getpid(void);

+

+/**

+ * Create a new thread.

+ *

+ * @param pool          The memory pool from which the thread record 

+ *                      will be allocated from.

+ * @param thread_name   The optional name to be assigned to the thread.

+ * @param proc          Thread entry function.

+ * @param arg           Argument to be passed to the thread entry function.

+ * @param stack_size    The size of the stack for the new thread, or ZERO or

+ *                      PJ_THREAD_DEFAULT_STACK_SIZE to let the 

+ *		        library choose the reasonable size for the stack. 

+ *                      For some systems, the stack will be allocated from 

+ *                      the pool, so the pool must have suitable capacity.

+ * @param flags         Flags for thread creation, which is bitmask combination 

+ *                      from enum pj_thread_create_flags.

+ * @param thread        Pointer to hold the newly created thread.

+ *

+ * @return	        PJ_SUCCESS on success, or the error code.

+ */

+PJ_DECL(pj_status_t) pj_thread_create(  pj_pool_t *pool, 

+                                        const char *thread_name,

+				        pj_thread_proc *proc, 

+                                        void *arg,

+				        pj_size_t stack_size, 

+                                        unsigned flags,

+					pj_thread_t **thread );

+

+/**

+ * Register a thread that was created by external or native API to PJLIB.

+ * This function must be called in the context of the thread being registered.

+ * When the thread is created by external function or API call,

+ * it must be 'registered' to PJLIB using pj_thread_register(), so that it can

+ * cooperate with PJLIB's framework. During registration, some data needs to

+ * be maintained, and this data must remain available during the thread's 

+ * lifetime.

+ *

+ * @param thread_name   The optional name to be assigned to the thread.

+ * @param desc          Thread descriptor, which must be available throughout 

+ *                      the lifetime of the thread.

+ * @param thread        Pointer to hold the created thread handle.

+ *

+ * @return              PJ_SUCCESS on success, or the error code.

+ */

+PJ_DECL(pj_status_t) pj_thread_register ( const char *thread_name,

+					  pj_thread_desc desc,

+					  pj_thread_t **thread);

+

+/**

+ * Get thread name.

+ *

+ * @param thread    The thread handle.

+ *

+ * @return Thread name as null terminated string.

+ */

+PJ_DECL(const char*) pj_thread_get_name(pj_thread_t *thread);

+

+/**

+ * Resume a suspended thread.

+ *

+ * @param thread    The thread handle.

+ *

+ * @return zero on success.

+ */

+PJ_DECL(pj_status_t) pj_thread_resume(pj_thread_t *thread);

+

+/**

+ * Get the current thread.

+ *

+ * @return Thread handle of current thread.

+ */

+PJ_DECL(pj_thread_t*) pj_thread_this(void);

+

+/**

+ * Join thread.

+ * This function will block the caller thread until the specified thread exits.

+ *

+ * @param thread    The thread handle.

+ *

+ * @return zero on success.

+ */

+PJ_DECL(pj_status_t) pj_thread_join(pj_thread_t *thread);

+

+

+/**

+ * Destroy thread and release resources allocated for the thread.

+ * However, the memory allocated for the pj_thread_t itself will only be released

+ * when the pool used to create the thread is destroyed.

+ *

+ * @param thread    The thread handle.

+ *

+ * @return zero on success.

+ */

+PJ_DECL(pj_status_t) pj_thread_destroy(pj_thread_t *thread);

+

+

+/**

+ * Put the current thread to sleep for the specified miliseconds.

+ *

+ * @param msec Miliseconds delay.

+ *

+ * @return zero if successfull.

+ */

+PJ_DECL(pj_status_t) pj_thread_sleep(unsigned msec);

+

+/**

+ * @def PJ_CHECK_STACK()

+ * PJ_CHECK_STACK() macro is used to check the sanity of the stack.

+ * The OS implementation may check that no stack overflow occurs, and

+ * it also may collect statistic about stack usage.

+ */

+#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0

+

+#  define PJ_CHECK_STACK() pj_thread_check_stack(__FILE__, __LINE__)

+

+/** @internal

+ * The implementation of stack checking. 

+ */

+PJ_DECL(void) pj_thread_check_stack(const char *file, int line);

+

+/** @internal

+ * Get maximum stack usage statistic. 

+ */

+PJ_DECL(pj_uint32_t) pj_thread_get_stack_max_usage(pj_thread_t *thread);

+

+/** @internal

+ * Dump thread stack status. 

+ */

+PJ_DECL(pj_status_t) pj_thread_get_stack_info(pj_thread_t *thread,

+					      const char **file,

+					      int *line);

+#else

+

+#  define PJ_CHECK_STACK()

+/** pj_thread_get_stack_max_usage() for the thread */

+#  define pj_thread_get_stack_max_usage(thread)	    0

+/** pj_thread_get_stack_info() for the thread */

+#  define pj_thread_get_stack_info(thread,f,l)	    (*(f)="",*(l)=0)

+#endif	/* PJ_OS_HAS_CHECK_STACK */

+

+/**

+ * @}

+ */

+

+///////////////////////////////////////////////////////////////////////////////

+/**

+ * @defgroup PJ_TLS Thread Local Storage.

+ * @ingroup PJ_OS

+ * @{

+ */

+

+/** 

+ * Allocate thread local storage index. The initial value of the variable at

+ * the index is zero.

+ *

+ * @param index	    Pointer to hold the return value.

+ * @return	    PJ_SUCCESS on success, or the error code.

+ */

+PJ_DECL(pj_status_t) pj_thread_local_alloc(long *index);

+

+/**

+ * Deallocate thread local variable.

+ *

+ * @param index	    The variable index.

+ */

+PJ_DECL(void) pj_thread_local_free(long index);

+

+/**

+ * Set the value of thread local variable.

+ *

+ * @param index	    The index of the variable.

+ * @param value	    The value.

+ */

+PJ_DECL(void) pj_thread_local_set(long index, void *value);

+

+/**

+ * Get the value of thread local variable.

+ *

+ * @param index	    The index of the variable.

+ * @return	    The value.

+ */

+PJ_DECL(void*) pj_thread_local_get(long index);

+

+

+/**

+ * @}

+ */

+

+

+///////////////////////////////////////////////////////////////////////////////

+/**

+ * @defgroup PJ_ATOMIC Atomic Variables

+ * @ingroup PJ_OS

+ * @{

+ *

+ * This module provides API to manipulate atomic variables.

+ *

+ * \section pj_atomic_examples_sec Examples

+ *

+ * For some example codes, please see:

+ *  - @ref page_pjlib_atomic_test

+ */

+

+

+/**

+ * Create atomic variable.

+ *

+ * @param pool	    The pool.

+ * @param initial   The initial value of the atomic variable.

+ * @param atomic    Pointer to hold the atomic variable upon return.

+ *

+ * @return	    PJ_SUCCESS on success, or the error code.

+ */

+PJ_DECL(pj_status_t) pj_atomic_create( pj_pool_t *pool, 

+				       pj_atomic_value_t initial,

+				       pj_atomic_t **atomic );

+

+/**

+ * Destroy atomic variable.

+ *

+ * @param atomic_var	the atomic variable.

+ *

+ * @return PJ_SUCCESS if success.

+ */

+PJ_DECL(pj_status_t) pj_atomic_destroy( pj_atomic_t *atomic_var );

+

+/**

+ * Set the value of an atomic type, and return the previous value.

+ *

+ * @param atomic_var	the atomic variable.

+ * @param value		value to be set to the variable.

+ *

+ * @return the previous value of the variable.

+ */

+PJ_DECL(pj_atomic_value_t) pj_atomic_set(pj_atomic_t *atomic_var, 

+					 pj_atomic_value_t value);

+

+/**

+ * Get the value of an atomic type.

+ *

+ * @param atomic_var	the atomic variable.

+ *

+ * @return the value of the atomic variable.

+ */

+PJ_DECL(pj_atomic_value_t) pj_atomic_get(pj_atomic_t *atomic_var);

+

+/**

+ * Increment the value of an atomic type.

+ *

+ * @param atomic_var	the atomic variable.

+ *

+ * @return the result.

+ */

+PJ_DECL(pj_atomic_value_t) pj_atomic_inc(pj_atomic_t *atomic_var);

+

+/**

+ * Decrement the value of an atomic type.

+ *

+ * @param atomic_var	the atomic variable.

+ *

+ * @return the result.

+ */

+PJ_DECL(pj_atomic_value_t) pj_atomic_dec(pj_atomic_t *atomic_var);

+

+/**

+ * @}

+ */

+

+///////////////////////////////////////////////////////////////////////////////

+/**

+ * @defgroup PJ_MUTEX Mutexes.

+ * @ingroup PJ_OS

+ * @{

+ *

+ * Mutex manipulation. Alternatively, application can use higher abstraction

+ * for lock objects, which provides uniform API for all kinds of lock 

+ * mechanisms, including mutex. See @ref PJ_LOCK for more information.

+ */

+

+/**

+ * Mutex types:

+ *  - PJ_MUTEX_DEFAULT: default mutex type, which is system dependent.

+ *  - PJ_MUTEX_SIMPLE: non-recursive mutex.

+ *  - PJ_MUTEX_RECURSIVE: recursive mutex.

+ */

+typedef enum pj_mutex_type_e

+{

+    PJ_MUTEX_DEFAULT,

+    PJ_MUTEX_SIMPLE,

+    PJ_MUTEX_RECURSE,

+} pj_mutex_type_e;

+

+

+/**

+ * Create mutex of the specified type.

+ *

+ * @param pool	    The pool.

+ * @param name	    Name to be associated with the mutex (for debugging).

+ * @param type	    The type of the mutex, of type #pj_mutex_type_e.

+ * @param mutex	    Pointer to hold the returned mutex instance.

+ *

+ * @return	    PJ_SUCCESS on success, or the error code.

+ */

+PJ_DECL(pj_status_t) pj_mutex_create(pj_pool_t *pool, 

+                                     const char *name,

+				     int type, 

+                                     pj_mutex_t **mutex);

+

+/**

+ * Create simple, non-recursive mutex.

+ * This function is a simple wrapper for #pj_mutex_create to create 

+ * non-recursive mutex.

+ *

+ * @param pool	    The pool.

+ * @param name	    Mutex name.

+ * @param mutex	    Pointer to hold the returned mutex instance.

+ *

+ * @return	    PJ_SUCCESS on success, or the error code.

+ */

+PJ_DECL(pj_status_t) pj_mutex_create_simple( pj_pool_t *pool, const char *name,

+					     pj_mutex_t **mutex );

+

+/**

+ * Create recursive mutex.

+ * This function is a simple wrapper for #pj_mutex_create to create 

+ * recursive mutex.

+ *

+ * @param pool	    The pool.

+ * @param name	    Mutex name.

+ * @param mutex	    Pointer to hold the returned mutex instance.

+ *

+ * @return	    PJ_SUCCESS on success, or the error code.

+ */

+PJ_DECL(pj_status_t) pj_mutex_create_recursive( pj_pool_t *pool,

+					        const char *name,

+						pj_mutex_t **mutex );

+

+/**

+ * Acquire mutex lock.

+ *

+ * @param mutex	    The mutex.

+ * @return	    PJ_SUCCESS on success, or the error code.

+ */

+PJ_DECL(pj_status_t) pj_mutex_lock(pj_mutex_t *mutex);

+

+/**

+ * Release mutex lock.

+ *

+ * @param mutex	    The mutex.

+ * @return	    PJ_SUCCESS on success, or the error code.

+ */

+PJ_DECL(pj_status_t) pj_mutex_unlock(pj_mutex_t *mutex);

+

+/**

+ * Try to acquire mutex lock.

+ *

+ * @param mutex	    The mutex.

+ * @return	    PJ_SUCCESS on success, or the error code if the

+ *		    lock couldn't be acquired.

+ */

+PJ_DECL(pj_status_t) pj_mutex_trylock(pj_mutex_t *mutex);

+

+/**

+ * Destroy mutex.

+ *

+ * @param mutex	    Te mutex.

+ * @return	    PJ_SUCCESS on success, or the error code.

+ */

+PJ_DECL(pj_status_t) pj_mutex_destroy(pj_mutex_t *mutex);

+

+/**

+ * Determine whether calling thread is owning the mutex (only available when

+ * PJ_DEBUG is set).

+ * @param mutex	    The mutex.

+ * @return	    Non-zero if yes.

+ */

+#if defined(PJ_DEBUG) && PJ_DEBUG != 0

+   PJ_DECL(pj_bool_t) pj_mutex_is_locked(pj_mutex_t *mutex);

+#else

+#  define pj_mutex_is_locked(mutex)	    1

+#endif

+

+/**

+ * @}

+ */

+

+///////////////////////////////////////////////////////////////////////////////

+/**

+ * @defgroup PJ_CRIT_SEC Critical sections.

+ * @ingroup PJ_OS

+ * @{

+ * Critical section protection can be used to protect regions where:

+ *  - mutual exclusion protection is needed.

+ *  - it's rather too expensive to create a mutex.

+ *  - the time spent in the region is very very brief.

+ *

+ * Critical section is a global object, and it prevents any threads from

+ * entering any regions that are protected by critical section once a thread

+ * is already in the section.

+ *

+ * Critial section is \a not recursive!

+ *

+ * Application <b>MUST NOT</b> call any functions that may cause current

+ * thread to block (such as allocating memory, performing I/O, locking mutex,

+ * etc.) while holding the critical section.

+ */

+/**

+ * Enter critical section.

+ */

+PJ_DECL(void) pj_enter_critical_section(void);

+

+/**

+ * Leave critical section.

+ */

+PJ_DECL(void) pj_leave_critical_section(void);

+

+/**

+ * @}

+ */

+

+///////////////////////////////////////////////////////////////////////////////

+#if defined(PJ_HAS_SEMAPHORE) && PJ_HAS_SEMAPHORE != 0

+/**

+ * @defgroup PJ_SEM Semaphores.

+ * @ingroup PJ_OS

+ * @{

+ *

+ * This module provides abstraction for semaphores, where available.

+ */

+

+/**

+ * Create semaphore.

+ *

+ * @param pool	    The pool.

+ * @param name	    Name to be assigned to the semaphore (for logging purpose)

+ * @param initial   The initial count of the semaphore.

+ * @param max	    The maximum count of the semaphore.

+ * @param sem	    Pointer to hold the semaphore created.

+ *

+ * @return	    PJ_SUCCESS on success, or the error code.

+ */

+PJ_DECL(pj_status_t) pj_sem_create( pj_pool_t *pool, 

+                                    const char *name,

+				    unsigned initial, 

+                                    unsigned max,

+				    pj_sem_t **sem);

+

+/**

+ * Wait for semaphore.

+ *

+ * @param sem	The semaphore.

+ *

+ * @return	PJ_SUCCESS on success, or the error code.

+ */

+PJ_DECL(pj_status_t) pj_sem_wait(pj_sem_t *sem);

+

+/**

+ * Try wait for semaphore.

+ *

+ * @param sem	The semaphore.

+ *

+ * @return	PJ_SUCCESS on success, or the error code.

+ */

+PJ_DECL(pj_status_t) pj_sem_trywait(pj_sem_t *sem);

+

+/**

+ * Release semaphore.

+ *

+ * @param sem	The semaphore.

+ *

+ * @return	PJ_SUCCESS on success, or the error code.

+ */

+PJ_DECL(pj_status_t) pj_sem_post(pj_sem_t *sem);

+

+/**

+ * Destroy semaphore.

+ *

+ * @param sem	The semaphore.

+ *

+ * @return	PJ_SUCCESS on success, or the error code.

+ */

+PJ_DECL(pj_status_t) pj_sem_destroy(pj_sem_t *sem);

+

+/**

+ * @}

+ */

+#endif	/* PJ_HAS_SEMAPHORE */

+

+

+///////////////////////////////////////////////////////////////////////////////

+#if defined(PJ_HAS_EVENT_OBJ) && PJ_HAS_EVENT_OBJ != 0

+/**

+ * @defgroup PJ_EVENT Event Object.

+ * @ingroup PJ_OS

+ * @{

+ *

+ * This module provides abstraction to event object (e.g. Win32 Event) where

+ * available. Event objects can be used for synchronization among threads.

+ */

+

+/**

+ * Create event object.

+ *

+ * @param pool		The pool.

+ * @param name		The name of the event object (for logging purpose).

+ * @param manual_reset	Specify whether the event is manual-reset

+ * @param initial	Specify the initial state of the event object.

+ * @param event		Pointer to hold the returned event object.

+ *

+ * @return event handle, or NULL if failed.

+ */

+PJ_DECL(pj_status_t) pj_event_create(pj_pool_t *pool, const char *name,

+				     pj_bool_t manual_reset, pj_bool_t initial,

+				     pj_event_t **event);

+

+/**

+ * Wait for event to be signaled.

+ *

+ * @param event	    The event object.

+ *

+ * @return zero if successfull.

+ */

+PJ_DECL(pj_status_t) pj_event_wait(pj_event_t *event);

+

+/**

+ * Try wait for event object to be signalled.

+ *

+ * @param event The event object.

+ *

+ * @return zero if successfull.

+ */

+PJ_DECL(pj_status_t) pj_event_trywait(pj_event_t *event);

+

+/**

+ * Set the event object state to signaled. For auto-reset event, this 

+ * will only release the first thread that are waiting on the event. For

+ * manual reset event, the state remains signaled until the event is reset.

+ * If there is no thread waiting on the event, the event object state 

+ * remains signaled.

+ *

+ * @param event	    The event object.

+ *

+ * @return zero if successfull.

+ */

+PJ_DECL(pj_status_t) pj_event_set(pj_event_t *event);

+

+/**

+ * Set the event object to signaled state to release appropriate number of

+ * waiting threads and then reset the event object to non-signaled. For

+ * manual-reset event, this function will release all waiting threads. For

+ * auto-reset event, this function will only release one waiting thread.

+ *

+ * @param event	    The event object.

+ *

+ * @return zero if successfull.

+ */

+PJ_DECL(pj_status_t) pj_event_pulse(pj_event_t *event);

+

+/**

+ * Set the event object state to non-signaled.

+ *

+ * @param event	    The event object.

+ *

+ * @return zero if successfull.

+ */

+PJ_DECL(pj_status_t) pj_event_reset(pj_event_t *event);

+

+/**

+ * Destroy the event object.

+ *

+ * @param event	    The event object.

+ *

+ * @return zero if successfull.

+ */

+PJ_DECL(pj_status_t) pj_event_destroy(pj_event_t *event);

+

+/**

+ * @}

+ */

+#endif	/* PJ_HAS_EVENT_OBJ */

+

+///////////////////////////////////////////////////////////////////////////////

+/**

+ * @addtogroup PJ_TIME Time Data Type and Manipulation.

+ * @ingroup PJ_OS

+ * @{

+ * This module provides API for manipulating time.

+ *

+ * \section pj_time_examples_sec Examples

+ *

+ * For examples, please see:

+ *  - \ref page_pjlib_sleep_test

+ */

+

+/**

+ * Get current time of day in local representation.

+ *

+ * @param tv	Variable to store the result.

+ *

+ * @return zero if successfull.

+ */

+PJ_DECL(pj_status_t) pj_gettimeofday(pj_time_val *tv);

+

+

+/**

+ * Parse time value into date/time representation.

+ *

+ * @param tv	The time.

+ * @param pt	Variable to store the date time result.

+ *

+ * @return zero if successfull.

+ */

+PJ_DECL(pj_status_t) pj_time_decode(const pj_time_val *tv, pj_parsed_time *pt);

+

+/**

+ * Encode date/time to time value.

+ *

+ * @param pt	The date/time.

+ * @param tv	Variable to store time value result.

+ *

+ * @return zero if successfull.

+ */

+PJ_DECL(pj_status_t) pj_time_encode(const pj_parsed_time *pt, pj_time_val *tv);

+

+/**

+ * Convert local time to GMT.

+ *

+ * @param tv	Time to convert.

+ *

+ * @return zero if successfull.

+ */

+PJ_DECL(pj_status_t) pj_time_local_to_gmt(pj_time_val *tv);

+

+/**

+ * Convert GMT to local time.

+ *

+ * @param tv	Time to convert.

+ *

+ * @return zero if successfull.

+ */

+PJ_DECL(pj_status_t) pj_time_gmt_to_local(pj_time_val *tv);

+

+/**

+ * @}

+ */

+

+///////////////////////////////////////////////////////////////////////////////

+#if defined(PJ_TERM_HAS_COLOR) && PJ_TERM_HAS_COLOR != 0

+

+/**

+ * @defgroup PJ_TERM Terminal

+ * @ingroup PJ_OS

+ * @{

+ */

+

+/**

+ * Set current terminal color.

+ *

+ * @param color	    The RGB color.

+ *

+ * @return zero on success.

+ */

+PJ_DECL(pj_status_t) pj_term_set_color(pj_color_t color);

+

+/**

+ * Get current terminal foreground color.

+ *

+ * @return RGB color.

+ */

+PJ_DECL(pj_color_t) pj_term_get_color(void);

+

+/**

+ * @}

+ */

+

+#endif	/* PJ_TERM_HAS_COLOR */

+

+///////////////////////////////////////////////////////////////////////////////

+/**

+ * @defgroup PJ_TIMESTAMP High Resolution Timestamp

+ * @ingroup PJ_OS

+ * @{

+ *

+ * PJLIB provides <b>High Resolution Timestamp</b> API to access highest 

+ * resolution timestamp value provided by the platform. The API is usefull

+ * to measure precise elapsed time, and can be used in applications such

+ * as profiling.

+ *

+ * The timestamp value is represented in cycles, and can be related to

+ * normal time (in seconds or sub-seconds) using various functions provided.

+ *

+ * \section pj_timestamp_examples_sec Examples

+ *

+ * For examples, please see:

+ *  - \ref page_pjlib_sleep_test

+ *  - \ref page_pjlib_timestamp_test

+ */

+

+/*

+ * High resolution timer.

+ */

+#if defined(PJ_HAS_HIGH_RES_TIMER) && PJ_HAS_HIGH_RES_TIMER != 0

+

+/**

+ * This structure represents high resolution (64bit) time value. The time

+ * values represent time in cycles, which is retrieved by calling

+ * #pj_get_timestamp().

+ */

+typedef union pj_timestamp

+{

+    struct

+    {

+	pj_uint32_t lo;     /**< Low 32-bit value of the 64-bit value. */

+	pj_uint32_t hi;     /**< high 32-bit value of the 64-bit value. */

+    } u32;                  /**< The 64-bit value as two 32-bit values. */

+

+#if PJ_HAS_INT64

+    pj_uint64_t u64;        /**< The whole 64-bit value, where available. */

+#endif

+} pj_timestamp;

+

+

+/**

+ * Acquire high resolution timer value. The time value are stored

+ * in cycles.

+ *

+ * @param ts	    High resolution timer value.

+ * @return	    PJ_SUCCESS or the appropriate error code.

+ *

+ * @see pj_get_timestamp_freq().

+ */

+PJ_DECL(pj_status_t) pj_get_timestamp(pj_timestamp *ts);

+

+/**

+ * Get high resolution timer frequency, in cycles per second.

+ *

+ * @param freq	    Timer frequency, in cycles per second.

+ * @return	    PJ_SUCCESS or the appropriate error code.

+ */

+PJ_DECL(pj_status_t) pj_get_timestamp_freq(pj_timestamp *freq);

+

+/**

+ * Calculate the elapsed time, and store it in pj_time_val.

+ * This function calculates the elapsed time using highest precision

+ * calculation that is available for current platform, considering

+ * whether floating point or 64-bit precision arithmetic is available. 

+ * For maximum portability, application should prefer to use this function

+ * rather than calculating the elapsed time by itself.

+ *

+ * @param start     The starting timestamp.

+ * @param stop      The end timestamp.

+ *

+ * @return	    Elapsed time as #pj_time_val.

+ *

+ * @see pj_elapsed_usec(), pj_elapsed_cycle(), pj_elapsed_nanosec()

+ */

+PJ_DECL(pj_time_val) pj_elapsed_time( const pj_timestamp *start,

+                                      const pj_timestamp *stop );

+

+/**

+ * Calculate the elapsed time in 32-bit microseconds.

+ * This function calculates the elapsed time using highest precision

+ * calculation that is available for current platform, considering

+ * whether floating point or 64-bit precision arithmetic is available. 

+ * For maximum portability, application should prefer to use this function

+ * rather than calculating the elapsed time by itself.

+ *

+ * @param start     The starting timestamp.

+ * @param stop      The end timestamp.

+ *

+ * @return	    Elapsed time in microsecond.

+ *

+ * @see pj_elapsed_time(), pj_elapsed_cycle(), pj_elapsed_nanosec()

+ */

+PJ_DECL(pj_uint32_t) pj_elapsed_usec( const pj_timestamp *start,

+                                      const pj_timestamp *stop );

+

+/**

+ * Calculate the elapsed time in 32-bit nanoseconds.

+ * This function calculates the elapsed time using highest precision

+ * calculation that is available for current platform, considering

+ * whether floating point or 64-bit precision arithmetic is available. 

+ * For maximum portability, application should prefer to use this function

+ * rather than calculating the elapsed time by itself.

+ *

+ * @param start     The starting timestamp.

+ * @param stop      The end timestamp.

+ *

+ * @return	    Elapsed time in nanoseconds.

+ *

+ * @see pj_elapsed_time(), pj_elapsed_cycle(), pj_elapsed_usec()

+ */

+PJ_DECL(pj_uint32_t) pj_elapsed_nanosec( const pj_timestamp *start,

+                                         const pj_timestamp *stop );

+

+/**

+ * Calculate the elapsed time in 32-bit cycles.

+ * This function calculates the elapsed time using highest precision

+ * calculation that is available for current platform, considering

+ * whether floating point or 64-bit precision arithmetic is available. 

+ * For maximum portability, application should prefer to use this function

+ * rather than calculating the elapsed time by itself.

+ *

+ * @param start     The starting timestamp.

+ * @param stop      The end timestamp.

+ *

+ * @return	    Elapsed time in cycles.

+ *

+ * @see pj_elapsed_usec(), pj_elapsed_time(), pj_elapsed_nanosec()

+ */

+PJ_DECL(pj_uint32_t) pj_elapsed_cycle( const pj_timestamp *start,

+                                       const pj_timestamp *stop );

+

+

+#endif	/* PJ_HAS_HIGH_RES_TIMER */

+

+/** @} */

+

+

+///////////////////////////////////////////////////////////////////////////////

+/**

+ * Internal PJLIB function to initialize the threading subsystem.

+ * @return          PJ_SUCCESS or the appropriate error code.

+ */

+pj_status_t pj_thread_init(void);

+

+

+PJ_END_DECL

+

+#endif  /* __PJ_OS_H__ */

+

diff --git a/pjlib/include/pj/pool.h b/pjlib/include/pj/pool.h
new file mode 100644
index 0000000..78ed45b
--- /dev/null
+++ b/pjlib/include/pj/pool.h
@@ -0,0 +1,570 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/pool.h 10    10/14/05 12:26a Bennylp $ */

+

+#ifndef __PJ_POOL_H__

+#define __PJ_POOL_H__

+

+/**

+ * @file pool.h

+ * @brief Memory Pool.

+ */

+

+#include <pj/list.h>

+

+PJ_BEGIN_DECL

+

+/**

+ * @defgroup PJ_POOL_GROUP Memory Pool Management

+ * @ingroup PJ

+ * @brief

+ * Memory pool management provides API to allocate and deallocate memory from

+ * memory pool and to manage and establish policy for pool creation and

+ * destruction in pool factory.

+ *

+ * \section PJ_POOL_FACTORY_SEC Pool Factory

+ * See: \ref PJ_POOL_FACTORY "Pool Factory"

+ *

+ * A memory pool must be created through a factory. A factory not only provides

+ * generic interface functions to create and release pool, but also provides 

+ * strategy to manage the life time of pools. One sample implementation, 

+ * \a pj_caching_pool, can be set to keep the pools released by application for

+ * future use as long as the total memory is below the limit.

+ * 

+ * The pool factory interface declared in PJLIB is designed to be extensible.

+ * Application can define its own strategy by creating it's own pool factory

+ * implementation, and this strategy can be used even by existing library

+ * without recompilation.

+ *

+ *

+ * \section PJ_POOL_POLICY_SEC Pool Factory Policy

+ * See: \ref PJ_POOL_FACTORY "Pool Factory Policy"

+ *

+ * A pool factory only defines functions to create and release pool and how

+ * to manage pools, but the rest of the functionalities are controlled by

+ * policy. A pool policy defines:

+ *  - how memory block is allocated and deallocated (the default implementation

+ *    allocates and deallocate memory by calling malloc() and free()).

+ *  - callback to be called when memory allocation inside a pool fails (the

+ *    default implementation will throw PJ_NO_MEMORY_EXCEPTION exception).

+ *  - concurrency when creating and releasing pool from/to the factory.

+ *

+ * A pool factory can be given different policy during creation to make

+ * it behave differently. For example, caching pool factory can be configured

+ * to allocate and deallocate from a static/contiguous/preallocated memory 

+ * instead of using malloc()/free().

+ * 

+ * What strategy/factory and what policy to use is not defined by PJLIB, but

+ * instead is left to application to make use whichever is most efficient for

+ * itself.

+ *

+ *

+ * \section PJ_POOL_POOL_SEC The Pool

+ * See: \ref PJ_POOL "Pool"

+ *

+ * The memory pool is an opaque object created by pool factory.

+ * Application uses this object to request a memory chunk, by calling

+ * #pj_pool_alloc or #pj_pool_calloc. When the application has finished using

+ * the pool, it must call #pj_pool_release to free all the chunks previously

+ * allocated and release the pool back to the factory.

+ *

+ * \section PJ_POOL_THREADING_SEC More on Threading Policies:

+ * - By design, memory allocation from a pool is not thread safe. We assumed 

+ *   that a pool will be owned by an object, and thread safety should be 

+ *   handled by that object. Thus these functions are not thread safe: 

+ *	- #pj_pool_alloc, 

+ *	- #pj_pool_calloc, 

+ *	- and other pool statistic functions.

+ * - Threading in the pool factory is decided by the policy set for the

+ *   factory when it was created.

+ *

+ * \section PJ_POOL_EXAMPLES_SEC Examples

+ *

+ * For some sample codes on how to use the pool, please see:

+ *  - @ref page_pjlib_pool_test

+ */

+

+/**

+ * @defgroup PJ_POOL Memory Pool.

+ * @ingroup PJ_POOL_GROUP

+ * @brief

+ * A memory pool is initialized with an initial amount of memory, which is

+ * called a block. Pool can be configured to dynamically allocate more memory 

+ * blocks when it runs out of memory. Subsequent memory allocations by user 

+ * will use up portions of these block. 

+ * The pool doesn't keep track of individual memory allocations

+ * by user, and the user doesn't have to free these indidual allocations. This

+ * makes memory allocation simple and very fast. All the memory allocated from

+ * the pool will be destroyed when the pool itself is destroyed.

+ * @{

+ */

+

+/**

+ * The type for function to receive callback from the pool when it is unable

+ * to allocate memory. The elegant way to handle this condition is to throw

+ * exception, and this is what is expected by most of this library 

+ * components.

+ */

+typedef void pj_pool_callback(pj_pool_t *pool, pj_size_t size);

+

+/**

+ * This class, which is used internally by the pool, describes a single 

+ * block of memory from which user memory allocations will be allocated from.

+ */

+typedef struct pj_pool_block

+{

+    PJ_DECL_LIST_MEMBER(struct pj_pool_block)   /**< List's prev and next.  */

+    unsigned char    *buf;                      /**< Start of buffer.       */

+    unsigned char    *cur;                      /**< Current alloc ptr.     */

+    unsigned char    *end;                      /**< End of buffer.         */

+} pj_pool_block;

+

+

+/**

+ * This structure describes the memory pool. Only implementors of pool factory

+ * need to care about the contents of this structure.

+ */

+struct pj_pool_t

+{

+    PJ_DECL_LIST_MEMBER(struct pj_pool_t)

+

+    /** Pool name */

+    char	    obj_name[PJ_MAX_OBJ_NAME];

+

+    /** Pool factory. */

+    pj_pool_factory *factory;

+

+    /** Current capacity allocated by the pool. */

+    pj_size_t	    capacity;

+

+    /** Number of memory used/allocated. */

+    pj_size_t	    used_size;

+

+    /** Size of memory block to be allocated when the pool runs out of memory */

+    pj_size_t	    increment_size;

+

+    /** List of memory blocks allcoated by the pool. */

+    pj_pool_block   block_list;

+

+    /** The callback to be called when the pool is unable to allocate memory. */

+    pj_pool_callback *callback;

+

+};

+

+

+/**

+ * Guidance on how much memory required for initial pool administrative data.

+ */

+#define PJ_POOL_SIZE	        (sizeof(struct pj_pool_t))

+

+/** 

+ * Pool memory alignment (must be power of 2). 

+ */

+#ifndef PJ_POOL_ALIGNMENT

+#   define PJ_POOL_ALIGNMENT    4

+#endif

+

+/**

+ * Create a new pool from the pool factory. This wrapper will call create_pool

+ * member of the pool factory.

+ *

+ * @param factory	    The pool factory.

+ * @param name		    The name to be assigned to the pool. The name should 

+ *			    not be longer than PJ_MAX_OBJ_NAME (32 chars), or 

+ *			    otherwise it will be truncated.

+ * @param initial_size	    The size of initial memory blocks taken by the pool.

+ *			    Note that the pool will take 68+20 bytes for 

+ *			    administrative area from this block.

+ * @param increment_size    the size of each additional blocks to be allocated

+ *			    when the pool is running out of memory. If user 

+ *			    requests memory which is larger than this size, then 

+ *			    an error occurs.

+ *			    Note that each time a pool allocates additional block, 

+ *			    it needs PJ_POOL_SIZE more to store some 

+ *			    administrative info.

+ * @param callback	    Callback to be called when error occurs in the pool.

+ *			    If this value is NULL, then the callback from pool

+ *			    factory policy will be used.

+ *			    Note that when an error occurs during pool creation, 

+ *			    the callback itself is not called. Instead, NULL 

+ *			    will be returned.

+ *

+ * @return                  The memory pool, or NULL.

+ */

+PJ_IDECL(pj_pool_t*) pj_pool_create(pj_pool_factory *factory, 

+				    const char *name,

+				    pj_size_t initial_size, 

+				    pj_size_t increment_size,

+				    pj_pool_callback *callback);

+

+/**

+ * Release the pool back to pool factory.

+ *

+ * @param pool	    Memory pool.

+ */

+PJ_IDECL(void) pj_pool_release( pj_pool_t *pool );

+

+/**

+ * Get pool object name.

+ *

+ * @param pool the pool.

+ *

+ * @return pool name as NULL terminated string.

+ */

+PJ_IDECL(const char *) pj_pool_getobjname( const pj_pool_t *pool );

+

+/**

+ * Reset the pool to its state when it was initialized.

+ * This means that if additional blocks have been allocated during runtime, 

+ * then they will be freed. Only the original block allocated during 

+ * initialization is retained. This function will also reset the internal 

+ * counters, such as pool capacity and used size.

+ *

+ * @param pool the pool.

+ */

+PJ_DECL(void) pj_pool_reset( pj_pool_t *pool );

+

+

+/**

+ * Get the pool capacity, that is, the system storage that have been allocated

+ * by the pool, and have been used/will be used to allocate user requests.

+ * There's no guarantee that the returned value represent a single

+ * contiguous block, because the capacity may be spread in several blocks.

+ *

+ * @param pool	the pool.

+ *

+ * @return the capacity.

+ */

+PJ_IDECL(pj_size_t) pj_pool_get_capacity( pj_pool_t *pool );

+

+/**

+ * Get the total size of user allocation request.

+ *

+ * @param pool	the pool.

+ *

+ * @return the total size.

+ */

+PJ_IDECL(pj_size_t) pj_pool_get_used_size( pj_pool_t *pool );

+

+/**

+ * Allocate storage with the specified size from the pool.

+ * If there's no storage available in the pool, then the pool can allocate more

+ * blocks if the increment size is larger than the requested size.

+ *

+ * @param pool	    the pool.

+ * @param size	    the requested size.

+ *

+ * @return pointer to the allocated memory.

+ */

+PJ_IDECL(void*) pj_pool_alloc( pj_pool_t *pool, pj_size_t size);

+

+/**

+ * Allocate storage  from the pool, and initialize it to zero.

+ * This function behaves like pj_pool_alloc(), except that the storage will

+ * be initialized to zero.

+ *

+ * @param pool	    the pool.

+ * @param count	    the number of elements in the array.

+ * @param elem	    the size of individual element.

+ *

+ * @return pointer to the allocated memory.

+ */

+PJ_IDECL(void*) pj_pool_calloc( pj_pool_t *pool, pj_size_t count, 

+				pj_size_t elem);

+

+

+/**

+ * @def pj_pool_zalloc(pj_pool_t *pool, pj_size_t size)

+ * Allocate storage from the pool and initialize it to zero.

+ *

+ * @param pool	    The pool.

+ * @param size	    The size to be allocated.

+ *

+ * @return	    Pointer to the allocated memory.

+ */

+#define pj_pool_zalloc(pool, size)  pj_pool_calloc(pool, 1, size)

+

+

+/**

+ * @}	// PJ_POOL

+ */

+

+///////////////////////////////////////////////////////////////////////////////

+/**

+ * @defgroup PJ_POOL_FACTORY Pool Factory and Policy.

+ * @ingroup PJ_POOL_GROUP

+ * @brief

+ * Pool factory declares an interface to create and destroy pool. There may

+ * be several strategies for pool creation, and these strategies should 

+ * implement the interface defined by pool factory.

+ *

+ * \section PJ_POOL_FACTORY_ITF Pool Factory Interface

+ * The pool factory defines the following interface:

+ *  - \a policy: the memory pool factory policy.

+ *  - \a create_pool(): create a new memory pool.

+ *  - \a release_pool(): release memory pool back to factory.

+ *

+ * \section PJ_POOL_FACTORY_POL Pool Factory Policy.

+ * The pool factory policy controls the behaviour of memory factories, and

+ * defines the following interface:

+ *  - \a block_alloc(): allocate memory block from backend memory mgmt/system.

+ *  - \a block_free(): free memory block back to backend memory mgmt/system.

+ * @{

+ */

+

+/* We unfortunately don't have support for factory policy options as now,

+   so we keep this commented at the moment.

+enum PJ_POOL_FACTORY_OPTION

+{

+    PJ_POOL_FACTORY_SERIALIZE = 1

+};

+*/

+

+/**

+ * This structure declares pool factory interface.

+ */

+typedef struct pj_pool_factory_policy

+{

+    /**

+     * Allocate memory block (for use by pool). This function is called

+     * by memory pool to allocate memory block.

+     * 

+     * @param factory	Pool factory.

+     * @param size	The size of memory block to allocate.

+     *

+     * @return		Memory block.

+     */

+    void* (*block_alloc)(pj_pool_factory *factory, pj_size_t size);

+

+    /**

+     * Free memory block.

+     *

+     * @param factory	Pool factory.

+     * @param mem	Memory block previously allocated by block_alloc().

+     * @param size	The size of memory block.

+     */

+    void (*block_free)(pj_pool_factory *factory, void *mem, pj_size_t size);

+

+    /**

+     * Default callback to be called when memory allocation fails.

+     */

+    pj_pool_callback *callback;

+

+    /**

+     * Option flags.

+     */

+    unsigned flags;

+

+} pj_pool_factory_policy;

+

+/**

+ * This constant denotes the exception number that will be thrown by default

+ * memory factory policy when memory allocation fails.

+ */

+extern int PJ_NO_MEMORY_EXCEPTION;

+

+/**

+ * This global variable points to default memory pool factory policy.

+ * The behaviour of the default policy is:

+ *  - block allocation and deallocation use malloc() and free().

+ *  - callback will raise PJ_NO_MEMORY_EXCEPTION exception.

+ *  - access to pool factory is not serialized (i.e. not thread safe).

+ */

+extern pj_pool_factory_policy pj_pool_factory_default_policy;

+

+/**

+ * This structure contains the declaration for pool factory interface.

+ */

+struct pj_pool_factory

+{

+    /**

+     * Memory pool policy.

+     */

+    pj_pool_factory_policy policy;

+

+    /**

+    * Create a new pool from the pool factory.

+    *

+    * @param factory	The pool factory.

+    * @param name	the name to be assigned to the pool. The name should 

+    *			not be longer than PJ_MAX_OBJ_NAME (32 chars), or 

+    *			otherwise it will be truncated.

+    * @param initial_size the size of initial memory blocks taken by the pool.

+    *			Note that the pool will take 68+20 bytes for 

+    *			administrative area from this block.

+    * @param increment_size the size of each additional blocks to be allocated

+    *			when the pool is running out of memory. If user 

+    *			requests memory which is larger than this size, then 

+    *			an error occurs.

+    *			Note that each time a pool allocates additional block, 

+    *			it needs 20 bytes (equal to sizeof(pj_pool_block)) to 

+    *			store some administrative info.

+    * @param callback	Cllback to be called when error occurs in the pool.

+    *			Note that when an error occurs during pool creation, 

+    *			the callback itself is not called. Instead, NULL 

+    *			will be returned.

+    *

+    * @return the memory pool, or NULL.

+    */

+    pj_pool_t*	(*create_pool)( pj_pool_factory *factory,

+				const char *name,

+				pj_size_t initial_size, 

+				pj_size_t increment_size,

+				pj_pool_callback *callback);

+

+    /**

+     * Release the pool to the pool factory.

+     *

+     * @param factory	The pool factory.

+     * @param pool	The pool to be released.

+    */

+    void (*release_pool)( pj_pool_factory *factory, pj_pool_t *pool );

+

+    /**

+     * Dump pool status to log.

+     *

+     * @param factory	The pool factory.

+     */

+    void (*dump_status)( pj_pool_factory *factory, pj_bool_t detail );

+};

+

+/**

+ * This function is intended to be used by pool factory implementors.

+ * @param factory           Pool factory.

+ * @param name              Pool name.

+ * @param initial_size      Initial size.

+ * @param increment_size    Increment size.

+ * @param callback          Callback.

+ * @return                  The pool object, or NULL.

+ */

+PJ_DECL(pj_pool_t*) pj_pool_create_int(	pj_pool_factory *factory, 

+					const char *name,

+					pj_size_t initial_size, 

+					pj_size_t increment_size,

+					pj_pool_callback *callback);

+

+/**

+ * This function is intended to be used by pool factory implementors.

+ * @param pool              The pool.

+ * @param name              Pool name.

+ * @param increment_size    Increment size.

+ * @param callback          Callback function.

+ */

+PJ_DECL(void) pj_pool_init_int( pj_pool_t *pool, 

+				const char *name,

+				pj_size_t increment_size,

+				pj_pool_callback *callback);

+

+/**

+ * This function is intended to be used by pool factory implementors.

+ * @param pool      The memory pool.

+ */

+PJ_DECL(void) pj_pool_destroy_int( pj_pool_t *pool );

+

+

+/**

+ *  @}	// PJ_POOL_FACTORY

+ */

+

+///////////////////////////////////////////////////////////////////////////////

+

+/**

+ * @defgroup PJ_CACHING_POOL Caching Pool Factory.

+ * @ingroup PJ_POOL_GROUP

+ * @brief

+ * Caching pool is one sample implementation of pool factory where the

+ * factory can reuse memory to create a pool. Application defines what the 

+ * maximum memory the factory can hold, and when a pool is released the

+ * factory decides whether to destroy the pool or to keep it for future use.

+ * If the total amount of memory in the internal cache is still within the

+ * limit, the factory will keep the pool in the internal cache, otherwise the

+ * pool will be destroyed, thus releasing the memory back to the system.

+ *

+ * @{

+ */

+

+/**

+ * Number of unique sizes, to be used as index to the free list.

+ * Each pool in the free list is organized by it's size.

+ */

+#define PJ_CACHING_POOL_ARRAY_SIZE	16

+

+/**

+ * Declaration for caching pool. Application doesn't normally need to

+ * care about the contents of this struct, it is only provided here because

+ * application need to define an instance of this struct (we can not allocate

+ * the struct from a pool since there is no pool factory yet!).

+ */

+struct pj_caching_pool 

+{

+    /** Pool factory interface, must be declared first. */

+    pj_pool_factory factory;

+

+    /** Current factory's capacity, i.e. number of bytes that are allocated

+     *  and available for application in this factory. The factory's

+     *  capacity represents the size of all pools kept by this factory

+     *  in it's free list, which will be returned to application when it

+     *  requests to create a new pool.

+     */

+    pj_size_t	    capacity;

+

+    /** Maximum size that can be held by this factory. Once the capacity

+     *  has exceeded @a max_capacity, further #pj_pool_release() will

+     *  flush the pool. If the capacity is still below the @a max_capacity,

+     *  #pj_pool_release() will save the pool to the factory's free list.

+     */

+    pj_size_t       max_capacity;

+

+    /**

+     * Number of pools currently held by applications. This number gets

+     * incremented everytime #pj_pool_create() is called, and gets

+     * decremented when #pj_pool_release() is called.

+     */

+    pj_size_t       used_count;

+

+    /**

+     * Lists of pools in the cache, indexed by pool size.

+     */

+    pj_list	    free_list[PJ_CACHING_POOL_ARRAY_SIZE];

+

+    /**

+     * List of pools currently allocated by applications.

+     */

+    pj_list	    used_list;

+};

+

+

+

+/**

+ * Initialize caching pool.

+ *

+ * @param ch_pool	The caching pool factory to be initialized.

+ * @param policy	Pool factory policy.

+ * @param max_capacity	The total capacity to be retained in the cache. When

+ *			the pool is returned to the cache, it will be kept in

+ *			recycling list if the total capacity of pools in this

+ *			list plus the capacity of the pool is still below this

+ *			value.

+ */

+PJ_DECL(void) pj_caching_pool_init( pj_caching_pool *ch_pool, 

+				    const pj_pool_factory_policy *policy,

+				    pj_size_t max_capacity);

+

+

+/**

+ * Destroy caching pool, and release all the pools in the recycling list.

+ *

+ * @param ch_pool	The caching pool.

+ */

+PJ_DECL(void) pj_caching_pool_destroy( pj_caching_pool *ch_pool );

+

+/**

+ * @}	// PJ_CACHING_POOL

+ */

+

+#  if PJ_FUNCTIONS_ARE_INLINED

+#    include "pool_i.h"

+#  endif

+

+PJ_END_DECL

+    

+#endif	/* __PJ_POOL_H__ */

+

diff --git a/pjlib/include/pj/pool_i.h b/pjlib/include/pj/pool_i.h
new file mode 100644
index 0000000..08dd7ca
--- /dev/null
+++ b/pjlib/include/pj/pool_i.h
@@ -0,0 +1,74 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/pool_i.h 6     10/14/05 12:26a Bennylp $ */

+

+

+#include <pj/string.h>

+

+PJ_DECL(void*) pj_pool_allocate_find(pj_pool_t *pool, unsigned size);

+

+PJ_IDEF(pj_size_t) pj_pool_get_capacity( pj_pool_t *pool )

+{

+    return pool->capacity;

+}

+

+PJ_IDEF(pj_size_t) pj_pool_get_used_size( pj_pool_t *pool )

+{

+    return pool->used_size;

+}

+

+PJ_IDEF(void*) pj_pool_alloc_from_block( pj_pool_t *pool,

+					 pj_pool_block *block, pj_size_t size )

+{

+    /* The operation below is valid for size==0. 

+     * When size==0, the function will return the pointer to the pool

+     * memory address, but no memory will be allocated.

+     */

+    if (size & (PJ_POOL_ALIGNMENT-1)) {

+	size &= ~(PJ_POOL_ALIGNMENT-1);

+	size += PJ_POOL_ALIGNMENT;

+    }

+    if ((unsigned)(block->end - block->cur) >= size) {

+	void *ptr = block->cur;

+	block->cur += size;

+	pool->used_size += size;

+	return ptr;

+    }

+    return NULL;

+}

+

+PJ_IDEF(void*) pj_pool_alloc( pj_pool_t *pool, pj_size_t size)

+{

+    pj_pool_block *block = pool->block_list.next;

+    void *ptr = pj_pool_alloc_from_block(pool, block, size);

+    if (!ptr)

+	ptr = pj_pool_allocate_find(pool, size);

+    return ptr;

+}

+

+

+PJ_IDEF(void*) pj_pool_calloc( pj_pool_t *pool, pj_size_t count, pj_size_t size)

+{

+    void *buf = pj_pool_alloc( pool, size*count);

+    if (buf)

+	pj_memset(buf, 0, size * count);

+    return buf;

+}

+

+PJ_IDEF(const char *) pj_pool_getobjname( const pj_pool_t *pool )

+{

+    return pool->obj_name;

+}

+

+PJ_IDEF(pj_pool_t*) pj_pool_create( pj_pool_factory *f, 

+				    const char *name,

+				    pj_size_t initial_size, 

+				    pj_size_t increment_size,

+				    pj_pool_callback *callback)

+{

+    return (*f->create_pool)(f, name, initial_size, increment_size, callback);

+}

+

+PJ_IDEF(void) pj_pool_release( pj_pool_t *pool )

+{

+    (*pool->factory->release_pool)(pool->factory, pool);

+}

+

diff --git a/pjlib/include/pj/rand.h b/pjlib/include/pj/rand.h
new file mode 100644
index 0000000..2f61231
--- /dev/null
+++ b/pjlib/include/pj/rand.h
@@ -0,0 +1,60 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/rand.h 3     10/14/05 12:26a Bennylp $ */

+/* $Log: /pjproject-0.3/pjlib/include/pj/rand.h $

+ * 

+ * 3     10/14/05 12:26a Bennylp

+ * Finished error code framework, some fixes in ioqueue, etc. Pretty

+ * major.

+ * 

+ * 2     9/17/05 10:37a Bennylp

+ * Major reorganization towards version 0.3.

+ * 

+ * 1     9/15/05 8:40p Bennylp

+ * Created.

+ */

+#ifndef __PJ_RAND_H__

+#define __PJ_RAND_H__

+

+/**

+ * @file rand.h

+ * @brief Random Number Generator.

+ */

+

+#include <pj/config.h>

+

+PJ_BEGIN_DECL

+

+

+/**

+ * @defgroup PJ_RAND Random Number Generator

+ * @ingroup PJ_MISC

+ * @{

+ * This module contains functions for generating random numbers.

+ * This abstraction is needed not only because not all platforms have

+ * \a rand() and \a srand(), but also on some platforms \a rand()

+ * only has 16-bit randomness, which is not good enough.

+ */

+

+/**

+ * Put in seed to random number generator.

+ *

+ * @param seed	    Seed value.

+ */

+PJ_DECL(void) pj_srand(unsigned int seed);

+

+

+/**

+ * Generate random integer with 32bit randomness.

+ *

+ * @return a random integer.

+ */

+PJ_DECL(int) pj_rand(void);

+

+

+/** @} */

+

+

+PJ_END_DECL

+

+

+#endif	/* __PJ_RAND_H__ */

+

diff --git a/pjlib/include/pj/rbtree.h b/pjlib/include/pj/rbtree.h
new file mode 100644
index 0000000..f94e365
--- /dev/null
+++ b/pjlib/include/pj/rbtree.h
@@ -0,0 +1,193 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/rbtree.h 5     10/14/05 12:26a Bennylp $ */

+

+#ifndef __PJ_RBTREE_H__

+#define __PJ_RBTREE_H__

+

+/**

+ * @file rbtree.h

+ * @brief Red/Black Tree

+ */

+

+#include <pj/types.h>

+

+PJ_BEGIN_DECL

+

+/**

+ * @defgroup PJ_RBTREE Red/Black Balanced Tree

+ * @ingroup PJ_DS

+ * @brief

+ * Red/Black tree is the variant of balanced tree, where the search, insert, 

+ * and delete operation is \b guaranteed to take at most \a O( lg(n) ).

+ * @{

+ */

+/**

+ * Color type for Red-Black tree.

+ */ 

+typedef enum pj_rbcolor_t

+{

+    PJ_RBCOLOR_BLACK,

+    PJ_RBCOLOR_RED

+} pj_rbcolor_t;

+

+/**

+ * The type of the node of the R/B Tree.

+ */

+typedef struct pj_rbtree_node 

+{

+    /** Pointers to the node's parent, and left and right siblings. */

+    struct pj_rbtree_node *parent, *left, *right;

+

+    /** Key associated with the node. */

+    const void *key;

+

+    /** User data associated with the node. */

+    void *user_data;

+

+    /** The R/B Tree node color. */

+    pj_rbcolor_t color;

+

+} pj_rbtree_node;

+

+

+/**

+ * The type of function use to compare key value of tree node.

+ * @return

+ *  0 if the keys are equal

+ * <0 if key1 is lower than key2

+ * >0 if key1 is greater than key2.

+ */

+typedef int pj_rbtree_comp(const void *key1, const void *key2);

+

+

+/**

+ * Declaration of a red-black tree. All elements in the tree must have UNIQUE

+ * key.

+ * A red black tree always maintains the balance of the tree, so that the

+ * tree height will not be greater than lg(N). Insert, search, and delete

+ * operation will take lg(N) on the worst case. But for insert and delete,

+ * there is additional time needed to maintain the balance of the tree.

+ */

+typedef struct pj_rbtree

+{

+    pj_rbtree_node null_node;   /**< Constant to indicate NULL node.    */

+    pj_rbtree_node *null;       /**< Constant to indicate NULL node.    */

+    pj_rbtree_node *root;       /**< Root tree node.                    */

+    unsigned size;              /**< Number of elements in the tree.    */

+    pj_rbtree_comp *comp;       /**< Key comparison function.           */

+} pj_rbtree;

+

+

+/**

+ * Guidance on how much memory required for each of the node.

+ */

+#define PJ_RBTREE_NODE_SIZE	    (sizeof(pj_rbtree_node))

+

+

+/**

+ * Guidance on memory required for the tree.

+ */

+#define PJ_RBTREE_SIZE		    (sizeof(pj_rbtree))

+

+

+/**

+ * Initialize the tree.

+ * @param tree the tree to be initialized.

+ * @param comp key comparison function to be used for this tree.

+ */

+PJ_DECL(void) pj_rbtree_init( pj_rbtree *tree, pj_rbtree_comp *comp);

+

+/**

+ * Get the first element in the tree.

+ * The first element always has the least value for the key, according to

+ * the comparison function.

+ * @param tree the tree.

+ * @return the tree node, or NULL if the tree has no element.

+ */

+PJ_DECL(pj_rbtree_node*) pj_rbtree_first( pj_rbtree *tree );

+

+/**

+ * Get the last element in the tree.

+ * The last element always has the greatest key value, according to the

+ * comparison function defined for the tree.

+ * @param tree the tree.

+ * @return the tree node, or NULL if the tree has no element.

+ */

+PJ_DECL(pj_rbtree_node*) pj_rbtree_last( pj_rbtree *tree );

+

+/**

+ * Get the successive element for the specified node.

+ * The successive element is an element with greater key value.

+ * @param tree the tree.

+ * @param node the node.

+ * @return the successive node, or NULL if the node has no successor.

+ */

+PJ_DECL(pj_rbtree_node*) pj_rbtree_next( pj_rbtree *tree, 

+					 pj_rbtree_node *node );

+

+/**

+ * The the previous node for the specified node.

+ * The previous node is an element with less key value.

+ * @param tree the tree.

+ * @param node the node.

+ * @return the previous node, or NULL if the node has no previous node.

+ */

+PJ_DECL(pj_rbtree_node*) pj_rbtree_prev( pj_rbtree *tree, 

+					 pj_rbtree_node *node );

+

+/**

+ * Insert a new node. 

+ * The node will be inserted at sorted location. The key of the node must 

+ * be UNIQUE, i.e. it hasn't existed in the tree.

+ * @param tree the tree.

+ * @param node the node to be inserted.

+ * @return zero on success, or -1 if the key already exist.

+ */

+PJ_DECL(int) pj_rbtree_insert( pj_rbtree *tree, 

+			       pj_rbtree_node *node );

+

+/**

+ * Find a node which has the specified key.

+ * @param tree the tree.

+ * @param key the key to search.

+ * @return the tree node with the specified key, or NULL if the key can not

+ *         be found.

+ */

+PJ_DECL(pj_rbtree_node*) pj_rbtree_find( pj_rbtree *tree,

+					 const void *key );

+

+/**

+ * Erase a node from the tree.

+ * @param tree the tree.

+ * @param node the node to be erased.

+ * @return the tree node itself.

+ */

+PJ_DECL(pj_rbtree_node*) pj_rbtree_erase( pj_rbtree *tree,

+					  pj_rbtree_node *node );

+

+/**

+ * Get the maximum tree height from the specified node.

+ * @param tree the tree.

+ * @param node the node, or NULL to get the root of the tree.

+ * @return the maximum height, which should be at most lg(N)

+ */

+PJ_DECL(unsigned) pj_rbtree_max_height( pj_rbtree *tree,

+					pj_rbtree_node *node );

+

+/**

+ * Get the minumum tree height from the specified node.

+ * @param tree the tree.

+ * @param node the node, or NULL to get the root of the tree.

+ * @return the height

+ */

+PJ_DECL(unsigned) pj_rbtree_min_height( pj_rbtree *tree,

+					pj_rbtree_node *node );

+

+

+/**

+ * @}

+ */

+

+PJ_END_DECL

+

+#endif	/* __PJ_RBTREE_H__ */

+

diff --git a/pjlib/include/pj/scanner.h b/pjlib/include/pj/scanner.h
new file mode 100644
index 0000000..5b04c68
--- /dev/null
+++ b/pjlib/include/pj/scanner.h
@@ -0,0 +1,454 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/scanner.h 10    10/14/05 12:26a Bennylp $ */

+

+#ifndef __PJ_PARSER_H__

+#define __PJ_PARSER_H__

+

+/**

+ * @file scanner.h

+ * @brief Text Scanning.

+ */

+

+#include <pj/types.h>

+

+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.

+ * @{

+ */

+

+/**

+ * This describes the type of individual character specification in

+ * #pj_char_spec.

+ */

+typedef pj_uint8_t pj_char_spec_element_t;

+

+/**

+ * 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.

+

+/**

+ * Initialize character spec.

+ * @param cs the scanner character specification.

+ */

+PJ_DECL(void) pj_cs_init( pj_char_spec cs);

+

+/**

+ * 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);

+

+/**

+ * 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.

+ */

+PJ_DECL(void) pj_cs_add_range( pj_char_spec cs, int cstart, int cend);

+

+/**

+ * Add alphabetic characters to the specification.

+ * @param cs the scanner character specification.

+ */

+PJ_DECL(void) pj_cs_add_alpha( pj_char_spec cs);

+

+/**

+ * Add numeric characters to the specification.

+ * @param cs the scanner character specification.

+ */

+PJ_DECL(void) pj_cs_add_num( pj_char_spec cs);

+

+/**

+ * Add the characters in the string to the specification.

+ * @param cs the scanner character specification.

+ * @param str the string.

+ */

+PJ_DECL(void) pj_cs_add_str( pj_char_spec cs, 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.

+ */

+PJ_DECL(void) pj_cs_del_range( pj_char_spec cs, int cstart, int cend);

+

+/**

+ * Delete characters in the specified string from the specification.

+ * @param cs the scanner character specification.

+ * @param str the string.

+ */

+PJ_DECL(void) pj_cs_del_str( pj_char_spec cs, const char *str);

+

+/**

+ * Invert specification.

+ * @param cs the scanner character specification.

+ */

+PJ_DECL(void) pj_cs_invert( pj_char_spec cs );

+

+/**

+ * Check whether the specified character belongs to the specification.

+ * @param cs 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 )

+{

+    return cs[c];

+}

+

+/**

+ * @}

+ */

+

+/**

+ * @defgroup PJ_SCANNER Text Scanner

+ * @ingroup PJ_SCAN

+ * @{

+ */

+

+/**

+ * Flags for scanner.

+ */

+enum

+{

+    /** This flags specifies that the scanner should automatically skip

+	whitespaces 

+     */

+    PJ_SCAN_AUTOSKIP_WS = 1,

+

+    /** This flags specifies that the scanner should automatically skip

+        SIP header continuation. This flag implies PJ_SCAN_AUTOSKIP_WS.

+     */

+    PJ_SCAN_AUTOSKIP_WS_HEADER = 3,

+

+    /** Auto-skip new lines.

+     */

+    PJ_SCAN_AUTOSKIP_NEWLINE = 4,

+};

+

+

+/* Forward decl. */

+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 .

+ */

+typedef void (*pj_syn_err_func_ptr)(struct pj_scanner *scanner);

+

+

+/**

+ * The text scanner structure.

+ */

+typedef struct pj_scanner

+{

+    char *begin;        /**< Start of input buffer. */

+    char *end;          /**< End of input buffer.   */

+    char *curptr;       /**< Current pointer.       */

+    int  line;          /**< Current line.          */

+    int  col;           /**< Current column.        */

+    int  skip_ws;       /**< Skip whitespace flag.  */

+    pj_syn_err_func_ptr callback;   /**< Syntax error callback. */

+} pj_scanner;

+

+

+/**

+ * This structure can be used by application to store the state of the parser,

+ * so that the scanner state can be rollback to this state when necessary.

+ */

+typedef struct pj_scan_state

+{

+    char *curptr;       /**< Current scanner's pointer. */

+    int   line;         /**< Current line.      */

+    int   col;          /**< Current column.    */

+} pj_scan_state;

+

+

+/**

+ * Initialize the scanner. Note that the input string buffer must have

+ * length at least buflen+1 because the scanner will NULL terminate the

+ * string during initialization.

+ *

+ * @param scanner   The scanner to be initialized.

+ * @param bufstart  The input buffer to scan. Note that buffer[buflen] will be 

+ *		    filled with NULL char until scanner is destroyed, so

+ *		    the actual buffer length must be at least buflen+1.

+ * @param buflen    The length of the input buffer, which normally is

+ *		    strlen(bufstart).

+ * @param options   Zero, or combination of PJ_SCAN_AUTOSKIP_WS or

+ *		    PJ_SCAN_AUTOSKIP_WS_HEADER

+ * @param callback  Callback to be called when the scanner encounters syntax

+ *		    error condition.

+ */

+PJ_DECL(void) pj_scan_init( pj_scanner *scanner, char *bufstart, int buflen, 

+			    unsigned options,

+			    pj_syn_err_func_ptr callback );

+

+

+/** 

+ * Call this function when application has finished using the scanner.

+ *

+ * @param scanner   The scanner.

+ */

+PJ_DECL(void) pj_scan_fini( pj_scanner *scanner );

+

+

+/** 

+ * Determine whether the EOF condition for the scanner has been met.

+ *

+ * @param scanner   The scanner.

+ *

+ * @return Non-zero if scanner is EOF.

+ */

+PJ_INLINE(int) pj_scan_is_eof( const pj_scanner *scanner)

+{

+    return scanner->curptr >= scanner->end;

+}

+

+

+/** 

+ * Peek strings in current position according to parameter spec, and return

+ * the strings in parameter out. The current scanner position will not be

+ * moved. If the scanner is already in EOF state, syntax error callback will

+ * be called thrown.

+ *

+ * @param scanner   The scanner.

+ * @param spec	    The spec to match input string.

+ * @param out	    String to store the result.

+ *

+ * @return the character right after the peek-ed position or zero if there's

+ *	   no more characters.

+ */

+PJ_DECL(int) pj_scan_peek( pj_scanner *scanner,

+			    const pj_char_spec spec, pj_str_t *out);

+

+

+/** 

+ * Peek len characters in current position, and return them in out parameter.

+ * Note that whitespaces or newlines will be returned as it is, regardless

+ * of PJ_SCAN_AUTOSKIP_WS settings. If the character left is less than len, 

+ * syntax error callback will be called.

+ *

+ * @param scanner   The scanner.

+ * @param len	    Length to peek.

+ * @param out	    String to store the result.

+ *

+ * @return the character right after the peek-ed position or zero if there's

+ *	   no more characters.

+ */

+PJ_DECL(int) pj_scan_peek_n( pj_scanner *scanner,

+			      pj_size_t len, pj_str_t *out);

+

+

+/** 

+ * Peek strings in current position until spec is matched, and return

+ * the strings in parameter out. The current scanner position will not be

+ * moved. If the scanner is already in EOF state, syntax error callback will

+ * be called.

+ *

+ * @param scanner   The scanner.

+ * @param spec	    The peeking will stop when the input match this spec.

+ * @param out	    String to store the result.

+ *

+ * @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);

+

+

+/** 

+ * Get characters from the buffer according to the spec, and return them

+ * in out parameter. The scanner will attempt to get as many characters as

+ * possible as long as the spec matches. If the first character doesn't

+ * match the spec, or scanner is already in EOF when this function is called,

+ * an exception will be thrown.

+ *

+ * @param scanner   The scanner.

+ * @param spec	    The spec to match input string.

+ * @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);

+

+

+/** 

+ * Get characters between quotes. If current input doesn't match begin_quote,

+ * syntax error will be thrown.

+ *

+ * @param scanner	The scanner.

+ * @param begin_quote	The character to begin the quote.

+ * @param end_quote	The character to end the quote.

+ * @param out		String to store the result.

+ */

+PJ_DECL(void) pj_scan_get_quote( pj_scanner *scanner,

+				  int begin_quote, int end_quote, 

+				  pj_str_t *out);

+

+/** 

+ * Get N characters from the scanner.

+ *

+ * @param scanner   The scanner.

+ * @param N	    Number of characters to get.

+ * @param out	    String to store the result.

+ */

+PJ_DECL(void) pj_scan_get_n( pj_scanner *scanner,

+			      unsigned N, pj_str_t *out);

+

+

+/** 

+ * Get one character from the scanner.

+ *

+ * @param scanner   The scanner.

+ *

+ * @return (unknown)

+ */

+PJ_DECL(int) pj_scan_get_char( pj_scanner *scanner );

+

+

+/** 

+ * Get a newline from the scanner. A newline is defined as '\\n', or '\\r', or

+ * "\\r\\n". If current input is not newline, syntax error will be thrown.

+ *

+ * @param scanner   The scanner.

+ */

+PJ_DECL(void) pj_scan_get_newline( pj_scanner *scanner );

+

+

+/** 

+ * Get characters from the scanner and move the scanner position until the

+ * current character matches the spec.

+ *

+ * @param scanner   The scanner.

+ * @param spec	    Get until the input match this spec.

+ * @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);

+

+

+/** 

+ * Get characters from the scanner and move the scanner position until the

+ * current character matches until_char.

+ *

+ * @param scanner	The scanner.

+ * @param until_char    Get until the input match this character.

+ * @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);

+

+

+/** 

+ * Get characters from the scanner and move the scanner position until the

+ * current character matches until_char.

+ *

+ * @param scanner	The scanner.

+ * @param until_spec	Get until the input match any of these characters.

+ * @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);

+

+/** 

+ * Advance the scanner N characters, and skip whitespace

+ * if necessary.

+ *

+ * @param scanner   The scanner.

+ * @param N	    Number of characters to skip.

+ * @param skip	    Flag to specify whether whitespace should be skipped

+ *		    after skipping the characters.

+ */

+PJ_DECL(void) pj_scan_advance_n( pj_scanner *scanner,

+				  unsigned N, pj_bool_t skip);

+

+

+/** 

+ * Compare string in current position with the specified string.

+ * 

+ * @param scanner   The scanner.

+ * @param s	    The string to compare with.

+ * @param len	    Length of the string to compare.

+ *

+ * @return zero, <0, or >0 (just like strcmp()).

+ */

+PJ_DECL(int) pj_scan_strcmp( pj_scanner *scanner, const char *s, int len);

+

+

+/** 

+ * Case-less string comparison of current position with the specified

+ * string.

+ *

+ * @param scanner   The scanner.

+ * @param s	    The string to compare with.

+ * @param len	    Length of the string to compare with.

+ *

+ * @return zero, <0, or >0 (just like strcmp()).

+ */

+PJ_DECL(int) pj_scan_stricmp( pj_scanner *scanner, const char *s, int len);

+

+

+/** 

+ * Manually skip whitespaces according to flag that was specified when

+ * the scanner was initialized.

+ *

+ * @param scanner   The scanner.

+ */

+PJ_DECL(void) pj_scan_skip_whitespace( pj_scanner *scanner );

+

+

+/** 

+ * Save the full scanner state.

+ *

+ * @param scanner   The scanner.

+ * @param state	    Variable to store scanner's state.

+ */

+PJ_DECL(void) pj_scan_save_state( pj_scanner *scanner, pj_scan_state *state);

+

+

+/** 

+ * Restore the full scanner state.

+ * Note that this would not restore the string if application has modified

+ * it. This will only restore the scanner scanning position.

+ *

+ * @param scanner   The scanner.

+ * @param state	    State of the scanner.

+ */

+PJ_DECL(void) pj_scan_restore_state( pj_scanner *scanner, 

+				      pj_scan_state *state);

+

+/**

+ * @}

+ */

+

+#if PJ_FUNCTIONS_ARE_INLINED

+#  include "scanner_i.h"

+#endif

+

+

+PJ_END_DECL

+

+#endif

+

diff --git a/pjlib/include/pj/sock.h b/pjlib/include/pj/sock.h
new file mode 100644
index 0000000..c0aa56c
--- /dev/null
+++ b/pjlib/include/pj/sock.h
@@ -0,0 +1,677 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/sock.h 10    10/14/05 12:26a Bennylp $ */

+

+#ifndef __PJ_SOCK_H__

+#define __PJ_SOCK_H__

+

+/**

+ * @file sock.h

+ * @brief Socket Abstraction.

+ */

+

+#include <pj/types.h>

+

+PJ_BEGIN_DECL 

+

+

+/**

+ * @defgroup PJ_SOCK Socket Abstraction

+ * @ingroup PJ_IO

+ * @{

+ *

+ * The PJLIB socket abstraction layer is a thin and very portable abstraction

+ * for socket API. It provides API similar to BSD socket API. The abstraction

+ * is needed because BSD socket API is not always available on all platforms,

+ * therefore it wouldn't be possible to create a trully portable network

+ * programs unless we provide such abstraction.

+ *

+ * Applications can use this API directly in their application, just

+ * as they would when using traditional BSD socket API, provided they

+ * call #pj_init() first.

+ *

+ * \section pj_sock_examples_sec Examples

+ *

+ * For some examples on how to use the socket API, please see:

+ *

+ *  - \ref page_pjlib_sock_test

+ *  - \ref page_pjlib_select_test

+ *  - \ref page_pjlib_sock_perf_test

+ */

+

+

+/**

+ * Supported address families. 

+ * APPLICATION MUST USE THESE VALUES INSTEAD OF NORMAL AF_*, BECAUSE

+ * THE LIBRARY WILL DO TRANSLATION TO THE NATIVE VALUE.

+ */

+extern const pj_uint16_t PJ_AF_UNIX;    /**< Unix domain socket.	*/

+#define PJ_AF_LOCAL	 PJ_AF_UNIX;    /**< POSIX name for AF_UNIX	*/

+extern const pj_uint16_t PJ_AF_INET;    /**< Internet IP protocol.	*/

+extern const pj_uint16_t PJ_AF_INET6;   /**< IP version 6.		*/

+extern const pj_uint16_t PJ_AF_PACKET;  /**< Packet family.		*/

+extern const pj_uint16_t PJ_AF_IRDA;    /**< IRDA sockets.		*/

+

+

+/**

+ * Supported types of sockets.

+ * APPLICATION MUST USE THESE VALUES INSTEAD OF NORMAL SOCK_*, BECAUSE

+ * THE LIBRARY WILL TRANSLATE THE VALUE TO THE NATIVE VALUE.

+ */

+

+extern const pj_uint16_t PJ_SOCK_STREAM; /**< Sequenced, reliable, connection-

+					      based byte streams.           */

+extern const pj_uint16_t PJ_SOCK_DGRAM;  /**< Connectionless, unreliable 

+					      datagrams of fixed maximum 

+					      lengths.                      */

+extern const pj_uint16_t PJ_SOCK_RAW;    /**< Raw protocol interface.       */

+extern const pj_uint16_t PJ_SOCK_RDM;    /**< Reliably-delivered messages.  */

+

+

+/**

+ * Socket level specified in #pj_sock_setsockopt().

+ * APPLICATION MUST USE THESE VALUES INSTEAD OF NORMAL SOL_*, BECAUSE

+ * THE LIBRARY WILL TRANSLATE THE VALUE TO THE NATIVE VALUE.

+ */

+extern const pj_uint16_t PJ_SOL_SOCKET;	/**< Socket level.  */

+extern const pj_uint16_t PJ_SOL_IP;	/**< IP level.	    */

+extern const pj_uint16_t PJ_SOL_TCP;	/**< TCP level.	    */

+extern const pj_uint16_t PJ_SOL_UDP;	/**< UDP level.	    */

+extern const pj_uint16_t PJ_SOL_IPV6;	/**< IP version 6   */

+

+/**

+ * Flags to be specified in #pj_sock_recv, #pj_sock_send, etc.

+ */

+typedef enum pj_sock_msg_flag

+{

+    PJ_MSG_OOB		= 0x01,	    /**< Out-of-band messages.		 */

+    PJ_MSG_PEEK		= 0x02,	    /**< Peek, don't remove from buffer. */

+    PJ_MSG_DONTROUTE	= 0x04,	    /**< Don't route.			 */

+} pj_sock_msg_flag;

+

+

+/**

+ * Flag to be specified in #pj_sock_shutdown.

+ */

+typedef enum pj_socket_sd_type

+{

+    PJ_SD_RECEIVE   = 0,    /**< No more receive.	    */

+    PJ_SHUT_RD	    = 0,    /**< Alias for SD_RECEIVE.	    */

+    PJ_SD_SEND	    = 1,    /**< No more sending.	    */

+    PJ_SHUT_WR	    = 1,    /**< Alias for SD_SEND.	    */

+    PJ_SD_BOTH	    = 2,    /**< No more send and receive.  */

+    PJ_SHUT_RDWR    = 2,    /**< Alias for SD_BOTH.	    */

+} pj_socket_sd_type;

+

+

+

+/** Address to accept any incoming messages. */

+#define PJ_INADDR_ANY	    ((pj_uint32_t)0)

+

+/** Address indicating an error return */

+#define PJ_INADDR_NONE	    ((pj_uint32_t)0xffffffff)

+

+/** Address to send to all hosts. */

+#define PJ_INADDR_BROADCAST ((pj_uint32_t)0xffffffff)

+

+

+/** 

+ * Maximum length specifiable by #pj_sock_listen().

+ * If the build system doesn't override this value, then the lowest 

+ * denominator (five, in Win32 systems) will be used.

+ */

+#if !defined(PJ_SOMAXCONN)

+#  define PJ_SOMAXCONN	5

+#endif

+

+

+/**

+ * Constant for invalid socket returned by #pj_sock_socket() and

+ * #pj_sock_accept().

+ */

+#define PJ_INVALID_SOCKET   (-1)

+

+/**

+ * Structure describing a generic socket address.

+ */

+typedef struct pj_sockaddr

+{

+    pj_uint16_t	sa_family;	/**< Common data: address family.   */

+    char	sa_data[14];	/**< Address data.		    */

+} pj_sockaddr;

+

+

+/**

+ * This structure describes Internet address.

+ */

+typedef struct pj_in_addr

+{

+    pj_uint32_t	s_addr;		/**< The 32bit IP address.	    */

+} pj_in_addr;

+

+

+/**

+ * This structure describes Internet socket address.

+ */

+typedef struct pj_sockaddr_in

+{

+    pj_uint16_t	sin_family;	/**< Address family.		    */

+    pj_uint16_t	sin_port;	/**< Transport layer port number.   */

+    pj_in_addr	sin_addr;	/**< IP address.		    */

+    char	sin_zero[8];	/**< Padding.			    */

+} pj_sockaddr_in;

+

+

+/**

+ * This structure describes IPv6 address.

+ */

+typedef struct pj_in6_addr

+{

+    /** Union of address formats. */

+    union {

+	pj_uint8_t  u6_addr8[16];   /**< u6_addr8   */

+	pj_uint16_t u6_addr16[8];   /**< u6_addr16  */

+	pj_uint32_t u6_addr32[4];   /**< u6_addr32  */

+    } in6_u;

+/** Shortcut to access in6_u.u6_addr8. */

+#define s6_addr                 in6_u.u6_addr8

+/** Shortcut to access in6_u.u6_addr16. */

+#define s6_addr16               in6_u.u6_addr16

+/** Shortcut to access in6_u.u6_addr32. */

+#define s6_addr32               in6_u.u6_addr32

+} pj_in6_addr;

+

+/** Initializer value for pj_in6_addr. */

+#define PJ_IN6ADDR_ANY_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } }

+

+/** Initializer value for pj_in6_addr. */

+#define PJ_IN6ADDR_LOOPBACK_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } }

+

+/**

+ * This structure describes IPv6 socket address.

+ */

+typedef struct pj_sockaddr_in6

+{

+    pj_uint16_t	sin6_family;	    /**< Address family		    */

+    pj_uint16_t	sin6_port;	    /**< Transport layer port number. */

+    pj_uint32_t	sin6_flowinfo;	    /**< IPv6 flow information	    */

+    pj_in6_addr sin6_addr;	    /**< IPv6 address.		    */

+    pj_uint32_t sin6_scope_id;	    /**< IPv6 scope-id		    */

+} pj_sockaddr_in6;

+

+

+/*****************************************************************************

+ *

+ * SOCKET ADDRESS MANIPULATION.

+ *

+ *****************************************************************************

+ */

+

+/**

+ * Convert 16-bit value from network byte order to host byte order.

+ *

+ * @param netshort  16-bit network value.

+ * @return	    16-bit host value.

+ */

+PJ_DECL(pj_uint16_t) pj_ntohs(pj_uint16_t netshort);

+

+/**

+ * Convert 16-bit value from host byte order to network byte order.

+ *

+ * @param hostshort 16-bit host value.

+ * @return	    16-bit network value.

+ */

+PJ_DECL(pj_uint16_t) pj_htons(pj_uint16_t hostshort);

+

+/**

+ * Convert 32-bit value from network byte order to host byte order.

+ *

+ * @param netlong   32-bit network value.

+ * @return	    32-bit host value.

+ */

+PJ_DECL(pj_uint32_t) pj_ntohl(pj_uint32_t netlong);

+

+/**

+ * Convert 32-bit value from host byte order to network byte order.

+ *

+ * @param hostlong  32-bit host value.

+ * @return	    32-bit network value.

+ */

+PJ_DECL(pj_uint32_t) pj_htonl(pj_uint32_t hostlong);

+

+/**

+ * Convert an Internet host address given in network byte order

+ * to string in standard numbers and dots notation.

+ *

+ * @param inaddr    The host address.

+ * @return	    The string address.

+ */

+PJ_DECL(char*) pj_inet_ntoa(pj_in_addr inaddr);

+

+/**

+ * This function converts the Internet host address cp from the standard

+ * numbers-and-dots notation into binary data and stores it in the structure

+ * that inp points to. 

+ *

+ * @param cp	IP address in standard numbers-and-dots notation.

+ * @param inp	Structure that holds the output of the conversion.

+ *

+ * @return	nonzero if the address is valid, zero if not.

+ */

+PJ_DECL(int) pj_inet_aton(const pj_str_t *cp, struct pj_in_addr *inp);

+

+/**

+ * Convert address string with numbers and dots to binary IP address.

+ * 

+ * @param cp	    The IP address in numbers and dots notation.

+ * @return	    If success, the IP address is returned in network

+ *		    byte order. If failed, PJ_INADDR_NONE will be

+ *		    returned.

+ * @remark

+ * This is an obsolete interface to #pj_inet_aton(); it is obsolete

+ * because -1 is a valid address (255.255.255.255), and #pj_inet_aton()

+ * provides a cleaner way to indicate error return.

+ */

+PJ_DECL(pj_in_addr) pj_inet_addr(const pj_str_t *cp);

+

+

+/**

+ * Get the transport layer port number of an Internet socket address.

+ * The port is returned in host byte order.

+ *

+ * @param addr	    The IP socket address.

+ * @return	    Port number, in host byte order.

+ */

+PJ_INLINE(pj_uint16_t) pj_sockaddr_in_get_port(const pj_sockaddr_in *addr)

+{

+    return pj_ntohs(addr->sin_port);

+}

+

+/**

+ * Set the port number of an Internet socket address.

+ *

+ * @param addr	    The IP socket address.

+ * @param hostport  The port number, in host byte order.

+ */

+PJ_INLINE(void) pj_sockaddr_in_set_port(pj_sockaddr_in *addr, 

+					pj_uint16_t hostport)

+{

+    addr->sin_port = pj_htons(hostport);

+}

+

+/**

+ * Get the IP address of an Internet socket address.

+ * The address is returned as 32bit value in host byte order.

+ *

+ * @param addr	    The IP socket address.

+ * @return	    32bit address, in host byte order.

+ */

+PJ_INLINE(pj_in_addr) pj_sockaddr_in_get_addr(const pj_sockaddr_in *addr)

+{

+    pj_in_addr in_addr;

+    in_addr.s_addr = pj_ntohl(addr->sin_addr.s_addr);

+    return in_addr;

+};

+

+/**

+ * Set the IP address of an Internet socket address.

+ *

+ * @param addr	    The IP socket address.

+ * @param hostaddr  The host address, in host byte order.

+ */

+PJ_INLINE(void) pj_sockaddr_in_set_addr(pj_sockaddr_in *addr,

+					pj_uint32_t hostaddr)

+{

+    addr->sin_addr.s_addr = pj_htonl(hostaddr);

+}

+

+/**

+ * Set the IP address of an IP socket address from string address, 

+ * with resolving the host if necessary. The string address may be in a

+ * standard numbers and dots notation or may be a hostname. If hostname

+ * is specified, then the function will resolve the host into the IP

+ * address.

+ *

+ * @param addr	    The IP socket address to be set.

+ * @param cp	    The address string, which can be in a standard 

+ *		    dotted numbers or a hostname to be resolved.

+ *

+ * @return	    Zero on success.

+ */

+PJ_DECL(pj_status_t) pj_sockaddr_in_set_str_addr( pj_sockaddr_in *addr,

+					          const pj_str_t *cp);

+

+/**

+ * Set the IP address and port of an IP socket address.

+ * The string address may be in a standard numbers and dots notation or 

+ * may be a hostname. If hostname is specified, then the function will 

+ * resolve the host into the IP address.

+ *

+ * @param addr	    The IP socket address to be set.

+ * @param cp	    The address string, which can be in a standard 

+ *		    dotted numbers or a hostname to be resolved.

+ * @param port	    The port number, in host byte order.

+ *

+ * @return	    Zero on success.

+ */

+PJ_DECL(pj_status_t) pj_sockaddr_in_init( pj_sockaddr_in *addr,

+				          const pj_str_t *cp,

+					  pj_uint16_t port);

+

+

+/*****************************************************************************

+ *

+ * HOST NAME AND ADDRESS.

+ *

+ *****************************************************************************

+ */

+

+/**

+ * Get system's host name.

+ *

+ * @return	    The hostname, or empty string if the hostname can not

+ *		    be identified.

+ */

+PJ_DECL(const pj_str_t*) pj_gethostname(void);

+

+/**

+ * Get host's IP address, which the the first IP address that is resolved

+ * from the hostname.

+ *

+ * @return	    The host's IP address, PJ_INADDR_NONE if the host

+ *		    IP address can not be identified.

+ */

+PJ_DECL(pj_in_addr) pj_gethostaddr(void);

+

+

+/*****************************************************************************

+ *

+ * SOCKET API.

+ *

+ *****************************************************************************

+ */

+

+/**

+ * Create new socket/endpoint for communication.

+ *

+ * @param family    Specifies a communication domain; this selects the

+ *		    protocol family which will be used for communication.

+ * @param type	    The socket has the indicated type, which specifies the 

+ *		    communication semantics.

+ * @param protocol  Specifies  a  particular  protocol  to  be used with the

+ *		    socket.  Normally only a single protocol exists to support 

+ *		    a particular socket  type  within  a given protocol family, 

+ *		    in which a case protocol can be specified as 0.

+ * @param sock	    New socket descriptor, or PJ_INVALID_SOCKET on error.

+ *

+ * @return	    Zero on success.

+ */

+PJ_DECL(pj_status_t) pj_sock_socket(int family, 

+				    int type, 

+				    int protocol,

+				    pj_sock_t *sock);

+

+/**

+ * Close the socket descriptor.

+ *

+ * @param sockfd    The socket descriptor.

+ *

+ * @return	    Zero on success.

+ */

+PJ_DECL(pj_status_t) pj_sock_close(pj_sock_t sockfd);

+

+

+/**

+ * This function gives the socket sockfd the local address my_addr. my_addr is

+ * addrlen bytes long.  Traditionally, this is called assigning a name to

+ * a socket. When a socket is created with #pj_sock_socket(), it exists in a

+ * name space (address family) but has no name assigned.

+ *

+ * @param sockfd    The socket desriptor.

+ * @param my_addr   The local address to bind the socket to.

+ * @param addrlen   The length of the address.

+ *

+ * @return	    Zero on success.

+ */

+PJ_DECL(pj_status_t) pj_sock_bind( pj_sock_t sockfd, 

+				   const pj_sockaddr_t *my_addr,

+				   int addrlen);

+

+/**

+ * Bind the IP socket sockfd to the given address and port.

+ *

+ * @param sockfd    The socket descriptor.

+ * @param addr	    Local address to bind the socket to, in host byte order.

+ * @param port	    The local port to bind the socket to, in host byte order.

+ *

+ * @return	    Zero on success.

+ */

+PJ_DECL(pj_status_t) pj_sock_bind_in( pj_sock_t sockfd, 

+				      pj_uint32_t addr,

+				      pj_uint16_t port);

+

+#if PJ_HAS_TCP

+/**

+ * Listen for incoming connection. This function only applies to connection

+ * oriented sockets (such as PJ_SOCK_STREAM or PJ_SOCK_SEQPACKET), and it

+ * indicates the willingness to accept incoming connections.

+ *

+ * @param sockfd	The socket descriptor.

+ * @param backlog	Defines the maximum length the queue of pending

+ *			connections may grow to.

+ *

+ * @return		Zero on success.

+ */

+PJ_DECL(pj_status_t) pj_sock_listen( pj_sock_t sockfd, 

+				     int backlog );

+

+/**

+ * Accept new connection on the specified connection oriented server socket.

+ *

+ * @param serverfd  The server socket.

+ * @param newsock   New socket on success, of PJ_INVALID_SOCKET if failed.

+ * @param addr	    A pointer to sockaddr type. If the argument is not NULL,

+ *		    it will be filled by the address of connecting entity.

+ * @param addrlen   Initially specifies the length of the address, and upon

+ *		    return will be filled with the exact address length.

+ *

+ * @return	    Zero on success, or the error number.

+ */

+PJ_DECL(pj_status_t) pj_sock_accept( pj_sock_t serverfd,

+				     pj_sock_t *newsock,

+				     pj_sockaddr_t *addr,

+				     int *addrlen);

+#endif

+

+/**

+ * The file descriptor sockfd must refer to a socket.  If the socket is of

+ * type PJ_SOCK_DGRAM  then the serv_addr address is the address to which

+ * datagrams are sent by default, and the only address from which datagrams

+ * are received. If the socket is of type PJ_SOCK_STREAM or PJ_SOCK_SEQPACKET,

+ * this call attempts to make a connection to another socket.  The

+ * other socket is specified by serv_addr, which is an address (of length

+ * addrlen) in the communications space of the  socket.  Each  communications

+ * space interprets the serv_addr parameter in its own way.

+ *

+ * @param sockfd	The socket descriptor.

+ * @param serv_addr	Server address to connect to.

+ * @param addrlen	The length of server address.

+ *

+ * @return		Zero on success.

+ */

+PJ_DECL(pj_status_t) pj_sock_connect( pj_sock_t sockfd,

+				      const pj_sockaddr_t *serv_addr,

+				      int addrlen);

+

+/**

+ * Return the address of peer which is connected to socket sockfd.

+ *

+ * @param sockfd	The socket descriptor.

+ * @param addr		Pointer to sockaddr structure to which the address

+ *			will be returned.

+ * @param namelen	Initially the length of the addr. Upon return the value

+ *			will be set to the actual length of the address.

+ *

+ * @return		Zero on success.

+ */

+PJ_DECL(pj_status_t) pj_sock_getpeername(pj_sock_t sockfd,

+					  pj_sockaddr_t *addr,

+					  int *namelen);

+

+/**

+ * Return the current name of the specified socket.

+ *

+ * @param sockfd	The socket descriptor.

+ * @param addr		Pointer to sockaddr structure to which the address

+ *			will be returned.

+ * @param namelen	Initially the length of the addr. Upon return the value

+ *			will be set to the actual length of the address.

+ *

+ * @return		Zero on success.

+ */

+PJ_DECL(pj_status_t) pj_sock_getsockname( pj_sock_t sockfd,

+					  pj_sockaddr_t *addr,

+					  int *namelen);

+

+/**

+ * Get socket option associated with a socket. Options may exist at multiple

+ * protocol levels; they are always present at the uppermost socket level.

+ *

+ * @param sockfd	The socket descriptor.

+ * @param level		The level which to get the option from.

+ * @param optname	The option name, which will be passed uninterpreted

+ *			by the library.

+ * @param optval	Identifies the buffer which the value will be

+ *			returned.

+ * @param optlen	Initially contains the length of the buffer, upon

+ *			return will be set to the actual size of the value.

+ *

+ * @return		Zero on success.

+ */

+PJ_DECL(pj_status_t) pj_sock_getsockopt( pj_sock_t sockfd,

+					 int level,

+					 int optname,

+					 void *optval,

+					 int *optlen);

+/**

+ * Manipulate the options associated with a socket. Options may exist at 

+ * multiple protocol levels; they are always present at the uppermost socket 

+ * level.

+ *

+ * @param sockfd	The socket descriptor.

+ * @param level		The level which to get the option from.

+ * @param optname	The option name, which will be passed uninterpreted

+ *			by the library.

+ * @param optval	Identifies the buffer which contain the value.

+ * @param optlen	The length of the value.

+ *

+ * @return		PJ_SUCCESS or the status code.

+ */

+PJ_DECL(pj_status_t) pj_sock_setsockopt( pj_sock_t sockfd,

+					 int level,

+					 int optname,

+					 const void *optval,

+					 int optlen);

+

+

+/**

+ * Receives data stream or message coming to the specified socket.

+ *

+ * @param sockfd	The socket descriptor.

+ * @param buf		The buffer to receive the data or message.

+ * @param len		On input, the length of the buffer. On return,

+ *			contains the length of data received.

+ * @param flags		Combination of #pj_sock_msg_flag.

+ *

+ * @return		PJ_SUCCESS or the error code.

+ */

+PJ_DECL(pj_status_t) pj_sock_recv(pj_sock_t sockfd,

+				  void *buf,

+				  pj_ssize_t *len,

+				  unsigned flags);

+

+/**

+ * Receives data stream or message coming to the specified socket.

+ *

+ * @param sockfd	The socket descriptor.

+ * @param buf		The buffer to receive the data or message.

+ * @param len		On input, the length of the buffer. On return,

+ *			contains the length of data received.

+ * @param flags		Bitmask combination of #pj_sock_msg_flag.

+ * @param from		If not NULL, it will be filled with the source

+ *			address of the connection.

+ * @param fromlen	Initially contains the length of from address,

+ *			and upon return will be filled with the actual

+ *			length of the address.

+ *

+ * @return		PJ_SUCCESS or the error code.

+ */

+PJ_DECL(pj_status_t) pj_sock_recvfrom( pj_sock_t sockfd,

+				      void *buf,

+				      pj_ssize_t *len,

+				      unsigned flags,

+				      pj_sockaddr_t *from,

+				      int *fromlen);

+

+/**

+ * Transmit data to the socket.

+ *

+ * @param sockfd	Socket descriptor.

+ * @param buf		Buffer containing data to be sent.

+ * @param len		On input, the length of the data in the buffer.

+ *			Upon return, it will be filled with the length

+ *			of data sent.

+ * @param flags		Bitmask combination of #pj_sock_msg_flag.

+ *

+ * @return		PJ_SUCCESS or the status code.

+ */

+PJ_DECL(pj_status_t) pj_sock_send(pj_sock_t sockfd,

+				  const void *buf,

+				  pj_ssize_t *len,

+				  unsigned flags);

+

+/**

+ * Transmit data to the socket to the specified address.

+ *

+ * @param sockfd	Socket descriptor.

+ * @param buf		Buffer containing data to be sent.

+ * @param len		On input, the length of the data in the buffer.

+ *			Upon return, it will be filled with the length

+ *			of data sent.

+ * @param flags		Bitmask combination of #pj_sock_msg_flag.

+ * @param to		The address to send.

+ * @param tolen		The length of the address in bytes.

+ *

+ * @return		The length of data successfully sent.

+ */

+PJ_DECL(pj_status_t) pj_sock_sendto(pj_sock_t sockfd,

+				    const void *buf,

+				    pj_ssize_t *len,

+				    unsigned flags,

+				    const pj_sockaddr_t *to,

+				    int tolen);

+

+#if PJ_HAS_TCP

+/**

+ * The shutdown call causes all or part of a full-duplex connection on the

+ * socket associated with sockfd to be shut down.

+ *

+ * @param sockfd	The socket descriptor.

+ * @param how		If how is PJ_SHUT_RD, further receptions will be 

+ *			disallowed. If how is PJ_SHUT_WR, further transmissions

+ *			will be disallowed. If how is PJ_SHUT_RDWR, further 

+ *			receptions andtransmissions will be disallowed.

+ *

+ * @return		Zero on success.

+ */

+PJ_DECL(pj_status_t) pj_sock_shutdown( pj_sock_t sockfd,

+				       int how);

+#endif

+

+/**

+ * @}

+ */

+

+

+PJ_END_DECL

+

+#endif	/* __PJ_SOCK_H__ */

+

diff --git a/pjlib/include/pj/sock_select.h b/pjlib/include/pj/sock_select.h
new file mode 100644
index 0000000..c54b31c
--- /dev/null
+++ b/pjlib/include/pj/sock_select.h
@@ -0,0 +1,141 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/sock_select.h 3     10/14/05 12:26a Bennylp $ */

+/* $Log: /pjproject-0.3/pjlib/include/pj/sock_select.h $

+ * 

+ * 3     10/14/05 12:26a Bennylp

+ * Finished error code framework, some fixes in ioqueue, etc. Pretty

+ * major.

+ * 

+ * 2     9/21/05 1:39p Bennylp

+ * Periodic checkin for backup.

+ * 

+ * 1     9/15/05 8:40p Bennylp

+ * Created.

+ */

+#ifndef __PJ_SELECT_H__

+#define __PJ_SELECT_H__

+

+/**

+ * @file sock_select.h

+ * @brief Socket select().

+ */

+

+#include <pj/types.h>

+

+PJ_BEGIN_DECL 

+

+/**

+ * @defgroup PJ_SOCK_SELECT Socket select() API.

+ * @ingroup PJ_IO

+ * @{

+ * This module provides portable abstraction for \a select() like API.

+ * The abstraction is needed so that it can utilize various event

+ * dispatching mechanisms that are available across platforms.

+ *

+ * The API is very similar to normal \a select() usage. 

+ *

+ * \section pj_sock_select_examples_sec Examples

+ *

+ * For some examples on how to use the select API, please see:

+ *

+ *  - \ref page_pjlib_select_test

+ */

+

+/**

+ * Portable structure declarations for pj_fd_set.

+ * The implementation of pj_sock_select() does not use this structure 

+ * per-se, but instead it will use the native fd_set structure. However,

+ * we must make sure that the size of pj_fd_set_t can accomodate the

+ * native fd_set structure.

+ */

+typedef struct pj_fd_set_t

+{

+    pj_sock_t	data[FD_SETSIZE + 4];   /**< Opaque buffer for fd_set */

+} pj_fd_set_t;

+

+

+/**

+ * Initialize the descriptor set pointed to by fdsetp to the null set.

+ *

+ * @param fdsetp    The descriptor set.

+ */

+PJ_DECL(void) PJ_FD_ZERO(pj_fd_set_t *fdsetp);

+

+

+/**

+ * Add the file descriptor fd to the set pointed to by fdsetp. 

+ * If the file descriptor fd is already in this set, there shall be no effect

+ * on the set, nor will an error be returned.

+ *

+ * @param fd	    The socket descriptor.

+ * @param fdsetp    The descriptor set.

+ */

+PJ_DECL(void) PJ_FD_SET(pj_sock_t fd, pj_fd_set_t *fdsetp);

+

+/**

+ * Remove the file descriptor fd from the set pointed to by fdsetp. 

+ * If fd is not a member of this set, there shall be no effect on the set, 

+ * nor will an error be returned.

+ *

+ * @param fd	    The socket descriptor.

+ * @param fdsetp    The descriptor set.

+ */

+PJ_DECL(void) PJ_FD_CLR(pj_sock_t fd, pj_fd_set_t *fdsetp);

+

+

+/**

+ * Evaluate to non-zero if the file descriptor fd is a member of the set 

+ * pointed to by fdsetp, and shall evaluate to zero otherwise.

+ *

+ * @param fd	    The socket descriptor.

+ * @param fdsetp    The descriptor set.

+ *

+ * @return	    Nonzero if fd is member of the descriptor set.

+ */

+PJ_DECL(pj_bool_t) PJ_FD_ISSET(pj_sock_t fd, const pj_fd_set_t *fdsetp);

+

+

+/**

+ * Get the number of descriptors in the set.

+ *

+ * @param fdsetp    The descriptor set.

+ *

+ * @return          Number of descriptors in the set.

+ */

+PJ_DECL(pj_size_t) PJ_FD_COUNT(const pj_fd_set_t *fdsetp);

+

+

+/**

+ * This function wait for a number of file  descriptors to change status.

+ * The behaviour is the same as select() function call which appear in

+ * standard BSD socket libraries.

+ *

+ * @param n	    On Unices, this specifies the highest-numbered

+ *		    descriptor in any of the three set, plus 1. On Windows,

+ *		    the value is ignored.

+ * @param readfds   Optional pointer to a set of sockets to be checked for 

+ *		    readability.

+ * @param writefds  Optional pointer to a set of sockets to be checked for 

+ *		    writability.

+ * @param exceptfds Optional pointer to a set of sockets to be checked for 

+ *		    errors.

+ * @param timeout   Maximum time for select to wait, or null for blocking 

+ *		    operations.

+ *

+ * @return	    The total number of socket handles that are ready, or

+ *		    zero if the time limit expired, or -1 if an error occurred.

+ */

+PJ_DECL(int) pj_sock_select( int n, 

+			     pj_fd_set_t *readfds, 

+			     pj_fd_set_t *writefds,

+			     pj_fd_set_t *exceptfds, 

+			     const pj_time_val *timeout);

+

+

+/**

+ * @}

+ */

+

+

+PJ_END_DECL

+

+#endif	/* __PJ_SELECT_H__ */

diff --git a/pjlib/include/pj/string.h b/pjlib/include/pj/string.h
new file mode 100644
index 0000000..4562add
--- /dev/null
+++ b/pjlib/include/pj/string.h
@@ -0,0 +1,515 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/string.h 8     10/14/05 12:26a Bennylp $ */

+

+#ifndef __PJ_STRING_H__

+#define __PJ_STRING_H__

+

+/**

+ * @file string.h

+ * @brief PJLIB String Operations.

+ */

+

+#include <pj/types.h>

+#include <pj/compat/string.h>

+

+PJ_BEGIN_DECL

+

+/**

+ * @defgroup PJ_PSTR String Operations

+ * @ingroup PJ_DS

+ * @{

+ * This module provides string manipulation API.

+ *

+ * \section pj_pstr_not_null_sec PJLIB String is NOT Null Terminated!

+ *

+ * That is the first information that developers need to know. Instead

+ * of using normal C string, strings in PJLIB are represented as

+ * pj_str_t structure below:

+ *

+ * <pre>

+ *   typedef struct pj_str_t

+ *   {

+ *       char      *ptr;

+ *       pj_size_t  slen;

+ *   } pj_str_t;

+ * </pre>

+ *

+ * There are some advantages of using this approach:

+ *  - the string can point to arbitrary location in memory even

+ *    if the string in that location is not null terminated. This is

+ *    most usefull for text parsing, where the parsed text can just

+ *    point to the original text in the input. If we use C string,

+ *    then we will have to copy the text portion from the input

+ *    to a string variable.

+ *  - because the length of the string is known, string copy operation

+ *    can be made more efficient.

+ *

+ * Most of APIs in PJLIB that expect or return string will represent

+ * the string as pj_str_t instead of normal C string.

+ *

+ * \section pj_pstr_examples_sec Examples

+ *

+ * For some examples, please see:

+ *  - @ref page_pjlib_string_test

+ */

+

+/**

+ * Create string initializer from a normal C string.

+ *

+ * @param str	Null terminated string to be stored.

+ *

+ * @return	pj_str_t.

+ */

+PJ_IDECL(pj_str_t) pj_str(char *str);

+

+/**

+ * Create constant string from normal C string.

+ *

+ * @param str	The string to be initialized.

+ * @param s	Null terminated string.

+ *

+ * @return	pj_str_t.

+ */

+PJ_INLINE(const pj_str_t*) pj_cstr(pj_str_t *str, const char *s)

+{

+    str->ptr = (char*)s;

+    str->slen = s ? strlen(s) : 0;

+    return str;

+}

+

+/**

+ * Set the pointer and length to the specified value.

+ *

+ * @param str	    the string.

+ * @param ptr	    pointer to set.

+ * @param length    length to set.

+ *

+ * @return the string.

+ */

+PJ_INLINE(pj_str_t*) pj_strset( pj_str_t *str, char *ptr, pj_size_t length)

+{

+    str->ptr = ptr;

+    str->slen = length;

+    return str;

+}

+

+/**

+ * Set the pointer and length of the string to the source string, which

+ * must be NULL terminated.

+ *

+ * @param str	    the string.

+ * @param src	    pointer to set.

+ *

+ * @return the string.

+ */

+PJ_INLINE(pj_str_t*) pj_strset2( pj_str_t *str, char *src)

+{

+    str->ptr = src;

+    str->slen = src ? strlen(src) : 0;

+    return str;

+}

+

+/**

+ * Set the pointer and the length of the string.

+ *

+ * @param str	    The target string.

+ * @param begin	    The start of the string.

+ * @param end	    The end of the string.

+ *

+ * @return the target string.

+ */

+PJ_INLINE(pj_str_t*) pj_strset3( pj_str_t *str, char *begin, char *end )

+{

+    str->ptr = begin;

+    str->slen = end-begin;

+    return str;

+}

+

+/**

+ * Assign string.

+ *

+ * @param dst	    The target string.

+ * @param src	    The source string.

+ *

+ * @return the target string.

+ */

+PJ_IDECL(pj_str_t*) pj_strassign( pj_str_t *dst, pj_str_t *src );

+

+/**

+ * Copy string contents.

+ *

+ * @param dst	    The target string.

+ * @param src	    The source string.

+ *

+ * @return the target string.

+ */

+PJ_IDECL(pj_str_t*) pj_strcpy(pj_str_t *dst, const pj_str_t *src);

+

+/**

+ * Copy string contents.

+ *

+ * @param dst	    The target string.

+ * @param src	    The source string.

+ *

+ * @return the target string.

+ */

+PJ_IDECL(pj_str_t*) pj_strcpy2(pj_str_t *dst, const char *src);

+

+/**

+ * Duplicate string.

+ *

+ * @param pool	    The pool.

+ * @param dst	    The string result.

+ * @param src	    The string to duplicate.

+ *

+ * @return the string result.

+ */

+PJ_IDECL(pj_str_t*) pj_strdup(pj_pool_t *pool,

+			      pj_str_t *dst,

+			      const pj_str_t *src);

+

+/**

+ * Duplicate string and NULL terminate the destination string.

+ *

+ * @param pool

+ * @param dst

+ * @param src

+ */

+PJ_IDECL(pj_str_t*) pj_strdup_with_null(pj_pool_t *pool,

+					pj_str_t *dst,

+					const pj_str_t *src);

+

+/**

+ * Duplicate string.

+ *

+ * @param pool	    The pool.

+ * @param dst	    The string result.

+ * @param src	    The string to duplicate.

+ *

+ * @return the string result.

+ */

+PJ_IDECL(pj_str_t*) pj_strdup2(pj_pool_t *pool,

+			       pj_str_t *dst,

+			       const char *src);

+

+/**

+ * Duplicate string.

+ *

+ * @param pool	    The pool.

+ * @param src	    The string to duplicate.

+ *

+ * @return the string result.

+ */

+PJ_IDECL(pj_str_t) pj_strdup3(pj_pool_t *pool, const char *src);

+

+/**

+ * Return the length of the string.

+ *

+ * @param str	    The string.

+ *

+ * @return the length of the string.

+ */

+PJ_INLINE(pj_size_t) pj_strlen( const pj_str_t *str )

+{

+    return str->slen;

+}

+

+/**

+ * Return the pointer to the string data.

+ *

+ * @param str	    The string.

+ *

+ * @return the pointer to the string buffer.

+ */

+PJ_INLINE(const char*) pj_strbuf( const pj_str_t *str )

+{

+    return str->ptr;

+}

+

+/**

+ * Compare strings. 

+ *

+ * @param str1	    The string to compare.

+ * @param str2	    The string to compare.

+ *

+ * @return 

+ *	- < 0 if str1 is less than str2

+ *      - 0   if str1 is identical to str2

+ *      - > 0 if str1 is greater than str2

+ */

+PJ_IDECL(int) pj_strcmp( const pj_str_t *str1, const pj_str_t *str2);

+

+/**

+ * Compare strings.

+ *

+ * @param str1	    The string to compare.

+ * @param str2	    The string to compare.

+ *

+ * @return 

+ *	- < 0 if str1 is less than str2

+ *      - 0   if str1 is identical to str2

+ *      - > 0 if str1 is greater than str2

+ */

+PJ_IDECL(int) pj_strcmp2( const pj_str_t *str1, const char *str2 );

+

+/**

+ * Compare strings. 

+ *

+ * @param str1	    The string to compare.

+ * @param str2	    The string to compare.

+ * @param len	    The maximum number of characters to compare.

+ *

+ * @return 

+ *	- < 0 if str1 is less than str2

+ *      - 0   if str1 is identical to str2

+ *      - > 0 if str1 is greater than str2

+ */

+PJ_IDECL(int) pj_strncmp( const pj_str_t *str1, const pj_str_t *str2, 

+			  pj_size_t len);

+

+/**

+ * Compare strings. 

+ *

+ * @param str1	    The string to compare.

+ * @param str2	    The string to compare.

+ * @param len	    The maximum number of characters to compare.

+ *

+ * @return 

+ *	- < 0 if str1 is less than str2

+ *      - 0   if str1 is identical to str2

+ *      - > 0 if str1 is greater than str2

+ */

+PJ_IDECL(int) pj_strncmp2( const pj_str_t *str1, const char *str2, 

+			   pj_size_t len);

+

+/**

+ * Perform lowercase comparison to the strings.

+ *

+ * @param str1	    The string to compare.

+ * @param str2	    The string to compare.

+ *

+ * @return 

+ *	- < 0 if str1 is less than str2

+ *      - 0   if str1 is identical to str2

+ *      - > 0 if str1 is greater than str2

+ */

+PJ_IDECL(int) pj_stricmp( const pj_str_t *str1, const pj_str_t *str2);

+

+/**

+ * Perform lowercase comparison to the strings.

+ *

+ * @param str1	    The string to compare.

+ * @param str2	    The string to compare.

+ *

+ * @return 

+ *	- < 0 if str1 is less than str2

+ *      - 0   if str1 is identical to str2

+ *      - > 0 if str1 is greater than str2

+ */

+PJ_IDECL(int) pj_stricmp2( const pj_str_t *str1, const char *str2);

+

+/**

+ * Perform lowercase comparison to the strings.

+ *

+ * @param str1	    The string to compare.

+ * @param str2	    The string to compare.

+ * @param len	    The maximum number of characters to compare.

+ *

+ * @return 

+ *	- < 0 if str1 is less than str2

+ *      - 0   if str1 is identical to str2

+ *      - > 0 if str1 is greater than str2

+ */

+PJ_IDECL(int) pj_strnicmp( const pj_str_t *str1, const pj_str_t *str2, 

+			   pj_size_t len);

+

+/**

+ * Perform lowercase comparison to the strings.

+ *

+ * @param str1	    The string to compare.

+ * @param str2	    The string to compare.

+ * @param len	    The maximum number of characters to compare.

+ *

+ * @return 

+ *	- < 0 if str1 is less than str2

+ *      - 0   if str1 is identical to str2

+ *      - > 0 if str1 is greater than str2

+ */

+PJ_IDECL(int) pj_strnicmp2( const pj_str_t *str1, const char *str2, 

+			    pj_size_t len);

+

+/**

+ * Concatenate strings.

+ *

+ * @param dst	    The destination string.

+ * @param src	    The source string.

+ */

+PJ_IDECL(void) pj_strcat(pj_str_t *dst, const pj_str_t *src);

+

+/**

+ * Finds a character in a string.

+ *

+ * @param str	    The string.

+ * @param chr	    The character to find.

+ *

+ * @return the pointer to first character found, or NULL.

+ */

+PJ_INLINE(char*) pj_strchr( pj_str_t *str, int chr)

+{

+    return (char*) memchr(str->ptr, chr, str->slen);

+}

+

+/**

+ * Remove (trim) leading whitespaces from the string.

+ *

+ * @param str	    The string.

+ *

+ * @return the string.

+ */

+PJ_DECL(pj_str_t*) pj_strltrim( pj_str_t *str );

+

+/**

+ * Remove (trim) the trailing whitespaces from the string.

+ *

+ * @param str	    The string.

+ *

+ * @return the string.

+ */

+PJ_DECL(pj_str_t*) pj_strrtrim( pj_str_t *str );

+

+/**

+ * Remove (trim) leading and trailing whitespaces from the string.

+ *

+ * @param str	    The string.

+ *

+ * @return the string.

+ */

+PJ_IDECL(pj_str_t*) pj_strtrim( pj_str_t *str );

+

+/**

+ * Initialize the buffer with some random string.

+ *

+ * @param str	    the string to store the result.

+ * @param length    the length of the random string to generate.

+ *

+ * @return the string.

+ */

+PJ_DECL(char*) pj_create_random_string(char *str, pj_size_t length);

+

+/**

+ * Convert string to unsigned integer.

+ *

+ * @param str	the string.

+ *

+ * @return the unsigned integer.

+ */

+PJ_DECL(unsigned long) pj_strtoul(const pj_str_t *str);

+

+/**

+ * Utility to convert unsigned integer to string. Note that the

+ * string will be NULL terminated.

+ *

+ * @param val	    the unsigned integer value.

+ * @param buf	    the buffer

+ *

+ * @return the number of characters written

+ */

+PJ_DECL(int) pj_utoa(unsigned long val, char *buf);

+

+/**

+ * Convert unsigned integer to string with minimum digits. Note that the

+ * string will be NULL terminated.

+ *

+ * @param val	    The unsigned integer value.

+ * @param buf	    The buffer.

+ * @param min_dig   Minimum digits to be printed, or zero to specify no

+ *		    minimum digit.

+ * @param pad	    The padding character to be put in front of the string

+ *		    when the digits is less than minimum.

+ *

+ * @return the number of characters written.

+ */

+PJ_DECL(int) pj_utoa_pad( unsigned long val, char *buf, int min_dig, int pad);

+

+/**

+ * Fill the memory location with value.

+ *

+ * @param dst	    The destination buffer.

+ * @param c	    Character to set.

+ * @param size	    The number of characters.

+ *

+ * @return the value of dst.

+ */

+PJ_INLINE(void*) pj_memset(void *dst, int c, pj_size_t size)

+{

+    return memset(dst, c, size);

+}

+

+/**

+ * Copy buffer.

+ *

+ * @param dst	    The destination buffer.

+ * @param src	    The source buffer.

+ * @param size	    The size to copy.

+ *

+ * @return the destination buffer.

+ */

+PJ_INLINE(void*) pj_memcpy(void *dst, const void *src, pj_size_t size)

+{

+    return memcpy(dst, src, size);

+}

+

+/**

+ * Move memory.

+ *

+ * @param dst	    The destination buffer.

+ * @param src	    The source buffer.

+ * @param size	    The size to copy.

+ *

+ * @return the destination buffer.

+ */

+PJ_INLINE(void*) pj_memmove(void *dst, const void *src, pj_size_t size)

+{

+    return memmove(dst, src, size);

+}

+

+/**

+ * Compare buffers.

+ *

+ * @param buf1	    The first buffer.

+ * @param buf2	    The second buffer.

+ * @param size	    The size to compare.

+ *

+ * @return negative, zero, or positive value.

+ */

+PJ_INLINE(int) pj_memcmp(const void *buf1, const void *buf2, pj_size_t size)

+{

+    return memcmp(buf1, buf2, size);

+}

+

+/**

+ * Find character in the buffer.

+ *

+ * @param buf	    The buffer.

+ * @param c	    The character to find.

+ * @param size	    The size to check.

+ *

+ * @return the pointer to location where the character is found, or NULL if

+ *         not found.

+ */

+PJ_INLINE(void*) pj_memchr(const void *buf, int c, pj_size_t size)

+{

+    return memchr(buf, c, size);

+}

+

+/**

+ * @}

+ */

+

+#if PJ_FUNCTIONS_ARE_INLINED

+#  include <pj/string_i.h>

+#endif

+

+PJ_END_DECL

+

+#endif	/* __PJ_STRING_H__ */

+

diff --git a/pjlib/include/pj/string_i.h b/pjlib/include/pj/string_i.h
new file mode 100644
index 0000000..0c60623
--- /dev/null
+++ b/pjlib/include/pj/string_i.h
@@ -0,0 +1,162 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/string_i.h 8     10/14/05 12:26a Bennylp $ */

+

+PJ_IDEF(pj_str_t) pj_str(char *str)

+{

+    pj_str_t dst;

+    dst.ptr = str;

+    dst.slen = str ? strlen(str) : 0;

+    return dst;

+}

+

+PJ_IDEF(pj_str_t*) pj_strdup(pj_pool_t *pool,

+			      pj_str_t *dst,

+			      const pj_str_t *src)

+{

+    if (src->slen) {

+	dst->ptr = (char*)pj_pool_alloc(pool, src->slen);

+	pj_memcpy(dst->ptr, src->ptr, src->slen);

+    }

+    dst->slen = src->slen;

+    return dst;

+}

+

+PJ_IDEF(pj_str_t*) pj_strdup_with_null( pj_pool_t *pool,

+					pj_str_t *dst,

+					const pj_str_t *src)

+{

+    if (src->slen) {

+	dst->ptr = (char*)pj_pool_alloc(pool, src->slen+1);

+	pj_memcpy(dst->ptr, src->ptr, src->slen);

+    } else {

+	dst->ptr = (char*)pj_pool_alloc(pool, 1);

+    }

+    dst->slen = src->slen;

+    dst->ptr[dst->slen] = '\0';

+    return dst;

+}

+

+PJ_IDEF(pj_str_t*) pj_strdup2(pj_pool_t *pool,

+			      pj_str_t *dst,

+			      const char *src)

+{

+    dst->slen = src ? strlen(src) : 0;

+    if (dst->slen) {

+	dst->ptr = (char*)pj_pool_alloc(pool, dst->slen);

+	pj_memcpy(dst->ptr, src, dst->slen);

+    } else {

+	dst->ptr = NULL;

+    }

+    return dst;

+}

+

+

+PJ_IDEF(pj_str_t) pj_strdup3(pj_pool_t *pool, const char *src)

+{

+    pj_str_t temp;

+    pj_strdup2(pool, &temp, src);

+    return temp;

+}

+

+PJ_IDEF(pj_str_t*) pj_strassign( pj_str_t *dst, pj_str_t *src )

+{

+    dst->ptr = src->ptr;

+    dst->slen = src->slen;

+    return dst;

+}

+

+PJ_IDEF(pj_str_t*) pj_strcpy(pj_str_t *dst, const pj_str_t *src)

+{

+    dst->slen = src->slen;

+    if (src->slen > 0)

+	pj_memcpy(dst->ptr, src->ptr, src->slen);

+    return dst;

+}

+

+PJ_IDEF(pj_str_t*) pj_strcpy2(pj_str_t *dst, const char *src)

+{

+    dst->slen = src ? strlen(src) : 0;

+    if (dst->slen > 0)

+	pj_memcpy(dst->ptr, src, dst->slen);

+    return dst;

+}

+

+PJ_IDEF(int) pj_strcmp( const pj_str_t *str1, const pj_str_t *str2)

+{

+    pj_ssize_t diff;

+

+    diff = str1->slen - str2->slen;

+    if (diff) {

+	return (int)diff;

+    } else if (str1->ptr) {

+	return strncmp(str1->ptr, str2->ptr, str1->slen);

+    } else {

+	return 0;

+    }

+}

+

+PJ_IDEF(int) pj_strncmp( const pj_str_t *str1, const pj_str_t *str2, 

+			 pj_size_t len)

+{

+    return (str1->ptr && str2->ptr) ? strncmp(str1->ptr, str2->ptr, len) :

+	   (str1->ptr == str2->ptr ? 0 : 1);

+}

+

+PJ_IDEF(int) pj_strncmp2( const pj_str_t *str1, const char *str2, 

+			  pj_size_t len)

+{

+    return (str1->ptr && str2) ? strncmp(str1->ptr, str2, len) :

+	   (str1->ptr==str2 ? 0 : 1);

+}

+

+PJ_IDEF(int) pj_strcmp2( const pj_str_t *str1, const char *str2 )

+{

+    return pj_strncmp2( str1, str2, str1->slen);

+}

+

+PJ_IDEF(int) pj_stricmp( const pj_str_t *str1, const pj_str_t *str2)

+{

+    pj_ssize_t diff;

+

+    diff = str1->slen - str2->slen;

+    if (diff) {

+	return (int)diff;

+    } else {

+	return strnicmp(str1->ptr, str2->ptr, str1->slen);

+    }

+}

+

+PJ_IDEF(int) pj_stricmp2( const pj_str_t *str1, const char *str2)

+{

+    return (str1->ptr && str2) ? strnicmp(str1->ptr, str2, str1->slen) :

+	   (str1->ptr==str2 ? 0 : 1);

+}

+

+PJ_IDEF(int) pj_strnicmp( const pj_str_t *str1, const pj_str_t *str2, 

+			  pj_size_t len)

+{

+    return (str1->ptr && str2->ptr) ? strnicmp(str1->ptr, str2->ptr, len) :

+	   (str1->ptr == str2->ptr ? 0 : 1);

+}

+

+PJ_IDEF(int) pj_strnicmp2( const pj_str_t *str1, const char *str2, 

+			   pj_size_t len)

+{

+    return (str1->ptr && str2) ? strnicmp(str1->ptr, str2, len) :

+	   (str1->ptr == str2 ? 0 : 1);

+}

+

+PJ_IDEF(void) pj_strcat(pj_str_t *dst, const pj_str_t *src)

+{

+    if (src->slen) {

+	pj_memcpy(dst->ptr + dst->slen, src->ptr, src->slen);

+	dst->slen += src->slen;

+    }

+}

+

+PJ_IDEF(pj_str_t*) pj_strtrim( pj_str_t *str )

+{

+    pj_strltrim(str);

+    pj_strrtrim(str);

+    return str;

+}

+

diff --git a/pjlib/include/pj/stun.h b/pjlib/include/pj/stun.h
new file mode 100644
index 0000000..999dda4
--- /dev/null
+++ b/pjlib/include/pj/stun.h
@@ -0,0 +1,123 @@
+#ifndef __PJ_STUN_H__

+#define __PJ_STUN_H__

+

+#include <pj/types.h>

+#include <pj/sock.h>

+

+PJ_BEGIN_DECL

+

+#define PJ_STUN_MAX_ATTR    16

+

+typedef enum pj_stun_msg_type

+{

+    PJ_STUN_BINDING_REQUEST		    = 0x0001,

+    PJ_STUN_BINDING_RESPONSE		    = 0x0101,

+    PJ_STUN_BINDING_ERROR_RESPONSE	    = 0x0111,

+    PJ_STUN_SHARED_SECRET_REQUEST	    = 0x0002,

+    PJ_STUN_SHARED_SECRET_RESPONSE	    = 0x0102,

+    PJ_STUN_SHARED_SECRET_ERROR_RESPONSE    = 0x0112

+} pj_stun_msg_type;

+

+typedef enum pj_stun_attr_type

+{

+    PJ_STUN_ATTR_MAPPED_ADDR = 1,

+    PJ_STUN_ATTR_RESPONSE_ADDR,

+    PJ_STUN_ATTR_CHANGE_REQUEST,

+    PJ_STUN_ATTR_SOURCE_ADDR,

+    PJ_STUN_ATTR_CHANGED_ADDR,

+    PJ_STUN_ATTR_USERNAME,

+    PJ_STUN_ATTR_PASSWORD,

+    PJ_STUN_ATTR_MESSAGE_INTEGRITY,

+    PJ_STUN_ATTR_ERROR_CODE,

+    PJ_STUN_ATTR_UNKNOWN_ATTRIBUTES,

+    PJ_STUN_ATTR_REFLECTED_FORM

+} pj_stun_attr_type;

+

+typedef struct pj_stun_msg_hdr

+{

+    pj_uint16_t		type;

+    pj_uint16_t		length;

+    pj_uint32_t		tsx[4];

+} pj_stun_msg_hdr;

+

+typedef struct pj_stun_attr_hdr

+{

+    pj_uint16_t		type;

+    pj_uint16_t		length;

+} pj_stun_attr_hdr;

+

+typedef struct pj_stun_mapped_addr_attr

+{

+    pj_stun_attr_hdr	hdr;

+    pj_uint8_t		ignored;

+    pj_uint8_t		family;

+    pj_uint16_t		port;

+    pj_uint32_t		addr;

+} pj_stun_mapped_addr_attr;

+

+typedef pj_stun_mapped_addr_attr pj_stun_response_addr_attr;

+typedef pj_stun_mapped_addr_attr pj_stun_changed_addr_attr;

+typedef pj_stun_mapped_addr_attr pj_stun_src_addr_attr;

+typedef pj_stun_mapped_addr_attr pj_stun_reflected_form_attr;

+

+typedef struct pj_stun_change_request_attr

+{

+    pj_stun_attr_hdr	hdr;

+    pj_uint32_t		value;

+} pj_stun_change_request_attr;

+

+typedef struct pj_stun_username_attr

+{

+    pj_stun_attr_hdr	hdr;

+    pj_uint32_t		value[1];

+} pj_stun_username_attr;

+

+typedef pj_stun_username_attr pj_stun_password_attr;

+

+typedef struct pj_stun_error_code_attr

+{

+    pj_stun_attr_hdr	hdr;

+    pj_uint16_t		ignored;

+    pj_uint8_t		err_class;

+    pj_uint8_t		number;

+    char		reason[4];

+} pj_stun_error_code_attr;

+

+typedef struct pj_stun_msg

+{

+    pj_stun_msg_hdr    *hdr;

+    int			attr_count;

+    pj_stun_attr_hdr   *attr[PJ_STUN_MAX_ATTR];

+} pj_stun_msg;

+

+/* STUN message API (stun.c). */

+

+PJ_DECL(pj_status_t) pj_stun_create_bind_req( pj_pool_t *pool, 

+					      void **msg, pj_size_t *len,

+					      pj_uint32_t id_hi,

+					      pj_uint32_t id_lo);

+PJ_DECL(pj_status_t) pj_stun_parse_msg( void *buf, pj_size_t len,

+				        pj_stun_msg *msg);

+PJ_DECL(void*) pj_stun_msg_find_attr( pj_stun_msg *msg, pj_stun_attr_type t);

+

+/* STUN simple client API (stun_client.c) */

+enum pj_stun_err_code {

+    PJ_STUN_ERR_MEMORY		= (-2),

+    PJ_STUN_ERR_RESOLVE		= (-3),

+    PJ_STUN_ERR_TRANSPORT	= (-4),

+    PJ_STUN_ERR_INVALID_MSG	= (-5),

+    PJ_STUN_ERR_NO_RESPONSE	= (-6),

+    PJ_STUN_ERR_SYMETRIC	= (-7),

+};

+

+PJ_DECL(pj_status_t) pj_stun_get_mapped_addr( pj_pool_factory *pf,

+					      int sock_cnt, pj_sock_t sock[],

+					      const pj_str_t *srv1, int port1,

+					      const pj_str_t *srv2, int port2,

+					      pj_sockaddr_in mapped_addr[]);

+PJ_DECL(const char*) pj_stun_get_err_msg(pj_status_t status);

+

+PJ_END_DECL

+

+#endif	/* __PJ_STUN_H__ */

+

diff --git a/pjlib/include/pj/timer.h b/pjlib/include/pj/timer.h
new file mode 100644
index 0000000..03e4be3
--- /dev/null
+++ b/pjlib/include/pj/timer.h
@@ -0,0 +1,237 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/timer.h 7     10/14/05 12:26a Bennylp $ */

+/* (C)1993-2003 Douglas C. Schmidt

+ *

+ * This file is originaly from ACE library by Doug Schmidt

+ * ACE(TM), TAO(TM) and CIAO(TM) are copyrighted by Douglas C. Schmidt and his research 

+ * group at Washington University, University of California, Irvine, and Vanderbilt 

+ * University Copyright (c) 1993-2003, all rights reserved.

+ *

+ */

+

+#ifndef __PJ_TIMER_H__

+#define __PJ_TIMER_H__

+

+/**

+ * @file timer.h

+ * @brief Timer Heap

+ */

+

+#include <pj/types.h>

+

+PJ_BEGIN_DECL

+

+/**

+ * @defgroup PJ_TIMER Timer Heap Management.

+ * @ingroup PJ_MISC

+ * @brief

+ * The timer scheduling implementation here is based on ACE library's 

+ * ACE_Timer_Heap, with only little modification to suit our library's style

+ * (I even left most of the comments in the original source).

+ *

+ * To quote the original quote in ACE_Timer_Heap_T class:

+ *

+ *      This implementation uses a heap-based callout queue of

+ *      absolute times.  Therefore, in the average and worst case,

+ *      scheduling, canceling, and expiring timers is O(log N) (where

+ *      N is the total number of timers).  In addition, we can also

+ *      preallocate as many \a ACE_Timer_Nodes as there are slots in

+ *      the heap.  This allows us to completely remove the need for

+ *      dynamic memory allocation, which is important for real-time

+ *      systems.

+ * @{

+ *

+ * \section pj_timer_examples_sec Examples

+ *

+ * For some examples on how to use the timer heap, please see the link below.

+ *

+ *  - \ref page_pjlib_timer_test

+ */

+

+

+/**

+ * The type for internal timer ID.

+ */

+typedef int pj_timer_id_t;

+

+/** 

+ * Forward declaration for pj_timer_entry. 

+ */

+struct pj_timer_entry;

+

+/**

+ * The type of callback function to be called by timer scheduler when a timer

+ * has expired.

+ *

+ * @param timer_heap    The timer heap.

+ * @param entry         Timer entry which timer's has expired.

+ */

+typedef void pj_timer_heap_callback(pj_timer_heap_t *timer_heap,

+				    struct pj_timer_entry *entry);

+

+

+/**

+ * This structure represents an entry to the timer.

+ */

+struct pj_timer_entry

+{

+    /** 

+     * User data to be associated with this entry. 

+     * Applications normally will put the instance of object that

+     * owns the timer entry in this field.

+     */

+    void *user_data;

+

+    /** 

+     * Arbitrary ID assigned by the user/owner of this entry. 

+     * Applications can use this ID to distinguish multiple

+     * timer entries that share the same callback and user_data.

+     */

+    int id;

+

+    /** 

+     * Callback to be called when the timer expires. 

+     */

+    pj_timer_heap_callback *cb;

+

+    /** 

+     * Internal unique timer ID, which is assigned by the timer heap. 

+     * Application should not touch this ID.

+     */

+    pj_timer_id_t _timer_id;

+

+    /** 

+     * The future time when the timer expires, which the value is updated

+     * by timer heap when the timer is scheduled.

+     */

+    pj_time_val _timer_value;

+};

+

+

+/**

+ * Default flag for timer heap, indicates that synchronization will be

+ * used.

+ */

+#define PJ_TIMER_HEAP_SYNCHRONIZE	(0)

+

+/**

+ * Flag to indicate that thread synchronization is NOT needed for the 

+ * timer heap.

+ */

+#define PJ_TIMER_HEAP_NO_SYNCHRONIZE	(1)

+

+/**

+ * Calculate memory size required to create a timer heap.

+ *

+ * @param count     Number of timer entries to be supported.

+ * @return          Memory size requirement in bytes.

+ */

+PJ_DECL(pj_size_t) pj_timer_heap_mem_size(pj_size_t count);

+

+/**

+ * Create a timer heap.

+ *

+ * @param pool      The pool where allocations in the timer heap will be 

+ *                  allocated. The timer heap will dynamicly allocate 

+ *                  more storate from the pool if the number of timer 

+ *                  entries registered is more than the size originally 

+ *                  requested when calling this function.

+ * @param count     The maximum number of timer entries to be supported 

+ *                  initially. If the application registers more entries 

+ *                  during runtime, then the timer heap will resize.

+ * @param flag      Creation flag, currently only PJ_TIMER_HEAP_NO_SYNCHRONIZE

+ *                  is recognized..

+ * @param ht        Pointer to receive the created timer heap.

+ *

+ * @return          PJ_SUCCESS, or the appropriate error code.

+ */

+PJ_DECL(pj_status_t) pj_timer_heap_create( pj_pool_t *pool,

+					   pj_size_t count,

+					   unsigned flag,

+                                           pj_timer_heap_t **ht);

+

+/**

+ * Initialize a timer entry. Application should call this function at least

+ * once before scheduling the entry to the timer heap, to properly initialize

+ * the timer entry.

+ *

+ * @param entry     The timer entry to be initialized.

+ * @param id        Arbitrary ID assigned by the user/owner of this entry.

+ *                  Applications can use this ID to distinguish multiple

+ *                  timer entries that share the same callback and user_data.

+ * @param user_data User data to be associated with this entry. 

+ *                  Applications normally will put the instance of object that

+ *                  owns the timer entry in this field.

+ * @param cb        Callback function to be called when the timer elapses.

+ *

+ * @return          The timer entry itself.

+ */

+PJ_DECL(pj_timer_entry*) pj_timer_entry_init( pj_timer_entry *entry,

+                                              int id,

+                                              void *user_data,

+                                              pj_timer_heap_callback *cb );

+

+/**

+ * Schedule a timer entry which will expire AFTER the specified delay.

+ *

+ * @param ht        The timer heap.

+ * @param entry     The entry to be registered. 

+ * @param delay     The interval to expire.

+ * @return          PJ_SUCCESS, or the appropriate error code.

+ */

+PJ_DECL(pj_status_t) pj_timer_heap_schedule( pj_timer_heap_t *ht,

+					     pj_timer_entry *entry, 

+					     const pj_time_val *delay);

+

+/**

+ * Cancel a previously registered timer.

+ *

+ * @param ht        The timer heap.

+ * @param entry     The entry to be cancelled.

+ * @return          The number of timer cancelled, which should be one if the

+ *                  entry has really been registered, or zero if no timer was

+ *                  cancelled.

+ */

+PJ_DECL(int) pj_timer_heap_cancel( pj_timer_heap_t *ht,

+				   pj_timer_entry *entry);

+

+/**

+ * Get the number of timer entries.

+ *

+ * @param ht        The timer heap.

+ * @return          The number of timer entries.

+ */

+PJ_DECL(pj_size_t) pj_timer_heap_count( pj_timer_heap_t *ht );

+

+/**

+ * Get the earliest time registered in the timer heap. The timer heap

+ * MUST have at least one timer being scheduled (application should use

+ * #pj_timer_heap_count() before calling this function).

+ *

+ * @param ht        The timer heap.

+ * @param timeval   The time deadline of the earliest timer entry.

+ *

+ * @return          PJ_SUCCESS, or PJ_ENOTFOUND if no entry is scheduled.

+ */

+PJ_DECL(pj_status_t) pj_timer_heap_earliest_time( pj_timer_heap_t *ht, 

+					   pj_time_val *timeval);

+

+/**

+ * Poll the timer heap, check for expired timers and call the callback for

+ * each of the expired timers.

+ *

+ * @param ht        The timer heap.

+ * @param next_delay If this parameter is not NULL, it will be filled up with

+ *		     the time delay until the next timer elapsed, or -1 in

+ *		     the sec part if no entry exist.

+ * @return          The number of timers expired.

+ */

+PJ_DECL(int) pj_timer_heap_poll( pj_timer_heap_t *ht, pj_time_val *next_delay);

+

+/**

+ * @}

+ */

+

+PJ_END_DECL

+

+#endif	/* __PJ_TIMER_H__ */

+

diff --git a/pjlib/include/pj/types.h b/pjlib/include/pj/types.h
new file mode 100644
index 0000000..0ad77d7
--- /dev/null
+++ b/pjlib/include/pj/types.h
@@ -0,0 +1,418 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/types.h 11    10/14/05 12:26a Bennylp $ */

+

+#ifndef __PJ_TYPES_H__

+#define __PJ_TYPES_H__

+

+

+/**

+ * @defgroup PJ PJ Library

+ */

+/**

+ * @file types.h

+ * @brief Declaration of basic types and utility.

+ */

+/**

+ * @defgroup PJ_BASIC Basic Data Types and Library Functionality.

+ * @ingroup PJ_DS

+ * @{

+ */

+#include <pj/config.h>

+

+PJ_BEGIN_DECL

+

+///////////////////////////////////////////////////////////////////////////////

+

+/** Unsigned 32bit integer. */

+typedef int		pj_int32_t;

+

+/** Signed 32bit integer. */

+typedef unsigned int	pj_uint32_t;

+

+/** Unsigned 16bit integer. */

+typedef short		pj_int16_t;

+

+/** Signed 16bit integer. */

+typedef unsigned short	pj_uint16_t;

+

+/** Unsigned 8bit integer. */

+typedef signed char	pj_int8_t;

+

+/** Signed 16bit integer. */

+typedef unsigned char	pj_uint8_t;

+

+/** Large unsigned integer. */

+typedef size_t		pj_size_t;

+

+/** Large signed integer. */

+typedef long		pj_ssize_t;

+

+/** Status code. */

+typedef int		pj_status_t;

+

+/** Boolean. */

+typedef int		pj_bool_t;

+

+/** Status is OK. */

+#define PJ_SUCCESS  0

+

+/** True value. */

+#define PJ_TRUE	    1

+

+/** False value. */

+#define PJ_FALSE    0

+

+

+///////////////////////////////////////////////////////////////////////////////

+/*

+ * Data structure types.

+ */

+/**

+ * This type is used as replacement to legacy C string, and used throughout

+ * the library. By convention, the string is NOT null terminated.

+ */

+struct pj_str_t

+{

+    /** Buffer pointer, which is by convention NOT null terminated. */

+    char       *ptr;

+

+    /** The length of the string. */

+    pj_ssize_t  slen;

+};

+

+

+/**

+ * The opaque data type for linked list, which is used as arguments throughout

+ * the linked list operations.

+ */

+typedef void pj_list_type;

+

+/** 

+ * List.

+ */

+typedef struct pj_list pj_list;

+

+/**

+ * Opaque data type for hash tables.

+ */

+typedef struct pj_hash_table_t pj_hash_table_t;

+

+/**

+ * Opaque data type for hash entry (only used internally by hash table).

+ */

+typedef struct pj_hash_entry pj_hash_entry;

+

+/**

+ * Data type for hash search iterator.

+ * This structure should be opaque, however applications need to declare

+ * concrete variable of this type, that's why the declaration is visible here.

+ */

+typedef struct pj_hash_iterator_t

+{

+    pj_uint32_t	     index;     /**< Internal index.     */

+    pj_hash_entry   *entry;     /**< Internal entry.     */

+} pj_hash_iterator_t;

+

+

+/**

+ * Forward declaration for memory pool factory.

+ */

+typedef struct pj_pool_factory pj_pool_factory;

+

+/**

+ * Opaque data type for memory pool.

+ */

+typedef struct pj_pool_t pj_pool_t;

+

+/**

+ * Forward declaration for caching pool, a pool factory implementation.

+ */

+typedef struct pj_caching_pool pj_caching_pool;

+

+/**

+ * This type is used as replacement to legacy C string, and used throughout

+ * the library.

+ */

+typedef struct pj_str_t pj_str_t;

+

+/**

+ * Opaque data type for I/O Queue structure.

+ */

+typedef struct pj_ioqueue_t pj_ioqueue_t;

+

+/**

+ * Opaque data type for key that identifies a handle registered to the

+ * I/O queue framework.

+ */

+typedef struct pj_ioqueue_key_t pj_ioqueue_key_t;

+

+/**

+ * Opaque data to identify timer heap.

+ */

+typedef struct pj_timer_heap_t pj_timer_heap_t;

+

+/**

+ * Forward declaration for timer entry.

+ */

+typedef struct pj_timer_entry pj_timer_entry;

+

+/** 

+ * Opaque data type for atomic operations.

+ */

+typedef struct pj_atomic_t pj_atomic_t;

+

+/**

+ * Value type of an atomic variable.

+ */

+typedef PJ_ATOMIC_VALUE_TYPE pj_atomic_value_t;

+ 

+///////////////////////////////////////////////////////////////////////////////

+

+/** Thread handle. */

+typedef struct pj_thread_t pj_thread_t;

+

+/** Lock object. */

+typedef struct pj_lock_t pj_lock_t;

+

+/** Mutex handle. */

+typedef struct pj_mutex_t pj_mutex_t;

+

+/** Semaphore handle. */

+typedef struct pj_sem_t pj_sem_t;

+

+/** Event object. */

+typedef struct pj_event_t pj_event_t;

+

+/** Unidirectional stream pipe object. */

+typedef struct pj_pipe_t pj_pipe_t;

+

+/** Operating system handle. */

+typedef void *pj_oshandle_t;

+

+/** Socket handle. */

+typedef long pj_sock_t;

+

+/** Generic socket address. */

+typedef void pj_sockaddr_t;

+

+/** Color type. */

+typedef unsigned int pj_color_t;

+

+/** Exception id. */

+typedef int pj_exception_id_t;

+

+///////////////////////////////////////////////////////////////////////////////

+

+/** Utility macro to compute the number of elements in static array. */

+#define PJ_ARRAY_SIZE(a)    (sizeof(a)/sizeof(a[0]))

+

+/** Maximum value for signed 32-bit integer. */

+#define PJ_MAXINT32  0x7FFFFFFFL

+

+/**

+ * Length of object names.

+ */

+#define PJ_MAX_OBJ_NAME	16

+

+///////////////////////////////////////////////////////////////////////////////

+/*

+ * General.

+ */

+/**

+ * Initialize the PJ Library.

+ * This function must be called before using the library. The purpose of this

+ * function is to initialize static library data, such as character table used

+ * in random string generation, and to initialize operating system dependent

+ * functionality (such as WSAStartup() in Windows).

+ */

+PJ_DECL(pj_status_t) pj_init(void);

+

+

+/**

+ * @}

+ */

+/**

+ * @addtogroup PJ_TIME Time Data Type and Manipulation.

+ * @ingroup PJ_MISC

+ * @{

+ */

+

+/**

+ * Representation of time value in this library.

+ * This type can be used to represent either an interval or a specific time

+ * or date. 

+ */

+typedef struct pj_time_val

+{

+    /** The seconds part of the time. */

+    long    sec;

+

+    /** The miliseconds fraction of the time. */

+    long    msec;

+

+} pj_time_val;

+

+/**

+ * Normalize the value in time value.

+ * @param t     Time value to be normalized.

+ */

+PJ_DECL(void) pj_time_val_normalize(pj_time_val *t);

+

+/**

+ * Get the total time value in miliseconds. This is the same as

+ * multiplying the second part with 1000 and then add the miliseconds

+ * part to the result.

+ *

+ * @param t     The time value.

+ * @return      Total time in miliseconds.

+ * @hideinitializer

+ */

+#define PJ_TIME_VAL_MSEC(t)	((t).sec * 1000 + (t).msec)

+

+/**

+ * This macro will check if \a t1 is equal to \a t2.

+ *

+ * @param t1    The first time value to compare.

+ * @param t2    The second time value to compare.

+ * @return      Non-zero if both time values are equal.

+ * @hideinitializer

+ */

+#define PJ_TIME_VAL_EQ(t1, t2)	((t1).sec==(t2).sec && (t1).msec==(t2).msec)

+

+/**

+ * This macro will check if \a t1 is greater than \a t2

+ *

+ * @param t1    The first time value to compare.

+ * @param t2    The second time value to compare.

+ * @return      Non-zero if t1 is greater than t2.

+ * @hideinitializer

+ */

+#define PJ_TIME_VAL_GT(t1, t2)	((t1).sec>(t2).sec || \

+                                ((t1).sec==(t2).sec && (t1).msec>(t2).msec))

+

+/**

+ * This macro will check if \a t1 is greater than or equal to \a t2

+ *

+ * @param t1    The first time value to compare.

+ * @param t2    The second time value to compare.

+ * @return      Non-zero if t1 is greater than or equal to t2.

+ * @hideinitializer

+ */

+#define PJ_TIME_VAL_GTE(t1, t2)	(PJ_TIME_VAL_GT(t1,t2) || \

+                                 PJ_TIME_VAL_EQ(t1,t2))

+

+/**

+ * This macro will check if \a t1 is less than \a t2

+ *

+ * @param t1    The first time value to compare.

+ * @param t2    The second time value to compare.

+ * @return      Non-zero if t1 is less than t2.

+ * @hideinitializer

+ */

+#define PJ_TIME_VAL_LT(t1, t2)	(!(PJ_TIME_VAL_GTE(t1,t2)))

+

+/**

+ * This macro will check if \a t1 is less than or equal to \a t2.

+ *

+ * @param t1    The first time value to compare.

+ * @param t2    The second time value to compare.

+ * @return      Non-zero if t1 is less than or equal to t2.

+ * @hideinitializer

+ */

+#define PJ_TIME_VAL_LTE(t1, t2)	(!PJ_TIME_VAL_GT(t1, t2))

+

+/**

+ * Add \a t2 to \a t1 and store the result in \a t1. Effectively

+ *

+ * this macro will expand as: (\a t1 += \a t2).

+ * @param t1    The time value to add.

+ * @param t2    The time value to be added to \a t1.

+ * @hideinitializer

+ */

+#define PJ_TIME_VAL_ADD(t1, t2)	    do {			    \

+					(t1).sec += (t2).sec;	    \

+					(t1).msec += (t2).msec;	    \

+					pj_time_val_normalize(&(t1)); \

+				    } while (0)

+

+

+/**

+ * Substract \a t2 from \a t1 and store the result in \a t1. Effectively

+ * this macro will expand as (\a t1 -= \a t2).

+ *

+ * @param t1    The time value to subsctract.

+ * @param t2    The time value to be substracted from \a t1.

+ * @hideinitializer

+ */

+#define PJ_TIME_VAL_SUB(t1, t2)	    do {			    \

+					(t1).sec -= (t2).sec;	    \

+					(t1).msec -= (t2).msec;	    \

+					pj_time_val_normalize(&(t1)); \

+				    } while (0)

+

+

+/**

+ * This structure represent the parsed representation of time.

+ * It is acquired by calling #pj_time_decode().

+ */

+typedef struct pj_parsed_time

+{

+    /** This represents day of week where value zero means Sunday */

+    int wday;

+

+    /** This represents day of the year, 0-365, where zero means

+     *  1st of January.

+     */

+    int yday;

+

+    /** This represents day of month: 1-31 */

+    int day;

+

+    /** This represents month, with the value is 0 - 11 (zero is January) */

+    int mon;

+

+    /** This represent the actual year (unlike in ANSI libc where

+     *  the value must be added by 1900).

+     */

+    int year;

+

+    /** This represents the second part, with the value is 0-59 */

+    int sec;

+

+    /** This represents the minute part, with the value is: 0-59 */

+    int min;

+

+    /** This represents the hour part, with the value is 0-23 */

+    int hour;

+

+    /** This represents the milisecond part, with the value is 0-999 */

+    int msec;

+

+} pj_parsed_time;

+

+

+/**

+ * @}	// Time Management

+ */

+

+///////////////////////////////////////////////////////////////////////////////

+/*

+ * Terminal.

+ */

+/**

+ * Color code combination.

+ */

+enum {

+    PJ_TERM_COLOR_R	= 2,    /**< Red            */

+    PJ_TERM_COLOR_G	= 4,    /**< Green          */

+    PJ_TERM_COLOR_B	= 1,    /**< Blue.          */

+    PJ_TERM_COLOR_BRIGHT = 8    /**< Bright mask.   */

+};

+

+

+

+

+PJ_END_DECL

+

+

+#endif /* __PJ_TYPES_H__ */

+

diff --git a/pjlib/include/pj/xml.h b/pjlib/include/pj/xml.h
new file mode 100644
index 0000000..6311448
--- /dev/null
+++ b/pjlib/include/pj/xml.h
@@ -0,0 +1,155 @@
+/* $Header: /pjproject-0.3/pjlib/include/pj/xml.h 4     10/14/05 12:26a Bennylp $ */

+

+#ifndef __PJ_XML_H__

+#define __PJ_XML_H__

+

+/**

+ * @file xml.h

+ * @brief PJLIB XML Parser/Helper.

+ */

+

+#include <pj/types.h>

+#include <pj/list.h>

+

+PJ_BEGIN_DECL

+

+/**

+ * @defgroup PJ_XML XML Parser/Helper.

+ * @ingroup PJ

+ * @{

+ */

+

+/** Typedef for XML attribute. */

+typedef struct pj_xml_attr pj_xml_attr;

+

+/** Typedef for XML nodes. */

+typedef struct pj_xml_node pj_xml_node;

+

+/** This structure declares XML attribute. */

+struct pj_xml_attr

+{

+    PJ_DECL_LIST_MEMBER(pj_xml_attr)

+    pj_str_t	name;	    /**< Attribute name. */

+    pj_str_t	value;	    /**< Attribute value. */

+};

+

+/** This structure describes XML node head inside XML node structure.

+ */

+typedef struct pj_xml_node_head

+{

+    PJ_DECL_LIST_MEMBER(pj_xml_node)

+} pj_xml_node_head;

+

+/** This structure describes XML node. */

+struct pj_xml_node

+{

+    PJ_DECL_LIST_MEMBER(pj_xml_node)    /** List @a prev and @a next member */

+    pj_str_t		name;		/** Node name. */

+    pj_xml_attr		attr_head;      /** Attribute list. */

+    pj_xml_node_head	node_head;      /** Node list. */

+    pj_str_t		content;	/** Node content. */

+};

+

+/**

+ * Parse XML message into XML document with a single root node. The parser

+ * is capable of parsing XML processing instruction construct ("<?") and 

+ * XML comments ("<!--"), however such constructs will be ignored and will not 

+ * be included in the resulted XML node tree.

+ *

+ * @param pool	    Pool to allocate memory from.

+ * @param msg	    The XML message to parse.

+ * @param len	    The length of the message.

+ *

+ * @return	    XML root node, or NULL if the XML document can not be parsed.

+ */

+PJ_DECL(pj_xml_node*) pj_xml_parse( pj_pool_t *pool, char *msg, pj_size_t len);

+

+

+/**

+ * Print XML into XML message. Note that the function WILL NOT NULL terminate

+ * the output.

+ *

+ * @param node	    The XML node to print.

+ * @param buf	    Buffer to hold the output message.

+ * @param len	    The length of the buffer.

+ * @param prolog    If set to nonzero, will print XML prolog ("<?xml..")

+ *

+ * @return	    The size of the printed message, or -1 if there is not 

+ *		    sufficient space in the buffer to print the message.

+ */

+PJ_DECL(int) pj_xml_print( const pj_xml_node *node, char *buf, pj_size_t len,

+			   pj_bool_t include_prolog);

+

+/**

+ * Add node to another node.

+ *

+ * @param parent    Parent node.

+ * @param node	    Node to be added to parent.

+ */

+PJ_DECL(void) pj_xml_add_node( pj_xml_node *parent, pj_xml_node *node );

+

+

+/**

+ * Add attribute to a node.

+ *

+ * @param node	    Node.

+ * @param attr	    Attribute to add to node.

+ */

+PJ_DECL(void) pj_xml_add_attr( pj_xml_node *node, pj_xml_attr *attr );

+

+/**

+ * Find first node with the specified name.

+ *

+ * @param parent    Parent node.

+ * @param name	    Node name to find.

+ *

+ * @return	    XML node found or NULL.

+ */

+PJ_DECL(pj_xml_node*) pj_xml_find_node(pj_xml_node *parent, const pj_str_t *name);

+

+/**

+ * Find first node with the specified name.

+ *

+ * @param parent    Parent node.

+ * @param name	    Node name to find.

+ *

+ * @return	    XML node found or NULL.

+ */

+PJ_DECL(pj_xml_node*) pj_xml_find_next_node(pj_xml_node *parent, pj_xml_node *node,

+					    const pj_str_t *name);

+

+/**

+ * Find first attribute within a node with the specified name and optional value.

+ *

+ * @param node	    XML Node.

+ * @param name	    Attribute name to find.

+ * @param value	    Optional value to match.

+ *

+ * @return	    XML attribute found, or NULL.

+ */

+PJ_DECL(pj_xml_attr*) pj_xml_find_attr(pj_xml_node *node, const pj_str_t *name,

+				       const pj_str_t *value);

+

+

+/**

+ * Find a direct child node with the specified name and match the function.

+ *

+ * @param node	    Parent node.

+ * @param name	    Optional name.

+ * @param data	    Data to be passed to matching function.

+ * @param match	    Optional matching function.

+ *

+ * @return	    The first matched node, or NULL.

+ */

+PJ_DECL(pj_xml_node*) pj_xml_find( pj_xml_node *parent, const pj_str_t *name,

+				   const void *data, 

+				   pj_bool_t (*match)(pj_xml_node *, const void*));

+

+

+/**

+ * @}

+ */

+

+PJ_END_DECL

+

+#endif	/* __PJ_XML_H__ */

diff --git a/pjlib/include/pjlib++.hpp b/pjlib/include/pjlib++.hpp
new file mode 100644
index 0000000..1bdd826
--- /dev/null
+++ b/pjlib/include/pjlib++.hpp
@@ -0,0 +1,17 @@
+/* $Header: /pjproject/pjlib/src/pjlib++.hpp 1     7/05/05 12:58a Bennylp $ */

+#ifndef __PJLIBPP_H__

+#define __PJLIBPP_H__

+

+#include <pj++/pool.hpp>

+#include <pj++/hash.hpp>

+//#include <pj++/ioqueue.hpp>

+#include <pj++/list.hpp>

+#include <pj++/os.hpp>

+#include <pj++/proactor.hpp>

+#include <pj++/scanner.hpp>

+#include <pj++/sock.hpp>

+#include <pj++/string.hpp>

+#include <pj++/timer.hpp>

+#include <pj++/tree.hpp>

+

+#endif	/* __PJLIBPP_H__ */

diff --git a/pjlib/include/pjlib.h b/pjlib/include/pjlib.h
new file mode 100644
index 0000000..06b7d7e
--- /dev/null
+++ b/pjlib/include/pjlib.h
@@ -0,0 +1,39 @@
+/* $Header: /pjproject-0.3/pjlib/include/pjlib.h 6     10/29/05 11:30a Bennylp $ */

+#ifndef __PJLIB_H__

+#define __PJLIB_H__

+

+/**

+ * @file pjlib.h

+ * @brief Include all PJLIB header files.

+ */

+

+#include <pj/addr_resolv.h>

+#include <pj/array.h>

+#include <pj/assert.h>

+#include <pj/ctype.h>

+#include <pj/errno.h>

+#include <pj/except.h>

+#include <pj/fifobuf.h>

+#include <pj/guid.h>

+#include <pj/hash.h>

+#include <pj/ioqueue.h>

+#include <pj/list.h>

+#include <pj/lock.h>

+#include <pj/log.h>

+#include <pj/md5.h>

+#include <pj/os.h>

+#include <pj/pool.h>

+#include <pj/rand.h>

+#include <pj/rbtree.h>

+#include <pj/scanner.h>

+#include <pj/sock.h>

+#include <pj/sock_select.h>

+#include <pj/string.h>

+#include <pj/stun.h>

+#include <pj/timer.h>

+#include <pj/xml.h>

+

+#include <pj/compat/high_precision.h>

+

+#endif  /* __PJLIB_H__ */

+