Changeset 107
- Timestamp:
- Jan 5, 2006 11:35:46 PM (19 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 5 added
- 30 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjlib/include/pj/compat/socket.h
r65 r107 80 80 # define OSERR_EWOULDBLOCK WSAEWOULDBLOCK 81 81 # define OSERR_EINPROGRESS WSAEINPROGRESS 82 # define OSERR_ECONNRESET WSAECONNRESET 82 83 #else 83 84 # define OSERR_EWOULDBLOCK EWOULDBLOCK 84 85 # define OSERR_EINPROGRESS EINPROGRESS 86 # define OSERR_ECONNRESET ECONNRESET 85 87 #endif 86 88 -
pjproject/trunk/pjlib/include/pj/list.h
r66 r107 118 118 119 119 /** 120 * Insert the node to the back of the list. This is just an alias for 121 * #pj_list_insert_before(). 122 * 123 * @param list The list. 124 * @param node The element to be inserted. 125 */ 126 PJ_INLINE(void) pj_list_push_back(pj_list_type *list, pj_list_type *node) 127 { 128 pj_list_insert_before(list, node); 129 } 130 131 132 /** 120 133 * Inserts all nodes in \a nodes to the target list. 121 134 * … … 136 149 */ 137 150 PJ_IDECL(void) pj_list_insert_after(pj_list_type *pos, pj_list_type *node); 151 152 153 /** 154 * Insert the node to the front of the list. This is just an alias for 155 * #pj_list_insert_after(). 156 * 157 * @param list The list. 158 * @param node The element to be inserted. 159 */ 160 PJ_INLINE(void) pj_list_push_front(pj_list_type *list, pj_list_type *node) 161 { 162 pj_list_insert_after(list, node); 163 } 164 138 165 139 166 /** -
pjproject/trunk/pjlib/src/pj/os_core_win32.c
r106 r107 863 863 struct pj_rwmutex_t 864 864 { 865 pj_mutex_t *read_lock, *write_lock; 866 int reader_count; 865 pj_mutex_t *read_lock; 866 /* write_lock must use semaphore, because write_lock may be released 867 * by thread other than the thread that acquire the write_lock in the 868 * first place. 869 */ 870 pj_sem_t *write_lock; 871 pj_int32_t reader_count; 867 872 }; 868 873 … … 886 891 return status; 887 892 888 status = pj_ mutex_create_recursive(pool, name, &rwmutex->write_lock);893 status = pj_sem_create(pool, name, 1, 1, &rwmutex->write_lock); 889 894 if (status != PJ_SUCCESS) { 890 895 pj_mutex_destroy(rwmutex->read_lock); … … 908 913 909 914 status = pj_mutex_lock(mutex->read_lock); 910 if (status != PJ_SUCCESS) 915 if (status != PJ_SUCCESS) { 916 pj_assert(!"This pretty much is unexpected"); 911 917 return status; 918 } 912 919 913 920 mutex->reader_count++; 921 922 pj_assert(mutex->reader_count < 0x7FFFFFF0L); 923 914 924 if (mutex->reader_count == 1) 915 pj_ mutex_lock(mutex->write_lock);925 pj_sem_wait(mutex->write_lock); 916 926 917 927 status = pj_mutex_unlock(mutex->read_lock); … … 926 936 { 927 937 PJ_ASSERT_RETURN(mutex, PJ_EINVAL); 928 return pj_ mutex_lock(mutex->write_lock);938 return pj_sem_wait(mutex->write_lock); 929 939 } 930 940 … … 940 950 941 951 status = pj_mutex_lock(mutex->read_lock); 942 if (status != PJ_SUCCESS) 952 if (status != PJ_SUCCESS) { 953 pj_assert(!"This pretty much is unexpected"); 943 954 return status; 955 } 944 956 945 957 pj_assert(mutex->reader_count >= 1); … … 947 959 --mutex->reader_count; 948 960 if (mutex->reader_count == 0) 949 pj_ mutex_unlock(mutex->write_lock);961 pj_sem_post(mutex->write_lock); 950 962 951 963 status = pj_mutex_unlock(mutex->read_lock); … … 960 972 { 961 973 PJ_ASSERT_RETURN(mutex, PJ_EINVAL); 962 return pj_mutex_unlock(mutex->write_lock); 974 pj_assert(mutex->reader_count <= 1); 975 return pj_sem_post(mutex->write_lock); 963 976 } 964 977 … … 972 985 PJ_ASSERT_RETURN(mutex, PJ_EINVAL); 973 986 pj_mutex_destroy(mutex->read_lock); 974 pj_ mutex_destroy(mutex->write_lock);987 pj_sem_destroy(mutex->write_lock); 975 988 return PJ_SUCCESS; 976 989 } -
pjproject/trunk/pjsip/build/pjsip_core.dsp
r106 r107 125 125 126 126 SOURCE=..\src\pjsip\sip_transaction.c 127 128 !IF "$(CFG)" == "pjsip_core - Win32 Release" 129 127 130 # PROP Exclude_From_Build 1 131 132 !ELSEIF "$(CFG)" == "pjsip_core - Win32 Debug" 133 134 !ENDIF 135 128 136 # End Source File 129 137 # Begin Source File … … 133 141 # Begin Source File 134 142 143 SOURCE=..\src\pjsip\sip_transport_loop.c 144 # End Source File 145 # Begin Source File 146 135 147 SOURCE=..\src\pjsip\sip_transport_udp.c 136 148 # End Source File … … 142 154 143 155 SOURCE=..\src\pjsip\sip_util.c 156 # End Source File 157 # Begin Source File 158 159 SOURCE=..\src\pjsip\sip_util_proxy.c 144 160 # End Source File 145 161 # Begin Source File … … 222 238 # Begin Source File 223 239 240 SOURCE=..\include\pjsip\sip_transport_loop.h 241 # End Source File 242 # Begin Source File 243 224 244 SOURCE=..\include\pjsip\sip_transport_udp.h 225 245 # End Source File -
pjproject/trunk/pjsip/build/test_pjsip.dsp
r106 r107 102 102 # Begin Source File 103 103 104 SOURCE="..\src\test-pjsip\transport_loop_test.c" 105 # End Source File 106 # Begin Source File 107 104 108 SOURCE="..\src\test-pjsip\transport_test.c" 105 109 # End Source File … … 107 111 108 112 SOURCE="..\src\test-pjsip\transport_udp_test.c" 113 # End Source File 114 # Begin Source File 115 116 SOURCE="..\src\test-pjsip\tsx_uac_test.c" 109 117 # End Source File 110 118 # Begin Source File -
pjproject/trunk/pjsip/include/pjsip/sip_config.h
r105 r107 46 46 #define PJSIP_RFC3261_BRANCH_LEN 7 47 47 48 /* Transaction related constants. */ 49 #define PJSIP_POOL_TSX_LAYER_LEN 4000 50 #define PJSIP_POOL_TSX_LAYER_INC 4000 51 #define PJSIP_MAX_TSX_COUNT (16*1024) 52 #define PJSIP_POOL_TSX_LEN 1536 //768 53 #define PJSIP_POOL_TSX_INC 256 54 #define PJSIP_MAX_TSX_KEY_LEN (PJSIP_MAX_URL_SIZE*2) 55 48 56 /* Message/URL related constants. */ 49 57 #define PJSIP_MAX_CALL_ID_LEN PJ_GUID_STRING_LENGTH … … 52 60 #define PJSIP_MAX_URL_SIZE 256 53 61 #define PJSIP_MAX_HNAME_LEN 64 54 55 /* Transction related constants. */56 #define PJSIP_MAX_TSX_COUNT (16*1024)57 #define PJSIP_POOL_LEN_TSX 1536 //76858 #define PJSIP_POOL_INC_TSX 25659 #define PJSIP_MAX_TSX_KEY_LEN (PJSIP_MAX_URL_SIZE*2)60 62 61 63 /* Dialog related constants. */ -
pjproject/trunk/pjsip/include/pjsip/sip_endpoint.h
r106 r107 210 210 * @param pool The pool to be destroyed. 211 211 */ 212 PJ_DECL(void) pjsip_endpt_ destroy_pool( pjsip_endpoint *endpt,212 PJ_DECL(void) pjsip_endpt_release_pool( pjsip_endpoint *endpt, 213 213 pj_pool_t *pool ); 214 214 -
pjproject/trunk/pjsip/include/pjsip/sip_errno.h
r106 r107 152 152 */ 153 153 #define PJSIP_ENOTRESPONSEMSG (PJSIP_ERRNO_START_PJSIP + 31) /* 171031 */ 154 /** 155 * @hideinitializer 156 * Invalid header field. 157 */ 158 #define PJSIP_EINVALIDHDR (PJSIP_ERRNO_START_PJSIP + 32) /* 171032 */ 154 159 155 160 -
pjproject/trunk/pjsip/include/pjsip/sip_msg.h
r106 r107 500 500 * content type found in Content-Type header. 501 501 * 502 * For outgoing messages, application m ustfill in this member with502 * For outgoing messages, application may fill in this member with 503 503 * appropriate value, because the stack will generate Content-Type header 504 504 * based on the value specified here. 505 * 506 * If the content_type is empty, no Content-Type AND Content-Length header 507 * will be added to the message. The stack assumes that application adds 508 * these headers themselves. 505 509 */ 506 510 pjsip_media_type content_type; … … 544 548 char *buf, pj_size_t size); 545 549 550 /** Clone the data part only of this message body. Note that this only 551 * duplicates the data part of the body instead of the whole message 552 * body. If application wants to duplicate the entire message body 553 * structure, it must call #pjsip_msg_body_clone(). 554 * 555 * @param pool Pool used to clone the data. 556 * @param data The data inside message body, to be cloned. 557 * @param len The length of the data. 558 * 559 * @return New data duplicated from the original data. 560 */ 561 void* (*clone_data)(pj_pool_t *pool, const void *data, unsigned len); 562 546 563 } pjsip_msg_body; 547 564 … … 561 578 PJ_DECL(int) pjsip_print_text_body( pjsip_msg_body *msg_body, 562 579 char *buf, pj_size_t size); 580 581 /** 582 * Clone the message body in src_body to the dst_body. This will duplicate 583 * the contents of the message body using the \a clone_data member of the 584 * source message body. 585 * 586 * @param pool Pool to use to duplicate the message body. 587 * @param dst_body Destination message body. 588 * @param src_body Source message body to duplicate. 589 * 590 * @return PJ_SUCCESS on success. 591 */ 592 PJ_DECL(pj_status_t) pjsip_msg_body_clone(pj_pool_t *pool, 593 pjsip_msg_body *dst_body, 594 const pjsip_msg_body *src_body ); 595 563 596 564 597 /** -
pjproject/trunk/pjsip/include/pjsip/sip_transaction.h
r105 r107 26 26 27 27 #include <pjsip/sip_msg.h> 28 #include <pjsip/sip_ resolve.h>28 #include <pjsip/sip_util.h> 29 29 #include <pj/timer.h> 30 30 … … 37 37 */ 38 38 39 /* Forward decl. */ 40 struct pjsip_transaction; 41 42 43 /** 44 * Transaction state. 39 /** 40 * This enumeration represents transaction state. 45 41 */ 46 42 typedef enum pjsip_tsx_state_e 47 43 { 48 PJSIP_TSX_STATE_NULL, 49 PJSIP_TSX_STATE_CALLING, 50 PJSIP_TSX_STATE_TRYING, 51 PJSIP_TSX_STATE_PROCEEDING, 52 PJSIP_TSX_STATE_COMPLETED, 53 PJSIP_TSX_STATE_CONFIRMED, 54 PJSIP_TSX_STATE_TERMINATED, 55 PJSIP_TSX_STATE_DESTROYED, 56 PJSIP_TSX_STATE_MAX, 44 PJSIP_TSX_STATE_NULL, /**< For UAC, before any message is sent. */ 45 PJSIP_TSX_STATE_CALLING, /**< For UAC, just after request is sent. */ 46 PJSIP_TSX_STATE_TRYING, /**< For UAS, just after request is received.*/ 47 PJSIP_TSX_STATE_PROCEEDING, /**< For UAS/UAC, after provisional response.*/ 48 PJSIP_TSX_STATE_COMPLETED, /**< For UAS/UAC, after final response. */ 49 PJSIP_TSX_STATE_CONFIRMED, /**< For UAS, after ACK is received. */ 50 PJSIP_TSX_STATE_TERMINATED, /**< For UAS/UAC, before it's destroyed. */ 51 PJSIP_TSX_STATE_DESTROYED, /**< For UAS/UAC, will be destroyed now. */ 52 PJSIP_TSX_STATE_MAX, /**< Number of states. */ 57 53 } pjsip_tsx_state_e; 58 54 59 55 60 56 /** 61 * State of the transport in the transaction. 62 * The transport is progressing independently of the transaction. 63 */ 64 typedef enum pjsip_tsx_transport_state_e 65 { 66 PJSIP_TSX_TRANSPORT_STATE_NULL, 67 PJSIP_TSX_TRANSPORT_STATE_RESOLVING, 68 PJSIP_TSX_TRANSPORT_STATE_CONNECTING, 69 PJSIP_TSX_TRANSPORT_STATE_FINAL, 70 } pjsip_tsx_transport_state_e; 71 72 73 /** 74 * Transaction state. 57 * This structure describes SIP transaction object. The transaction object 58 * is used to handle both UAS and UAC transaction. 75 59 */ 76 60 struct pjsip_transaction … … 80 64 */ 81 65 pj_pool_t *pool; /**< Pool owned by the tsx. */ 66 pjsip_module *tsx_user; /**< Transaction user. */ 82 67 pjsip_endpoint *endpt; /**< Endpoint instance. */ 83 68 pj_mutex_t *mutex; /**< Mutex for this tsx. */ 84 char obj_name[PJ_MAX_OBJ_NAME]; /**< Tsx name. */85 int tracing; /**< Tracing enabled? */86 69 87 70 /* 88 71 * Transaction identification. 89 72 */ 73 char obj_name[PJ_MAX_OBJ_NAME]; /**< Log info. */ 90 74 pjsip_role_e role; /**< Role (UAS or UAC) */ 91 75 pjsip_method method; /**< The method. */ 92 76 int cseq; /**< The CSeq */ 93 pj_str_t transaction_key;/**< hash table key. */77 pj_str_t transaction_key;/**< Hash table key. */ 94 78 pj_str_t branch; /**< The branch Id. */ 95 79 … … 99 83 int status_code; /**< Last status code seen. */ 100 84 pjsip_tsx_state_e state; /**< State. */ 101 int handle_ack; /**< Should we handle ACK? */ 85 int handle_200resp; /**< UAS 200/INVITE retrsm.*/ 86 int tracing; /**< Tracing enabled? */ 102 87 103 88 /** Handler according to current state. */ … … 107 92 * Transport. 108 93 */ 109 pjsip_tsx_transport_state_e transport_state;/**< Transport's state. */110 pjsip_host_info dest_name; /**< Destination address. */111 pjsip_server_addresses remote_addr; /**< Addresses resolved. */112 int current_addr; /**< Address currently used. */113 114 94 pjsip_transport *transport; /**< Transport to use. */ 95 pj_sockaddr addr; /**< Destination address. */ 96 int addr_len; /**< Address length. */ 97 pjsip_response_addr res_addr; /**< Response address. */ 98 unsigned transport_flag; /**< Miscelaneous flag. */ 115 99 116 100 /* … … 118 102 */ 119 103 pjsip_tx_data *last_tx; /**< Msg kept for retrans. */ 120 int has_unsent_msg; /**< Non-zero if tsx need to121 transmit msg once resolver122 completes. */123 104 int retransmit_count;/**< Retransmission count. */ 124 105 pj_timer_entry retransmit_timer;/**< Retransmit timer. */ … … 126 107 127 108 /** Module specific data. */ 128 void *mod ule_data[PJSIP_MAX_MODULE];109 void *mod_data[PJSIP_MAX_MODULE]; 129 110 }; 130 111 131 112 132 113 /** 133 * Create new transaction. Application would normally use 134 * #pjsip_endpt_create_tsx rather than this function. 135 * 136 * @param pool Pool to use by the transaction. 137 * @param endpt Endpoint. 138 * @param p_tsx Pointer to return the transaction. 139 * 140 * @return PJ_SUCCESS or the appropriate error code. 141 * 142 * @see pjsip_endpt_create_tsx 143 * 144 */ 145 PJ_DEF(pj_status_t) pjsip_tsx_create( pj_pool_t *pool, 146 pjsip_endpoint *endpt, 147 pjsip_transaction **p_tsx); 148 149 /** 150 * Init transaction as UAC from the specified transmit data (\c tdata). 151 * The transmit data must have a valid \c Request-Line and \c CSeq header. 152 * If \c Route headers are present, it will be used to calculate remote 153 * destination. 114 * Create and register transaction layer module to the specified endpoint. 115 * 116 * @param endpt The endpoint instance. 117 * 118 * @return PJ_SUCCESS on success. 119 */ 120 PJ_DECL(pj_status_t) pjsip_tsx_layer_init(pjsip_endpoint *endpt); 121 122 /** 123 * Get the instance of the transaction layer module. 124 * 125 * @return The transaction layer module. 126 */ 127 PJ_DECL(pjsip_module*) pjsip_tsx_layer_instance(void); 128 129 /** 130 * Unregister and destroy transaction layer module. 131 * 132 * @return PJ_SUCCESS on success. 133 */ 134 PJ_DECL(pj_status_t) pjsip_tsx_layer_destroy(void); 135 136 /** 137 * Find a transaction with the specified key. The transaction key normally 138 * is created by calling #pjsip_tsx_create_key() from an incoming message. 139 * 140 * @param key The key string to find the transaction. 141 * @param lock If non-zero, transaction will be locked before the 142 * function returns, to make sure that it's not deleted 143 * by other threads. 144 * 145 * @return The matching transaction instance, or NULL if transaction 146 * can not be found. 147 */ 148 PJ_DECL(pjsip_transaction*) pjsip_tsx_layer_find_tsx( const pj_str_t *key, 149 pj_bool_t lock ); 150 151 /** 152 * Create, initialize, and register a new transaction as UAC from the 153 * specified transmit data (\c tdata). The transmit data must have a valid 154 * \c Request-Line and \c CSeq header. 154 155 * 155 156 * If \c Via header does not exist, it will be created along with a unique 156 157 * \c branch parameter. If it exists and contains branch parameter, then 157 * the \c branch parameter will be used as is as the transaction key. 158 * 159 * The \c Route headers in the transmit data, if present, are used to 160 * calculate remote destination. 161 * 162 * At the end of the function, the transaction will start resolving the 163 * addresses of remote server to contact. Transport will be acquired as soon 164 * as the resolving job completes. 165 * 166 * @param tsx The transaction. 167 * @param tdata The transmit data. 158 * the \c branch parameter will be used as is as the transaction key. If 159 * it exists but branch parameter doesn't exist, a unique branch parameter 160 * will be created. 161 * 162 * @param tsx_user Module to be registered as transaction user of the new 163 * transaction, which will receive notification from the 164 * transaction via on_tsx_state() callback. 165 * @param tdata The outgoing request message. 166 * @param p_tsx On return will contain the new transaction instance. 168 167 * 169 168 * @return PJ_SUCCESS if successfull. 170 169 */ 171 PJ_DECL(pj_status_t) pjsip_tsx_init_uac( pjsip_transaction *tsx, 172 pjsip_tx_data *tdata); 173 174 /** 175 * Init transaction as UAS. 176 * 177 * @param tsx The transaction to be initialized. 170 PJ_DECL(pj_status_t) pjsip_tsx_create_uac( pjsip_module *tsx_user, 171 pjsip_tx_data *tdata, 172 pjsip_transaction **p_tsx); 173 174 /** 175 * Create, initialize, and register a new transaction as UAS from the 176 * specified incoming request in \c rdata. 177 * 178 * @param tsx_user Module to be registered as transaction user of the new 179 * transaction, which will receive notification from the 180 * transaction via on_tsx_state() callback. 178 181 * @param rdata The received incoming request. 179 * 180 * @return PJ_SUCCESS if successfull. 181 */ 182 PJ_DECL(pj_status_t) pjsip_tsx_init_uas( pjsip_transaction *tsx, 183 pjsip_rx_data *rdata); 184 185 /** 186 * Process incoming message for this transaction. 187 * 188 * @param tsx The transaction. 189 * @param rdata The incoming message. 190 */ 191 PJ_DECL(void) pjsip_tsx_on_rx_msg( pjsip_transaction *tsx, 192 pjsip_rx_data *rdata); 193 194 /** 195 * Transmit message with this transaction. 182 * @param p_tsx On return will contain the new transaction instance. 183 * 184 * @return PJ_SUCCESS if successfull. 185 */ 186 PJ_DECL(pj_status_t) pjsip_tsx_create_uas( pjsip_module *tsx_user, 187 pjsip_rx_data *rdata, 188 pjsip_transaction **p_tsx ); 189 190 /** 191 * Transmit message in tdata with this transaction. It is possible to 192 * pass NULL in tdata for UAC transaction, which in this case the request 193 * message which was specified in #pjsip_tsx_create_uac() will be sent. 196 194 * 197 195 * @param tsx The transaction. 198 196 * @param tdata The outgoing message. 199 */ 200 PJ_DECL(void) pjsip_tsx_on_tx_msg( pjsip_transaction *tsx, 201 pjsip_tx_data *tdata); 202 203 204 /** 205 * Transmit ACK message for 2xx/INVITE with this transaction. The ACK for 206 * non-2xx/INVITE is automatically sent by the transaction. 207 * This operation is only valid if the transaction is configured to handle ACK 208 * (tsx->handle_ack is non-zero). If this attribute is not set, then the 209 * transaction will comply with RFC-3261, i.e. it will set itself to 210 * TERMINATED state when it receives 2xx/INVITE. 211 * 212 * @param tsx The transaction. 213 * @param tdata The ACK request. 214 */ 215 PJ_DECL(void) pjsip_tsx_on_tx_ack( pjsip_transaction *tsx, 216 pjsip_tx_data *tdata); 217 218 /** 219 * Force terminate transaction. 220 * 221 * @param tsx The transaction. 222 * @param code The status code to report. 223 */ 224 PJ_DECL(void) pjsip_tsx_terminate( pjsip_transaction *tsx, 225 int code ); 197 * 198 * @return PJ_SUCCESS if successfull. 199 */ 200 PJ_DECL(pj_status_t) pjsip_tsx_send_msg( pjsip_transaction *tsx, 201 pjsip_tx_data *tdata); 202 226 203 227 204 /** … … 245 222 246 223 /** 224 * Force terminate transaction. 225 * 226 * @param tsx The transaction. 227 * @param code The status code to report. 228 */ 229 PJ_DECL(pj_status_t) pjsip_tsx_terminate( pjsip_transaction *tsx, 230 int st_code ); 231 232 233 /** 234 * Get the transaction instance in the incoming message. If the message 235 * has a corresponding transaction, this function will return non NULL 236 * value. 237 * 238 * @param rdata The incoming message buffer. 239 * 240 * @return The transaction instance associated with this message, 241 * or NULL if the message doesn't match any transactions. 242 */ 243 PJ_DECL(pjsip_transaction*) pjsip_rdata_get_tsx( pjsip_rx_data *rdata ); 244 245 246 /** 247 247 * @} 248 248 */ … … 263 263 264 264 265 /* Thread Local Storage ID for transaction lock (initialized by endpoint) */266 extern long pjsip_tsx_lock_tls_id;267 268 265 PJ_END_DECL 269 266 -
pjproject/trunk/pjsip/include/pjsip/sip_transport.h
r106 r107 172 172 173 173 /** The length of the packet received. */ 174 intlen;174 pj_ssize_t len; 175 175 176 176 /** The source address from which the packet was received. */ … … 252 252 { 253 253 /** 254 * This the transaction key generated for themessage.254 * Data attached by modules to this message. 255 255 */ 256 pj_str_t key;256 void *mod_data[PJSIP_MAX_MODULE]; 257 257 258 258 } endpt_info; -
pjproject/trunk/pjsip/include/pjsip/sip_transport_udp.h
- Property svn:keywords set to Id
-
pjproject/trunk/pjsip/include/pjsip/sip_types.h
r105 r107 52 52 /** SCTP. */ 53 53 PJSIP_TRANSPORT_SCTP, 54 55 /** Loopback (stream, reliable) */ 56 PJSIP_TRANSPORT_LOOP, 57 58 /** Loopback (datagram, unreliable) */ 59 PJSIP_TRANSPORT_LOOP_DGRAM, 54 60 55 61 } pjsip_transport_type_e; -
pjproject/trunk/pjsip/include/pjsip/sip_util.h
r106 r107 329 329 330 330 /** 331 * This composite function sends response message statelessly to an incoming 332 * request message. Internally it calls #pjsip_endpt_create_response() and 333 * #pjsip_endpt_send_response(). 334 * 335 * @param endpt The endpoint instance. 336 * @param rdata The incoming request message. 337 * @param st_code Status code of the response. 338 * @param st_text Optional status text of the response. 339 * @param hdr_list Optional header list to be added to the response. 340 * @param body Optional message body to be added to the response. 341 * 342 * @return PJ_SUCCESS if response message has successfully been 343 * created. 344 */ 345 PJ_DECL(pj_status_t) pjsip_endpt_respond_stateless(pjsip_endpoint *endpt, 346 pjsip_rx_data *rdata, 347 int st_code, 348 const pj_str_t *st_text, 349 const pjsip_hdr *hdr_list, 350 const pjsip_msg_body *body); 351 352 353 /** 331 354 * Send outgoing request and initiate UAC transaction for the request. 332 355 * This is an auxiliary function to be used by application to send arbitrary … … 353 376 void (*cb)(void*,pjsip_event*)); 354 377 378 /** 379 * Create new request message to be forwarded upstream to new destination URI 380 * in uri. The new request is a full/deep clone of the request received in 381 * rdata, unless if other copy mechanism is specified in the options. 382 * The branch parameter, if not NULL, will be used as the branch-param in 383 * the Via header. If it is NULL, then a unique branch parameter will be used. 384 * 385 * @param endpt The endpoint instance. 386 * @param rdata The incoming request message. 387 * @param uri The URI where the request will be forwarded to. 388 * @param branch Optional branch parameter. 389 * @param options Optional option flags when duplicating the message. 390 * @param tdata The result. 391 * 392 * @return PJ_SUCCESS on success. 393 */ 394 PJ_DECL(pj_status_t) pjsip_endpt_create_request_fwd( pjsip_endpoint *endpt, 395 pjsip_rx_data *rdata, 396 const pjsip_uri *uri, 397 const pj_str_t *branch, 398 unsigned options, 399 pjsip_tx_data **tdata); 400 401 /** 402 * Create new response message to be forwarded downstream by the proxy from 403 * the response message found in rdata. Note that this function practically 404 * will clone the response as is, i.e. without checking the validity of the 405 * response or removing top most Via header. This function will perform 406 * full/deep clone of the response, unless other copy mechanism is used in 407 * the options. 408 * 409 * @param endpt The endpoint instance. 410 * @param rdata The incoming response message. 411 * @param options Optional option flags when duplicate the message. 412 * @param tdata The result 413 * 414 * @return PJ_SUCCESS on success. 415 */ 416 PJ_DECL(pj_status_t) pjsip_endpt_create_response_fwd( pjsip_endpoint *endpt, 417 pjsip_rx_data *rdata, 418 unsigned options, 419 pjsip_tx_data **tdata); 420 421 422 /** 423 * Create a globally unique branch parameter based on the information in 424 * the incoming request message. This function guarantees that subsequent 425 * retransmissions of the same request will generate the same branch id. 426 * This function can also be used in the loop detection process. 427 * If the same request arrives back in the proxy with the same URL, it will 428 * calculate into the same branch id. 429 * Note that the returned string was allocated from rdata's pool. 430 * 431 * @param rdata The incoming request message. 432 * 433 * @return Unique branch-ID string. 434 */ 435 PJ_DECL(pj_str_t) pjsip_calculate_branch_id( pjsip_rx_data *rdata ); 436 355 437 356 438 /** -
pjproject/trunk/pjsip/include/pjsip_core.h
r106 r107 33 33 #include <pjsip/sip_transport.h> 34 34 #include <pjsip/sip_transport_udp.h> 35 #include <pjsip/sip_transport_loop.h> 35 36 #include <pjsip/sip_uri.h> 36 37 #include <pjsip/sip_util.h> -
pjproject/trunk/pjsip/src/pjsip/sip_endpoint.c
r106 r107 491 491 * recycled. 492 492 */ 493 PJ_DEF(void) pjsip_endpt_ destroy_pool( pjsip_endpoint *endpt, pj_pool_t *pool )494 { 495 PJ_LOG(5, (THIS_FILE, "pjsip_endpt_ destroy_pool(%s)", pj_pool_getobjname(pool)));493 PJ_DEF(void) pjsip_endpt_release_pool( pjsip_endpoint *endpt, pj_pool_t *pool ) 494 { 495 PJ_LOG(5, (THIS_FILE, "pjsip_endpt_release_pool(%s)", pj_pool_getobjname(pool))); 496 496 497 497 pj_mutex_lock(endpt->mutex); -
pjproject/trunk/pjsip/src/pjsip/sip_errno.c
- Property svn:keywords set to Id
r106 r107 1 /* $Id :$ */1 /* $Id$ */ 2 2 /* 3 3 * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org> … … 48 48 { PJSIP_ENOTREQUESTMSG, "Expecting request message"}, 49 49 { PJSIP_ENOTRESPONSEMSG, "Expecting response message"}, 50 { PJSIP_EINVALIDHDR, "Invalid header field"}, 50 51 51 52 /* Transport errors */ -
pjproject/trunk/pjsip/src/pjsip/sip_msg.c
r106 r107 20 20 #include <pjsip/sip_parser.h> 21 21 #include <pjsip/print_util.h> 22 #include <pjsip/sip_errno.h> 22 23 #include <pj/string.h> 23 24 #include <pj/pool.h> … … 366 367 /* Process message body. */ 367 368 if (msg->body) { 368 pj_str_t ctype_hdr = { "Content-Type: ", 14}; 369 int len; 370 const pjsip_media_type *media = &msg->body->content_type; 371 char *clen_pos; 372 373 /* Add Content-Type header. */ 374 if ( (end-p) < 24+media->type.slen+media->subtype.slen+media->param.slen) { 375 return -1; 369 char *clen_pos = NULL; 370 371 /* Automaticly adds Content-Type and Content-Length headers, only 372 * if content_type is set in the message body. 373 */ 374 if (msg->body->content_type.type.slen) { 375 pj_str_t ctype_hdr = { "Content-Type: ", 14}; 376 const pjsip_media_type *media = &msg->body->content_type; 377 378 /* Add Content-Type header. */ 379 if ( (end-p) < 24 + media->type.slen + media->subtype.slen + 380 media->param.slen) 381 { 382 return -1; 383 } 384 pj_memcpy(p, ctype_hdr.ptr, ctype_hdr.slen); 385 p += ctype_hdr.slen; 386 p += print_media_type(p, media); 387 *p++ = '\r'; 388 *p++ = '\n'; 389 390 /* Add Content-Length header. */ 391 if ((end-p) < clen_hdr.slen + 12 + 2) { 392 return -1; 393 } 394 pj_memcpy(p, clen_hdr.ptr, clen_hdr.slen); 395 p += clen_hdr.slen; 396 397 /* Print blanks after "Content-Type:", this is where we'll put 398 * the content length value after we know the length of the 399 * body. 400 */ 401 pj_memset(p, ' ', 12); 402 clen_pos = p; 403 p += 12; 404 *p++ = '\r'; 405 *p++ = '\n'; 376 406 } 377 pj_memcpy(p, ctype_hdr.ptr, ctype_hdr.slen);378 p += ctype_hdr.slen;379 p += print_media_type(p, media);380 *p++ = '\r';381 *p++ = '\n';382 383 /* Add Content-Length header. */384 if ((end-p) < clen_hdr.slen+12+2) {385 return -1;386 }387 pj_memcpy(p, clen_hdr.ptr, clen_hdr.slen);388 p += clen_hdr.slen;389 390 /* Print blanks after "Content-Type:", this is where we'll put391 * the content length value after we know the length of the392 * body.393 */394 pj_memset(p, ' ', 12);395 clen_pos = p;396 p += 12;397 *p++ = '\r';398 *p++ = '\n';399 407 400 408 /* Add blank newline. */ … … 412 420 * Content-Length header. 413 421 */ 414 len = pj_utoa(len, clen_pos); 415 clen_pos[len] = ' '; 422 if (clen_pos) { 423 len = pj_utoa(len, clen_pos); 424 clen_pos[len] = ' '; 425 } 416 426 417 427 } else { … … 1465 1475 /////////////////////////////////////////////////////////////////////////////// 1466 1476 /* 1467 * General purpose function to textual data in a SIP body.1477 * Message body manipulations. 1468 1478 */ 1469 1479 PJ_DEF(int) pjsip_print_text_body(pjsip_msg_body *msg_body, char *buf, pj_size_t size) … … 1474 1484 return msg_body->len; 1475 1485 } 1486 1487 PJ_DEF(pj_status_t) pjsip_msg_body_clone( pj_pool_t *pool, 1488 pjsip_msg_body *dst_body, 1489 const pjsip_msg_body *src_body ) 1490 { 1491 /* First check if clone_data field is initialized. */ 1492 PJ_ASSERT_RETURN( src_body->clone_data!=NULL, PJ_EINVAL ); 1493 1494 /* Duplicate content-type */ 1495 pj_strdup(pool, &dst_body->content_type.type, 1496 &src_body->content_type.type); 1497 pj_strdup(pool, &dst_body->content_type.subtype, 1498 &src_body->content_type.subtype); 1499 pj_strdup(pool, &dst_body->content_type.param, 1500 &src_body->content_type.param); 1501 1502 /* Duplicate data. */ 1503 dst_body->data = (*src_body->clone_data)(pool, src_body->data, 1504 src_body->len ); 1505 1506 /* Length. */ 1507 dst_body->len = src_body->len; 1508 1509 /* Function pointers. */ 1510 dst_body->print_body = src_body->print_body; 1511 dst_body->clone_data = src_body->clone_data; 1512 1513 return PJ_SUCCESS; 1514 } 1515 -
pjproject/trunk/pjsip/src/pjsip/sip_transaction.c
r106 r107 18 18 */ 19 19 #include <pjsip/sip_transaction.h> 20 #include <pjsip/sip_transport.h>21 #include <pjsip/sip_config.h>22 20 #include <pjsip/sip_util.h> 23 #include <pjsip/sip_ event.h>21 #include <pjsip/sip_module.h> 24 22 #include <pjsip/sip_endpoint.h> 25 23 #include <pjsip/sip_errno.h> 24 #include <pjsip/sip_event.h> 25 #include <pj/hash.h> 26 #include <pj/pool.h> 27 #include <pj/os.h> 28 #include <pj/string.h> 29 #include <pj/assert.h> 30 #include <pj/guid.h> 26 31 #include <pj/log.h> 27 #include <pj/string.h> 28 #include <pj/os.h> 29 #include <pj/guid.h> 30 #include <pj/pool.h> 31 #include <pj/assert.h> 32 33 #if 0 // XXX JUNK 34 /* Initialize TLS ID for transaction lock. */ 35 status = pj_thread_local_alloc(&pjsip_tsx_lock_tls_id); 36 if (status != PJ_SUCCESS) { 37 goto on_error; 38 } 39 pj_thread_local_set(pjsip_tsx_lock_tls_id, NULL); 40 41 42 /* Create hash table for transaction. */ 43 endpt->tsx_table = pj_hash_create( endpt->pool, PJSIP_MAX_TSX_COUNT ); 44 if (!endpt->tsx_table) { 45 status = PJ_ENOMEM; 46 goto on_error; 47 } 48 49 50 /* 51 * Create a new transaction. 52 * Endpoint must then initialize the new transaction as either UAS or UAC, and 53 * register it to the hash table. 54 */ 55 PJ_DEF(pj_status_t) pjsip_endpt_create_tsx(pjsip_endpoint *endpt, 56 pjsip_transaction **p_tsx) 57 { 58 pj_pool_t *pool; 59 60 PJ_ASSERT_RETURN(endpt && p_tsx, PJ_EINVAL); 61 62 PJ_LOG(5, (THIS_FILE, "pjsip_endpt_create_tsx()")); 63 64 /* Request one pool for the transaction. Mutex is locked there. */ 65 pool = pjsip_endpt_create_pool(endpt, "ptsx%p", 66 PJSIP_POOL_LEN_TSX, PJSIP_POOL_INC_TSX); 67 if (pool == NULL) { 68 return PJ_ENOMEM; 69 } 70 71 /* Create the transaction. */ 72 return pjsip_tsx_create(pool, endpt, p_tsx); 73 } 74 75 76 /* 77 * Register the transaction to the endpoint. 78 * This will put the transaction to the transaction hash table. Before calling 79 * this function, the transaction must be INITIALIZED as either UAS or UAC, so 80 * that the transaction key is built. 81 */ 82 PJ_DEF(void) pjsip_endpt_register_tsx( pjsip_endpoint *endpt, 83 pjsip_transaction *tsx) 84 { 85 PJ_LOG(5, (THIS_FILE, "pjsip_endpt_register_tsx(%s)", tsx->obj_name)); 86 87 pj_assert(tsx->transaction_key.slen != 0); 88 //pj_assert(tsx->state != PJSIP_TSX_STATE_NULL); 89 90 /* Lock hash table mutex. */ 91 pj_mutex_lock(endpt->tsx_table_mutex); 92 93 /* Register the transaction to the hash table. */ 94 pj_hash_set( tsx->pool, endpt->tsx_table, tsx->transaction_key.ptr, 95 tsx->transaction_key.slen, tsx); 96 97 /* Unlock mutex. */ 98 pj_mutex_unlock(endpt->tsx_table_mutex); 99 } 100 101 /* 102 * Find transaction by the key. 103 */ 104 PJ_DEF(pjsip_transaction*) pjsip_endpt_find_tsx( pjsip_endpoint *endpt, 105 const pj_str_t *key ) 106 { 107 pjsip_transaction *tsx; 108 109 PJ_LOG(5, (THIS_FILE, "pjsip_endpt_find_tsx()")); 110 111 /* Start lock mutex in the endpoint. */ 112 pj_mutex_lock(endpt->tsx_table_mutex); 113 114 /* Find the transaction in the hash table. */ 115 tsx = pj_hash_get( endpt->tsx_table, key->ptr, key->slen ); 116 117 /* Unlock mutex. */ 118 pj_mutex_unlock(endpt->tsx_table_mutex); 119 120 return tsx; 121 } 122 123 /* 124 * Create key. 125 */ 126 static void rdata_create_key( pjsip_rx_data *rdata) 127 { 128 pjsip_role_e role; 129 if (rdata->msg_info.msg->type == PJSIP_REQUEST_MSG) { 130 role = PJSIP_ROLE_UAS; 131 } else { 132 role = PJSIP_ROLE_UAC; 133 } 134 pjsip_tsx_create_key(rdata->tp_info.pool, &rdata->endpt_info.key, role, 135 &rdata->msg_info.cseq->method, rdata); 136 } 137 138 139 /* 140 * This is the callback that is called by the transport manager when it 141 * receives a message from the network. 142 */ 143 static void endpt_transport_callback( pjsip_endpoint *endpt, 144 pj_status_t status, 145 pjsip_rx_data *rdata ) 146 { 147 pjsip_msg *msg = rdata->msg_info.msg; 148 pjsip_transaction *tsx; 149 pj_bool_t a_new_transaction_just_been_created = PJ_FALSE; 150 151 PJ_LOG(5, (THIS_FILE, "endpt_transport_callback(rdata=%p)", rdata)); 152 153 if (status != PJ_SUCCESS) { 154 const char *src_addr = rdata->pkt_info.src_name; 155 int port = rdata->pkt_info.src_port; 156 PJSIP_ENDPT_LOG_ERROR((endpt, "transport", status, 157 "Src.addr=%s:%d, packet:--\n" 158 "%s\n" 159 "-- end of packet. Error", 160 src_addr, port, rdata->msg_info.msg_buf)); 161 return; 162 } 163 164 /* For response, check that the value in Via sent-by match the transport. 165 * If not matched, silently drop the response. 166 * Ref: RFC3261 Section 18.1.2 Receiving Response 167 */ 168 if (msg->type == PJSIP_RESPONSE_MSG) { 169 const pj_str_t *addr_addr; 170 int port = rdata->msg_info.via->sent_by.port; 171 pj_bool_t mismatch = PJ_FALSE; 172 if (port == 0) { 173 int type; 174 type = rdata->tp_info.transport->key.type; 175 port = pjsip_transport_get_default_port_for_type(type); 176 } 177 addr_addr = &rdata->tp_info.transport->local_name.host; 178 if (pj_strcmp(&rdata->msg_info.via->sent_by.host, addr_addr) != 0) 179 mismatch = PJ_TRUE; 180 else if (port != rdata->tp_info.transport->local_name.port) { 181 /* Port or address mismatch, we should discard response */ 182 /* But we saw one implementation (we don't want to name it to 183 * protect the innocence) which put wrong sent-by port although 184 * the "rport" parameter is correct. 185 * So we discard the response only if the port doesn't match 186 * both the port in sent-by and rport. We try to be lenient here! 187 */ 188 if (rdata->msg_info.via->rport_param != rdata->tp_info.transport->local_name.port) 189 mismatch = PJ_TRUE; 190 else { 191 PJ_LOG(4,(THIS_FILE, "Response %p has mismatch port in sent-by" 192 " but the rport parameter is correct", 193 rdata)); 194 } 195 } 196 197 if (mismatch) { 198 pjsip_event e; 199 200 PJSIP_EVENT_INIT_DISCARD_MSG(e, rdata, PJSIP_EINVALIDVIA); 201 endpt_do_event( endpt, &e ); 202 return; 203 } 204 } 205 206 /* Create key for transaction lookup. */ 207 rdata_create_key( rdata); 208 209 /* Find the transaction for the received message. */ 210 PJ_LOG(5, (THIS_FILE, "finding tsx with key=%.*s", 211 rdata->endpt_info.key.slen, rdata->endpt_info.key.ptr)); 212 213 /* Start lock mutex in the endpoint. */ 214 pj_mutex_lock(endpt->tsx_table_mutex); 215 216 /* Find the transaction in the hash table. */ 217 tsx = pj_hash_get( endpt->tsx_table, rdata->endpt_info.key.ptr, rdata->endpt_info.key.slen ); 218 219 /* Unlock mutex. */ 220 pj_mutex_unlock(endpt->tsx_table_mutex); 221 222 /* If the transaction is not found... */ 223 if (tsx == NULL || tsx->state == PJSIP_TSX_STATE_TERMINATED) { 224 225 /* 226 * For response message, discard the message, except if the response is 227 * an 2xx class response to INVITE, which in this case it must be 228 * passed to TU to be acked. 229 */ 230 if (msg->type == PJSIP_RESPONSE_MSG) { 231 232 /* Inform TU about the 200 message, only if it's INVITE. */ 233 if (PJSIP_IS_STATUS_IN_CLASS(msg->line.status.code, 200) && 234 rdata->msg_info.cseq->method.id == PJSIP_INVITE_METHOD) 235 { 236 pjsip_event e; 237 238 /* Should not happen for UA. Tsx theoritically lives until 239 * all responses are absorbed. 240 */ 241 pj_assert(0); 242 243 PJSIP_EVENT_INIT_RX_200_MSG(e, rdata); 244 endpt_do_event( endpt, &e ); 245 246 } else { 247 /* Just discard the response, inform TU. */ 248 pjsip_event e; 249 250 PJSIP_EVENT_INIT_DISCARD_MSG(e, rdata, 251 PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_CALL_TSX_DOES_NOT_EXIST)); 252 endpt_do_event( endpt, &e ); 253 } 254 255 /* 256 * For non-ACK request message, create a new transaction. 257 */ 258 } else if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) { 259 260 pj_status_t status; 261 262 /* Create transaction, mutex is locked there. */ 263 status = pjsip_endpt_create_tsx(endpt, &tsx); 264 if (status != PJ_SUCCESS) { 265 PJSIP_ENDPT_LOG_ERROR((endpt, THIS_FILE, status, 266 "Unable to create transaction")); 267 return; 268 } 269 270 /* Initialize transaction as UAS. */ 271 pjsip_tsx_init_uas( tsx, rdata ); 272 273 /* Register transaction, mutex is locked there. */ 274 pjsip_endpt_register_tsx( endpt, tsx ); 275 276 a_new_transaction_just_been_created = PJ_TRUE; 277 } 278 } 279 280 /* If transaction is found (or newly created), pass the message. 281 * Otherwise if it's an ACK request, pass directly to TU. 282 */ 283 if (tsx && tsx->state != PJSIP_TSX_STATE_TERMINATED) { 284 /* Dispatch message to transaction. */ 285 pjsip_tsx_on_rx_msg( tsx, rdata ); 286 287 } else if (rdata->msg_info.msg->line.req.method.id == PJSIP_ACK_METHOD) { 288 /* 289 * This is an ACK message, but the INVITE transaction could not 290 * be found (possibly because the branch parameter in Via in ACK msg 291 * is different than the branch in original INVITE). This happens with 292 * SER! 293 */ 294 pjsip_event event; 295 296 PJSIP_EVENT_INIT_RX_ACK_MSG(event,rdata); 297 endpt_do_event( endpt, &event ); 298 } 299 300 /* 301 * If a new request message has just been receieved, but no modules 302 * seem to be able to handle the request message, then terminate the 303 * transaction. 304 * 305 * Ideally for cases like "unsupported method", we should be able to 306 * answer the request statelessly. But we can not do that since the 307 * endpoint shoule be able to be used as both user agent and proxy stack, 308 * and a proxy stack should be able to handle arbitrary methods. 309 */ 310 if (a_new_transaction_just_been_created && tsx->status_code < 100) { 311 /* Certainly no modules has sent any response message. 312 * Check that any modules has attached a module data. 313 */ 314 int i; 315 for (i=0; i<PJSIP_MAX_MODULE; ++i) { 316 if (tsx->module_data[i] != NULL) { 317 break; 318 } 319 } 320 if (i == PJSIP_MAX_MODULE) { 321 /* No modules have attached itself to the transaction. 322 * Terminate the transaction with 501/Not Implemented. 323 */ 324 pjsip_tx_data *tdata; 325 pj_status_t status; 326 327 if (tsx->method.id == PJSIP_OPTIONS_METHOD) { 328 status = pjsip_endpt_create_response(endpt, rdata, 200, 329 &tdata); 330 } else { 331 status = pjsip_endpt_create_response(endpt, rdata, 332 PJSIP_SC_METHOD_NOT_ALLOWED, 333 &tdata); 334 } 335 336 if (status != PJ_SUCCESS) { 337 PJSIP_ENDPT_LOG_ERROR((endpt, THIS_FILE, status, 338 "Unable to create response")); 339 return; 340 } 341 342 if (endpt->allow_hdr) { 343 pjsip_msg_add_hdr( tdata->msg, 344 pjsip_hdr_shallow_clone(tdata->pool, endpt->allow_hdr)); 345 } 346 pjsip_tsx_on_tx_msg( tsx, tdata ); 347 348 } else { 349 /* 350 * If a module has registered itself in the transaction but it 351 * hasn't responded the request, chances are the module wouldn't 352 * respond to the request at all. We terminate the request here 353 * with 500/Internal Server Error, to be safe. 354 */ 355 pjsip_tx_data *tdata; 356 pj_status_t status; 357 358 status = pjsip_endpt_create_response(endpt, rdata, 500, &tdata); 359 if (status != PJ_SUCCESS) { 360 PJSIP_ENDPT_LOG_ERROR((endpt, THIS_FILE, status, 361 "Unable to create response")); 362 return; 363 } 364 365 pjsip_tsx_on_tx_msg(tsx, tdata); 366 } 367 } 368 } 369 370 371 372 /* Transaction tables. */ 373 count = pj_hash_count(endpt->tsx_table); 374 PJ_LOG(3, (THIS_FILE, " Number of transactions: %u", count)); 375 376 if (count && detail) { 377 pj_hash_iterator_t it_val; 378 pj_hash_iterator_t *it; 379 pj_time_val now; 380 381 PJ_LOG(3, (THIS_FILE, " Dumping transaction tables:")); 382 383 pj_gettimeofday(&now); 384 it = pj_hash_first(endpt->tsx_table, &it_val); 385 386 while (it != NULL) { 387 int timeout_diff; 388 389 /* Get the transaction. No need to lock transaction's mutex 390 * since we already hold endpoint mutex, so that no transactions 391 * will be deleted. 392 */ 393 pjsip_transaction *tsx = pj_hash_this(endpt->tsx_table, it); 394 395 const char *role = (tsx->role == PJSIP_ROLE_UAS ? "UAS" : "UAC"); 396 397 if (tsx->timeout_timer._timer_id != -1) { 398 if (tsx->timeout_timer._timer_value.sec > now.sec) { 399 timeout_diff = tsx->timeout_timer._timer_value.sec - now.sec; 400 } else { 401 timeout_diff = now.sec - tsx->timeout_timer._timer_value.sec; 402 timeout_diff = 0 - timeout_diff; 403 } 404 } else { 405 timeout_diff = -1; 406 } 407 408 PJ_LOG(3, (THIS_FILE, " %s %s %10.*s %.9u %s t=%ds", 409 tsx->obj_name, role, 410 tsx->method.name.slen, tsx->method.name.ptr, 411 tsx->cseq, 412 pjsip_tsx_state_str(tsx->state), 413 timeout_diff)); 414 415 it = pj_hash_next(endpt->tsx_table, it); 416 } 417 } 418 419 420 421 #endif // XXX JUNK 422 423 /* Thread Local Storage ID for transaction lock (initialized by endpoint) */ 424 long pjsip_tsx_lock_tls_id; 425 426 /* State names */ 32 33 /***************************************************************************** 34 ** 35 ** Declarations and static variable definitions section. 36 ** 37 ***************************************************************************** 38 39 /* Prototypes. */ 40 static pj_status_t mod_tsx_layer_load(pjsip_endpoint *endpt); 41 static pj_status_t mod_tsx_layer_start(void); 42 static pj_status_t mod_tsx_layer_stop(void); 43 static pj_status_t mod_tsx_layer_unload(void); 44 static pj_bool_t mod_tsx_layer_on_rx_request(pjsip_rx_data *rdata); 45 static pj_bool_t mod_tsx_layer_on_rx_response(pjsip_rx_data *rdata); 46 47 /* Transaction layer module definition. */ 48 static struct mod_tsx_layer 49 { 50 struct pjsip_module mod; 51 pj_pool_t *pool; 52 pjsip_endpoint *endpt; 53 pj_mutex_t *mutex; 54 pj_hash_table_t *htable; 55 } mod_tsx_layer = 56 { { 57 NULL, NULL, /* List's prev and next. */ 58 { "mod-tsx-layer", 13 }, /* Module name. */ 59 -1, /* Module ID */ 60 PJSIP_MOD_PRIORITY_TSX_LAYER, /* Priority. */ 61 NULL, /* User_data. */ 62 0, /* Methods count. */ 63 { NULL }, /* Array of methods. */ 64 mod_tsx_layer_load, /* load(). */ 65 mod_tsx_layer_start, /* start() */ 66 mod_tsx_layer_stop, /* stop() */ 67 mod_tsx_layer_unload, /* unload() */ 68 mod_tsx_layer_on_rx_request, /* on_rx_request() */ 69 mod_tsx_layer_on_rx_response, /* on_rx_response() */ 70 NULL 71 } 72 }; 73 74 /* Thread Local Storage ID for transaction lock */ 75 static long pjsip_tsx_lock_tls_id; 76 77 /* Transaction state names */ 427 78 static const char *state_str[] = 428 79 { … … 440 91 static const char *role_name[] = 441 92 { 442 "Client", 443 "Server" 93 "UAC", 94 "UAS" 95 }; 96 97 /* Transport flag. */ 98 enum 99 { 100 TSX_HAS_PENDING_TRANSPORT = 1, 101 TSX_HAS_PENDING_RESCHED = 2, 102 TSX_HAS_PENDING_SEND = 4, 103 TSX_HAS_PENDING_DESTROY = 8, 444 104 }; 445 105 … … 469 129 }; 470 130 471 /* Function Prototypes */ 472 static pj_status_t pjsip_tsx_on_state_null( pjsip_transaction *tsx, 131 132 /* Prototypes. */ 133 static void lock_tsx(pjsip_transaction *tsx, struct tsx_lock_data *lck); 134 static pj_status_t unlock_tsx( pjsip_transaction *tsx, 135 struct tsx_lock_data *lck); 136 static pj_status_t tsx_on_state_null( pjsip_transaction *tsx, 473 137 pjsip_event *event); 474 static pj_status_t pjsip_tsx_on_state_calling(pjsip_transaction *tsx,138 static pj_status_t tsx_on_state_calling( pjsip_transaction *tsx, 475 139 pjsip_event *event); 476 static pj_status_t pjsip_tsx_on_state_trying(pjsip_transaction *tsx,140 static pj_status_t tsx_on_state_trying( pjsip_transaction *tsx, 477 141 pjsip_event *event); 478 static pj_status_t pjsip_tsx_on_state_proceeding_uas( pjsip_transaction *tsx,142 static pj_status_t tsx_on_state_proceeding_uas( pjsip_transaction *tsx, 479 143 pjsip_event *event); 480 static pj_status_t pjsip_tsx_on_state_proceeding_uac( pjsip_transaction *tsx,144 static pj_status_t tsx_on_state_proceeding_uac( pjsip_transaction *tsx, 481 145 pjsip_event *event); 482 static pj_status_t pjsip_tsx_on_state_completed_uas(pjsip_transaction *tsx,146 static pj_status_t tsx_on_state_completed_uas( pjsip_transaction *tsx, 483 147 pjsip_event *event); 484 static pj_status_t pjsip_tsx_on_state_completed_uac(pjsip_transaction *tsx,148 static pj_status_t tsx_on_state_completed_uac( pjsip_transaction *tsx, 485 149 pjsip_event *event); 486 static pj_status_t pjsip_tsx_on_state_confirmed(pjsip_transaction *tsx,150 static pj_status_t tsx_on_state_confirmed( pjsip_transaction *tsx, 487 151 pjsip_event *event); 488 static pj_status_t pjsip_tsx_on_state_terminated(pjsip_transaction *tsx,152 static pj_status_t tsx_on_state_terminated( pjsip_transaction *tsx, 489 153 pjsip_event *event); 490 static pj_status_t pjsip_tsx_on_state_destroyed(pjsip_transaction *tsx,154 static pj_status_t tsx_on_state_destroyed( pjsip_transaction *tsx, 491 155 pjsip_event *event); 492 493 static void tsx_timer_callback( pj_timer_heap_t *theap, 494 pj_timer_entry *entry); 495 static int tsx_send_msg( pjsip_transaction *tsx, 496 pjsip_tx_data *tdata); 497 static void lock_tsx( pjsip_transaction *tsx, struct 498 tsx_lock_data *lck ); 499 static pj_status_t unlock_tsx( pjsip_transaction *tsx, 500 struct tsx_lock_data *lck ); 156 static void tsx_timer_callback( pj_timer_heap_t *theap, 157 pj_timer_entry *entry); 158 static pj_status_t tsx_create( pjsip_module *tsx_user, 159 pjsip_transaction **p_tsx); 160 static void tsx_destroy( pjsip_transaction *tsx ); 161 static void tsx_resched_retransmission( pjsip_transaction *tsx ); 162 static pj_status_t tsx_retransmit( pjsip_transaction *tsx, int resched); 163 static int tsx_send_msg( pjsip_transaction *tsx, 164 pjsip_tx_data *tdata); 165 static void tsx_on_rx_msg( pjsip_transaction *tsx, 166 pjsip_rx_data *rdata ); 167 501 168 502 169 /* State handlers for UAC, indexed by state */ … … 504 171 pjsip_event *) = 505 172 { 506 & pjsip_tsx_on_state_null,507 & pjsip_tsx_on_state_calling,508 &pjsip_tsx_on_state_trying,509 & pjsip_tsx_on_state_proceeding_uac,510 & pjsip_tsx_on_state_completed_uac,511 & pjsip_tsx_on_state_confirmed,512 & pjsip_tsx_on_state_terminated,513 & pjsip_tsx_on_state_destroyed,173 &tsx_on_state_null, 174 &tsx_on_state_calling, 175 NULL, 176 &tsx_on_state_proceeding_uac, 177 &tsx_on_state_completed_uac, 178 &tsx_on_state_confirmed, 179 &tsx_on_state_terminated, 180 &tsx_on_state_destroyed, 514 181 }; 515 182 … … 518 185 pjsip_event *) = 519 186 { 520 & pjsip_tsx_on_state_null,521 &pjsip_tsx_on_state_calling,522 & pjsip_tsx_on_state_trying,523 & pjsip_tsx_on_state_proceeding_uas,524 & pjsip_tsx_on_state_completed_uas,525 & pjsip_tsx_on_state_confirmed,526 & pjsip_tsx_on_state_terminated,527 & pjsip_tsx_on_state_destroyed,187 &tsx_on_state_null, 188 NULL, 189 &tsx_on_state_trying, 190 &tsx_on_state_proceeding_uas, 191 &tsx_on_state_completed_uas, 192 &tsx_on_state_confirmed, 193 &tsx_on_state_terminated, 194 &tsx_on_state_destroyed, 528 195 }; 529 196 197 /***************************************************************************** 198 ** 199 ** Utilities 200 ** 201 ***************************************************************************** 202 */ 530 203 /* 531 204 * Get transaction state name. … … 543 216 return role_name[role]; 544 217 } 545 546 547 548 /*549 * Unregister the transaction from the hash table, and destroy the resources550 * from the transaction.551 */552 PJ_DEF(void) pjsip_endpt_destroy_tsx( pjsip_endpoint *endpt,553 pjsip_transaction *tsx)554 {555 PJ_LOG(5, (THIS_FILE, "pjsip_endpt_destroy_tsx(%s)", tsx->obj_name));556 557 pj_assert(tsx->state == PJSIP_TSX_STATE_DESTROYED);558 559 /* No need to lock transaction.560 * This function typically is called from the transaction callback, which561 * means that transaction mutex is being held.562 */563 pj_assert( pj_mutex_is_locked(tsx->mutex) );564 565 /* Lock endpoint. */566 pj_mutex_lock( endpt->tsx_table_mutex );567 568 /* Unregister from the hash table. */569 pj_hash_set( NULL, endpt->tsx_table, tsx->transaction_key.ptr,570 tsx->transaction_key.slen, NULL);571 572 /* Unlock endpoint mutex. */573 pj_mutex_unlock( endpt->tsx_table_mutex );574 575 /* Destroy transaction mutex. */576 pj_mutex_destroy( tsx->mutex );577 578 /* Release the pool for the transaction. */579 pj_pool_release(tsx->pool);580 581 PJ_LOG(4, (THIS_FILE, "tsx%p destroyed", tsx));582 }583 584 218 585 219 … … 644 278 *p++ = SEPARATOR; 645 279 646 /* Add Request-URI */647 /* This is BUG!648 * Response doesn't have Request-URI!649 *650 len = req_uri->vptr->print( PJSIP_URI_IN_REQ_URI, req_uri, p, end-p );651 p += len;652 *p++ = SEPARATOR;653 */654 655 280 /* Add method, except when method is INVITE or ACK. */ 656 281 if (method->id != PJSIP_INVITE_METHOD && method->id != PJSIP_ACK_METHOD) { … … 771 396 } 772 397 773 774 /* 775 * Create new transaction. 776 */ 777 PJ_DEF(pj_status_t) pjsip_tsx_create( pj_pool_t *pool, 778 pjsip_endpoint *endpt, 779 pjsip_transaction **p_tsx) 780 { 398 /***************************************************************************** 399 ** 400 ** Transaction layer module 401 ** 402 ***************************************************************************** 403 404 /* 405 * Create transaction layer module and registers it to the endpoint. 406 */ 407 PJ_DEF(pj_status_t) pjsip_tsx_layer_init(pjsip_endpoint *endpt) 408 { 409 pj_pool_t *pool; 410 pj_status_t status; 411 412 413 PJ_ASSERT_RETURN(mod_tsx_layer.endpt==NULL, PJ_EINVALIDOP); 414 415 416 /* Initialize TLS ID for transaction lock. */ 417 status = pj_thread_local_alloc(&pjsip_tsx_lock_tls_id); 418 if (status != PJ_SUCCESS) 419 return status; 420 421 pj_thread_local_set(pjsip_tsx_lock_tls_id, NULL); 422 423 /* 424 * Initialize transaction layer structure. 425 */ 426 427 /* Create pool for the module. */ 428 pool = pjsip_endpt_create_pool(endpt, "tsxlayer", 429 PJSIP_POOL_TSX_LAYER_LEN, 430 PJSIP_POOL_TSX_LAYER_INC ); 431 if (!pool) 432 return PJ_ENOMEM; 433 434 435 /* Initialize some attributes. */ 436 mod_tsx_layer.pool = pool; 437 mod_tsx_layer.endpt = endpt; 438 439 440 /* Create hash table. */ 441 mod_tsx_layer.htable = pj_hash_create( pool, PJSIP_MAX_TSX_COUNT ); 442 if (!mod_tsx_layer.htable) { 443 pjsip_endpt_release_pool(endpt, pool); 444 return PJ_ENOMEM; 445 } 446 447 /* Create mutex. */ 448 status = pj_mutex_create_recursive(pool, "tsxlayer", &mod_tsx_layer.mutex); 449 if (status != PJ_SUCCESS) { 450 pjsip_endpt_release_pool(endpt, pool); 451 return status; 452 } 453 454 /* 455 * Register transaction layer module to endpoint. 456 */ 457 status = pjsip_endpt_register_module( endpt, &mod_tsx_layer.mod ); 458 if (status != PJ_SUCCESS) { 459 pj_mutex_destroy(mod_tsx_layer.mutex); 460 pjsip_endpt_release_pool(endpt, pool); 461 return status; 462 } 463 464 return PJ_SUCCESS; 465 } 466 467 468 /* 469 * Get the instance of transaction layer module. 470 */ 471 PJ_DEF(pjsip_module*) pjsip_tsx_layer_instance(void) 472 { 473 return &mod_tsx_layer.mod; 474 } 475 476 477 /* 478 * Unregister and destroy transaction layer module. 479 */ 480 PJ_DEF(pj_status_t) pjsip_tsx_layer_destroy(void) 481 { 482 /* Are we registered? */ 483 PJ_ASSERT_RETURN(mod_tsx_layer.endpt!=NULL, PJ_EINVALIDOP); 484 485 /* Unregister from endpoint. 486 * Clean-ups will be done in the unload() module callback. 487 */ 488 return pjsip_endpt_unregister_module( mod_tsx_layer.endpt, 489 &mod_tsx_layer.mod); 490 } 491 492 493 /* 494 * Register the transaction to the hash table. 495 */ 496 static void mod_tsx_layer_register_tsx( pjsip_transaction *tsx) 497 { 498 pj_assert(tsx->transaction_key.slen != 0); 499 //pj_assert(tsx->state != PJSIP_TSX_STATE_NULL); 500 501 /* Lock hash table mutex. */ 502 pj_mutex_lock(mod_tsx_layer.mutex); 503 504 /* Register the transaction to the hash table. */ 505 pj_hash_set( tsx->pool, mod_tsx_layer.htable, tsx->transaction_key.ptr, 506 tsx->transaction_key.slen, tsx); 507 508 /* Unlock mutex. */ 509 pj_mutex_unlock(mod_tsx_layer.mutex); 510 } 511 512 513 /* 514 * Unregister the transaction from the hash table. 515 */ 516 static void mod_tsx_layer_unregister_tsx( pjsip_transaction *tsx) 517 { 518 pj_assert(tsx->transaction_key.slen != 0); 519 //pj_assert(tsx->state != PJSIP_TSX_STATE_NULL); 520 521 /* Lock hash table mutex. */ 522 pj_mutex_lock(mod_tsx_layer.mutex); 523 524 /* Register the transaction to the hash table. */ 525 pj_hash_set( NULL, mod_tsx_layer.htable, tsx->transaction_key.ptr, 526 tsx->transaction_key.slen, NULL); 527 528 /* Unlock mutex. */ 529 pj_mutex_unlock(mod_tsx_layer.mutex); 530 } 531 532 533 /* 534 * Find a transaction. 535 */ 536 PJ_DEF(pjsip_transaction*) pjsip_tsx_layer_find_tsx( const pj_str_t *key, 537 pj_bool_t lock ) 538 { 539 pjsip_transaction *tsx; 540 541 pj_mutex_lock(mod_tsx_layer.mutex); 542 tsx = pj_hash_get( mod_tsx_layer.htable, key->ptr, key->slen ); 543 pj_mutex_unlock(mod_tsx_layer.mutex); 544 545 546 /* Race condition! 547 * Transaction may gets deleted before we have chance to lock it. 548 */ 549 PJ_TODO(FIX_RACE_CONDITION_HERE); 550 if (tsx && lock) 551 pj_mutex_lock(tsx->mutex); 552 553 return tsx; 554 } 555 556 557 /* This module callback is called when module is being loaded by 558 * endpoint. It does nothing for this module. 559 */ 560 static pj_status_t mod_tsx_layer_load(pjsip_endpoint *endpt) 561 { 562 PJ_UNUSED_ARG(endpt); 563 return PJ_SUCCESS; 564 } 565 566 567 /* This module callback is called when module is being started by 568 * endpoint. It does nothing for this module. 569 */ 570 static pj_status_t mod_tsx_layer_start(void) 571 { 572 return PJ_SUCCESS; 573 } 574 575 576 /* This module callback is called when module is being stopped by 577 * endpoint. 578 */ 579 static pj_status_t mod_tsx_layer_stop(void) 580 { 581 pj_hash_iterator_t it_buf, *it; 582 583 pj_mutex_lock(mod_tsx_layer.mutex); 584 585 /* Destroy all transactions. */ 586 it = pj_hash_first(mod_tsx_layer.htable, &it_buf); 587 while (it) { 588 pjsip_transaction *tsx = pj_hash_this(mod_tsx_layer.htable, it); 589 if (tsx) 590 tsx_destroy(tsx); 591 it = pj_hash_next(mod_tsx_layer.htable, it); 592 } 593 594 pj_mutex_unlock(mod_tsx_layer.mutex); 595 return PJ_SUCCESS; 596 } 597 598 599 /* This module callback is called when module is being unloaded by 600 * endpoint. 601 */ 602 static pj_status_t mod_tsx_layer_unload(void) 603 { 604 /* Destroy mutex. */ 605 pj_mutex_destroy(mod_tsx_layer.mutex); 606 607 /* Release pool. */ 608 pjsip_endpt_release_pool(mod_tsx_layer.endpt, mod_tsx_layer.pool); 609 610 /* Mark as unregistered. */ 611 mod_tsx_layer.endpt = NULL; 612 613 return PJ_SUCCESS; 614 } 615 616 617 /* This module callback is called when endpoint has received an 618 * incoming request message. 619 */ 620 static pj_bool_t mod_tsx_layer_on_rx_request(pjsip_rx_data *rdata) 621 { 622 pj_str_t key; 623 pjsip_transaction *tsx; 624 625 pjsip_tsx_create_key(rdata->tp_info.pool, &key, PJSIP_ROLE_UAS, 626 &rdata->msg_info.cseq->method, rdata); 627 628 /* Find transaction. */ 629 pj_mutex_lock( mod_tsx_layer.mutex ); 630 tsx = pj_hash_get( mod_tsx_layer.htable, key.ptr, key.slen ); 631 if (tsx == NULL || tsx->state == PJSIP_TSX_STATE_TERMINATED) { 632 /* Transaction not found. 633 * Reject the request so that endpoint passes the request to 634 * upper layer modules. 635 */ 636 pj_mutex_unlock( mod_tsx_layer.mutex); 637 return PJ_FALSE; 638 } 639 640 /* Unlock hash table. */ 641 pj_mutex_unlock( mod_tsx_layer.mutex ); 642 643 /* Race condition! 644 * Transaction may gets deleted before we have chance to lock it 645 * in tsx_on_rx_msg(). 646 */ 647 PJ_TODO(FIX_RACE_CONDITION_HERE); 648 649 /* Pass the message to the transaction. */ 650 tsx_on_rx_msg(tsx, rdata ); 651 652 return PJ_TRUE; 653 } 654 655 656 /* This module callback is called when endpoint has received an 657 * incoming response message. 658 */ 659 static pj_bool_t mod_tsx_layer_on_rx_response(pjsip_rx_data *rdata) 660 { 661 pj_str_t key; 662 pjsip_transaction *tsx; 663 664 pjsip_tsx_create_key(rdata->tp_info.pool, &key, PJSIP_ROLE_UAC, 665 &rdata->msg_info.cseq->method, rdata); 666 667 /* Find transaction. */ 668 pj_mutex_lock( mod_tsx_layer.mutex ); 669 tsx = pj_hash_get( mod_tsx_layer.htable, key.ptr, key.slen ); 670 if (tsx == NULL || tsx->state == PJSIP_TSX_STATE_TERMINATED) { 671 /* Transaction not found. 672 * Reject the request so that endpoint passes the request to 673 * upper layer modules. 674 */ 675 pj_mutex_unlock( mod_tsx_layer.mutex); 676 return PJ_FALSE; 677 } 678 679 /* Unlock hash table. */ 680 pj_mutex_unlock( mod_tsx_layer.mutex ); 681 682 /* Race condition! 683 * Transaction may gets deleted before we have chance to lock it 684 * in tsx_on_rx_msg(). 685 */ 686 PJ_TODO(FIX_RACE_CONDITION_HERE); 687 688 /* Pass the message to the transaction. */ 689 tsx_on_rx_msg(tsx, rdata ); 690 691 return PJ_TRUE; 692 } 693 694 695 /* 696 * Get transaction instance in the rdata. 697 */ 698 PJ_DEF(pjsip_transaction*) pjsip_rdata_get_tsx( pjsip_rx_data *rdata ) 699 { 700 return rdata->endpt_info.mod_data[mod_tsx_layer.mod.id]; 701 } 702 703 704 /***************************************************************************** 705 ** 706 ** Transaction 707 ** 708 ***************************************************************************** 709 710 /* 711 * Lock transaction and set the value of Thread Local Storage. 712 */ 713 static void lock_tsx(pjsip_transaction *tsx, struct tsx_lock_data *lck) 714 { 715 struct tsx_lock_data *prev_data; 716 717 pj_mutex_lock(tsx->mutex); 718 prev_data = (struct tsx_lock_data *) 719 pj_thread_local_get(pjsip_tsx_lock_tls_id); 720 lck->prev = prev_data; 721 lck->tsx = tsx; 722 lck->is_alive = 1; 723 pj_thread_local_set(pjsip_tsx_lock_tls_id, lck); 724 } 725 726 727 /* 728 * Unlock transaction. 729 * This will selectively unlock the mutex ONLY IF the transaction has not been 730 * destroyed. The function knows whether the transaction has been destroyed 731 * because when transaction is destroyed the is_alive flag for the transaction 732 * will be set to zero. 733 */ 734 static pj_status_t unlock_tsx( pjsip_transaction *tsx, 735 struct tsx_lock_data *lck) 736 { 737 pj_assert( (void*)pj_thread_local_get(pjsip_tsx_lock_tls_id) == lck); 738 pj_assert( lck->tsx == tsx ); 739 pj_thread_local_set(pjsip_tsx_lock_tls_id, lck->prev); 740 if (lck->is_alive) 741 pj_mutex_unlock(tsx->mutex); 742 743 return lck->is_alive ? PJ_SUCCESS : PJSIP_ETSXDESTROYED; 744 } 745 746 747 /* Create and initialize basic transaction structure. 748 * This function is called by both UAC and UAS creation. 749 */ 750 static pj_status_t tsx_create( pjsip_module *tsx_user, 751 pjsip_transaction **p_tsx) 752 { 753 pj_pool_t *pool; 781 754 pjsip_transaction *tsx; 782 755 pj_status_t status; 783 756 784 tsx = pj_pool_calloc(pool, 1, sizeof(pjsip_transaction)); 785 757 pool = pjsip_endpt_create_pool( mod_tsx_layer.endpt, "tsx", 758 PJSIP_POOL_TSX_LEN, PJSIP_POOL_TSX_INC ); 759 if (!pool) 760 return PJ_ENOMEM; 761 762 tsx = pj_pool_zalloc(pool, sizeof(pjsip_transaction)); 786 763 tsx->pool = pool; 787 tsx->endpt = endpt; 764 tsx->tsx_user = tsx_user; 765 tsx->endpt = mod_tsx_layer.endpt; 766 767 pj_sprintf(tsx->obj_name, "tsx%p", tsx); 768 769 tsx->handle_200resp = 1; 788 770 tsx->retransmit_timer.id = TSX_TIMER_RETRANSMISSION; 789 771 tsx->retransmit_timer._timer_id = -1; … … 794 776 tsx->timeout_timer.user_data = tsx; 795 777 tsx->timeout_timer.cb = &tsx_timer_callback; 796 pj_sprintf(tsx->obj_name, "tsx%p", tsx);797 status = pj_mutex_create_recursive(pool, " mtsx%p", &tsx->mutex);778 779 status = pj_mutex_create_recursive(pool, "tsx%p", &tsx->mutex); 798 780 if (status != PJ_SUCCESS) { 781 pjsip_endpt_release_pool(mod_tsx_layer.endpt, pool); 799 782 return status; 800 783 } … … 804 787 } 805 788 806 /* 807 * Lock transaction and set the value of Thread Local Storage. 808 */ 809 static void lock_tsx(pjsip_transaction *tsx, struct tsx_lock_data *lck) 810 { 811 struct tsx_lock_data *prev_data; 812 813 pj_mutex_lock(tsx->mutex); 814 prev_data = (struct tsx_lock_data *) 815 pj_thread_local_get(pjsip_tsx_lock_tls_id); 816 lck->prev = prev_data; 817 lck->tsx = tsx; 818 lck->is_alive = 1; 819 pj_thread_local_set(pjsip_tsx_lock_tls_id, lck); 820 } 821 822 823 /* 824 * Unlock transaction. 825 * This will selectively unlock the mutex ONLY IF the transaction has not been 826 * destroyed. The function knows whether the transaction has been destroyed 827 * because when transaction is destroyed the is_alive flag for the transaction 828 * will be set to zero. 829 */ 830 static pj_status_t unlock_tsx( pjsip_transaction *tsx, 831 struct tsx_lock_data *lck) 832 { 833 pj_assert( (void*)pj_thread_local_get(pjsip_tsx_lock_tls_id) == lck); 834 pj_assert( lck->tsx == tsx ); 835 pj_thread_local_set(pjsip_tsx_lock_tls_id, lck->prev); 836 if (lck->is_alive) 837 pj_mutex_unlock(tsx->mutex); 838 839 return lck->is_alive ? PJ_SUCCESS : PJSIP_ETSXDESTROYED; 840 } 789 790 /* Destroy transaction. */ 791 static void tsx_destroy( pjsip_transaction *tsx ) 792 { 793 pj_mutex_destroy(tsx->mutex); 794 pjsip_endpt_release_pool(tsx->endpt, tsx->pool); 795 } 796 797 798 /* 799 * Callback when timer expires. 800 */ 801 static void tsx_timer_callback( pj_timer_heap_t *theap, pj_timer_entry *entry) 802 { 803 pjsip_event event; 804 pjsip_transaction *tsx = entry->user_data; 805 struct tsx_lock_data lck; 806 807 PJ_UNUSED_ARG(theap); 808 809 PJ_LOG(5,(tsx->obj_name, "got timer event (%s timer)", 810 (entry->id==TSX_TIMER_RETRANSMISSION ? "Retransmit":"Timeout"))); 811 812 813 if (entry->id == TSX_TIMER_RETRANSMISSION) { 814 PJSIP_EVENT_INIT_TIMER(event, &tsx->retransmit_timer); 815 } else { 816 PJSIP_EVENT_INIT_TIMER(event, &tsx->timeout_timer); 817 } 818 819 /* Dispatch event to transaction. */ 820 lock_tsx(tsx, &lck); 821 (*tsx->state_handler)(tsx, &event); 822 unlock_tsx(tsx, &lck); 823 } 824 841 825 842 826 /* … … 848 832 void *event_src ) 849 833 { 850 pjsip_event e;851 852 834 PJ_LOG(4, (tsx->obj_name, "STATE %s-->%s, cause = %s", 853 835 state_str[tsx->state], state_str[state], … … 865 847 866 848 /* Inform TU */ 867 PJSIP_EVENT_INIT_TSX_STATE(e, tsx, event_src_type, event_src); 868 pjsip_endpt_send_tsx_event( tsx->endpt, &e ); 849 if (tsx->tsx_user && tsx->tsx_user->on_tsx_state) { 850 pjsip_event e; 851 PJSIP_EVENT_INIT_TSX_STATE(e, tsx, event_src_type, event_src); 852 (*tsx->tsx_user->on_tsx_state)(tsx, &e); 853 } 854 869 855 870 856 /* When the transaction is terminated, release transport, and free the … … 872 858 */ 873 859 if (state == PJSIP_TSX_STATE_TERMINATED) { 860 pj_time_val timeout = {0, 0}; 874 861 875 862 /* Decrement transport reference counter. */ 876 if (tsx->transport && 877 tsx->transport_state == PJSIP_TSX_TRANSPORT_STATE_FINAL) 878 { 863 if (tsx->transport) { 879 864 pjsip_transport_dec_ref( tsx->transport ); 880 865 tsx->transport = NULL; … … 896 881 } 897 882 898 /* If transport is not pending, reschedule timeout timer to 899 * destroy this transaction. 900 */ 901 if (tsx->transport_state == PJSIP_TSX_TRANSPORT_STATE_FINAL) { 902 pj_time_val timeout = {0, 0}; 883 /* Reschedule timeout timer to destroy this transaction. */ 884 if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) { 885 tsx->transport_flag |= TSX_HAS_PENDING_DESTROY; 886 } else { 903 887 pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer, 904 888 &timeout); 905 889 } 890 906 891 907 892 } else if (state == PJSIP_TSX_STATE_DESTROYED) { … … 915 900 lck = lck->prev; 916 901 } 917 } 918 } 919 920 /* 921 * Look-up destination address and select which transport to be used to send 922 * the request message. The procedure used here follows the guidelines on 923 * sending the request in RFC3261 chapter 8.1.2. 924 * 925 * This function also modifies the message (request line and Route headers) 926 * accordingly. 927 */ 928 static pj_status_t tsx_process_route( pjsip_transaction *tsx, 929 pjsip_tx_data *tdata, 930 pjsip_host_info *send_addr ) 931 { 932 pjsip_route_hdr *route_hdr; 933 934 pj_assert(tdata->msg->type == PJSIP_REQUEST_MSG); 935 936 /* Get the first "Route" header from the message. If the message doesn't 937 * have any "Route" headers but the endpoint has, then copy the "Route" 938 * headers from the endpoint first. 939 */ 940 route_hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE, NULL); 941 if (!route_hdr) { 942 const pjsip_route_hdr *hdr_list; 943 const pjsip_route_hdr *hdr; 944 hdr_list = (const pjsip_route_hdr*)pjsip_endpt_get_routing(tsx->endpt); 945 hdr = hdr_list->next; 946 while (hdr != hdr_list { 947 route_hdr = pjsip_hdr_shallow_clone(tdata->pool, hdr); 948 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)route_hdr); 949 hdr = hdr->next; 950 } 951 } 952 953 return pjsip_get_request_addr(tdata, send_addr); 954 } 955 956 957 /* 958 * Callback from the transport job. 959 * This callback is called when asychronous transport connect() operation 960 * has completed, with or without error. 961 */ 962 static void tsx_transport_callback(pjsip_transport *tr, 963 void *token, 964 pj_status_t status) 965 { 966 char addr[PJ_MAX_HOSTNAME]; 967 pjsip_transaction *tsx = token; 968 struct tsx_lock_data lck; 969 970 pj_memcpy(addr, tsx->dest_name.addr.host.ptr, tsx->dest_name.addr.host.slen); 971 addr[tsx->dest_name.addr.host.slen] = '\0'; 972 973 974 if (status == PJ_SUCCESS) { 975 PJ_LOG(4, (tsx->obj_name, "%s connected to %s:%d", 976 tr->type_name, 977 addr, tsx->dest_name.addr.port)); 978 } else { 979 PJ_LOG(4, (tsx->obj_name, "%s unable to connect to %s:%d, status=%d", 980 tr->type_name, 981 addr, tsx->dest_name.addr.port, status)); 982 } 983 984 /* Lock transaction. */ 985 lock_tsx(tsx, &lck); 986 987 if (status != PJ_SUCCESS) { 988 tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_FINAL; 989 tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR; 990 991 tsx_set_state(tsx, PJSIP_TSX_STATE_TERMINATED, 992 PJSIP_EVENT_TRANSPORT_ERROR, (void*)status); 993 994 /* Unlock transaction. */ 995 unlock_tsx(tsx, &lck); 996 return; 997 } 998 999 /* See if transaction has already been terminated. 1000 * If so, schedule to destroy the transaction. 1001 */ 1002 if (tsx->state == PJSIP_TSX_STATE_TERMINATED) { 1003 pj_time_val timeout = {0, 0}; 1004 pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer, 1005 &timeout); 1006 1007 /* Unlock transaction. */ 1008 unlock_tsx(tsx, &lck); 1009 return; 1010 } 1011 1012 /* Add reference counter to the transport. */ 1013 pjsip_transport_add_ref(tr); 1014 1015 /* Mark transport as ready. */ 1016 tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_FINAL; 1017 tsx->transport = tr; 1018 1019 /* If there's a pending message to send, send it now. */ 1020 if (tsx->has_unsent_msg) { 1021 tsx_send_msg( tsx, tsx->last_tx ); 1022 } 1023 1024 /* Unlock transaction. */ 1025 unlock_tsx(tsx, &lck); 1026 } 1027 1028 /* 1029 * Callback from the resolver job. 1030 */ 1031 static void tsx_resolver_callback(pj_status_t status, 1032 void *token, 1033 const struct pjsip_server_addresses *addr) 1034 { 1035 pjsip_transaction *tsx = token; 1036 struct tsx_lock_data lck; 1037 pjsip_transport *tp; 1038 1039 PJ_LOG(4, (tsx->obj_name, "resolver job complete, status=%d", status)); 1040 1041 if (status != PJ_SUCCESS || addr->count == 0) { 1042 lock_tsx(tsx, &lck); 1043 tsx->status_code = PJSIP_SC_TSX_RESOLVE_ERROR; 1044 tsx_set_state(tsx, PJSIP_TSX_STATE_TERMINATED, 1045 PJSIP_EVENT_TRANSPORT_ERROR, (void*)status); 1046 unlock_tsx(tsx, &lck); 1047 return; 1048 } 1049 1050 /* Lock transaction. */ 1051 lock_tsx(tsx, &lck); 1052 1053 /* Copy server addresses. */ 1054 pj_memcpy(&tsx->remote_addr, addr, sizeof(*addr)); 1055 1056 /* Create/find the transport for the remote address. */ 1057 tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_CONNECTING; 1058 status = pjsip_endpt_alloc_transport( tsx->endpt, addr->entry[0].type, 1059 &addr->entry[0].addr, 1060 addr->entry[0].addr_len, 1061 &tp); 1062 tsx_transport_callback(tp, tsx, status); 1063 1064 /* Unlock transaction */ 1065 unlock_tsx(tsx, &lck); 1066 1067 /* There should be nothing to do after this point. 1068 * Execution for the transaction will resume when the callback for the 1069 * transport is called. 1070 */ 1071 } 1072 1073 /* 1074 * Initialize the transaction as UAC transaction. 1075 */ 1076 PJ_DEF(pj_status_t) pjsip_tsx_init_uac( pjsip_transaction *tsx, 1077 pjsip_tx_data *tdata) 1078 { 902 903 /* Unregister transaction. */ 904 mod_tsx_layer_unregister_tsx(tsx); 905 906 /* Destroy transaction. */ 907 tsx_destroy(tsx); 908 } 909 } 910 911 912 /* 913 * Create, initialize, and register UAC transaction. 914 */ 915 PJ_DEF(pj_status_t) pjsip_tsx_create_uac( pjsip_module *tsx_user, 916 pjsip_tx_data *tdata, 917 pjsip_transaction **p_tsx) 918 { 919 pjsip_transaction *tsx; 1079 920 pjsip_msg *msg; 1080 921 pjsip_cseq_hdr *cseq; 1081 922 pjsip_via_hdr *via; 923 struct tsx_lock_data lck; 1082 924 pj_status_t status; 1083 struct tsx_lock_data lck; 1084 1085 PJ_LOG(4,(tsx->obj_name, "initializing tsx as UAC (tdata=%p)", tdata)); 925 926 PJ_ASSERT_RETURN(tdata!=NULL && p_tsx!=NULL, PJ_EINVAL); 927 928 /* Keep shortcut */ 929 msg = tdata->msg; 930 931 /* Make sure CSeq header is present. */ 932 cseq = pjsip_msg_find_hdr(msg, PJSIP_H_CSEQ, NULL); 933 if (!cseq) { 934 pj_assert(!"CSeq header not present in outgoing message!"); 935 return PJSIP_EMISSINGHDR; 936 } 937 938 939 /* Create transaction instance. */ 940 status = tsx_create( tsx_user, &tsx); 941 if (status != PJ_SUCCESS) 942 return status; 943 1086 944 1087 945 /* Lock transaction. */ 1088 946 lock_tsx(tsx, &lck); 1089 947 1090 /* Keep shortcut */1091 msg = tdata->msg;1092 1093 948 /* Role is UAC. */ 1094 949 tsx->role = PJSIP_ROLE_UAC; … … 1096 951 /* Save method. */ 1097 952 pjsip_method_copy( tsx->pool, &tsx->method, &msg->line.req.method); 953 954 /* Save CSeq. */ 955 tsx->cseq = cseq->cseq; 1098 956 1099 957 /* Generate Via header if it doesn't exist. */ … … 1104 962 } 1105 963 964 /* Generate branch parameter if it doesn't exist. */ 1106 965 if (via->branch_param.slen == 0) { 1107 966 pj_str_t tmp; … … 1116 975 /* Save branch parameter. */ 1117 976 tsx->branch = via->branch_param; 977 1118 978 } else { 1119 979 /* Copy branch parameter. */ … … 1121 981 } 1122 982 1123 1124 /* Generate transaction key. */ 1125 status = create_tsx_key_3261( tsx->pool, &tsx->transaction_key, 1126 PJSIP_ROLE_UAC, &tsx->method, 1127 &via->branch_param); 1128 if (status != PJ_SUCCESS) { 1129 unlock_tsx(tsx, &lck); 1130 return status; 1131 } 983 /* Generate transaction key. */ 984 create_tsx_key_3261( tsx->pool, &tsx->transaction_key, 985 PJSIP_ROLE_UAC, &tsx->method, 986 &via->branch_param); 1132 987 1133 988 PJ_LOG(6, (tsx->obj_name, "tsx_key=%.*s", tsx->transaction_key.slen, 1134 989 tsx->transaction_key.ptr)); 1135 1136 /* Save CSeq. */1137 cseq = pjsip_msg_find_hdr(msg, PJSIP_H_CSEQ, NULL);1138 if (!cseq) {1139 pj_assert(!"CSeq header not present in outgoing message!");1140 unlock_tsx(tsx, &lck);1141 return PJSIP_EMISSINGHDR;1142 }1143 tsx->cseq = cseq->cseq;1144 1145 990 1146 991 /* Begin with State_Null. … … 1148 993 */ 1149 994 tsx->state = PJSIP_TSX_STATE_NULL; 1150 tsx->state_handler = &pjsip_tsx_on_state_null; 1151 1152 /* Get destination name from the message. */ 1153 status = tsx_process_route(tsx, tdata, &tsx->dest_name); 1154 if (status != PJ_SUCCESS) { 1155 tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_FINAL; 1156 tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR; 1157 tsx_set_state(tsx, PJSIP_TSX_STATE_TERMINATED, 1158 PJSIP_EVENT_TRANSPORT_ERROR, (void*)status); 1159 unlock_tsx(tsx, &lck); 1160 return status; 1161 } 1162 1163 /* Resolve destination. 1164 * This will start asynchronous resolver job, and when it finishes, 1165 * the callback will be called. 1166 */ 1167 PJ_LOG(5,(tsx->obj_name, "tsx resolving destination %.*s:%d", 1168 tsx->dest_name.addr.host.slen, 1169 tsx->dest_name.addr.host.ptr, 1170 tsx->dest_name.addr.port)); 1171 1172 tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_RESOLVING; 1173 pjsip_endpt_resolve( tsx->endpt, tsx->pool, &tsx->dest_name, 1174 tsx, &tsx_resolver_callback); 1175 1176 /* There should be nothing to do after this point. 1177 * Execution for the transaction will resume when the resolver callback is 1178 * called. 1179 */ 1180 1181 /* Unlock transaction and return. 1182 * If transaction has been destroyed WITHIN the current thread, the 1183 * unlock_tsx() function will return -1. 1184 */ 1185 return unlock_tsx(tsx, &lck); 1186 } 1187 1188 1189 /* 1190 * Initialize the transaction as UAS transaction. 1191 */ 1192 PJ_DEF(pj_status_t) pjsip_tsx_init_uas( pjsip_transaction *tsx, 1193 pjsip_rx_data *rdata) 1194 { 1195 pjsip_msg *msg = rdata->msg_info.msg; 995 tsx->state_handler = &tsx_on_state_null; 996 997 /* Save the message. */ 998 tsx->last_tx = tdata; 999 pjsip_tx_data_add_ref(tsx->last_tx); 1000 1001 1002 /* Register transaction to hash table. */ 1003 mod_tsx_layer_register_tsx(tsx); 1004 1005 1006 /* Unlock transaction and return. */ 1007 unlock_tsx(tsx, &lck); 1008 1009 *p_tsx = tsx; 1010 return PJ_SUCCESS; 1011 } 1012 1013 1014 /* 1015 * Create, initialize, and register UAS transaction. 1016 */ 1017 PJ_DEF(pj_status_t) pjsip_tsx_create_uas( pjsip_module *tsx_user, 1018 pjsip_rx_data *rdata, 1019 pjsip_transaction **p_tsx) 1020 { 1021 pjsip_transaction *tsx; 1022 pjsip_msg *msg; 1196 1023 pj_str_t *branch; 1197 1024 pjsip_cseq_hdr *cseq; … … 1199 1026 struct tsx_lock_data lck; 1200 1027 1201 PJ_LOG(4,(tsx->obj_name, "initializing tsx as UAS (rdata=%p)", rdata)); 1028 PJ_ASSERT_RETURN(rdata!=NULL && p_tsx!=NULL, PJ_EINVAL); 1029 1030 /* Keep shortcut to message */ 1031 msg = rdata->msg_info.msg; 1032 1033 /* Make sure this is a request message. */ 1034 PJ_ASSERT_RETURN(msg->type == PJSIP_REQUEST_MSG, PJSIP_ENOTREQUESTMSG); 1035 1036 /* Make sure CSeq header is present. */ 1037 cseq = rdata->msg_info.cseq; 1038 if (!cseq) 1039 return PJSIP_EMISSINGHDR; 1040 1041 /* Make sure Via header is present. */ 1042 if (rdata->msg_info.via == NULL) 1043 return PJSIP_EMISSINGHDR; 1044 1045 1046 /* 1047 * Create transaction instance. 1048 */ 1049 status = tsx_create( tsx_user, &tsx); 1050 if (status != PJ_SUCCESS) 1051 return status; 1052 1202 1053 1203 1054 /* Lock transaction. */ 1204 1055 lock_tsx(tsx, &lck); 1205 1056 1206 /* Keep shortcut to message */1207 msg = rdata->msg_info.msg;1208 1209 1057 /* Role is UAS */ 1210 1058 tsx->role = PJSIP_ROLE_UAS; … … 1212 1060 /* Save method. */ 1213 1061 pjsip_method_copy( tsx->pool, &tsx->method, &msg->line.req.method); 1062 1063 /* Save CSeq */ 1064 tsx->cseq = cseq->cseq; 1214 1065 1215 1066 /* Get transaction key either from branch for RFC3261 message, or … … 1219 1070 PJSIP_ROLE_UAS, &tsx->method, rdata); 1220 1071 if (status != PJ_SUCCESS) { 1221 unlock_tsx(tsx, &lck);1072 tsx_destroy(tsx); 1222 1073 return status; 1223 1074 } … … 1230 1081 tsx->transaction_key.ptr)); 1231 1082 1232 /* Save CSeq */ 1233 cseq = rdata->msg_info.cseq; 1234 tsx->cseq = cseq->cseq; 1235 1236 /* Begin with state NULL 1083 1084 /* Begin with state TRYING. 1237 1085 * Manually set-up the state becase we don't want to call the callback. 1238 1086 */ 1239 tsx->state = PJSIP_TSX_STATE_NULL; 1240 tsx->state_handler = &pjsip_tsx_on_state_null; 1241 1242 /* Get the transport to send the response. 1243 * According to section 18.2.2 of RFC3261, if the transport is reliable 1244 * then the response must be sent using that transport. 1087 tsx->state = PJSIP_TSX_STATE_TRYING; 1088 tsx->state_handler = &tsx_on_state_trying; 1089 1090 /* Get response address. */ 1091 status = pjsip_get_response_addr( tsx->pool, rdata, &tsx->res_addr ); 1092 if (status != PJ_SUCCESS) { 1093 tsx_destroy(tsx); 1094 return status; 1095 } 1096 1097 /* If it's decided that we should use current transport, keep the 1098 * transport. 1245 1099 */ 1246 /* In addition, RFC 3581 says, if Via has "rport" parameter specified, 1247 * then return the response using the same transport. 1248 */ 1249 if (PJSIP_TRANSPORT_IS_RELIABLE(rdata->tp_info.transport) || 1250 rdata->msg_info.via->rport_param >= 0) 1251 { 1252 tsx->transport = rdata->tp_info.transport; 1100 if (tsx->res_addr.transport) { 1101 tsx->transport = tsx->res_addr.transport; 1253 1102 pjsip_transport_add_ref(tsx->transport); 1254 tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_FINAL; 1255 1256 tsx->current_addr = 0; 1257 tsx->remote_addr.count = 1; 1258 tsx->remote_addr.entry[0].type = tsx->transport->key.type; 1259 pj_memcpy(&tsx->remote_addr.entry[0].addr, 1260 &rdata->pkt_info.src_addr, rdata->pkt_info.src_addr_len); 1261 1262 } else { 1263 pj_status_t status; 1264 1265 status = pjsip_get_response_addr(tsx->pool, rdata->tp_info.transport, 1266 rdata->msg_info.via, &tsx->dest_name); 1267 if (status != PJ_SUCCESS) { 1268 tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_FINAL; 1269 tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR; 1270 tsx_set_state(tsx, PJSIP_TSX_STATE_TERMINATED, 1271 PJSIP_EVENT_TRANSPORT_ERROR, (void*)status); 1272 unlock_tsx(tsx, &lck); 1273 return status; 1274 } 1275 1276 /* Resolve destination. 1277 * This will start asynchronous resolver job, and when it finishes, 1278 * the callback will be called. 1279 */ 1280 PJ_LOG(5,(tsx->obj_name, "tsx resolving destination %.*s:%d", 1281 tsx->dest_name.addr.host.slen, 1282 tsx->dest_name.addr.host.ptr, 1283 tsx->dest_name.addr.port)); 1284 1285 tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_RESOLVING; 1286 pjsip_endpt_resolve( tsx->endpt, tsx->pool, &tsx->dest_name, 1287 tsx, &tsx_resolver_callback); 1288 } 1289 1290 /* There should be nothing to do after this point. 1291 * Execution for the transaction will resume when the resolver callback is 1292 * called. 1293 */ 1294 1295 /* Unlock transaction and return. 1296 * If transaction has been destroyed WITHIN the current thread, the 1297 * unlock_tsx() function will return -1. 1298 */ 1299 return unlock_tsx(tsx, &lck); 1300 } 1301 1302 /* 1303 * Callback when timer expires. 1304 */ 1305 static void tsx_timer_callback( pj_timer_heap_t *theap, pj_timer_entry *entry) 1306 { 1307 pjsip_event event; 1308 pjsip_transaction *tsx = entry->user_data; 1103 pj_memcpy(&tsx->addr, &tsx->res_addr.addr, tsx->res_addr.addr_len); 1104 tsx->addr_len = tsx->res_addr.addr_len; 1105 } 1106 1107 1108 /* Register the transaction. */ 1109 mod_tsx_layer_register_tsx(tsx); 1110 1111 1112 /* Unlock transaction and return. */ 1113 unlock_tsx(tsx, &lck); 1114 1115 *p_tsx = tsx; 1116 return PJ_SUCCESS; 1117 } 1118 1119 1120 /* 1121 * Forcely terminate transaction. 1122 */ 1123 PJ_DEF(pj_status_t) pjsip_tsx_terminate( pjsip_transaction *tsx, int code ) 1124 { 1309 1125 struct tsx_lock_data lck; 1310 1126 1311 PJ_UNUSED_ARG(theap); 1312 1313 PJ_LOG(5,(tsx->obj_name, "got timer event (%s timer)", 1314 (entry->id==TSX_TIMER_RETRANSMISSION ? "Retransmit" : "Timeout"))); 1315 1316 1317 if (entry->id == TSX_TIMER_RETRANSMISSION) { 1318 PJSIP_EVENT_INIT_TIMER(event, &tsx->retransmit_timer); 1319 } else { 1320 PJSIP_EVENT_INIT_TIMER(event, &tsx->timeout_timer); 1321 } 1322 1323 /* Dispatch event to transaction. */ 1127 PJ_ASSERT_RETURN(tsx != NULL, PJ_EINVAL); 1128 PJ_ASSERT_RETURN(code >= 200, PJ_EINVAL); 1129 1324 1130 lock_tsx(tsx, &lck); 1325 (*tsx->state_handler)(tsx, &event); 1131 tsx->status_code = code; 1132 tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, PJSIP_EVENT_USER, NULL); 1326 1133 unlock_tsx(tsx, &lck); 1327 } 1328 1329 /* 1330 * Transmit ACK message for 2xx/INVITE with this transaction. The ACK for 1331 * non-2xx/INVITE is automatically sent by the transaction. 1332 * This operation is only valid if the transaction is configured to handle ACK 1333 * (tsx->handle_ack is non-zero). If this attribute is not set, then the 1334 * transaction will comply with RFC-3261, i.e. it will set itself to 1335 * TERMINATED state when it receives 2xx/INVITE. 1336 */ 1337 PJ_DEF(void) pjsip_tsx_on_tx_ack( pjsip_transaction *tsx, pjsip_tx_data *tdata) 1338 { 1339 pjsip_msg *msg; 1340 pjsip_host_info dest_addr; 1341 pjsip_via_hdr *via; 1342 struct tsx_lock_data lck; 1343 pj_status_t status = PJ_SUCCESS; 1344 1345 /* Lock tsx. */ 1346 lock_tsx(tsx, &lck); 1347 1348 pj_assert(tsx->handle_ack != 0); 1349 1350 msg = tdata->msg; 1351 1352 /* Generate branch parameter if it doesn't exist. */ 1353 via = pjsip_msg_find_hdr(msg, PJSIP_H_VIA, NULL); 1354 if (via == NULL) { 1355 via = pjsip_via_hdr_create(tdata->pool); 1356 pjsip_msg_add_hdr(msg, (pjsip_hdr*) via); 1357 } 1358 1359 if (via->branch_param.slen == 0) { 1360 via->branch_param = tsx->branch; 1361 } else { 1362 pj_assert( pj_strcmp(&via->branch_param, &tsx->branch) == 0 ); 1363 } 1364 1365 /* Get destination name from the message. */ 1366 status = tsx_process_route(tsx, tdata, &dest_addr); 1367 if (status != 0){ 1368 goto on_error; 1369 } 1370 1371 /* Compare message's destination name with transaction's destination name. 1372 * If NOT equal, then we'll have to resolve the destination. 1373 */ 1374 if (dest_addr.type == tsx->dest_name.type && 1375 dest_addr.flag == tsx->dest_name.flag && 1376 dest_addr.addr.port == tsx->dest_name.addr.port && 1377 pj_stricmp(&dest_addr.addr.host, &tsx->dest_name.addr.host) == 0) 1378 { 1379 /* Equal destination. We can use current transport. */ 1380 pjsip_tsx_on_tx_msg(tsx, tdata); 1381 unlock_tsx(tsx, &lck); 1382 return; 1383 1384 } 1385 1386 /* New destination; we'll have to resolve host and create new transport. */ 1387 pj_memcpy(&tsx->dest_name, &dest_addr, sizeof(dest_addr)); 1388 pj_strdup(tsx->pool, &tsx->dest_name.addr.host, &dest_addr.addr.host); 1389 1390 PJ_LOG(5,(tsx->obj_name, "tsx resolving destination %.*s:%d", 1391 tsx->dest_name.addr.host.slen, 1392 tsx->dest_name.addr.host.ptr, 1393 tsx->dest_name.addr.port)); 1394 1395 tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_RESOLVING; 1396 pjsip_transport_dec_ref(tsx->transport); 1397 tsx->transport = NULL; 1398 1399 /* Put the message in queue. */ 1400 pjsip_tsx_on_tx_msg(tsx, tdata); 1401 1402 /* This is a bug! 1403 * We shouldn't change transaction's state before actually sending the 1404 * message. Otherwise transaction will terminate before message is sent, 1405 * and timeout timer will be scheduled. 1406 */ 1407 PJ_TODO(TSX_DONT_CHANGE_STATE_BEFORE_SENDING_ACK) 1408 1409 /* 1410 * This will start asynchronous resolver job, and when it finishes, 1411 * the callback will be called. 1412 */ 1413 1414 tsx->transport_state = PJSIP_TSX_TRANSPORT_STATE_RESOLVING; 1415 pjsip_endpt_resolve( tsx->endpt, tsx->pool, &tsx->dest_name, 1416 tsx, &tsx_resolver_callback); 1417 1418 unlock_tsx(tsx, &lck); 1419 1420 /* There should be nothing to do after this point. 1421 * Execution for the transaction will resume when the resolver callback is 1422 * called. 1423 */ 1424 return; 1425 1426 on_error: 1427 /* Failure condition. 1428 * Send TERMINATED event. 1429 */ 1430 tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR; 1431 1432 tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, 1433 PJSIP_EVENT_TRANSPORT_ERROR, (void*)status); 1434 1435 unlock_tsx(tsx, &lck); 1134 1135 return PJ_SUCCESS; 1436 1136 } 1437 1137 … … 1440 1140 * This function is called by TU to send a message. 1441 1141 */ 1442 PJ_DEF( void) pjsip_tsx_on_tx_msg( pjsip_transaction *tsx,1443 pjsip_tx_data *tdata )1142 PJ_DEF(pj_status_t) pjsip_tsx_send_msg( pjsip_transaction *tsx, 1143 pjsip_tx_data *tdata ) 1444 1144 { 1445 1145 pjsip_event event; 1446 1146 struct tsx_lock_data lck; 1447 1147 pj_status_t status; 1148 1149 if (tdata == NULL) 1150 tdata = tsx->last_tx; 1151 1152 PJ_ASSERT_RETURN(tdata != NULL, PJ_EINVALIDOP); 1448 1153 1449 1154 PJ_LOG(5,(tsx->obj_name, "Request to transmit msg on state %s (tdata=%p)", … … 1456 1161 status = (*tsx->state_handler)(tsx, &event); 1457 1162 unlock_tsx(tsx, &lck); 1458 } 1163 1164 return status; 1165 } 1166 1459 1167 1460 1168 /* … … 1462 1170 * transaction is received. 1463 1171 */ 1464 PJ_DEF(void) pjsip_tsx_on_rx_msg( pjsip_transaction *tsx, 1465 pjsip_rx_data *rdata) 1172 static void tsx_on_rx_msg( pjsip_transaction *tsx, pjsip_rx_data *rdata) 1466 1173 { 1467 1174 pjsip_event event; … … 1472 1179 state_str[tsx->state], rdata)); 1473 1180 1181 /* Put the transaction in the rdata's mod_data. */ 1182 rdata->endpt_info.mod_data[mod_tsx_layer.mod.id] = tsx; 1183 1184 /* Init event. */ 1474 1185 PJSIP_EVENT_INIT_RX_MSG(event, tsx, rdata); 1475 1186 … … 1480 1191 } 1481 1192 1482 /* 1483 * Forcely terminate transaction. 1484 */ 1485 PJ_DEF(void) pjsip_tsx_terminate( pjsip_transaction *tsx, int code ) 1486 { 1193 1194 /* Callback called by send message framework */ 1195 static void send_msg_callback( pjsip_send_state *send_state, 1196 pj_ssize_t sent, pj_bool_t *cont ) 1197 { 1198 pjsip_transaction *tsx = send_state->token; 1487 1199 struct tsx_lock_data lck; 1488 1200 1489 1201 lock_tsx(tsx, &lck); 1490 tsx->status_code = code; 1491 tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, 1492 PJSIP_EVENT_USER, NULL); 1202 1203 if (sent > 0) { 1204 /* Successfully sent! */ 1205 pj_assert(send_state->cur_transport != NULL); 1206 1207 if (tsx->transport != send_state->cur_transport) { 1208 if (tsx->transport) { 1209 pjsip_transport_dec_ref(tsx->transport); 1210 tsx->transport = NULL; 1211 } 1212 tsx->transport = send_state->cur_transport; 1213 pjsip_transport_add_ref(tsx->transport); 1214 } 1215 1216 /* Clear pending transport flag. */ 1217 tsx->transport_flag &= ~(TSX_HAS_PENDING_TRANSPORT); 1218 1219 /* Pending destroy? */ 1220 if (tsx->transport_flag & TSX_HAS_PENDING_DESTROY) { 1221 tsx_set_state( tsx, PJSIP_TSX_STATE_DESTROYED, 1222 PJSIP_EVENT_UNKNOWN, NULL ); 1223 unlock_tsx(tsx, &lck); 1224 return; 1225 } 1226 1227 /* Need to transmit a message? */ 1228 if (tsx->transport_flag & TSX_HAS_PENDING_SEND) { 1229 tsx->transport_flag &= ~(TSX_HAS_PENDING_SEND); 1230 tsx_send_msg(tsx, tsx->last_tx); 1231 } 1232 1233 /* Need to reschedule retransmission? */ 1234 if (tsx->transport_flag & TSX_HAS_PENDING_RESCHED) { 1235 tsx->transport_flag &= ~(TSX_HAS_PENDING_RESCHED); 1236 tsx_resched_retransmission(tsx); 1237 } 1238 1239 } else { 1240 /* Failed to send! */ 1241 pj_assert(sent != 0); 1242 1243 /* If transaction is using the same transport as the failed one, 1244 * release the transport. 1245 */ 1246 if (send_state->cur_transport==tsx->transport && 1247 tsx->transport != NULL) 1248 { 1249 pjsip_transport_dec_ref(tsx->transport); 1250 tsx->transport = NULL; 1251 } 1252 1253 if (!*cont) { 1254 PJ_LOG(4,(tsx->obj_name, "Failed to send message! status=%d", 1255 -sent)); 1256 1257 /* Clear pending transport flag. */ 1258 tsx->transport_flag &= ~(TSX_HAS_PENDING_TRANSPORT); 1259 1260 /* Terminate transaction. */ 1261 tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR; 1262 tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, 1263 PJSIP_EVENT_TRANSPORT_ERROR, send_state->tdata ); 1264 } 1265 } 1493 1266 1494 1267 unlock_tsx(tsx, &lck); 1495 1268 } 1496 1269 1497 /* 1498 * Transport send completion callback. 1499 */ 1500 static void tsx_on_send_complete(void *token, pjsip_tx_data *tdata, 1501 pj_ssize_t bytes_sent) 1502 { 1503 PJ_UNUSED_ARG(token); 1504 PJ_UNUSED_ARG(tdata); 1505 1506 if (bytes_sent <= 0) { 1507 PJ_TODO(HANDLE_TRANSPORT_ERROR); 1508 } 1270 1271 /* Transport callback. */ 1272 static void transport_callback(void *token, pjsip_tx_data *tdata, 1273 pj_ssize_t sent) 1274 { 1275 if (sent < 0) { 1276 pjsip_transaction *tsx = token; 1277 struct tsx_lock_data lck; 1278 1279 PJ_LOG(4,(tsx->obj_name, "Failed to send message! status=%d", 1280 -sent)); 1281 1282 lock_tsx(tsx, &lck); 1283 1284 /* Dereference transport. */ 1285 pjsip_transport_dec_ref(tsx->transport); 1286 tsx->transport = NULL; 1287 1288 /* Terminate transaction. */ 1289 tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR; 1290 tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, 1291 PJSIP_EVENT_TRANSPORT_ERROR, tdata ); 1292 1293 unlock_tsx(tsx, &lck); 1294 } 1509 1295 } 1510 1296 1511 1297 /* 1512 1298 * Send message to the transport. 1513 * If transport is not yet available, then do nothing. The message will be1514 * transmitted when transport connection completion callback is called.1515 1299 */ 1516 1300 static pj_status_t tsx_send_msg( pjsip_transaction *tsx, 1517 1301 pjsip_tx_data *tdata) 1518 1302 { 1519 pj_status_t status = PJ_SUCCESS; 1520 1521 PJ_LOG(5,(tsx->obj_name, "sending msg (tdata=%p)", tdata)); 1522 1523 if (tsx->transport_state == PJSIP_TSX_TRANSPORT_STATE_FINAL) { 1524 pjsip_event before_tx_event; 1525 1526 pj_assert(tsx->transport != NULL); 1527 1528 /* Make sure Via transport info is filled up properly for 1529 * requests. 1303 pj_status_t status = PJ_EBUG; 1304 1305 PJ_ASSERT_RETURN(tsx && tdata, PJ_EINVAL); 1306 1307 /* Send later if transport is still pending. */ 1308 if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) { 1309 tsx->transport_flag |= TSX_HAS_PENDING_SEND; 1310 return PJ_SUCCESS; 1311 } 1312 1313 if (tdata->msg->type == PJSIP_REQUEST_MSG) { 1314 /* If we have the transport, send the message using that transport. 1315 * Otherwise perform full transport resolution. 1530 1316 */ 1531 if (tdata->msg->type == PJSIP_REQUEST_MSG) { 1532 pjsip_via_hdr *via = (pjsip_via_hdr*) 1533 pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL); 1534 1535 /* For request message, set "rport" parameter by default. */ 1536 if (tdata->msg->type == PJSIP_REQUEST_MSG) 1537 via->rport_param = 0; 1538 1539 /* Don't update Via sent-by on retransmission. */ 1540 if (via->sent_by.host.slen == 0) { 1541 pj_strdup2(tdata->pool, &via->transport, 1542 tsx->transport->type_name); 1543 pj_strdup(tdata->pool, &via->sent_by.host, 1544 &tsx->transport->local_name.host); 1545 via->sent_by.port = tsx->transport->local_name.port; 1317 if (tsx->transport) { 1318 status = pjsip_transport_send( tsx->transport, tdata, &tsx->addr, 1319 tsx->addr_len, tsx, 1320 &transport_callback); 1321 if (status == PJ_EPENDING) 1322 status = PJ_SUCCESS; 1323 1324 if (status != PJ_SUCCESS) { 1325 /* On error, release transport to force using full transport 1326 * resolution procedure. 1327 */ 1328 if (tsx->transport) { 1329 pjsip_transport_dec_ref(tsx->transport); 1330 tsx->transport = NULL; 1331 } 1332 tsx->addr_len = 0; 1546 1333 } 1547 1334 } 1548 1549 /* Notify everybody we're about to send message. */ 1550 PJSIP_EVENT_INIT_PRE_TX_MSG(before_tx_event, tsx, tdata, 1551 tsx->retransmit_count); 1552 pjsip_endpt_send_tsx_event( tsx->endpt, &before_tx_event ); 1553 1554 tsx->has_unsent_msg = 0; 1555 status = pjsip_transport_send(tsx->transport, tdata, 1556 &tsx->remote_addr.entry[tsx->current_addr].addr, 1557 tsx->remote_addr.entry[tsx->current_addr].addr_len, 1558 tsx, &tsx_on_send_complete); 1559 if (status != PJ_SUCCESS && status != PJ_EPENDING) { 1560 PJ_TODO(HANDLE_TRANSPORT_ERROR); 1561 goto on_error; 1562 } 1335 1336 if (!tsx->transport) { 1337 tsx->transport_flag |= TSX_HAS_PENDING_TRANSPORT; 1338 status = pjsip_endpt_send_request_stateless(tsx->endpt, tdata, tsx, 1339 &send_msg_callback); 1340 if (status == PJ_EPENDING) 1341 status = PJ_SUCCESS; 1342 } 1343 1563 1344 } else { 1564 tsx->has_unsent_msg = 1; 1565 } 1566 1567 return 0; 1568 1569 on_error: 1570 tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR; 1571 tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, 1572 PJSIP_EVENT_TRANSPORT_ERROR, (void*)status); 1345 /* If we have the transport, send the message using that transport. 1346 * Otherwise perform full transport resolution. 1347 */ 1348 if (tsx->transport) { 1349 status = pjsip_transport_send( tsx->transport, tdata, 1350 &tsx->addr, tsx->addr_len, 1351 tsx, &transport_callback); 1352 if (status == PJ_EPENDING) 1353 status = PJ_SUCCESS; 1354 1355 if (status != PJ_SUCCESS) { 1356 if (tsx->transport) { 1357 pjsip_transport_dec_ref(tsx->transport); 1358 tsx->transport = NULL; 1359 } 1360 tsx->addr_len = 0; 1361 tsx->res_addr.transport = NULL; 1362 tsx->res_addr.addr_len = 0; 1363 } 1364 1365 } 1366 1367 if (!tsx->transport) { 1368 tsx->transport_flag |= TSX_HAS_PENDING_TRANSPORT; 1369 status = pjsip_endpt_send_response( tsx->endpt, &tsx->res_addr, 1370 tdata, tsx, 1371 &send_msg_callback); 1372 if (status == PJ_EPENDING) 1373 status = PJ_SUCCESS; 1374 } 1375 } 1376 1573 1377 return status; 1574 1378 } 1575 1379 1380 1576 1381 /* 1577 1382 * Retransmit last message sent. 1578 1383 */ 1579 static pj_status_t pjsip_tsx_retransmit( pjsip_transaction *tsx, 1580 int should_restart_timer) 1384 static void tsx_resched_retransmission( pjsip_transaction *tsx ) 1385 { 1386 pj_time_val timeout; 1387 int msec_time; 1388 1389 pj_assert((tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) == 0); 1390 1391 msec_time = (1 << (tsx->retransmit_count)) * PJSIP_T1_TIMEOUT; 1392 1393 if (msec_time>PJSIP_T2_TIMEOUT && tsx->method.id!=PJSIP_INVITE_METHOD) 1394 msec_time = PJSIP_T2_TIMEOUT; 1395 1396 timeout.sec = msec_time / 1000; 1397 timeout.msec = msec_time % 1000; 1398 pjsip_endpt_schedule_timer( tsx->endpt, &tsx->retransmit_timer, 1399 &timeout); 1400 } 1401 1402 /* 1403 * Retransmit last message sent. 1404 */ 1405 static pj_status_t tsx_retransmit( pjsip_transaction *tsx, int resched) 1581 1406 { 1582 1407 pj_status_t status; 1583 1408 1409 PJ_ASSERT_RETURN(tsx->last_tx!=NULL, PJ_EBUG); 1410 1584 1411 PJ_LOG(4,(tsx->obj_name, "retransmiting (tdata=%p, count=%d, restart?=%d)", 1585 tsx->last_tx, tsx->retransmit_count, should_restart_timer)); 1586 1587 pj_assert(tsx->last_tx != NULL); 1412 tsx->last_tx, tsx->retransmit_count, resched)); 1588 1413 1589 1414 ++tsx->retransmit_count; 1590 1415 1591 1416 status = tsx_send_msg( tsx, tsx->last_tx); 1592 if (status != PJ_SUCCESS) {1417 if (status != PJ_SUCCESS) 1593 1418 return status; 1594 }1595 1419 1596 1420 /* Restart timer T1. */ 1597 if (should_restart_timer) { 1598 pj_time_val timeout; 1599 int msec_time = (1 << (tsx->retransmit_count)) * PJSIP_T1_TIMEOUT; 1600 1601 if (tsx->method.id!=PJSIP_INVITE_METHOD && msec_time>PJSIP_T2_TIMEOUT) 1602 msec_time = PJSIP_T2_TIMEOUT; 1603 1604 timeout.sec = msec_time / 1000; 1605 timeout.msec = msec_time % 1000; 1606 pjsip_endpt_schedule_timer( tsx->endpt, &tsx->retransmit_timer, 1607 &timeout); 1421 if (resched) { 1422 if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) { 1423 tsx->transport_flag |= TSX_HAS_PENDING_RESCHED; 1424 } else { 1425 tsx_resched_retransmission(tsx); 1426 } 1608 1427 } 1609 1428 … … 1611 1430 } 1612 1431 1432 1613 1433 /* 1614 1434 * Handler for events in state Null. 1615 1435 */ 1616 static pj_status_t pjsip_tsx_on_state_null( pjsip_transaction *tsx,1617 1436 static pj_status_t tsx_on_state_null( pjsip_transaction *tsx, 1437 pjsip_event *event ) 1618 1438 { 1619 1439 pj_status_t status; 1620 1440 1621 pj_assert( tsx->state == PJSIP_TSX_STATE_NULL); 1622 pj_assert( tsx->last_tx == NULL ); 1623 pj_assert( tsx->has_unsent_msg == 0); 1441 pj_assert(tsx->state == PJSIP_TSX_STATE_NULL); 1624 1442 1625 1443 if (tsx->role == PJSIP_ROLE_UAS) { 1626 1444 1627 /* Set state to Trying. */ 1628 pj_assert(event->type == PJSIP_EVENT_RX_MSG); 1629 tsx_set_state( tsx, PJSIP_TSX_STATE_TRYING, 1630 PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata ); 1445 /* UAS doesn't have STATE_NULL. 1446 * State has moved from NULL after transaction is initialized. 1447 */ 1448 pj_assert(!"Bug bug bug!!"); 1449 return PJ_EBUG; 1631 1450 1632 1451 } else { 1633 pjsip_tx_data *tdata = event->body.tx_msg.tdata; 1452 pjsip_tx_data *tdata; 1453 1454 /* Must be transmit event. */ 1455 PJ_ASSERT_RETURN(event->type == PJSIP_EVENT_TX_MSG, PJ_EBUG); 1456 1457 /* Get the txdata */ 1458 tdata = event->body.tx_msg.tdata; 1634 1459 1635 1460 /* Save the message for retransmission. */ 1636 tsx->last_tx = tdata; 1637 pjsip_tx_data_add_ref(tdata); 1461 if (tsx->last_tx && tsx->last_tx != tdata) { 1462 pjsip_tx_data_dec_ref(tsx->last_tx); 1463 tsx->last_tx = NULL; 1464 } 1465 if (tsx->last_tx != tdata) { 1466 tsx->last_tx = tdata; 1467 pjsip_tx_data_add_ref(tdata); 1468 } 1638 1469 1639 1470 /* Send the message. */ … … 1652 1483 * transport is being used. 1653 1484 */ 1654 if (tsx->transport_state == PJSIP_TSX_TRANSPORT_STATE_FINAL && 1655 PJSIP_TRANSPORT_IS_RELIABLE(tsx->transport)==0) 1656 { 1657 pjsip_endpt_schedule_timer(tsx->endpt, &tsx->retransmit_timer, 1658 &t1_timer_val); 1485 if (!PJSIP_TRANSPORT_IS_RELIABLE(tsx->transport)) { 1659 1486 tsx->retransmit_count = 0; 1487 if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) { 1488 tsx->transport_flag |= TSX_HAS_PENDING_RESCHED; 1489 } else { 1490 pjsip_endpt_schedule_timer(tsx->endpt, &tsx->retransmit_timer, 1491 &t1_timer_val); 1492 } 1660 1493 } 1661 1494 … … 1668 1501 } 1669 1502 1503 1670 1504 /* 1671 1505 * State Calling is for UAC after it sends request but before any responses 1672 1506 * is received. 1673 1507 */ 1674 static pj_status_t pjsip_tsx_on_state_calling( pjsip_transaction *tsx,1675 1508 static pj_status_t tsx_on_state_calling( pjsip_transaction *tsx, 1509 pjsip_event *event ) 1676 1510 { 1677 1511 pj_assert(tsx->state == PJSIP_TSX_STATE_CALLING); … … 1684 1518 1685 1519 /* Retransmit the request. */ 1686 status = pjsip_tsx_retransmit( tsx, 1 );1520 status = tsx_retransmit( tsx, 1 ); 1687 1521 if (status != PJ_SUCCESS) { 1688 1522 return status; … … 1706 1540 1707 1541 /* Transaction is destroyed */ 1708 return PJSIP_ETSXDESTROYED;1542 //return PJSIP_ETSXDESTROYED; 1709 1543 1710 1544 } else if (event->type == PJSIP_EVENT_RX_MSG) { 1711 int code; 1545 pjsip_msg *msg; 1546 //int code; 1547 1548 /* Get message instance */ 1549 msg = event->body.rx_msg.rdata->msg_info.msg; 1550 1551 /* Better be a response message. */ 1552 if (msg->type != PJSIP_RESPONSE_MSG) 1553 return PJSIP_ENOTRESPONSEMSG; 1712 1554 1713 1555 /* Cancel retransmission timer A. */ … … 1723 1565 */ 1724 1566 /* Keep last_tx for authorization. */ 1725 code = event->body.rx_msg.rdata->msg_info.msg->line.status.code; 1726 if (tsx->method.id != PJSIP_INVITE_METHOD && code!=401 && code!=407) { 1727 pjsip_tx_data_dec_ref(tsx->last_tx); 1728 tsx->last_tx = NULL; 1729 } 1567 //blp: always keep last_tx until transaction is destroyed 1568 //code = msg->line.status.code; 1569 //if (tsx->method.id != PJSIP_INVITE_METHOD && code!=401 && code!=407) { 1570 // pjsip_tx_data_dec_ref(tsx->last_tx); 1571 // tsx->last_tx = NULL; 1572 //} 1730 1573 1731 1574 /* Processing is similar to state Proceeding. */ 1732 pjsip_tsx_on_state_proceeding_uac( tsx, event);1575 tsx_on_state_proceeding_uac( tsx, event); 1733 1576 1734 1577 } else { 1735 pj_assert( 0);1578 pj_assert(!"Unexpected event"); 1736 1579 return PJ_EBUG; 1737 1580 } … … 1739 1582 return PJ_SUCCESS; 1740 1583 } 1584 1741 1585 1742 1586 /* … … 1746 1590 * non-INVITE client transaction (bug in RFC?). 1747 1591 */ 1748 static pj_status_t pjsip_tsx_on_state_trying( pjsip_transaction *tsx,1749 1592 static pj_status_t tsx_on_state_trying( pjsip_transaction *tsx, 1593 pjsip_event *event) 1750 1594 { 1751 1595 pj_status_t status; … … 1762 1606 * response because we haven't sent any!). 1763 1607 */ 1764 //pj_assert(event->type == PJSIP_EVENT_TX_MSG);1765 1608 if (event->type != PJSIP_EVENT_TX_MSG) { 1766 1609 return PJ_SUCCESS; … … 1770 1613 * "Proceeding" state. 1771 1614 */ 1772 status = pjsip_tsx_on_state_proceeding_uas( tsx, event);1615 status = tsx_on_state_proceeding_uas( tsx, event); 1773 1616 1774 1617 /* Inform the TU of the state transision if state is still State_Trying */ 1775 1618 if (status==PJ_SUCCESS && tsx->state == PJSIP_TSX_STATE_TRYING) { 1619 1776 1620 tsx_set_state( tsx, PJSIP_TSX_STATE_PROCEEDING, 1777 1621 PJSIP_EVENT_TX_MSG, event->body.tx_msg.tdata); 1622 1778 1623 } 1779 1624 1780 1625 return status; 1781 1626 } 1627 1782 1628 1783 1629 /* … … 1785 1631 * This state happens after the TU sends provisional response. 1786 1632 */ 1787 static pj_status_t pjsip_tsx_on_state_proceeding_uas( pjsip_transaction *tsx,1788 1633 static pj_status_t tsx_on_state_proceeding_uas( pjsip_transaction *tsx, 1634 pjsip_event *event) 1789 1635 { 1790 1636 pj_assert(tsx->state == PJSIP_TSX_STATE_PROCEEDING || … … 1799 1645 pj_status_t status; 1800 1646 1801 /* Send last response. */ 1802 status = pjsip_tsx_retransmit( tsx, 0 ); 1803 if (status != PJ_SUCCESS) { 1804 return status; 1647 /* Must have last response sent. */ 1648 PJ_ASSERT_RETURN(tsx->last_tx != NULL, PJ_EBUG); 1649 1650 /* Send last response */ 1651 if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) { 1652 tsx->transport_flag |= TSX_HAS_PENDING_SEND; 1653 } else { 1654 status = tsx_send_msg(tsx, tsx->last_tx); 1655 if (status != PJ_SUCCESS) 1656 return status; 1805 1657 } 1806 1658 … … 1816 1668 1817 1669 /* This can only be a response message. */ 1818 pj_assert(msg->type == PJSIP_RESPONSE_MSG); 1819 1820 /* Status code must be higher than last sent. */ 1821 pj_assert(msg->line.status.code >= tsx->status_code); 1670 PJ_ASSERT_RETURN(msg->type==PJSIP_RESPONSE_MSG, PJSIP_ENOTRESPONSEMSG); 1822 1671 1823 1672 /* Update last status */ … … 1848 1697 pjsip_tx_data_add_ref( tdata ); 1849 1698 } 1699 1850 1700 tsx_set_state( tsx, PJSIP_TSX_STATE_PROCEEDING, 1851 1701 PJSIP_EVENT_TX_MSG, tdata ); … … 1853 1703 } else if (PJSIP_IS_STATUS_IN_CLASS(tsx->status_code, 200)) { 1854 1704 1855 if (tsx->method.id == PJSIP_INVITE_METHOD && tsx->handle_ ack==0) {1705 if (tsx->method.id == PJSIP_INVITE_METHOD && tsx->handle_200resp==0) { 1856 1706 1857 1707 /* 2xx class message is not saved, because retransmission … … 1862 1712 1863 1713 /* Transaction is destroyed. */ 1864 return PJSIP_ETSXDESTROYED;1714 //return PJSIP_ETSXDESTROYED; 1865 1715 1866 1716 } else { … … 1869 1719 if (tsx->method.id == PJSIP_INVITE_METHOD) { 1870 1720 tsx->retransmit_count = 0; 1871 pjsip_endpt_schedule_timer( tsx->endpt, 1872 &tsx->retransmit_timer, 1873 &t1_timer_val); 1721 if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) { 1722 tsx->transport_flag |= TSX_HAS_PENDING_RESCHED; 1723 } else { 1724 pjsip_endpt_schedule_timer( tsx->endpt, 1725 &tsx->retransmit_timer, 1726 &t1_timer_val); 1727 } 1874 1728 } 1875 1729 … … 1885 1739 * reliable transport. 1886 1740 */ 1887 if ( PJSIP_TRANSPORT_IS_RELIABLE(tsx->transport)==0) {1741 if (!PJSIP_TRANSPORT_IS_RELIABLE(tsx->transport)) { 1888 1742 timeout = timeout_timer_val; 1889 1743 } else { … … 1916 1770 * timer G will be scheduled (retransmission). 1917 1771 */ 1918 if ( PJSIP_TRANSPORT_IS_RELIABLE(tsx->transport)==0) {1772 if (!PJSIP_TRANSPORT_IS_RELIABLE(tsx->transport)) { 1919 1773 pjsip_cseq_hdr *cseq = pjsip_msg_find_hdr( msg, PJSIP_H_CSEQ, 1920 1774 NULL); 1921 1775 if (cseq->method.id == PJSIP_INVITE_METHOD) { 1922 1776 tsx->retransmit_count = 0; 1923 pjsip_endpt_schedule_timer(tsx->endpt, 1924 &tsx->retransmit_timer, 1925 &t1_timer_val); 1777 if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) { 1778 tsx->transport_flag |= TSX_HAS_PENDING_RESCHED; 1779 } else { 1780 pjsip_endpt_schedule_timer(tsx->endpt, 1781 &tsx->retransmit_timer, 1782 &t1_timer_val); 1783 } 1926 1784 } 1927 1785 } … … 1938 1796 } else if (event->type == PJSIP_EVENT_TIMER && 1939 1797 event->body.timer.entry == &tsx->retransmit_timer) { 1798 1940 1799 /* Retransmission timer elapsed. */ 1941 1800 pj_status_t status; 1942 1801 1802 /* Must not be triggered while transport is pending. */ 1803 pj_assert((tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) == 0); 1804 1943 1805 /* Must have last response to retransmit. */ 1944 1806 pj_assert(tsx->last_tx != NULL); 1945 1807 1946 1808 /* Retransmit the last response. */ 1947 status = pjsip_tsx_retransmit( tsx, 1 );1809 status = tsx_retransmit( tsx, 1 ); 1948 1810 if (status != PJ_SUCCESS) { 1949 1811 return status; … … 1954 1816 1955 1817 /* Timeout timer. should not happen? */ 1956 pj_assert( 0);1818 pj_assert(!"Should not happen(?)"); 1957 1819 1958 1820 tsx->status_code = PJSIP_SC_TSX_TIMEOUT; … … 1964 1826 1965 1827 } else { 1966 pj_assert( 0);1828 pj_assert(!"Unexpected event"); 1967 1829 return PJ_EBUG; 1968 1830 } … … 1970 1832 return PJ_SUCCESS; 1971 1833 } 1834 1972 1835 1973 1836 /* … … 1976 1839 * UAS. 1977 1840 */ 1978 static pj_status_t pjsip_tsx_on_state_proceeding_uac(pjsip_transaction *tsx,1979 1841 static pj_status_t tsx_on_state_proceeding_uac(pjsip_transaction *tsx, 1842 pjsip_event *event) 1980 1843 { 1981 1844 … … 1984 1847 1985 1848 if (event->type != PJSIP_EVENT_TIMER) { 1849 pjsip_msg *msg; 1850 1986 1851 /* Must be incoming response, because we should not retransmit 1987 1852 * request once response has been received. … … 1992 1857 } 1993 1858 1994 tsx->status_code = event->body.rx_msg.rdata->msg_info.msg->line.status.code; 1859 msg = event->body.rx_msg.rdata->msg_info.msg; 1860 1861 /* Must be a response message. */ 1862 if (msg->type != PJSIP_RESPONSE_MSG) { 1863 pj_assert(!"Expecting response message!"); 1864 return PJSIP_ENOTRESPONSEMSG; 1865 } 1866 1867 tsx->status_code = msg->line.status.code; 1995 1868 } else { 1996 1869 tsx->status_code = PJSIP_SC_TSX_TIMEOUT; … … 2011 1884 * handled in TU). For non-INVITE, state moves to Completed. 2012 1885 */ 2013 if (tsx->method.id == PJSIP_INVITE_METHOD && tsx->handle_ack == 0) {1886 if (tsx->method.id == PJSIP_INVITE_METHOD) { 2014 1887 tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, 2015 1888 PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata ); 2016 return PJSIP_ETSXDESTROYED;1889 //return PJSIP_ETSXDESTROYED; 2017 1890 2018 1891 } else { … … 2047 1920 /* Generate and send ACK for INVITE. */ 2048 1921 if (tsx->method.id == PJSIP_INVITE_METHOD) { 2049 pjsip_endpt_create_ack( tsx->endpt, tsx->last_tx, 2050 event->body.rx_msg.rdata ); 1922 pjsip_tx_data *ack; 1923 1924 status = pjsip_endpt_create_ack( tsx->endpt, tsx->last_tx, 1925 event->body.rx_msg.rdata, 1926 &ack); 1927 if (status != PJ_SUCCESS) 1928 return status; 1929 1930 if (ack != tsx->last_tx) { 1931 pjsip_tx_data_dec_ref(tsx->last_tx); 1932 tsx->last_tx = ack; 1933 } 1934 2051 1935 status = tsx_send_msg( tsx, tsx->last_tx); 2052 1936 if (status != PJ_SUCCESS) { … … 2056 1940 2057 1941 /* Start Timer D with TD/T4 timer if unreliable transport is used. */ 2058 if ( PJSIP_TRANSPORT_IS_RELIABLE(tsx->transport) == 0) {1942 if (!PJSIP_TRANSPORT_IS_RELIABLE(tsx->transport)) { 2059 1943 if (tsx->method.id == PJSIP_INVITE_METHOD) { 2060 1944 timeout = td_timer_val; … … 2073 1957 } else { 2074 1958 // Shouldn't happen because there's no timer for this state. 2075 pj_assert( 0);1959 pj_assert(!"Unexpected event"); 2076 1960 return PJ_EBUG; 2077 1961 } … … 2080 1964 } 2081 1965 1966 2082 1967 /* 2083 1968 * Handler for events in Completed state for UAS 2084 1969 */ 2085 static pj_status_t pjsip_tsx_on_state_completed_uas( pjsip_transaction *tsx,2086 1970 static pj_status_t tsx_on_state_completed_uas( pjsip_transaction *tsx, 1971 pjsip_event *event) 2087 1972 { 2088 1973 pj_assert(tsx->state == PJSIP_TSX_STATE_COMPLETED); … … 2090 1975 if (event->type == PJSIP_EVENT_RX_MSG) { 2091 1976 pjsip_msg *msg = event->body.rx_msg.rdata->msg_info.msg; 2092 pjsip_cseq_hdr *cseq = pjsip_msg_find_hdr( msg, PJSIP_H_CSEQ, NULL ); 1977 1978 /* This must be a request message retransmission. */ 1979 if (msg->type != PJSIP_REQUEST_MSG) 1980 return PJSIP_ENOTREQUESTMSG; 2093 1981 2094 1982 /* On receive request retransmission, retransmit last response. */ 2095 if ( cseq->method.id != PJSIP_ACK_METHOD) {1983 if (msg->line.req.method.id != PJSIP_ACK_METHOD) { 2096 1984 pj_status_t status; 2097 1985 2098 status = pjsip_tsx_retransmit( tsx, 0 );1986 status = tsx_retransmit( tsx, 0 ); 2099 1987 if (status != PJ_SUCCESS) { 2100 1988 return status; … … 2123 2011 pj_status_t status; 2124 2012 2125 status = pjsip_tsx_retransmit( tsx, 1 );2013 status = tsx_retransmit( tsx, 1 ); 2126 2014 if (status != PJ_SUCCESS) { 2127 2015 return status; … … 2140 2028 PJSIP_EVENT_TIMER, &tsx->timeout_timer ); 2141 2029 2142 return PJSIP_ETSXDESTROYED;2030 //return PJSIP_ETSXDESTROYED; 2143 2031 2144 2032 } else { … … 2146 2034 tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, 2147 2035 PJSIP_EVENT_TIMER, &tsx->timeout_timer ); 2148 return PJSIP_ETSXDESTROYED;2036 //return PJSIP_ETSXDESTROYED; 2149 2037 } 2150 2038 } … … 2152 2040 } else { 2153 2041 /* Ignore request to transmit. */ 2154 pj_assert(event->body.tx_msg.tdata == tsx->last_tx); 2042 PJ_ASSERT_RETURN(event->type == PJSIP_EVENT_TX_MSG && 2043 event->body.tx_msg.tdata == tsx->last_tx, 2044 PJ_EINVALIDOP); 2155 2045 } 2156 2046 … … 2158 2048 } 2159 2049 2050 2160 2051 /* 2161 2052 * Handler for events in Completed state for UAC transaction. 2162 2053 */ 2163 static pj_status_t pjsip_tsx_on_state_completed_uac( pjsip_transaction *tsx,2164 2054 static pj_status_t tsx_on_state_completed_uac( pjsip_transaction *tsx, 2055 pjsip_event *event) 2165 2056 { 2166 2057 pj_assert(tsx->state == PJSIP_TSX_STATE_COMPLETED); … … 2175 2066 2176 2067 /* Transaction has been destroyed. */ 2177 return PJSIP_ETSXDESTROYED;2068 //return PJSIP_ETSXDESTROYED; 2178 2069 2179 2070 } else if (event->type == PJSIP_EVENT_RX_MSG) { … … 2189 2080 pj_status_t status; 2190 2081 2191 status = pjsip_tsx_retransmit( tsx, 0 );2082 status = tsx_retransmit( tsx, 0 ); 2192 2083 if (status != PJ_SUCCESS) { 2193 2084 return status; … … 2200 2091 /* Just drop the response. */ 2201 2092 } 2202 } else if (tsx->method.id == PJSIP_INVITE_METHOD &&2203 event->type == PJSIP_EVENT_TX_MSG &&2204 event->body.tx_msg.tdata->msg->line.req.method.id==PJSIP_ACK_METHOD) {2205 2206 pj_status_t status;2207 2208 /* Set last transmitted message. */2209 if (tsx->last_tx != event->body.tx_msg.tdata) {2210 pjsip_tx_data_dec_ref( tsx->last_tx );2211 tsx->last_tx = event->body.tx_msg.tdata;2212 pjsip_tx_data_add_ref( tsx->last_tx );2213 }2214 2215 /* No state changed, but notify app.2216 * Must notify now, so app has chance to put SDP in outgoing ACK msg.2217 */2218 tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED,2219 PJSIP_EVENT_TX_MSG, event->body.tx_msg.tdata );2220 2221 /* Send msg */2222 status = tsx_send_msg(tsx, event->body.tx_msg.tdata);2223 if (status != PJ_SUCCESS)2224 return status;2225 2093 2226 2094 } else { 2227 pj_assert( 0);2228 return PJ_E BUG;2095 pj_assert(!"Unexpected event"); 2096 return PJ_EINVALIDOP; 2229 2097 } 2230 2098 … … 2232 2100 } 2233 2101 2102 2234 2103 /* 2235 2104 * Handler for events in state Confirmed. 2236 2105 */ 2237 static pj_status_t pjsip_tsx_on_state_confirmed( pjsip_transaction *tsx,2238 2106 static pj_status_t tsx_on_state_confirmed( pjsip_transaction *tsx, 2107 pjsip_event *event) 2239 2108 { 2240 2109 pj_assert(tsx->state == PJSIP_TSX_STATE_CONFIRMED); … … 2247 2116 if (event->type == PJSIP_EVENT_RX_MSG) { 2248 2117 2249 pjsip_method_e method_id = 2250 event->body.rx_msg.rdata->msg_info.msg->line.req.method.id; 2251 2252 /* Must be a request message. */2253 pj_assert(event->body.rx_msg.rdata->msg_info.msg->type == PJSIP_REQUEST_MSG);2118 pjsip_msg *msg = event->body.rx_msg.rdata->msg_info.msg; 2119 2120 /* Only expecting request message. */ 2121 if (msg->type != PJSIP_REQUEST_MSG) 2122 return PJSIP_ENOTREQUESTMSG; 2254 2123 2255 2124 /* Must be an ACK request or a late INVITE retransmission. */ 2256 pj_assert(method_id == PJSIP_ACK_METHOD || 2257 method_id == PJSIP_INVITE_METHOD); 2258 2259 /* Just so that compiler won't complain about unused vars when 2260 * building release code. 2261 */ 2262 PJ_UNUSED_ARG(method_id); 2125 pj_assert(msg->line.req.method.id == PJSIP_ACK_METHOD || 2126 msg->line.req.method.id == PJSIP_INVITE_METHOD); 2263 2127 2264 2128 } else if (event->type == PJSIP_EVENT_TIMER) { … … 2271 2135 2272 2136 /* Transaction has been destroyed. */ 2273 return PJSIP_ETSXDESTROYED;2137 //return PJSIP_ETSXDESTROYED; 2274 2138 2275 2139 } else { 2276 pj_assert( 0);2140 pj_assert(!"Unexpected event"); 2277 2141 return PJ_EBUG; 2278 2142 } … … 2281 2145 } 2282 2146 2147 2283 2148 /* 2284 2149 * Handler for events in state Terminated. 2285 2150 */ 2286 static pj_status_t pjsip_tsx_on_state_terminated( pjsip_transaction *tsx,2287 2151 static pj_status_t tsx_on_state_terminated( pjsip_transaction *tsx, 2152 pjsip_event *event) 2288 2153 { 2289 2154 pj_assert(tsx->state == PJSIP_TSX_STATE_TERMINATED); 2290 2291 PJ_UNUSED_ARG(event); 2155 pj_assert(event->type == PJSIP_EVENT_TIMER); 2292 2156 2293 2157 /* Destroy this transaction */ … … 2299 2163 2300 2164 2301 static pj_status_t pjsip_tsx_on_state_destroyed(pjsip_transaction *tsx, 2302 pjsip_event *event) 2165 /* 2166 * Handler for events in state Destroyed. 2167 * Shouldn't happen! 2168 */ 2169 static pj_status_t tsx_on_state_destroyed(pjsip_transaction *tsx, 2170 pjsip_event *event) 2303 2171 { 2304 2172 PJ_UNUSED_ARG(tsx); 2305 2173 PJ_UNUSED_ARG(event); 2306 return PJ_SUCCESS; 2307 } 2308 2174 pj_assert(!"Not expecting any events!!"); 2175 return PJ_EBUG; 2176 } 2177 -
pjproject/trunk/pjsip/src/pjsip/sip_transport.c
r106 r107 71 71 { PJSIP_TRANSPORT_TCP, 5060, {"TCP", 3}, PJSIP_TRANSPORT_RELIABLE}, 72 72 { PJSIP_TRANSPORT_TLS, 5061, {"TLS", 3}, PJSIP_TRANSPORT_RELIABLE | PJSIP_TRANSPORT_SECURE}, 73 { PJSIP_TRANSPORT_SCTP, 5060, {"SCTP", 4}, PJSIP_TRANSPORT_RELIABLE} 73 { PJSIP_TRANSPORT_SCTP, 5060, {"SCTP", 4}, PJSIP_TRANSPORT_RELIABLE}, 74 { PJSIP_TRANSPORT_LOOP, 15060, {"LOOP", 4}, PJSIP_TRANSPORT_RELIABLE}, 75 { PJSIP_TRANSPORT_LOOP_DGRAM, 15060, {"LOOP-DGRAM", 10}, PJSIP_TRANSPORT_DATAGRAM}, 74 76 }; 75 77 … … 195 197 status = pj_atomic_create(tdata->pool, 0, &tdata->ref_cnt); 196 198 if (status != PJ_SUCCESS) { 197 pjsip_endpt_ destroy_pool( mgr->endpt, tdata->pool );199 pjsip_endpt_release_pool( mgr->endpt, tdata->pool ); 198 200 return status; 199 201 } … … 202 204 status = pj_lock_create_null_mutex(pool, "tdta%p", &tdata->lock); 203 205 if (status != PJ_SUCCESS) { 204 pjsip_endpt_ destroy_pool( mgr->endpt, tdata->pool );206 pjsip_endpt_release_pool( mgr->endpt, tdata->pool ); 205 207 return status; 206 208 } … … 239 241 pj_atomic_destroy( tdata->ref_cnt ); 240 242 pj_lock_destroy( tdata->lock ); 241 pjsip_endpt_ destroy_pool( tdata->mgr->endpt, tdata->pool );243 pjsip_endpt_release_pool( tdata->mgr->endpt, tdata->pool ); 242 244 return PJSIP_EBUFDESTROYED; 243 245 } else { … … 716 718 } 717 719 718 /* If message is received from address that's different from sent-by, 719 * MUST add received parameter to the via. 720 */ 721 if (pj_strcmp2(&rdata->msg_info.via->sent_by.host, 722 rdata->pkt_info.src_name) != 0) 723 { 724 pj_strdup2(rdata->tp_info.pool, 725 &rdata->msg_info.via->recvd_param, 726 rdata->pkt_info.src_name); 727 } 720 /* Always add received parameter to the via. */ 721 pj_strdup2(rdata->tp_info.pool, 722 &rdata->msg_info.via->recvd_param, 723 rdata->pkt_info.src_name); 728 724 729 725 /* RFC 3581: -
pjproject/trunk/pjsip/src/pjsip/sip_transport_udp.c
- Property svn:keywords set to Id
r106 r107 1 /* $Id :$ */1 /* $Id$ */ 2 2 /* 3 3 * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org> … … 193 193 struct udp_transport *tp = (struct udp_transport*)transport; 194 194 pj_ssize_t size; 195 pj_status_t status; 195 196 196 197 PJ_ASSERT_RETURN(transport && tdata, PJ_EINVAL); … … 204 205 /* Send to ioqueue! */ 205 206 size = tdata->buf.cur - tdata->buf.start; 206 return pj_ioqueue_sendto(tp->key, (pj_ioqueue_op_key_t*)&tdata->op_key, 207 tdata->buf.start, &size, 0, 208 rem_addr, addr_len); 207 status = pj_ioqueue_sendto(tp->key, (pj_ioqueue_op_key_t*)&tdata->op_key, 208 tdata->buf.start, &size, 0, 209 rem_addr, addr_len); 210 211 if (status != PJ_EPENDING) 212 tdata->op_key.tdata = NULL; 213 214 return status; 209 215 } 210 216 … … 245 251 246 252 /* Destroy pool. */ 247 pjsip_endpt_ destroy_pool(tp->base.endpt, tp->base.pool);253 pjsip_endpt_release_pool(tp->base.endpt, tp->base.pool); 248 254 249 255 return PJ_SUCCESS; … … 420 426 421 427 /* Done. */ 422 *p_transport = &tp->base; 428 if (p_transport) 429 *p_transport = &tp->base; 423 430 return PJ_SUCCESS; 424 431 -
pjproject/trunk/pjsip/src/pjsip/sip_util.c
r106 r107 177 177 target = pjsip_parse_uri( tdata->pool, tmp.ptr, tmp.slen, 0); 178 178 if (target == NULL) { 179 PJ_LOG(4,(THIS_FILE, "Error creating request: invalid target %s", 180 tmp.ptr)); 179 status = PJSIP_EINVALIDREQURI; 181 180 goto on_error; 182 181 } … … 188 187 PJSIP_PARSE_URI_AS_NAMEADDR); 189 188 if (from->uri == NULL) { 190 PJ_LOG(4,(THIS_FILE, "Error creating request: invalid 'From' URI '%s'", 191 tmp.ptr)); 189 status = PJSIP_EINVALIDHDR; 192 190 goto on_error; 193 191 } … … 200 198 PJSIP_PARSE_URI_AS_NAMEADDR); 201 199 if (to->uri == NULL) { 202 PJ_LOG(4,(THIS_FILE, "Error creating request: invalid 'To' URI '%s'", 203 tmp.ptr)); 200 status = PJSIP_EINVALIDHDR; 204 201 goto on_error; 205 202 } … … 212 209 PJSIP_PARSE_URI_AS_NAMEADDR); 213 210 if (contact->uri == NULL) { 214 PJ_LOG(4,(THIS_FILE, 215 "Error creating request: invalid 'Contact' URI '%s'", 216 tmp.ptr)); 211 status = PJSIP_EINVALIDHDR; 217 212 goto on_error; 218 213 } … … 1170 1165 return PJ_SUCCESS; 1171 1166 } else { 1172 send_response_transport_cb(send_state, tdata, -status);1167 pjsip_transport_dec_ref(send_state->cur_transport); 1173 1168 return status; 1174 1169 } … … 1180 1175 } 1181 1176 1177 /* 1178 * Send response 1179 */ 1180 PJ_DEF(pj_status_t) pjsip_endpt_respond_stateless( pjsip_endpoint *endpt, 1181 pjsip_rx_data *rdata, 1182 int st_code, 1183 const pj_str_t *st_text, 1184 const pjsip_hdr *hdr_list, 1185 const pjsip_msg_body *body) 1186 { 1187 pj_status_t status; 1188 pjsip_response_addr res_addr; 1189 pjsip_tx_data *tdata; 1190 1191 /* Create response message */ 1192 status = pjsip_endpt_create_response( endpt, rdata, st_code, st_text, 1193 &tdata); 1194 if (status != PJ_SUCCESS) 1195 return status; 1196 1197 /* Add the message headers, if any */ 1198 if (hdr_list) { 1199 const pjsip_hdr *hdr = hdr_list->next; 1200 while (hdr != hdr_list) { 1201 pjsip_msg_add_hdr( tdata->msg, pjsip_hdr_clone(tdata->pool, hdr) ); 1202 hdr = hdr->next; 1203 } 1204 } 1205 1206 /* Add the message body, if any. */ 1207 if (body) { 1208 tdata->msg->body = pj_pool_alloc(tdata->pool, sizeof(pjsip_msg_body)); 1209 status = pjsip_msg_body_clone( tdata->pool, tdata->msg->body, body ); 1210 if (status != PJ_SUCCESS) { 1211 pjsip_tx_data_dec_ref(tdata); 1212 return status; 1213 } 1214 } 1215 1216 /* Get where to send request. */ 1217 status = pjsip_get_response_addr( tdata->pool, rdata, &res_addr ); 1218 if (status != PJ_SUCCESS) { 1219 pjsip_tx_data_dec_ref(tdata); 1220 return status; 1221 } 1222 1223 /* Send! */ 1224 status = pjsip_endpt_send_response( endpt, &res_addr, tdata, NULL, NULL ); 1225 1226 return status; 1227 } 1182 1228 1183 1229 /* -
pjproject/trunk/pjsip/src/pjsip/sip_util_statefull.c
- Property svn:keywords changed from "Id Revision" to Id
-
pjproject/trunk/pjsip/src/test-pjsip/msg_test.c
r106 r107 48 48 /* 'Normal' message with all headers. */ 49 49 "INVITE sip:user@foo SIP/2.0\n" 50 "From: Hi I'm Joe <sip:joe.user@bar.otherdomain.com>;tag=123457890123456 7890\r"50 "From: Hi I'm Joe <sip:joe.user@bar.otherdomain.com>;tag=123457890123456\r" 51 51 "To: Fellow User <sip:user@foo.bar.domain.com>\r\n" 52 52 "Call-ID: 12345678901234567890@bar\r\n" … … 58 58 "Route: <sip:bigbox3.site3.atlanta.com;lr>,\r\n" 59 59 " <sip:server10.biloxi.com;lr>\r" 60 "Record-Route: <sip:server10.biloxi.com>,\r\n" 60 "Record-Route: <sip:server10.biloxi.com>,\r\n" /* multiple routes+folding*/ 61 61 " <sip:bigbox3.site3.atlanta.com;lr>\n" 62 "Via: SIP/2.0/SCTP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c23 12983.1\n"63 "Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8\n" 62 "Via: SIP/2.0/SCTP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c230\n" 63 "Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8\n" /* folding. */ 64 64 " ;received=192.0.2.1\r\n" 65 65 "Via: SIP/2.0/UDP 10.2.1.1, SIP/2.0/TCP 192.168.1.1\n" 66 66 "Organization: \r" 67 67 "Max-Forwards: 70\n" 68 "X-Header: \r\n" 68 "X-Header: \r\n" /* empty header */ 69 "P-Associated-URI:\r\n" /* empty header without space */ 69 70 "\r\n", 70 71 &create_msg0, … … 352 353 pj_strdup2(pool, &url->host, "foo"); 353 354 354 /* "From: Hi I'm Joe <sip:joe.user@bar.otherdomain.com>;tag=123457890123456 7890\r" */355 /* "From: Hi I'm Joe <sip:joe.user@bar.otherdomain.com>;tag=123457890123456\r" */ 355 356 fromto = pjsip_from_hdr_create(pool); 356 357 pjsip_msg_add_hdr(msg, (pjsip_hdr*)fromto); 357 pj_strdup2(pool, &fromto->tag, "123457890123456 7890");358 pj_strdup2(pool, &fromto->tag, "123457890123456"); 358 359 name_addr = pjsip_name_addr_create(pool); 359 360 fromto->uri = (pjsip_uri*)name_addr; … … 463 464 url->lr_param = 1; 464 465 465 /* "Via: SIP/2.0/SCTP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c23 12983.1\n" */466 /* "Via: SIP/2.0/SCTP bigbox3.site3.atlanta.com;branch=z9hG4bK77ef4c230\n" */ 466 467 via = pjsip_via_hdr_create(pool); 467 468 pjsip_msg_add_hdr(msg, (pjsip_hdr*)via); 468 469 pj_strdup2(pool, &via->transport, "SCTP"); 469 470 pj_strdup2(pool, &via->sent_by.host, "bigbox3.site3.atlanta.com"); 470 pj_strdup2(pool, &via->branch_param, "z9hG4bK77ef4c23 12983.1");471 pj_strdup2(pool, &via->branch_param, "z9hG4bK77ef4c230"); 471 472 472 473 /* "Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8\n" … … 513 514 str.ptr = "X-Header"; 514 515 str.slen = 8; 516 generic = pjsip_generic_string_hdr_create(pool, &str); 517 pjsip_msg_add_hdr(msg, (pjsip_hdr*)generic); 518 str.ptr = NULL; 519 str.slen = 0; 520 generic->hvalue = str; 521 522 /* P-Associated-URI:\r\n */ 523 str.ptr = "P-Associated-URI"; 524 str.slen = 16; 515 525 generic = pjsip_generic_string_hdr_create(pool, &str); 516 526 pjsip_msg_add_hdr(msg, (pjsip_hdr*)generic); … … 678 688 pool = pjsip_endpt_create_pool(endpt, NULL, POOL_SIZE, POOL_SIZE); 679 689 status = test_entry( pool, &test_array[i] ); 680 pjsip_endpt_ destroy_pool(endpt, pool);690 pjsip_endpt_release_pool(endpt, pool); 681 691 682 692 if (status != PJ_SUCCESS) … … 692 702 pool = pjsip_endpt_create_pool(endpt, NULL, POOL_SIZE, POOL_SIZE); 693 703 status = test_entry( pool, &test_array[i] ); 694 pjsip_endpt_ destroy_pool(endpt, pool);704 pjsip_endpt_release_pool(endpt, pool); 695 705 696 706 if (status != PJ_SUCCESS) -
pjproject/trunk/pjsip/src/test-pjsip/test.c
r106 r107 82 82 PJ_LOG(3,("","")); 83 83 84 DO_TEST(uri_test()); 85 DO_TEST(msg_test()); 86 DO_TEST(txdata_test()); 87 DO_TEST(transport_udp_test()); 84 //DO_TEST(uri_test()); 85 //DO_TEST(msg_test()); 86 //DO_TEST(txdata_test()); 87 //DO_TEST(transport_udp_test()); 88 DO_TEST(transport_loop_test()); 89 //DO_TEST(tsx_uac_test()); 88 90 89 91 on_return: -
pjproject/trunk/pjsip/src/test-pjsip/test.h
r106 r107 24 24 extern pjsip_endpoint *endpt; 25 25 26 #define TEST_UDP_PORT 15060 26 #define TEST_UDP_PORT 15060 27 #define TEST_UDP_PORT_STR "15060" 27 28 28 29 /* The tests */ … … 31 32 int txdata_test(void); 32 33 int transport_udp_test(void); 34 int transport_loop_test(void); 35 int tsx_uac_test(void); 33 36 34 37 /* Transport test helpers (transport_test.c). */ … … 36 39 int transport_send_recv_test( pjsip_transport_type_e tp_type, 37 40 pjsip_transport *ref_tp, 38 c onst pj_sockaddr_in *rem_addr);41 char *target_url ); 39 42 int transport_rt_test( pjsip_transport_type_e tp_type, 40 43 pjsip_transport *ref_tp, 41 c onst pj_sockaddr_in *rem_addr);44 char *target_url ); 42 45 43 46 /* Test main entry */ -
pjproject/trunk/pjsip/src/test-pjsip/transport_test.c
- Property svn:keywords changed from "Id Revision" to Id
r106 r107 76 76 */ 77 77 #define FROM_HDR "Bob <sip:bob@example.com>" 78 #define TO_HDR "Alice <sip:alice@example.com>"79 78 #define CONTACT_HDR "Bob <sip:bob@127.0.0.1>" 80 79 #define CALL_ID_HDR "SendRecv-Test" … … 109 108 &my_on_rx_request, /* on_rx_request() */ 110 109 &my_on_rx_response, /* on_rx_response() */ 111 NULL, /* tsx_handler() */110 NULL, /* on_tsx_state() */ 112 111 }; 113 112 … … 189 188 int transport_send_recv_test( pjsip_transport_type_e tp_type, 190 189 pjsip_transport *ref_tp, 191 c onst pj_sockaddr_in *rem_addr)190 char *target_url ) 192 191 { 193 192 pj_status_t status; 194 char target_buf[80];195 193 pj_str_t target, from, to, contact, call_id, body; 196 194 pjsip_method method; … … 210 208 211 209 /* Create a request message. */ 212 pj_sprintf(target_buf, "sip:%s:%d", pj_inet_ntoa(rem_addr->sin_addr), 213 pj_ntohs(rem_addr->sin_port)); 214 target = pj_str(target_buf); 210 target = pj_str(target_url); 215 211 from = pj_str(FROM_HDR); 216 to = pj_str( TO_HDR);212 to = pj_str(target_url); 217 213 contact = pj_str(CONTACT_HDR); 218 214 call_id = pj_str(CALL_ID_HDR); … … 334 330 } rt_test_data[16]; 335 331 336 static char rt_target_uri[ 32];332 static char rt_target_uri[64]; 337 333 static pj_bool_t rt_stop; 338 334 static pj_str_t rt_call_id; … … 350 346 status = pjsip_endpt_create_response( endpt, rdata, 200, NULL, &tdata); 351 347 if (status != PJ_SUCCESS) { 348 app_perror(" error creating response", status); 352 349 return PJ_TRUE; 353 350 } 354 351 status = pjsip_get_response_addr( tdata->pool, rdata, &res_addr); 355 352 if (status != PJ_SUCCESS) { 353 app_perror(" error in get response address", status); 356 354 pjsip_tx_data_dec_ref(tdata); 357 355 return PJ_TRUE; … … 359 357 status = pjsip_endpt_send_response( endpt, &res_addr, tdata, NULL, NULL); 360 358 if (status != PJ_SUCCESS) { 359 app_perror(" error sending response", status); 361 360 pjsip_tx_data_dec_ref(tdata); 362 361 return PJ_TRUE; … … 377 376 target = pj_str(rt_target_uri); 378 377 from = pj_str(FROM_HDR); 379 to = pj_str( TO_HDR);378 to = pj_str(rt_target_uri); 380 379 contact = pj_str(CONTACT_HDR); 381 380 call_id = rt_test_data[thread_id].call_id; … … 431 430 static int rt_thread(void *arg) 432 431 { 433 int thread_id = (int)arg;432 int i, thread_id = (int)arg; 434 433 pj_time_val poll_delay = { 0, 10 }; 435 434 … … 444 443 pjsip_endpt_handle_events(endpt, &poll_delay); 445 444 } 445 446 /* Exhaust responses. */ 447 for (i=0; i<100; ++i) 448 pjsip_endpt_handle_events(endpt, &poll_delay); 449 446 450 return 0; 447 451 } … … 449 453 int transport_rt_test( pjsip_transport_type_e tp_type, 450 454 pjsip_transport *ref_tp, 451 c onst pj_sockaddr_in *rem_addr)455 char *target_url ) 452 456 { 453 457 enum { THREADS = 4, INTERVAL = 10 }; … … 484 488 485 489 /* Initialize static test data. */ 486 pj_sprintf(rt_target_uri, "sip:%s:%d", pj_inet_ntoa(rem_addr->sin_addr), 487 pj_ntohs(rem_addr->sin_port)); 490 pj_native_strcpy(rt_target_uri, target_url); 488 491 rt_call_id = pj_str("RT-Call-Id/"); 489 492 rt_stop = PJ_FALSE; … … 552 555 PJ_LOG(3,("", " average round-trip=%d usec", usec_rt)); 553 556 554 pjsip_endpt_ destroy_pool(endpt, pool);557 pjsip_endpt_release_pool(endpt, pool); 555 558 556 559 if (is_reliable && (total_sent != total_recv)) { -
pjproject/trunk/pjsip/src/test-pjsip/transport_udp_test.c
- Property svn:keywords changed from "Id Revision" to Id
r106 r107 77 77 pj_sockaddr_in_init(&rem_addr, pj_cstr(&s, "127.0.0.1"), TEST_UDP_PORT); 78 78 for (i=0; i<SEND_RECV_LOOP; ++i) { 79 status = transport_send_recv_test(PJSIP_TRANSPORT_UDP, tp, &rem_addr); 79 status = transport_send_recv_test(PJSIP_TRANSPORT_UDP, tp, 80 "sip:alice@127.0.0.1:"TEST_UDP_PORT_STR); 80 81 if (status != 0) 81 82 return status; … … 83 84 84 85 /* Multi-threaded round-trip test. */ 85 status = transport_rt_test(PJSIP_TRANSPORT_UDP, tp, &rem_addr); 86 status = transport_rt_test(PJSIP_TRANSPORT_UDP, tp, 87 "sip:alice@127.0.0.1:"TEST_UDP_PORT_STR); 86 88 if (status != 0) 87 89 return status; … … 94 96 pjsip_transport_dec_ref(udp_tp); 95 97 98 /* Force destroy this transport. */ 99 status = pjsip_transport_unregister( pjsip_endpt_get_tpmgr(endpt), udp_tp); 100 if (status != PJ_SUCCESS) 101 return -90; 102 103 96 104 /* Done */ 97 105 return 0; -
pjproject/trunk/pjsip/src/test-pjsip/txdata_test.c
- Property svn:keywords changed from "Id Revision" to Id
-
pjproject/trunk/pjsip/src/test-pjsip/uri_test.c
r106 r107 805 805 } 806 806 } 807 pjsip_endpt_ destroy_pool(endpt, pool);807 pjsip_endpt_release_pool(endpt, pool); 808 808 809 809 PJ_LOG(3,("", " benchmarking...")); … … 819 819 PJ_LOG(3,("uri_test", " error %d when testing entry %d", 820 820 status, i)); 821 pjsip_endpt_ destroy_pool(endpt, pool);821 pjsip_endpt_release_pool(endpt, pool); 822 822 goto on_return; 823 823 } 824 824 } 825 pjsip_endpt_ destroy_pool(endpt, pool);825 pjsip_endpt_release_pool(endpt, pool); 826 826 } 827 827
Note: See TracChangeset
for help on using the changeset viewer.