diff options
Diffstat (limited to 'pjsip')
37 files changed, 2359 insertions, 1606 deletions
diff --git a/pjsip/build/TODO.txt b/pjsip/build/TODO.txt deleted file mode 100644 index 670e2bff..00000000 --- a/pjsip/build/TODO.txt +++ /dev/null @@ -1,21 +0,0 @@ -- regc refresh automatically
-- if dialog CANCEL return 481, disconnect the dialog
-- presence implement callback from event_sub
-- presence supports multiple tuples!
-- implement event headers!
-
-Prio Task
- 10 General authentication framework in pjsua.
- 10 Start on SUBSCRIBE/NOTIFY framework.
- 10 Refactor pjsip_event
----
- 10 Concurrency in pool factory because endpt pool is shared by app.
- Choices:
- - another pool factory (thread safe) for app ==> waste memory.
- - endpt pool is thread safe ==> slow
- 10 Sound in Linux
- 10 Support TCP
- 10 Per instance configuration:
- - max number of tsxs
- - max number of dialogs
- - socket buffer size
diff --git a/pjsip/build/pjsip_core.dsp b/pjsip/build/pjsip_core.dsp index 0703f914..2204a6f3 100644 --- a/pjsip/build/pjsip_core.dsp +++ b/pjsip/build/pjsip_core.dsp @@ -32,16 +32,16 @@ RSC=rc.exe # PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Output_Dir ".\output\pjsip-core-i386-win32-vc6-release"
+# PROP BASE Intermediate_Dir ".\output\pjsip-core-i386-win32-vc6-release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
-# PROP Output_Dir ".\output\pjsip_core_vc6_Release"
-# PROP Intermediate_Dir ".\output\pjsip_core_vc6_Release"
+# PROP Output_Dir ".\output\pjsip-core-i386-win32-vc6-release"
+# PROP Intermediate_Dir ".\output\pjsip-core-i386-win32-vc6-release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD CPP /nologo /MD /W4 /Zi /O2 /I "../src" /I "../../pjlib/src" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FR /FD /c
+# ADD CPP /nologo /MD /W4 /Zi /O2 /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
@@ -50,22 +50,22 @@ BSC32=bscmake.exe # ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo /out:"../lib/pjsip_core_vc6s.lib"
+# ADD LIB32 /nologo /out:"../lib/pjsip-core-i386-win32-vc6-release.lib"
!ELSEIF "$(CFG)" == "pjsip_core - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Output_Dir ".\output\pjsip-core-i386-win32-vc6-debug"
+# PROP BASE Intermediate_Dir ".\output\pjsip-core-i386-win32-vc6-debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
-# PROP Output_Dir ".\output\pjsip_core_vc6_Debug"
-# PROP Intermediate_Dir ".\output\pjsip_core_vc6_Debug"
+# PROP Output_Dir ".\output\pjsip-core-i386-win32-vc6-debug"
+# PROP Intermediate_Dir ".\output\pjsip-core-i386-win32-vc6-debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../src" /I "../../pjlib/src" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /FD /GZ /c
+# ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /GZ /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
@@ -74,7 +74,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo /out:"../lib/pjsip_core_vc6sd.lib"
+# ADD LIB32 /nologo /out:"../lib/pjsip-core-i386-win32-vc6-debug.lib"
!ENDIF
@@ -135,75 +135,79 @@ SOURCE=..\src\pjsip\sip_uri.c # PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
-SOURCE=..\src\pjsip_core.h
+SOURCE=..\include\pjsip_core.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\print.h
+SOURCE=..\include\pjsip\print_util.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_auth.h
+SOURCE=..\include\pjsip\sip_auth.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_auth_msg.h
+SOURCE=..\include\pjsip\sip_auth_msg.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_auth_parser.h
+SOURCE=..\include\pjsip\sip_auth_parser.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_config.h
+SOURCE=..\include\pjsip\sip_config.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_endpoint.h
+SOURCE=..\include\pjsip\sip_endpoint.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_event.h
+SOURCE=..\include\pjsip\sip_errno.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_misc.h
+SOURCE=..\include\pjsip\sip_event.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_module.h
+SOURCE=..\include\pjsip\sip_misc.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_msg.h
+SOURCE=..\include\pjsip\sip_module.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_parser.h
+SOURCE=..\include\pjsip\sip_msg.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_private.h
+SOURCE=..\include\pjsip\sip_parser.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_resolve.h
+SOURCE=..\include\pjsip\sip_private.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_transaction.h
+SOURCE=..\include\pjsip\sip_resolve.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_transport.h
+SOURCE=..\include\pjsip\sip_transaction.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_types.h
+SOURCE=..\include\pjsip\sip_transport.h
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip\sip_uri.h
+SOURCE=..\include\pjsip\sip_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\pjsip\sip_uri.h
# End Source File
# End Group
# Begin Group "Inline Files"
@@ -211,7 +215,7 @@ SOURCE=..\src\pjsip\sip_uri.h # PROP Default_Filter ""
# Begin Source File
-SOURCE=..\src\pjsip\sip_msg_i.h
+SOURCE=..\include\pjsip\sip_msg_i.h
# End Source File
# End Group
# Begin Source File
diff --git a/pjsip/build/pjsip_ua.dsp b/pjsip/build/pjsip_ua.dsp index efde2534..cd45b10c 100644 --- a/pjsip/build/pjsip_ua.dsp +++ b/pjsip/build/pjsip_ua.dsp @@ -87,15 +87,19 @@ LIB32=link.exe -lib # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
-SOURCE=..\src\pjsip_mod_ua\sip_dialog.c
+SOURCE="..\src\pjsip-ua\sip_dialog.c"
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip_mod_ua\sip_reg.c
+SOURCE="..\src\pjsip-ua\sip_reg.c"
# End Source File
# Begin Source File
-SOURCE=..\src\pjsip_mod_ua\sip_ua.c
+SOURCE="..\src\pjsip-ua\sip_ua.c"
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjsip-ua\sip_ua_private.h"
# End Source File
# End Group
# Begin Group "Header Files"
diff --git a/pjsip/build/tounix b/pjsip/build/tounix deleted file mode 100644 index 82b84c90..00000000 --- a/pjsip/build/tounix +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh
-name=`basename $1`
-cp $1 /tmp
-cat /tmp/$name | tr -d '\r' > $1
-rm -f /tmp/$name
diff --git a/pjsip/src/pjsip/print.h b/pjsip/include/pjsip/print_util.h index d1b9850c..b23d45fc 100644 --- a/pjsip/src/pjsip/print.h +++ b/pjsip/include/pjsip/print_util.h @@ -1,5 +1,4 @@ /* $Id$ - * */ #ifndef __PJSIP_PRINT_H__ #define __PJSIP_PRINT_H__ diff --git a/pjsip/include/pjsip/sip_auth.h b/pjsip/include/pjsip/sip_auth.h index 3396b669..c34ca030 100644 --- a/pjsip/include/pjsip/sip_auth.h +++ b/pjsip/include/pjsip/sip_auth.h @@ -1,5 +1,4 @@ /* $Id$ - * */ #ifndef __PJSIP_AUTH_SIP_AUTH_H__ #define __PJSIP_AUTH_SIP_AUTH_H__ @@ -60,7 +59,7 @@ struct pjsip_cred_info */ typedef struct pjsip_cached_auth_hdr { - PJ_DECL_LIST_MEMBER(struct pjsip_cached_auth_hdr) + PJ_DECL_LIST_MEMBER(struct pjsip_cached_auth_hdr); pjsip_method method; pjsip_authorization_hdr *hdr; @@ -80,7 +79,7 @@ typedef struct pjsip_cached_auth_hdr */ typedef struct pjsip_auth_session { - PJ_DECL_LIST_MEMBER(struct pjsip_auth_session) + PJ_DECL_LIST_MEMBER(struct pjsip_auth_session); pj_str_t realm; pj_bool_t is_proxy; diff --git a/pjsip/include/pjsip/sip_auth_msg.h b/pjsip/include/pjsip/sip_auth_msg.h index ce1ca1e7..8e68331d 100644 --- a/pjsip/include/pjsip/sip_auth_msg.h +++ b/pjsip/include/pjsip/sip_auth_msg.h @@ -1,5 +1,4 @@ /* $Id$ - * */ #ifndef __PJSIP_AUTH_SIP_AUTH_MSG_H__ #define __PJSIP_AUTH_SIP_AUTH_MSG_H__ @@ -68,7 +67,7 @@ typedef struct pjsip_pgp_credential pjsip_pgp_credential; */ struct pjsip_authorization_hdr { - PJSIP_DECL_HDR_MEMBER(struct pjsip_authorization_hdr) + PJSIP_DECL_HDR_MEMBER(struct pjsip_authorization_hdr); pj_str_t scheme; union { @@ -157,7 +156,7 @@ typedef struct pjsip_pgp_challenge pjsip_pgp_challenge; */ struct pjsip_www_authenticate_hdr { - PJSIP_DECL_HDR_MEMBER(struct pjsip_www_authenticate_hdr) + PJSIP_DECL_HDR_MEMBER(struct pjsip_www_authenticate_hdr); pj_str_t scheme; union { diff --git a/pjsip/include/pjsip/sip_auth_parser.h b/pjsip/include/pjsip/sip_auth_parser.h index 7f280ecd..c1d4f231 100644 --- a/pjsip/include/pjsip/sip_auth_parser.h +++ b/pjsip/include/pjsip/sip_auth_parser.h @@ -1,5 +1,4 @@ /* $Id$ - * */ #ifndef __PJSIP_AUTH_SIP_AUTH_PARSER_H__ #define __PJSIP_AUTH_SIP_AUTH_PARSER_H__ @@ -23,9 +22,11 @@ PJ_BEGIN_DECL * Initialize and register authorization parser module. * This will register parser handler for various Authorization related headers * such as Authorization, WWW-Authenticate, Proxy-Authorizization, and - * Proxy-Authenticate headers. + * Proxy-Authenticate headers.
+ *
+ * @return PJ_SUCCESS or the appropriate status code. */ -PJ_DECL(void) pjsip_auth_init_parser(); +PJ_DECL(pj_status_t) pjsip_auth_init_parser(void); /** * DeInitialize authorization parser module. diff --git a/pjsip/include/pjsip/sip_config.h b/pjsip/include/pjsip/sip_config.h index a594d488..bba037cb 100644 --- a/pjsip/include/pjsip/sip_config.h +++ b/pjsip/include/pjsip/sip_config.h @@ -1,5 +1,4 @@ /* $Id$ - * */ #ifndef __PJSIP_SIP_CONFIG_H__ #define __PJSIP_SIP_CONFIG_H__ @@ -133,7 +132,6 @@ #include <pj/config.h> -#include <pj/compat.h> #endif /* __PJSIP_SIP_CONFIG_H__ */ diff --git a/pjsip/include/pjsip/sip_endpoint.h b/pjsip/include/pjsip/sip_endpoint.h index d950657d..e67e2863 100644 --- a/pjsip/include/pjsip/sip_endpoint.h +++ b/pjsip/include/pjsip/sip_endpoint.h @@ -1,5 +1,4 @@ /* $Id$ - * */ #ifndef __PJSIP_SIP_ENDPOINT_H__ #define __PJSIP_SIP_ENDPOINT_H__ @@ -28,13 +27,15 @@ PJ_BEGIN_DECL * SIP Endpoint instance (pjsip_endpoint) can be viewed as the master/owner of * all SIP objects in an application. It performs the following roles: * - it manages the allocation/deallocation of memory pools for all objects. - * - it manages listeners and transports, and how they are used by transactions. + * - it manages listeners and transports, and how they are used by
+ * transactions. * - it owns transaction hash table. * - it receives incoming messages from transport layer and automatically * dispatches them to the correct transaction (or create a new one). * - it has a single instance of timer management (timer heap). * - it manages modules, which is the primary means of extending the library. - * - it provides single polling function for all objects and distributes events. + * - it provides single polling function for all objects and distributes
+ * events. * - it provides SIP policy such as which outbound proxy to use for all * outgoing SIP request messages. * - it automatically handles incoming requests which can not be handled by @@ -49,15 +50,22 @@ PJ_BEGIN_DECL /** * Create an instance of SIP endpoint from the specified pool factory. - * The pool factory reference then will be kept by the endpoint, so that future - * memory allocations by SIP components will be taken from the same pool factory. - * - * @param pf Pool factory that will be used for the lifetime of endpoint. - * - * @return the endpoint instance on success. + * The pool factory reference then will be kept by the endpoint, so that
+ * future memory allocations by SIP components will be taken from the same
+ * pool factory. + * + * @param pf Pool factory that will be used for the lifetime of
+ * endpoint.
+ * @param name Optional name to be specified for the endpoint.
+ * If this parameter is NULL, then the name will use
+ * local host name.
+ * @param endpt Pointer to receive endpoint instance. + * + * @return PJ_SUCCESS on success. */ -PJ_DECL(pjsip_endpoint*) pjsip_endpt_create(pj_pool_factory *pf); - +PJ_DECL(pj_status_t) pjsip_endpt_create(pj_pool_factory *pf,
+ pjsip_endpoint **endpt); +
/** * Destroy endpoint instance. Application must make sure that all pending * transactions have been terminated properly, because this function does not @@ -66,6 +74,16 @@ PJ_DECL(pjsip_endpoint*) pjsip_endpt_create(pj_pool_factory *pf); * @param endpt The SIP endpoint to be destroyed. */ PJ_DECL(void) pjsip_endpt_destroy(pjsip_endpoint *endpt); +
+/**
+ * Get endpoint name.
+ *
+ * @param endpt The SIP endpoint instance.
+ *
+ * @return Endpoint name, as was registered during endpoint
+ * creation. The string is NULL terminated.
+ */
+PJ_DECL(const pj_str_t*) pjsip_endpt_name(const pjsip_endpoint *endpt);
/** * Poll for events. Application must call this function periodically to ensure @@ -153,10 +171,13 @@ PJ_DECL(void) pjsip_endpt_cancel_timer( pjsip_endpoint *endpt, * transaction to endpoint with #pjsip_endpt_register_tsx. * This function, like all other endpoint functions, is thread safe. * - * @param endpt The SIP endpoint. - * @return The new transaction, or NULL on failure. + * @param endpt The SIP endpoint.
+ * @param p_tsx Pointer to receive the transaction.
+ * + * @return PJ_SUCCESS or the appropriate error code. */ -PJ_DECL(pjsip_transaction*) pjsip_endpt_create_tsx(pjsip_endpoint *endpt); +PJ_DECL(pj_status_t) pjsip_endpt_create_tsx(pjsip_endpoint *endpt,
+ pjsip_transaction **p_tsx); /** * Register the transaction to the endpoint's transaction table. @@ -187,10 +208,13 @@ PJ_DECL(void) pjsip_endpt_destroy_tsx( pjsip_endpoint *endpt, * Create a new transmit data buffer. * This function, like all other endpoint functions, is thread safe. * - * @param endpt the endpoint. - * @return new transmit data. + * @param endpt The endpoint.
+ * @param p_tdata Pointer to receive transmit data buffer.
+ * + * @return PJ_SUCCESS or the appropriate error code. */ -PJ_DECL(pjsip_tx_data*) pjsip_endpt_create_tdata( pjsip_endpoint *endpt ); +PJ_DECL(pj_status_t) pjsip_endpt_create_tdata( pjsip_endpoint *endpt,
+ pjsip_tx_data **p_tdata); /** * Asynchronously resolve a SIP target host or domain according to rule @@ -330,6 +354,24 @@ PJ_DECL(pj_status_t) pjsip_endpt_set_proxies( pjsip_endpoint *endpt, * @return List of "Route" header. */ PJ_DECL(const pjsip_route_hdr*) pjsip_endpt_get_routing( pjsip_endpoint *endpt ); +
+/**
+ * Log an error.
+ */
+PJ_DECL(void) pjsip_endpt_log_error( pjsip_endpoint *endpt,
+ const char *sender,
+ pj_status_t error_code,
+ const char *format,
+ ... );
+
+#define PJSIP_ENDPT_LOG_ERROR(expr) \
+ pjsip_endpt_log_error expr
+
+#define PJSIP_ENDPT_TRACE(tracing,expr) \
+ do { \
+ if ((tracing)) \
+ PJ_LOG(4,expr); \
+ } while (0)
/** * @} diff --git a/pjsip/include/pjsip/sip_errno.h b/pjsip/include/pjsip/sip_errno.h new file mode 100644 index 00000000..6e4a6f72 --- /dev/null +++ b/pjsip/include/pjsip/sip_errno.h @@ -0,0 +1,86 @@ +/* $Id$
+ */
+#ifndef __PJSIP_SIP_ERRNO_H__
+#define __PJSIP_SIP_ERRNO_H__
+
+#include <pj/errno.h>
+
+/**
+ * Start of error code relative to PJ_ERRNO_START_USER.
+ */
+#define PJSIP_ERRNO_START (PJ_ERRNO_START_USER+10000)
+
+/**
+ * Create error value from SIP status code.
+ * @param code SIP status code.
+ * @return Error code in pj_status_t namespace.
+ */
+#define PJSIP_ERRNO_FROM_SIP_STATUS(code) (PJSIP_ERRNO_START+code)
+
+/**
+ * Get SIP status code from error value.
+ * If conversion to SIP status code is not available, a SIP status code
+ * 599 will be returned.
+ *
+ * @param status Error code in pj_status_t namespace.
+ * @return SIP status code.
+ */
+#define PJSIP_ERRNO_TO_SIP_STATUS(status) \
+ ((status>=PJSIP_ERRNO_FROM_SIP_STATUS(100) && \
+ status<PJSIP_ERRNO_FROM_SIP_STATUS(999)) ? \
+ status-PJSIP_ERRNO_FROM_SIP_STATUS(0) : 599)
+
+
+/**
+ * Start of PJSIP generated error code values.
+ */
+#define PJSIP_ERRNO_START_PJSIP (PJSIP_ERRNO_START + 10000)
+
+/**
+ * @hideinitializer
+ * Missing required header(s).
+ */
+#define PJSIP_EMISSINGHDR (PJSIP_ERRNO_START_PJSIP + 1)
+/**
+ * @hideinitializer
+ * Unsupported URL scheme.
+ */
+#define PJSIP_EINVALIDSCHEME (PJSIP_ERRNO_START_PJSIP + 2)
+/**
+ * @hideinitializer
+ * Transaction has just been destroyed.
+ */
+#define PJSIP_ETSXDESTROYED (PJSIP_ERRNO_START_PJSIP + 3)
+/**
+ * @hideinitializer
+ * Buffer overflow. See also PJSIP_EMSGTOOLONG.
+ */
+#define PJSIP_EOVERFLOW (PJSIP_ERRNO_START_PJSIP + 4)
+/**
+ * @hideinitializer
+ * Message not completely received.
+ */
+#define PJSIP_EPARTIALMSG (PJSIP_ERRNO_START_PJSIP + 5)
+/**
+ * @hideinitializer
+ * Message too long. See also PJSIP_EOVERFLOW.
+ */
+#define PJSIP_EMSGTOOLONG (PJSIP_ERRNO_START_PJSIP + 6)
+/**
+ * @hideinitializer
+ * Buffer is being sent, operation still pending.
+ */
+#define PJSIP_EPENDINGTX (PJSIP_ERRNO_START_PJSIP + 7)
+/**
+ * @hideinitializer
+ * Unsupported transport type.
+ */
+#define PJSIP_EUNSUPTRANSPORT (PJSIP_ERRNO_START_PJSIP + 8)
+/**
+ * @hideinitializer
+ * Invalid Via header in response (sent-by, etc).
+ */
+#define PJSIP_EINVALIDVIA (PJSIP_ERRNO_START_PJSIP + 9)
+
+
+#endif /* __PJSIP_SIP_ERRNO_H__ */
diff --git a/pjsip/include/pjsip/sip_event.h b/pjsip/include/pjsip/sip_event.h index ac7bc691..98ac3850 100644 --- a/pjsip/include/pjsip/sip_event.h +++ b/pjsip/include/pjsip/sip_event.h @@ -1,5 +1,4 @@ /* $Id$ - * */ #ifndef __PJSIP_SIP_EVENT_H__ #define __PJSIP_SIP_EVENT_H__ @@ -25,7 +24,7 @@ PJ_BEGIN_DECL typedef enum pjsip_event_id_e { /** Unidentified event. */ - PJSIP_EVENT_UNIDENTIFIED, + PJSIP_EVENT_UNKNOWN, /** Timer event, normally only used internally in transaction. */ PJSIP_EVENT_TIMER, @@ -40,10 +39,10 @@ typedef enum pjsip_event_id_e PJSIP_EVENT_TRANSPORT_ERROR, /** Transaction state changed event. */ - PJSIP_EVENT_TSX_STATE_CHANGED, + PJSIP_EVENT_TSX_STATE, /** 2xx response received event. */ - PJSIP_EVENT_RX_200_RESPONSE, + PJSIP_EVENT_RX_200_MSG, /** ACK request received event. */ PJSIP_EVENT_RX_ACK_MSG, @@ -55,7 +54,7 @@ typedef enum pjsip_event_id_e PJSIP_EVENT_USER, /** On before transmitting message. */ - PJSIP_EVENT_BEFORE_TX, + PJSIP_EVENT_PRE_TX_MSG, } pjsip_event_id_e; @@ -76,46 +75,208 @@ typedef enum pjsip_event_id_e struct pjsip_event { /** This is necessary so that we can put events as a list. */ - PJ_DECL_LIST_MEMBER(struct pjsip_event) + PJ_DECL_LIST_MEMBER(struct pjsip_event); /** The event type, can be any value of \b pjsip_event_id_e. - * @see pjsip_event_id_e */ pjsip_event_id_e type; - - /** This field determines what is the content of \b src (source data). - */ - pjsip_event_id_e src_type; - - /** Source data, which content is dependent on \b src_type. - * - if src_type==PJSIP_EVENT_RX_MSG, src.rdata is valid. - * - if src_type==PJSIP_EVENT_TX_MSG, src.tdata is valid. - * - if src_type==PJSIP_EVENT_TIMER, src.timer is valid. - */ - union - { - pjsip_rx_data *rdata; - pjsip_tx_data *tdata; - pj_timer_entry *timer; - void *data; - unsigned long udata; - } src; - - /** The object that generates this event. */ - union - { - pjsip_transaction *tsx; - void *ptr; - unsigned long udata; - } obj; - - /** Other data. */ - union - { - long long_data; - void * ptr_data; - } data; +
+ /*
+ * The event body.
+ * By convention, the first member of each struct in the union must be
+ * the pointer which is relevant to the event.
+ */
+ union
+ {
+ /** Timer event. */
+ struct
+ {
+ pj_timer_entry *entry; /**< The timer entry. */
+ } timer;
+
+ /** Transaction state has changed event. */
+ struct
+ {
+ union
+ {
+ pjsip_rx_data *rdata; /**< The incoming message. */
+ pjsip_tx_data *tdata; /**< The outgoing message. */
+ pj_timer_entry *timer; /**< The timer. */
+ pj_status_t status;/**< Transport error status. */
+ void *data; /**< Generic data. */
+ } src;
+ pjsip_transaction *tsx; /**< The transaction. */
+ pjsip_event_id_e type; /**< Type of event source:
+ * - PJSIP_EVENT_TX_MSG
+ * - PJSIP_EVENT_RX_MSG,
+ * - PJSIP_EVENT_TRANSPORT_ERROR
+ * - PJSIP_EVENT_TIMER
+ * - PJSIP_EVENT_USER
+ */
+ } tsx_state;
+
+ /** Message transmission event. */
+ struct
+ {
+ pjsip_tx_data *tdata; /**< The transmit data buffer. */
+ pjsip_transaction *tsx; /**< The transaction. */
+
+ } tx_msg;
+
+ /** Pre-transmission event. */
+ struct
+ {
+ pjsip_tx_data *tdata; /**< Msg to be transmitted. */
+ pjsip_transaction *tsx; /**< The transaction. */
+ int retcnt;/**< Retransmission count. */
+ } pre_tx_msg;
+
+ /** Transmission error event. */
+ struct
+ {
+ pjsip_tx_data *tdata; /**< The transmit data. */
+ pjsip_transaction *tsx; /**< The transaction. */
+ } tx_error;
+
+ /** Message arrival event. */
+ struct
+ {
+ pjsip_rx_data *rdata; /**< The receive data buffer. */
+ pjsip_transaction *tsx; /**< The transaction. */
+ } rx_msg;
+
+ /** Receipt of 200/INVITE response. */
+ struct
+ {
+ pjsip_rx_data *rdata; /**< The 200 response msg. */
+ } rx_200_msg;
+
+ /** Receipt of ACK message. */
+ struct
+ {
+ pjsip_rx_data *rdata; /**< The ack message. */
+ } rx_ack_msg;
+
+ /** Notification that endpoint has discarded a message. */
+ struct
+ {
+ pjsip_rx_data *rdata; /**< The discarded message. */
+ pj_status_t reason;/**< The reason. */
+ } discard_msg;
+
+ /** User event. */
+ struct
+ {
+ void *user1; /**< User data 1. */
+ void *user2; /**< User data 2. */
+ void *user3; /**< User data 3. */
+ void *user4; /**< User data 4. */
+ } user;
+
+ } body;
}; +
+/**
+ * Init timer event.
+ */
+#define PJSIP_EVENT_INIT_TIMER(event,pentry) \
+ do { \
+ (event).type = PJSIP_EVENT_TIMER; \
+ (event).body.timer.entry = pentry; \
+ } while (0)
+
+/**
+ * Init tsx state event.
+ */
+#define PJSIP_EVENT_INIT_TSX_STATE(event,ptsx,ptype,pdata) \
+ do { \
+ (event).type = PJSIP_EVENT_TSX_STATE; \
+ (event).body.tsx_state.tsx = ptsx; \
+ (event).body.tsx_state.type = ptype; \
+ (event).body.tsx_state.src.data = pdata; \
+ } while (0)
+
+/**
+ * Init tx msg event.
+ */
+#define PJSIP_EVENT_INIT_TX_MSG(event,ptsx,ptdata) \
+ do { \
+ (event).type = PJSIP_EVENT_TX_MSG; \
+ (event).body.tx_msg.tsx = ptsx; \
+ (event).body.tx_msg.tdata = ptdata; \
+ } while (0)
+
+/**
+ * Init rx msg event.
+ */
+#define PJSIP_EVENT_INIT_RX_MSG(event,ptsx,prdata) \
+ do { \
+ (event).type = PJSIP_EVENT_RX_MSG; \
+ (event).body.rx_msg.tsx = ptsx; \
+ (event).body.rx_msg.rdata = prdata; \
+ } while (0)
+
+/**
+ * Init transport error event.
+ */
+#define PJSIP_EVENT_INIT_TRANSPORT_ERROR(event,ptsx,ptdata) \
+ do { \
+ (event).type = PJSIP_EVENT_TRANSPORT_ERROR; \
+ (event).body.tx_error.tsx = ptsx; \
+ (event).body.tx_error.tdata = ptdata; \
+ } while (0)
+
+/**
+ * Init rx 200/INVITE event.
+ */
+#define PJSIP_EVENT_INIT_RX_200_MSG(event,prdata) \
+ do { \
+ (event).type = PJSIP_EVENT_RX_200_MSG; \
+ (event).body.rx_200_msg.rdata = prdata; \
+ } while (0)
+
+/**
+ * Init rx ack msg event.
+ */
+#define PJSIP_EVENT_INIT_RX_ACK_MSG(event,prdata) \
+ do { \
+ (event).type = PJSIP_EVENT_RX_ACK_MSG; \
+ (event).body.rx_ack_msg.rdata = prdata; \
+ } while (0)
+
+/**
+ * Init discard msg event.
+ */
+#define PJSIP_EVENT_INIT_DISCARD_MSG(event,prdata,preason) \
+ do { \
+ (event).type = PJSIP_EVENT_DISCARD_MSG; \
+ (event).body.discard_msg.rdata = prdata; \
+ (event).body.discard_msg.reason = preason; \
+ } while (0)
+
+/**
+ * Init user event.
+ */
+#define PJSIP_EVENT_INIT_USER(event,u1,u2,u3,u4) \
+ do { \
+ (event).type = PJSIP_EVENT_USER; \
+ (event).body.user.user1 = (void*)u1; \
+ (event).body.user.user2 = (void*)u2; \
+ (event).body.user.user3 = (void*)u3; \
+ (event).body.user.user4 = (void*)u4; \
+ } while (0)
+
+/**
+ * Init pre tx msg event.
+ */
+#define PJSIP_EVENT_INIT_PRE_TX_MSG(event,ptsx,ptdata,pretcnt) \
+ do { \
+ (event).type = PJSIP_EVENT_PRE_TX_MSG; \
+ (event).body.pre_tx_msg.tsx = ptsx; \
+ (event).body.pre_tx_msg.tdata = ptdata; \
+ (event).body.pre_tx_msg.retcnt = pretcnt; \
+ } while (0)
+
/** * Get the event string from the event ID. diff --git a/pjsip/include/pjsip/sip_misc.h b/pjsip/include/pjsip/sip_misc.h index be2ccca9..4101dbc1 100644 --- a/pjsip/include/pjsip/sip_misc.h +++ b/pjsip/include/pjsip/sip_misc.h @@ -1,5 +1,4 @@ /* $Id$ - * */ #ifndef __PJSIP_SIP_MISC_H__ #define __PJSIP_SIP_MISC_H__ @@ -29,19 +28,21 @@ PJ_BEGIN_DECL * @param contact URL to put in Contact header. * @param call_id Optional Call-ID (put NULL to generate unique Call-ID). * @param cseq Optional CSeq (put -1 to generate random CSeq). - * @param text Optional text body (put NULL to omit body). + * @param text Optional text body (put NULL to omit body).
+ * @param p_tdata Pointer to receive the transmit data. * - * @return The transmit data. + * @return PJ_SUCCESS, or the appropriate error code. */ -PJ_DECL(pjsip_tx_data*) pjsip_endpt_create_request( pjsip_endpoint *endpt, - const pjsip_method *method, - const pj_str_t *target, - const pj_str_t *from, - const pj_str_t *to, - const pj_str_t *contact, - const pj_str_t *call_id, - int cseq, - const pj_str_t *text); +PJ_DECL(pj_status_t) pjsip_endpt_create_request( pjsip_endpoint *endpt, + const pjsip_method *method, + const pj_str_t *target, + const pj_str_t *from, + const pj_str_t *to, + const pj_str_t *contact, + const pj_str_t *call_id, + int cseq, + const pj_str_t *text,
+ pjsip_tx_data **p_tdata); /** * Create an independent request message from the specified headers. This @@ -57,11 +58,12 @@ PJ_DECL(pjsip_tx_data*) pjsip_endpt_create_request( pjsip_endpoint *endpt, * @param contact URL to put in Contact header. * @param call_id Optional Call-ID (put NULL to generate unique Call-ID). * @param cseq Optional CSeq (put -1 to generate random CSeq). - * @param text Optional text body (put NULL to omit body). + * @param text Optional text body (put NULL to omit body).
+ * @param p_tdata Pointer to receive the transmit data. * - * @return The transmit data. + * @return PJ_SUCCESS, or the appropriate error code. */ -PJ_DECL(pjsip_tx_data*) +PJ_DECL(pj_status_t) pjsip_endpt_create_request_from_hdr( pjsip_endpoint *endpt, const pjsip_method *method, const pjsip_uri *target, @@ -70,7 +72,8 @@ pjsip_endpt_create_request_from_hdr( pjsip_endpoint *endpt, const pjsip_contact_hdr *contact, const pjsip_cid_hdr *call_id, int cseq, - const pj_str_t *text ); + const pj_str_t *text,
+ pjsip_tx_data **p_tdata); /** * Send outgoing request and initiate UAC transaction for the request. @@ -89,7 +92,7 @@ pjsip_endpt_create_request_from_hdr( pjsip_endpoint *endpt, * the previously registered token and the event that triggers * the completion of the transaction. * - * @return Zero if transaction is started successfully. + * @return PJ_SUCCESS, or the appropriate error code. */ PJ_DECL(pj_status_t) pjsip_endpt_send_request( pjsip_endpoint *endpt, pjsip_tx_data *tdata, @@ -106,13 +109,15 @@ PJ_DECL(pj_status_t) pjsip_endpt_send_request( pjsip_endpoint *endpt, * * @param endpt The endpoint. * @param rdata The request receive data. - * @param code Status code to be put in the response. + * @param code Status code to be put in the response.
+ * @param p_tdata Pointer to receive the transmit data. * - * @return Transmit data. + * @return PJ_SUCCESS, or the appropriate error code. */ -PJ_DECL(pjsip_tx_data*) pjsip_endpt_create_response(pjsip_endpoint *endpt, - const pjsip_rx_data *rdata, - int code); +PJ_DECL(pj_status_t) pjsip_endpt_create_response( pjsip_endpoint *endpt, + const pjsip_rx_data *rdata, + int code,
+ pjsip_tx_data **p_tdata); /** * Construct a full ACK request for the received non-2xx final response. @@ -136,11 +141,13 @@ PJ_DECL(void) pjsip_endpt_create_ack( pjsip_endpoint *endpt, * * @param endpt The endpoint. * @param tdata The transmit buffer for the request being cancelled. + * @param p_tdata Pointer to receive the transmit data.
* - * @return Cancel request. + * @return PJ_SUCCESS, or the appropriate error code. */ -PJ_DECL(pjsip_tx_data*) pjsip_endpt_create_cancel( pjsip_endpoint *endpt, - pjsip_tx_data *tdata ); +PJ_DECL(pj_status_t) pjsip_endpt_create_cancel( pjsip_endpoint *endpt, + pjsip_tx_data *tdata,
+ pjsip_tx_data **p_tdata); /** @@ -159,7 +166,6 @@ PJ_DECL(pj_status_t) pjsip_get_response_addr(pj_pool_t *pool, const pjsip_via_hdr *via, pjsip_host_port *addr); - /** * @} */ diff --git a/pjsip/include/pjsip/sip_module.h b/pjsip/include/pjsip/sip_module.h index f380b967..7bf53ab4 100644 --- a/pjsip/include/pjsip/sip_module.h +++ b/pjsip/include/pjsip/sip_module.h @@ -1,5 +1,4 @@ /* $Id$ - * */ #ifndef __PJSIP_SIP_MODULE_H__ #define __PJSIP_SIP_MODULE_H__ diff --git a/pjsip/include/pjsip/sip_msg.h b/pjsip/include/pjsip/sip_msg.h index 76834c29..ed9450b1 100644 --- a/pjsip/include/pjsip/sip_msg.h +++ b/pjsip/include/pjsip/sip_msg.h @@ -1,5 +1,4 @@ /* $Id$ - * */ #ifndef __PJSIP_SIP_MSG_H__ #define __PJSIP_SIP_MSG_H__ @@ -260,7 +259,7 @@ typedef struct pjsip_hdr_vptr */ #define PJSIP_DECL_HDR_MEMBER(hdr) \ /** List members. */ \ - PJ_DECL_LIST_MEMBER(hdr) \ + PJ_DECL_LIST_MEMBER(hdr); \ /** Header type */ \ pjsip_hdr_e type; \ /** Header name. */ \ @@ -268,17 +267,17 @@ typedef struct pjsip_hdr_vptr /** Header short name version. */ \ pj_str_t sname; \ /** Virtual function table. */ \ - pjsip_hdr_vptr *vptr; + pjsip_hdr_vptr *vptr /** * Generic SIP header structure, for generic manipulation for headers in the * message. All header fields can be typecasted to this type. */ -typedef struct pjsip_hdr +struct pjsip_hdr { - PJSIP_DECL_HDR_MEMBER(struct pjsip_hdr) -} pjsip_hdr; + PJSIP_DECL_HDR_MEMBER(struct pjsip_hdr); +}; /** @@ -687,7 +686,7 @@ PJ_IDECL(void) pjsip_msg_insert_first_hdr( pjsip_msg *msg, pjsip_hdr *hdr ); * @return The length of the printed characters (in bytes), or NEGATIVE * value if the message is too large for the specified buffer. */ -PJ_DECL(int) pjsip_msg_print( pjsip_msg *msg, char *buf, pj_size_t size); +PJ_DECL(pj_ssize_t) pjsip_msg_print(pjsip_msg *msg, char *buf, pj_size_t size); /** * @} @@ -707,7 +706,7 @@ PJ_DECL(int) pjsip_msg_print( pjsip_msg *msg, char *buf, pj_size_t size); */ typedef struct pjsip_generic_string_hdr { - PJSIP_DECL_HDR_MEMBER(struct pjsip_generic_string_hdr) /**< Standard header field. */ + PJSIP_DECL_HDR_MEMBER(struct pjsip_generic_string_hdr); /**< Standard header field. */ pj_str_t hvalue; /**< hvalue */ } pjsip_generic_string_hdr; @@ -756,7 +755,7 @@ pjsip_generic_string_hdr_create_with_text( pj_pool_t *pool, */ typedef struct pjsip_generic_int_hdr { - PJSIP_DECL_HDR_MEMBER(struct pjsip_generic_int_hdr) /**< Standard header field. */ + PJSIP_DECL_HDR_MEMBER(struct pjsip_generic_int_hdr); /**< Standard header field. */ pj_int32_t ivalue; /**< ivalue */ } pjsip_generic_int_hdr; @@ -805,7 +804,7 @@ pjsip_generic_int_hdr_create_with_value( pj_pool_t *pool, typedef struct pjsip_generic_array_hdr { - PJSIP_DECL_HDR_MEMBER(struct pjsip_generic_array_hdr) + PJSIP_DECL_HDR_MEMBER(struct pjsip_generic_array_hdr); unsigned count; /**< Number of elements. */ pj_str_t values[PJSIP_GENERIC_ARRAY_MAX_COUNT]; /**< Elements. */ } pjsip_generic_array_hdr; @@ -886,7 +885,7 @@ PJ_DECL(pjsip_allow_hdr*) pjsip_allow_hdr_create(pj_pool_t *pool); */ typedef struct pjsip_cid_hdr { - PJSIP_DECL_HDR_MEMBER(struct pjsip_cid_hdr) + PJSIP_DECL_HDR_MEMBER(struct pjsip_cid_hdr); pj_str_t id; /**< Call-ID string. */ } pjsip_cid_hdr; @@ -917,7 +916,7 @@ PJ_DECL(pjsip_cid_hdr*) pjsip_cid_hdr_create( pj_pool_t *pool ); */ typedef struct pjsip_clen_hdr { - PJSIP_DECL_HDR_MEMBER(struct pjsip_clen_hdr) + PJSIP_DECL_HDR_MEMBER(struct pjsip_clen_hdr); int len; /**< Content length. */ } pjsip_clen_hdr; @@ -945,7 +944,7 @@ PJ_DECL(pjsip_clen_hdr*) pjsip_clen_hdr_create( pj_pool_t *pool ); */ typedef struct pjsip_cseq_hdr { - PJSIP_DECL_HDR_MEMBER(struct pjsip_cseq_hdr) + PJSIP_DECL_HDR_MEMBER(struct pjsip_cseq_hdr); int cseq; /**< CSeq number. */ pjsip_method method; /**< CSeq method. */ } pjsip_cseq_hdr; @@ -977,7 +976,7 @@ PJ_DECL(pjsip_cseq_hdr*) pjsip_cseq_hdr_create( pj_pool_t *pool ); */ typedef struct pjsip_contact_hdr { - PJSIP_DECL_HDR_MEMBER(struct pjsip_contact_hdr) + PJSIP_DECL_HDR_MEMBER(struct pjsip_contact_hdr); int star; /**< The contact contains only a '*' character */ pjsip_uri *uri; /**< URI in the contact. */ int q1000; /**< The "q" value times 1000 (to avoid float) */ @@ -1010,7 +1009,7 @@ PJ_DECL(pjsip_contact_hdr*) pjsip_contact_hdr_create( pj_pool_t *pool ); */ typedef struct pjsip_ctype_hdr { - PJSIP_DECL_HDR_MEMBER(struct pjsip_ctype_hdr) + PJSIP_DECL_HDR_MEMBER(struct pjsip_ctype_hdr); pjsip_media_type media; /**< Media type. */ } pjsip_ctype_hdr; @@ -1061,7 +1060,7 @@ PJ_DECL(pjsip_expires_hdr*) pjsip_expires_hdr_create( pj_pool_t *pool ); */ typedef struct pjsip_fromto_hdr { - PJSIP_DECL_HDR_MEMBER(struct pjsip_fromto_hdr) + PJSIP_DECL_HDR_MEMBER(struct pjsip_fromto_hdr); pjsip_uri *uri; /**< URI in From/To header. */ pj_str_t tag; /**< Header "tag" parameter. */ pj_str_t other_param; /**< Other params, concatenated as a single string. */ @@ -1170,7 +1169,7 @@ PJ_DECL(pjsip_min_expires_hdr*) pjsip_min_expires_hdr_create(pj_pool_t *pool); */ typedef struct pjsip_routing_hdr { - PJSIP_DECL_HDR_MEMBER(struct pjsip_routing_hdr) /**< Generic header fields. */ + PJSIP_DECL_HDR_MEMBER(struct pjsip_routing_hdr); /**< Generic header fields. */ pjsip_name_addr name_addr; /**< The URL in the Route/Record-Route header. */ pj_str_t other_param; /** Other parameter. */ } pjsip_routing_hdr; @@ -1327,7 +1326,7 @@ PJ_DECL(pjsip_unsupported_hdr*) pjsip_unsupported_hdr_create(pj_pool_t *pool); */ typedef struct pjsip_via_hdr { - PJSIP_DECL_HDR_MEMBER(struct pjsip_via_hdr) + PJSIP_DECL_HDR_MEMBER(struct pjsip_via_hdr); pj_str_t transport; /**< Transport type. */ pjsip_host_port sent_by; /**< Host and optional port */ int ttl_param; /**< TTL parameter, or -1 if it's not specified. */ diff --git a/pjsip/include/pjsip/sip_parser.h b/pjsip/include/pjsip/sip_parser.h index 69e4aba7..5ae2f80f 100644 --- a/pjsip/include/pjsip/sip_parser.h +++ b/pjsip/include/pjsip/sip_parser.h @@ -1,5 +1,4 @@ /* $Id$ - * */ #ifndef __PJSIP_SIP_PARSER_H__ #define __PJSIP_SIP_PARSER_H__ @@ -10,7 +9,7 @@ */ #include <pjsip/sip_types.h> -#include <pj/scanner.h> +#include <pjlib-util/scanner.h> #include <pj/list.h> PJ_BEGIN_DECL @@ -51,13 +50,24 @@ enum */ typedef struct pjsip_parser_err_report { - PJ_DECL_LIST_MEMBER(struct pjsip_parser_err_report) + PJ_DECL_LIST_MEMBER(struct pjsip_parser_err_report); int exception_code; /**< Error exception (e.g. PJSIP_SYN_ERR_EXCEPTION) */ int line; /**< Line number. */ int col; /**< Column number. */ pj_str_t hname; /**< Header name, if any. */ } pjsip_parser_err_report; +
+/**
+ * Parsing context, the default argument for parsing functions.
+ */
+typedef struct pjsip_parse_ctx
+{
+ pj_scanner *scanner; /**< The scanner. */
+ pj_pool_t *pool; /**< The pool. */
+ pjsip_rx_data *rdata; /**< Optional rdata. */
+} pjsip_parse_ctx;
+
/** * Type of function to parse header. The parsing function must follow these @@ -76,7 +86,7 @@ typedef struct pjsip_parser_err_report * - for the last header, these separator is optional since parsing * can be terminated when seeing EOF. */ -typedef void* (pjsip_parse_hdr_func)(pj_scanner *scanner, pj_pool_t *pool); +typedef pjsip_hdr* (pjsip_parse_hdr_func)(pjsip_parse_ctx *context); /** * Type of function to parse URI scheme. @@ -94,8 +104,7 @@ typedef void* (pjsip_parse_uri_func)(pj_scanner *scanner, pj_pool_t *pool); * @param hshortname The short header name or NULL. * @param fptr The pointer to function to parser the header. * - * @return zero if success. - * @see pjsip_parse_hdr_func + * @return PJ_SUCCESS if success, or the appropriate error code. */ PJ_DECL(pj_status_t) pjsip_register_hdr_parser( const char *hname, const char *hshortname, @@ -183,6 +192,27 @@ PJ_DECL(pjsip_msg *) pjsip_parse_msg( pj_pool_t *pool, char *buf, pj_size_t size, pjsip_parser_err_report *err_list); +
+/**
+ * Parse a packet buffer and build a rdata. The resulting message will be
+ * stored in \c msg field in the \c rdata. This behaves pretty much like
+ * #pjsip_parse_msg(), except that it will also initialize the header fields
+ * in the \c rdata.
+ *
+ * This function is normally called by the transport layer.
+ *
+ * @param buf The input buffer
+ * @param buf The input buffer, which size must be at least (size+1)
+ * because the function will temporarily put NULL
+ * termination at the end of the buffer during parsing.
+ * @param size The length of the string (not counting NULL terminator).
+ * @param rdata The receive data buffer to store the message and
+ * its elements.
+ *
+ * @return The message inside the rdata if successfull, or NULL.
+ */
+PJ_DECL(pjsip_msg *) pjsip_parse_rdata( char *buf, pj_size_t size,
+ pjsip_rx_data *rdata );
/** * Check incoming packet to see if a (probably) valid SIP message has been @@ -193,10 +223,12 @@ PJ_DECL(pjsip_msg *) pjsip_parse_msg( pj_pool_t *pool, * @param msg_size [out] If message is valid, this parameter will contain * the size of the SIP message (including body, if any). * - * @return PJ_TRUE (1) if a message is found. + * @return PJ_SUCCESS if a message is found, or an error code. */ -PJ_DECL(pj_bool_t) pjsip_find_msg( const char *buf, pj_size_t size, - pj_bool_t is_datagram, pj_size_t *msg_size); +PJ_DECL(pj_status_t) pjsip_find_msg(const char *buf,
+ pj_size_t size, + pj_bool_t is_datagram,
+ pj_size_t *msg_size); /** * Parse the content of a header and return the header instance. @@ -247,7 +279,7 @@ PJ_DECL(pj_status_t) pjsip_parse_headers( pj_pool_t *pool, * parsers. */ extern -pj_char_spec pjsip_HOST_SPEC, /* For scanning host part. */ +pj_cis_t pjsip_HOST_SPEC, /* For scanning host part. */ pjsip_DIGIT_SPEC, /* Decimal digits */ pjsip_ALPHA_SPEC, /* Alpha (A-Z, a-z) */ pjsip_ALNUM_SPEC, /* Decimal + Alpha. */ diff --git a/pjsip/include/pjsip/sip_private.h b/pjsip/include/pjsip/sip_private.h index afcff08b..b2661350 100644 --- a/pjsip/include/pjsip/sip_private.h +++ b/pjsip/include/pjsip/sip_private.h @@ -1,5 +1,4 @@ /* $Id$ - * */ #ifndef __PJSIP_SIP_PRIVATE_H__ #define __PJSIP_SIP_PRIVATE_H__ @@ -26,16 +25,18 @@ PJ_BEGIN_DECL * @param endpt The endpoint * @param cb Callback to be called to receive messages from transport. */ -PJ_DECL(pjsip_transport_mgr*) pjsip_transport_mgr_create( pj_pool_t *pool, - pjsip_endpoint *endpt, - void (*cb)(pjsip_endpoint *,pjsip_rx_data *)); +PJ_DECL(pj_status_t) pjsip_transport_mgr_create( pj_pool_t *pool, + pjsip_endpoint *endpt, + void (*cb)(pjsip_endpoint *,
+ pjsip_rx_data *),
+ pjsip_transport_mgr **); /** * Destroy transport manager and release all transports. * @param mgr Transport manager to be destroyed. */ -PJ_DECL(void) pjsip_transport_mgr_destroy( pjsip_transport_mgr *mgr ); +PJ_DECL(pj_status_t) pjsip_transport_mgr_destroy( pjsip_transport_mgr *mgr ); /** * Poll for transport events. diff --git a/pjsip/include/pjsip/sip_resolve.h b/pjsip/include/pjsip/sip_resolve.h index 4a47c135..5464db91 100644 --- a/pjsip/include/pjsip/sip_resolve.h +++ b/pjsip/include/pjsip/sip_resolve.h @@ -1,5 +1,4 @@ /* $Id$ - * */ #ifndef __PJSIP_SIP_RESOLVE_H__ #define __PJSIP_SIP_RESOLVE_H__ diff --git a/pjsip/include/pjsip/sip_transaction.h b/pjsip/include/pjsip/sip_transaction.h index 3ef6ad14..cdb11235 100644 --- a/pjsip/include/pjsip/sip_transaction.h +++ b/pjsip/include/pjsip/sip_transaction.h @@ -1,5 +1,4 @@ /* $Id$ - * */ #ifndef __PJSIP_SIP_TRANSACTION_H__ #define __PJSIP_SIP_TRANSACTION_H__ @@ -11,8 +10,6 @@ #include <pjsip/sip_msg.h> #include <pjsip/sip_resolve.h> -//#include <pjsip/sip_config.h> -//#include <pjsip/sip_endpoint.h> #include <pj/timer.h> PJ_BEGIN_DECL @@ -22,7 +19,8 @@ PJ_BEGIN_DECL * @ingroup PJSIP * @{ */ - +
+/* Forward decl. */ struct pjsip_transaction; @@ -60,68 +58,111 @@ typedef enum pjsip_tsx_transport_state_e * Transaction state. */ struct pjsip_transaction -{ - pj_pool_t *pool; - pjsip_endpoint *endpt; - char obj_name[PJ_MAX_OBJ_NAME]; - pjsip_role_e role; - int status_code; - pjsip_tsx_state_e state; - int (*state_handler)(struct pjsip_transaction *, pjsip_event *); - - pj_mutex_t *mutex; - pjsip_method method; - int cseq; - pj_str_t transaction_key; - pj_str_t branch; - - pjsip_tsx_transport_state_e transport_state; - pjsip_host_port dest_name; - int current_addr; - pjsip_server_addresses remote_addr; - pjsip_transport_t *transport; - - pjsip_tx_data *last_tx; - int has_unsent_msg; - int handle_ack; - int retransmit_count; - - pj_timer_entry retransmit_timer; - pj_timer_entry timeout_timer; +{
+ /*
+ * Administrivia
+ */
+ pj_pool_t *pool; /**< Pool owned by the tsx. */
+ pjsip_endpoint *endpt; /**< Endpoint instance. */
+ pj_mutex_t *mutex; /**< Mutex for this tsx. */
+ char obj_name[PJ_MAX_OBJ_NAME]; /**< Tsx name. */
+ int tracing; /**< Tracing enabled? */
+
+ /*
+ * Transaction identification.
+ */
+ pjsip_role_e role; /**< Role (UAS or UAC) */
+ pjsip_method method; /**< The method. */
+ int cseq; /**< The CSeq */
+ pj_str_t transaction_key;/**< hash table key. */
+ pj_str_t branch; /**< The branch Id. */
+
+ /*
+ * State and status.
+ */
+ int status_code; /**< Last status code seen. */
+ pjsip_tsx_state_e state; /**< State. */
+ int handle_ack; /**< Should we handle ACK? */
+
+ /** Handler according to current state. */
+ pj_status_t (*state_handler)(struct pjsip_transaction *, pjsip_event *); +
+ /*
+ * Transport.
+ */ + pjsip_tsx_transport_state_e transport_state;/**< Transport's state. */
+ pjsip_host_port dest_name; /**< Destination address. */
+ pjsip_server_addresses remote_addr; /**< Addresses resolved. */
+ int current_addr; /**< Address currently used. */
+
+ pjsip_transport_t *transport; /**< Transport to use. */ +
+ /*
+ * Messages and timer.
+ */
+ pjsip_tx_data *last_tx; /**< Msg kept for retrans. */
+ int has_unsent_msg; /**< Non-zero if tsx need to
+ transmit msg once resolver
+ completes. */
+ int retransmit_count;/**< Retransmission count. */ + pj_timer_entry retransmit_timer;/**< Retransmit timer. */
+ pj_timer_entry timeout_timer; /**< Timeout timer. */
+
+ /** Module specific data. */ void *module_data[PJSIP_MAX_MODULE]; }; /** - * Init transaction as UAC. - * @param tsx the transaction. - * @param tdata the transmit data. - * @return PJ_SUCCESS if successfull. + * Init transaction as UAC from the specified transmit data (\c tdata).
+ * The transmit data must have a valid \c Request-Line and \c CSeq header.
+ * If \c Route headers are present, it will be used to calculate remote
+ * destination.
+ *
+ * If \c Via header does not exist, it will be created along with a unique
+ * \c branch parameter. If it exists and contains branch parameter, then
+ * the \c branch parameter will be used as is as the transaction key.
+ *
+ * The \c Route headers in the transmit data, if present, are used to
+ * calculate remote destination.
+ *
+ * At the end of the function, the transaction will start resolving the
+ * addresses of remote server to contact. Transport will be acquired as soon
+ * as the resolving job completes.
+ * + * @param tsx The transaction. + * @param tdata The transmit data.
+ * + * @return PJ_SUCCESS if successfull. */ PJ_DECL(pj_status_t) pjsip_tsx_init_uac( pjsip_transaction *tsx, pjsip_tx_data *tdata); /** - * Init transaction as UAS. - * @param tsx the transaction to be initialized. - * @param rdata the received incoming request. + * Init transaction as UAS.
+ * + * @param tsx The transaction to be initialized. + * @param rdata The received incoming request.
+ * * @return PJ_SUCCESS if successfull. */ PJ_DECL(pj_status_t) pjsip_tsx_init_uas( pjsip_transaction *tsx, pjsip_rx_data *rdata); /** - * Process incoming message for this transaction. - * @param tsx the transaction. - * @param rdata the incoming message. + * Process incoming message for this transaction.
+ * + * @param tsx The transaction. + * @param rdata The incoming message. */ PJ_DECL(void) pjsip_tsx_on_rx_msg( pjsip_transaction *tsx, pjsip_rx_data *rdata); /** - * Transmit message with this transaction. - * @param tsx the transaction. - * @param tdata the outgoing message. + * Transmit message with this transaction.
+ * + * @param tsx The transaction. + * @param tdata The outgoing message. */ PJ_DECL(void) pjsip_tsx_on_tx_msg( pjsip_transaction *tsx, pjsip_tx_data *tdata); @@ -133,35 +174,41 @@ PJ_DECL(void) pjsip_tsx_on_tx_msg( pjsip_transaction *tsx, * This operation is only valid if the transaction is configured to handle ACK * (tsx->handle_ack is non-zero). If this attribute is not set, then the * transaction will comply with RFC-3261, i.e. it will set itself to - * TERMINATED state when it receives 2xx/INVITE. - * @param tsx The transaction. - * @param tdata The ACK request. + * TERMINATED state when it receives 2xx/INVITE.
+ * + * @param tsx The transaction. + * @param tdata The ACK request. */ PJ_DECL(void) pjsip_tsx_on_tx_ack( pjsip_transaction *tsx, pjsip_tx_data *tdata); /** - * Forcely terminate transaction. - * @param tsx the transaction. - * @param code the status code to report. + * Force terminate transaction.
+ * + * @param tsx The transaction. + * @param code The status code to report. */ PJ_DECL(void) pjsip_tsx_terminate( pjsip_transaction *tsx, int code ); /** * Create transaction key, which is used to match incoming requests - * or response (retransmissions) against transactions. - * @param pool The pool - * @param key Output key. - * @param role The role of the transaction. - * @param method The method to be put as a key. - * @param rdata The received data to calculate. - */ -PJ_DECL(void) pjsip_tsx_create_key( pj_pool_t *pool, - pj_str_t *key, - pjsip_role_e role, - const pjsip_method *method, - const pjsip_rx_data *rdata ); + * or response (retransmissions) against transactions.
+ * + * @param pool The pool + * @param key Output key. + * @param role The role of the transaction. + * @param method The method to be put as a key. + * @param rdata The received data to calculate.
+ *
+ * @return PJ_SUCCESS or the appropriate error code.
+ */ +PJ_DECL(pj_status_t) pjsip_tsx_create_key( pj_pool_t *pool, + pj_str_t *key, + pjsip_role_e role, + const pjsip_method *method, + const pjsip_rx_data *rdata ); +
/** * @} @@ -183,7 +230,7 @@ PJ_DECL(const char *) pjsip_role_name(pjsip_role_e role); /* Thread Local Storage ID for transaction lock (initialized by endpoint) */ -extern int pjsip_tsx_lock_tls_id; +extern long pjsip_tsx_lock_tls_id; PJ_END_DECL diff --git a/pjsip/include/pjsip/sip_transport.h b/pjsip/include/pjsip/sip_transport.h index 29b5d8d1..dd3baea9 100644 --- a/pjsip/include/pjsip/sip_transport.h +++ b/pjsip/include/pjsip/sip_transport.h @@ -1,5 +1,4 @@ /* $Id$ - * */ #ifndef __PJSIP_SIP_TRANSPORT_H__ #define __PJSIP_SIP_TRANSPORT_H__ @@ -13,6 +12,7 @@ #include <pjsip/sip_parser.h> #include <pj/sock.h> #include <pj/list.h> +#include <pj/ioqueue.h>
PJ_BEGIN_DECL @@ -36,10 +36,13 @@ PJ_BEGIN_DECL */ struct pjsip_rx_data { - PJ_DECL_LIST_MEMBER(struct pjsip_rx_data) + //PJ_DECL_LIST_MEMBER(struct pjsip_rx_data); /** Memory pool for this buffer. */ pj_pool_t *pool; +
+ /** Ioqueue op key. */
+ pj_ioqueue_op_key_t op_key;
/** Time when the message was received. */ pj_time_val timestamp; @@ -73,21 +76,33 @@ struct pjsip_rx_data /** The From header as found in the message. */ pjsip_from_hdr *from; - /** The tag in the From header as found in the message. */ - pj_str_t from_tag; - /** The To header as found in the message. */ pjsip_to_hdr *to; - /** The To tag header as found in the message. */ - pj_str_t to_tag; - /** The topmost Via header as found in the message. */ pjsip_via_hdr *via; /** The CSeq header as found in the message. */ pjsip_cseq_hdr *cseq; - +
+ /** Max forwards header. */
+ pjsip_max_forwards_hdr *max_fwd;
+
+ /** The first route header. */
+ pjsip_route_hdr *route;
+
+ /** The first record-route header. */
+ pjsip_rr_hdr *record_route;
+
+ /** Content-type header. */
+ pjsip_ctype_hdr *ctype;
+
+ /** Content-length header. */
+ pjsip_clen_hdr *clen;
+
+ /** The first Require header. */
+ pjsip_require_hdr *require;
+
/** The list of error generated by the parser when parsing this message. */ pjsip_parser_err_report parse_err; }; @@ -109,7 +124,7 @@ struct pjsip_rx_data */ struct pjsip_tx_data { - PJ_DECL_LIST_MEMBER(struct pjsip_tx_data) + PJ_DECL_LIST_MEMBER(struct pjsip_tx_data); /** Memory pool for this buffer. */ pj_pool_t *pool; @@ -126,6 +141,9 @@ struct pjsip_tx_data /** The transport manager for this buffer. */ pjsip_transport_mgr *mgr; +
+ /** Ioqueue asynchronous operation key. */
+ pj_ioqueue_op_key_t op_key;
/** The message in this buffer. */ pjsip_msg *msg; @@ -355,14 +373,16 @@ pjsip_transport_get_remote_addr( const pjsip_transport_t * tr ); * * @param tr The transport to send the message. * @param tdata The outgoing message buffer. - * @param addr The remote address. + * @param addr The remote address.
+ * @param sent If not null, it will be filled up with the length of
+ * data sent. * - * @return The number of bytes sent, or zero if the connection - * has closed, or -1 on error. + * @return PJ_SUCCESS on success, or the appropriate error code. */ -PJ_DECL(int) pjsip_transport_send_msg( pjsip_transport_t *tr, - pjsip_tx_data *tdata, - const pj_sockaddr_in *addr); +PJ_DECL(pj_status_t) pjsip_transport_send_msg( pjsip_transport_t *tr, + pjsip_tx_data *tdata, + const pj_sockaddr_in *addr,
+ pj_ssize_t *sent); /** @@ -386,7 +406,8 @@ PJ_DECL(int) pjsip_transport_send_msg( pjsip_transport_t *tr, * @param mgr The transport manager. * @return The transmit buffer data, or NULL on error. */ -pjsip_tx_data* pjsip_tx_data_create( pjsip_transport_mgr *mgr ); +pj_status_t pjsip_tx_data_create( pjsip_transport_mgr *mgr,
+ pjsip_tx_data **tdata ); /** diff --git a/pjsip/include/pjsip/sip_types.h b/pjsip/include/pjsip/sip_types.h index 33e8ca03..64f5f3ae 100644 --- a/pjsip/include/pjsip/sip_types.h +++ b/pjsip/include/pjsip/sip_types.h @@ -1,5 +1,4 @@ /* $Id$ - * */ #ifndef __PJSIP_SIP_TYPES_H__ #define __PJSIP_SIP_TYPES_H__ @@ -71,6 +70,11 @@ typedef struct pjsip_rx_data pjsip_rx_data; * Forward declaration for message (sip_msg.h). */ typedef struct pjsip_msg pjsip_msg; +
+/**
+ * Forward declaration for header field (sip_msg.h).
+ */
+typedef struct pjsip_hdr pjsip_hdr;
/** * Forward declaration for URI (sip_uri.h). @@ -132,7 +136,26 @@ typedef struct pjsip_host_port pj_str_t host; /**< Host part. */ int port; /**< Port number. */ } pjsip_host_port; - +
+
+/**
+ * Convert exception ID into pj_status_t status.
+ *
+ * @param exception_id Exception Id.
+ *
+ * @return Error code for the specified exception Id.
+ */
+PJ_DECL(pj_status_t) pjsip_exception_to_status(int exception_id);
+
+/**
+ * Return standard pj_status_t status from current exception.
+ */
+#define PJSIP_RETURN_EXCEPTION() pjsip_exception_to_status(PJ_GET_EXCEPTION())
+
+/**
+ * Attributes to inform that the function may throw exceptions.
+ */
+#define PJSIP_THROW_SPEC(list)
#endif /* __PJSIP_SIP_TYPES_H__ */ diff --git a/pjsip/include/pjsip/sip_uri.h b/pjsip/include/pjsip/sip_uri.h index c43bc3df..8d72d0ae 100644 --- a/pjsip/include/pjsip/sip_uri.h +++ b/pjsip/include/pjsip/sip_uri.h @@ -1,5 +1,4 @@ /* $Id$ - * */ #ifndef __PJSIP_SIP_URI_H__ #define __PJSIP_SIP_URI_H__ diff --git a/pjsip/include/pjsip_core.h b/pjsip/include/pjsip_core.h index acce9cc6..96b39488 100644 --- a/pjsip/include/pjsip_core.h +++ b/pjsip/include/pjsip_core.h @@ -1,5 +1,4 @@ /* $Id$ - * */ #ifndef __PJSIP_CORE_H__ #define __PJSIP_CORE_H__ diff --git a/pjsip/src/pjsip/sip_auth.c b/pjsip/src/pjsip/sip_auth.c index 91e91862..030b4a40 100644 --- a/pjsip/src/pjsip/sip_auth.c +++ b/pjsip/src/pjsip/sip_auth.c @@ -1,15 +1,16 @@ /* $Id$ - * */ #include <pjsip/sip_auth.h> #include <pjsip/sip_auth_parser.h> /* just to get pjsip_DIGEST_STR */ #include <pjsip/sip_transport.h> #include <pjsip/sip_endpoint.h> -#include <pj/md5.h> +#include <pjlib-util/md5.h> #include <pj/log.h> #include <pj/string.h> #include <pj/pool.h> -#include <pj/guid.h> +#include <pj/guid.h>
+#include <pj/assert.h> +#include <pj/ctype.h>
/* Length of digest string. */ #define MD5STRLEN 32 @@ -146,7 +147,7 @@ static pj_bool_t has_auth_qop( pj_pool_t *pool, const pj_str_t *qop_offer) pj_strdup_with_null( pool, &qop, qop_offer); p = qop.ptr; while (*p) { - *p = (char)tolower(*p); + *p = (char)pj_tolower(*p); ++p; } @@ -217,7 +218,7 @@ static pj_status_t respond_digest( pj_pool_t *pool, */ cred->qop = pjsip_AUTH_STR; cred->nc.ptr = pj_pool_alloc(pool, 16); - sprintf(cred->nc.ptr, "%06u", nc); + pj_snprintf(cred->nc.ptr, 16, "%06u", nc); if (cnonce && cnonce->slen) { pj_strdup(pool, &cred->cnonce, cnonce); @@ -484,7 +485,7 @@ PJ_DEF(const pjsip_cred_info*) pjsip_auth_find_cred( unsigned count, const pj_str_t *scheme) { unsigned i; - PJ_UNUSED_ARG(scheme) + PJ_UNUSED_ARG(scheme); for (i=0; i<count; ++i) { if (pj_stricmp(&cred[i].realm, realm) == 0) return &cred[i]; @@ -715,7 +716,7 @@ PJ_DEF(pjsip_tx_data*) pjsip_auth_reinit_req( pjsip_endpoint *endpt, const pjsip_hdr *hdr; pjsip_via_hdr *via; - PJ_UNUSED_ARG(endpt) + PJ_UNUSED_ARG(endpt); pj_assert(rdata->msg->type == PJSIP_RESPONSE_MSG); pj_assert(rdata->msg->line.status.code == 401 || diff --git a/pjsip/src/pjsip/sip_auth_msg.c b/pjsip/src/pjsip/sip_auth_msg.c index a5d52f10..9e88ef4a 100644 --- a/pjsip/src/pjsip/sip_auth_msg.c +++ b/pjsip/src/pjsip/sip_auth_msg.c @@ -1,12 +1,12 @@ /* $Id$ - * */ #include <pjsip/sip_auth_msg.h> #include <pjsip/sip_auth_parser.h> #include <pj/pool.h> #include <pj/list.h> -#include <pj/string.h> -#include <pjsip/print.h> +#include <pj/string.h>
+#include <pj/assert.h> +#include <pjsip/print_util.h> /////////////////////////////////////////////////////////////////////////////// /* @@ -67,9 +67,9 @@ static int print_digest_credential(pjsip_digest_credential *cred, char *buf, pj_ static int print_pgp_credential(pjsip_pgp_credential *cred, char *buf, pj_size_t size) { - PJ_UNUSED_ARG(cred) - PJ_UNUSED_ARG(buf) - PJ_UNUSED_ARG(size) + PJ_UNUSED_ARG(cred); + PJ_UNUSED_ARG(buf); + PJ_UNUSED_ARG(size); return -1; } @@ -212,9 +212,9 @@ static int print_digest_challenge( pjsip_digest_challenge *chal, static int print_pgp_challenge( pjsip_pgp_challenge *chal, char *buf, pj_size_t size) { - PJ_UNUSED_ARG(chal) - PJ_UNUSED_ARG(buf) - PJ_UNUSED_ARG(size) + PJ_UNUSED_ARG(chal); + PJ_UNUSED_ARG(buf); + PJ_UNUSED_ARG(size); return -1; } diff --git a/pjsip/src/pjsip/sip_auth_parser.c b/pjsip/src/pjsip/sip_auth_parser.c index 2f5a3baf..5e121b50 100644 --- a/pjsip/src/pjsip/sip_auth_parser.c +++ b/pjsip/src/pjsip/sip_auth_parser.c @@ -1,21 +1,25 @@ /* $Id$ - * */ #include <pjsip/sip_auth_parser.h> #include <pjsip/sip_auth_msg.h> -#include <pjsip/sip_parser.h> +#include <pjsip/sip_parser.h>
+#include <pj/assert.h> #include <pj/string.h> #include <pj/except.h> -static pjsip_authorization_hdr* parse_hdr_authorization( pj_scanner *scanner, pj_pool_t *pool); -static pjsip_proxy_authorization_hdr* parse_hdr_proxy_authorization( pj_scanner *scanner, pj_pool_t *pool); -static pjsip_www_authenticate_hdr* parse_hdr_www_authenticate( pj_scanner *scanner, pj_pool_t *pool); -static pjsip_proxy_authenticate_hdr* parse_hdr_proxy_authenticate( pj_scanner *scanner, pj_pool_t *pool); +static pjsip_hdr* parse_hdr_authorization ( pjsip_parse_ctx *ctx ); +static pjsip_hdr* parse_hdr_proxy_authorization ( pjsip_parse_ctx *ctx ); +static pjsip_hdr* parse_hdr_www_authenticate ( pjsip_parse_ctx *ctx ); +static pjsip_hdr* parse_hdr_proxy_authenticate ( pjsip_parse_ctx *ctx ); -static void parse_digest_credential( pj_scanner *scanner, pj_pool_t *pool, pjsip_digest_credential *cred); -static void parse_pgp_credential( pj_scanner *scanner, pj_pool_t *pool, pjsip_pgp_credential *cred); -static void parse_digest_challenge( pj_scanner *scanner, pj_pool_t *pool, pjsip_digest_challenge *chal); -static void parse_pgp_challenge( pj_scanner *scanner, pj_pool_t *pool, pjsip_pgp_challenge *chal); +static void parse_digest_credential ( pj_scanner *scanner, pj_pool_t *pool,
+ pjsip_digest_credential *cred); +static void parse_pgp_credential ( pj_scanner *scanner, pj_pool_t *pool,
+ pjsip_pgp_credential *cred); +static void parse_digest_challenge ( pj_scanner *scanner, pj_pool_t *pool,
+ pjsip_digest_challenge *chal); +static void parse_pgp_challenge ( pj_scanner *scanner, pj_pool_t *pool,
+ pjsip_pgp_challenge *chal); const pj_str_t pjsip_USERNAME_STR = { "username", 8 }, pjsip_REALM_STR = { "realm", 5}, @@ -43,12 +47,13 @@ const pj_str_t pjsip_USERNAME_STR = { "username", 8 }, pjsip_QUOTED_AUTH_STR = { "\"auth\"", 6 }; -static void parse_digest_credential( pj_scanner *scanner, pj_pool_t *pool, pjsip_digest_credential *cred) +static void parse_digest_credential( pj_scanner *scanner, pj_pool_t *pool,
+ pjsip_digest_credential *cred) { for (;;) { pj_str_t name, value; - pjsip_parse_param_imp(scanner, &name, &value, PJSIP_PARSE_REMOVE_QUOTE); + pjsip_parse_param_imp(scanner, &name, &value,PJSIP_PARSE_REMOVE_QUOTE); if (!pj_stricmp(&name, &pjsip_USERNAME_STR)) { cred->username = value; @@ -81,32 +86,34 @@ static void parse_digest_credential( pj_scanner *scanner, pj_pool_t *pool, pjsip cred->nc = value; } else { - pjsip_concat_param_imp(&cred->other_param, pool, &name, &value, ','); + pjsip_concat_param_imp(&cred->other_param,pool,&name,&value, ','); } /* Eat comma */ - if (!pj_scan_is_eof(scanner) && *scanner->current == ',') + if (!pj_scan_is_eof(scanner) && *scanner->curptr == ',') pj_scan_get_char(scanner); else break; } } -static void parse_pgp_credential( pj_scanner *scanner, pj_pool_t *pool, pjsip_pgp_credential *cred) +static void parse_pgp_credential( pj_scanner *scanner, pj_pool_t *pool,
+ pjsip_pgp_credential *cred) { - PJ_UNUSED_ARG(scanner) - PJ_UNUSED_ARG(pool) - PJ_UNUSED_ARG(cred) + PJ_UNUSED_ARG(scanner); + PJ_UNUSED_ARG(pool); + PJ_UNUSED_ARG(cred); PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); } -static void parse_digest_challenge( pj_scanner *scanner, pj_pool_t *pool, pjsip_digest_challenge *chal) +static void parse_digest_challenge( pj_scanner *scanner, pj_pool_t *pool,
+ pjsip_digest_challenge *chal) { for (;;) { pj_str_t name, value; - pjsip_parse_param_imp(scanner, &name, &value, PJSIP_PARSE_REMOVE_QUOTE); + pjsip_parse_param_imp(scanner, &name, &value,PJSIP_PARSE_REMOVE_QUOTE); if (!pj_stricmp(&name, &pjsip_REALM_STR)) { chal->realm = value; @@ -121,8 +128,11 @@ static void parse_digest_challenge( pj_scanner *scanner, pj_pool_t *pool, pjsip_ chal->opaque = value; } else if (!pj_stricmp(&name, &pjsip_STALE_STR)) { - if (!pj_stricmp(&value, &pjsip_TRUE_STR) || !pj_stricmp(&value, &pjsip_QUOTED_TRUE_STR)) - chal->stale = 1; + if (!pj_stricmp(&value, &pjsip_TRUE_STR) ||
+ !pj_stricmp(&value, &pjsip_QUOTED_TRUE_STR))
+ { + chal->stale = 1;
+ } } else if (!pj_stricmp(&name, &pjsip_ALGORITHM_STR)) { chal->algorithm = value; @@ -132,35 +142,37 @@ static void parse_digest_challenge( pj_scanner *scanner, pj_pool_t *pool, pjsip_ chal->qop = value; } else { - pjsip_concat_param_imp(&chal->other_param, pool, &name, &value, ','); + pjsip_concat_param_imp(&chal->other_param, pool,
+ &name, &value, ','); } /* Eat comma */ - if (!pj_scan_is_eof(scanner) && *scanner->current == ',') + if (!pj_scan_is_eof(scanner) && *scanner->curptr == ',') pj_scan_get_char(scanner); else break; } } -static void parse_pgp_challenge( pj_scanner *scanner, pj_pool_t *pool, pjsip_pgp_challenge *chal) +static void parse_pgp_challenge( pj_scanner *scanner, pj_pool_t *pool,
+ pjsip_pgp_challenge *chal) { - PJ_UNUSED_ARG(scanner) - PJ_UNUSED_ARG(pool) - PJ_UNUSED_ARG(chal) + PJ_UNUSED_ARG(scanner); + PJ_UNUSED_ARG(pool); + PJ_UNUSED_ARG(chal); PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); } -static void int_parse_hdr_authorization( pj_scanner *scanner, pj_pool_t *pool, +static void int_parse_hdr_authorization( pj_scanner *scanner, pj_pool_t *pool, pjsip_authorization_hdr *hdr) { - if (*scanner->current == '"') { + if (*scanner->curptr == '"') { pj_scan_get_quote(scanner, '"', '"', &hdr->scheme); hdr->scheme.ptr++; hdr->scheme.slen -= 2; } else { - pj_scan_get(scanner, pjsip_TOKEN_SPEC, &hdr->scheme); + pj_scan_get(scanner, &pjsip_TOKEN_SPEC, &hdr->scheme); } if (!pj_stricmp(&hdr->scheme, &pjsip_DIGEST_STR)) { @@ -181,12 +193,12 @@ static void int_parse_hdr_authorization( pj_scanner *scanner, pj_pool_t *pool, static void int_parse_hdr_authenticate( pj_scanner *scanner, pj_pool_t *pool, pjsip_www_authenticate_hdr *hdr) { - if (*scanner->current == '"') { + if (*scanner->curptr == '"') { pj_scan_get_quote(scanner, '"', '"', &hdr->scheme); hdr->scheme.ptr++; hdr->scheme.slen -= 2; } else { - pj_scan_get(scanner, pjsip_TOKEN_SPEC, &hdr->scheme); + pj_scan_get(scanner, &pjsip_TOKEN_SPEC, &hdr->scheme); } if (!pj_stricmp(&hdr->scheme, &pjsip_DIGEST_STR)) { @@ -205,41 +217,56 @@ static void int_parse_hdr_authenticate( pj_scanner *scanner, pj_pool_t *pool, } -static pjsip_authorization_hdr *parse_hdr_authorization( pj_scanner *scanner, pj_pool_t *pool) +static pjsip_hdr* parse_hdr_authorization( pjsip_parse_ctx *ctx ) { - pjsip_authorization_hdr *hdr = pjsip_authorization_hdr_create(pool); - int_parse_hdr_authorization(scanner, pool, hdr); - return hdr; + pjsip_authorization_hdr *hdr = pjsip_authorization_hdr_create(ctx->pool); + int_parse_hdr_authorization(ctx->scanner, ctx->pool, hdr); + return (pjsip_hdr*)hdr; } -static pjsip_proxy_authorization_hdr *parse_hdr_proxy_authorization( pj_scanner *scanner, pj_pool_t *pool) +static pjsip_hdr* parse_hdr_proxy_authorization( pjsip_parse_ctx *ctx ) { - pjsip_proxy_authorization_hdr *hdr = pjsip_proxy_authorization_hdr_create(pool); - int_parse_hdr_authorization(scanner, pool, hdr); - return hdr; + pjsip_proxy_authorization_hdr *hdr =
+ pjsip_proxy_authorization_hdr_create(ctx->pool); + int_parse_hdr_authorization(ctx->scanner, ctx->pool, hdr); + return (pjsip_hdr*)hdr; } -static pjsip_www_authenticate_hdr *parse_hdr_www_authenticate( pj_scanner *scanner, pj_pool_t *pool) +static pjsip_hdr* parse_hdr_www_authenticate( pjsip_parse_ctx *ctx ) { - pjsip_www_authenticate_hdr *hdr = pjsip_www_authenticate_hdr_create(pool); - int_parse_hdr_authenticate(scanner, pool, hdr); - return hdr; + pjsip_www_authenticate_hdr *hdr =
+ pjsip_www_authenticate_hdr_create(ctx->pool); + int_parse_hdr_authenticate(ctx->scanner, ctx->pool, hdr); + return (pjsip_hdr*)hdr; } -static pjsip_proxy_authenticate_hdr *parse_hdr_proxy_authenticate( pj_scanner *scanner, pj_pool_t *pool) +static pjsip_hdr* parse_hdr_proxy_authenticate( pjsip_parse_ctx *ctx ) { - pjsip_proxy_authenticate_hdr *hdr = pjsip_proxy_authenticate_hdr_create(pool); - int_parse_hdr_authenticate(scanner, pool, hdr); - return hdr; + pjsip_proxy_authenticate_hdr *hdr =
+ pjsip_proxy_authenticate_hdr_create(ctx->pool); + int_parse_hdr_authenticate(ctx->scanner, ctx->pool, hdr); + return (pjsip_hdr*)hdr; } -PJ_DEF(void) pjsip_auth_init_parser() -{ - pjsip_register_hdr_parser( "Authorization", NULL, (pjsip_parse_hdr_func*) &parse_hdr_authorization); - pjsip_register_hdr_parser( "Proxy-Authorization", NULL, (pjsip_parse_hdr_func*) &parse_hdr_proxy_authorization); - pjsip_register_hdr_parser( "WWW-Authenticate", NULL, (pjsip_parse_hdr_func*) &parse_hdr_www_authenticate); - pjsip_register_hdr_parser( "Proxy-Authenticate", NULL, (pjsip_parse_hdr_func*) &parse_hdr_proxy_authenticate); +PJ_DEF(pj_status_t) pjsip_auth_init_parser() +{
+ pj_status_t status;
+ + status = pjsip_register_hdr_parser( "Authorization", NULL,
+ &parse_hdr_authorization);
+ PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); + status = pjsip_register_hdr_parser( "Proxy-Authorization", NULL,
+ &parse_hdr_proxy_authorization);
+ PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); + status = pjsip_register_hdr_parser( "WWW-Authenticate", NULL,
+ &parse_hdr_www_authenticate);
+ PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); + status = pjsip_register_hdr_parser( "Proxy-Authenticate", NULL,
+ &parse_hdr_proxy_authenticate);
+ PJ_ASSERT_RETURN(status==PJ_SUCCESS, status);
+
+ return PJ_SUCCESS; } PJ_DEF(void) pjsip_auth_deinit_parser() diff --git a/pjsip/src/pjsip/sip_endpoint.c b/pjsip/src/pjsip/sip_endpoint.c index 321d2e34..49c70b1b 100644 --- a/pjsip/src/pjsip/sip_endpoint.c +++ b/pjsip/src/pjsip/sip_endpoint.c @@ -1,5 +1,4 @@ /* $Id$ - * */ #include <pjsip/sip_endpoint.h> #include <pjsip/sip_transaction.h> @@ -7,17 +6,20 @@ #include <pjsip/sip_event.h> #include <pjsip/sip_resolve.h> #include <pjsip/sip_module.h> -#include <pjsip/sip_misc.h> +#include <pjsip/sip_misc.h>
+#include <pjsip/sip_errno.h> #include <pj/except.h> #include <pj/log.h> #include <pj/string.h> #include <pj/os.h> #include <pj/pool.h> #include <pj/hash.h> +#include <pj/assert.h>
+#include <pj/errno.h>
#define PJSIP_EX_NO_MEMORY PJ_NO_MEMORY_EXCEPTION -#define LOG_THIS "endpoint..." +#define THIS_FILE "endpoint" #define MAX_METHODS 32 @@ -84,7 +86,8 @@ static void endpt_transport_callback( pjsip_endpoint *, pjsip_rx_data *rdata ); * Create transaction. * Defined in sip_transaction.c */ -pjsip_transaction * pjsip_tsx_create( pj_pool_t *pool, pjsip_endpoint *endpt); +pj_status_t pjsip_tsx_create( pj_pool_t *pool, pjsip_endpoint *endpt,
+ pjsip_transaction **tsx ); /* * This is the global handler for memory allocation failure, for pools that @@ -94,8 +97,8 @@ pjsip_transaction * pjsip_tsx_create( pj_pool_t *pool, pjsip_endpoint *endpt); */ static void pool_callback( pj_pool_t *pool, pj_size_t size ) { - PJ_UNUSED_ARG(pool) - PJ_UNUSED_ARG(size) + PJ_UNUSED_ARG(pool); + PJ_UNUSED_ARG(size); PJ_THROW(PJSIP_EX_NO_MEMORY); } @@ -111,7 +114,7 @@ static pj_status_t init_modules( pjsip_endpoint *endpt ) //pj_str_t str_COMMA = { ", ", 2 }; extern pjsip_module aux_tsx_module; - PJ_LOG(5, (LOG_THIS, "init_modules()")); + PJ_LOG(5, (THIS_FILE, "init_modules()")); /* Load static modules. */ endpt->mod_count = PJSIP_MAX_MODULE; @@ -164,7 +167,7 @@ static pj_status_t init_modules( pjsip_endpoint *endpt ) if (endpt->method_cnt < MAX_METHODS) { endpt->methods[endpt->method_cnt++] = mod->methods[j]; } else { - PJ_LOG(1,(LOG_THIS, "Too many methods")); + PJ_LOG(1,(THIS_FILE, "Too many methods")); return -1; } } @@ -200,7 +203,7 @@ static pj_status_t init_modules( pjsip_endpoint *endpt ) PJ_DEF(void) pjsip_endpt_destroy_tsx( pjsip_endpoint *endpt, pjsip_transaction *tsx) { - PJ_LOG(5, (LOG_THIS, "pjsip_endpt_destroy_tsx(%s)", tsx->obj_name)); + PJ_LOG(5, (THIS_FILE, "pjsip_endpt_destroy_tsx(%s)", tsx->obj_name)); pj_assert(tsx->state == PJSIP_TSX_STATE_DESTROYED); @@ -226,7 +229,7 @@ PJ_DEF(void) pjsip_endpt_destroy_tsx( pjsip_endpoint *endpt, /* Release the pool for the transaction. */ pj_pool_release(tsx->pool); - PJ_LOG(4, (LOG_THIS, "tsx%p destroyed", tsx)); + PJ_LOG(4, (THIS_FILE, "tsx%p destroyed", tsx)); } @@ -247,11 +250,11 @@ static void endpt_do_event( pjsip_endpoint *endpt, pjsip_event *evt) } /* Destroy transaction if it is terminated. */ - if (evt->type == PJSIP_EVENT_TSX_STATE_CHANGED && - evt->obj.tsx->state == PJSIP_TSX_STATE_DESTROYED) + if (evt->type == PJSIP_EVENT_TSX_STATE && + evt->body.tsx_state.tsx->state == PJSIP_TSX_STATE_DESTROYED) { /* No need to lock mutex. Mutex is locked inside the destroy function */ - pjsip_endpt_destroy_tsx( endpt, evt->obj.tsx ); + pjsip_endpt_destroy_tsx( endpt, evt->body.tsx_state.tsx ); } } @@ -260,7 +263,8 @@ static void endpt_do_event( pjsip_endpoint *endpt, pjsip_event *evt) * to be processed later. */ void pjsip_endpt_send_tsx_event( pjsip_endpoint *endpt, pjsip_event *evt ) -{ +{
+ // Need to protect this with try/catch? endpt_do_event(endpt, evt); } @@ -301,7 +305,7 @@ PJ_DEF(pj_status_t) pjsip_endpt_set_proxies( pjsip_endpoint *endpt, hdr = pjsip_parse_hdr(endpt->pool, &str_ROUTE, dup, len, NULL); if (!hdr) { pj_mutex_unlock(endpt->mutex); - PJ_LOG(4,(LOG_THIS, "Invalid URL %s in proxy URL", dup)); + PJ_LOG(4,(THIS_FILE, "Invalid URL %s in proxy URL", dup)); return -1; } @@ -327,21 +331,24 @@ PJ_DEF(const pjsip_route_hdr*) pjsip_endpt_get_routing( pjsip_endpoint *endpt ) /* * Initialize endpoint. */ -PJ_DEF(pjsip_endpoint*) pjsip_endpt_create(pj_pool_factory *pf) +PJ_DEF(pj_status_t) pjsip_endpt_create(pj_pool_factory *pf,
+ pjsip_endpoint **p_endpt) { pj_status_t status; pj_pool_t *pool; pjsip_endpoint *endpt; pjsip_max_forwards_hdr *mf_hdr; - PJ_LOG(5, (LOG_THIS, "pjsip_endpt_create()")); + PJ_LOG(5, (THIS_FILE, "pjsip_endpt_create()")); +
+ *p_endpt = NULL;
/* Create pool */ pool = pj_pool_create(pf, "pept%p", PJSIP_POOL_LEN_ENDPT, PJSIP_POOL_INC_ENDPT, &pool_callback); if (!pool) - return NULL; + return PJ_ENOMEM; /* Create endpoint. */ endpt = pj_pool_calloc(pool, 1, sizeof(*endpt)); @@ -349,53 +356,51 @@ PJ_DEF(pjsip_endpoint*) pjsip_endpt_create(pj_pool_factory *pf) endpt->pf = pf; /* Create mutex for the events, etc. */ - endpt->mutex = pj_mutex_create( endpt->pool, "ept%p", 0 ); - if (!endpt->mutex) { - PJ_LOG(4, (LOG_THIS, "pjsip_endpt_init(): error creating endpoint mutex")); + status = pj_mutex_create_recursive( endpt->pool, "ept%p", &endpt->mutex ); + if (status != PJ_SUCCESS) { goto on_error; } /* Create mutex for the transaction table. */ - endpt->tsx_table_mutex = pj_mutex_create( endpt->pool, "mtbl%p", 0); - if (!endpt->tsx_table_mutex) { - PJ_LOG(4, (LOG_THIS, "pjsip_endpt_init(): error creating endpoint mutex(2)")); + status = pj_mutex_create_recursive( endpt->pool, "mtbl%p",
+ &endpt->tsx_table_mutex); + if (status != PJ_SUCCESS) { goto on_error; } /* Create hash table for transaction. */ endpt->tsx_table = pj_hash_create( endpt->pool, PJSIP_MAX_TSX_COUNT ); if (!endpt->tsx_table) { - PJ_LOG(4, (LOG_THIS, "pjsip_endpt_init(): error creating tsx hash table")); + status = PJ_ENOMEM; goto on_error; } /* Create timer heap to manage all timers within this endpoint. */ - endpt->timer_heap = pj_timer_heap_create( endpt->pool, PJSIP_MAX_TIMER_COUNT, 0); - if (!endpt->timer_heap) { - PJ_LOG(4, (LOG_THIS, "pjsip_endpt_init(): error creating timer heap")); + status = pj_timer_heap_create( endpt->pool, PJSIP_MAX_TIMER_COUNT,
+ &endpt->timer_heap); + if (status != PJ_SUCCESS) { goto on_error; } /* Create transport manager. */ - endpt->transport_mgr = pjsip_transport_mgr_create( endpt->pool, - endpt, - &endpt_transport_callback); - if (!endpt->transport_mgr) { - PJ_LOG(4, (LOG_THIS, "pjsip_endpt_init(): error creating transport mgr")); + status = pjsip_transport_mgr_create( endpt->pool, + endpt, + &endpt_transport_callback,
+ &endpt->transport_mgr); + if (status != PJ_SUCCESS) { goto on_error; } /* Create asynchronous DNS resolver. */ endpt->resolver = pjsip_resolver_create(endpt->pool); if (!endpt->resolver) { - PJ_LOG(4, (LOG_THIS, "pjsip_endpt_init(): error creating resolver")); + PJ_LOG(4, (THIS_FILE, "pjsip_endpt_init(): error creating resolver")); goto on_error; } /* Initialize TLS ID for transaction lock. */ - pjsip_tsx_lock_tls_id = pj_thread_local_alloc(); - if (pjsip_tsx_lock_tls_id == -1) { - PJ_LOG(4, (LOG_THIS, "pjsip_endpt_init(): error allocating TLS")); + status = pj_thread_local_alloc(&pjsip_tsx_lock_tls_id); + if (status != PJ_SUCCESS) { goto on_error; } pj_thread_local_set(pjsip_tsx_lock_tls_id, NULL); @@ -414,12 +419,13 @@ PJ_DEF(pjsip_endpoint*) pjsip_endpt_create(pj_pool_factory *pf) /* Load and init modules. */ status = init_modules(endpt); if (status != PJ_SUCCESS) { - PJ_LOG(4, (LOG_THIS, "pjsip_endpt_init(): error in init_modules()")); - return NULL; + PJ_LOG(4, (THIS_FILE, "pjsip_endpt_init(): error in init_modules()")); + return status; } - /* Done. */ - return endpt; + /* Done. */
+ *p_endpt = endpt; + return status; on_error: if (endpt->transport_mgr) { @@ -436,8 +442,8 @@ on_error: } pj_pool_release( endpt->pool ); - PJ_LOG(4, (LOG_THIS, "pjsip_endpt_init() failed")); - return NULL; + PJ_LOG(4, (THIS_FILE, "pjsip_endpt_init() failed")); + return status; } /* @@ -445,7 +451,7 @@ on_error: */ PJ_DEF(void) pjsip_endpt_destroy(pjsip_endpoint *endpt) { - PJ_LOG(5, (LOG_THIS, "pjsip_endpt_destroy()")); + PJ_LOG(5, (THIS_FILE, "pjsip_endpt_destroy()")); /* Shutdown and destroy all transports. */ pjsip_transport_mgr_destroy(endpt->transport_mgr); @@ -470,7 +476,7 @@ PJ_DEF(pj_pool_t*) pjsip_endpt_create_pool( pjsip_endpoint *endpt, { pj_pool_t *pool; - PJ_LOG(5, (LOG_THIS, "pjsip_endpt_create_pool()")); + PJ_LOG(5, (THIS_FILE, "pjsip_endpt_create_pool()")); /* Lock endpoint mutex. */ pj_mutex_lock(endpt->mutex); @@ -483,9 +489,9 @@ PJ_DEF(pj_pool_t*) pjsip_endpt_create_pool( pjsip_endpoint *endpt, pj_mutex_unlock(endpt->mutex); if (pool) { - PJ_LOG(5, (LOG_THIS, " pool %s created", pj_pool_getobjname(pool))); + PJ_LOG(5, (THIS_FILE, " pool %s created", pj_pool_getobjname(pool))); } else { - PJ_LOG(4, (LOG_THIS, "Unable to create pool %s!", pool_name)); + PJ_LOG(4, (THIS_FILE, "Unable to create pool %s!", pool_name)); } return pool; @@ -497,7 +503,7 @@ PJ_DEF(pj_pool_t*) pjsip_endpt_create_pool( pjsip_endpoint *endpt, */ PJ_DEF(void) pjsip_endpt_destroy_pool( pjsip_endpoint *endpt, pj_pool_t *pool ) { - PJ_LOG(5, (LOG_THIS, "pjsip_endpt_destroy_pool(%s)", pj_pool_getobjname(pool))); + PJ_LOG(5, (THIS_FILE, "pjsip_endpt_destroy_pool(%s)", pj_pool_getobjname(pool))); pj_mutex_lock(endpt->mutex); pj_pool_release( pool ); @@ -513,7 +519,7 @@ PJ_DEF(void) pjsip_endpt_handle_events( pjsip_endpoint *endpt, pj_time_val timeout; int i; - PJ_LOG(5, (LOG_THIS, "pjsip_endpt_handle_events()")); + PJ_LOG(5, (THIS_FILE, "pjsip_endpt_handle_events()")); /* Poll the timer. The timer heap has its own mutex for better * granularity, so we don't need to lock end endpoint. We also keep @@ -543,7 +549,7 @@ PJ_DEF(pj_status_t) pjsip_endpt_schedule_timer( pjsip_endpoint *endpt, pj_timer_entry *entry, const pj_time_val *delay ) { - PJ_LOG(5, (LOG_THIS, "pjsip_endpt_schedule_timer(entry=%p, delay=%u.%u)", + PJ_LOG(5, (THIS_FILE, "pjsip_endpt_schedule_timer(entry=%p, delay=%u.%u)", entry, delay->sec, delay->msec)); return pj_timer_heap_schedule( endpt->timer_heap, entry, delay ); } @@ -554,7 +560,7 @@ PJ_DEF(pj_status_t) pjsip_endpt_schedule_timer( pjsip_endpoint *endpt, PJ_DEF(void) pjsip_endpt_cancel_timer( pjsip_endpoint *endpt, pj_timer_entry *entry ) { - PJ_LOG(5, (LOG_THIS, "pjsip_endpt_cancel_timer(entry=%p)", entry)); + PJ_LOG(5, (THIS_FILE, "pjsip_endpt_cancel_timer(entry=%p)", entry)); pj_timer_heap_cancel( endpt->timer_heap, entry ); } @@ -563,26 +569,24 @@ PJ_DEF(void) pjsip_endpt_cancel_timer( pjsip_endpoint *endpt, * Endpoint must then initialize the new transaction as either UAS or UAC, and * register it to the hash table. */ -PJ_DEF(pjsip_transaction*) pjsip_endpt_create_tsx(pjsip_endpoint *endpt) +PJ_DEF(pj_status_t) pjsip_endpt_create_tsx(pjsip_endpoint *endpt,
+ pjsip_transaction **p_tsx) { pj_pool_t *pool; - pjsip_transaction *tsx; +
+ PJ_ASSERT_RETURN(endpt && p_tsx, PJ_EINVAL);
- PJ_LOG(5, (LOG_THIS, "pjsip_endpt_create_tsx()")); + PJ_LOG(5, (THIS_FILE, "pjsip_endpt_create_tsx()")); /* Request one pool for the transaction. Mutex is locked there. */ pool = pjsip_endpt_create_pool(endpt, "ptsx%p", PJSIP_POOL_LEN_TSX, PJSIP_POOL_INC_TSX); if (pool == NULL) { - PJ_LOG(2, (LOG_THIS, "failed to create transaction (no pool)")); - return NULL; + return PJ_ENOMEM; } /* Create the transaction. */ - tsx = pjsip_tsx_create(pool, endpt); - - /* Return */ - return tsx; + return pjsip_tsx_create(pool, endpt, p_tsx); } /* @@ -594,7 +598,7 @@ PJ_DEF(pjsip_transaction*) pjsip_endpt_create_tsx(pjsip_endpoint *endpt) PJ_DEF(void) pjsip_endpt_register_tsx( pjsip_endpoint *endpt, pjsip_transaction *tsx) { - PJ_LOG(5, (LOG_THIS, "pjsip_endpt_register_tsx(%s)", tsx->obj_name)); + PJ_LOG(5, (THIS_FILE, "pjsip_endpt_register_tsx(%s)", tsx->obj_name)); pj_assert(tsx->transaction_key.slen != 0); //pj_assert(tsx->state != PJSIP_TSX_STATE_NULL); @@ -618,7 +622,7 @@ PJ_DECL(pjsip_transaction*) pjsip_endpt_find_tsx( pjsip_endpoint *endpt, { pjsip_transaction *tsx; - PJ_LOG(5, (LOG_THIS, "pjsip_endpt_find_tsx()")); + PJ_LOG(5, (THIS_FILE, "pjsip_endpt_find_tsx()")); /* Start lock mutex in the endpoint. */ pj_mutex_lock(endpt->tsx_table_mutex); @@ -658,7 +662,7 @@ static void endpt_transport_callback( pjsip_endpoint *endpt, pjsip_transaction *tsx; pj_bool_t a_new_transaction_just_been_created = PJ_FALSE; - PJ_LOG(5, (LOG_THIS, "endpt_transport_callback(rdata=%p)", rdata)); + PJ_LOG(5, (THIS_FILE, "endpt_transport_callback(rdata=%p)", rdata)); /* For response, check that the value in Via sent-by match the transport. * If not matched, silently drop the response. @@ -675,10 +679,10 @@ static void endpt_transport_callback( pjsip_endpoint *endpt, port = pjsip_transport_get_default_port_for_type(type); } addr = pjsip_transport_get_addr_name(rdata->transport); - addr_addr = pj_sockaddr_get_str_addr(addr); + addr_addr = pj_inet_ntoa(addr->sin_addr); if (pj_strcmp2(&rdata->via->sent_by.host, addr_addr) != 0) mismatch = PJ_TRUE; - else if (port != pj_sockaddr_get_port(addr)) { + else if (port != pj_ntohs(addr->sin_port)) { /* Port or address mismatch, we should discard response */ /* But we saw one implementation (we don't want to name it to * protect the innocence) which put wrong sent-by port although @@ -686,10 +690,10 @@ static void endpt_transport_callback( pjsip_endpoint *endpt, * So we discard the response only if the port doesn't match * both the port in sent-by and rport. We try to be lenient here! */ - if (rdata->via->rport_param != pj_sockaddr_get_port(addr)) + if (rdata->via->rport_param != pj_sockaddr_in_get_port(addr)) mismatch = PJ_TRUE; else { - PJ_LOG(4,(LOG_THIS, "Response %p has mismatch port in sent-by" + PJ_LOG(4,(THIS_FILE, "Response %p has mismatch port in sent-by" " but the rport parameter is correct", rdata)); } @@ -698,13 +702,7 @@ static void endpt_transport_callback( pjsip_endpoint *endpt, if (mismatch) { pjsip_event e; - PJ_LOG(3, (LOG_THIS, "Response %p discarded: sent-by mismatch", - rdata)); - - e.type = PJSIP_EVENT_DISCARD_MSG; - e.src_type = PJSIP_EVENT_RX_MSG; - e.src.rdata = rdata; - e.obj.ptr = NULL; + PJSIP_EVENT_INIT_DISCARD_MSG(e, rdata, PJSIP_EINVALIDVIA); endpt_do_event( endpt, &e ); return; } @@ -714,7 +712,7 @@ static void endpt_transport_callback( pjsip_endpoint *endpt, rdata_create_key( rdata); /* Find the transaction for the received message. */ - PJ_LOG(5, (LOG_THIS, "finding tsx with key=%.*s", + PJ_LOG(5, (THIS_FILE, "finding tsx with key=%.*s", rdata->key.slen, rdata->key.ptr)); /* Start lock mutex in the endpoint. */ @@ -747,34 +745,32 @@ static void endpt_transport_callback( pjsip_endpoint *endpt, */ pj_assert(0); - e.type = PJSIP_EVENT_RX_200_RESPONSE; - e.src_type = PJSIP_EVENT_RX_MSG; - e.src.rdata = rdata; - e.obj.ptr = NULL; + PJSIP_EVENT_INIT_RX_200_MSG(e, rdata); endpt_do_event( endpt, &e ); } else { /* Just discard the response, inform TU. */ pjsip_event e; - PJ_LOG(3, (LOG_THIS, "Response %p discarded: transaction not found", - rdata)); - - e.type = PJSIP_EVENT_DISCARD_MSG; - e.src_type = PJSIP_EVENT_RX_MSG; - e.src.rdata = rdata; - e.obj.ptr = NULL; + PJSIP_EVENT_INIT_DISCARD_MSG(e, rdata,
+ PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_CALL_TSX_DOES_NOT_EXIST)); endpt_do_event( endpt, &e ); } /* * For non-ACK request message, create a new transaction. */ - } else if (rdata->msg->line.req.method.id != PJSIP_ACK_METHOD) { + } else if (rdata->msg->line.req.method.id != PJSIP_ACK_METHOD) {
+
+ pj_status_t status;
+ /* Create transaction, mutex is locked there. */ - tsx = pjsip_endpt_create_tsx(endpt); - if (!tsx) - return; + status = pjsip_endpt_create_tsx(endpt, &tsx); + if (status != PJ_SUCCESS) {
+ PJSIP_ENDPT_LOG_ERROR((endpt, THIS_FILE, status,
+ "Unable to create transaction")); + return;
+ } /* Initialize transaction as UAS. */ pjsip_tsx_init_uas( tsx, rdata ); @@ -802,10 +798,7 @@ static void endpt_transport_callback( pjsip_endpoint *endpt, */ pjsip_event event; - event.type = PJSIP_EVENT_RX_ACK_MSG; - event.src_type = PJSIP_EVENT_RX_MSG; - event.src.rdata = rdata; - event.obj.ptr = NULL; + PJSIP_EVENT_INIT_RX_ACK_MSG(event,rdata); endpt_do_event( endpt, &event ); } @@ -833,14 +826,24 @@ static void endpt_transport_callback( pjsip_endpoint *endpt, /* No modules have attached itself to the transaction. * Terminate the transaction with 501/Not Implemented. */ - pjsip_tx_data *tdata; + pjsip_tx_data *tdata;
+ pj_status_t status; if (tsx->method.id == PJSIP_OPTIONS_METHOD) { - tdata = pjsip_endpt_create_response(endpt, rdata, 200); + status = pjsip_endpt_create_response(endpt, rdata, 200,
+ &tdata); } else { - tdata = pjsip_endpt_create_response(endpt, rdata, - PJSIP_SC_METHOD_NOT_ALLOWED); - } + status = pjsip_endpt_create_response(endpt, rdata, + PJSIP_SC_METHOD_NOT_ALLOWED,
+ &tdata); + }
+
+ if (status != PJ_SUCCESS) {
+ PJSIP_ENDPT_LOG_ERROR((endpt, THIS_FILE, status,
+ "Unable to create response"));
+ return;
+ }
+ if (endpt->allow_hdr) { pjsip_msg_add_hdr( tdata->msg, pjsip_hdr_shallow_clone(tdata->pool, endpt->allow_hdr)); @@ -854,8 +857,16 @@ static void endpt_transport_callback( pjsip_endpoint *endpt, * respond to the request at all. We terminate the request here * with 500/Internal Server Error, to be safe. */ - pjsip_tx_data *tdata; - tdata = pjsip_endpt_create_response(endpt, rdata, 500); + pjsip_tx_data *tdata;
+ pj_status_t status;
+ + status = pjsip_endpt_create_response(endpt, rdata, 500, &tdata);
+ if (status != PJ_SUCCESS) {
+ PJSIP_ENDPT_LOG_ERROR((endpt, THIS_FILE, status,
+ "Unable to create response"));
+ return;
+ }
+ pjsip_tsx_on_tx_msg(tsx, tdata); } } @@ -864,10 +875,11 @@ static void endpt_transport_callback( pjsip_endpoint *endpt, /* * Create transmit data buffer. */ -PJ_DEF(pjsip_tx_data*) pjsip_endpt_create_tdata( pjsip_endpoint *endpt ) +PJ_DEF(pj_status_t) pjsip_endpt_create_tdata( pjsip_endpoint *endpt,
+ pjsip_tx_data **p_tdata)
{ - PJ_LOG(5, (LOG_THIS, "pjsip_endpt_create_tdata()")); - return pjsip_tx_data_create(endpt->transport_mgr); + PJ_LOG(5, (THIS_FILE, "pjsip_endpt_create_tdata()")); + return pjsip_tx_data_create(endpt->transport_mgr, p_tdata); } /* @@ -879,7 +891,7 @@ PJ_DEF(void) pjsip_endpt_resolve( pjsip_endpoint *endpt, void *token, pjsip_resolver_callback *cb) { - PJ_LOG(5, (LOG_THIS, "pjsip_endpt_resolve()")); + PJ_LOG(5, (THIS_FILE, "pjsip_endpt_resolve()")); pjsip_resolve( endpt->resolver, pool, target, token, cb); } @@ -893,7 +905,7 @@ PJ_DEF(void) pjsip_endpt_get_transport( pjsip_endpoint *endpt, void *token, pjsip_transport_completion_callback *cb) { - PJ_LOG(5, (LOG_THIS, "pjsip_endpt_get_transport()")); + PJ_LOG(5, (THIS_FILE, "pjsip_endpt_get_transport()")); pjsip_transport_get( endpt->transport_mgr, pool, type, remote, token, cb); } @@ -904,7 +916,7 @@ PJ_DEF(pj_status_t) pjsip_endpt_create_listener( pjsip_endpoint *endpt, pj_sockaddr_in *addr, const pj_sockaddr_in *addr_name) { - PJ_LOG(5, (LOG_THIS, "pjsip_endpt_create_listener()")); + PJ_LOG(5, (THIS_FILE, "pjsip_endpt_create_listener()")); return pjsip_create_listener( endpt->transport_mgr, type, addr, addr_name ); } @@ -912,7 +924,7 @@ PJ_DEF(pj_status_t) pjsip_endpt_create_udp_listener( pjsip_endpoint *endpt, pj_sock_t sock, const pj_sockaddr_in *addr_name) { - PJ_LOG(5, (LOG_THIS, "pjsip_endpt_create_udp_listener()")); + PJ_LOG(5, (THIS_FILE, "pjsip_endpt_create_udp_listener()")); return pjsip_create_udp_listener( endpt->transport_mgr, sock, addr_name ); } @@ -923,31 +935,31 @@ PJ_DEF(void) pjsip_endpt_dump( pjsip_endpoint *endpt, pj_bool_t detail ) pj_hash_iterator_t itr_val; pj_hash_iterator_t *itr; - PJ_LOG(5, (LOG_THIS, "pjsip_endpt_dump()")); + PJ_LOG(5, (THIS_FILE, "pjsip_endpt_dump()")); /* Lock mutex. */ pj_mutex_lock(endpt->mutex); - PJ_LOG(3, (LOG_THIS, "Dumping endpoint %p:", endpt)); + PJ_LOG(3, (THIS_FILE, "Dumping endpoint %p:", endpt)); /* Dumping pool factory. */ (*endpt->pf->dump_status)(endpt->pf, detail); /* Pool health. */ - PJ_LOG(3, (LOG_THIS," Endpoint pool capacity=%u, used_size=%u", + PJ_LOG(3, (THIS_FILE," Endpoint pool capacity=%u, used_size=%u", pj_pool_get_capacity(endpt->pool), pj_pool_get_used_size(endpt->pool))); /* Transaction tables. */ count = pj_hash_count(endpt->tsx_table); - PJ_LOG(3, (LOG_THIS, " Number of transactions: %u", count)); + PJ_LOG(3, (THIS_FILE, " Number of transactions: %u", count)); if (count && detail) { pj_hash_iterator_t it_val; pj_hash_iterator_t *it; pj_time_val now; - PJ_LOG(3, (LOG_THIS, " Dumping transaction tables:")); + PJ_LOG(3, (THIS_FILE, " Dumping transaction tables:")); pj_gettimeofday(&now); it = pj_hash_first(endpt->tsx_table, &it_val); @@ -974,7 +986,7 @@ PJ_DEF(void) pjsip_endpt_dump( pjsip_endpoint *endpt, pj_bool_t detail ) timeout_diff = -1; } - PJ_LOG(3, (LOG_THIS, " %s %s %10.*s %.9u %s t=%ds", + PJ_LOG(3, (THIS_FILE, " %s %s %10.*s %.9u %s t=%ds", tsx->obj_name, role, tsx->method.name.slen, tsx->method.name.ptr, tsx->cseq, @@ -991,7 +1003,7 @@ PJ_DEF(void) pjsip_endpt_dump( pjsip_endpoint *endpt, pj_bool_t detail ) */ itr = pjsip_transport_first( endpt->transport_mgr, &itr_val ); if (itr) { - PJ_LOG(3, (LOG_THIS, " Dumping transports:")); + PJ_LOG(3, (THIS_FILE, " Dumping transports:")); do { char src_addr[128], dst_addr[128]; @@ -1001,14 +1013,14 @@ PJ_DEF(void) pjsip_endpt_dump( pjsip_endpoint *endpt, pj_bool_t detail ) t = pjsip_transport_this(endpt->transport_mgr, itr); addr = pjsip_transport_get_local_addr(t); - strcpy(src_addr, pj_sockaddr_get_str_addr(addr)); - src_port = pj_sockaddr_get_port(addr); + pj_native_strcpy(src_addr, pj_inet_ntoa(addr->sin_addr)); + src_port = pj_ntohs(addr->sin_port); addr = pjsip_transport_get_remote_addr(t); - strcpy(dst_addr, pj_sockaddr_get_str_addr(addr)); - dst_port = pj_sockaddr_get_port(addr); + pj_native_strcpy(dst_addr, pj_inet_ntoa(addr->sin_addr)); + dst_port = pj_ntohs(addr->sin_port); - PJ_LOG(3, (LOG_THIS, " %s %s %s:%d --> %s:%d (refcnt=%d)", + PJ_LOG(3, (THIS_FILE, " %s %s %s:%d --> %s:%d (refcnt=%d)", pjsip_transport_get_type_name(t), pjsip_transport_get_obj_name(t), src_addr, src_port, @@ -1020,13 +1032,13 @@ PJ_DEF(void) pjsip_endpt_dump( pjsip_endpoint *endpt, pj_bool_t detail ) } /* Timer. */ - PJ_LOG(3,(LOG_THIS, " Timer heap has %u entries", + PJ_LOG(3,(THIS_FILE, " Timer heap has %u entries", pj_timer_heap_count(endpt->timer_heap))); /* Unlock mutex. */ pj_mutex_unlock(endpt->mutex); #else - PJ_LOG(3,(LOG_THIS, "pjsip_end_dump: can't dump because it's disabled.")); + PJ_LOG(3,(THIS_FILE, "pjsip_end_dump: can't dump because it's disabled.")); #endif } diff --git a/pjsip/src/pjsip/sip_misc.c b/pjsip/src/pjsip/sip_misc.c index 38a2e95c..a9562397 100644 --- a/pjsip/src/pjsip/sip_misc.c +++ b/pjsip/src/pjsip/sip_misc.c @@ -1,5 +1,4 @@ /* $Id$ - * */ #include <pjsip/sip_misc.h> #include <pjsip/sip_transport.h> @@ -13,8 +12,11 @@ #include <pj/guid.h> #include <pj/pool.h> #include <pj/except.h> +#include <pj/rand.h>
+#include <pj/assert.h>
+#include <pj/errno.h>
-#define LOG_THIS "endpoint..." +#define THIS_FILE "endpoint" static const char *event_str[] = { @@ -44,8 +46,8 @@ struct aux_tsx_data static pj_status_t aux_tsx_init( pjsip_endpoint *endpt, struct pjsip_module *mod, pj_uint32_t id ) { - PJ_UNUSED_ARG(endpt) - PJ_UNUSED_ARG(mod) + PJ_UNUSED_ARG(endpt); + PJ_UNUSED_ARG(mod); aux_mod_id = id; return 0; @@ -53,13 +55,16 @@ static pj_status_t aux_tsx_init( pjsip_endpoint *endpt, static void aux_tsx_handler( struct pjsip_module *mod, pjsip_event *event ) { - pjsip_transaction *tsx = event->obj.tsx; + pjsip_transaction *tsx; struct aux_tsx_data *tsx_data; - PJ_UNUSED_ARG(mod) + PJ_UNUSED_ARG(mod); - if (event->type != PJSIP_EVENT_TSX_STATE_CHANGED) - return; + if (event->type != PJSIP_EVENT_TSX_STATE) + return;
+
+ pj_assert(event->body.tsx_state.tsx != NULL);
+ tsx = event->body.tsx_state.tsx; if (tsx == NULL) return; if (tsx->module_data[aux_mod_id] == NULL) @@ -99,9 +104,10 @@ PJ_DEF(pj_status_t) pjsip_endpt_send_request( pjsip_endpoint *endpt, void (*cb)(void*,pjsip_event*)) { pjsip_transaction *tsx; - struct aux_tsx_data *tsx_data; + struct aux_tsx_data *tsx_data;
+ pj_status_t status; - tsx = pjsip_endpt_create_tsx(endpt); + status = pjsip_endpt_create_tsx(endpt, &tsx); if (!tsx) { pjsip_tx_data_dec_ref(tdata); return -1; @@ -134,7 +140,8 @@ PJ_DEF(pj_status_t) pjsip_endpt_send_request( pjsip_endpoint *endpt, * That's why the session will shallow_clone it's headers before calling * this function. */ -static void init_request_throw( pjsip_tx_data *tdata, +static void init_request_throw( pjsip_endpoint *endpt,
+ pjsip_tx_data *tdata, pjsip_method *method, pjsip_uri *param_target, pjsip_from_hdr *param_from, @@ -146,6 +153,7 @@ static void init_request_throw( pjsip_tx_data *tdata, { pjsip_msg *msg; pjsip_msg_body *body; + const pjsip_hdr *endpt_hdr;
/* Create the message. */ msg = tdata->msg = pjsip_msg_create(tdata->pool, PJSIP_REQUEST_MSG); @@ -153,7 +161,15 @@ static void init_request_throw( pjsip_tx_data *tdata, /* Init request URI. */ pj_memcpy(&msg->line.req.method, method, sizeof(*method)); msg->line.req.uri = param_target; - +
+ /* Add additional request headers from endpoint. */
+ endpt_hdr = pjsip_endpt_get_request_headers(endpt)->next;
+ while (endpt_hdr != pjsip_endpt_get_request_headers(endpt)) {
+ pjsip_hdr *hdr = pjsip_hdr_shallow_clone(tdata->pool, endpt_hdr);
+ pjsip_msg_add_hdr( tdata->msg, hdr );
+ endpt_hdr = endpt_hdr->next;
+ }
+
/* Add From header. */ if (param_from->tag.slen == 0) pj_create_unique_string(tdata->pool, ¶m_from->tag); @@ -189,15 +205,16 @@ static void init_request_throw( pjsip_tx_data *tdata, /* * Create arbitrary request. */ -PJ_DEF(pjsip_tx_data*) pjsip_endpt_create_request( pjsip_endpoint *endpt, - const pjsip_method *method, - const pj_str_t *param_target, - const pj_str_t *param_from, - const pj_str_t *param_to, - const pj_str_t *param_contact, - const pj_str_t *param_call_id, - int param_cseq, - const pj_str_t *param_text) +PJ_DEF(pj_status_t) pjsip_endpt_create_request( pjsip_endpoint *endpt, + const pjsip_method *method, + const pj_str_t *param_target, + const pj_str_t *param_from, + const pj_str_t *param_to, + const pj_str_t *param_contact, + const pj_str_t *param_call_id, + int param_cseq, + const pj_str_t *param_text,
+ pjsip_tx_data **p_tdata) { pjsip_uri *target; pjsip_tx_data *tdata; @@ -206,14 +223,15 @@ PJ_DEF(pjsip_tx_data*) pjsip_endpt_create_request( pjsip_endpoint *endpt, pjsip_contact_hdr *contact; pjsip_cseq_hdr *cseq = NULL; /* = NULL, warning in VC6 */ pjsip_cid_hdr *call_id; - pj_str_t tmp; + pj_str_t tmp;
+ pj_status_t status; PJ_USE_EXCEPTION; - PJ_LOG(5,(LOG_THIS, "Entering pjsip_endpt_create_request()")); + PJ_LOG(5,(THIS_FILE, "Entering pjsip_endpt_create_request()")); - tdata = pjsip_endpt_create_tdata(endpt); - if (!tdata) - return NULL; + status = pjsip_endpt_create_tdata(endpt, &tdata); + if (status != PJ_SUCCESS) + return status; /* Init reference counter to 1. */ pjsip_tx_data_add_ref(tdata); @@ -223,7 +241,7 @@ PJ_DEF(pjsip_tx_data*) pjsip_endpt_create_request( pjsip_endpoint *endpt, pj_strdup_with_null(tdata->pool, &tmp, param_target); target = pjsip_parse_uri( tdata->pool, tmp.ptr, tmp.slen, 0); if (target == NULL) { - PJ_LOG(4,(LOG_THIS, "Error creating request: invalid target %s", + PJ_LOG(4,(THIS_FILE, "Error creating request: invalid target %s", tmp.ptr)); goto on_error; } @@ -234,7 +252,7 @@ PJ_DEF(pjsip_tx_data*) pjsip_endpt_create_request( pjsip_endpoint *endpt, from->uri = pjsip_parse_uri( tdata->pool, tmp.ptr, tmp.slen, PJSIP_PARSE_URI_AS_NAMEADDR); if (from->uri == NULL) { - PJ_LOG(4,(LOG_THIS, "Error creating request: invalid 'From' URI '%s'", + PJ_LOG(4,(THIS_FILE, "Error creating request: invalid 'From' URI '%s'", tmp.ptr)); goto on_error; } @@ -246,7 +264,7 @@ PJ_DEF(pjsip_tx_data*) pjsip_endpt_create_request( pjsip_endpoint *endpt, to->uri = pjsip_parse_uri( tdata->pool, tmp.ptr, tmp.slen, PJSIP_PARSE_URI_AS_NAMEADDR); if (to->uri == NULL) { - PJ_LOG(4,(LOG_THIS, "Error creating request: invalid 'To' URI '%s'", + PJ_LOG(4,(THIS_FILE, "Error creating request: invalid 'To' URI '%s'", tmp.ptr)); goto on_error; } @@ -258,7 +276,7 @@ PJ_DEF(pjsip_tx_data*) pjsip_endpt_create_request( pjsip_endpoint *endpt, contact->uri = pjsip_parse_uri( tdata->pool, tmp.ptr, tmp.slen, PJSIP_PARSE_URI_AS_NAMEADDR); if (contact->uri == NULL) { - PJ_LOG(4,(LOG_THIS, + PJ_LOG(4,(THIS_FILE, "Error creating request: invalid 'Contact' URI '%s'", tmp.ptr)); goto on_error; @@ -285,30 +303,30 @@ PJ_DEF(pjsip_tx_data*) pjsip_endpt_create_request( pjsip_endpoint *endpt, pjsip_method_copy(tdata->pool, &cseq->method, method); /* Create the request. */ - init_request_throw( tdata, &cseq->method, target, from, to, contact, - call_id, cseq, param_text); + init_request_throw( endpt, tdata, &cseq->method, target, from, to,
+ contact, call_id, cseq, param_text); } PJ_DEFAULT { - PJ_LOG(4,(LOG_THIS, "Caught exception %d when creating request", - PJ_GET_EXCEPTION())); + status = PJ_ENOMEM; goto on_error; } PJ_END - PJ_LOG(4,(LOG_THIS, "Request %s (%d %.*s) created.", + PJ_LOG(4,(THIS_FILE, "Request %s (%d %.*s) created.", tdata->obj_name, cseq->cseq, cseq->method.name.slen, cseq->method.name.ptr)); - - return tdata; +
+ *p_tdata = tdata; + return PJ_SUCCESS; on_error: pjsip_tx_data_dec_ref(tdata); - return NULL; + return status; } -PJ_DEF(pjsip_tx_data*) +PJ_DEF(pj_status_t) pjsip_endpt_create_request_from_hdr( pjsip_endpoint *endpt, const pjsip_method *method, const pjsip_uri *param_target, @@ -317,7 +335,8 @@ pjsip_endpt_create_request_from_hdr( pjsip_endpoint *endpt, const pjsip_contact_hdr *param_contact, const pjsip_cid_hdr *param_call_id, int param_cseq, - const pj_str_t *param_text ) + const pj_str_t *param_text,
+ pjsip_tx_data **p_tdata) { pjsip_uri *target; pjsip_tx_data *tdata; @@ -325,14 +344,15 @@ pjsip_endpt_create_request_from_hdr( pjsip_endpoint *endpt, pjsip_to_hdr *to; pjsip_contact_hdr *contact; pjsip_cid_hdr *call_id; - pjsip_cseq_hdr *cseq = NULL; /* The NULL because warning in VC6 */ + pjsip_cseq_hdr *cseq = NULL; /* The NULL because warning in VC6 */
+ pj_status_t status; PJ_USE_EXCEPTION; - PJ_LOG(5,(LOG_THIS, "Entering pjsip_endpt_create_request_from_hdr()")); + PJ_LOG(5,(THIS_FILE, "Entering pjsip_endpt_create_request_from_hdr()")); - tdata = pjsip_endpt_create_tdata(endpt); - if (!tdata) - return NULL; + status = pjsip_endpt_create_tdata(endpt, &tdata); + if (status != PJ_SUCCESS) + return status; pjsip_tx_data_add_ref(tdata); @@ -354,53 +374,56 @@ pjsip_endpt_create_request_from_hdr( pjsip_endpoint *endpt, cseq->cseq = pj_rand() % 0xFFFF; pjsip_method_copy(tdata->pool, &cseq->method, method); - init_request_throw(tdata, &cseq->method, target, from, to, contact, - call_id, cseq, param_text); + init_request_throw(endpt, tdata, &cseq->method, target, from, to,
+ contact, call_id, cseq, param_text); } PJ_DEFAULT { - PJ_LOG(4,(LOG_THIS, "Caught exception %d when creating request", - PJ_GET_EXCEPTION())); + status = PJ_ENOMEM; goto on_error; } PJ_END; - PJ_LOG(4,(LOG_THIS, "Request %s (%d %.*s) created.", + PJ_LOG(4,(THIS_FILE, "Request %s (%d %.*s) created.", tdata->obj_name, cseq->cseq, cseq->method.name.slen, - cseq->method.name.ptr)); - return tdata; + cseq->method.name.ptr));
+
+ *p_tdata = tdata; + return PJ_SUCCESS; on_error: pjsip_tx_data_dec_ref(tdata); - return NULL; + return status; } /* * Construct a minimal response message for the received request. */ -PJ_DEF(pjsip_tx_data*) pjsip_endpt_create_response( pjsip_endpoint *endpt, - const pjsip_rx_data *rdata, - int code) +PJ_DEF(pj_status_t) pjsip_endpt_create_response( pjsip_endpoint *endpt, + const pjsip_rx_data *rdata, + int code,
+ pjsip_tx_data **p_tdata) { pjsip_tx_data *tdata; pjsip_msg *msg, *req_msg; pjsip_hdr *hdr; pjsip_via_hdr *via; - pjsip_rr_hdr *rr; + pjsip_rr_hdr *rr;
+ pj_status_t status; /* rdata must be a request message. */ req_msg = rdata->msg; pj_assert(req_msg->type == PJSIP_REQUEST_MSG); /* Log this action. */ - PJ_LOG(5,(LOG_THIS, "pjsip_endpt_create_response(rdata=%p, code=%d)", + PJ_LOG(5,(THIS_FILE, "pjsip_endpt_create_response(rdata=%p, code=%d)", rdata, code)); /* Create a new transmit buffer. */ - tdata = pjsip_endpt_create_tdata( endpt ); - if (!tdata) - return NULL; + status = pjsip_endpt_create_tdata( endpt, &tdata); + if (status != PJ_SUCCESS) + return status; /* Create new response message. */ tdata->msg = msg = pjsip_msg_create(tdata->pool, PJSIP_RESPONSE_MSG); @@ -450,8 +473,9 @@ PJ_DEF(pjsip_tx_data*) pjsip_endpt_create_response( pjsip_endpoint *endpt, hdr = pjsip_hdr_clone(tdata->pool, rdata->cseq); pjsip_msg_add_hdr( msg, hdr); - /* All done. */ - return tdata; + /* All done. */
+ *p_tdata = tdata; + return PJ_SUCCESS; } @@ -478,7 +502,7 @@ PJ_DEF(void) pjsip_endpt_create_ack(pjsip_endpoint *endpt, rdata->msg->line.status.code >= 300); /* Log this action. */ - PJ_LOG(5,(LOG_THIS, "pjsip_endpt_create_ack(rdata=%p)", rdata)); + PJ_LOG(5,(THIS_FILE, "pjsip_endpt_create_ack(rdata=%p)", rdata)); /* Create new request message. */ ack_msg = pjsip_msg_create(tdata->pool, PJSIP_REQUEST_MSG); @@ -502,7 +526,7 @@ PJ_DEF(void) pjsip_endpt_create_ack(pjsip_endpoint *endpt, /* Copy To header from the original INVITE. */ to = (pjsip_to_hdr*)pjsip_msg_find_remove_hdr( invite_msg, PJSIP_H_TO, NULL); - pj_strdup(tdata->pool, &to->tag, &rdata->to_tag); + pj_strdup(tdata->pool, &to->tag, &rdata->to->tag); pjsip_msg_add_hdr( ack_msg, (pjsip_hdr*)to ); /* Must contain single Via, just as the original INVITE. */ @@ -542,30 +566,33 @@ PJ_DEF(void) pjsip_endpt_create_ack(pjsip_endpoint *endpt, * Construct CANCEL request for the previously sent request, according to * chapter 9.1 of RFC3261. */ -PJ_DEF(pjsip_tx_data*) pjsip_endpt_create_cancel( pjsip_endpoint *endpt, - pjsip_tx_data *req_tdata ) +PJ_DEF(pj_status_t) pjsip_endpt_create_cancel( pjsip_endpoint *endpt, + pjsip_tx_data *req_tdata,
+ pjsip_tx_data **p_tdata) { pjsip_msg *req_msg; /* the original request. */ pjsip_tx_data *cancel_tdata; pjsip_msg *cancel_msg; pjsip_hdr *hdr; pjsip_cseq_hdr *req_cseq, *cseq; - pjsip_uri *req_uri; + pjsip_uri *req_uri;
+ pj_status_t status; /* Log this action. */ - PJ_LOG(5,(LOG_THIS, "pjsip_endpt_create_cancel(tdata=%p)", req_tdata)); + PJ_LOG(5,(THIS_FILE, "pjsip_endpt_create_cancel(tdata=%p)", req_tdata)); /* Get the original request. */ req_msg = req_tdata->msg; /* The transmit buffer must INVITE request. */ - pj_assert(req_msg->type == PJSIP_REQUEST_MSG && - req_msg->line.req.method.id == PJSIP_INVITE_METHOD ); + PJ_ASSERT_RETURN(req_msg->type == PJSIP_REQUEST_MSG && + req_msg->line.req.method.id == PJSIP_INVITE_METHOD,
+ PJ_EINVAL); /* Create new transmit buffer. */ - cancel_tdata = pjsip_endpt_create_tdata( endpt ); - if (!cancel_tdata) { - return NULL; + status = pjsip_endpt_create_tdata( endpt, &cancel_tdata); + if (status != PJ_SUCCESS) { + return status; } /* Create CANCEL request message. */ @@ -622,8 +649,9 @@ PJ_DEF(pjsip_tx_data*) pjsip_endpt_create_cancel( pjsip_endpoint *endpt, /* Done. * Return the transmit buffer containing the CANCEL request. - */ - return cancel_tdata; + */
+ *p_tdata = cancel_tdata; + return PJ_SUCCESS; } /* Get the address parameters (host, port, flag, TTL, etc) to send the @@ -650,8 +678,8 @@ PJ_DEF(pj_status_t) pjsip_get_response_addr(pj_pool_t *pool, const pj_sockaddr_in *remote_addr; remote_addr = pjsip_transport_get_remote_addr(req_transport); pj_strdup2(pool, &send_addr->host, - pj_sockaddr_get_str_addr(remote_addr)); - send_addr->port = pj_sockaddr_get_port(remote_addr); + pj_inet_ntoa(remote_addr->sin_addr)); + send_addr->port = pj_sockaddr_in_get_port(remote_addr); } else { /* Set the host part */ diff --git a/pjsip/src/pjsip/sip_msg.c b/pjsip/src/pjsip/sip_msg.c index fff7bacc..587df864 100644 --- a/pjsip/src/pjsip/sip_msg.c +++ b/pjsip/src/pjsip/sip_msg.c @@ -1,8 +1,7 @@ /* $Id$ - * */ #include <pjsip/sip_msg.h> -#include <pjsip/print.h> +#include <pjsip/print_util.h> #include <pj/string.h> #include <pj/pool.h> @@ -264,7 +263,7 @@ PJ_DEF(void*) pjsip_msg_find_remove_hdr( pjsip_msg *msg, return hdr; } -PJ_DEF(int) pjsip_msg_print( pjsip_msg *msg, char *buf, pj_size_t size) +PJ_DEF(pj_ssize_t) pjsip_msg_print( pjsip_msg *msg, char *buf, pj_size_t size) { char *p=buf, *end=buf+size; int len; diff --git a/pjsip/src/pjsip/sip_parser.c b/pjsip/src/pjsip/sip_parser.c index 4d439120..63cc3b53 100644 --- a/pjsip/src/pjsip/sip_parser.c +++ b/pjsip/src/pjsip/sip_parser.c @@ -1,25 +1,28 @@ /* $Id$ - * */ #include <pjsip/sip_parser.h> #include <pjsip/sip_uri.h> #include <pjsip/sip_msg.h> -#include <pjsip/sip_auth_parser.h> -#include <pj/scanner.h> +#include <pjsip/sip_auth_parser.h>
+#include <pjsip/sip_errno.h>
+#include <pjsip/sip_transport.h> /* rdata structure */ +#include <pjlib-util/scanner.h> #include <pj/except.h> #include <pj/log.h> #include <pj/hash.h> #include <pj/os.h> #include <pj/pool.h> #include <pj/string.h> -#include <ctype.h> /* tolower() */ +#include <pj/ctype.h> +#include <pj/assert.h>
#define RESERVED ";/?:@&=+$," #define MARK "-_.!~*'()" #define ESCAPED "%" #define USER "&=+$,;?/" #define PASS "&=+$," -#define TOKEN "-.!%*_=`'~+" /* '+' is because of application/pidf+xml in Content-Type! */ +#define TOKEN "-.!%*_=`'~+" /* '+' is because of application/pidf+xml
+ * in Content-Type! */ #define HOST "_-." #define HEX_DIGIT "abcdefABCDEF" #define PARAM_CHAR "[]/:&+$" MARK "%" @@ -45,109 +48,98 @@ static int parser_is_initialized; /* * Global vars (also extern). */ -const pj_str_t pjsip_USER_STR = { "user", 4}; -const pj_str_t pjsip_METHOD_STR = { "method", 6}; +const pj_str_t pjsip_USER_STR = { "user", 4}; +const pj_str_t pjsip_METHOD_STR = { "method", 6}; const pj_str_t pjsip_TRANSPORT_STR = { "transport", 9}; -const pj_str_t pjsip_MADDR_STR = { "maddr", 5 }; -const pj_str_t pjsip_LR_STR = { "lr", 2 }; -const pj_str_t pjsip_SIP_STR = { "sip", 3 }; -const pj_str_t pjsip_SIPS_STR = { "sips", 4 }; -const pj_str_t pjsip_TEL_STR = { "tel", 3 }; -const pj_str_t pjsip_BRANCH_STR = { "branch", 6 }; -const pj_str_t pjsip_TTL_STR = { "ttl", 3 }; -const pj_str_t pjsip_PNAME_STR = { "received", 8 }; -const pj_str_t pjsip_Q_STR = { "q", 1 }; -const pj_str_t pjsip_EXPIRES_STR = { "expires", 7 }; -const pj_str_t pjsip_TAG_STR = { "tag", 3 }; -const pj_str_t pjsip_RPORT_STR = { "rport", 5}; - -pj_char_spec pjsip_HOST_SPEC, /* For scanning host part. */ - pjsip_DIGIT_SPEC, /* Decimal digits */ - pjsip_ALPHA_SPEC, /* Alpha (A-Z, a-z) */ - pjsip_ALNUM_SPEC, /* Decimal + Alpha. */ - pjsip_TOKEN_SPEC, /* Token. */ - pjsip_HEX_SPEC, /* Hexadecimal digits. */ - pjsip_PARAM_CHAR_SPEC, /* For scanning pname (or pvalue when it's not quoted.) */ - pjsip_PROBE_USER_HOST_SPEC, /* Hostname characters. */ - pjsip_PASSWD_SPEC, /* Password. */ - pjsip_USER_SPEC, /* User */ - pjsip_ARRAY_ELEMENTS, /* Array separator. */ - pjsip_NEWLINE_OR_EOF_SPEC, /* For eating up header.*/ - pjsip_DISPLAY_SCAN_SPEC; /* Used when searching for display name in URL. */ +const pj_str_t pjsip_MADDR_STR = { "maddr", 5 }; +const pj_str_t pjsip_LR_STR = { "lr", 2 }; +const pj_str_t pjsip_SIP_STR = { "sip", 3 }; +const pj_str_t pjsip_SIPS_STR = { "sips", 4 }; +const pj_str_t pjsip_TEL_STR = { "tel", 3 }; +const pj_str_t pjsip_BRANCH_STR = { "branch", 6 }; +const pj_str_t pjsip_TTL_STR = { "ttl", 3 }; +const pj_str_t pjsip_PNAME_STR = { "received", 8 }; +const pj_str_t pjsip_Q_STR = { "q", 1 }; +const pj_str_t pjsip_EXPIRES_STR = { "expires", 7 }; +const pj_str_t pjsip_TAG_STR = { "tag", 3 }; +const pj_str_t pjsip_RPORT_STR = { "rport", 5}; +
+/* Character Input Specification buffer. */
+static pj_cis_buf_t cis_buf;
+
+/* Character Input Specifications. */ +pj_cis_t pjsip_HOST_SPEC, /* For scanning host part. */ + pjsip_DIGIT_SPEC, /* Decimal digits */ + pjsip_ALPHA_SPEC, /* Alpha (A-Z, a-z) */ + pjsip_ALNUM_SPEC, /* Decimal + Alpha. */ + pjsip_TOKEN_SPEC, /* Token. */ + pjsip_HEX_SPEC, /* Hexadecimal digits. */ + pjsip_PARAM_CHAR_SPEC, /* For scanning pname (or pvalue when
+ * it's not quoted.) */ + pjsip_PROBE_USER_HOST_SPEC, /* Hostname characters. */ + pjsip_PASSWD_SPEC, /* Password. */ + pjsip_USER_SPEC, /* User */ + pjsip_ARRAY_ELEMENTS, /* Array separator. */ + pjsip_NEWLINE_OR_EOF_SPEC, /* For eating up header.*/ + pjsip_DISPLAY_SCAN_SPEC; /* Used when searching for display name
+ * in URL. */ /* * Forward decl. */ -static pjsip_msg * int_parse_msg( pj_scanner *scanner, - pj_pool_t *pool, - pjsip_parser_err_report *err_list); -static void int_parse_param( pj_scanner *scanner, - pj_str_t *pname, - pj_str_t *pvalue); -static void int_parse_req_line( pj_scanner *scanner, - pj_pool_t *pool, - pjsip_request_line *req_line); -static int int_is_next_user( pj_scanner *scanner); -static void int_parse_status_line( pj_scanner *scanner, - pjsip_status_line *line); -static void int_parse_user_pass( pj_scanner *scanner, - pj_str_t *user, - pj_str_t *pass); -static void int_parse_uri_host_port( pj_scanner *scanner, - pj_str_t *p_host, - int *p_port); -static pjsip_uri * int_parse_uri_or_name_addr( pj_scanner *scanner, - pj_pool_t *pool, unsigned option); -static pjsip_url * int_parse_sip_url( pj_scanner *scanner, - pj_pool_t *pool, - pj_bool_t parse_params); -static pjsip_name_addr* int_parse_name_addr( pj_scanner *scanner, - pj_pool_t *pool ); -static void parse_hdr_end( pj_scanner *scanner ); -static pjsip_accept_hdr* parse_hdr_accept( pj_scanner *scanner, - pj_pool_t *pool); -static pjsip_allow_hdr* parse_hdr_allow( pj_scanner *scanner, - pj_pool_t *pool); -static pjsip_cid_hdr* parse_hdr_call_id( pj_scanner *scanner, - pj_pool_t *pool); -static pjsip_contact_hdr* parse_hdr_contact( pj_scanner *scanner, - pj_pool_t *pool); -static pjsip_clen_hdr* parse_hdr_content_length( pj_scanner *scanner, - pj_pool_t *pool); -static pjsip_ctype_hdr* parse_hdr_content_type( pj_scanner *scanner, - pj_pool_t *pool); -static pjsip_cseq_hdr* parse_hdr_cseq( pj_scanner *scanner, - pj_pool_t *pool); -static pjsip_expires_hdr* parse_hdr_expires( pj_scanner *scanner, - pj_pool_t *pool); -static pjsip_from_hdr* parse_hdr_from( pj_scanner *scanner, - pj_pool_t *pool); -static pjsip_max_forwards_hdr* parse_hdr_max_forwards( pj_scanner *scanner, - pj_pool_t *pool); -static pjsip_min_expires_hdr* parse_hdr_min_expires( pj_scanner *scanner, - pj_pool_t *pool); -static pjsip_rr_hdr* parse_hdr_rr( pj_scanner *scanner, - pj_pool_t *pool); -static pjsip_route_hdr* parse_hdr_route( pj_scanner *scanner, - pj_pool_t *pool); -static pjsip_require_hdr* parse_hdr_require( pj_scanner *scanner, - pj_pool_t *pool); -static pjsip_retry_after_hdr* parse_hdr_retry_after( pj_scanner *scanner, - pj_pool_t *pool); -static pjsip_supported_hdr* parse_hdr_supported( pj_scanner *scanner, - pj_pool_t *pool); -static pjsip_to_hdr* parse_hdr_to( pj_scanner *scanner, - pj_pool_t *pool); -static pjsip_unsupported_hdr* parse_hdr_unsupported( pj_scanner *scanner, - pj_pool_t *pool); -static pjsip_via_hdr* parse_hdr_via( pj_scanner *scanner, - pj_pool_t *pool); -static pjsip_generic_string_hdr* parse_hdr_generic_string( pj_scanner *scanner, - pj_pool_t *pool); +static pjsip_msg * int_parse_msg( pjsip_parse_ctx *ctx, + pjsip_parser_err_report *err_list); +static void int_parse_param( pj_scanner *scanner, + pj_str_t *pname, + pj_str_t *pvalue); +static void int_parse_req_line( pj_scanner *scanner, + pj_pool_t *pool, + pjsip_request_line *req_line); +static int int_is_next_user( pj_scanner *scanner); +static void int_parse_status_line( pj_scanner *scanner, + pjsip_status_line *line); +static void int_parse_user_pass( pj_scanner *scanner, + pj_str_t *user, + pj_str_t *pass); +static void int_parse_uri_host_port( pj_scanner *scanner, + pj_str_t *p_host, + int *p_port); +static pjsip_uri * int_parse_uri_or_name_addr( pj_scanner *scanner, + pj_pool_t *pool,
+ unsigned option); +static pjsip_url * int_parse_sip_url( pj_scanner *scanner, + pj_pool_t *pool, + pj_bool_t parse_params); +static pjsip_name_addr *
+ int_parse_name_addr( pj_scanner *scanner, + pj_pool_t *pool ); +static void parse_hdr_end( pj_scanner *scanner );
+ +static pjsip_hdr* parse_hdr_accept( pjsip_parse_ctx *ctx ); +static pjsip_hdr* parse_hdr_allow( pjsip_parse_ctx *ctx ); +static pjsip_hdr* parse_hdr_call_id( pjsip_parse_ctx *ctx); +static pjsip_hdr* parse_hdr_contact( pjsip_parse_ctx *ctx); +static pjsip_hdr* parse_hdr_content_len( pjsip_parse_ctx *ctx ); +static pjsip_hdr* parse_hdr_content_type( pjsip_parse_ctx *ctx ); +static pjsip_hdr* parse_hdr_cseq( pjsip_parse_ctx *ctx ); +static pjsip_hdr* parse_hdr_expires( pjsip_parse_ctx *ctx ); +static pjsip_hdr* parse_hdr_from( pjsip_parse_ctx *ctx ); +static pjsip_hdr* parse_hdr_max_forwards( pjsip_parse_ctx *ctx); +static pjsip_hdr* parse_hdr_min_expires( pjsip_parse_ctx *ctx ); +static pjsip_hdr* parse_hdr_rr( pjsip_parse_ctx *ctx ); +static pjsip_hdr* parse_hdr_route( pjsip_parse_ctx *ctx ); +static pjsip_hdr* parse_hdr_require( pjsip_parse_ctx *ctx ); +static pjsip_hdr* parse_hdr_retry_after( pjsip_parse_ctx *ctx ); +static pjsip_hdr* parse_hdr_supported( pjsip_parse_ctx *ctx ); +static pjsip_hdr* parse_hdr_to( pjsip_parse_ctx *ctx ); +static pjsip_hdr* parse_hdr_unsupported( pjsip_parse_ctx *ctx ); +static pjsip_hdr* parse_hdr_via( pjsip_parse_ctx *ctx ); +static pjsip_hdr* parse_hdr_generic_string( pjsip_parse_ctx *ctx); /* Convert non NULL terminated string to integer. */ -static unsigned long pj_strtoul_mindigit(const pj_str_t *str, unsigned mindig) +static unsigned long pj_strtoul_mindigit(const pj_str_t *str,
+ unsigned mindig) { unsigned long value; unsigned i; @@ -163,20 +155,20 @@ static unsigned long pj_strtoul_mindigit(const pj_str_t *str, unsigned mindig) } /* Case insensitive comparison */ -#define parser_stricmp(str1, str2) \ - (str1.slen != str2.slen ? -1 : \ - !(memcmp(str1.ptr, str2.ptr, str1.slen)==0 || stricmp(str1.ptr, str2.ptr)==0)) +#define parser_stricmp(str1, str2) pj_stricmp(&str1, &str2) + /* Syntax error handler for parser. */ static void on_syntax_error(pj_scanner *scanner) { - PJ_UNUSED_ARG(scanner) + PJ_UNUSED_ARG(scanner); PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); } /* Concatenate unrecognized params into single string. */ void pjsip_concat_param_imp( pj_str_t *param, pj_pool_t *pool, - const pj_str_t *pname, const pj_str_t *pvalue, int sepchar) + const pj_str_t *pname, const pj_str_t *pvalue,
+ int sepchar) { char *new_param, *p; int len; @@ -213,75 +205,144 @@ static void concat_param( pj_str_t *param, pj_pool_t *pool, } /* Initialize static properties of the parser. */ -static void init_parser() +static pj_status_t init_parser() { - static int initialized; - + static int initialized;
+ pj_status_t status; +
if (initialized) - return; + return PJ_SUCCESS; initialized = 1; - - pj_cs_add_num( pjsip_DIGIT_SPEC ); - pj_cs_add_alpha( pjsip_ALPHA_SPEC ); - - pj_cs_add_alpha( pjsip_ALNUM_SPEC ); - pj_cs_add_num( pjsip_ALNUM_SPEC ); - - pj_cs_add_str(pjsip_NEWLINE_OR_EOF_SPEC, "\r\n"); +
+ pj_cis_buf_init(&cis_buf);
+
+ status = pj_cis_init(&cis_buf, &pjsip_DIGIT_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ pj_cis_add_num(&pjsip_DIGIT_SPEC); +
+ status = pj_cis_init(&cis_buf, &pjsip_ALPHA_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); + pj_cis_add_alpha( &pjsip_ALPHA_SPEC ); +
+ status = pj_cis_init(&cis_buf, &pjsip_ALNUM_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); + pj_cis_add_alpha( &pjsip_ALNUM_SPEC ); + pj_cis_add_num( &pjsip_ALNUM_SPEC ); +
+ status = pj_cis_init(&cis_buf, &pjsip_NEWLINE_OR_EOF_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); + pj_cis_add_str(&pjsip_NEWLINE_OR_EOF_SPEC, "\r\n"); //pj_cs_set(pjsip_NEWLINE_OR_EOF_SPEC, 0); - - pj_cs_add_str( pjsip_ARRAY_ELEMENTS, ",\r\n"); - - pj_memcpy(pjsip_TOKEN_SPEC, pjsip_ALNUM_SPEC, sizeof(pj_char_spec)); - pj_cs_add_str( pjsip_TOKEN_SPEC, TOKEN); - - pj_memcpy(pjsip_HOST_SPEC, pjsip_ALNUM_SPEC, sizeof(pj_char_spec)); - pj_cs_add_str( pjsip_HOST_SPEC, HOST); - - pj_memcpy(pjsip_HEX_SPEC, pjsip_DIGIT_SPEC, sizeof(pj_char_spec)); - pj_cs_add_str( pjsip_HEX_SPEC, HEX_DIGIT); - - pj_memcpy(pjsip_PARAM_CHAR_SPEC, pjsip_ALNUM_SPEC, sizeof(pj_char_spec)); - pj_cs_add_str( pjsip_PARAM_CHAR_SPEC, PARAM_CHAR); - - pj_memcpy(pjsip_USER_SPEC, pjsip_ALNUM_SPEC, sizeof(pj_char_spec)); - pj_cs_add_str( pjsip_USER_SPEC, MARK ESCAPED USER ); - - pj_memcpy(pjsip_PASSWD_SPEC, pjsip_ALNUM_SPEC, sizeof(pj_char_spec)); - pj_cs_add_str( pjsip_PASSWD_SPEC, MARK ESCAPED PASS); - - pj_cs_add_str( pjsip_PROBE_USER_HOST_SPEC, "@ \n>"); - pj_cs_invert( pjsip_PROBE_USER_HOST_SPEC ); - - pj_cs_add_str( pjsip_DISPLAY_SCAN_SPEC, ":\r\n<"); - - pjsip_register_hdr_parser( "Accept", NULL, (pjsip_parse_hdr_func*) &parse_hdr_accept); - pjsip_register_hdr_parser( "Allow", NULL, (pjsip_parse_hdr_func*) &parse_hdr_allow); - pjsip_register_hdr_parser( "Call-ID", NULL, (pjsip_parse_hdr_func*) &parse_hdr_call_id); - pjsip_register_hdr_parser( "Contact", "m", (pjsip_parse_hdr_func*) &parse_hdr_contact); - pjsip_register_hdr_parser( "Content-Length", NULL, (pjsip_parse_hdr_func*) &parse_hdr_content_length); - pjsip_register_hdr_parser( "Content-Type", NULL, (pjsip_parse_hdr_func*) &parse_hdr_content_type); - pjsip_register_hdr_parser( "CSeq", NULL, (pjsip_parse_hdr_func*) &parse_hdr_cseq); - pjsip_register_hdr_parser( "Expires", NULL, (pjsip_parse_hdr_func*) &parse_hdr_expires); - pjsip_register_hdr_parser( "From", "f", (pjsip_parse_hdr_func*) &parse_hdr_from); - pjsip_register_hdr_parser( "Max-Forwards", NULL, (pjsip_parse_hdr_func*) &parse_hdr_max_forwards); - pjsip_register_hdr_parser( "Min-Expires", NULL, (pjsip_parse_hdr_func*) &parse_hdr_min_expires); - pjsip_register_hdr_parser( "Record-Route", NULL, (pjsip_parse_hdr_func*) &parse_hdr_rr); - pjsip_register_hdr_parser( "Route", NULL, (pjsip_parse_hdr_func*) &parse_hdr_route); - pjsip_register_hdr_parser( "Require", NULL, (pjsip_parse_hdr_func*) &parse_hdr_require); - pjsip_register_hdr_parser( "Retry-After", NULL, (pjsip_parse_hdr_func*) &parse_hdr_retry_after); - pjsip_register_hdr_parser( "Supported", "k", (pjsip_parse_hdr_func*) &parse_hdr_supported); - pjsip_register_hdr_parser( "To", "t", (pjsip_parse_hdr_func*) &parse_hdr_to); - pjsip_register_hdr_parser( "Unsupported", NULL, (pjsip_parse_hdr_func*) &parse_hdr_unsupported); - pjsip_register_hdr_parser( "Via", NULL, (pjsip_parse_hdr_func*) &parse_hdr_via); +
+ status = pj_cis_init(&cis_buf, &pjsip_ARRAY_ELEMENTS);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); + pj_cis_add_str( &pjsip_ARRAY_ELEMENTS, ",\r\n"); +
+ status = pj_cis_dup(&pjsip_TOKEN_SPEC, &pjsip_ALNUM_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); + pj_cis_add_str( &pjsip_TOKEN_SPEC, TOKEN); +
+ status = pj_cis_dup(&pjsip_HOST_SPEC, &pjsip_ALNUM_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); + pj_cis_add_str( &pjsip_HOST_SPEC, HOST); +
+ status = pj_cis_dup(&pjsip_HEX_SPEC, &pjsip_DIGIT_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); + pj_cis_add_str( &pjsip_HEX_SPEC, HEX_DIGIT); +
+ status = pj_cis_dup(&pjsip_PARAM_CHAR_SPEC, &pjsip_ALNUM_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); + pj_cis_add_str(&pjsip_PARAM_CHAR_SPEC, PARAM_CHAR); +
+ status = pj_cis_dup(&pjsip_USER_SPEC, &pjsip_ALNUM_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); + pj_cis_add_str( &pjsip_USER_SPEC, MARK ESCAPED USER ); +
+ status = pj_cis_dup(&pjsip_PASSWD_SPEC, &pjsip_ALNUM_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); + pj_cis_add_str( &pjsip_PASSWD_SPEC, MARK ESCAPED PASS); +
+ status = pj_cis_init(&cis_buf, &pjsip_PROBE_USER_HOST_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); + pj_cis_add_str( &pjsip_PROBE_USER_HOST_SPEC, "@ \n>"); + pj_cis_invert( &pjsip_PROBE_USER_HOST_SPEC ); +
+ status = pj_cis_init(&cis_buf, &pjsip_DISPLAY_SCAN_SPEC);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); + pj_cis_add_str( &pjsip_DISPLAY_SCAN_SPEC, ":\r\n<"); + + status = pjsip_register_hdr_parser( "Accept", NULL, &parse_hdr_accept);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ + status = pjsip_register_hdr_parser( "Allow", NULL, &parse_hdr_allow);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ + status = pjsip_register_hdr_parser( "Call-ID", NULL, &parse_hdr_call_id);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ + status = pjsip_register_hdr_parser( "Contact", "m", &parse_hdr_contact);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ + status = pjsip_register_hdr_parser( "Content-Length", NULL,
+ &parse_hdr_content_len);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ + status = pjsip_register_hdr_parser( "Content-Type", NULL,
+ &parse_hdr_content_type);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ + status = pjsip_register_hdr_parser( "CSeq", NULL, &parse_hdr_cseq);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ + status = pjsip_register_hdr_parser( "Expires", NULL, &parse_hdr_expires);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ + status = pjsip_register_hdr_parser( "From", "f", &parse_hdr_from);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ + status = pjsip_register_hdr_parser( "Max-Forwards", NULL,
+ &parse_hdr_max_forwards);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ + status = pjsip_register_hdr_parser( "Min-Expires", NULL,
+ &parse_hdr_min_expires);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ + status = pjsip_register_hdr_parser( "Record-Route", NULL, &parse_hdr_rr);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ + status = pjsip_register_hdr_parser( "Route", NULL, &parse_hdr_route);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ + status = pjsip_register_hdr_parser( "Require", NULL, &parse_hdr_require);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ + status = pjsip_register_hdr_parser( "Retry-After", NULL,
+ &parse_hdr_retry_after);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ + status = pjsip_register_hdr_parser( "Supported", "k",
+ &parse_hdr_supported);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ + status = pjsip_register_hdr_parser( "To", "t", &parse_hdr_to);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ + status = pjsip_register_hdr_parser( "Unsupported", NULL,
+ &parse_hdr_unsupported);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+ + status = pjsip_register_hdr_parser( "Via", NULL, &parse_hdr_via);
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); /* Register auth parser. */ - pjsip_auth_init_parser(); - + status = pjsip_auth_init_parser(); +
+ return status; } -static void init_sip_parser() +static void init_sip_parser(void) { if (!parser_is_initialized) { /* Prevent race cond. */ @@ -317,29 +378,30 @@ static int compare_handler( const handler_rec *r1, return 1; /* Equal length and equal hash. compare the strings. */ - return strcmp(r1->hname, name); + return pj_native_strcmp(r1->hname, name); } /* Register one handler for one header name. */ -static int int_register_parser( const char *name, pjsip_parse_hdr_func *fptr ) +static pj_status_t int_register_parser( const char *name,
+ pjsip_parse_hdr_func *fptr ) { unsigned pos; handler_rec rec; unsigned i; if (handler_count >= PJ_ARRAY_SIZE(handler)) { - return -1; + return PJ_ETOOMANY; } /* Initialize temporary handler. */ rec.handler = fptr; rec.hname_len = strlen(name); if (rec.hname_len >= sizeof(rec.hname)) { - return -1; + return PJ_ENAMETOOLONG; } /* Name is copied in lowercase. */ for (i=0; i<rec.hname_len; ++i) { - rec.hname[i] = (char)tolower(name[i]); + rec.hname[i] = (char)pj_tolower(name[i]); } rec.hname[i] = '\0'; /* Hash value is calculated from the lowercase name. */ @@ -348,10 +410,11 @@ static int int_register_parser( const char *name, pjsip_parse_hdr_func *fptr ) /* Get the pos to insert the new handler. */ for (pos=0; pos < handler_count; ++pos) { int d; - d = compare_handler(&handler[pos], rec.hname, rec.hname_len, rec.hname_hash); + d = compare_handler(&handler[pos], rec.hname, rec.hname_len,
+ rec.hname_hash); if (d == 0) { pj_assert(0); - return -1; + return PJ_EEXISTS; } if (d > 0) { break; @@ -360,13 +423,14 @@ static int int_register_parser( const char *name, pjsip_parse_hdr_func *fptr ) /* Shift handlers. */ if (pos != handler_count) { - pj_memmove( &handler[pos+1], &handler[pos], (handler_count-pos)*sizeof(handler_rec)); + pj_memmove( &handler[pos+1], &handler[pos],
+ (handler_count-pos)*sizeof(handler_rec)); } /* Add new handler. */ pj_memcpy( &handler[pos], &rec, sizeof(handler_rec)); ++handler_count; - return 0; + return PJ_SUCCESS; } /* Register parser handler. If both header name and short name are valid, @@ -375,14 +439,19 @@ static int int_register_parser( const char *name, pjsip_parse_hdr_func *fptr ) PJ_DEF(pj_status_t) pjsip_register_hdr_parser( const char *hname, const char *hshortname, pjsip_parse_hdr_func *fptr) -{ - if (int_register_parser(hname, fptr)) { - return -1; +{
+ pj_status_t status;
+
+ status = int_register_parser(hname, fptr); + if (status != PJ_SUCCESS) { + return status; } - if (hshortname && int_register_parser(hshortname, fptr)) { - return -1; + if (hshortname) {
+ status = int_register_parser(hshortname, fptr);
+ if (status != PJ_SUCCESS) + return status; } - return 0; + return PJ_SUCCESS; } /* Find handler to parse the header name. */ @@ -392,17 +461,18 @@ static pjsip_parse_hdr_func * find_handler(const pj_str_t *hname) char hname_copy[PJSIP_MAX_HNAME_LEN]; pj_uint32_t hash; int comp; - unsigned i, n; + unsigned n; +
+ if (hname->slen >= PJSIP_MAX_HNAME_LEN) {
+ pj_assert(!"Header name is too long!");
+ return NULL;
+ }
/* Calculate hash value while converting the header to lowercase. * Don't assume that 'hname' is NULL terminated. */ - hash = 0; - for (i=0; i<(unsigned)hname->slen; ++i) { - hname_copy[i] = (char)tolower(hname->ptr[i]); - hash = hash * PJ_HASH_MULTIPLIER + hname_copy[i]; - } - hname_copy[i] = '\0'; + hash = pj_hash_calc_tolower(0, hname_copy, hname);
+ hname_copy[hname->slen] = '\0'; /* Binary search for the handler. */ comp = -1; @@ -428,19 +498,26 @@ static pjsip_parse_hdr_func * find_handler(const pj_str_t *hname) } /* Public function to parse SIP message. */ -PJ_DEF(pjsip_msg*) pjsip_parse_msg( pj_pool_t *pool, char *buf, pj_size_t size, +PJ_DEF(pjsip_msg*) pjsip_parse_msg( pj_pool_t *pool,
+ char *buf, pj_size_t size, pjsip_parser_err_report *err_list) { pjsip_msg *msg = NULL; - pj_scanner scanner; + pj_scanner scanner;
+ pjsip_parse_ctx context; PJ_USE_EXCEPTION; init_sip_parser(); - pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER, &on_syntax_error); + pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER,
+ &on_syntax_error); +
+ context.scanner = &scanner;
+ context.pool = pool;
+ context.rdata = NULL;
PJ_TRY { - msg = int_parse_msg(&scanner, pool, err_list); + msg = int_parse_msg(&context, err_list); } PJ_DEFAULT { msg = NULL; @@ -450,6 +527,35 @@ PJ_DEF(pjsip_msg*) pjsip_parse_msg( pj_pool_t *pool, char *buf, pj_size_t size, pj_scan_fini(&scanner); return msg; } +
+/* Public function to parse as rdata.*/
+PJ_DEF(pjsip_msg *) pjsip_parse_rdata( char *buf, pj_size_t size,
+ pjsip_rx_data *rdata )
+{
+ pj_scanner scanner;
+ pjsip_parse_ctx context;
+ PJ_USE_EXCEPTION;
+
+ init_sip_parser();
+
+ pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER,
+ &on_syntax_error);
+
+ context.scanner = &scanner;
+ context.pool = rdata->pool;
+ context.rdata = rdata;
+
+ PJ_TRY {
+ rdata->msg = int_parse_msg(&context, &rdata->parse_err);
+ }
+ PJ_DEFAULT {
+ rdata->msg = NULL;
+ }
+ PJ_END
+
+ pj_scan_fini(&scanner);
+ return rdata->msg;
+}
/* Determine if a message has been received. */ PJ_DEF(pj_bool_t) pjsip_find_msg( const char *buf, pj_size_t size, @@ -466,24 +572,26 @@ PJ_DEF(pj_bool_t) pjsip_find_msg( const char *buf, pj_size_t size, /* For datagram, the whole datagram IS the message. */ if (is_datagram) { - return PJ_TRUE; + return PJ_SUCCESS; } /* Find the end of header area by finding an empty line. */ - if ((pos = strstr(buf, "\n\r\n")) == NULL) { - return PJ_FALSE; + if ((pos = pj_native_strstr(buf, "\n\r\n")) == NULL) { + return PJSIP_EPARTIALMSG; } hdr_end = pos+1; body_start = pos+3; /* Find "Content-Length" header the hard way. */ - line = strchr(buf, '\n'); + line = pj_native_strchr(buf, '\n'); while (line && line < hdr_end-14) { ++line; - if ( ((*line=='C' || *line=='c') && strncasecmp(line, "Content-Length", 14) == 0) || - ((*line=='l' || *line=='L') && (*(line+1)==' ' || *(line+1)=='\t' || *(line+1)==':'))) + if ( ((*line=='C' || *line=='c') &&
+ pj_native_strncasecmp(line, "Content-Length", 14) == 0) || + ((*line=='l' || *line=='L') &&
+ (*(line+1)==' ' || *(line+1)=='\t' || *(line+1)==':'))) { /* Try to parse the header. */ pj_scanner scanner; @@ -509,7 +617,7 @@ PJ_DEF(pj_bool_t) pjsip_find_msg( const char *buf, pj_size_t size, } /* Get number */ - pj_scan_get(&scanner, pjsip_DIGIT_SPEC, &str_clen); + pj_scan_get(&scanner, &pjsip_DIGIT_SPEC, &str_clen); /* Get newline. */ pj_scan_get_newline(&scanner); @@ -527,24 +635,22 @@ PJ_DEF(pj_bool_t) pjsip_find_msg( const char *buf, pj_size_t size, break; /* Go to next line. */ - line = strchr(line, '\n'); + line = pj_native_strchr(line, '\n'); } /* Found Content-Length? */ if (content_length == -1) { - PJ_LOG(4, ("sipparser", "pjsip_find_msg: incoming TCP packet has missing " - "Content-Length header, treated as incomplete.")); - return PJ_FALSE; + return PJSIP_EMISSINGHDR; } /* Enough packet received? */ *msg_size = (body_start - buf) + content_length; - return (*msg_size) <= size; + return (*msg_size) <= size ? PJ_SUCCESS : PJSIP_EPARTIALMSG; #else - PJ_UNUSED_ARG(buf) - PJ_UNUSED_ARG(is_datagram) + PJ_UNUSED_ARG(buf); + PJ_UNUSED_ARG(is_datagram); *msg_size = size; - return 1; + return PJ_SUCCESS; #endif } @@ -557,10 +663,7 @@ PJ_DEF(pjsip_uri*) pjsip_parse_uri( pj_pool_t *pool, pj_scanner scanner; pjsip_uri *uri = NULL; - if (!parser_is_initialized) { - init_parser(); - parser_is_initialized = 1; - } + init_sip_parser(); pj_scan_init(&scanner, buf, size, 0, &on_syntax_error); @@ -571,7 +674,9 @@ PJ_DEF(pjsip_uri*) pjsip_parse_uri( pj_pool_t *pool, PJ_END; /* Must have exhausted all inputs. */ - if (pj_scan_is_eof(&scanner) || *scanner.current=='\r' || *scanner.current=='\n') { + if (pj_scan_is_eof(&scanner) || *scanner.curptr=='\r' ||
+ *scanner.curptr=='\n')
+ { /* Success. */ pj_scan_fini(&scanner); return uri; @@ -586,7 +691,8 @@ PJ_DEF(pjsip_uri*) pjsip_parse_uri( pj_pool_t *pool, * This assumes that the 'data' member points to a contigous memory where the * actual body is laid. */ -static int generic_print_body (pjsip_msg_body *msg_body, char *buf, pj_size_t size) +static int generic_print_body (pjsip_msg_body *msg_body,
+ char *buf, pj_size_t size) { pjsip_msg_body *body = msg_body; if (size < body->len) @@ -597,19 +703,21 @@ static int generic_print_body (pjsip_msg_body *msg_body, char *buf, pj_size_t si } /* Internal function to parse SIP message */ -static pjsip_msg *int_parse_msg( pj_scanner *scanner, pj_pool_t *pool, +static pjsip_msg *int_parse_msg( pjsip_parse_ctx *ctx, pjsip_parser_err_report *err_list) { PJ_USE_EXCEPTION; int ch; pjsip_msg *msg; pjsip_ctype_hdr *ctype_hdr = NULL; + pj_scanner *scanner = ctx->scanner;
+ pj_pool_t *pool = ctx->pool;
/* Skip leading newlines. */ - ch = *scanner->current; + ch = *scanner->curptr; while (ch=='\r' || ch=='\n') { pj_scan_get_char(scanner); - ch = *scanner->current; + ch = *scanner->curptr; } msg = pjsip_msg_create(pool, PJSIP_REQUEST_MSG); @@ -630,7 +738,7 @@ static pjsip_msg *int_parse_msg( pj_scanner *scanner, pj_pool_t *pool, pjsip_hdr *hdr = NULL; /* Get hname. */ - pj_scan_get( scanner, pjsip_TOKEN_SPEC, &hname); + pj_scan_get( scanner, &pjsip_TOKEN_SPEC, &hname); ch = pj_scan_get_char( scanner ); if (ch != ':') { PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); @@ -645,12 +753,11 @@ static pjsip_msg *int_parse_msg( pj_scanner *scanner, pj_pool_t *pool, * hname/hvalue pair. */ if (handler) { - hdr = (*handler)(scanner, pool); + hdr = (*handler)(ctx); } else { - pjsip_generic_string_hdr *ghdr = parse_hdr_generic_string(scanner, pool); - ghdr->type = PJSIP_H_OTHER; - ghdr->name = ghdr->sname = hname; - hdr = (pjsip_hdr*)ghdr; + hdr = parse_hdr_generic_string(ctx); + hdr->type = PJSIP_H_OTHER; + hdr->name = hdr->sname = hname; } /* Check if we've just parsed a Content-Type header. @@ -668,8 +775,9 @@ static pjsip_msg *int_parse_msg( pj_scanner *scanner, pj_pool_t *pool, pj_str_t token; hdr = NULL; - PJ_LOG(4,("sipparser", "Syntax error in line %d col %d (hname=%.*s)", - scanner->line, scanner->col, hname.slen, hname.ptr)); + //PJ_LOG(4,("sipparser",
+ // "Syntax error in line %d col %d (hname=%.*s)", + // scanner->line, scanner->col, hname.slen, hname.ptr)); if (err_list) { pjsip_parser_err_report *err_info; @@ -684,7 +792,7 @@ static pjsip_msg *int_parse_msg( pj_scanner *scanner, pj_pool_t *pool, } if (!pj_scan_is_eof(scanner)) { - pj_scan_get_until(scanner, pjsip_NEWLINE_OR_EOF_SPEC, &token); + pj_scan_get_until(scanner, &pjsip_NEWLINE_OR_EOF_SPEC, &token); parse_hdr_end(scanner); } } @@ -702,23 +810,23 @@ static pjsip_msg *int_parse_msg( pj_scanner *scanner, pj_pool_t *pool, /* Parse until EOF or an empty line is found. */ } while (!pj_scan_is_eof(scanner) && - *scanner->current != '\r' && *scanner->current != '\n'); + *scanner->curptr != '\r' && *scanner->curptr != '\n'); /* If empty line is found, eat it. */ if (!pj_scan_is_eof(scanner)) { - if (*scanner->current=='\r' || *scanner->current=='\n') { + if (*scanner->curptr=='\r' || *scanner->curptr=='\n') { pj_scan_get_newline(scanner); } } - /* If we have Content-Type header, treat the rest of the message as body. */ + /* If we have Content-Type header, treat the rest of the message as body.*/ if (ctype_hdr) { pjsip_msg_body *body = pj_pool_alloc(pool, sizeof(pjsip_msg_body)); - pj_strdup (pool, &body->content_type.type, &ctype_hdr->media.type); - pj_strdup (pool, &body->content_type.subtype, &ctype_hdr->media.subtype); - pj_strdup (pool, &body->content_type.param, &ctype_hdr->media.param); - body->data = scanner->current; - body->len = scanner->end - scanner->current; + pj_strdup(pool, &body->content_type.type, &ctype_hdr->media.type); + pj_strdup(pool, &body->content_type.subtype, &ctype_hdr->media.subtype); + pj_strdup(pool, &body->content_type.param, &ctype_hdr->media.param); + body->data = scanner->curptr; + body->len = scanner->end - scanner->curptr; body->print_body = &generic_print_body; msg->body = body; @@ -733,20 +841,20 @@ void pjsip_parse_param_imp( pj_scanner *scanner, unsigned option) { /* pname */ - pj_scan_get(scanner, pjsip_PARAM_CHAR_SPEC, pname); + pj_scan_get(scanner, &pjsip_PARAM_CHAR_SPEC, pname); /* pvalue, if any */ - if (*scanner->current == '=') { + if (*scanner->curptr == '=') { pj_scan_get_char(scanner); /* pvalue can be a quoted string. */ - if (*scanner->current == '"') { + if (*scanner->curptr == '"') { pj_scan_get_quote( scanner, '"', '"', pvalue); if (option & PJSIP_PARSE_REMOVE_QUOTE) { pvalue->ptr++; pvalue->slen -= 2; } } else { - pj_scan_get(scanner, pjsip_PARAM_CHAR_SPEC, pvalue); + pj_scan_get(scanner, &pjsip_PARAM_CHAR_SPEC, pvalue); } } else { pvalue->ptr = NULL; @@ -769,11 +877,11 @@ static void int_parse_param( pj_scanner *scanner, static void int_parse_uri_host_port( pj_scanner *scanner, pj_str_t *host, int *p_port) { - pj_scan_get( scanner, pjsip_HOST_SPEC, host); - if (*scanner->current == ':') { + pj_scan_get( scanner, &pjsip_HOST_SPEC, host); + if (*scanner->curptr == ':') { pj_str_t port; pj_scan_get_char(scanner); - pj_scan_get(scanner, pjsip_DIGIT_SPEC, &port); + pj_scan_get(scanner, &pjsip_DIGIT_SPEC, &port); *p_port = pj_strtoul(&port); } else { *p_port = 0; @@ -789,7 +897,7 @@ static int int_is_next_user(pj_scanner *scanner) /* Find character '@'. If this character exist, then the token * must be a username. */ - if (pj_scan_peek( scanner, pjsip_PROBE_USER_HOST_SPEC, &dummy) == '@') + if (pj_scan_peek( scanner, &pjsip_PROBE_USER_HOST_SPEC, &dummy) == '@') is_user = 1; else is_user = 0; @@ -801,10 +909,10 @@ static int int_is_next_user(pj_scanner *scanner) static void int_parse_user_pass( pj_scanner *scanner, pj_str_t *user, pj_str_t *pass) { - pj_scan_get( scanner, pjsip_USER_SPEC, user); - if ( *scanner->current == ':') { + pj_scan_get( scanner, &pjsip_USER_SPEC, user); + if ( *scanner->curptr == ':') { pj_scan_get_char( scanner ); - pj_scan_get( scanner, pjsip_PASSWD_SPEC, pass); + pj_scan_get( scanner, &pjsip_PASSWD_SPEC, pass); } else { pass->ptr = NULL; pass->slen = 0; @@ -815,13 +923,13 @@ static void int_parse_user_pass( pj_scanner *scanner, } /* Parse all types of URI. */ -static pjsip_uri *int_parse_uri_or_name_addr(pj_scanner *scanner, pj_pool_t *pool, - unsigned option) +static pjsip_uri *int_parse_uri_or_name_addr( pj_scanner *scanner, pj_pool_t *pool, + unsigned opt) { pjsip_uri *uri; int is_name_addr = 0; - if (*scanner->current=='"' || *scanner->current=='<') { + if (*scanner->curptr=='"' || *scanner->curptr=='<') { uri = (pjsip_uri*)int_parse_name_addr( scanner, pool ); is_name_addr = 1; } else { @@ -830,14 +938,17 @@ static pjsip_uri *int_parse_uri_or_name_addr(pj_scanner *scanner, pj_pool_t *poo int colon; pj_scan_save_state( scanner, &backtrack); - pj_scan_get( scanner, pjsip_TOKEN_SPEC, &scheme); + pj_scan_get( scanner, &pjsip_TOKEN_SPEC, &scheme); colon = pj_scan_get_char( scanner ); pj_scan_restore_state( scanner, &backtrack); - if (colon==':' && (parser_stricmp(scheme, pjsip_SIP_STR)==0 || parser_stricmp(scheme, pjsip_SIPS_STR)==0)) + if (colon==':' &&
+ (parser_stricmp(scheme, pjsip_SIP_STR)==0 ||
+ parser_stricmp(scheme, pjsip_SIPS_STR)==0)) { - uri = (pjsip_uri*)int_parse_sip_url( scanner, pool, - (option & PJSIP_PARSE_URI_IN_FROM_TO_HDR) == 0 ); + uri = (pjsip_uri*)
+ int_parse_sip_url( scanner, pool, + (opt & PJSIP_PARSE_URI_IN_FROM_TO_HDR)== 0); } else if (colon==':' && parser_stricmp( scheme, pjsip_TEL_STR)==0) { @@ -852,7 +963,7 @@ static pjsip_uri *int_parse_uri_or_name_addr(pj_scanner *scanner, pj_pool_t *poo } /* Should we return the URI object as name address? */ - if (option & PJSIP_PARSE_URI_AS_NAMEADDR) { + if (opt & PJSIP_PARSE_URI_AS_NAMEADDR) { if (is_name_addr == 0) { pjsip_name_addr *name_addr; @@ -870,21 +981,22 @@ static pjsip_uri *int_parse_uri_or_name_addr(pj_scanner *scanner, pj_pool_t *poo static pjsip_uri *int_parse_uri(pj_scanner *scanner, pj_pool_t *pool, pj_bool_t parse_params) { - if (*scanner->current=='"' || *scanner->current=='<') { + if (*scanner->curptr=='"' || *scanner->curptr=='<') { return (pjsip_uri*)int_parse_name_addr( scanner, pool ); } else { pj_str_t scheme; int colon; /* Get scheme. */ - colon = pj_scan_peek(scanner, pjsip_TOKEN_SPEC, &scheme); + colon = pj_scan_peek(scanner, &pjsip_TOKEN_SPEC, &scheme); if (colon != ':') { PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); } - if ((parser_stricmp(scheme, pjsip_SIP_STR)==0 || parser_stricmp(scheme, pjsip_SIPS_STR)==0)) + if ((parser_stricmp(scheme, pjsip_SIP_STR)==0 ||
+ parser_stricmp(scheme, pjsip_SIPS_STR)==0)) { - return (pjsip_uri*)int_parse_sip_url( scanner, pool, parse_params ); + return (pjsip_uri*)int_parse_sip_url( scanner, pool, parse_params); } else if (parser_stricmp(scheme, pjsip_TEL_STR)==0) { PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); @@ -908,7 +1020,7 @@ static pjsip_url *int_parse_sip_url( pj_scanner *scanner, int skip_ws = scanner->skip_ws; scanner->skip_ws = 0; - pj_scan_get(scanner, pjsip_TOKEN_SPEC, &scheme); + pj_scan_get(scanner, &pjsip_TOKEN_SPEC, &scheme); colon = pj_scan_get_char(scanner); if (colon != ':') { PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); @@ -937,7 +1049,7 @@ static pjsip_url *int_parse_sip_url( pj_scanner *scanner, int_parse_uri_host_port(scanner, &url->host, &url->port); /* Get URL parameters. */ - while ( parse_params && *scanner->current == ';' ) { + while ( parse_params && *scanner->curptr == ';' ) { pj_str_t pname, pvalue; int_parse_param( scanner, &pname, &pvalue); @@ -948,7 +1060,7 @@ static pjsip_url *int_parse_sip_url( pj_scanner *scanner, } else if (!parser_stricmp(pname, pjsip_METHOD_STR) && pvalue.slen) { url->method_param = pvalue; - } else if (!parser_stricmp(pname, pjsip_TRANSPORT_STR) && pvalue.slen) { + } else if (!parser_stricmp(pname,pjsip_TRANSPORT_STR) && pvalue.slen) { url->transport_param = pvalue; } else if (!parser_stricmp(pname, pjsip_TTL_STR) && pvalue.slen) { @@ -966,8 +1078,9 @@ static pjsip_url *int_parse_sip_url( pj_scanner *scanner, } /* Get header params. */ - if (parse_params && *scanner->current == '?') { - pj_scan_get_until(scanner, pjsip_NEWLINE_OR_EOF_SPEC, &url->header_param); + if (parse_params && *scanner->curptr == '?') { + pj_scan_get_until(scanner, &pjsip_NEWLINE_OR_EOF_SPEC,
+ &url->header_param); } scanner->skip_ws = skip_ws; @@ -984,10 +1097,10 @@ static pjsip_name_addr *int_parse_name_addr( pj_scanner *scanner, name_addr = pjsip_name_addr_create(pool); - if (*scanner->current == '"') { + if (*scanner->curptr == '"') { pj_scan_get_quote( scanner, '"', '"', &name_addr->display); - } else if (*scanner->current != '<') { + } else if (*scanner->curptr != '<') { int next; pj_str_t dummy; @@ -996,7 +1109,7 @@ static pjsip_name_addr *int_parse_name_addr( pj_scanner *scanner, * We're only interested in display name, because SIP URL * will be parser later. */ - next = pj_scan_peek_until(scanner, pjsip_DISPLAY_SCAN_SPEC, &dummy); + next = pj_scan_peek_until(scanner, &pjsip_DISPLAY_SCAN_SPEC, &dummy); if (next == '<') { /* Ok, this is what we're looking for, a display name. */ pj_scan_get_until_ch( scanner, '<', &name_addr->display); @@ -1008,7 +1121,7 @@ static pjsip_name_addr *int_parse_name_addr( pj_scanner *scanner, pj_scan_skip_whitespace(scanner); /* Get the SIP-URL */ - has_bracket = (*scanner->current == '<'); + has_bracket = (*scanner->curptr == '<'); if (has_bracket) pj_scan_get_char(scanner); name_addr->uri = int_parse_uri( scanner, pool, PJ_TRUE ); @@ -1025,7 +1138,7 @@ static void int_parse_req_line( pj_scanner *scanner, pj_pool_t *pool, { pj_str_t token; - pj_scan_get( scanner, pjsip_TOKEN_SPEC, &token); + pj_scan_get( scanner, &pjsip_TOKEN_SPEC, &token); pjsip_method_init_np( &req_line->method, &token); req_line->uri = int_parse_uri(scanner, pool, PJ_TRUE); @@ -1045,9 +1158,10 @@ static void int_parse_status_line( pj_scanner *scanner, PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); pj_scan_advance_n( scanner, 7, 1); - pj_scan_get( scanner, pjsip_DIGIT_SPEC, &token); + pj_scan_get( scanner, &pjsip_DIGIT_SPEC, &token); status_line->code = pj_strtoul(&token); - pj_scan_get_until( scanner, pjsip_NEWLINE_OR_EOF_SPEC, &status_line->reason); + pj_scan_get_until( scanner, &pjsip_NEWLINE_OR_EOF_SPEC,
+ &status_line->reason); pj_scan_get_newline( scanner ); } @@ -1056,7 +1170,7 @@ static void parse_hdr_end( pj_scanner *scanner ) { if (pj_scan_is_eof(scanner)) { ; /* Do nothing. */ - } else if (*scanner->current == '&') { + } else if (*scanner->curptr == '&') { pj_scan_get_char(scanner); } else { pj_scan_get_newline(scanner); @@ -1073,12 +1187,13 @@ void pjsip_parse_end_hdr_imp( pj_scanner *scanner ) static void parse_generic_array_hdr( pjsip_generic_array_hdr *hdr, pj_scanner *scanner) { - pj_scan_get_until( scanner, pjsip_ARRAY_ELEMENTS, &hdr->values[0]); + pj_scan_get_until( scanner, &pjsip_ARRAY_ELEMENTS, &hdr->values[0]); hdr->count++; - while (*scanner->current == ',') { + while (*scanner->curptr == ',') { pj_scan_get_char(scanner); - pj_scan_get_until( scanner, pjsip_ARRAY_ELEMENTS, &hdr->values[hdr->count]); + pj_scan_get_until( scanner, &pjsip_ARRAY_ELEMENTS,
+ &hdr->values[hdr->count]); hdr->count++; } parse_hdr_end(scanner); @@ -1088,7 +1203,7 @@ static void parse_generic_array_hdr( pjsip_generic_array_hdr *hdr, static void parse_generic_string_hdr( pjsip_generic_string_hdr *hdr, pj_scanner *scanner ) { - pj_scan_get_until( scanner, pjsip_NEWLINE_OR_EOF_SPEC, &hdr->hvalue); + pj_scan_get_until( scanner, &pjsip_NEWLINE_OR_EOF_SPEC, &hdr->hvalue); parse_hdr_end(scanner); } @@ -1097,38 +1212,39 @@ static void parse_generic_int_hdr( pjsip_generic_int_hdr *hdr, pj_scanner *scanner ) { pj_str_t tmp; - pj_scan_get_until( scanner, pjsip_NEWLINE_OR_EOF_SPEC, &tmp); + pj_scan_get_until( scanner, &pjsip_NEWLINE_OR_EOF_SPEC, &tmp); hdr->ivalue = pj_strtoul(&tmp); parse_hdr_end(scanner); } /* Parse Accept header. */ -static pjsip_accept_hdr* parse_hdr_accept( pj_scanner *scanner, - pj_pool_t *pool) +static pjsip_hdr* parse_hdr_accept(pjsip_parse_ctx *ctx) { - pjsip_accept_hdr *accept = pjsip_accept_hdr_create(pool); - parse_generic_array_hdr(accept, scanner); - return accept; + pjsip_accept_hdr *accept = pjsip_accept_hdr_create(ctx->pool); + parse_generic_array_hdr(accept, ctx->scanner); + return (pjsip_hdr*)accept; } /* Parse Allow header. */ -static pjsip_allow_hdr* parse_hdr_allow( pj_scanner *scanner, - pj_pool_t *pool) +static pjsip_hdr* parse_hdr_allow(pjsip_parse_ctx *ctx) { - pjsip_allow_hdr *allow = pjsip_allow_hdr_create(pool); - parse_generic_array_hdr(allow, scanner); - return allow; + pjsip_allow_hdr *allow = pjsip_allow_hdr_create(ctx->pool); + parse_generic_array_hdr(allow, ctx->scanner); + return (pjsip_hdr*)allow; } /* Parse Call-ID header. */ -static pjsip_cid_hdr* parse_hdr_call_id( pj_scanner *scanner, - pj_pool_t *pool) +static pjsip_hdr* parse_hdr_call_id(pjsip_parse_ctx *ctx) { - pjsip_cid_hdr *hdr = pjsip_cid_hdr_create(pool); - pj_scan_get_until( scanner, pjsip_NEWLINE_OR_EOF_SPEC, &hdr->id); - parse_hdr_end(scanner); - return hdr; + pjsip_cid_hdr *hdr = pjsip_cid_hdr_create(ctx->pool); + pj_scan_get_until( ctx->scanner, &pjsip_NEWLINE_OR_EOF_SPEC, &hdr->id); + parse_hdr_end(ctx->scanner);
+
+ if (ctx->rdata)
+ ctx->rdata->call_id = hdr->id;
+ + return (pjsip_hdr*)hdr; } /* Parse and interpret Contact param. */ @@ -1136,7 +1252,7 @@ static void int_parse_contact_param( pjsip_contact_hdr *hdr, pj_scanner *scanner, pj_pool_t *pool) { - while ( *scanner->current == ';' ) { + while ( *scanner->curptr == ';' ) { pj_str_t pname, pvalue; int_parse_param( scanner, &pname, &pvalue); @@ -1159,103 +1275,114 @@ static void int_parse_contact_param( pjsip_contact_hdr *hdr, } /* Parse Contact header. */ -PJ_DEF(pjsip_contact_hdr*) parse_hdr_contact( pj_scanner *scanner, - pj_pool_t *pool) +static pjsip_hdr* parse_hdr_contact( pjsip_parse_ctx *ctx ) { - pjsip_contact_hdr *first = NULL; + pjsip_contact_hdr *first = NULL;
+ pj_scanner *scanner = ctx->scanner; do { - pjsip_contact_hdr *hdr = pjsip_contact_hdr_create(pool); + pjsip_contact_hdr *hdr = pjsip_contact_hdr_create(ctx->pool); if (first == NULL) first = hdr; else pj_list_insert_before(first, hdr); - if (*scanner->current == '*') { + if (*scanner->curptr == '*') { pj_scan_get_char(scanner); hdr->star = 1; } else { hdr->star = 0; - hdr->uri = int_parse_uri_or_name_addr(scanner, pool, PJSIP_PARSE_URI_AS_NAMEADDR); + hdr->uri = int_parse_uri_or_name_addr(scanner, ctx->pool,
+ PJSIP_PARSE_URI_AS_NAMEADDR); - int_parse_contact_param(hdr, scanner, pool); + int_parse_contact_param(hdr, scanner, ctx->pool); } - if (*scanner->current != ',') + if (*scanner->curptr != ',') break; pj_scan_get_char(scanner); } while (1); - parse_hdr_end(scanner); - return first; + parse_hdr_end(scanner);
+ + return (pjsip_hdr*)first; } /* Parse Content-Length header. */ -PJ_DEF(pjsip_clen_hdr*) parse_hdr_content_length( pj_scanner *scanner, - pj_pool_t *pool) +static pjsip_hdr* parse_hdr_content_len( pjsip_parse_ctx *ctx ) { pj_str_t digit; pjsip_clen_hdr *hdr; - hdr = pjsip_clen_hdr_create(pool); - pj_scan_get(scanner, pjsip_DIGIT_SPEC, &digit); + hdr = pjsip_clen_hdr_create(ctx->pool); + pj_scan_get(ctx->scanner, &pjsip_DIGIT_SPEC, &digit); hdr->len = pj_strtoul(&digit); - parse_hdr_end(scanner); - return hdr; + parse_hdr_end(ctx->scanner);
+
+ if (ctx->rdata)
+ ctx->rdata->clen = hdr;
+ + return (pjsip_hdr*)hdr; } /* Parse Content-Type header. */ -PJ_DEF(pjsip_ctype_hdr*) parse_hdr_content_type( pj_scanner *scanner, - pj_pool_t *pool) +static pjsip_hdr* parse_hdr_content_type( pjsip_parse_ctx *ctx ) { pjsip_ctype_hdr *hdr; + pj_scanner *scanner = ctx->scanner;
- hdr = pjsip_ctype_hdr_create(pool); + hdr = pjsip_ctype_hdr_create(ctx->pool); /* Parse media type and subtype. */ - pj_scan_get(scanner, pjsip_TOKEN_SPEC, &hdr->media.type); + pj_scan_get(scanner, &pjsip_TOKEN_SPEC, &hdr->media.type); pj_scan_get_char(scanner); - pj_scan_get(scanner, pjsip_TOKEN_SPEC, &hdr->media.subtype); + pj_scan_get(scanner, &pjsip_TOKEN_SPEC, &hdr->media.subtype); /* Parse media parameters */ - while (*scanner->current == ';') { + while (*scanner->curptr == ';') { pj_str_t pname, pvalue; int_parse_param(scanner, &pname, &pvalue); - concat_param(&hdr->media.param, pool, &pname, &pvalue); + concat_param(&hdr->media.param, ctx->pool, &pname, &pvalue); } - parse_hdr_end(scanner); - return hdr; + parse_hdr_end(ctx->scanner);
+
+ if (ctx->rdata)
+ ctx->rdata->ctype = hdr;
+ + return (pjsip_hdr*)hdr; } /* Parse CSeq header. */ -PJ_DEF(pjsip_cseq_hdr*) parse_hdr_cseq( pj_scanner *scanner, - pj_pool_t *pool) +static pjsip_hdr* parse_hdr_cseq( pjsip_parse_ctx *ctx ) { pj_str_t cseq, method; pjsip_cseq_hdr *hdr; - hdr = pjsip_cseq_hdr_create(pool); - pj_scan_get( scanner, pjsip_DIGIT_SPEC, &cseq); + hdr = pjsip_cseq_hdr_create(ctx->pool); + pj_scan_get( ctx->scanner, &pjsip_DIGIT_SPEC, &cseq); hdr->cseq = pj_strtoul(&cseq); - pj_scan_get( scanner, pjsip_TOKEN_SPEC, &method); + pj_scan_get( ctx->scanner, &pjsip_TOKEN_SPEC, &method); pjsip_method_init_np(&hdr->method, &method); - parse_hdr_end( scanner ); - return hdr; + parse_hdr_end( ctx->scanner );
+
+ if (ctx->rdata)
+ ctx->rdata->cseq = hdr;
+ + return (pjsip_hdr*)hdr; } /* Parse Expires header. */ -static pjsip_expires_hdr* parse_hdr_expires(pj_scanner *scanner, - pj_pool_t *pool) +static pjsip_hdr* parse_hdr_expires(pjsip_parse_ctx *ctx) { - pjsip_expires_hdr *hdr = pjsip_expires_hdr_create(pool); - parse_generic_int_hdr(hdr, scanner); - return hdr; + pjsip_expires_hdr *hdr = pjsip_expires_hdr_create(ctx->pool); + parse_generic_int_hdr(hdr, ctx->scanner); + return (pjsip_hdr*)hdr; } /* Parse From: or To: header. */ @@ -1267,7 +1394,7 @@ static void parse_hdr_fromto( pj_scanner *scanner, PJSIP_PARSE_URI_AS_NAMEADDR | PJSIP_PARSE_URI_IN_FROM_TO_HDR); - while ( *scanner->current == ';' ) { + while ( *scanner->curptr == ';' ) { pj_str_t pname, pvalue; int_parse_param( scanner, &pname, &pvalue); @@ -1284,66 +1411,71 @@ static void parse_hdr_fromto( pj_scanner *scanner, } /* Parse From: header. */ -PJ_DEF(pjsip_from_hdr*) parse_hdr_from( pj_scanner *scanner, - pj_pool_t *pool) +static pjsip_hdr* parse_hdr_from( pjsip_parse_ctx *ctx ) { - pjsip_from_hdr *hdr = pjsip_from_hdr_create(pool); - parse_hdr_fromto(scanner, pool, hdr); - return hdr; + pjsip_from_hdr *hdr = pjsip_from_hdr_create(ctx->pool); + parse_hdr_fromto(ctx->scanner, ctx->pool, hdr);
+ if (ctx->rdata)
+ ctx->rdata->from = hdr;
+ + return (pjsip_hdr*)hdr; } /* Parse Require: header. */ -static pjsip_require_hdr* parse_hdr_require( pj_scanner *scanner, - pj_pool_t *pool) +static pjsip_hdr* parse_hdr_require( pjsip_parse_ctx *ctx ) { - pjsip_require_hdr *hdr = pjsip_require_hdr_create(pool); - parse_generic_array_hdr(hdr, scanner); - return hdr; + pjsip_require_hdr *hdr = pjsip_require_hdr_create(ctx->pool); + parse_generic_array_hdr(hdr, ctx->scanner);
+
+ if (ctx->rdata && ctx->rdata->require == NULL)
+ ctx->rdata->require = hdr;
+ + return (pjsip_hdr*)hdr; } /* Parse Retry-After: header. */ -static pjsip_retry_after_hdr* parse_hdr_retry_after(pj_scanner *scanner, - pj_pool_t *pool) +static pjsip_hdr* parse_hdr_retry_after(pjsip_parse_ctx *ctx) { pjsip_retry_after_hdr *hdr; - hdr = pjsip_retry_after_hdr_create(pool); - parse_generic_int_hdr(hdr, scanner); - return hdr; + hdr = pjsip_retry_after_hdr_create(ctx->pool); + parse_generic_int_hdr(hdr, ctx->scanner); + return (pjsip_hdr*)hdr; } /* Parse Supported: header. */ -static pjsip_supported_hdr* parse_hdr_supported(pj_scanner *scanner, - pj_pool_t *pool) +static pjsip_hdr* parse_hdr_supported(pjsip_parse_ctx *ctx) { - pjsip_supported_hdr *hdr = pjsip_supported_hdr_create(pool); - parse_generic_array_hdr(hdr, scanner); - return hdr; + pjsip_supported_hdr *hdr = pjsip_supported_hdr_create(ctx->pool); + parse_generic_array_hdr(hdr, ctx->scanner); + return (pjsip_hdr*)hdr; } /* Parse To: header. */ -PJ_DEF(pjsip_to_hdr*) parse_hdr_to( pj_scanner *scanner, - pj_pool_t *pool) +static pjsip_hdr* parse_hdr_to( pjsip_parse_ctx *ctx ) { - pjsip_to_hdr *hdr = pjsip_to_hdr_create(pool); - parse_hdr_fromto(scanner, pool, hdr); - return hdr; + pjsip_to_hdr *hdr = pjsip_to_hdr_create(ctx->pool); + parse_hdr_fromto(ctx->scanner, ctx->pool, hdr);
+
+ if (ctx->rdata)
+ ctx->rdata->to = hdr;
+ + return (pjsip_hdr*)hdr; } /* Parse Unsupported: header. */ -static pjsip_unsupported_hdr* parse_hdr_unsupported(pj_scanner *scanner, - pj_pool_t *pool) +static pjsip_hdr* parse_hdr_unsupported(pjsip_parse_ctx *ctx) { - pjsip_unsupported_hdr *hdr = pjsip_unsupported_hdr_create(pool); - parse_generic_array_hdr(hdr, scanner); - return hdr; + pjsip_unsupported_hdr *hdr = pjsip_unsupported_hdr_create(ctx->pool); + parse_generic_array_hdr(hdr, ctx->scanner); + return (pjsip_hdr*)hdr; } /* Parse and interpret Via parameters. */ static void int_parse_via_param( pjsip_via_hdr *hdr, pj_scanner *scanner, pj_pool_t *pool) { - while ( *scanner->current == ';' ) { + while ( *scanner->curptr == ';' ) { pj_str_t pname, pvalue; int_parse_param( scanner, &pname, &pvalue); @@ -1373,23 +1505,25 @@ static void int_parse_via_param( pjsip_via_hdr *hdr, pj_scanner *scanner, } /* Parse Max-Forwards header. */ -static pjsip_max_forwards_hdr* parse_hdr_max_forwards( pj_scanner *scanner, - pj_pool_t *pool) +static pjsip_hdr* parse_hdr_max_forwards( pjsip_parse_ctx *ctx ) { pjsip_max_forwards_hdr *hdr; - hdr = pjsip_max_forwards_hdr_create(pool); - parse_generic_int_hdr(hdr, scanner); - return hdr; + hdr = pjsip_max_forwards_hdr_create(ctx->pool); + parse_generic_int_hdr(hdr, ctx->scanner);
+
+ if (ctx->rdata)
+ ctx->rdata->max_fwd = hdr;
+ + return (pjsip_hdr*)hdr; } /* Parse Min-Expires header. */ -static pjsip_min_expires_hdr* parse_hdr_min_expires(pj_scanner *scanner, - pj_pool_t *pool) +static pjsip_hdr* parse_hdr_min_expires(pjsip_parse_ctx *ctx) { pjsip_min_expires_hdr *hdr; - hdr = pjsip_min_expires_hdr_create(pool); - parse_generic_int_hdr(hdr, scanner); - return hdr; + hdr = pjsip_min_expires_hdr_create(ctx->pool); + parse_generic_int_hdr(hdr, ctx->scanner); + return (pjsip_hdr*)hdr; } @@ -1400,65 +1534,76 @@ static void parse_hdr_rr_route( pj_scanner *scanner, pj_pool_t *pool, pjsip_name_addr *temp=int_parse_name_addr(scanner, pool); pj_memcpy(&hdr->name_addr, temp, sizeof(*temp)); - if (*scanner->current == ';') { - pj_scan_get_until(scanner, pjsip_NEWLINE_OR_EOF_SPEC, &hdr->other_param); + if (*scanner->curptr == ';') { + pj_scan_get_until(scanner, &pjsip_NEWLINE_OR_EOF_SPEC,
+ &hdr->other_param); } } /* Parse Record-Route header. */ -PJ_DEF(pjsip_rr_hdr*) parse_hdr_rr( pj_scanner *scanner, pj_pool_t *pool) +static pjsip_hdr* parse_hdr_rr( pjsip_parse_ctx *ctx) { - pjsip_rr_hdr *first = NULL; + pjsip_rr_hdr *first = NULL;
+ pj_scanner *scanner = ctx->scanner; do { - pjsip_rr_hdr *hdr = pjsip_rr_hdr_create(pool); + pjsip_rr_hdr *hdr = pjsip_rr_hdr_create(ctx->pool); if (!first) { first = hdr; } else { pj_list_insert_before(first, hdr); } - parse_hdr_rr_route(scanner, pool, hdr); - if (*scanner->current == ',') { + parse_hdr_rr_route(scanner, ctx->pool, hdr); + if (*scanner->curptr == ',') { pj_scan_get_char(scanner); } else { break; } } while (1); - parse_hdr_end(scanner); - return first; + parse_hdr_end(scanner);
+
+ if (ctx->rdata && ctx->rdata->record_route==NULL)
+ ctx->rdata->record_route = first;
+ + return (pjsip_hdr*)first; } /* Parse Route: header. */ -PJ_DEF(pjsip_route_hdr*) parse_hdr_route( pj_scanner *scanner, - pj_pool_t *pool) +static pjsip_hdr* parse_hdr_route( pjsip_parse_ctx *ctx ) { - pjsip_route_hdr *first = NULL; + pjsip_route_hdr *first = NULL;
+ pj_scanner *scanner = ctx->scanner; do { - pjsip_route_hdr *hdr = pjsip_route_hdr_create(pool); + pjsip_route_hdr *hdr = pjsip_route_hdr_create(ctx->pool); if (!first) { first = hdr; } else { pj_list_insert_before(first, hdr); } - parse_hdr_rr_route(scanner, pool, hdr); - if (*scanner->current == ',') { + parse_hdr_rr_route(scanner, ctx->pool, hdr); + if (*scanner->curptr == ',') { pj_scan_get_char(scanner); } else { break; } } while (1); - parse_hdr_end(scanner); - return first; + parse_hdr_end(scanner);
+
+ if (ctx->rdata && ctx->rdata->route==NULL)
+ ctx->rdata->route = first;
+ + return (pjsip_hdr*)first; } /* Parse Via: header. */ -PJ_DEF(pjsip_via_hdr*) parse_hdr_via( pj_scanner *scanner, pj_pool_t *pool) +static pjsip_hdr* parse_hdr_via( pjsip_parse_ctx *ctx ) { - pjsip_via_hdr *first = NULL; + pjsip_via_hdr *first = NULL;
+ pj_scanner *scanner = ctx->scanner; do { - pjsip_via_hdr *hdr = pjsip_via_hdr_create(pool); + pjsip_via_hdr *hdr = pjsip_via_hdr_create(ctx->pool); if (!first) first = hdr; else @@ -1469,46 +1614,49 @@ PJ_DEF(pjsip_via_hdr*) parse_hdr_via( pj_scanner *scanner, pj_pool_t *pool) pj_scan_advance_n( scanner, 8, 1); - pj_scan_get( scanner, pjsip_TOKEN_SPEC, &hdr->transport); - pj_scan_get( scanner, pjsip_HOST_SPEC, &hdr->sent_by.host); + pj_scan_get( scanner, &pjsip_TOKEN_SPEC, &hdr->transport); + pj_scan_get( scanner, &pjsip_HOST_SPEC, &hdr->sent_by.host); - if (*scanner->current==':') { + if (*scanner->curptr==':') { pj_str_t digit; pj_scan_get_char(scanner); - pj_scan_get(scanner, pjsip_DIGIT_SPEC, &digit); + pj_scan_get(scanner, &pjsip_DIGIT_SPEC, &digit); hdr->sent_by.port = pj_strtoul(&digit); } else { hdr->sent_by.port = 5060; } - int_parse_via_param(hdr, scanner, pool); + int_parse_via_param(hdr, scanner, ctx->pool); - if (*scanner->current == '(') { + if (*scanner->curptr == '(') { pj_scan_get_char(scanner); pj_scan_get_until_ch( scanner, ')', &hdr->comment); pj_scan_get_char( scanner ); } - if (*scanner->current != ',') + if (*scanner->curptr != ',') break; pj_scan_get_char(scanner); } while (1); - parse_hdr_end(scanner); - return first; + parse_hdr_end(scanner);
+
+ if (ctx->rdata && ctx->rdata->via == NULL)
+ ctx->rdata->via = first;
+ + return (pjsip_hdr*)first; } /* Parse generic header. */ -PJ_DEF(pjsip_generic_string_hdr*) parse_hdr_generic_string( pj_scanner *scanner, - pj_pool_t *pool) +static pjsip_hdr* parse_hdr_generic_string( pjsip_parse_ctx *ctx ) { pjsip_generic_string_hdr *hdr; - hdr = pjsip_generic_string_hdr_create(pool, NULL); - parse_generic_string_hdr(hdr, scanner); - return hdr; + hdr = pjsip_generic_string_hdr_create(ctx->pool, NULL); + parse_generic_string_hdr(hdr, ctx->scanner); + return (pjsip_hdr*)hdr; } @@ -1517,23 +1665,28 @@ PJ_DEF(void*) pjsip_parse_hdr( pj_pool_t *pool, const pj_str_t *hname, char *buf, pj_size_t size, int *parsed_len ) { pj_scanner scanner; - pjsip_hdr *hdr = NULL; + pjsip_hdr *hdr = NULL;
+ pjsip_parse_ctx context; PJ_USE_EXCEPTION; init_sip_parser(); - pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER, &on_syntax_error); + pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER,
+ &on_syntax_error); +
+ context.scanner = &scanner;
+ context.pool = pool;
+ context.rdata = NULL;
PJ_TRY { pjsip_parse_hdr_func *handler = find_handler(hname); if (handler) { - hdr = (*handler)(&scanner, pool); + hdr = (*handler)(&context); } else { - pjsip_generic_string_hdr *ghdr = parse_hdr_generic_string(&scanner, pool); - ghdr->type = PJSIP_H_OTHER; - pj_strdup(pool, &ghdr->name, hname); - ghdr->sname = ghdr->name; - hdr = (pjsip_hdr*)ghdr; + hdr = parse_hdr_generic_string(&context); + hdr->type = PJSIP_H_OTHER; + pj_strdup(pool, &hdr->name, hname); + hdr->sname = hdr->name; } } @@ -1543,7 +1696,7 @@ PJ_DEF(void*) pjsip_parse_hdr( pj_pool_t *pool, const pj_str_t *hname, PJ_END if (parsed_len) { - *parsed_len = (scanner.current - scanner.begin); + *parsed_len = (scanner.curptr - scanner.begin); } pj_scan_fini(&scanner); diff --git a/pjsip/src/pjsip/sip_resolve.c b/pjsip/src/pjsip/sip_resolve.c index 1267b8b4..b199eaba 100644 --- a/pjsip/src/pjsip/sip_resolve.c +++ b/pjsip/src/pjsip/sip_resolve.c @@ -1,11 +1,11 @@ /* $Id$ - * */ #include <pjsip/sip_resolve.h> #include <pjsip/sip_transport.h> #include <pj/pool.h> -#include <ctype.h> +#include <pj/ctype.h> +#include <pj/assert.h>
struct pjsip_resolver_t { @@ -21,7 +21,7 @@ PJ_DEF(pjsip_resolver_t*) pjsip_resolver_create(pj_pool_t *pool) PJ_DEF(void) pjsip_resolver_destroy(pjsip_resolver_t *resolver) { - PJ_UNUSED_ARG(resolver) + PJ_UNUSED_ARG(resolver); } static int is_str_ip(const pj_str_t *host) @@ -30,7 +30,7 @@ static int is_str_ip(const pj_str_t *host) const char *end = ((const char*)host->ptr) + host->slen; while (p != end) { - if (isdigit(*p) || *p=='.') { + if (pj_isdigit(*p) || *p=='.') { ++p; } else { return 0; @@ -50,8 +50,8 @@ PJ_DEF(void) pjsip_resolve( pjsip_resolver_t *resolver, int is_ip_addr; pjsip_transport_type_e type = target->type; - PJ_UNUSED_ARG(resolver) - PJ_UNUSED_ARG(pool) + PJ_UNUSED_ARG(resolver); + PJ_UNUSED_ARG(pool); /* We only do synchronous resolving at this moment. */ PJ_TODO(SUPPORT_RFC3263_SERVER_RESOLUTION) @@ -94,9 +94,11 @@ PJ_DEF(void) pjsip_resolve( pjsip_resolver_t *resolver, /* Resolve hostname. */ if (!is_ip_addr) { - status = pj_sockaddr_init(&svr_addr.entry[0].addr, &target->host, target->port); + status = pj_sockaddr_in_init(&svr_addr.entry[0].addr, &target->host,
+ (pj_uint16_t)target->port); } else { - status = pj_sockaddr_init(&svr_addr.entry[0].addr, &target->host, target->port); + status = pj_sockaddr_in_init(&svr_addr.entry[0].addr, &target->host,
+ (pj_uint16_t)target->port); pj_assert(status == PJ_SUCCESS); } diff --git a/pjsip/src/pjsip/sip_transaction.c b/pjsip/src/pjsip/sip_transaction.c index cdb20626..ebc0a803 100644 --- a/pjsip/src/pjsip/sip_transaction.c +++ b/pjsip/src/pjsip/sip_transaction.c @@ -1,5 +1,4 @@ /* $Id$ - * */ #include <pjsip/sip_transaction.h> #include <pjsip/sip_transport.h> @@ -7,14 +6,16 @@ #include <pjsip/sip_misc.h> #include <pjsip/sip_event.h> #include <pjsip/sip_endpoint.h> +#include <pjsip/sip_errno.h> #include <pj/log.h> #include <pj/string.h> #include <pj/os.h> #include <pj/guid.h> #include <pj/pool.h> +#include <pj/assert.h> /* Thread Local Storage ID for transaction lock (initialized by endpoint) */ -int pjsip_tsx_lock_tls_id; +long pjsip_tsx_lock_tls_id; /* State names */ static const char *state_str[] = @@ -43,10 +44,14 @@ typedef struct tsx_lock_data { int is_alive; } tsx_lock_data; + /* Timer timeout value constants */ -static const pj_time_val t1_timer_val = { PJSIP_T1_TIMEOUT/1000, PJSIP_T1_TIMEOUT%1000 }; -static const pj_time_val t4_timer_val = { PJSIP_T4_TIMEOUT/1000, PJSIP_T4_TIMEOUT%1000 }; -static const pj_time_val td_timer_val = { PJSIP_TD_TIMEOUT/1000, PJSIP_TD_TIMEOUT%1000 }; +static const pj_time_val t1_timer_val = { PJSIP_T1_TIMEOUT/1000, + PJSIP_T1_TIMEOUT%1000 }; +static const pj_time_val t4_timer_val = { PJSIP_T4_TIMEOUT/1000, + PJSIP_T4_TIMEOUT%1000 }; +static const pj_time_val td_timer_val = { PJSIP_TD_TIMEOUT/1000, + PJSIP_TD_TIMEOUT%1000 }; static const pj_time_val timeout_timer_val = { (64*PJSIP_T1_TIMEOUT)/1000, (64*PJSIP_T1_TIMEOUT)%1000 }; @@ -58,35 +63,39 @@ enum Transaction_Timer_Id }; /* Function Prototypes */ -static int pjsip_tsx_on_state_null( pjsip_transaction *tsx, - pjsip_event *event); -static int pjsip_tsx_on_state_calling( pjsip_transaction *tsx, - pjsip_event *event); -static int pjsip_tsx_on_state_trying( pjsip_transaction *tsx, - pjsip_event *event); -static int pjsip_tsx_on_state_proceeding_uas( pjsip_transaction *tsx, - pjsip_event *event); -static int pjsip_tsx_on_state_proceeding_uac( pjsip_transaction *tsx, - pjsip_event *event); -static int pjsip_tsx_on_state_completed_uas( pjsip_transaction *tsx, - pjsip_event *event); -static int pjsip_tsx_on_state_completed_uac( pjsip_transaction *tsx, - pjsip_event *event); -static int pjsip_tsx_on_state_confirmed( pjsip_transaction *tsx, - pjsip_event *event); -static int pjsip_tsx_on_state_terminated( pjsip_transaction *tsx, - pjsip_event *event); -static int pjsip_tsx_on_state_destroyed( pjsip_transaction *tsx, - pjsip_event *event); -static void tsx_timer_callback( pj_timer_heap_t *theap, - pj_timer_entry *entry); -static int tsx_send_msg( pjsip_transaction *tsx, pjsip_tx_data *tdata); -static void lock_tsx( pjsip_transaction *tsx, struct tsx_lock_data *lck ); -static pj_status_t unlock_tsx( pjsip_transaction *tsx, struct tsx_lock_data *lck ); +static pj_status_t pjsip_tsx_on_state_null( pjsip_transaction *tsx, + pjsip_event *event); +static pj_status_t pjsip_tsx_on_state_calling( pjsip_transaction *tsx, + pjsip_event *event); +static pj_status_t pjsip_tsx_on_state_trying( pjsip_transaction *tsx, + pjsip_event *event); +static pj_status_t pjsip_tsx_on_state_proceeding_uas( pjsip_transaction *tsx, + pjsip_event *event); +static pj_status_t pjsip_tsx_on_state_proceeding_uac( pjsip_transaction *tsx, + pjsip_event *event); +static pj_status_t pjsip_tsx_on_state_completed_uas( pjsip_transaction *tsx, + pjsip_event *event); +static pj_status_t pjsip_tsx_on_state_completed_uac( pjsip_transaction *tsx, + pjsip_event *event); +static pj_status_t pjsip_tsx_on_state_confirmed(pjsip_transaction *tsx, + pjsip_event *event); +static pj_status_t pjsip_tsx_on_state_terminated(pjsip_transaction *tsx, + pjsip_event *event); +static pj_status_t pjsip_tsx_on_state_destroyed(pjsip_transaction *tsx, + pjsip_event *event);
+ +static void tsx_timer_callback( pj_timer_heap_t *theap, + pj_timer_entry *entry); +static int tsx_send_msg( pjsip_transaction *tsx,
+ pjsip_tx_data *tdata); +static void lock_tsx( pjsip_transaction *tsx, struct
+ tsx_lock_data *lck ); +static pj_status_t unlock_tsx( pjsip_transaction *tsx, + struct tsx_lock_data *lck ); /* State handlers for UAC, indexed by state */ -static int (*tsx_state_handler_uac[PJSIP_TSX_STATE_MAX])(pjsip_transaction *tsx, - pjsip_event *event ) = +static int (*tsx_state_handler_uac[PJSIP_TSX_STATE_MAX])(pjsip_transaction *, + pjsip_event *) = { &pjsip_tsx_on_state_null, &pjsip_tsx_on_state_calling, @@ -99,8 +108,8 @@ static int (*tsx_state_handler_uac[PJSIP_TSX_STATE_MAX])(pjsip_transaction *tsx }; /* State handlers for UAS */ -static int (*tsx_state_handler_uas[PJSIP_TSX_STATE_MAX])(pjsip_transaction *tsx, - pjsip_event *event ) = +static int (*tsx_state_handler_uas[PJSIP_TSX_STATE_MAX])(pjsip_transaction *, + pjsip_event *) = { &pjsip_tsx_on_state_null, &pjsip_tsx_on_state_calling, @@ -153,11 +162,11 @@ PJ_DEF(const char *) pjsip_role_name(pjsip_role_e role) * The transaction key is constructed from the common components of above * components. Additional comparison is needed to fully match a transaction. */ -void create_tsx_key_2543( pj_pool_t *pool, - pj_str_t *str, - pjsip_role_e role, - const pjsip_method *method, - const pjsip_rx_data *rdata ) +static pj_status_t create_tsx_key_2543( pj_pool_t *pool, + pj_str_t *str, + pjsip_role_e role, + const pjsip_method *method, + const pjsip_rx_data *rdata ) { #define SEPARATOR '$' char *key, *p, *end; @@ -166,17 +175,22 @@ void create_tsx_key_2543( pj_pool_t *pool, pjsip_uri *req_uri; pj_str_t *host; + PJ_ASSERT_RETURN(pool && str && method && rdata, PJ_EINVAL); + PJ_ASSERT_RETURN(rdata->msg, PJ_EINVAL); + PJ_ASSERT_RETURN(rdata->via, PJSIP_EMISSINGHDR); + PJ_ASSERT_RETURN(rdata->cseq, PJSIP_EMISSINGHDR); + PJ_ASSERT_RETURN(rdata->from, PJSIP_EMISSINGHDR); + host = &rdata->via->sent_by.host; req_uri = (pjsip_uri*)rdata->msg->line.req.uri; /* Calculate length required. */ - len_required = PJSIP_MAX_URL_SIZE + /* URI */ - 9 + /* CSeq number */ - rdata->from_tag.slen + /* From tag. */ + len_required = 9 + /* CSeq number */ + rdata->from->tag.slen + /* From tag. */ rdata->call_id.slen + /* Call-ID */ host->slen + /* Via host. */ 9 + /* Via port. */ - 32; /* Separator+Allowance. */ + 16; /* Separator+Allowance. */ key = p = pj_pool_alloc(pool, len_required); end = p + len_required; @@ -223,9 +237,6 @@ void create_tsx_key_2543( pj_pool_t *pool, * only used to match request retransmission, and we expect that the * request retransmissions will contain the same port. */ - if ((end-p) < host->slen + 12) { - goto on_error; - } pj_memcpy(p, host->ptr, host->slen); p += host->slen; *p++ = ':'; @@ -240,27 +251,22 @@ void create_tsx_key_2543( pj_pool_t *pool, str->ptr = key; str->slen = p-key; - return; - -on_error: - PJ_LOG(2,("tsx........", "Not enough buffer (%d) for transaction key", - len_required)); - pj_assert(0); - str->ptr = NULL; - str->slen = 0; + return PJ_SUCCESS; } /* * Create transaction key for RFC3161 compliant system. */ -void create_tsx_key_3261( pj_pool_t *pool, - pj_str_t *key, - pjsip_role_e role, - const pjsip_method *method, - const pj_str_t *branch ) +static pj_status_t create_tsx_key_3261( pj_pool_t *pool, + pj_str_t *key, + pjsip_role_e role, + const pjsip_method *method, + const pj_str_t *branch) { char *p; + PJ_ASSERT_RETURN(pool && key && method && branch, PJ_EINVAL); + p = key->ptr = pj_pool_alloc(pool, branch->slen + method->name.slen + 4 ); /* Add role. */ @@ -280,18 +286,22 @@ void create_tsx_key_3261( pj_pool_t *pool, /* Set length */ key->slen = p - key->ptr; + + return PJ_SUCCESS; } /* * Create key from the incoming data, to be used to search the transaction * in the transaction hash table. */ -PJ_DEF(void) pjsip_tsx_create_key( pj_pool_t *pool, pj_str_t *key, - pjsip_role_e role, - const pjsip_method *method, - const pjsip_rx_data *rdata ) +PJ_DEF(pj_status_t) pjsip_tsx_create_key( pj_pool_t *pool, pj_str_t *key, + pjsip_role_e role, + const pjsip_method *method, + const pjsip_rx_data *rdata) { - pj_str_t rfc3261_branch = {PJSIP_RFC3261_BRANCH_ID, PJSIP_RFC3261_BRANCH_LEN}; + pj_str_t rfc3261_branch = {PJSIP_RFC3261_BRANCH_ID, + PJSIP_RFC3261_BRANCH_LEN}; + /* Get the branch parameter in the top-most Via. * If branch parameter is started with "z9hG4bK", then the message was @@ -300,17 +310,18 @@ PJ_DEF(void) pjsip_tsx_create_key( pj_pool_t *pool, pj_str_t *key, */ const pj_str_t *branch = &rdata->via->branch_param; - if (pj_strncmp(branch, &rfc3261_branch, PJSIP_RFC3261_BRANCH_LEN) == 0) { + if (pj_strncmp(branch,&rfc3261_branch,PJSIP_RFC3261_BRANCH_LEN)==0) { /* Create transaction key. */ - create_tsx_key_3261(pool, key, role, method, branch); + return create_tsx_key_3261(pool, key, role, method, branch); } else { - /* Create the key for the message. This key will be matched up with the - * transaction key. For RFC2563 transactions, the transaction key - * was created by the same function, so it will match the message. + /* Create the key for the message. This key will be matched up + * with the transaction key. For RFC2563 transactions, the + * transaction key was created by the same function, so it will + * match the message. */ - create_tsx_key_2543( pool, key, role, method, rdata ); + return create_tsx_key_2543( pool, key, role, method, rdata ); } } @@ -318,10 +329,12 @@ PJ_DEF(void) pjsip_tsx_create_key( pj_pool_t *pool, pj_str_t *key, /* * Create new transaction. */ -PJ_DEF(pjsip_transaction *) pjsip_tsx_create(pj_pool_t *pool, - pjsip_endpoint *endpt) +pj_status_t pjsip_tsx_create( pj_pool_t *pool, + pjsip_endpoint *endpt, + pjsip_transaction **p_tsx) { pjsip_transaction *tsx; + pj_status_t status; tsx = pj_pool_calloc(pool, 1, sizeof(pjsip_transaction)); @@ -335,13 +348,14 @@ PJ_DEF(pjsip_transaction *) pjsip_tsx_create(pj_pool_t *pool, tsx->timeout_timer._timer_id = -1; tsx->timeout_timer.user_data = tsx; tsx->timeout_timer.cb = &tsx_timer_callback; - sprintf(tsx->obj_name, "tsx%p", tsx); - tsx->mutex = pj_mutex_create(pool, "mtsx%p", 0); - if (!tsx->mutex) { - return NULL; + pj_sprintf(tsx->obj_name, "tsx%p", tsx); + status = pj_mutex_create_recursive(pool, "mtsx%p", &tsx->mutex); + if (status != PJ_SUCCESS) { + return status; } - return tsx; + *p_tsx = tsx; + return PJ_SUCCESS; } /* @@ -352,7 +366,8 @@ static void lock_tsx(pjsip_transaction *tsx, struct tsx_lock_data *lck) struct tsx_lock_data *prev_data; pj_mutex_lock(tsx->mutex); - prev_data = (struct tsx_lock_data *) pj_thread_local_get(pjsip_tsx_lock_tls_id); + prev_data = (struct tsx_lock_data *) + pj_thread_local_get(pjsip_tsx_lock_tls_id); lck->prev = prev_data; lck->tsx = tsx; lck->is_alive = 1; @@ -367,7 +382,8 @@ static void lock_tsx(pjsip_transaction *tsx, struct tsx_lock_data *lck) * because when transaction is destroyed the is_alive flag for the transaction * will be set to zero. */ -static pj_status_t unlock_tsx(pjsip_transaction *tsx, struct tsx_lock_data *lck) +static pj_status_t unlock_tsx( pjsip_transaction *tsx, + struct tsx_lock_data *lck) { pj_assert( (void*)pj_thread_local_get(pjsip_tsx_lock_tls_id) == lck); pj_assert( lck->tsx == tsx ); @@ -375,7 +391,7 @@ static pj_status_t unlock_tsx(pjsip_transaction *tsx, struct tsx_lock_data *lck) if (lck->is_alive) pj_mutex_unlock(tsx->mutex); - return lck->is_alive ? 0 : -1; + return lck->is_alive ? PJ_SUCCESS : PJSIP_ETSXDESTROYED; } /* @@ -383,13 +399,14 @@ static pj_status_t unlock_tsx(pjsip_transaction *tsx, struct tsx_lock_data *lck) */ static void tsx_set_state( pjsip_transaction *tsx, pjsip_tsx_state_e state, - const pjsip_event *event ) + pjsip_event_id_e event_src_type, + void *event_src ) { pjsip_event e; - PJ_LOG(4, (tsx->obj_name, "STATE %s-->%s, ev=%s (src:%s)", - state_str[tsx->state], state_str[state], pjsip_event_str(event->type), - pjsip_event_str(event->src_type))); + PJ_LOG(4, (tsx->obj_name, "STATE %s-->%s, cause = %s", + state_str[tsx->state], state_str[state], + pjsip_event_str(event_src_type))); /* Change state. */ tsx->state = state; @@ -402,9 +419,7 @@ static void tsx_set_state( pjsip_transaction *tsx, } /* Inform TU */ - pj_memcpy(&e, event, sizeof(*event)); - e.type = PJSIP_EVENT_TSX_STATE_CHANGED; - e.obj.tsx = tsx; + PJSIP_EVENT_INIT_TSX_STATE(e, tsx, event_src_type, event_src); pjsip_endpt_send_tsx_event( tsx->endpt, &e ); /* When the transaction is terminated, release transport, and free the @@ -413,7 +428,9 @@ static void tsx_set_state( pjsip_transaction *tsx, if (state == PJSIP_TSX_STATE_TERMINATED) { /* Decrement transport reference counter. */ - if (tsx->transport && tsx->transport_state == PJSIP_TSX_TRANSPORT_STATE_FINAL) { + if (tsx->transport && + tsx->transport_state == PJSIP_TSX_TRANSPORT_STATE_FINAL) + { pjsip_transport_dec_ref( tsx->transport ); tsx->transport = NULL; } @@ -483,7 +500,8 @@ static pj_status_t tsx_process_route( pjsip_transaction *tsx, topmost_route_uri = &first_route_hdr->name_addr; while (last_route_hdr->next != (void*)&tdata->msg->hdr) { pjsip_route_hdr *hdr; - hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE, last_route_hdr->next); + hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE, + last_route_hdr->next); if (!hdr) break; last_route_hdr = hdr; @@ -563,14 +581,16 @@ static pj_status_t tsx_process_route( pjsip_transaction *tsx, send_addr->flag |= (PJSIP_TRANSPORT_SECURE | PJSIP_TRANSPORT_RELIABLE); pj_strdup(tdata->pool, &send_addr->host, &url->host); send_addr->port = url->port; - send_addr->type = pjsip_transport_get_type_from_name(&url->transport_param); + send_addr->type = + pjsip_transport_get_type_from_name(&url->transport_param); } else if (PJSIP_URI_SCHEME_IS_SIP(target_uri)) { pjsip_uri *uri = (pjsip_uri*) target_uri; const pjsip_url *url = (const pjsip_url*)pjsip_uri_get_uri(uri); pj_strdup(tdata->pool, &send_addr->host, &url->host); send_addr->port = url->port; - send_addr->type = pjsip_transport_get_type_from_name(&url->transport_param); + send_addr->type = + pjsip_transport_get_type_from_name(&url->transport_param); #if PJ_HAS_TCP if (send_addr->type == PJSIP_TRANSPORT_TCP || send_addr->type == PJSIP_TRANSPORT_SCTP) @@ -579,9 +599,8 @@ static pj_status_t tsx_process_route( pjsip_transaction *tsx, } #endif } else { - PJ_LOG(2, (tsx->obj_name, "Unable to lookup destination address for " - "non SIP-URL")); - return -1; + pj_assert(!"Unsupported URI scheme!"); + return PJSIP_EINVALIDSCHEME; } /* If target URI is different than request URI, replace @@ -598,7 +617,7 @@ static pj_status_t tsx_process_route( pjsip_transaction *tsx, } /* Success. */ - return 0; + return PJ_SUCCESS; } @@ -624,7 +643,7 @@ static void tsx_transport_callback(pjsip_transport_t *tr, pjsip_transport_get_type_name(tr), addr, tsx->dest_name.port)); } else { - PJ_LOG(3, (tsx->obj_name, "%s unable to connect to %s:%d, status=%d", + PJ_LOG(4, (tsx->obj_name, "%s unable to connect to %s:%d, status=%d", pjsip_transport_get_type_name(tr), addr, tsx->dest_name.port, status)); } @@ -633,23 +652,19 @@ static void tsx_transport_callback(pjsip_transport_t *tr, lock_tsx(tsx, &lck); if (status != PJ_SUCCESS) { - pjsip_event event; - - event.type = PJSIP_EVENT_TRANSPORT_ERROR; - event.src_type = PJSIP_EVENT_TX_MSG; - event.src.tdata = tsx->last_tx; - tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_FINAL; tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR; - tsx_set_state(tsx, PJSIP_TSX_STATE_TERMINATED, &event); + + tsx_set_state(tsx, PJSIP_TSX_STATE_TERMINATED, + PJSIP_EVENT_TRANSPORT_ERROR, (void*)status); /* Unlock transaction. */ unlock_tsx(tsx, &lck); return; } - /* See if transaction has already been terminated. If so, schedule to destroy - * the transaction. + /* See if transaction has already been terminated. + * If so, schedule to destroy the transaction. */ if (tsx->state == PJSIP_TSX_STATE_TERMINATED) { pj_time_val timeout = {0, 0}; @@ -690,15 +705,10 @@ static void tsx_resolver_callback(pj_status_t status, PJ_LOG(4, (tsx->obj_name, "resolver job complete, status=%d", status)); if (status != PJ_SUCCESS || addr->count == 0) { - pjsip_event event; - - event.type = PJSIP_EVENT_TRANSPORT_ERROR; - event.src_type = PJSIP_EVENT_TX_MSG; - event.src.tdata = tsx->last_tx; - lock_tsx(tsx, &lck); tsx->status_code = PJSIP_SC_TSX_RESOLVE_ERROR; - tsx_set_state(tsx, PJSIP_TSX_STATE_TERMINATED, &event); + tsx_set_state(tsx, PJSIP_TSX_STATE_TERMINATED, + PJSIP_EVENT_TRANSPORT_ERROR, (void*)status); unlock_tsx(tsx, &lck); return; } @@ -711,8 +721,8 @@ static void tsx_resolver_callback(pj_status_t status, /* Create/find the transport for the remote address. */ PJ_LOG(5,(tsx->obj_name, "tsx getting transport for %s:%d", - pj_sockaddr_get_str_addr(&addr->entry[0].addr), - pj_sockaddr_get_port(&addr->entry[0].addr))); + pj_inet_ntoa(addr->entry[0].addr.sin_addr), + pj_ntohs(addr->entry[0].addr.sin_port))); tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_CONNECTING; pjsip_endpt_get_transport(tsx->endpt, tsx->pool, @@ -738,8 +748,8 @@ PJ_DEF(pj_status_t) pjsip_tsx_init_uac( pjsip_transaction *tsx, pjsip_msg *msg; pjsip_cseq_hdr *cseq; pjsip_via_hdr *via; + pj_status_t status; struct tsx_lock_data lck; - const pjsip_hdr *endpt_hdr; PJ_LOG(4,(tsx->obj_name, "initializing tsx as UAC (tdata=%p)", tdata)); @@ -755,7 +765,7 @@ PJ_DEF(pj_status_t) pjsip_tsx_init_uac( pjsip_transaction *tsx, /* Save method. */ pjsip_method_copy( tsx->pool, &tsx->method, &msg->line.req.method); - /* Generate branch parameter if it doesn't exist. */ + /* Generate Via header if it doesn't exist. */ via = pjsip_msg_find_hdr(msg, PJSIP_H_VIA, NULL); if (via == NULL) { via = pjsip_via_hdr_create(tdata->pool); @@ -771,23 +781,23 @@ PJ_DEF(pj_status_t) pjsip_tsx_init_uac( pjsip_transaction *tsx, tmp.ptr = via->branch_param.ptr + PJSIP_RFC3261_BRANCH_LEN; pj_generate_unique_string( &tmp ); - } - /* Copy branch parameter. */ - tsx->branch = via->branch_param; - - /* Add additional request headers from endpoint. */ - endpt_hdr = pjsip_endpt_get_request_headers(tsx->endpt)->next; - while (endpt_hdr != pjsip_endpt_get_request_headers(tsx->endpt)) { - pjsip_hdr *hdr = pjsip_hdr_shallow_clone(tdata->pool, endpt_hdr); - pjsip_msg_add_hdr( tdata->msg, hdr ); - endpt_hdr = endpt_hdr->next; + /* Save branch parameter. */ + tsx->branch = via->branch_param; + } else { + /* Copy branch parameter. */ + pj_strdup(tsx->pool, &tsx->branch, &via->branch_param); } + /* Generate transaction key. */ - create_tsx_key_3261( tsx->pool, &tsx->transaction_key, - PJSIP_ROLE_UAC, &tsx->method, - &via->branch_param); + status = create_tsx_key_3261( tsx->pool, &tsx->transaction_key, + PJSIP_ROLE_UAC, &tsx->method, + &via->branch_param); + if (status != PJ_SUCCESS) { + unlock_tsx(tsx, &lck); + return status; + } PJ_LOG(6, (tsx->obj_name, "tsx_key=%.*s", tsx->transaction_key.slen, tsx->transaction_key.ptr)); @@ -795,8 +805,9 @@ PJ_DEF(pj_status_t) pjsip_tsx_init_uac( pjsip_transaction *tsx, /* Save CSeq. */ cseq = pjsip_msg_find_hdr(msg, PJSIP_H_CSEQ, NULL); if (!cseq) { - PJ_LOG(4,(tsx->obj_name, "CSeq header not present in outgoing message!")); - return -1; + pj_assert(!"CSeq header not present in outgoing message!"); + unlock_tsx(tsx, &lck); + return PJSIP_EMISSINGHDR; } tsx->cseq = cseq->cseq; @@ -805,22 +816,17 @@ PJ_DEF(pj_status_t) pjsip_tsx_init_uac( pjsip_transaction *tsx, * Manually set-up the state becase we don't want to call the callback. */ tsx->state = PJSIP_TSX_STATE_NULL; - tsx->state_handler = pjsip_tsx_on_state_null; + tsx->state_handler = &pjsip_tsx_on_state_null; /* Get destination name from the message. */ - if (tsx_process_route(tsx, tdata, &tsx->dest_name) != 0) { - pjsip_event event; - PJ_LOG(3,(tsx->obj_name, "Error: unable to get destination address for request")); - - event.type = PJSIP_EVENT_TRANSPORT_ERROR; - event.src_type = PJSIP_EVENT_TX_MSG; - event.src.tdata = tsx->last_tx; - + status = tsx_process_route(tsx, tdata, &tsx->dest_name); + if (status != PJ_SUCCESS) { tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_FINAL; tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR; - tsx_set_state(tsx, PJSIP_TSX_STATE_TERMINATED, &event); + tsx_set_state(tsx, PJSIP_TSX_STATE_TERMINATED, + PJSIP_EVENT_TRANSPORT_ERROR, (void*)status); unlock_tsx(tsx, &lck); - return -1; + return status; } /* Resolve destination. @@ -858,6 +864,7 @@ PJ_DEF(pj_status_t) pjsip_tsx_init_uas( pjsip_transaction *tsx, pjsip_msg *msg = rdata->msg; pj_str_t *branch; pjsip_cseq_hdr *cseq; + pj_status_t status; struct tsx_lock_data lck; PJ_LOG(4,(tsx->obj_name, "initializing tsx as UAS (rdata=%p)", rdata)); @@ -877,8 +884,12 @@ PJ_DEF(pj_status_t) pjsip_tsx_init_uas( pjsip_transaction *tsx, /* Get transaction key either from branch for RFC3261 message, or * create transaction key. */ - pjsip_tsx_create_key(tsx->pool, &tsx->transaction_key, PJSIP_ROLE_UAS, - &tsx->method, rdata); + status = pjsip_tsx_create_key(tsx->pool, &tsx->transaction_key, + PJSIP_ROLE_UAS, &tsx->method, rdata); + if (status != PJ_SUCCESS) { + unlock_tsx(tsx, &lck); + return status; + } /* Duplicate branch parameter for transaction. */ branch = &rdata->via->branch_param; @@ -913,7 +924,8 @@ PJ_DEF(pj_status_t) pjsip_tsx_init_uas( pjsip_transaction *tsx, tsx->current_addr = 0; tsx->remote_addr.count = 1; - tsx->remote_addr.entry[0].type = pjsip_transport_get_type(tsx->transport); + tsx->remote_addr.entry[0].type = + pjsip_transport_get_type(tsx->transport); pj_memcpy(&tsx->remote_addr.entry[0].addr, &rdata->addr, rdata->addr_len); @@ -923,17 +935,10 @@ PJ_DEF(pj_status_t) pjsip_tsx_init_uas( pjsip_transaction *tsx, status = pjsip_get_response_addr(tsx->pool, rdata->transport, rdata->via, &tsx->dest_name); if (status != PJ_SUCCESS) { - pjsip_event event; - PJ_LOG(2,(tsx->obj_name, "Unable to get destination address " - "for response")); - - event.type = PJSIP_EVENT_TRANSPORT_ERROR; - event.src_type = PJSIP_EVENT_TX_MSG; - event.src.tdata = tsx->last_tx; - tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_FINAL; tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR; - tsx_set_state(tsx, PJSIP_TSX_STATE_TERMINATED, &event); + tsx_set_state(tsx, PJSIP_TSX_STATE_TERMINATED, + PJSIP_EVENT_TRANSPORT_ERROR, (void*)status); unlock_tsx(tsx, &lck); return status; } @@ -943,7 +948,8 @@ PJ_DEF(pj_status_t) pjsip_tsx_init_uas( pjsip_transaction *tsx, * the callback will be called. */ PJ_LOG(5,(tsx->obj_name, "tsx resolving destination %.*s:%d", - tsx->dest_name.host.slen, tsx->dest_name.host.ptr, + tsx->dest_name.host.slen, + tsx->dest_name.host.ptr, tsx->dest_name.port)); tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_RESOLVING; @@ -975,11 +981,14 @@ static void tsx_timer_callback( pj_timer_heap_t *theap, pj_timer_entry *entry) PJ_UNUSED_ARG(theap); PJ_LOG(5,(tsx->obj_name, "got timer event (%s timer)", - (entry->id == TSX_TIMER_RETRANSMISSION ? "Retransmit" : "Timeout"))); + (entry->id==TSX_TIMER_RETRANSMISSION ? "Retransmit" : "Timeout"))); - event.type = event.src_type = PJSIP_EVENT_TIMER; - event.src.timer = (entry->id == TSX_TIMER_RETRANSMISSION ? - &tsx->retransmit_timer : &tsx->timeout_timer); + + if (entry->id == TSX_TIMER_RETRANSMISSION) { + PJSIP_EVENT_INIT_TIMER(event, &tsx->retransmit_timer); + } else { + PJSIP_EVENT_INIT_TIMER(event, &tsx->timeout_timer); + } /* Dispatch event to transaction. */ lock_tsx(tsx, &lck); @@ -999,10 +1008,11 @@ PJ_DEF(void) pjsip_tsx_on_tx_ack( pjsip_transaction *tsx, pjsip_tx_data *tdata) { pjsip_msg *msg; pjsip_host_port dest_addr; - pjsip_event event; pjsip_via_hdr *via; struct tsx_lock_data lck; + pj_status_t status = PJ_SUCCESS; + /* Lock tsx. */ lock_tsx(tsx, &lck); pj_assert(tsx->handle_ack != 0); @@ -1023,8 +1033,8 @@ PJ_DEF(void) pjsip_tsx_on_tx_ack( pjsip_transaction *tsx, pjsip_tx_data *tdata) } /* Get destination name from the message. */ - if (tsx_process_route(tsx, tdata, &dest_addr) != 0){ - PJ_LOG(2,(tsx->obj_name, "Unable to get destination address for request")); + status = tsx_process_route(tsx, tdata, &dest_addr); + if (status != 0){ goto on_error; } @@ -1088,10 +1098,9 @@ on_error: * Send TERMINATED event. */ tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR; - event.type = PJSIP_EVENT_TRANSPORT_ERROR; - event.src_type = PJSIP_EVENT_TX_MSG; - event.src.tdata = tdata; - tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, &event); + + tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, + PJSIP_EVENT_TRANSPORT_ERROR, (void*)status); unlock_tsx(tsx, &lck); } @@ -1105,19 +1114,16 @@ PJ_DEF(void) pjsip_tsx_on_tx_msg( pjsip_transaction *tsx, { pjsip_event event; struct tsx_lock_data lck; + pj_status_t status; - PJ_LOG(5,(tsx->obj_name, "on transmit msg (tdata=%p)", tdata)); - - event.type = event.src_type = PJSIP_EVENT_TX_MSG; - event.src.tdata = tdata; + PJ_LOG(5,(tsx->obj_name, "Request to transmit msg on state %s (tdata=%p)", + state_str[tsx->state], tdata)); - PJ_LOG(5,(tsx->obj_name, "on state %s (ev=%s, src=%s, data=%p)", - state_str[tsx->state], pjsip_event_str(event.type), - pjsip_event_str(event.src_type), event.src.data)); + PJSIP_EVENT_INIT_TX_MSG(event, tsx, tdata); /* Dispatch to transaction. */ lock_tsx(tsx, &lck); - (*tsx->state_handler)(tsx, &event); + status = (*tsx->state_handler)(tsx, &event); unlock_tsx(tsx, &lck); } @@ -1130,17 +1136,16 @@ PJ_DEF(void) pjsip_tsx_on_rx_msg( pjsip_transaction *tsx, { pjsip_event event; struct tsx_lock_data lck; + pj_status_t status; - event.type = event.src_type = PJSIP_EVENT_RX_MSG; - event.src.rdata = rdata; + PJ_LOG(5,(tsx->obj_name, "Incoming msg on state %s (rdata=%p)", + state_str[tsx->state], rdata)); - PJ_LOG(5,(tsx->obj_name, "on state %s (ev=%s, src=%s, data=%p)", - state_str[tsx->state], pjsip_event_str(event.type), - pjsip_event_str(event.src_type), event.src.data)); + PJSIP_EVENT_INIT_RX_MSG(event, tsx, rdata); /* Dispatch to transaction. */ lock_tsx(tsx, &lck); - (*tsx->state_handler)(tsx, &event); + status = (*tsx->state_handler)(tsx, &event); unlock_tsx(tsx, &lck); } @@ -1149,17 +1154,12 @@ PJ_DEF(void) pjsip_tsx_on_rx_msg( pjsip_transaction *tsx, */ PJ_DEF(void) pjsip_tsx_terminate( pjsip_transaction *tsx, int code ) { - pjsip_event event; struct tsx_lock_data lck; lock_tsx(tsx, &lck); - tsx->status_code = code; - event.type = PJSIP_EVENT_USER; - event.src_type = PJSIP_EVENT_USER; - event.src.data = 0; - event.obj.tsx = tsx; - tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, &event); + tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, + PJSIP_EVENT_USER, NULL); unlock_tsx(tsx, &lck); } @@ -1169,14 +1169,15 @@ PJ_DEF(void) pjsip_tsx_terminate( pjsip_transaction *tsx, int code ) * If transport is not yet available, then do nothing. The message will be * transmitted when transport connection completion callback is called. */ -static int tsx_send_msg( pjsip_transaction *tsx, pjsip_tx_data *tdata) +static pj_status_t tsx_send_msg( pjsip_transaction *tsx, + pjsip_tx_data *tdata) { - pjsip_event event; + pj_status_t status = PJ_SUCCESS; PJ_LOG(5,(tsx->obj_name, "sending msg (tdata=%p)", tdata)); if (tsx->transport_state == PJSIP_TSX_TRANSPORT_STATE_FINAL) { - int sent; + pj_ssize_t sent; pjsip_event before_tx_event; pj_assert(tsx->transport != NULL); @@ -1199,25 +1200,22 @@ static int tsx_send_msg( pjsip_transaction *tsx, pjsip_tx_data *tdata) pj_strdup2(tdata->pool, &via->transport, pjsip_transport_get_type_name(tsx->transport)); pj_strdup2(tdata->pool, &via->sent_by.host, - pj_sockaddr_get_str_addr(addr_name)); - via->sent_by.port = pj_sockaddr_get_port(addr_name); + pj_inet_ntoa(addr_name->sin_addr)); + via->sent_by.port = pj_ntohs(addr_name->sin_port); } } /* Notify everybody we're about to send message. */ - before_tx_event.type = PJSIP_EVENT_BEFORE_TX; - before_tx_event.src_type = PJSIP_EVENT_TX_MSG; - before_tx_event.obj.tsx = tsx; - before_tx_event.src.tdata = tdata; - before_tx_event.data.long_data = tsx->retransmit_count; - pjsip_endpt_send_tsx_event( tsx->endpt, &before_tx_event ); + PJSIP_EVENT_INIT_PRE_TX_MSG(before_tx_event, tsx, tdata, + tsx->retransmit_count); + pjsip_endpt_send_tsx_event( tsx->endpt, &before_tx_event ); tsx->has_unsent_msg = 0; - sent = pjsip_transport_send_msg( - tsx->transport, tdata, - &tsx->remote_addr.entry[tsx->current_addr].addr - ); - if (sent < 1) { + status = pjsip_transport_send_msg( + tsx->transport, tdata, + &tsx->remote_addr.entry[tsx->current_addr].addr, + &sent); + if (status != PJ_SUCCESS) { goto on_error; } } else { @@ -1228,11 +1226,9 @@ static int tsx_send_msg( pjsip_transaction *tsx, pjsip_tx_data *tdata) on_error: tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR; - event.type = PJSIP_EVENT_TRANSPORT_ERROR; - event.src_type = PJSIP_EVENT_TX_MSG; - event.src.tdata = tdata; - tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, &event); - return -1; + tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, + PJSIP_EVENT_TRANSPORT_ERROR, (void*)status); + return status; } /* @@ -1241,6 +1237,8 @@ on_error: static pj_status_t pjsip_tsx_retransmit( pjsip_transaction *tsx, int should_restart_timer) { + pj_status_t status; + PJ_LOG(4,(tsx->obj_name, "retransmiting (tdata=%p, count=%d, restart?=%d)", tsx->last_tx, tsx->retransmit_count, should_restart_timer)); @@ -1248,8 +1246,9 @@ static pj_status_t pjsip_tsx_retransmit( pjsip_transaction *tsx, ++tsx->retransmit_count; - if (tsx_send_msg( tsx, tsx->last_tx) != 0) { - return -1; + status = tsx_send_msg( tsx, tsx->last_tx); + if (status != PJ_SUCCESS) { + return status; } /* Restart timer T1. */ @@ -1257,12 +1256,13 @@ static pj_status_t pjsip_tsx_retransmit( pjsip_transaction *tsx, pj_time_val timeout; int msec_time = (1 << (tsx->retransmit_count)) * PJSIP_T1_TIMEOUT; - if (tsx->method.id != PJSIP_INVITE_METHOD && msec_time > PJSIP_T2_TIMEOUT) + if (tsx->method.id!=PJSIP_INVITE_METHOD && msec_time>PJSIP_T2_TIMEOUT) msec_time = PJSIP_T2_TIMEOUT; timeout.sec = msec_time / 1000; timeout.msec = msec_time % 1000; - pjsip_endpt_schedule_timer( tsx->endpt, &tsx->retransmit_timer, &timeout); + pjsip_endpt_schedule_timer( tsx->endpt, &tsx->retransmit_timer, + &timeout); } return PJ_SUCCESS; @@ -1271,8 +1271,11 @@ static pj_status_t pjsip_tsx_retransmit( pjsip_transaction *tsx, /* * Handler for events in state Null. */ -static int pjsip_tsx_on_state_null( pjsip_transaction *tsx, pjsip_event *event ) +static pj_status_t pjsip_tsx_on_state_null( pjsip_transaction *tsx, + pjsip_event *event ) { + pj_status_t status; + pj_assert( tsx->state == PJSIP_TSX_STATE_NULL); pj_assert( tsx->last_tx == NULL ); pj_assert( tsx->has_unsent_msg == 0); @@ -1281,24 +1284,27 @@ static int pjsip_tsx_on_state_null( pjsip_transaction *tsx, pjsip_event *event /* Set state to Trying. */ pj_assert(event->type == PJSIP_EVENT_RX_MSG); - tsx_set_state( tsx, PJSIP_TSX_STATE_TRYING, event); + tsx_set_state( tsx, PJSIP_TSX_STATE_TRYING, + PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata ); } else { - pjsip_tx_data *tdata = event->src.tdata; + pjsip_tx_data *tdata = event->body.tx_msg.tdata; /* Save the message for retransmission. */ tsx->last_tx = tdata; pjsip_tx_data_add_ref(tdata); /* Send the message. */ - if (tsx_send_msg( tsx, tdata) != 0) { - return -1; + status = tsx_send_msg( tsx, tdata); + if (status != PJ_SUCCESS) { + return status; } /* Start Timer B (or called timer F for non-INVITE) for transaction * timeout. */ - pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer, &timeout_timer_val); + pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer, + &timeout_timer_val); /* Start Timer A (or timer E) for retransmission only if unreliable * transport is being used. @@ -1306,12 +1312,14 @@ static int pjsip_tsx_on_state_null( pjsip_transaction *tsx, pjsip_event *event if (tsx->transport_state == PJSIP_TSX_TRANSPORT_STATE_FINAL && PJSIP_TRANSPORT_IS_RELIABLE(tsx->transport)==0) { - pjsip_endpt_schedule_timer(tsx->endpt, &tsx->retransmit_timer, &t1_timer_val); + pjsip_endpt_schedule_timer(tsx->endpt, &tsx->retransmit_timer, + &t1_timer_val); tsx->retransmit_count = 0; } /* Move state. */ - tsx_set_state( tsx, PJSIP_TSX_STATE_CALLING, event); + tsx_set_state( tsx, PJSIP_TSX_STATE_CALLING, + PJSIP_EVENT_TX_MSG, tdata); } return PJ_SUCCESS; @@ -1321,23 +1329,25 @@ static int pjsip_tsx_on_state_null( pjsip_transaction *tsx, pjsip_event *event * State Calling is for UAC after it sends request but before any responses * is received. */ -static int pjsip_tsx_on_state_calling( pjsip_transaction *tsx, - pjsip_event *event) +static pj_status_t pjsip_tsx_on_state_calling( pjsip_transaction *tsx, + pjsip_event *event ) { pj_assert(tsx->state == PJSIP_TSX_STATE_CALLING); pj_assert(tsx->role == PJSIP_ROLE_UAC); if (event->type == PJSIP_EVENT_TIMER && - event->src.timer == &tsx->retransmit_timer) + event->body.timer.entry == &tsx->retransmit_timer) { + pj_status_t status; /* Retransmit the request. */ - if (pjsip_tsx_retransmit( tsx, 1 ) != 0) { - return -1; + status = pjsip_tsx_retransmit( tsx, 1 ); + if (status != PJ_SUCCESS) { + return status; } } else if (event->type == PJSIP_EVENT_TIMER && - event->src.timer == &tsx->timeout_timer) + event->body.timer.entry == &tsx->timeout_timer) { /* Cancel retransmission timer. */ @@ -1349,10 +1359,11 @@ static int pjsip_tsx_on_state_calling( pjsip_transaction *tsx, tsx->status_code = PJSIP_SC_TSX_TIMEOUT; /* Inform TU. */ - tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, event ); + tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, + PJSIP_EVENT_TIMER, &tsx->timeout_timer); /* Transaction is destroyed */ - return -1; + return PJSIP_ETSXDESTROYED; } else if (event->type == PJSIP_EVENT_RX_MSG) { int code; @@ -1369,7 +1380,7 @@ static int pjsip_tsx_on_state_calling( pjsip_transaction *tsx, * the final response. */ /* Keep last_tx for authorization. */ - code = event->src.rdata->msg->line.status.code; + code = event->body.rx_msg.rdata->msg->line.status.code; if (tsx->method.id != PJSIP_INVITE_METHOD && code!=401 && code!=407) { pjsip_tx_data_dec_ref(tsx->last_tx); tsx->last_tx = NULL; @@ -1380,6 +1391,7 @@ static int pjsip_tsx_on_state_calling( pjsip_transaction *tsx, } else { pj_assert(0); + return PJ_EBUG; } return PJ_SUCCESS; @@ -1391,9 +1403,10 @@ static int pjsip_tsx_on_state_calling( pjsip_transaction *tsx, * Note: this is different than RFC3261, which can use Trying state for * non-INVITE client transaction (bug in RFC?). */ -static int pjsip_tsx_on_state_trying( pjsip_transaction *tsx, pjsip_event *event) +static pj_status_t pjsip_tsx_on_state_trying( pjsip_transaction *tsx, + pjsip_event *event) { - int result; + pj_status_t status; pj_assert(tsx->state == PJSIP_TSX_STATE_TRYING); @@ -1414,21 +1427,23 @@ static int pjsip_tsx_on_state_trying( pjsip_transaction *tsx, pjsip_event *even /* The rest of the processing of the event is exactly the same as in * "Proceeding" state. */ - result = pjsip_tsx_on_state_proceeding_uas( tsx, event); + status = pjsip_tsx_on_state_proceeding_uas( tsx, event); /* Inform the TU of the state transision if state is still State_Trying */ - if (result==0 && tsx->state == PJSIP_TSX_STATE_TRYING) { - tsx_set_state( tsx, PJSIP_TSX_STATE_PROCEEDING, event); + if (status==PJ_SUCCESS && tsx->state == PJSIP_TSX_STATE_TRYING) { + tsx_set_state( tsx, PJSIP_TSX_STATE_PROCEEDING, + PJSIP_EVENT_TX_MSG, event->body.tx_msg.tdata); } - return result; + return status; } /* * Handler for events in Proceeding for UAS * This state happens after the TU sends provisional response. */ -static int pjsip_tsx_on_state_proceeding_uas( pjsip_transaction *tsx, pjsip_event *event) +static pj_status_t pjsip_tsx_on_state_proceeding_uas( pjsip_transaction *tsx, + pjsip_event *event) { pj_assert(tsx->state == PJSIP_TSX_STATE_PROCEEDING || tsx->state == PJSIP_TSX_STATE_TRYING); @@ -1439,13 +1454,17 @@ static int pjsip_tsx_on_state_proceeding_uas( pjsip_transaction *tsx, pjsip_even /* Receive request retransmission. */ if (event->type == PJSIP_EVENT_RX_MSG) { + pj_status_t status; + /* Send last response. */ - if (pjsip_tsx_retransmit( tsx, 0 ) != 0) { - return -1; + status = pjsip_tsx_retransmit( tsx, 0 ); + if (status != PJ_SUCCESS) { + return status; } } else if (event->type == PJSIP_EVENT_TX_MSG ) { - pjsip_tx_data *tdata = event->src.tdata; + pjsip_tx_data *tdata = event->body.tx_msg.tdata; + pj_status_t status; /* The TU sends response message to the request. Save this message so * that we can retransmit the last response in case we receive request @@ -1471,8 +1490,9 @@ static int pjsip_tsx_on_state_proceeding_uas( pjsip_transaction *tsx, pjsip_even } /* Send the message. */ - if (tsx_send_msg(tsx, tdata) != 0) { - return -1; + status = tsx_send_msg(tsx, tdata); + if (status != PJ_SUCCESS) { + return status; } // Update To tag header for RFC2543 transaction. @@ -1485,26 +1505,29 @@ static int pjsip_tsx_on_state_proceeding_uas( pjsip_transaction *tsx, pjsip_even tsx->last_tx = tdata; pjsip_tx_data_add_ref( tdata ); } - tsx_set_state( tsx, PJSIP_TSX_STATE_PROCEEDING, event); + tsx_set_state( tsx, PJSIP_TSX_STATE_PROCEEDING, + PJSIP_EVENT_TX_MSG, tdata ); } else if (PJSIP_IS_STATUS_IN_CLASS(tsx->status_code, 200)) { if (tsx->method.id == PJSIP_INVITE_METHOD && tsx->handle_ack==0) { - /* 2xx class message is not saved, because retransmission is handled - * by the TU. + /* 2xx class message is not saved, because retransmission + * is handled by TU. */ - tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, event); + tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, + PJSIP_EVENT_TX_MSG, tdata ); /* Transaction is destroyed. */ - return -1; + return PJSIP_ETSXDESTROYED; } else { pj_time_val timeout; if (tsx->method.id == PJSIP_INVITE_METHOD) { tsx->retransmit_count = 0; - pjsip_endpt_schedule_timer( tsx->endpt, &tsx->retransmit_timer, + pjsip_endpt_schedule_timer( tsx->endpt, + &tsx->retransmit_timer, &t1_timer_val); } @@ -1525,37 +1548,45 @@ static int pjsip_tsx_on_state_proceeding_uas( pjsip_transaction *tsx, pjsip_even timeout.sec = timeout.msec = 0; } - pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer, &timeout); + pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer, + &timeout); /* Set state to "Completed" */ - tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED, event); + tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED, + PJSIP_EVENT_TX_MSG, tdata ); } } else if (tsx->status_code >= 300) { - /* 3xx-6xx class message causes transaction to move to "Completed" state. */ + /* 3xx-6xx class message causes transaction to move to + * "Completed" state. + */ if (tsx->last_tx != tdata) { tsx->last_tx = tdata; pjsip_tx_data_add_ref( tdata ); } /* Start timer H for transaction termination */ - pjsip_endpt_schedule_timer(tsx->endpt,&tsx->timeout_timer,&timeout_timer_val); + pjsip_endpt_schedule_timer(tsx->endpt,&tsx->timeout_timer, + &timeout_timer_val); /* For INVITE, if unreliable transport is used, retransmission * timer G will be scheduled (retransmission). */ if (PJSIP_TRANSPORT_IS_RELIABLE(tsx->transport)==0) { - pjsip_cseq_hdr *cseq = pjsip_msg_find_hdr( msg, PJSIP_H_CSEQ, NULL); + pjsip_cseq_hdr *cseq = pjsip_msg_find_hdr( msg, PJSIP_H_CSEQ, + NULL); if (cseq->method.id == PJSIP_INVITE_METHOD) { tsx->retransmit_count = 0; - pjsip_endpt_schedule_timer(tsx->endpt, &tsx->retransmit_timer, + pjsip_endpt_schedule_timer(tsx->endpt, + &tsx->retransmit_timer, &t1_timer_val); } } /* Inform TU */ - tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED, event); + tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED, + PJSIP_EVENT_TX_MSG, tdata ); } else { pj_assert(0); @@ -1563,34 +1594,38 @@ static int pjsip_tsx_on_state_proceeding_uas( pjsip_transaction *tsx, pjsip_even } else if (event->type == PJSIP_EVENT_TIMER && - event->src.timer == &tsx->retransmit_timer) { + event->body.timer.entry == &tsx->retransmit_timer) { /* Retransmission timer elapsed. */ + pj_status_t status; /* Must have last response to retransmit. */ pj_assert(tsx->last_tx != NULL); /* Retransmit the last response. */ - if (pjsip_tsx_retransmit( tsx, 1 ) != 0) { - return -1; + status = pjsip_tsx_retransmit( tsx, 1 ); + if (status != PJ_SUCCESS) { + return status; } } else if (event->type == PJSIP_EVENT_TIMER && - event->src.timer == &tsx->timeout_timer) { + event->body.timer.entry == &tsx->timeout_timer) { /* Timeout timer. should not happen? */ pj_assert(0); tsx->status_code = PJSIP_SC_TSX_TIMEOUT; - tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, event); + tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, + PJSIP_EVENT_TIMER, &tsx->timeout_timer); - return -1; + return PJ_EBUG; } else { pj_assert(0); + return PJ_EBUG; } - return 0; + return PJ_SUCCESS; } /* @@ -1598,7 +1633,8 @@ static int pjsip_tsx_on_state_proceeding_uas( pjsip_transaction *tsx, pjsip_even * This state happens after provisional response(s) has been received from * UAS. */ -static int pjsip_tsx_on_state_proceeding_uac( pjsip_transaction *tsx, pjsip_event *event) +static pj_status_t pjsip_tsx_on_state_proceeding_uac(pjsip_transaction *tsx, + pjsip_event *event) { pj_assert(tsx->state == PJSIP_TSX_STATE_PROCEEDING || @@ -1610,10 +1646,10 @@ static int pjsip_tsx_on_state_proceeding_uac( pjsip_transaction *tsx, pjsip_even */ pj_assert(event->type == PJSIP_EVENT_RX_MSG); if (event->type != PJSIP_EVENT_RX_MSG) { - return 0; + return PJ_EINVALIDOP; } - tsx->status_code = event->src.rdata->msg->line.status.code; + tsx->status_code = event->body.rx_msg.rdata->msg->line.status.code; } else { tsx->status_code = PJSIP_SC_TSX_TIMEOUT; } @@ -1621,7 +1657,8 @@ static int pjsip_tsx_on_state_proceeding_uac( pjsip_transaction *tsx, pjsip_even if (PJSIP_IS_STATUS_IN_CLASS(tsx->status_code, 100)) { /* Inform the message to TU. */ - tsx_set_state( tsx, PJSIP_TSX_STATE_PROCEEDING, event); + tsx_set_state( tsx, PJSIP_TSX_STATE_PROCEEDING, + PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata ); } else if (PJSIP_IS_STATUS_IN_CLASS(tsx->status_code,200)) { @@ -1632,8 +1669,9 @@ static int pjsip_tsx_on_state_proceeding_uac( pjsip_transaction *tsx, pjsip_even * handled in TU). For non-INVITE, state moves to Completed. */ if (tsx->method.id == PJSIP_INVITE_METHOD && tsx->handle_ack == 0) { - tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, event); - return -1; + tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, + PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata ); + return PJSIP_ETSXDESTROYED; } else { pj_time_val timeout; @@ -1649,23 +1687,28 @@ static int pjsip_tsx_on_state_proceeding_uac( pjsip_transaction *tsx, pjsip_even } else { timeout.sec = timeout.msec = 0; } - pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer, &timeout); + pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer, + &timeout); /* Move state to Completed, inform TU. */ - tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED, event); + tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED, + PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata ); } } else if (tsx->status_code >= 300 && tsx->status_code <= 699) { pj_time_val timeout; + pj_status_t status; /* Stop timer B. */ pjsip_endpt_cancel_timer( tsx->endpt, &tsx->timeout_timer ); /* Generate and send ACK for INVITE. */ if (tsx->method.id == PJSIP_INVITE_METHOD) { - pjsip_endpt_create_ack( tsx->endpt, tsx->last_tx, event->src.rdata ); - if (tsx_send_msg( tsx, tsx->last_tx) != 0) { - return -1; + pjsip_endpt_create_ack( tsx->endpt, tsx->last_tx, + event->body.rx_msg.rdata ); + status = tsx_send_msg( tsx, tsx->last_tx); + if (status != PJ_SUCCESS) { + return status; } } @@ -1682,11 +1725,13 @@ static int pjsip_tsx_on_state_proceeding_uac( pjsip_transaction *tsx, pjsip_even pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer, &timeout); /* Inform TU. */ - tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED, event); + tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED, + PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata ); } else { // Shouldn't happen because there's no timer for this state. pj_assert(0); + return PJ_EBUG; } return PJ_SUCCESS; @@ -1695,18 +1740,22 @@ static int pjsip_tsx_on_state_proceeding_uac( pjsip_transaction *tsx, pjsip_even /* * Handler for events in Completed state for UAS */ -static int pjsip_tsx_on_state_completed_uas( pjsip_transaction *tsx, pjsip_event *event) +static pj_status_t pjsip_tsx_on_state_completed_uas( pjsip_transaction *tsx, + pjsip_event *event) { pj_assert(tsx->state == PJSIP_TSX_STATE_COMPLETED); if (event->type == PJSIP_EVENT_RX_MSG) { - pjsip_msg *msg = event->src.rdata->msg; + pjsip_msg *msg = event->body.rx_msg.rdata->msg; pjsip_cseq_hdr *cseq = pjsip_msg_find_hdr( msg, PJSIP_H_CSEQ, NULL ); /* On receive request retransmission, retransmit last response. */ if (cseq->method.id != PJSIP_ACK_METHOD) { - if (pjsip_tsx_retransmit( tsx, 0 ) != 0) { - return -1; + pj_status_t status; + + status = pjsip_tsx_retransmit( tsx, 0 ); + if (status != PJ_SUCCESS) { + return status; } } else { @@ -1717,18 +1766,23 @@ static int pjsip_tsx_on_state_completed_uas( pjsip_transaction *tsx, pjsip_event /* Start timer I in T4 interval (transaction termination). */ pjsip_endpt_cancel_timer( tsx->endpt, &tsx->timeout_timer ); - pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer, &t4_timer_val); + pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer, + &t4_timer_val); /* Move state to "Confirmed" */ - tsx_set_state( tsx, PJSIP_TSX_STATE_CONFIRMED, event); + tsx_set_state( tsx, PJSIP_TSX_STATE_CONFIRMED, + PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata ); } } else if (event->type == PJSIP_EVENT_TIMER) { - if (event->src.timer == &tsx->retransmit_timer) { + if (event->body.timer.entry == &tsx->retransmit_timer) { /* Retransmit message. */ - if (pjsip_tsx_retransmit( tsx, 1 ) != 0) { - return -1; + pj_status_t status; + + status = pjsip_tsx_retransmit( tsx, 1 ); + if (status != PJ_SUCCESS) { + return status; } } else { @@ -1740,20 +1794,22 @@ static int pjsip_tsx_on_state_completed_uas( pjsip_transaction *tsx, pjsip_event tsx->status_code = PJSIP_SC_TSX_TIMEOUT; - tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, event); + tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, + PJSIP_EVENT_TIMER, &tsx->timeout_timer ); - return -1; + return PJSIP_ETSXDESTROYED; } else { /* Transaction terminated, it can now be deleted. */ - tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, event); - return -1; + tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, + PJSIP_EVENT_TIMER, &tsx->timeout_timer ); + return PJSIP_ETSXDESTROYED; } } } else { /* Ignore request to transmit. */ - pj_assert(event->src.tdata == tsx->last_tx); + pj_assert(event->body.tx_msg.tdata == tsx->last_tx); } return PJ_SUCCESS; @@ -1762,32 +1818,37 @@ static int pjsip_tsx_on_state_completed_uas( pjsip_transaction *tsx, pjsip_event /* * Handler for events in Completed state for UAC transaction. */ -static int pjsip_tsx_on_state_completed_uac( pjsip_transaction *tsx, pjsip_event *event) +static pj_status_t pjsip_tsx_on_state_completed_uac( pjsip_transaction *tsx, + pjsip_event *event) { pj_assert(tsx->state == PJSIP_TSX_STATE_COMPLETED); if (event->type == PJSIP_EVENT_TIMER) { /* Must be the timeout timer. */ - pj_assert(event->src.timer == &tsx->timeout_timer); + pj_assert(event->body.timer.entry == &tsx->timeout_timer); /* Move to Terminated state. */ - tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, event); + tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, + PJSIP_EVENT_TIMER, event->body.timer.entry ); /* Transaction has been destroyed. */ - return -1; + return PJSIP_ETSXDESTROYED; } else if (event->type == PJSIP_EVENT_RX_MSG) { if (tsx->method.id == PJSIP_INVITE_METHOD) { /* On received of final response retransmission, retransmit the ACK. * TU doesn't need to be informed. */ - pjsip_msg *msg = event->src.rdata->msg; + pjsip_msg *msg = event->body.rx_msg.rdata->msg; pj_assert(msg->type == PJSIP_RESPONSE_MSG); if (msg->type==PJSIP_RESPONSE_MSG && msg->line.status.code >= 200) { - if (pjsip_tsx_retransmit( tsx, 0 ) != 0) { - return -1; + pj_status_t status; + + status = pjsip_tsx_retransmit( tsx, 0 ); + if (status != PJ_SUCCESS) { + return status; } } else { /* Very late retransmission of privisional response. */ @@ -1798,34 +1859,41 @@ static int pjsip_tsx_on_state_completed_uac( pjsip_transaction *tsx, pjsip_event } } else if (tsx->method.id == PJSIP_INVITE_METHOD && event->type == PJSIP_EVENT_TX_MSG && - event->src.tdata->msg->line.req.method.id == PJSIP_ACK_METHOD) { + event->body.tx_msg.tdata->msg->line.req.method.id==PJSIP_ACK_METHOD) { + + pj_status_t status; /* Set last transmitted message. */ - if (tsx->last_tx != event->src.tdata) { + if (tsx->last_tx != event->body.tx_msg.tdata) { pjsip_tx_data_dec_ref( tsx->last_tx ); - tsx->last_tx = event->src.tdata; + tsx->last_tx = event->body.tx_msg.tdata; pjsip_tx_data_add_ref( tsx->last_tx ); } /* No state changed, but notify app. * Must notify now, so app has chance to put SDP in outgoing ACK msg. */ - tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED, event ); + tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED, + PJSIP_EVENT_TX_MSG, event->body.tx_msg.tdata ); /* Send msg */ - tsx_send_msg(tsx, event->src.tdata); + status = tsx_send_msg(tsx, event->body.tx_msg.tdata); + if (status != PJ_SUCCESS) + return status; } else { pj_assert(0); + return PJ_EBUG; } - return 0; + return PJ_SUCCESS; } /* * Handler for events in state Confirmed. */ -static int pjsip_tsx_on_state_confirmed( pjsip_transaction *tsx, pjsip_event *event) +static pj_status_t pjsip_tsx_on_state_confirmed( pjsip_transaction *tsx, + pjsip_event *event) { pj_assert(tsx->state == PJSIP_TSX_STATE_CONFIRMED); @@ -1835,25 +1903,36 @@ static int pjsip_tsx_on_state_confirmed( pjsip_transaction *tsx, pjsip_event *ev /* Absorb any ACK received. */ if (event->type == PJSIP_EVENT_RX_MSG) { + + pjsip_method_e method_id = + event->body.rx_msg.rdata->msg->line.req.method.id; + /* Must be a request message. */ - pj_assert(event->src.rdata->msg->type == PJSIP_REQUEST_MSG); + pj_assert(event->body.rx_msg.rdata->msg->type == PJSIP_REQUEST_MSG); /* Must be an ACK request or a late INVITE retransmission. */ - pj_assert(event->src.rdata->msg->line.req.method.id == PJSIP_ACK_METHOD || - event->src.rdata->msg->line.req.method.id == PJSIP_INVITE_METHOD); + pj_assert(method_id == PJSIP_ACK_METHOD || + method_id == PJSIP_INVITE_METHOD); + + /* Just so that compiler won't complain about unused vars when + * building release code. + */ + PJ_UNUSED_ARG(method_id); } else if (event->type == PJSIP_EVENT_TIMER) { /* Must be from timeout_timer_. */ - pj_assert(event->src.timer == &tsx->timeout_timer); + pj_assert(event->body.timer.entry == &tsx->timeout_timer); /* Move to Terminated state. */ - tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, event); + tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, + PJSIP_EVENT_TIMER, &tsx->timeout_timer ); /* Transaction has been destroyed. */ - return -1; + return PJSIP_ETSXDESTROYED; } else { pj_assert(0); + return PJ_EBUG; } return PJ_SUCCESS; @@ -1862,23 +1941,26 @@ static int pjsip_tsx_on_state_confirmed( pjsip_transaction *tsx, pjsip_event *ev /* * Handler for events in state Terminated. */ -static int pjsip_tsx_on_state_terminated( pjsip_transaction *tsx, pjsip_event *event) +static pj_status_t pjsip_tsx_on_state_terminated( pjsip_transaction *tsx, + pjsip_event *event) { pj_assert(tsx->state == PJSIP_TSX_STATE_TERMINATED); - PJ_UNUSED_ARG(event) + PJ_UNUSED_ARG(event); /* Destroy this transaction */ - tsx_set_state(tsx, PJSIP_TSX_STATE_DESTROYED, event); + tsx_set_state(tsx, PJSIP_TSX_STATE_DESTROYED, + event->type, event->body.user.user1 ); return PJ_SUCCESS; } -static int pjsip_tsx_on_state_destroyed( pjsip_transaction *tsx, pjsip_event *event) +static pj_status_t pjsip_tsx_on_state_destroyed(pjsip_transaction *tsx, + pjsip_event *event) { - PJ_UNUSED_ARG(tsx) - PJ_UNUSED_ARG(event) + PJ_UNUSED_ARG(tsx); + PJ_UNUSED_ARG(event); return PJ_SUCCESS; } diff --git a/pjsip/src/pjsip/sip_transport.c b/pjsip/src/pjsip/sip_transport.c index 65b8ec45..09eb6cfb 100644 --- a/pjsip/src/pjsip/sip_transport.c +++ b/pjsip/src/pjsip/sip_transport.c @@ -1,17 +1,18 @@ /* $Id$ - * */ #include <pjsip/sip_transport.h> #include <pjsip/sip_endpoint.h> #include <pjsip/sip_parser.h> #include <pjsip/sip_msg.h> #include <pjsip/sip_private.h> +#include <pjsip/sip_errno.h>
#include <pj/os.h> #include <pj/log.h> #include <pj/ioqueue.h> #include <pj/hash.h> #include <pj/string.h> #include <pj/pool.h> +#include <pj/assert.h>
#define MGR_IDLE_CHECK_INTERVAL 30 #define MGR_HASH_TABLE_SIZE PJSIP_MAX_DIALOG_COUNT @@ -44,7 +45,7 @@ struct pjsip_transport_t /** Standard list members, for chaining the transport in the * listener list. */ - PJ_DECL_LIST_MEMBER(struct pjsip_transport_t) + PJ_DECL_LIST_MEMBER(struct pjsip_transport_t); /** Transport's pool. */ pj_pool_t *pool; @@ -66,10 +67,13 @@ struct pjsip_transport_t /** I/O Queue key */ pj_ioqueue_key_t *key; - +
+ /** Accept key. */
+ pj_ioqueue_op_key_t accept_op;
+
/** Receive data buffer */ pjsip_rx_data *rdata; - +
/** Pointer to transport manager */ pjsip_transport_mgr *mgr; @@ -114,7 +118,9 @@ struct pjsip_transport_mgr pj_mutex_t *mutex; pjsip_endpoint *endpt; pj_ioqueue_t *ioqueue; - pj_time_val next_idle_check; + pj_time_val next_idle_check;
+ pj_size_t send_buf_size;
+ pj_size_t recv_buf_size; void (*message_callback)(pjsip_endpoint*, pjsip_rx_data *rdata); }; @@ -144,7 +150,7 @@ typedef struct transport_key */ struct transport_callback { - PJ_DECL_LIST_MEMBER(struct transport_callback) + PJ_DECL_LIST_MEMBER(struct transport_callback); /** User defined token to be passed to the callback. */ void *token; @@ -173,10 +179,18 @@ const struct #endif }; -static void on_ioqueue_read(pj_ioqueue_key_t *key, pj_ssize_t bytes_read); -static void on_ioqueue_write(pj_ioqueue_key_t *key, pj_ssize_t bytes_sent); -static void on_ioqueue_accept(pj_ioqueue_key_t *key, int status); -static void on_ioqueue_connect(pj_ioqueue_key_t *key, int status); +static void on_ioqueue_read(pj_ioqueue_key_t *key,
+ pj_ioqueue_op_key_t *op_key,
+ pj_ssize_t bytes_read); +static void on_ioqueue_write(pj_ioqueue_key_t *key,
+ pj_ioqueue_op_key_t *op_key,
+ pj_ssize_t bytes_sent); +static void on_ioqueue_accept(pj_ioqueue_key_t *key,
+ pj_ioqueue_op_key_t *op_key,
+ pj_sock_t newsock,
+ int status); +static void on_ioqueue_connect(pj_ioqueue_key_t *key,
+ int status); static pj_ioqueue_callback ioqueue_transport_callback = { @@ -194,11 +208,11 @@ static void init_key_from_transport(transport_key *key, key->type = (pj_uint8_t)tr->type; key->zero = 0; - key->addr = pj_sockaddr_get_addr(&tr->remote_addr); - key->port = pj_sockaddr_get_port(&tr->remote_addr); + key->addr = pj_sockaddr_in_get_addr(&tr->remote_addr).s_addr; + key->port = pj_sockaddr_in_get_port(&tr->remote_addr); /* if (key->port == 0) { - key->port = pj_sockaddr_get_port(&tr->local_addr); + key->port = pj_sockaddr_in_get_port(&tr->local_addr); } */ } @@ -212,15 +226,15 @@ static void init_tcp_key(transport_key *key, pjsip_transport_type_e type, key->type = (pj_uint8_t)type; key->zero = 0; - key->addr = pj_sockaddr_get_addr(addr); - key->port = pj_sockaddr_get_port(addr); + key->addr = pj_sockaddr_in_get_addr(addr).s_addr; + key->port = pj_sockaddr_in_get_port(addr); } #endif static void init_udp_key(transport_key *key, pjsip_transport_type_e type, const pj_sockaddr_in *addr) { - PJ_UNUSED_ARG(addr) + PJ_UNUSED_ARG(addr); /* This is to detect alignment problems. */ pj_assert(sizeof(transport_key) == 8); @@ -236,7 +250,7 @@ static void init_udp_key(transport_key *key, pjsip_transport_type_e type, pj_str_t localaddr = pj_str("127.0.0.1"); pj_sockaddr_in addr; pj_sockaddr_set_str_addr(&addr, &localaddr); - key->addr = pj_sockaddr_get_addr(&addr); + key->addr = pj_sockaddr_in_get_addr(&addr); } #endif } @@ -297,31 +311,36 @@ pjsip_transport_get_type_from_name(const pj_str_t *name) /* * Create new transmit buffer. */ -pjsip_tx_data* pjsip_tx_data_create( pjsip_transport_mgr *mgr ) +pj_status_t pjsip_tx_data_create( pjsip_transport_mgr *mgr,
+ pjsip_tx_data **p_tdata ) { pj_pool_t *pool; pjsip_tx_data *tdata; + pj_status_t status;
PJ_LOG(5, ("", "pjsip_tx_data_create")); +
+ PJ_ASSERT_RETURN(mgr && p_tdata, PJ_EINVAL);
pool = pjsip_endpt_create_pool( mgr->endpt, "ptdt%p", PJSIP_POOL_LEN_TDATA, PJSIP_POOL_INC_TDATA ); if (!pool) { - return NULL; + return PJ_ENOMEM; } tdata = pj_pool_calloc(pool, 1, sizeof(pjsip_tx_data)); tdata->pool = pool; tdata->mgr = mgr; - sprintf(tdata->obj_name,"txd%p", tdata); + pj_sprintf(tdata->obj_name,"txd%p", tdata); - tdata->ref_cnt = pj_atomic_create(tdata->pool, 0); - if (!tdata->ref_cnt) { + status = pj_atomic_create(tdata->pool, 0, &tdata->ref_cnt); + if (status != PJ_SUCCESS) { pjsip_endpt_destroy_pool( mgr->endpt, tdata->pool ); - return NULL; + return status; } - - return tdata; +
+ *p_tdata = tdata; + return PJ_SUCCESS; } /* @@ -339,7 +358,7 @@ PJ_DEF(void) pjsip_tx_data_add_ref( pjsip_tx_data *tdata ) PJ_DEF(void) pjsip_tx_data_dec_ref( pjsip_tx_data *tdata ) { pj_assert( pj_atomic_get(tdata->ref_cnt) > 0); - if (pj_atomic_dec(tdata->ref_cnt) <= 0) { + if (pj_atomic_dec_and_get(tdata->ref_cnt) <= 0) { PJ_LOG(6,(tdata->obj_name, "destroying txdata")); pj_atomic_destroy( tdata->ref_cnt ); pjsip_endpt_destroy_pool( tdata->mgr->endpt, tdata->pool ); @@ -375,7 +394,7 @@ PJ_DEF(pjsip_transport_type_e) pjsip_get_transport_type_from_flag(unsigned flag) return PJSIP_TRANSPORT_TCP; } else #else - PJ_UNUSED_ARG(flag) + PJ_UNUSED_ARG(flag); #endif { return PJSIP_TRANSPORT_UDP; @@ -452,7 +471,7 @@ PJ_DEF(void) pjsip_transport_add_ref( pjsip_transport_t * tr ) PJ_DEF(void) pjsip_transport_dec_ref( pjsip_transport_t *tr ) { pj_assert(tr->ref_cnt > 0); - if (pj_atomic_dec(tr->ref_cnt) == 0) { + if (pj_atomic_dec_and_get(tr->ref_cnt) == 0) { pj_gettimeofday(&tr->close_time); tr->close_time.sec += PJSIP_TRANSPORT_CLOSE_TIMEOUT; } @@ -461,13 +480,15 @@ PJ_DEF(void) pjsip_transport_dec_ref( pjsip_transport_t *tr ) /* * Open the underlying transport. */ -static pj_sock_t create_socket( pjsip_transport_type_e type, - pj_sockaddr_in *local ) +static pj_status_t create_socket( pjsip_transport_type_e type, + pj_sockaddr_in *local,
+ pj_sock_t *p_sock) { int sock_family; int sock_type; int sock_proto; - int len; + int len;
+ pj_status_t status; pj_sock_t sock; /* Set socket parameters */ @@ -483,30 +504,23 @@ static pj_sock_t create_socket( pjsip_transport_type_e type, sock_proto = 0; #endif } else { - PJ_LOG(2,("", "create_socket: unsupported transport type %s", - get_type_name(type))); - return PJ_INVALID_SOCKET; + return PJ_EINVAL; } /* Create socket. */ - sock = pj_sock_socket( sock_family, sock_type, sock_proto, PJ_SOCK_ASYNC); - if (sock == PJ_INVALID_SOCKET) { - PJ_PERROR((THIS_FILE, "%s socket()", get_type_name(type))); - return PJ_INVALID_SOCKET; - } + status = pj_sock_socket( sock_family, sock_type, sock_proto, &sock); + if (status != PJ_SUCCESS) + return status; /* Bind the socket to the requested address, or if no address is * specified, let the operating system chooses the address. */ if (/*local->sin_addr.s_addr != 0 &&*/ local->sin_port != 0) { - /* Bind to the requested address. */ - if (pj_sock_bind(sock, local, sizeof(*local)) != 0) { - PJ_PERROR((THIS_FILE, "bind() to %s %s:%d", - get_type_name(type), - pj_sockaddr_get_str_addr(local), - pj_sockaddr_get_port(local))); + /* Bind to the requested address. */
+ status = pj_sock_bind(sock, local, sizeof(*local)); + if (status != PJ_SUCCESS) { pj_sock_close(sock); - return PJ_INVALID_SOCKET; + return status; } } else if (type == PJSIP_TRANSPORT_UDP) { /* Only for UDP sockets: bind to any address so that the operating @@ -515,23 +529,24 @@ static pj_sock_t create_socket( pjsip_transport_type_e type, * get 0.0.0.0 as local address). */ pj_memset(local, 0, sizeof(*local)); - local->sin_family = PJ_AF_INET; - if (pj_sock_bind(sock, local, sizeof(*local)) != 0) { - PJ_PERROR((THIS_FILE, "bind() to %s 0.0.0.0:0", get_type_name(type))); + local->sin_family = PJ_AF_INET;
+ status = pj_sock_bind(sock, local, sizeof(*local)); + if (status != PJ_SUCCESS) { pj_sock_close(sock); - return PJ_INVALID_SOCKET; + return status; } /* Get the local address. */ - len = sizeof(pj_sockaddr_in); - if (pj_sock_getsockname(sock, local, &len)) { - PJ_PERROR((THIS_FILE, "getsockname()")); + len = sizeof(pj_sockaddr_in);
+ status = pj_sock_getsockname(sock, local, &len); + if (status != PJ_SUCCESS) { pj_sock_close(sock); - return -1; + return status; } } - - return sock; +
+ *p_sock = sock; + return PJ_SUCCESS; } /* @@ -547,21 +562,24 @@ static void destroy_socket( pjsip_transport_t * tr) /* * Create a new transport object. */ -static pjsip_transport_t* create_transport( pjsip_transport_mgr *mgr, - pjsip_transport_type_e type, - pj_sock_t sock_hnd, - const pj_sockaddr_in *local_addr, - const pj_sockaddr_in *addr_name) +static pj_status_t create_transport( pjsip_transport_mgr *mgr, + pjsip_transport_type_e type, + pj_sock_t sock_hnd, + const pj_sockaddr_in *local_addr, + const pj_sockaddr_in *addr_name,
+ pjsip_transport_t **p_transport ) { pj_pool_t *tr_pool=NULL, *rdata_pool=NULL; - pjsip_transport_t *tr = NULL; + pjsip_transport_t *tr = NULL;
+ pj_status_t status; /* Allocate pool for transport from endpoint. */ tr_pool = pjsip_endpt_create_pool( mgr->endpt, transport_get_name_format(type), PJSIP_POOL_LEN_TRANSPORT, PJSIP_POOL_INC_TRANSPORT ); - if (!tr_pool) { + if (!tr_pool) {
+ status = PJ_ENOMEM; goto on_error; } @@ -570,7 +588,8 @@ static pjsip_transport_t* create_transport( pjsip_transport_mgr *mgr, "prdt%p", PJSIP_POOL_LEN_RDATA, PJSIP_POOL_INC_RDATA ); - if (!rdata_pool) { + if (!rdata_pool) {
+ status = PJ_ENOMEM; goto on_error; } @@ -582,7 +601,7 @@ static pjsip_transport_t* create_transport( pjsip_transport_mgr *mgr, tr->sock = sock_hnd; pj_memcpy(&tr->local_addr, local_addr, sizeof(pj_sockaddr_in)); pj_list_init(&tr->cb_list); - sprintf(tr->obj_name, transport_get_name_format(type), tr); + pj_sprintf(tr->obj_name, transport_get_name_format(type), tr); if (type != PJSIP_TRANSPORT_UDP) { tr->flag |= PJSIP_TRANSPORT_RELIABLE; @@ -594,11 +613,10 @@ static pjsip_transport_t* create_transport( pjsip_transport_mgr *mgr, } pj_memcpy(&tr->addr_name, addr_name, sizeof(*addr_name)); - /* Create atomic */ - tr->ref_cnt = pj_atomic_create(tr_pool, 0); - if (!tr->ref_cnt) { + /* Create atomic */
+ status = pj_atomic_create(tr_pool, 0, &tr->ref_cnt); + if (status != PJ_SUCCESS) goto on_error; - } /* Init rdata in the transport. */ tr->rdata = pj_pool_alloc(rdata_pool, sizeof(*tr->rdata)); @@ -607,22 +625,20 @@ static pjsip_transport_t* create_transport( pjsip_transport_mgr *mgr, tr->rdata->transport = tr; /* Init transport mutex. */ - tr->tr_mutex = pj_mutex_create(tr_pool, "mtr%p", 0); - if (!tr->tr_mutex) { - PJ_PERROR((tr->obj_name, "pj_mutex_create()")); + status = pj_mutex_create_recursive(tr_pool, "mtr%p", &tr->tr_mutex); + if (status != PJ_SUCCESS) goto on_error; - } /* Register to I/O Queue */ - tr->key = pj_ioqueue_register(tr_pool, mgr->ioqueue, - (pj_oshandle_t)tr->sock, tr, - &ioqueue_transport_callback); - if (tr->key == NULL) { - PJ_PERROR((tr->obj_name, "pj_ioqueue_register()")); + status = pj_ioqueue_register_sock( tr_pool, mgr->ioqueue, + tr->sock, tr, + &ioqueue_transport_callback,
+ &tr->key); + if (status != PJ_SUCCESS) goto on_error; - } - - return tr; +
+ *p_transport = tr; + return PJ_SUCCESS; on_error: if (tr && tr->tr_mutex) { @@ -634,18 +650,18 @@ on_error: if (rdata_pool) { pjsip_endpt_destroy_pool(mgr->endpt, rdata_pool); } - return NULL; + return status; } /* * Destroy transport. */ -static void destroy_transport( pjsip_transport_mgr *mgr, pjsip_transport_t *tr ) +static void destroy_transport( pjsip_transport_mgr *mgr, pjsip_transport_t *tr) { transport_key hash_key; /* Remove from I/O queue. */ - pj_ioqueue_unregister( mgr->ioqueue, tr->key ); + pj_ioqueue_unregister( tr->key ); /* Remove from hash table */ init_key_from_transport(&hash_key, tr); @@ -668,12 +684,18 @@ static void destroy_transport( pjsip_transport_mgr *mgr, pjsip_transport_t *tr ) } -static int transport_send_msg( pjsip_transport_t *tr, pjsip_tx_data *tdata, - const pj_sockaddr_in *addr) +static pj_status_t transport_send_msg( pjsip_transport_t *tr,
+ pjsip_tx_data *tdata, + const pj_sockaddr_in *addr,
+ pj_ssize_t *p_sent) { const char *buf = tdata->buf.start; - int sent; - int len; + pj_ssize_t size; + pj_status_t status; +
+ /* Can only send if tdata is not being sent! */
+ if (pj_ioqueue_is_pending(tr->key, &tdata->op_key))
+ return PJSIP_EPENDINGTX;
/* Allocate buffer if necessary. */ if (tdata->buf.start == NULL) { @@ -684,34 +706,31 @@ static int transport_send_msg( pjsip_transport_t *tr, pjsip_tx_data *tdata, /* Print the message if it's not printed */ if (tdata->buf.cur <= tdata->buf.start) { - len = pjsip_msg_print(tdata->msg, tdata->buf.start, - tdata->buf.end - tdata->buf.start); - if (len < 1) { - return len; - } - tdata->buf.cur += len; - tdata->buf.cur[len] = '\0'; + size = pjsip_msg_print( tdata->msg, tdata->buf.start, + tdata->buf.end - tdata->buf.start); + if (size < 0) {
+ return PJSIP_EMSGTOOLONG; + }
+ pj_assert(size != 0); + tdata->buf.cur += size; + tdata->buf.cur[size] = '\0'; } - /* BUG BUG BUG */ - /* MUST CHECK THAT THE SOCKET IS READY TO SEND (IOQueue)! */ - PJ_TODO(BUG_BUG_BUG___SENDING_DATAGRAM_WHILE_SOCKET_IS_PENDING__) - /* Send the message. */ buf = tdata->buf.start; - len = tdata->buf.cur - tdata->buf.start; + size = tdata->buf.cur - tdata->buf.start; if (tr->type == PJSIP_TRANSPORT_UDP) { PJ_LOG(4,(tr->obj_name, "sendto %s:%d, %d bytes, data:\n" "----------- begin msg ------------\n" "%s" "------------ end msg -------------", - pj_sockaddr_get_str_addr(addr), - pj_sockaddr_get_port(addr), - len, buf)); - - sent = pj_ioqueue_sendto( tr->mgr->ioqueue, tr->key, - buf, len, addr, sizeof(*addr)); + pj_inet_ntoa(addr->sin_addr), + pj_sockaddr_in_get_port(addr), + size, buf)); +
+ status = pj_ioqueue_sendto( tr->key, &tdata->op_key, + buf, &size, 0, addr, sizeof(*addr)); } #if PJ_HAS_TCP else { @@ -719,40 +738,33 @@ static int transport_send_msg( pjsip_transport_t *tr, pjsip_tx_data *tdata, "----------- begin msg ------------\n" "%s" "------------ end msg -------------", - len, buf)); + size, buf)); - sent = pj_ioqueue_write (tr->mgr->ioqueue, tr->key, buf, len); + status = pj_ioqueue_send(tr->key, &tdata->op_key, buf, &size, 0); } #else else { - pj_assert(0); - sent = -1; + pj_assert(!"Unsupported transport");
+ status = PJSIP_EUNSUPTRANSPORT; } #endif - - if (sent == len || sent == PJ_IOQUEUE_PENDING) { - return len; - } - - /* On error, clear the flag. */ - PJ_PERROR((tr->obj_name, tr->type == PJSIP_TRANSPORT_UDP ? "pj_ioqueue_sendto()" : "pj_ioqueue_write()")); - return -1; +
+ *p_sent = size; + return status; } /* * Send a SIP message using the specified transport, to the address specified * in the outgoing data. */ -PJ_DEF(int) pjsip_transport_send_msg( pjsip_transport_t *tr, - pjsip_tx_data *tdata, - const pj_sockaddr_in *addr) +PJ_DEF(pj_status_t) pjsip_transport_send_msg( pjsip_transport_t *tr, + pjsip_tx_data *tdata, + const pj_sockaddr_in *addr,
+ pj_ssize_t *sent) { - int sent; - PJ_LOG(5, (tr->obj_name, "pjsip_transport_send_msg(tdata=%s)", tdata->obj_name)); - sent = transport_send_msg(tr, tdata, addr ); - return sent; + return transport_send_msg(tr, tdata, addr, sent ); } /////////////////////////////////////////////////////////////////////////////// @@ -760,44 +772,47 @@ PJ_DEF(int) pjsip_transport_send_msg( pjsip_transport_t *tr, /* * Create a new transport manager. */ -PJ_DEF(pjsip_transport_mgr*) -pjsip_transport_mgr_create( pj_pool_t *pool, - pjsip_endpoint * endpt, - void (*cb)(pjsip_endpoint*,pjsip_rx_data *) ) +PJ_DEF(pj_status_t) pjsip_transport_mgr_create( pj_pool_t *pool, + pjsip_endpoint * endpt, + void (*cb)(pjsip_endpoint*,
+ pjsip_rx_data *),
+ pjsip_transport_mgr **p_mgr) { pjsip_transport_mgr *mgr; + pj_status_t status;
PJ_LOG(5, (LOG_TRANSPORT_MGR, "pjsip_transport_mgr_create()")); mgr = pj_pool_alloc(pool, sizeof(*mgr)); mgr->endpt = endpt; mgr->message_callback = cb; - + mgr->send_buf_size = DEFAULT_SO_SNDBUF;
+ mgr->recv_buf_size = DEFAULT_SO_RCVBUF;
+ mgr->transport_table = pj_hash_create(pool, MGR_HASH_TABLE_SIZE); if (!mgr->transport_table) { - PJ_LOG(3, (LOG_TRANSPORT_MGR, "error creating transport manager hash table")); - return NULL; + return PJ_ENOMEM; } - mgr->ioqueue = pj_ioqueue_create(pool, PJSIP_MAX_TRANSPORTS); - if (!mgr->ioqueue) { - PJ_LOG(3, (LOG_TRANSPORT_MGR, "error creating IO queue")); - return NULL; + status = pj_ioqueue_create(pool, PJSIP_MAX_TRANSPORTS, &mgr->ioqueue); + if (status != PJ_SUCCESS) { + return status; } - mgr->mutex = pj_mutex_create(pool, "tmgr%p", 0); - if (!mgr->mutex) { - PJ_LOG(3, (LOG_TRANSPORT_MGR, "error creating mutex")); + status = pj_mutex_create_recursive(pool, "tmgr%p", &mgr->mutex); + if (status != PJ_SUCCESS) { pj_ioqueue_destroy(mgr->ioqueue); - return NULL; + return status; } pj_gettimeofday(&mgr->next_idle_check); - mgr->next_idle_check.sec += MGR_IDLE_CHECK_INTERVAL; - return mgr; + mgr->next_idle_check.sec += MGR_IDLE_CHECK_INTERVAL;
+
+ *p_mgr = mgr; + return status; } /* * Destroy transport manager. */ -PJ_DEF(void) pjsip_transport_mgr_destroy( pjsip_transport_mgr *mgr ) +PJ_DEF(pj_status_t) pjsip_transport_mgr_destroy( pjsip_transport_mgr *mgr ) { pj_hash_iterator_t itr_val; pj_hash_iterator_t *itr; @@ -822,7 +837,9 @@ PJ_DEF(void) pjsip_transport_mgr_destroy( pjsip_transport_mgr *mgr ) } pj_ioqueue_destroy(mgr->ioqueue); - pj_mutex_unlock(mgr->mutex); + pj_mutex_unlock(mgr->mutex);
+
+ return PJ_SUCCESS; } /* @@ -835,62 +852,81 @@ static pj_status_t create_listener( pjsip_transport_mgr *mgr, const pj_sockaddr_in *addr_name) { pjsip_transport_t *tr; - struct transport_key *hash_key; - int opt_val; - - opt_val = DEFAULT_SO_SNDBUF; - if (pj_sock_setsockopt( sock_hnd, SOL_SOCKET, SO_SNDBUF, &opt_val, sizeof(opt_val)) != PJ_SUCCESS) { - PJ_LOG(3, (LOG_TRANSPORT_MGR, "create listener: error setting SNDBUF to %d", DEFAULT_SO_SNDBUF)); - // Just ignore the error. + struct transport_key *hash_key;
+ const pj_str_t loopback_addr = { "127.0.0.1", 9 }; + pj_status_t status; +
+ if (mgr->send_buf_size != 0) { + int opt_val = mgr->send_buf_size;
+ status = pj_sock_setsockopt( sock_hnd, PJ_SOL_SOCKET,
+ PJ_SO_SNDBUF,
+ &opt_val, sizeof(opt_val));
+ + if (status != PJ_SUCCESS) { + return status; + }
} - - opt_val = DEFAULT_SO_RCVBUF; - if (pj_sock_setsockopt( sock_hnd, SOL_SOCKET, SO_RCVBUF, &opt_val, sizeof(opt_val)) != PJ_SUCCESS) { - PJ_LOG(3, (LOG_TRANSPORT_MGR, "create listener: error setting RCVBUF to %d", DEFAULT_SO_SNDBUF)); - // Just ignore the error +
+ if (mgr->recv_buf_size != 0) { + int opt_val = mgr->recv_buf_size;
+ status = pj_sock_setsockopt( sock_hnd, PJ_SOL_SOCKET,
+ PJ_SO_RCVBUF,
+ &opt_val, sizeof(opt_val)); + if (status != PJ_SUCCESS) { + return status; + }
} - tr = create_transport(mgr, type, sock_hnd, local_addr, addr_name); - if (!tr) { + status = create_transport(mgr, type, sock_hnd, local_addr, addr_name, &tr); + if (status != PJ_SUCCESS) { pj_sock_close(sock_hnd); - return -1; + return status; } #if PJ_HAS_TCP if (type == PJSIP_TRANSPORT_TCP) { - pj_status_t status; - - if (pj_sock_listen(tr->sock, BACKLOG) != 0) { - PJ_PERROR((tr->obj_name, "listen()")); - destroy_transport(mgr, tr); - return -1; - } - tr->accept_data.addrlen = sizeof(tr->accept_data.local); - status = pj_ioqueue_accept(mgr->ioqueue, tr->key, - &tr->accept_data.sock, - &tr->accept_data.local, - &tr->accept_data.remote, - &tr->accept_data.addrlen); - if (status != PJ_IOQUEUE_PENDING) { - PJ_PERROR((tr->obj_name, "pj_ioqueue_accept()")); +
+ status = pj_sock_listen(tr->sock, BACKLOG); + if (status != 0) { destroy_transport(mgr, tr); - return -1; + return status; } +
+ /* Discard immediate connections. */
+ do {
+ tr->accept_data.addrlen = sizeof(tr->accept_data.local); + status = pj_ioqueue_accept(tr->key, &tr->accept_op, + &tr->accept_data.sock, + &tr->accept_data.local, + &tr->accept_data.remote, + &tr->accept_data.addrlen);
+ if (status==PJ_SUCCESS) {
+ pj_sock_close(tr->accept_data.sock);
+ } else if (status != PJ_EPENDING) { + destroy_transport(mgr, tr); + return status; + }
+ } while (status==PJ_SUCCESS); } else #endif - if (type == PJSIP_TRANSPORT_UDP) { - pj_status_t status; - - tr->rdata->addr_len = sizeof(tr->rdata->addr); - status = pj_ioqueue_recvfrom( mgr->ioqueue, tr->key, - tr->rdata->packet, PJSIP_MAX_PKT_LEN, - &tr->rdata->addr, - &tr->rdata->addr_len); - if (status != PJ_IOQUEUE_PENDING) { - PJ_PERROR((tr->obj_name, "pj_ioqueue_recvfrom()")); - destroy_transport(mgr, tr); - return -1; - } + if (type == PJSIP_TRANSPORT_UDP) {
+ pj_ssize_t bytes;
+
+ /* Discard immediate data. */
+ do { + tr->rdata->addr_len = sizeof(tr->rdata->addr);
+ bytes = PJSIP_MAX_PKT_LEN; + status = pj_ioqueue_recvfrom( tr->key, &tr->rdata->op_key, + tr->rdata->packet, &bytes, 0, + &tr->rdata->addr, + &tr->rdata->addr_len);
+ if (status == PJ_SUCCESS) {
+ ; + } else if (status != PJ_EPENDING) { + destroy_transport(mgr, tr); + return status; + }
+ } while (status == PJ_SUCCESS); } pj_atomic_set(tr->ref_cnt, 1); @@ -900,26 +936,29 @@ static pj_status_t create_listener( pjsip_transport_mgr *mgr, /* Set remote address to 127.0.0.1 for UDP socket bound to 127.0.0.1. * See further comments on struct pjsip_transport_t definition. - */ - if (type == PJSIP_TRANSPORT_UDP && local_addr->sin_addr.s_addr == inet_addr("127.0.0.1")) { + */
+ if (type == PJSIP_TRANSPORT_UDP &&
+ local_addr->sin_addr.s_addr == pj_inet_addr(&loopback_addr).s_addr)
+ { pj_str_t localaddr = pj_str("127.0.0.1"); - pj_sockaddr_set_str_addr( &tr->remote_addr, &localaddr); + pj_sockaddr_in_set_str_addr( &tr->remote_addr, &localaddr); } hash_key = pj_pool_alloc(tr->pool, sizeof(transport_key)); init_key_from_transport(hash_key, tr); pj_mutex_lock(mgr->mutex); - pj_hash_set(tr->pool, mgr->transport_table, hash_key, sizeof(transport_key), tr); + pj_hash_set(tr->pool, mgr->transport_table,
+ hash_key, sizeof(transport_key), tr); pj_mutex_unlock(mgr->mutex); PJ_LOG(4,(tr->obj_name, "Listening at %s %s:%d", get_type_name(tr->type), - pj_sockaddr_get_str_addr(&tr->local_addr), - pj_sockaddr_get_port(&tr->local_addr))); + pj_inet_ntoa(tr->local_addr.sin_addr), + pj_sockaddr_in_get_port(&tr->local_addr))); PJ_LOG(4,(tr->obj_name, "Listener public address is at %s %s:%d", get_type_name(tr->type), - pj_sockaddr_get_str_addr(&tr->addr_name), - pj_sockaddr_get_port(&tr->addr_name))); + pj_inet_ntoa(tr->addr_name.sin_addr), + pj_sockaddr_in_get_port(&tr->addr_name))); return PJ_SUCCESS; } @@ -932,12 +971,13 @@ PJ_DEF(pj_status_t) pjsip_create_listener( pjsip_transport_mgr *mgr, const pj_sockaddr_in *addr_name) { pj_sock_t sock_hnd; + pj_status_t status;
PJ_LOG(5, (LOG_TRANSPORT_MGR, "pjsip_create_listener(type=%d)", type)); - sock_hnd = create_socket(type, local_addr); - if (sock_hnd == PJ_INVALID_SOCKET) { - return -1; + status = create_socket(type, local_addr, &sock_hnd); + if (status != PJ_SUCCESS) { + return status; } return create_listener(mgr, type, sock_hnd, local_addr, addr_name); @@ -950,13 +990,16 @@ PJ_DEF(pj_status_t) pjsip_create_udp_listener( pjsip_transport_mgr *mgr, pj_sock_t sock, const pj_sockaddr_in *addr_name) { - pj_sockaddr_in local_addr; + pj_sockaddr_in local_addr;
+ pj_status_t status; int addrlen = sizeof(local_addr); +
+ status = pj_sock_getsockname(sock, (pj_sockaddr_t*)&local_addr, &addrlen); + if (status != PJ_SUCCESS) + return status; - if (pj_sock_getsockname(sock, (pj_sockaddr_t*)&local_addr, &addrlen) != 0) - return -1; - - return create_listener(mgr, PJSIP_TRANSPORT_UDP, sock, &local_addr, addr_name); + return create_listener(mgr, PJSIP_TRANSPORT_UDP, sock,
+ &local_addr, addr_name); } /* @@ -973,7 +1016,7 @@ PJ_DEF(void) pjsip_transport_get( pjsip_transport_mgr *mgr, transport_key search_key, *hash_key; pjsip_transport_t *tr; pj_sockaddr_in local; - int sock_hnd; + pj_sock_t sock_hnd; pj_status_t status; struct transport_callback *cb_rec; @@ -1029,49 +1072,50 @@ PJ_DEF(void) pjsip_transport_get( pjsip_transport_mgr *mgr, /* Transport not found. Create new one. */ pj_memset(&local, 0, sizeof(local)); local.sin_family = PJ_AF_INET; - sock_hnd = create_socket(type, &local); - if (sock_hnd == PJ_INVALID_SOCKET) { + status = create_socket(type, &local, &sock_hnd); + if (status != PJ_SUCCESS) { pj_mutex_unlock(mgr->mutex); - (*cb_rec->cb)(NULL, cb_rec->token, -1); + (*cb_rec->cb)(NULL, cb_rec->token, status); return; } - tr = create_transport(mgr, type, sock_hnd, &local, NULL); - if (!tr) { + status = create_transport(mgr, type, sock_hnd, &local, NULL, &tr); + if (status != PJ_SUCCESS) { pj_mutex_unlock(mgr->mutex); - (*cb_rec->cb)(NULL, cb_rec->token, -1); + (*cb_rec->cb)(NULL, cb_rec->token, status); return; } #if PJ_HAS_TCP if (type == PJSIP_TRANSPORT_TCP) { pj_memcpy(&tr->remote_addr, remote, sizeof(pj_sockaddr_in)); - status = pj_ioqueue_connect(mgr->ioqueue, tr->key, - &tr->remote_addr, sizeof(pj_sockaddr_in)); + status = pj_ioqueue_connect(tr->key, &tr->remote_addr,
+ sizeof(pj_sockaddr_in)); pj_assert(status != 0); - if (status != PJ_IOQUEUE_PENDING) { - PJ_PERROR((tr->obj_name, "pj_ioqueue_connect()")); + if (status != PJ_EPENDING) {
+ PJ_TODO(HANDLE_IMMEDIATE_CONNECT); destroy_transport(mgr, tr); pj_mutex_unlock(mgr->mutex); - (*cb_rec->cb)(NULL, cb_rec->token, -1); + (*cb_rec->cb)(NULL, cb_rec->token, status); return; } } else #endif if (type == PJSIP_TRANSPORT_UDP) { - int len; + pj_ssize_t size; do { - tr->rdata->addr_len = sizeof(tr->rdata->addr); - len = pj_ioqueue_recvfrom( mgr->ioqueue, tr->key, - tr->rdata->packet, PJSIP_MAX_PKT_LEN, - &tr->rdata->addr, - &tr->rdata->addr_len); - pj_assert(len < 0); - if (len != PJ_IOQUEUE_PENDING) { - PJ_PERROR((tr->obj_name, "pj_ioqueue_recvfrom()")); + tr->rdata->addr_len = sizeof(tr->rdata->addr);
+ size = PJSIP_MAX_PKT_LEN; + status = pj_ioqueue_recvfrom( tr->key, &tr->rdata->op_key, + tr->rdata->packet, &size, 0, + &tr->rdata->addr, + &tr->rdata->addr_len);
+ if (status == PJ_SUCCESS)
+ ; + else if (status != PJ_EPENDING) { destroy_transport(mgr, tr); pj_mutex_unlock(mgr->mutex); - (*cb_rec->cb)(NULL, cb_rec->token, -1); + (*cb_rec->cb)(NULL, cb_rec->token, status); return; } @@ -1082,7 +1126,7 @@ PJ_DEF(void) pjsip_transport_get( pjsip_transport_mgr *mgr, */ PJ_TODO(FIXED_BUG_ON_IMMEDIATE_TRANSPORT_DATA); - } while (len != PJ_IOQUEUE_PENDING); + } while (status == PJ_SUCCESS); //Bug: cb will never be called! // Must force status to PJ_SUCCESS; @@ -1092,15 +1136,16 @@ PJ_DEF(void) pjsip_transport_get( pjsip_transport_mgr *mgr, } else { pj_mutex_unlock(mgr->mutex); - (*cb_rec->cb)(NULL, cb_rec->token, -1); + (*cb_rec->cb)(NULL, cb_rec->token, PJSIP_EUNSUPTRANSPORT); return; } - pj_assert(status==PJ_IOQUEUE_PENDING || status==PJ_SUCCESS); + pj_assert(status==PJ_EPENDING || status==PJ_SUCCESS); pj_mutex_lock(tr->tr_mutex); hash_key = pj_pool_alloc(tr->pool, sizeof(transport_key)); pj_memcpy(hash_key, &search_key, sizeof(transport_key)); - pj_hash_set(tr->pool, mgr->transport_table, hash_key, sizeof(transport_key), tr); + pj_hash_set(tr->pool, mgr->transport_table,
+ hash_key, sizeof(transport_key), tr); if (status == PJ_SUCCESS) { pj_mutex_unlock(tr->tr_mutex); pj_mutex_unlock(mgr->mutex); @@ -1123,24 +1168,28 @@ static void handle_new_connection( pjsip_transport_mgr *mgr, pj_status_t status ) { pjsip_transport_t *tr; - transport_key *hash_key; + transport_key *hash_key;
+ pj_ssize_t size;
pj_assert (listener->type == PJSIP_TRANSPORT_TCP); if (status != PJ_SUCCESS) { - PJ_PERROR((listener->obj_name, "accept() returned error")); - return; + PJSIP_ENDPT_LOG_ERROR((mgr->endpt, listener->obj_name, status,
+ "Error in accept() completion"));
+ goto on_return; } PJ_LOG(4,(listener->obj_name, "incoming tcp connection from %s:%d", - pj_sockaddr_get_str_addr(&listener->accept_data.remote), - pj_sockaddr_get_port(&listener->accept_data.remote))); - - tr = create_transport(mgr, listener->type, - listener->accept_data.sock, - &listener->accept_data.local, - NULL); - if (!tr) { + pj_inet_ntoa(listener->accept_data.remote.sin_addr), + pj_sockaddr_in_get_port(&listener->accept_data.remote))); + + status = create_transport(mgr, listener->type, + listener->accept_data.sock, + &listener->accept_data.local, + NULL, &tr); + if (status != PJ_SUCCESS) { + PJSIP_ENDPT_LOG_ERROR((mgr->endpt, listener->obj_name, status,
+ "Error in creating new incoming TCP"));
goto on_return; } @@ -1153,32 +1202,40 @@ static void handle_new_connection( pjsip_transport_mgr *mgr, */ tr->rdata->addr = listener->accept_data.remote; tr->rdata->addr_len = listener->accept_data.addrlen; - - status = pj_ioqueue_read (mgr->ioqueue, tr->key, tr->rdata->packet, PJSIP_MAX_PKT_LEN); - if (status != PJ_IOQUEUE_PENDING) { - PJ_PERROR((tr->obj_name, "pj_ioqueue_read()")); +
+ size = PJSIP_MAX_PKT_LEN; + status = pj_ioqueue_recv(tr->key, &tr->rdata->op_key,
+ tr->rdata->packet, &size, 0); + if (status != PJ_EPENDING) { + PJSIP_ENDPT_LOG_ERROR((mgr->endpt, listener->obj_name, status,
+ "Error in receiving data"));
+ PJ_TODO(IMMEDIATE_DATA); destroy_transport(mgr, tr); goto on_return; } - pj_memcpy(&tr->remote_addr, &listener->accept_data.remote, listener->accept_data.addrlen); + pj_memcpy(&tr->remote_addr, &listener->accept_data.remote,
+ listener->accept_data.addrlen); hash_key = pj_pool_alloc(tr->pool, sizeof(transport_key)); init_key_from_transport(hash_key, tr); pj_mutex_lock(mgr->mutex); - pj_hash_set(tr->pool, mgr->transport_table, hash_key, sizeof(transport_key), tr); + pj_hash_set(tr->pool, mgr->transport_table, hash_key,
+ sizeof(transport_key), tr); pj_mutex_unlock(mgr->mutex); on_return: /* Re-initiate asynchronous accept() */ listener->accept_data.addrlen = sizeof(listener->accept_data.local); - status = pj_ioqueue_accept(mgr->ioqueue, listener->key, + status = pj_ioqueue_accept(listener->key, &listener->accept_op, &listener->accept_data.sock, &listener->accept_data.local, &listener->accept_data.remote, &listener->accept_data.addrlen); - if (status != PJ_IOQUEUE_PENDING) { - PJ_PERROR((listener->obj_name, "pj_ioqueue_accept()")); + if (status != PJ_EPENDING) { + PJSIP_ENDPT_LOG_ERROR((mgr->endpt, listener->obj_name, status,
+ "Error in receiving data"));
+ PJ_TODO(IMMEDIATE_ACCEPT); return; } } @@ -1193,8 +1250,9 @@ static void handle_connect_completion( pjsip_transport_mgr *mgr, { struct transport_callback new_list; struct transport_callback *cb_rec; + pj_ssize_t recv_size;
- PJ_UNUSED_ARG(mgr) + PJ_UNUSED_ARG(mgr); /* On connect completion, we must call all registered callbacks in * the transport. @@ -1221,11 +1279,12 @@ static void handle_connect_completion( pjsip_transport_mgr *mgr, */ if (status == PJ_SUCCESS) { int addrlen = sizeof(tr->local_addr); - int rc; - if ((rc=pj_sock_getsockname(tr->sock, (pj_sockaddr_t*)&tr->local_addr, &addrlen)) == 0) { +
+ status = pj_sock_getsockname(tr->sock,
+ (pj_sockaddr_t*)&tr->local_addr,
+ &addrlen); + if (status == PJ_SUCCESS) { pj_memcpy(&tr->addr_name, &tr->local_addr, sizeof(tr->addr_name)); - } else { - PJ_LOG(4,(tr->obj_name, "Unable to get local address (getsockname=%d)", rc)); } } @@ -1243,15 +1302,18 @@ static void handle_connect_completion( pjsip_transport_mgr *mgr, /* Success? */ if (status != PJ_SUCCESS) { - destroy_transport(mgr, tr); + destroy_transport(mgr, tr);
+ PJ_TODO(WTF); return; } - /* Initiate read operation to socket. */ - status = pj_ioqueue_read (mgr->ioqueue, tr->key, tr->rdata->packet, PJSIP_MAX_PKT_LEN); - if (status != PJ_IOQUEUE_PENDING) { - PJ_PERROR((tr->obj_name, "pj_ioqueue_read()")); - destroy_transport(mgr, tr); + /* Initiate read operation to socket. */
+ recv_size = PJSIP_MAX_PKT_LEN; + status = pj_ioqueue_recv( tr->key, &tr->rdata->op_key, tr->rdata->packet,
+ &recv_size, 0); + if (status != PJ_EPENDING) { + destroy_transport(mgr, tr);
+ PJ_TODO(IMMEDIATE_DATA); return; } } @@ -1269,7 +1331,6 @@ static void handle_received_data( pjsip_transport_mgr *mgr, pj_ssize_t size ) { pjsip_msg *msg; - pjsip_cid_hdr *call_id; pjsip_rx_data *rdata = tr->rdata; pj_pool_t *rdata_pool; pjsip_hdr *hdr; @@ -1315,8 +1376,8 @@ static void handle_received_data( pjsip_transport_mgr *mgr, rdata->packet[rdata->len] = '\0'; /* Get source address and port for logging purpose. */ - src_addr = pj_sockaddr_get_str_addr(&rdata->addr); - src_port = pj_sockaddr_get_port(&rdata->addr); + src_addr = pj_inet_ntoa(rdata->addr.sin_addr); + src_port = pj_sockaddr_in_get_port(&rdata->addr); /* Print the whole data to the log. */ PJ_LOG(4,(tr->obj_name, "%d bytes recvfrom %s:%d:\n" @@ -1333,15 +1394,15 @@ static void handle_received_data( pjsip_transport_mgr *mgr, #if PJ_HAS_TCP /* For TCP transport, check if the whole message has been received. */ if (tr->type != PJSIP_TRANSPORT_UDP) { - pj_bool_t is_complete; - is_complete = pjsip_find_msg(rdata->packet, rdata->len, PJ_FALSE, &msg_fragment_size); - if (!is_complete) { - if (rdata->len == PJSIP_MAX_PKT_LEN) { - PJ_LOG(1,(tr->obj_name, - "Transport buffer full (%d bytes) for TCP socket %s:%d " - "(probably too many invalid fragments received). " - "Buffer will be discarded.", - PJSIP_MAX_PKT_LEN, src_addr, src_port)); + pj_status_t msg_status; + msg_status = pjsip_find_msg(rdata->packet, rdata->len, PJ_FALSE,
+ &msg_fragment_size); + if (msg_status != PJ_SUCCESS) { + if (rdata->len == PJSIP_MAX_PKT_LEN) {
+ PJSIP_ENDPT_LOG_ERROR((mgr->endpt, tr->obj_name,
+ PJSIP_EOVERFLOW,
+ "Buffer discarded for %s:%d", + src_addr, src_port)); goto on_return; } else { goto tcp_read_packet; @@ -1357,36 +1418,21 @@ static void handle_received_data( pjsip_transport_mgr *mgr, PJ_LOG(5,(tr->obj_name, "Parsing %d bytes from %s:%d", msg_fragment_size, src_addr, src_port)); - msg = pjsip_parse_msg( rdata->pool, rdata->packet, msg_fragment_size, - &rdata->parse_err); + msg = pjsip_parse_rdata( rdata->packet, msg_fragment_size, rdata); if (msg == NULL) { PJ_LOG(3,(tr->obj_name, "Bad message (%d bytes from %s:%d)", msg_fragment_size, src_addr, src_port)); goto finish_process_fragment; } - - /* Attach newly created message to rdata. */ - rdata->msg = msg; - - /* Extract Call-ID, From and To header and tags, topmost Via, and CSeq - * header from the message. - */ - call_id = pjsip_msg_find_hdr( msg, PJSIP_H_CALL_ID, NULL); - rdata->from = pjsip_msg_find_hdr( msg, PJSIP_H_FROM, NULL); - rdata->to = pjsip_msg_find_hdr( msg, PJSIP_H_TO, NULL); - rdata->via = pjsip_msg_find_hdr( msg, PJSIP_H_VIA, NULL); - rdata->cseq = pjsip_msg_find_hdr( msg, PJSIP_H_CSEQ, NULL); - - if (call_id == NULL || rdata->from == NULL || rdata->to == NULL || - rdata->via == NULL || rdata->cseq == NULL) +
+ /* Perform basic header checking. */ + if (rdata->call_id.ptr == NULL || rdata->from == NULL ||
+ rdata->to == NULL || rdata->via == NULL || rdata->cseq == NULL) { PJ_LOG(3,(tr->obj_name, "Bad message from %s:%d: missing some header", src_addr, src_port)); goto finish_process_fragment; } - rdata->call_id = call_id->id; - rdata->from_tag = rdata->from->tag; - rdata->to_tag = rdata->to->tag; /* If message is received from address that's different from the sent-by, * MUST add received parameter to the via. @@ -1401,14 +1447,14 @@ static void handle_received_data( pjsip_transport_mgr *mgr, * If message contains "rport" param, put the received port there. */ if (rdata->via->rport_param == 0) { - rdata->via->rport_param = pj_sockaddr_get_port(&rdata->addr); + rdata->via->rport_param = pj_sockaddr_in_get_port(&rdata->addr); } /* Drop response message if it has more than one Via. */ if (msg->type == PJSIP_RESPONSE_MSG) { hdr = (pjsip_hdr*)rdata->via->next; - if (hdr) { + if (hdr != &rdata->msg->hdr) { hdr = pjsip_msg_find_hdr(msg, PJSIP_H_VIA, hdr); if (hdr) { PJ_LOG(3,(tr->obj_name, "Bad message from %s:%d: " @@ -1444,10 +1490,12 @@ on_return: /* Read the next packet. */ rdata->addr_len = sizeof(rdata->addr); - if (tr->type == PJSIP_TRANSPORT_UDP) { - pj_ioqueue_recvfrom( tr->mgr->ioqueue, tr->key, - tr->rdata->packet, PJSIP_MAX_PKT_LEN, - &rdata->addr, &rdata->addr_len); + if (tr->type == PJSIP_TRANSPORT_UDP) {
+ pj_ssize_t size = PJSIP_MAX_PKT_LEN; + pj_ioqueue_recvfrom(tr->key, &tr->rdata->op_key, + tr->rdata->packet, &size, 0, + &rdata->addr, &rdata->addr_len);
+ PJ_TODO(HANDLE_IMMEDIATE_DATA); } #if PJ_HAS_TCP @@ -1455,10 +1503,12 @@ on_return: label inside the '#if PJ_HAS_TCP' block to avoid 'unreferenced label' warning. */ tcp_read_packet: - if (tr->type == PJSIP_TRANSPORT_TCP) { - pj_ioqueue_read( tr->mgr->ioqueue, tr->key, + if (tr->type == PJSIP_TRANSPORT_TCP) {
+ pj_ssize_t size = PJSIP_MAX_PKT_LEN - tr->rdata->len;
+ pj_ioqueue_recv( tr->key, &tr->rdata->op_key, tr->rdata->packet + tr->rdata->len, - PJSIP_MAX_PKT_LEN - tr->rdata->len); + &size, 0);
+ PJ_TODO(HANDLE_IMMEDIATE_DATA_1); } #endif } @@ -1507,7 +1557,9 @@ static void transport_mgr_on_idle( pjsip_transport_mgr *mgr ) pj_mutex_unlock(mgr->mutex); } -static void on_ioqueue_read(pj_ioqueue_key_t *key, pj_ssize_t bytes_read) +static void on_ioqueue_read(pj_ioqueue_key_t *key,
+ pj_ioqueue_op_key_t *op_key,
+ pj_ssize_t bytes_read) { pjsip_transport_t *t; t = pj_ioqueue_get_user_data(key); @@ -1515,17 +1567,22 @@ static void on_ioqueue_read(pj_ioqueue_key_t *key, pj_ssize_t bytes_read) handle_received_data( t->mgr, t, bytes_read ); } -static void on_ioqueue_write(pj_ioqueue_key_t *key, pj_ssize_t bytes_sent) +static void on_ioqueue_write(pj_ioqueue_key_t *key,
+ pj_ioqueue_op_key_t *op_key,
+ pj_ssize_t bytes_sent) { - PJ_UNUSED_ARG(key) - PJ_UNUSED_ARG(bytes_sent) + PJ_UNUSED_ARG(key); + PJ_UNUSED_ARG(bytes_sent); /* Completion of write operation. * Do nothing. */ } -static void on_ioqueue_accept(pj_ioqueue_key_t *key, int status) +static void on_ioqueue_accept(pj_ioqueue_key_t *key,
+ pj_ioqueue_op_key_t *op_key,
+ pj_sock_t newsock,
+ int status) { #if PJ_HAS_TCP pjsip_transport_t *t; @@ -1533,8 +1590,8 @@ static void on_ioqueue_accept(pj_ioqueue_key_t *key, int status) handle_new_connection( t->mgr, t, status ); #else - PJ_UNUSED_ARG(key) - PJ_UNUSED_ARG(status) + PJ_UNUSED_ARG(key); + PJ_UNUSED_ARG(status); #endif } @@ -1546,8 +1603,8 @@ static void on_ioqueue_connect(pj_ioqueue_key_t *key, int status) handle_connect_completion( t->mgr, t, status); #else - PJ_UNUSED_ARG(key) - PJ_UNUSED_ARG(status) + PJ_UNUSED_ARG(key); + PJ_UNUSED_ARG(status); #endif } diff --git a/pjsip/src/pjsip/sip_uri.c b/pjsip/src/pjsip/sip_uri.c index 516b78c9..8085f7fc 100644 --- a/pjsip/src/pjsip/sip_uri.c +++ b/pjsip/src/pjsip/sip_uri.c @@ -1,11 +1,11 @@ /* $Id$ - * */ #include <pjsip/sip_uri.h> #include <pjsip/sip_msg.h> -#include <pjsip/print.h> +#include <pjsip/print_util.h> #include <pj/string.h> #include <pj/pool.h> +#include <pj/assert.h>
#define IS_SIPS(url) ((url)->vptr==&sips_url_vptr) @@ -68,13 +68,13 @@ static pjsip_uri_vptr name_addr_vptr = static const pj_str_t *pjsip_url_get_scheme(const pjsip_url *url) { - PJ_UNUSED_ARG(url) + PJ_UNUSED_ARG(url); return &sip_str; } static const pj_str_t *pjsips_url_get_scheme(const pjsip_url *url) { - PJ_UNUSED_ARG(url) + PJ_UNUSED_ARG(url); return &sips_str; } @@ -253,7 +253,7 @@ static int pjsip_url_compare( pjsip_uri_context_e context, return -1; } - if (strcmp(str_url1, str_url2)) { + if (pj_native_strcmp(str_url1, str_url2)) { /* Not equal */ return -1; } diff --git a/pjsip/src/pjsua/getopt.c b/pjsip/src/pjsua/getopt.c index caa8920f..5d4689cf 100644 --- a/pjsip/src/pjsua/getopt.c +++ b/pjsip/src/pjsua/getopt.c @@ -278,7 +278,7 @@ static char *posixly_correct; On some systems, it contains special magic macros that don't work in GCC. */ #include <string.h> -#define my_index strchr +#define my_index pj_native_strchr #else static char * @@ -644,7 +644,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ - if (optind != argc && !strcmp (argv[optind], "--")) + if (optind != argc && !pj_native_strcmp(argv[optind], "--")) { optind++; diff --git a/pjsip/src/pjsua/main.c b/pjsip/src/pjsua/main.c index c04d1a22..a8a0f49a 100644 --- a/pjsip/src/pjsua/main.c +++ b/pjsip/src/pjsua/main.c @@ -250,7 +250,7 @@ static void pres_on_received_request(pjsip_presentity *pres, pjsip_rx_data *rdat urllen = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, rdata->from->uri, url, sizeof(url)-1); if (urllen < 1) { - strcpy(url, "<unknown>"); + pj_native_strcpy(url, "<unknown>"); } else { url[urllen] = '\0'; } @@ -1103,7 +1103,7 @@ static pj_status_t init_stack() } if (global.user_id[0]=='\0') { - strcpy(global.user_id, "user"); + pj_native_strcpy(global.user_id, "user"); } /* build contact */ @@ -1233,12 +1233,12 @@ static int on_incoming_im_msg(pjsip_rx_data *rdata) len = pjsip_uri_print( PJSIP_URI_IN_CONTACT_HDR, rdata->from->uri, from, sizeof(from)); if (len > 0) from[len] = '\0'; - else strcpy(from, "<URL too long..>"); + else pj_native_strcpy(from, "<URL too long..>"); len = pjsip_uri_print( PJSIP_URI_IN_CONTACT_HDR, rdata->to->uri, to, sizeof(to)); if (len > 0) to[len] = '\0'; - else strcpy(to, "<URL too long..>"); + else pj_native_strcpy(to, "<URL too long..>"); PJ_LOG(3,(THIS_FILE, "Incoming instant message:")); diff --git a/pjsip/src/pjsua/misc.c b/pjsip/src/pjsua/misc.c index 36439ccc..58cc795f 100644 --- a/pjsip/src/pjsua/misc.c +++ b/pjsip/src/pjsua/misc.c @@ -341,7 +341,7 @@ static int parse_args(pj_pool_t *pool, int argc, char *argv[]) global.cred_info[0].data = pj_str(optarg); break; case OPT_USE_STUN1: /* STUN server 1 */ - p = strchr(optarg, ':'); + p = pj_native_strchr(optarg, ':'); if (p) { *p = '\0'; global.stun_srv1 = pj_str(optarg); @@ -356,7 +356,7 @@ static int parse_args(pj_pool_t *pool, int argc, char *argv[]) } break; case OPT_USE_STUN2: /* STUN server 2 */ - p = strchr(optarg, ':'); + p = pj_native_strchr(optarg, ':'); if (p) { *p = '\0'; global.stun_srv2 = pj_str(optarg); |