Changeset 106 for pjproject/trunk
- Timestamp:
- Dec 30, 2005 11:50:15 PM (19 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 4 added
- 29 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjlib/include/pj/assert.h
r65 r106 68 68 #endif 69 69 70 /** 71 * @hideinitializer 72 * If #PJ_ENABLE_EXTRA_CHECK is declared and non-zero, then 73 * #PJ_ASSERT_ON_FAIL macro will evaluate the expression in @a expr during 74 * run-time. If the expression yields false, assertion will be triggered 75 * and @a exec_on_fail will be executed. 76 * 77 * If #PJ_ENABLE_EXTRA_CHECK is not declared or is zero, then no run-time 78 * checking will be performed. The macro simply evaluates to pj_assert(expr). 79 */ 80 #if defined(PJ_ENABLE_EXTRA_CHECK) && PJ_ENABLE_EXTRA_CHECK != 0 81 # define PJ_ASSERT_ON_FAIL(expr,exec_on_fail) \ 82 do { \ 83 pj_assert(expr); \ 84 if (!(expr)) exec_on_fail; \ 85 } while (0) 86 #else 87 # define PJ_ASSERT_ON_FAIL(expr,exec_on_fail) pj_assert(expr) 88 #endif 89 70 90 /** @} */ 71 91 -
pjproject/trunk/pjlib/include/pj/os.h
r70 r106 505 505 * @} 506 506 */ 507 508 /////////////////////////////////////////////////////////////////////////////// 509 /** 510 * @defgroup PJ_RW_MUTEX Reader/Writer Mutex 511 * @ingroup PJ_OS 512 * @{ 513 * Reader/writer mutex is a classic synchronization object where multiple 514 * readers can acquire the mutex, but only a single writer can acquire the 515 * mutex. 516 */ 517 typedef struct pj_rwmutex_t pj_rwmutex_t; 518 519 /** 520 * Create reader/writer mutex. 521 * 522 * @param pool Pool to allocate memory for the mutex. 523 * @param name Name to be assigned to the mutex. 524 * @param mutex Pointer to receive the newly created mutex. 525 * 526 * @return PJ_SUCCESS on success, or the error code. 527 */ 528 PJ_DECL(pj_status_t) pj_rwmutex_create(pj_pool_t *pool, const char *name, 529 pj_rwmutex_t **mutex); 530 531 /** 532 * Lock the mutex for reading. 533 * 534 * @param mutex The mutex. 535 * @return PJ_SUCCESS on success, or the error code. 536 */ 537 PJ_DECL(pj_status_t) pj_rwmutex_lock_read(pj_rwmutex_t *mutex); 538 539 /** 540 * Lock the mutex for writing. 541 * 542 * @param mutex The mutex. 543 * @return PJ_SUCCESS on success, or the error code. 544 */ 545 PJ_DECL(pj_status_t) pj_rwmutex_lock_write(pj_rwmutex_t *mutex); 546 547 /** 548 * Release read lock. 549 * 550 * @param mutex The mutex. 551 * @return PJ_SUCCESS on success, or the error code. 552 */ 553 PJ_DECL(pj_status_t) pj_rwmutex_unlock_read(pj_rwmutex_t *mutex); 554 555 /** 556 * Release write lock. 557 * 558 * @param mutex The mutex. 559 * @return PJ_SUCCESS on success, or the error code. 560 */ 561 PJ_DECL(pj_status_t) pj_rwmutex_unlock_write(pj_rwmutex_t *mutex); 562 563 /** 564 * Destroy reader/writer mutex. 565 * 566 * @param mutex The mutex. 567 * @return PJ_SUCCESS on success, or the error code. 568 */ 569 PJ_DECL(pj_status_t) pj_rwmutex_destroy(pj_rwmutex_t *mutex); 570 571 572 /** 573 * @} 574 */ 575 507 576 508 577 /////////////////////////////////////////////////////////////////////////////// -
pjproject/trunk/pjlib/include/pj/sock.h
r66 r106 177 177 * This structure describes Internet socket address. 178 178 */ 179 typedefstruct pj_sockaddr_in179 struct pj_sockaddr_in 180 180 { 181 181 pj_uint16_t sin_family; /**< Address family. */ … … 183 183 pj_in_addr sin_addr; /**< IP address. */ 184 184 char sin_zero[8]; /**< Padding. */ 185 } pj_sockaddr_in;185 }; 186 186 187 187 -
pjproject/trunk/pjlib/include/pj/types.h
r66 r106 218 218 /** Generic socket address. */ 219 219 typedef void pj_sockaddr_t; 220 221 /** Forward declaration. */ 222 typedef struct pj_sockaddr_in pj_sockaddr_in; 220 223 221 224 /** Color type. */ -
pjproject/trunk/pjlib/src/pj/os_core_win32.c
r70 r106 860 860 861 861 /////////////////////////////////////////////////////////////////////////////// 862 863 struct pj_rwmutex_t 864 { 865 pj_mutex_t *read_lock, *write_lock; 866 int reader_count; 867 }; 868 869 /* 870 * Create reader/writer mutex. 871 * 872 */ 873 PJ_DEF(pj_status_t) pj_rwmutex_create(pj_pool_t *pool, const char *name, 874 pj_rwmutex_t **p_mutex) 875 { 876 pj_status_t status; 877 pj_rwmutex_t *rwmutex; 878 879 PJ_ASSERT_RETURN(pool && p_mutex, PJ_EINVAL); 880 881 *p_mutex = NULL; 882 rwmutex = pj_pool_alloc(pool, sizeof(struct pj_rwmutex_t)); 883 884 status = pj_mutex_create_simple(pool, name, &rwmutex ->read_lock); 885 if (status != PJ_SUCCESS) 886 return status; 887 888 status = pj_mutex_create_recursive(pool, name, &rwmutex->write_lock); 889 if (status != PJ_SUCCESS) { 890 pj_mutex_destroy(rwmutex->read_lock); 891 return status; 892 } 893 894 rwmutex->reader_count = 0; 895 *p_mutex = rwmutex; 896 return PJ_SUCCESS; 897 } 898 899 /* 900 * Lock the mutex for reading. 901 * 902 */ 903 PJ_DEF(pj_status_t) pj_rwmutex_lock_read(pj_rwmutex_t *mutex) 904 { 905 pj_status_t status; 906 907 PJ_ASSERT_RETURN(mutex, PJ_EINVAL); 908 909 status = pj_mutex_lock(mutex->read_lock); 910 if (status != PJ_SUCCESS) 911 return status; 912 913 mutex->reader_count++; 914 if (mutex->reader_count == 1) 915 pj_mutex_lock(mutex->write_lock); 916 917 status = pj_mutex_unlock(mutex->read_lock); 918 return status; 919 } 920 921 /* 922 * Lock the mutex for writing. 923 * 924 */ 925 PJ_DEF(pj_status_t) pj_rwmutex_lock_write(pj_rwmutex_t *mutex) 926 { 927 PJ_ASSERT_RETURN(mutex, PJ_EINVAL); 928 return pj_mutex_lock(mutex->write_lock); 929 } 930 931 /* 932 * Release read lock. 933 * 934 */ 935 PJ_DEF(pj_status_t) pj_rwmutex_unlock_read(pj_rwmutex_t *mutex) 936 { 937 pj_status_t status; 938 939 PJ_ASSERT_RETURN(mutex, PJ_EINVAL); 940 941 status = pj_mutex_lock(mutex->read_lock); 942 if (status != PJ_SUCCESS) 943 return status; 944 945 pj_assert(mutex->reader_count >= 1); 946 947 --mutex->reader_count; 948 if (mutex->reader_count == 0) 949 pj_mutex_unlock(mutex->write_lock); 950 951 status = pj_mutex_unlock(mutex->read_lock); 952 return status; 953 } 954 955 /* 956 * Release write lock. 957 * 958 */ 959 PJ_DEF(pj_status_t) pj_rwmutex_unlock_write(pj_rwmutex_t *mutex) 960 { 961 PJ_ASSERT_RETURN(mutex, PJ_EINVAL); 962 return pj_mutex_unlock(mutex->write_lock); 963 } 964 965 966 /* 967 * Destroy reader/writer mutex. 968 * 969 */ 970 PJ_DEF(pj_status_t) pj_rwmutex_destroy(pj_rwmutex_t *mutex) 971 { 972 PJ_ASSERT_RETURN(mutex, PJ_EINVAL); 973 pj_mutex_destroy(mutex->read_lock); 974 pj_mutex_destroy(mutex->write_lock); 975 return PJ_SUCCESS; 976 } 977 978 /////////////////////////////////////////////////////////////////////////////// 862 979 /* 863 980 * pj_enter_critical_section() -
pjproject/trunk/pjlib/src/pj/sock_bsd.c
r66 r106 188 188 PJ_CHECK_STACK(); 189 189 190 PJ_ASSERT_RETURN( str_addr &&str_addr->slen < PJ_MAX_HOSTNAME,190 PJ_ASSERT_RETURN(!str_addr || str_addr->slen < PJ_MAX_HOSTNAME, 191 191 (addr->sin_addr.s_addr=PJ_INADDR_NONE, PJ_EINVAL)); 192 192 … … 225 225 pj_uint16_t port) 226 226 { 227 PJ_ASSERT_RETURN(addr && str_addr, 228 (addr->sin_addr.s_addr=PJ_INADDR_NONE, PJ_EINVAL)); 227 PJ_ASSERT_RETURN(addr, (addr->sin_addr.s_addr=PJ_INADDR_NONE, PJ_EINVAL)); 229 228 230 229 addr->sin_family = PJ_AF_INET; -
pjproject/trunk/pjsip/build/pjsip_core.dsp
r82 r106 125 125 126 126 SOURCE=..\src\pjsip\sip_transaction.c 127 # PROP Exclude_From_Build 1 127 128 # End Source File 128 129 # Begin Source File … … 141 142 142 143 SOURCE=..\src\pjsip\sip_util.c 144 # End Source File 145 # Begin Source File 146 147 SOURCE=..\src\pjsip\sip_util_statefull.c 148 # PROP Exclude_From_Build 1 143 149 # End Source File 144 150 # End Group -
pjproject/trunk/pjsip/build/test_pjsip.dsp
r105 r106 102 102 # Begin Source File 103 103 104 SOURCE="..\src\test-pjsip\transport_test.c" 105 # End Source File 106 # Begin Source File 107 108 SOURCE="..\src\test-pjsip\transport_udp_test.c" 109 # End Source File 110 # Begin Source File 111 112 SOURCE="..\src\test-pjsip\txdata_test.c" 113 # End Source File 114 # Begin Source File 115 104 116 SOURCE="..\src\test-pjsip\uri_test.c" 105 117 # End Source File -
pjproject/trunk/pjsip/include/pjsip/sip_endpoint.h
r105 r106 116 116 const pj_time_val *max_timeout); 117 117 118 119 /** 120 * Schedule timer to endpoint's timer heap. Application must poll the endpoint 121 * periodically (by calling #pjsip_endpt_handle_events) to ensure that the 122 * timer events are handled in timely manner. When the timeout for the timer 123 * has elapsed, the callback specified in the entry argument will be called. 124 * This function, like all other endpoint functions, is thread safe. 125 * 126 * @param endpt The endpoint. 127 * @param entry The timer entry. 128 * @param delay The relative delay of the timer. 129 * @return PJ_OK (zero) if successfull. 130 */ 131 PJ_DECL(pj_status_t) pjsip_endpt_schedule_timer( pjsip_endpoint *endpt, 132 pj_timer_entry *entry, 133 const pj_time_val *delay ); 134 135 /** 136 * Cancel the previously registered timer. 137 * This function, like all other endpoint functions, is thread safe. 138 * 139 * @param endpt The endpoint. 140 * @param entry The timer entry previously registered. 141 */ 142 PJ_DECL(void) pjsip_endpt_cancel_timer( pjsip_endpoint *endpt, 143 pj_timer_entry *entry ); 144 145 118 146 /** 119 147 * Dump endpoint status to the log. This will print the status to the log … … 126 154 */ 127 155 PJ_DECL(void) pjsip_endpt_dump( pjsip_endpoint *endpt, pj_bool_t detail ); 156 157 158 /** 159 * Register new module to the endpoint. 160 * The endpoint will then call the load and start function in the module to 161 * properly initialize the module, and assign a unique module ID for the 162 * module. 163 * 164 * @param endpt The endpoint. 165 * @param module The module to be registered. 166 * 167 * @return PJ_SUCCESS on success. 168 */ 169 PJ_DECL(pj_status_t) pjsip_endpt_register_module( pjsip_endpoint *endpt, 170 pjsip_module *module ); 171 172 /** 173 * Unregister a module from the endpoint. 174 * The endpoint will then call the stop and unload function in the module to 175 * properly shutdown the module. 176 * 177 * @param endpt The endpoint. 178 * @param module The module to be registered. 179 * 180 * @return PJ_SUCCESS on success. 181 */ 182 PJ_DECL(pj_status_t) pjsip_endpt_unregister_module( pjsip_endpoint *endpt, 183 pjsip_module *module ); 184 128 185 129 186 /** … … 157 214 158 215 /** 159 * Schedule timer to endpoint's timer heap. Application must poll the endpoint160 * periodically (by calling #pjsip_endpt_handle_events) to ensure that the161 * timer events are handled in timely manner. When the timeout for the timer162 * has elapsed, the callback specified in the entry argument will be called.163 * This function, like all other endpoint functions, is thread safe.164 *165 * @param endpt The endpoint.166 * @param entry The timer entry.167 * @param delay The relative delay of the timer.168 * @return PJ_OK (zero) if successfull.169 */170 PJ_DECL(pj_status_t) pjsip_endpt_schedule_timer( pjsip_endpoint *endpt,171 pj_timer_entry *entry,172 const pj_time_val *delay );173 174 /**175 * Cancel the previously registered timer.176 * This function, like all other endpoint functions, is thread safe.177 *178 * @param endpt The endpoint.179 * @param entry The timer entry previously registered.180 */181 PJ_DECL(void) pjsip_endpt_cancel_timer( pjsip_endpoint *endpt,182 pj_timer_entry *entry );183 184 /**185 216 * Create a new transaction. After creating the transaction, application MUST 186 217 * initialize the transaction as either UAC or UAS (by calling … … 279 310 * @see pjsip_transport_get 280 311 */ 281 PJ_DECL(pj_status_t) pjsip_endpt_alloc_transport( pjsip_endpoint *endpt, 282 pjsip_transport_type_e type, 283 const pj_sockaddr *remote, 284 int addr_len, 285 pjsip_transport **p_transport); 312 PJ_DECL(pj_status_t) 313 pjsip_endpt_acquire_transport( pjsip_endpoint *endpt, 314 pjsip_transport_type_e type, 315 const pj_sockaddr_t *remote, 316 int addr_len, 317 pjsip_transport **p_transport); 286 318 287 319 /** -
pjproject/trunk/pjsip/include/pjsip/sip_errno.h
r65 r106 94 94 /** 95 95 * @hideinitializer 96 * Invalid message (syntax error)96 * General invalid message error (e.g. syntax error) 97 97 */ 98 98 #define PJSIP_EINVALIDMSG (PJSIP_ERRNO_START_PJSIP + 20) /* 171020 */ … … 114 114 /** 115 115 * @hideinitializer 116 * Missing Request-URI. 117 */ 118 #define PJSIP_EMISSINGREQURI (PJSIP_ERRNO_START_PJSIP + 24) /* 171024 */ 119 /** 120 * @hideinitializer 116 121 * Missing required header(s). 117 122 */ 118 #define PJSIP_EMISSINGHDR (PJSIP_ERRNO_START_PJSIP + 24) /* 171024 */ 123 #define PJSIP_EMISSINGHDR (PJSIP_ERRNO_START_PJSIP + 25) /* 171025 */ 124 /** 125 * @hideinitializer 126 * Missing message body. 127 */ 128 #define PJSIP_EMISSINGBODY (PJSIP_ERRNO_START_PJSIP + 26) /* 171026 */ 119 129 /** 120 130 * @hideinitializer 121 131 * Invalid Via header in response (sent-by, etc). 122 132 */ 123 #define PJSIP_EINVALIDVIA (PJSIP_ERRNO_START_PJSIP + 2 5) /* 171025*/133 #define PJSIP_EINVALIDVIA (PJSIP_ERRNO_START_PJSIP + 27) /* 171027 */ 124 134 /** 125 135 * @hideinitializer 126 136 * Multiple Via headers in response. 127 137 */ 128 #define PJSIP_EMULTIPLEVIA (PJSIP_ERRNO_START_PJSIP + 26) /* 171026 */ 138 #define PJSIP_EMULTIPLEVIA (PJSIP_ERRNO_START_PJSIP + 28) /* 171028 */ 139 /** 140 * @hideinitializer 141 * Invalid request URI. 142 */ 143 #define PJSIP_EINVALIDREQURI (PJSIP_ERRNO_START_PJSIP + 29) /* 171029 */ 144 /** 145 * @hideinitializer 146 * Expecting request message. 147 */ 148 #define PJSIP_ENOTREQUESTMSG (PJSIP_ERRNO_START_PJSIP + 30) /* 171030 */ 149 /** 150 * @hideinitializer 151 * Expecting response message. 152 */ 153 #define PJSIP_ENOTRESPONSEMSG (PJSIP_ERRNO_START_PJSIP + 31) /* 171031 */ 154 129 155 130 156 /************************************************************ … … 145 171 * Rx buffer overflow. See also PJSIP_EMSGTOOLONG. 146 172 */ 147 #define PJSIP_ERXOVERFLOW (PJSIP_ERRNO_START_PJSIP + 42)/* 171042 */ 173 #define PJSIP_ERXOVERFLOW (PJSIP_ERRNO_START_PJSIP + 42) /* 171042 */ 174 /** 175 * @hideinitializer 176 * This is not really an error, it just informs application that 177 * transmit data has been deleted on return of pjsip_tx_data_dec_ref(). 178 */ 179 #define PJSIP_EBUFDESTROYED (PJSIP_ERRNO_START_PJSIP + 43) /* 171043 */ 148 180 149 181 -
pjproject/trunk/pjsip/include/pjsip/sip_module.h
r65 r106 42 42 struct pjsip_module 43 43 { 44 /** To allow chaining of modules in the endpoint. */ 45 PJ_DECL_LIST_MEMBER(struct pjsip_module); 46 44 47 /** 45 48 * Module name. … … 48 51 49 52 /** 50 * Flag to indicate the type of interfaces supported by the module.53 * Module ID. 51 54 */ 52 pj_uint32_t flag;55 int id; 53 56 54 57 /** … … 57 60 * initialized later. 58 61 */ 59 pj_uint32_t priority;62 int priority; 60 63 61 64 /** … … 63 66 * the module itself. 64 67 */ 65 void * mod_data;68 void *user_data; 66 69 67 70 /** … … 79 82 * 80 83 * @param endpt The endpoint instance. 81 * @param mod The module. 82 * @param id The unique module ID assigned to this module. 83 * 84 * @return Module should return zero when initialization succeed. 84 * @return Module should return PJ_SUCCESS to indicate success. 85 85 */ 86 pj_status_t (*init_module)(pjsip_endpoint *endpt, 87 struct pjsip_module *mod, pj_uint32_t id); 86 pj_status_t (*load)(pjsip_endpoint *endpt); 88 87 89 88 /** 90 89 * Pointer to function to be called to start the module. 91 90 * 92 * @param mod The module.93 *94 91 * @return Module should return zero to indicate success. 95 92 */ 96 pj_status_t (*start_module)(struct pjsip_module *mod); 93 pj_status_t (*start)(void); 94 95 /** 96 * Pointer to function to be called to deinitialize the module before 97 * it is unloaded. 98 * 99 * @return Module should return PJ_SUCCESS to indicate success. 100 */ 101 pj_status_t (*stop)(void); 97 102 98 103 /** … … 102 107 * @param mod The module. 103 108 * 104 * @return Module should return zeroto indicate success.109 * @return Module should return PJ_SUCCESS to indicate success. 105 110 */ 106 pj_status_t (* deinit_module)(struct pjsip_module *mod);111 pj_status_t (*unload)(void); 107 112 108 113 /** 109 * Pointer to function to receive transaction related events. 110 * If the module doesn't wish to receive such notification, this member 111 * must be set to NULL. 114 * Called to process incoming request. 112 115 * 113 * @param mod The module. 114 * @param event The transaction event. 116 * @param rdata The incoming message. 117 * 118 * @return Module should return PJ_TRUE if it handles the request, 119 * or otherwise it should return PJ_FALSE to allow other 120 * modules to handle the request. 115 121 */ 116 void (*tsx_handler)(struct pjsip_module *mod, pjsip_event *event); 122 pj_bool_t (*on_rx_request)(pjsip_rx_data *rdata); 123 124 /** 125 * Called to processed incoming response. 126 * 127 * @param rdata The incoming message. 128 * 129 * @return Module should return PJ_TRUE if it handles the 130 * response, or otherwise it should return PJ_FALSE to 131 * allow other modules to handle the response. 132 */ 133 pj_bool_t (*on_rx_response)(pjsip_rx_data *rdata); 134 135 /** 136 * Called when this module is acting as transaction user for the specified 137 * transaction, when the transaction's state has changed. 138 * 139 * @param tsx The transaction. 140 * @param event The event which has caused the transaction state 141 * to change. 142 */ 143 void (*on_tsx_state)(pjsip_transaction *tsx, pjsip_event *event); 144 117 145 }; 118 146 119 147 120 148 /** 121 * Prototype of function to register static modules (eg modules that are 122 * linked staticly with the application). This function must be implemented 123 * by any applications that use PJSIP library. 124 * 125 * @param count [input/output] On input, it contains the maximum number of 126 * elements in the array. On output, the function fills with 127 * the number of modules to be registered. 128 * @param modules [output] array of pointer to modules to be registered. 149 * Module priority guidelines. 129 150 */ 130 pj_status_t register_static_modules( pj_size_t *count, 131 pjsip_module **modules ); 151 enum pjsip_module_priority 152 { 153 PJSIP_MOD_PRIORITY_TSX_LAYER = 4, 154 PJSIP_MOD_PRIORITY_UA_PROXY_LAYER = 16, 155 PJSIP_MOD_PRIORITY_APPLICATION = 32, 156 }; 157 132 158 133 159 /** -
pjproject/trunk/pjsip/include/pjsip/sip_msg.h
r65 r106 53 53 typedef enum pjsip_method_e 54 54 { 55 /** INVITE method, for establishing dialogs. */ 56 PJSIP_INVITE_METHOD, 57 58 /** CANCEL method, for cancelling request. */ 59 PJSIP_CANCEL_METHOD, 60 61 /** ACK method, for acknowledging final response to INVITE. */ 62 PJSIP_ACK_METHOD, 63 64 /** BYE method, for terminating dialog. */ 65 PJSIP_BYE_METHOD, 66 67 /** REGISTER method. */ 68 PJSIP_REGISTER_METHOD, 69 70 /** OPTIONS method, for querying remote capabilities. */ 71 PJSIP_OPTIONS_METHOD, 72 73 /** Other method, which means that the method name itself will be stored 74 elsewhere. */ 75 PJSIP_OTHER_METHOD, 55 PJSIP_INVITE_METHOD, /**< INVITE method, for establishing dialogs. */ 56 PJSIP_CANCEL_METHOD, /**< CANCEL method, for cancelling request. */ 57 PJSIP_ACK_METHOD, /**< ACK method. */ 58 PJSIP_BYE_METHOD, /**< BYE method, for terminating dialog. */ 59 PJSIP_REGISTER_METHOD, /**< REGISTER method. */ 60 PJSIP_OPTIONS_METHOD, /**< OPTIONS method. */ 61 62 PJSIP_OTHER_METHOD, /**< Other method. */ 76 63 77 64 } pjsip_method_e; … … 92 79 method string. */ 93 80 } pjsip_method; 81 82 83 /* 84 * For convenience, standard method structures are defined in the library. 85 */ 86 extern const pjsip_method pjsip_invite_method; /**< INVITE structure. */ 87 extern const pjsip_method pjsip_cancel_method; /**< CANCEL structure. */ 88 extern const pjsip_method pjsip_ack_method; /**< ACK structure. */ 89 extern const pjsip_method pjsip_bye_method; /**< BYE structure. */ 90 extern const pjsip_method pjsip_register_method; /**< REGISTER structure.*/ 91 extern const pjsip_method pjsip_options_method; /**< OPTIONS structure. */ 94 92 95 93 … … 639 637 * type is found. 640 638 */ 641 PJ_DECL(void*) pjsip_msg_find_hdr( pjsip_msg *msg,642 pjsip_hdr_e type, void *start);639 PJ_DECL(void*) pjsip_msg_find_hdr( const pjsip_msg *msg, 640 pjsip_hdr_e type, const void *start); 643 641 644 642 /** … … 655 653 * type is found. 656 654 */ 657 PJ_DECL(void*) pjsip_msg_find_hdr_by_name( pjsip_msg *msg, 658 const pj_str_t *name, void *start); 655 PJ_DECL(void*) pjsip_msg_find_hdr_by_name( const pjsip_msg *msg, 656 const pj_str_t *name, 657 const void *start); 659 658 660 659 /** … … 703 702 * value if the message is too large for the specified buffer. 704 703 */ 705 PJ_DECL(pj_ssize_t) pjsip_msg_print(pjsip_msg *msg, char *buf, pj_size_t size); 704 PJ_DECL(pj_ssize_t) pjsip_msg_print(const pjsip_msg *msg, 705 char *buf, pj_size_t size); 706 706 707 707 /** -
pjproject/trunk/pjsip/include/pjsip/sip_transport.h
r105 r106 368 368 /** 369 369 * Decrement reference counter of the transmit buffer. 370 * When the transmit buffer is no longer used, it will be destroyed. 370 * When the transmit buffer is no longer used, it will be destroyed and 371 * caller is informed with PJSIP_EBUFDESTROYED return status. 371 372 * 372 373 * @param tdata The transmit buffer data. 373 */ 374 PJ_DECL(void) pjsip_tx_data_dec_ref( pjsip_tx_data *tdata ); 374 * @return This function will always succeeded eventhough the return 375 * status is non-zero. A status PJSIP_EBUFDESTROYED will be 376 * returned to inform that buffer is destroyed. 377 */ 378 PJ_DECL(pj_status_t) pjsip_tx_data_dec_ref( pjsip_tx_data *tdata ); 375 379 376 380 /** … … 378 382 * 379 383 * @param tdata The transmit buffer. 384 * @return Non-zero (PJ_TRUE) if buffer contains a valid message. 380 385 */ 381 386 PJ_DECL(pj_bool_t) pjsip_tx_data_is_valid( pjsip_tx_data *tdata ); … … 543 548 /** 544 549 * Create new outbound connection. 550 * Note that the factory is responsible for both creating the 551 * transport and registering it to the transport manager. 545 552 */ 546 553 pj_status_t (*create_transport)(pjsip_tpfactory *factory, … … 548 555 pjsip_endpoint *endpt, 549 556 const pj_sockaddr *rem_addr, 557 int addr_len, 550 558 pjsip_transport **transport); 551 559 … … 622 630 * suitable transport is found, a new one will be created. 623 631 */ 624 PJ_DECL(pj_status_t) pjsip_tpmgr_a lloc_transport(pjsip_tpmgr *mgr,625 pjsip_transport_type_e type,626 const pj_sockaddr_t *remote,627 int addr_len,628 pjsip_transport **p_transport);632 PJ_DECL(pj_status_t) pjsip_tpmgr_acquire_transport(pjsip_tpmgr *mgr, 633 pjsip_transport_type_e type, 634 const pj_sockaddr_t *remote, 635 int addr_len, 636 pjsip_transport **tp); 629 637 630 638 -
pjproject/trunk/pjsip/include/pjsip/sip_transport_udp.h
r105 r106 22 22 #include <pjsip/sip_transport.h> 23 23 24 PJ_ DECL24 PJ_BEGIN_DECL 25 25 26 26 /** -
pjproject/trunk/pjsip/include/pjsip/sip_util.h
r105 r106 21 21 22 22 #include <pjsip/sip_msg.h> 23 #include <pjsip/sip_resolve.h> 23 24 24 25 PJ_BEGIN_DECL … … 34 35 * request outside a dialog, such as OPTIONS, MESSAGE, etc. To create a request 35 36 * inside a dialog, application should use #pjsip_dlg_create_request. 37 * 38 * This function adds the following headers in the request: 39 * - From, To, Call-ID, and CSeq, 40 * - Contact header, if contact is specified. 41 * - A blank Via header. 42 * - Additional request headers (such as Max-Forwards) which are copied 43 * from endpoint configuration. 44 * 45 * In addition, the function adds a unique tag in the From header. 36 46 * 37 47 * Once a transmit data is created, the reference counter is initialized to 1. … … 63 73 /** 64 74 * Create an independent request message from the specified headers. This 65 * function will shallow clone the headers and put them in the request. 75 * function will clone the headers and put them in the request. 76 * 77 * This function adds the following headers in the request: 78 * - From, To, Call-ID, and CSeq, 79 * - Contact header, if contact is specified. 80 * - A blank Via header. 81 * - Additional request headers (such as Max-Forwards) which are copied 82 * from endpoint configuration. 83 * 84 * In addition, the function adds a unique tag in the From header. 66 85 * 67 86 * Once a transmit data is created, the reference counter is initialized to 1. … … 93 112 94 113 /** 114 * Construct a minimal response message for the received request. This function 115 * will construct all the Via, Record-Route, Call-ID, From, To, CSeq, and 116 * Call-ID headers from the request. 117 * 118 * Note: the txdata reference counter is set to ZERO!. 119 * 120 * @param endpt The endpoint. 121 * @param rdata The request receive data. 122 * @param st_code Status code to be put in the response. 123 * @param st_text Optional status text, or NULL to get the default text. 124 * @param p_tdata Pointer to receive the transmit data. 125 * 126 * @return PJ_SUCCESS, or the appropriate error code. 127 */ 128 PJ_DECL(pj_status_t) pjsip_endpt_create_response( pjsip_endpoint *endpt, 129 const pjsip_rx_data *rdata, 130 int st_code, 131 const pj_str_t *st_text, 132 pjsip_tx_data **p_tdata); 133 134 /** 135 * Construct a full ACK request for the received non-2xx final response. 136 * This utility function is normally called by the transaction to construct 137 * an ACK request to 3xx-6xx final response. 138 * The generation of ACK message for 2xx final response is different than 139 * this one. 140 * 141 * @param endpt The endpoint. 142 * @param tdata This contains the original INVITE request 143 * @param rdata The final response. 144 * @param ack The ACK request created. 145 * 146 * @return PJ_SUCCESS, or the appropriate error code. 147 */ 148 PJ_DECL(pj_status_t) pjsip_endpt_create_ack( pjsip_endpoint *endpt, 149 const pjsip_tx_data *tdata, 150 const pjsip_rx_data *rdata, 151 pjsip_tx_data **ack); 152 153 154 /** 155 * Construct CANCEL request for the previously sent request. 156 * 157 * @param endpt The endpoint. 158 * @param tdata The transmit buffer for the request being cancelled. 159 * @param p_tdata Pointer to receive the transmit data. 160 * 161 * @return PJ_SUCCESS, or the appropriate error code. 162 */ 163 PJ_DECL(pj_status_t) pjsip_endpt_create_cancel( pjsip_endpoint *endpt, 164 const pjsip_tx_data *tdata, 165 pjsip_tx_data **p_tdata); 166 167 168 /** 169 * Find which destination to be used to send the request message, based 170 * on the request URI and Route headers in the message. The procedure 171 * used here follows the guidelines on sending the request in RFC 3261 172 * chapter 8.1.2. 173 * 174 * This function may modify the message (request line and Route headers), 175 * if the Route information specifies strict routing and the request 176 * URI in the message is different than the calculated target URI. In that 177 * case, the target URI will be put as the request URI of the request and 178 * current request URI will be put as the last entry of the Route headers. 179 * 180 * @param tdata The transmit data containing the request message. 181 * @param dest_info On return, it contains information about destination 182 * host to contact, along with the preferable transport 183 * type, if any. Caller will then normally proceed with 184 * resolving this host with server resolution procedure 185 * described in RFC 3263. 186 * 187 * @return PJ_SUCCESS, or the appropriate error code. 188 */ 189 PJ_DECL(pj_status_t) pjsip_get_request_addr( pjsip_tx_data *tdata, 190 pjsip_host_info *dest_info ); 191 192 193 /** 194 * This structure holds the state of outgoing stateless request. 195 */ 196 typedef struct pjsip_send_state 197 { 198 /** Application token, which was specified when the function 199 * #pjsip_endpt_send_request_stateless() is called. 200 */ 201 void *token; 202 203 /** Endpoint instance. 204 */ 205 pjsip_endpoint *endpt; 206 207 /** Transmit data buffer being sent. 208 */ 209 pjsip_tx_data *tdata; 210 211 /** Server addresses resolved. 212 */ 213 pjsip_server_addresses addr; 214 215 /** Current server address being tried. 216 */ 217 unsigned cur_addr; 218 219 /** Current transport being used. 220 */ 221 pjsip_transport *cur_transport; 222 223 /** The application callback which was specified when the function 224 * #pjsip_endpt_send_request_stateless() was called. 225 */ 226 void (*app_cb)(struct pjsip_send_state*, 227 pj_ssize_t sent, 228 pj_bool_t *cont); 229 } pjsip_send_state; 230 231 /** 232 * Send outgoing request statelessly The function will take care of which 233 * destination and transport to use based on the information in the message, 234 * taking care of URI in the request line and Route header. 235 * 236 * This function is different than #pjsip_transport_send() in that this 237 * function adds/modify the Via header as necessary. 238 * 239 * @param endpt The endpoint instance. 240 * @param tdata The transmit data to be sent. 241 * 242 * @return PJ_SUCCESS, or the appropriate error code. 243 */ 244 PJ_DECL(pj_status_t) 245 pjsip_endpt_send_request_stateless( pjsip_endpoint *endpt, 246 pjsip_tx_data *tdata, 247 void *token, 248 void (*cb)(pjsip_send_state*, 249 pj_ssize_t sent, 250 pj_bool_t *cont)); 251 252 /** 253 * This structure describes destination information to send response. 254 * It is initialized by calling #pjsip_get_response_addr(). 255 * 256 * If the response message should be sent using transport from which 257 * the request was received, then transport, addr, and addr_len fields 258 * are initialized. 259 * 260 * The dst_host field is also initialized. It should be used when server 261 * fails to send the response using the transport from which the request 262 * was received, or when the transport is NULL, which means server 263 * must send the response to this address (this situation occurs when 264 * maddr parameter is set, or when rport param is not set in the request). 265 */ 266 typedef struct pjsip_response_addr 267 { 268 pjsip_transport *transport; /**< Immediate transport to be used. */ 269 pj_sockaddr addr; /**< Immediate address to send to. */ 270 int addr_len; /**< Address length. */ 271 pjsip_host_info dst_host; /**< Destination host to contact. */ 272 } pjsip_response_addr; 273 274 /** 275 * Determine which address (and transport) to use to send response message 276 * based on the received request. This function follows the specification 277 * in section 18.2.2 of RFC 3261 and RFC 3581 for calculating the destination 278 * address and transport. 279 * 280 * The information about destination to send the response will be returned 281 * in res_addr argument. Please see #pjsip_response_addr for more info. 282 * 283 * @param pool The pool. 284 * @param rdata The incoming request received by the server. 285 * @param res_addr On return, it will be initialized with information about 286 * destination address and transport to send the response. 287 * 288 * @return zero (PJ_OK) if successfull. 289 */ 290 PJ_DECL(pj_status_t) pjsip_get_response_addr(pj_pool_t *pool, 291 pjsip_rx_data *rdata, 292 pjsip_response_addr *res_addr); 293 294 /** 295 * Send response in tdata statelessly. The function will take care of which 296 * response destination and transport to use based on the information in the 297 * Via header (such as the presence of rport, symmetric transport, etc.). 298 * 299 * This function will create a new ephemeral transport if no existing 300 * transports can be used to send the message to the destination. The ephemeral 301 * transport will be destroyed after some period if it is not used to send any 302 * more messages. 303 * 304 * The behavior of this function complies with section 18.2.2 of RFC 3261 305 * and RFC 3581. 306 * 307 * @param endpt The endpoint instance. 308 * @param res_addr The information about the address and transport to send 309 * the response to. Application can get this information 310 * by calling #pjsip_get_response_addr(). 311 * @param tdata The response message to be sent. 312 * @param token Token to be passed back when the callback is called. 313 * @param cb Optional callback to notify the transmission status 314 * to application, and to inform whether next address or 315 * transport will be tried. 316 * 317 * @return PJ_SUCCESS if response has been successfully created and 318 * sent to transport layer, or a non-zero error code. 319 * However, even when it returns PJ_SUCCESS, there is no 320 * guarantee that the response has been successfully sent. 321 */ 322 PJ_DECL(pj_status_t) pjsip_endpt_send_response( pjsip_endpoint *endpt, 323 pjsip_response_addr *res_addr, 324 pjsip_tx_data *tdata, 325 void *token, 326 void (*cb)(pjsip_send_state*, 327 pj_ssize_t sent, 328 pj_bool_t *cont)); 329 330 /** 95 331 * Send outgoing request and initiate UAC transaction for the request. 96 332 * This is an auxiliary function to be used by application to send arbitrary … … 117 353 void (*cb)(void*,pjsip_event*)); 118 354 119 /**120 * Construct a minimal response message for the received request. This function121 * will construct all the Via, Record-Route, Call-ID, From, To, CSeq, and122 * Call-ID headers from the request.123 *124 * Note: the txdata reference counter is set to ZERO!.125 *126 * @param endpt The endpoint.127 * @param rdata The request receive data.128 * @param code Status code to be put in the response.129 * @param p_tdata Pointer to receive the transmit data.130 *131 * @return PJ_SUCCESS, or the appropriate error code.132 */133 PJ_DECL(pj_status_t) pjsip_endpt_create_response( pjsip_endpoint *endpt,134 const pjsip_rx_data *rdata,135 int code,136 pjsip_tx_data **p_tdata);137 138 /**139 * Construct a full ACK request for the received non-2xx final response.140 * This utility function is normally called by the transaction to construct141 * an ACK request to 3xx-6xx final response.142 * The generation of ACK message for 2xx final response is different than143 * this one.144 *145 * @param endpt The endpoint.146 * @param tdata On input, this contains the original INVITE request, and on147 * output, it contains the ACK message.148 * @param rdata The final response message.149 */150 PJ_DECL(void) pjsip_endpt_create_ack( pjsip_endpoint *endpt,151 pjsip_tx_data *tdata,152 const pjsip_rx_data *rdata );153 154 155 /**156 * Construct CANCEL request for the previously sent request.157 *158 * @param endpt The endpoint.159 * @param tdata The transmit buffer for the request being cancelled.160 * @param p_tdata Pointer to receive the transmit data.161 *162 * @return PJ_SUCCESS, or the appropriate error code.163 */164 PJ_DECL(pj_status_t) pjsip_endpt_create_cancel( pjsip_endpoint *endpt,165 pjsip_tx_data *tdata,166 pjsip_tx_data **p_tdata);167 168 169 /**170 * Get the address parameters (host, port, flag, TTL, etc) to send the171 * response.172 *173 * @param pool The pool.174 * @param tr The transport where the request was received.175 * @param via The top-most Via header of the request.176 * @param addr The send address concluded from the calculation.177 *178 * @return zero (PJ_OK) if successfull.179 */180 PJ_DECL(pj_status_t) pjsip_get_response_addr(pj_pool_t *pool,181 const pjsip_transport *tr,182 const pjsip_via_hdr *via,183 pjsip_host_info *addr);184 355 185 356 /** -
pjproject/trunk/pjsip/include/pjsip_core.h
r82 r106 32 32 #include <pjsip/sip_transaction.h> 33 33 #include <pjsip/sip_transport.h> 34 #include <pjsip/sip_transport_udp.h> 34 35 #include <pjsip/sip_uri.h> 35 36 #include <pjsip/sip_util.h> -
pjproject/trunk/pjsip/src/pjsip/sip_endpoint.c
r105 r106 57 57 pj_str_t name; 58 58 59 /** Transaction table. */60 pj_hash_table_t *tsx_table;61 62 /** Mutex for transaction table. */63 pj_mutex_t *tsx_table_mutex;64 65 59 /** Timer heap. */ 66 60 pj_timer_heap_t *timer_heap; … … 75 69 pjsip_resolver_t *resolver; 76 70 77 /** Number of modules registered. */78 pj_ uint32_t mod_count;71 /** Modules lock. */ 72 pj_rwmutex_t *mod_mutex; 79 73 80 74 /** Modules. */ 81 75 pjsip_module *modules[PJSIP_MAX_MODULE]; 76 77 /** Module list, sorted by priority. */ 78 pjsip_module module_list; 82 79 83 80 /** Number of supported methods. */ … … 128 125 129 126 /* 130 * Initialize modules. 131 */ 132 static pj_status_t init_modules( pjsip_endpoint *endpt ) 127 * Register new module to the endpoint. 128 * The endpoint will then call the load and start function in the module to 129 * properly initialize the module, and assign a unique module ID for the 130 * module. 131 */ 132 PJ_DEF(pj_status_t) pjsip_endpt_register_module( pjsip_endpoint *endpt, 133 pjsip_module *mod ) 134 { 135 pj_status_t status = PJ_SUCCESS; 136 pjsip_module *m; 137 int i; 138 139 pj_rwmutex_lock_write(endpt->mod_mutex); 140 141 /* Make sure that this module has not been registered. */ 142 PJ_ASSERT_ON_FAIL( pj_list_find_node(&endpt->module_list, mod) == NULL, 143 {status = PJ_EEXISTS; goto on_return;}); 144 145 /* Find unused ID for this module. */ 146 for (i=0; i<PJ_ARRAY_SIZE(endpt->modules); ++i) { 147 if (endpt->modules[i] == NULL) 148 break; 149 } 150 if (i == PJ_ARRAY_SIZE(endpt->modules)) { 151 pj_assert(!"Too many modules registered!"); 152 status = PJ_ETOOMANY; 153 goto on_return; 154 } 155 156 /* Assign the ID. */ 157 mod->id = i; 158 159 /* Try to load the module. */ 160 if (mod->load) { 161 status = (*mod->load)(endpt); 162 if (status != PJ_SUCCESS) 163 goto on_return; 164 } 165 166 /* Try to start the module. */ 167 if (mod->start) { 168 status = (*mod->start)(); 169 if (status != PJ_SUCCESS) 170 goto on_return; 171 } 172 173 /* Save the module. */ 174 endpt->modules[i] = mod; 175 176 /* Put in the module list, sorted by priority. */ 177 m = endpt->module_list.next; 178 while (m != &endpt->module_list) { 179 if (m->priority > mod->priority) 180 break; 181 m = m->next; 182 } 183 pj_list_insert_before(m, mod); 184 185 /* Done. */ 186 PJ_TODO(BUILD_ALLOW_HEADER_BASED_ON_MODULES_SUPPORTED_METHODS); 187 188 on_return: 189 pj_rwmutex_unlock_write(endpt->mod_mutex); 190 return status; 191 } 192 193 /* 194 * Unregister a module from the endpoint. 195 * The endpoint will then call the stop and unload function in the module to 196 * properly shutdown the module. 197 */ 198 PJ_DEF(pj_status_t) pjsip_endpt_unregister_module( pjsip_endpoint *endpt, 199 pjsip_module *mod ) 133 200 { 134 201 pj_status_t status; 135 unsigned i; 136 //pj_str_t str_COMMA = { ", ", 2 }; 137 extern pjsip_module aux_tsx_module; 138 139 PJ_LOG(5, (THIS_FILE, "init_modules()")); 140 141 /* Load static modules. */ 142 endpt->mod_count = PJSIP_MAX_MODULE; 143 status = register_static_modules( &endpt->mod_count, endpt->modules ); 144 if (status != 0) { 145 return status; 146 } 147 148 /* Add mini aux module. */ 149 endpt->modules[endpt->mod_count++] = &aux_tsx_module; 150 151 /* Load dynamic modules. */ 152 // Not supported yet! 153 154 /* Sort modules on the priority. */ 155 for (i=endpt->mod_count-1; i>0; --i) { 156 pj_uint32_t max = 0; 157 unsigned j; 158 for (j=1; j<=i; ++j) { 159 if (endpt->modules[j]->priority > endpt->modules[max]->priority) 160 max = j; 161 } 162 if (max != i) { 163 pjsip_module *temp = endpt->modules[max]; 164 endpt->modules[max] = endpt->modules[i]; 165 endpt->modules[i] = temp; 166 } 167 } 168 169 /* Initialize each module. */ 170 for (i=0; i < endpt->mod_count; ++i) { 171 int j; 172 173 pjsip_module *mod = endpt->modules[i]; 174 if (mod->init_module) { 175 status = mod->init_module(endpt, mod, i); 176 if (status != 0) { 177 return status; 178 } 179 } 180 181 /* Collect all supported methods from modules. */ 182 for (j=0; j<mod->method_cnt; ++j) { 183 unsigned k; 184 for (k=0; k<endpt->method_cnt; ++k) { 185 if (pjsip_method_cmp(mod->methods[j], endpt->methods[k]) == 0) 186 break; 187 } 188 if (k == endpt->method_cnt) { 189 if (endpt->method_cnt < MAX_METHODS) { 190 endpt->methods[endpt->method_cnt++] = mod->methods[j]; 191 } else { 192 PJ_LOG(1,(THIS_FILE, "Too many methods")); 193 return -1; 194 } 195 } 196 } 197 } 198 199 /* Create Allow header. */ 200 endpt->allow_hdr = pjsip_allow_hdr_create( endpt->pool ); 201 endpt->allow_hdr->count = endpt->method_cnt; 202 for (i=0; i<endpt->method_cnt; ++i) { 203 endpt->allow_hdr->values[i] = endpt->methods[i]->name; 204 } 205 206 /* Start each module. */ 207 for (i=0; i < endpt->mod_count; ++i) { 208 pjsip_module *mod = endpt->modules[i]; 209 if (mod->start_module) { 210 status = mod->start_module(mod); 211 if (status != 0) { 212 return status; 213 } 214 } 215 } 202 203 pj_rwmutex_lock_write(endpt->mod_mutex); 204 205 /* Make sure the module exists in the list. */ 206 PJ_ASSERT_ON_FAIL( pj_list_find_node(&endpt->module_list, mod) == mod, 207 {status = PJ_ENOTFOUND;goto on_return;} ); 208 209 /* Make sure the module exists in the array. */ 210 PJ_ASSERT_ON_FAIL( mod->id>=0 && mod->id<PJ_ARRAY_SIZE(endpt->modules) && 211 endpt->modules[mod->id] == mod, 212 {status = PJ_ENOTFOUND; goto on_return;}); 213 214 /* Try to stop the module. */ 215 if (mod->stop) { 216 status = (*mod->stop)(); 217 if (status != PJ_SUCCESS) goto on_return; 218 } 219 220 /* Try to unload the module. */ 221 if (mod->unload) { 222 status = (*mod->unload)(); 223 if (status != PJ_SUCCESS) goto on_return; 224 } 225 226 /* Remove module from array. */ 227 endpt->modules[mod->id] = NULL; 228 229 /* Remove module from list. */ 230 pj_list_erase(mod); 216 231 217 232 /* Done. */ 218 return 0; 219 } 220 221 /* 222 * Unregister the transaction from the hash table, and destroy the resources 223 * from the transaction. 224 */ 225 PJ_DEF(void) pjsip_endpt_destroy_tsx( pjsip_endpoint *endpt, 226 pjsip_transaction *tsx) 227 { 228 PJ_LOG(5, (THIS_FILE, "pjsip_endpt_destroy_tsx(%s)", tsx->obj_name)); 229 230 pj_assert(tsx->state == PJSIP_TSX_STATE_DESTROYED); 231 232 /* No need to lock transaction. 233 * This function typically is called from the transaction callback, which 234 * means that transaction mutex is being held. 235 */ 236 pj_assert( pj_mutex_is_locked(tsx->mutex) ); 237 238 /* Lock endpoint. */ 239 pj_mutex_lock( endpt->tsx_table_mutex ); 240 241 /* Unregister from the hash table. */ 242 pj_hash_set( NULL, endpt->tsx_table, tsx->transaction_key.ptr, 243 tsx->transaction_key.slen, NULL); 244 245 /* Unlock endpoint mutex. */ 246 pj_mutex_unlock( endpt->tsx_table_mutex ); 247 248 /* Destroy transaction mutex. */ 249 pj_mutex_destroy( tsx->mutex ); 250 251 /* Release the pool for the transaction. */ 252 pj_pool_release(tsx->pool); 253 254 PJ_LOG(4, (THIS_FILE, "tsx%p destroyed", tsx)); 255 } 256 257 258 /* 259 * Receive transaction events from transactions and dispatch them to the 260 * modules. 261 */ 262 static void endpt_do_event( pjsip_endpoint *endpt, pjsip_event *evt) 263 { 264 unsigned i; 265 266 /* Dispatch event to modules. */ 267 for (i=0; i<endpt->mod_count; ++i) { 268 pjsip_module *mod = endpt->modules[i]; 269 if (mod && mod->tsx_handler) { 270 mod->tsx_handler( mod, evt ); 271 } 272 } 273 274 /* Destroy transaction if it is terminated. */ 275 if (evt->type == PJSIP_EVENT_TSX_STATE && 276 evt->body.tsx_state.tsx->state == PJSIP_TSX_STATE_DESTROYED) 277 { 278 /* No need to lock mutex. Mutex is locked inside the destroy function */ 279 pjsip_endpt_destroy_tsx( endpt, evt->body.tsx_state.tsx ); 280 } 281 } 282 283 /* 284 * Receive transaction events from transactions and put in the event queue 285 * to be processed later. 286 */ 287 void pjsip_endpt_send_tsx_event( pjsip_endpoint *endpt, pjsip_event *evt ) 288 { 289 // Need to protect this with try/catch? 290 endpt_do_event(endpt, evt); 233 status = PJ_SUCCESS; 234 235 PJ_TODO(REMOVE_METHODS_FROM_ALLOW_HEADER_WHEN_MODULE_IS_UNREGISTERED); 236 237 on_return: 238 pj_rwmutex_unlock_write(endpt->mod_mutex); 239 return status; 291 240 } 292 241 … … 376 325 377 326 /* Create endpoint. */ 378 endpt = pj_pool_ calloc(pool, 1, sizeof(*endpt));327 endpt = pj_pool_zalloc(pool, sizeof(*endpt)); 379 328 endpt->pool = pool; 380 329 endpt->pf = pf; 330 331 /* Init modules list. */ 332 pj_list_init(&endpt->module_list); 333 334 /* Create R/W mutex for module manipulation. */ 335 status = pj_rwmutex_create(endpt->pool, "ept%p", &endpt->mod_mutex); 336 if (status != PJ_SUCCESS) 337 goto on_error; 381 338 382 339 /* Init parser. */ … … 400 357 } 401 358 402 /* Create mutex for the transaction table. */403 status = pj_mutex_create_recursive( endpt->pool, "mtbl%p",404 &endpt->tsx_table_mutex);405 if (status != PJ_SUCCESS) {406 goto on_error;407 }408 409 /* Create hash table for transaction. */410 endpt->tsx_table = pj_hash_create( endpt->pool, PJSIP_MAX_TSX_COUNT );411 if (!endpt->tsx_table) {412 status = PJ_ENOMEM;413 goto on_error;414 }415 416 359 /* Create timer heap to manage all timers within this endpoint. */ 417 360 status = pj_timer_heap_create( endpt->pool, PJSIP_MAX_TIMER_COUNT, … … 453 396 } 454 397 455 /* Initialize TLS ID for transaction lock. */456 status = pj_thread_local_alloc(&pjsip_tsx_lock_tls_id);457 if (status != PJ_SUCCESS) {458 goto on_error;459 }460 pj_thread_local_set(pjsip_tsx_lock_tls_id, NULL);461 462 398 /* Initialize request headers. */ 463 399 pj_list_init(&endpt->req_hdr); … … 471 407 pj_list_insert_before( &endpt->req_hdr, mf_hdr); 472 408 473 /* Load and init modules. */474 status = init_modules(endpt);475 if (status != PJ_SUCCESS) {476 PJ_LOG(4, (THIS_FILE, "pjsip_endpt_init(): error in init_modules()"));477 return status;478 }479 480 409 /* Done. */ 481 410 *p_endpt = endpt; … … 491 420 endpt->mutex = NULL; 492 421 } 493 if (endpt-> tsx_table_mutex) {494 pj_ mutex_destroy(endpt->tsx_table_mutex);495 endpt-> tsx_table_mutex = NULL;422 if (endpt->mod_mutex) { 423 pj_rwmutex_destroy(endpt->mod_mutex); 424 endpt->mod_mutex = NULL; 496 425 } 497 426 pj_pool_release( endpt->pool ); … … 513 442 /* Delete endpoint mutex. */ 514 443 pj_mutex_destroy(endpt->mutex); 515 516 /* Delete transaction table mutex. */517 pj_mutex_destroy(endpt->tsx_table_mutex);518 444 519 445 /* Finally destroy pool. */ … … 625 551 626 552 /* 627 * Create a new transaction.628 * Endpoint must then initialize the new transaction as either UAS or UAC, and629 * register it to the hash table.630 */631 PJ_DEF(pj_status_t) pjsip_endpt_create_tsx(pjsip_endpoint *endpt,632 pjsip_transaction **p_tsx)633 {634 pj_pool_t *pool;635 636 PJ_ASSERT_RETURN(endpt && p_tsx, PJ_EINVAL);637 638 PJ_LOG(5, (THIS_FILE, "pjsip_endpt_create_tsx()"));639 640 /* Request one pool for the transaction. Mutex is locked there. */641 pool = pjsip_endpt_create_pool(endpt, "ptsx%p",642 PJSIP_POOL_LEN_TSX, PJSIP_POOL_INC_TSX);643 if (pool == NULL) {644 return PJ_ENOMEM;645 }646 647 /* Create the transaction. */648 return pjsip_tsx_create(pool, endpt, p_tsx);649 }650 651 /*652 * Register the transaction to the endpoint.653 * This will put the transaction to the transaction hash table. Before calling654 * this function, the transaction must be INITIALIZED as either UAS or UAC, so655 * that the transaction key is built.656 */657 PJ_DEF(void) pjsip_endpt_register_tsx( pjsip_endpoint *endpt,658 pjsip_transaction *tsx)659 {660 PJ_LOG(5, (THIS_FILE, "pjsip_endpt_register_tsx(%s)", tsx->obj_name));661 662 pj_assert(tsx->transaction_key.slen != 0);663 //pj_assert(tsx->state != PJSIP_TSX_STATE_NULL);664 665 /* Lock hash table mutex. */666 pj_mutex_lock(endpt->tsx_table_mutex);667 668 /* Register the transaction to the hash table. */669 pj_hash_set( tsx->pool, endpt->tsx_table, tsx->transaction_key.ptr,670 tsx->transaction_key.slen, tsx);671 672 /* Unlock mutex. */673 pj_mutex_unlock(endpt->tsx_table_mutex);674 }675 676 /*677 * Find transaction by the key.678 */679 PJ_DEF(pjsip_transaction*) pjsip_endpt_find_tsx( pjsip_endpoint *endpt,680 const pj_str_t *key )681 {682 pjsip_transaction *tsx;683 684 PJ_LOG(5, (THIS_FILE, "pjsip_endpt_find_tsx()"));685 686 /* Start lock mutex in the endpoint. */687 pj_mutex_lock(endpt->tsx_table_mutex);688 689 /* Find the transaction in the hash table. */690 tsx = pj_hash_get( endpt->tsx_table, key->ptr, key->slen );691 692 /* Unlock mutex. */693 pj_mutex_unlock(endpt->tsx_table_mutex);694 695 return tsx;696 }697 698 /*699 * Create key.700 */701 static void rdata_create_key( pjsip_rx_data *rdata)702 {703 pjsip_role_e role;704 if (rdata->msg_info.msg->type == PJSIP_REQUEST_MSG) {705 role = PJSIP_ROLE_UAS;706 } else {707 role = PJSIP_ROLE_UAC;708 }709 pjsip_tsx_create_key(rdata->tp_info.pool, &rdata->endpt_info.key, role,710 &rdata->msg_info.cseq->method, rdata);711 }712 713 /*714 553 * This is the callback that is called by the transport manager when it 715 554 * receives a message from the network. … … 720 559 { 721 560 pjsip_msg *msg = rdata->msg_info.msg; 722 pjsip_transaction *tsx;723 pj_bool_t a_new_transaction_just_been_created = PJ_FALSE;724 561 725 562 PJ_LOG(5, (THIS_FILE, "endpt_transport_callback(rdata=%p)", rdata)); 726 563 727 564 if (status != PJ_SUCCESS) { 728 const char *src_addr = rdata->pkt_info.src_name;729 int port = rdata->pkt_info.src_port;730 565 PJSIP_ENDPT_LOG_ERROR((endpt, "transport", status, 731 " Src.addr=%s:%d, packet:--\n"566 "Error processing packet from %s:%d, packet:--\n" 732 567 "%s\n" 733 "-- end of packet. Error", 734 src_addr, port, rdata->msg_info.msg_buf)); 568 "-- end of packet.", 569 rdata->pkt_info.src_name, 570 rdata->pkt_info.src_port, 571 rdata->msg_info.msg_buf)); 735 572 return; 736 573 } … … 741 578 */ 742 579 if (msg->type == PJSIP_RESPONSE_MSG) { 743 const pj_str_t * addr_addr;580 const pj_str_t *local_addr; 744 581 int port = rdata->msg_info.via->sent_by.port; 745 582 pj_bool_t mismatch = PJ_FALSE; … … 749 586 port = pjsip_transport_get_default_port_for_type(type); 750 587 } 751 addr_addr = &rdata->tp_info.transport->local_name.host;752 if (pj_strcmp(&rdata->msg_info.via->sent_by.host, addr_addr) != 0)588 local_addr = &rdata->tp_info.transport->local_name.host; 589 if (pj_strcmp(&rdata->msg_info.via->sent_by.host, local_addr) != 0) 753 590 mismatch = PJ_TRUE; 754 591 else if (port != rdata->tp_info.transport->local_name.port) { … … 760 597 * both the port in sent-by and rport. We try to be lenient here! 761 598 */ 762 if (rdata->msg_info.via->rport_param != rdata->tp_info.transport->local_name.port) 599 if (rdata->msg_info.via->rport_param != 600 rdata->tp_info.transport->local_name.port) 763 601 mismatch = PJ_TRUE; 764 602 else { 765 PJ_LOG(4,(THIS_FILE, "Response %p has mismatch port in sent-by" 766 " but the rport parameter is correct", 767 rdata)); 603 PJ_LOG(4,(THIS_FILE, "Response %p from %s has mismatch port in " 604 "sent-by but the rport parameter is " 605 "correct", 606 rdata, rdata->pkt_info.src_name)); 768 607 } 769 608 } 770 609 771 610 if (mismatch) { 772 pjsip_event e; 773 774 PJSIP_EVENT_INIT_DISCARD_MSG(e, rdata, PJSIP_EINVALIDVIA); 775 endpt_do_event( endpt, &e ); 611 PJ_TODO(ENDPT_REPORT_WHEN_DROPPING_MESSAGE); 612 PJ_LOG(4,(THIS_FILE, "Dropping response from %s:%d because sent-by" 613 " is mismatch", 614 rdata->pkt_info.src_name, 615 rdata->pkt_info.src_port)); 776 616 return; 777 617 } 778 } 779 780 /* Create key for transaction lookup. */ 781 rdata_create_key( rdata); 782 783 /* Find the transaction for the received message. */ 784 PJ_LOG(5, (THIS_FILE, "finding tsx with key=%.*s", 785 rdata->endpt_info.key.slen, rdata->endpt_info.key.ptr)); 786 787 /* Start lock mutex in the endpoint. */ 788 pj_mutex_lock(endpt->tsx_table_mutex); 789 790 /* Find the transaction in the hash table. */ 791 tsx = pj_hash_get( endpt->tsx_table, rdata->endpt_info.key.ptr, rdata->endpt_info.key.slen ); 792 793 /* Unlock mutex. */ 794 pj_mutex_unlock(endpt->tsx_table_mutex); 795 796 /* If the transaction is not found... */ 797 if (tsx == NULL || tsx->state == PJSIP_TSX_STATE_TERMINATED) { 798 799 /* 800 * For response message, discard the message, except if the response is 801 * an 2xx class response to INVITE, which in this case it must be 802 * passed to TU to be acked. 803 */ 804 if (msg->type == PJSIP_RESPONSE_MSG) { 805 806 /* Inform TU about the 200 message, only if it's INVITE. */ 807 if (PJSIP_IS_STATUS_IN_CLASS(msg->line.status.code, 200) && 808 rdata->msg_info.cseq->method.id == PJSIP_INVITE_METHOD) 809 { 810 pjsip_event e; 811 812 /* Should not happen for UA. Tsx theoritically lives until 813 * all responses are absorbed. 814 */ 815 pj_assert(0); 816 817 PJSIP_EVENT_INIT_RX_200_MSG(e, rdata); 818 endpt_do_event( endpt, &e ); 819 820 } else { 821 /* Just discard the response, inform TU. */ 822 pjsip_event e; 823 824 PJSIP_EVENT_INIT_DISCARD_MSG(e, rdata, 825 PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_CALL_TSX_DOES_NOT_EXIST)); 826 endpt_do_event( endpt, &e ); 827 } 828 829 /* 830 * For non-ACK request message, create a new transaction. 831 */ 832 } else if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) { 833 834 pj_status_t status; 835 836 /* Create transaction, mutex is locked there. */ 837 status = pjsip_endpt_create_tsx(endpt, &tsx); 838 if (status != PJ_SUCCESS) { 839 PJSIP_ENDPT_LOG_ERROR((endpt, THIS_FILE, status, 840 "Unable to create transaction")); 841 return; 842 } 843 844 /* Initialize transaction as UAS. */ 845 pjsip_tsx_init_uas( tsx, rdata ); 846 847 /* Register transaction, mutex is locked there. */ 848 pjsip_endpt_register_tsx( endpt, tsx ); 849 850 a_new_transaction_just_been_created = PJ_TRUE; 618 } 619 620 621 /* Distribute to modules. */ 622 pj_rwmutex_lock_read(endpt->mod_mutex); 623 624 if (msg->type == PJSIP_REQUEST_MSG) { 625 pjsip_module *mod; 626 pj_bool_t handled = PJ_FALSE; 627 628 mod = endpt->module_list.next; 629 while (mod != &endpt->module_list) { 630 if (mod->on_rx_request) 631 handled = (*mod->on_rx_request)(rdata); 632 if (handled) 633 break; 634 mod = mod->next; 851 635 } 852 } 853 854 /* If transaction is found (or newly created), pass the message. 855 * Otherwise if it's an ACK request, pass directly to TU. 856 */ 857 if (tsx && tsx->state != PJSIP_TSX_STATE_TERMINATED) { 858 /* Dispatch message to transaction. */ 859 pjsip_tsx_on_rx_msg( tsx, rdata ); 860 861 } else if (rdata->msg_info.msg->line.req.method.id == PJSIP_ACK_METHOD) { 862 /* 863 * This is an ACK message, but the INVITE transaction could not 864 * be found (possibly because the branch parameter in Via in ACK msg 865 * is different than the branch in original INVITE). This happens with 866 * SER! 867 */ 868 pjsip_event event; 869 870 PJSIP_EVENT_INIT_RX_ACK_MSG(event,rdata); 871 endpt_do_event( endpt, &event ); 872 } 873 874 /* 875 * If a new request message has just been receieved, but no modules 876 * seem to be able to handle the request message, then terminate the 877 * transaction. 878 * 879 * Ideally for cases like "unsupported method", we should be able to 880 * answer the request statelessly. But we can not do that since the 881 * endpoint shoule be able to be used as both user agent and proxy stack, 882 * and a proxy stack should be able to handle arbitrary methods. 883 */ 884 if (a_new_transaction_just_been_created && tsx->status_code < 100) { 885 /* Certainly no modules has sent any response message. 886 * Check that any modules has attached a module data. 887 */ 888 int i; 889 for (i=0; i<PJSIP_MAX_MODULE; ++i) { 890 if (tsx->module_data[i] != NULL) { 636 637 /* No module is able to handle the request. */ 638 if (!handled) { 639 PJ_TODO(ENDPT_RESPOND_UNHANDLED_REQUEST); 640 PJ_LOG(4,(THIS_FILE, "Request from %s:%d was dropped/unhandled by" 641 " any modules")); 642 } 643 644 } else { 645 pjsip_module *mod; 646 pj_bool_t handled = PJ_FALSE; 647 648 mod = endpt->module_list.next; 649 while (mod != &endpt->module_list) { 650 if (mod->on_rx_response) 651 handled = (*mod->on_rx_response)(rdata); 652 if (handled) 891 653 break; 892 }654 mod = mod->next; 893 655 } 894 if (i == PJSIP_MAX_MODULE) { 895 /* No modules have attached itself to the transaction. 896 * Terminate the transaction with 501/Not Implemented. 897 */ 898 pjsip_tx_data *tdata; 899 pj_status_t status; 900 901 if (tsx->method.id == PJSIP_OPTIONS_METHOD) { 902 status = pjsip_endpt_create_response(endpt, rdata, 200, 903 &tdata); 904 } else { 905 status = pjsip_endpt_create_response(endpt, rdata, 906 PJSIP_SC_METHOD_NOT_ALLOWED, 907 &tdata); 908 } 909 910 if (status != PJ_SUCCESS) { 911 PJSIP_ENDPT_LOG_ERROR((endpt, THIS_FILE, status, 912 "Unable to create response")); 913 return; 914 } 915 916 if (endpt->allow_hdr) { 917 pjsip_msg_add_hdr( tdata->msg, 918 pjsip_hdr_shallow_clone(tdata->pool, endpt->allow_hdr)); 919 } 920 pjsip_tsx_on_tx_msg( tsx, tdata ); 921 922 } else { 923 /* 924 * If a module has registered itself in the transaction but it 925 * hasn't responded the request, chances are the module wouldn't 926 * respond to the request at all. We terminate the request here 927 * with 500/Internal Server Error, to be safe. 928 */ 929 pjsip_tx_data *tdata; 930 pj_status_t status; 931 932 status = pjsip_endpt_create_response(endpt, rdata, 500, &tdata); 933 if (status != PJ_SUCCESS) { 934 PJSIP_ENDPT_LOG_ERROR((endpt, THIS_FILE, status, 935 "Unable to create response")); 936 return; 937 } 938 939 pjsip_tsx_on_tx_msg(tsx, tdata); 656 657 if (!handled) { 658 PJ_LOG(4,(THIS_FILE, "Response from %s:%d was dropped/unhandled by" 659 " any modules")); 940 660 } 941 661 } 662 663 pj_rwmutex_unlock_read(endpt->mod_mutex); 942 664 } 943 665 … … 984 706 * Find/create transport. 985 707 */ 986 PJ_DEF(pj_status_t) pjsip_endpt_a lloc_transport(pjsip_endpoint *endpt,708 PJ_DEF(pj_status_t) pjsip_endpt_acquire_transport(pjsip_endpoint *endpt, 987 709 pjsip_transport_type_e type, 988 const pj_sockaddr *remote,710 const pj_sockaddr_t *remote, 989 711 int addr_len, 990 pjsip_transport ** p_transport)991 { 992 PJ_LOG(5, (THIS_FILE, "pjsip_endpt_a lloc_transport()"));993 return pjsip_tpmgr_a lloc_transport(endpt->transport_mgr, type,994 remote, addr_len, p_transport);712 pjsip_transport **transport) 713 { 714 PJ_LOG(5, (THIS_FILE, "pjsip_endpt_acquire_transport()")); 715 return pjsip_tpmgr_acquire_transport(endpt->transport_mgr, type, 716 remote, addr_len, transport); 995 717 } 996 718 … … 1050 772 { 1051 773 #if PJ_LOG_MAX_LEVEL >= 3 1052 unsigned count;1053 1054 774 PJ_LOG(5, (THIS_FILE, "pjsip_endpt_dump()")); 1055 775 … … 1066 786 pj_pool_get_capacity(endpt->pool), 1067 787 pj_pool_get_used_size(endpt->pool))); 1068 1069 /* Transaction tables. */1070 count = pj_hash_count(endpt->tsx_table);1071 PJ_LOG(3, (THIS_FILE, " Number of transactions: %u", count));1072 1073 if (count && detail) {1074 pj_hash_iterator_t it_val;1075 pj_hash_iterator_t *it;1076 pj_time_val now;1077 1078 PJ_LOG(3, (THIS_FILE, " Dumping transaction tables:"));1079 1080 pj_gettimeofday(&now);1081 it = pj_hash_first(endpt->tsx_table, &it_val);1082 1083 while (it != NULL) {1084 int timeout_diff;1085 1086 /* Get the transaction. No need to lock transaction's mutex1087 * since we already hold endpoint mutex, so that no transactions1088 * will be deleted.1089 */1090 pjsip_transaction *tsx = pj_hash_this(endpt->tsx_table, it);1091 1092 const char *role = (tsx->role == PJSIP_ROLE_UAS ? "UAS" : "UAC");1093 1094 if (tsx->timeout_timer._timer_id != -1) {1095 if (tsx->timeout_timer._timer_value.sec > now.sec) {1096 timeout_diff = tsx->timeout_timer._timer_value.sec - now.sec;1097 } else {1098 timeout_diff = now.sec - tsx->timeout_timer._timer_value.sec;1099 timeout_diff = 0 - timeout_diff;1100 }1101 } else {1102 timeout_diff = -1;1103 }1104 1105 PJ_LOG(3, (THIS_FILE, " %s %s %10.*s %.9u %s t=%ds",1106 tsx->obj_name, role,1107 tsx->method.name.slen, tsx->method.name.ptr,1108 tsx->cseq,1109 pjsip_tsx_state_str(tsx->state),1110 timeout_diff));1111 1112 it = pj_hash_next(endpt->tsx_table, it);1113 }1114 }1115 788 1116 789 /* Transports. -
pjproject/trunk/pjsip/src/pjsip/sip_errno.c
r65 r106 40 40 { PJSIP_EMSGTOOLONG, "Message too long" }, 41 41 { PJSIP_EPARTIALMSG, "Partial message" }, 42 { PJSIP_EMISSINGREQURI, "Missing Request-URI" }, 42 43 { PJSIP_EMISSINGHDR, "Missing required header(s)" }, 44 { PJSIP_EMISSINGBODY, "Missing message body" }, 43 45 { PJSIP_EINVALIDVIA, "Invalid Via header" }, 44 46 { PJSIP_EMULTIPLEVIA, "Multiple Via headers in response" }, 47 { PJSIP_EINVALIDREQURI, "Invalid Request URI" }, 48 { PJSIP_ENOTREQUESTMSG, "Expecting request message"}, 49 { PJSIP_ENOTRESPONSEMSG, "Expecting response message"}, 45 50 46 51 /* Transport errors */ … … 48 53 { PJSIP_EPENDINGTX, "Transmit buffer already pending"}, 49 54 { PJSIP_ERXOVERFLOW, "Rx buffer overflow"}, 55 { PJSIP_EBUFDESTROYED, "Buffer destroyed"}, 50 56 51 57 /* Transaction errors */ -
pjproject/trunk/pjsip/src/pjsip/sip_msg.c
r82 r106 22 22 #include <pj/string.h> 23 23 #include <pj/pool.h> 24 #include <pj/assert.h> 24 25 25 26 /* … … 30 31 #endif 31 32 32 static const pj_str_t method_names[] = 33 { 34 { "INVITE", 6 }, 35 { "CANCEL", 6 }, 36 { "ACK", 3 }, 37 { "BYE", 3 }, 38 { "REGISTER", 8 }, 39 { "OPTIONS", 7 }, 33 const pjsip_method 34 pjsip_invite_method = { PJSIP_INVITE_METHOD, { "INVITE",6 } }, 35 pjsip_cancel_method = { PJSIP_CANCEL_METHOD, { "CANCEL",6 } }, 36 pjsip_ack_method = { PJSIP_ACK_METHOD, { "ACK",3} }, 37 pjsip_bye_method = { PJSIP_BYE_METHOD, { "BYE",3} }, 38 pjsip_register_method = { PJSIP_REGISTER_METHOD, { "REGISTER",8} }, 39 pjsip_options_method = { PJSIP_OPTIONS_METHOD, { "OPTIONS",7} }; 40 41 static const pj_str_t *method_names[] = 42 { 43 &pjsip_invite_method.name, 44 &pjsip_cancel_method.name, 45 &pjsip_ack_method.name, 46 &pjsip_bye_method.name, 47 &pjsip_register_method.name, 48 &pjsip_options_method.name 40 49 }; 41 50 … … 179 188 PJ_DEF(void) pjsip_method_set( pjsip_method *m, pjsip_method_e me ) 180 189 { 190 pj_assert(me < PJSIP_OTHER_METHOD); 181 191 m->id = me; 182 m->name = method_names[me];192 m->name = *method_names[me]; 183 193 } 184 194 … … 188 198 int i; 189 199 for (i=0; i<PJ_ARRAY_SIZE(method_names); ++i) { 190 if (pj_stricmp(str, &method_names[i])==0) {200 if (pj_stricmp(str, method_names[i])==0) { 191 201 m->id = (pjsip_method_e)i; 192 m->name = method_names[i];202 m->name = *method_names[i]; 193 203 return; 194 204 } … … 236 246 } 237 247 238 PJ_DEF(void*) pjsip_msg_find_hdr( pjsip_msg *msg,239 pjsip_hdr_e hdr_type, void *start)240 { 241 pjsip_hdr *hdr=start, *end=&msg->hdr;248 PJ_DEF(void*) pjsip_msg_find_hdr( const pjsip_msg *msg, 249 pjsip_hdr_e hdr_type, const void *start) 250 { 251 const pjsip_hdr *hdr=start, *end=&msg->hdr; 242 252 243 253 if (hdr == NULL) { … … 246 256 for (; hdr!=end; hdr = hdr->next) { 247 257 if (hdr->type == hdr_type) 248 return hdr;258 return (void*)hdr; 249 259 } 250 260 return NULL; 251 261 } 252 262 253 PJ_DEF(void*) pjsip_msg_find_hdr_by_name( pjsip_msg *msg, 254 const pj_str_t *name, void *start) 255 { 256 pjsip_hdr *hdr=start, *end=&msg->hdr; 263 PJ_DEF(void*) pjsip_msg_find_hdr_by_name( const pjsip_msg *msg, 264 const pj_str_t *name, 265 const void *start) 266 { 267 const pjsip_hdr *hdr=start, *end=&msg->hdr; 257 268 258 269 if (hdr == NULL) { … … 262 273 if (hdr->type < PJSIP_H_OTHER) { 263 274 if (pj_stricmp(&pjsip_hdr_names[hdr->type], name) == 0) 264 return hdr;275 return (void*)hdr; 265 276 } else { 266 277 if (pj_stricmp(&hdr->name, name) == 0) 267 return hdr;278 return (void*)hdr; 268 279 } 269 280 } … … 281 292 } 282 293 283 PJ_DEF(pj_ssize_t) pjsip_msg_print( pjsip_msg *msg, char *buf, pj_size_t size) 294 PJ_DEF(pj_ssize_t) pjsip_msg_print( const pjsip_msg *msg, 295 char *buf, pj_size_t size) 284 296 { 285 297 char *p=buf, *end=buf+size; … … 1350 1362 pjsip_via_hdr *hdr = pj_pool_calloc(pool, 1, sizeof(*hdr)); 1351 1363 init_hdr(hdr, PJSIP_H_VIA, &via_hdr_vptr); 1352 hdr->sent_by.port = 5060;1364 //hdr->sent_by.port = 5060; 1353 1365 hdr->ttl_param = -1; 1354 1366 hdr->rport_param = -1; … … 1384 1396 pj_memcpy(buf, hdr->sent_by.host.ptr, hdr->sent_by.host.slen); 1385 1397 buf += hdr->sent_by.host.slen; 1386 *buf++ = ':'; 1387 printed = pj_utoa(hdr->sent_by.port, buf); 1388 buf += printed; 1398 if (hdr->sent_by.port != 0) { 1399 *buf++ = ':'; 1400 printed = pj_utoa(hdr->sent_by.port, buf); 1401 buf += printed; 1402 } 1389 1403 1390 1404 if (hdr->ttl_param >= 0) { -
pjproject/trunk/pjsip/src/pjsip/sip_parser.c
r82 r106 1783 1783 pj_scan_get(scanner, &pjsip_DIGIT_SPEC, &digit); 1784 1784 hdr->sent_by.port = pj_strtoul(&digit); 1785 } else {1786 hdr->sent_by.port = 5060;1787 1785 } 1788 1786 -
pjproject/trunk/pjsip/src/pjsip/sip_transaction.c
r105 r106 30 30 #include <pj/pool.h> 31 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 32 422 33 423 /* Thread Local Storage ID for transaction lock (initialized by endpoint) */ … … 153 543 return role_name[role]; 154 544 } 545 546 547 548 /* 549 * Unregister the transaction from the hash table, and destroy the resources 550 * 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, which 561 * 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 155 584 156 585 … … 501 930 pjsip_host_info *send_addr ) 502 931 { 503 const pjsip_uri *new_request_uri, *target_uri; 504 const pjsip_name_addr *topmost_route_uri; 505 pjsip_route_hdr *first_route_hdr, *last_route_hdr; 932 pjsip_route_hdr *route_hdr; 506 933 507 934 pj_assert(tdata->msg->type == PJSIP_REQUEST_MSG); … … 511 938 * headers from the endpoint first. 512 939 */ 513 last_route_hdr = first_route_hdr = 514 pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE, NULL); 515 if (first_route_hdr) { 516 topmost_route_uri = &first_route_hdr->name_addr; 517 while (last_route_hdr->next != (void*)&tdata->msg->hdr) { 518 pjsip_route_hdr *hdr; 519 hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE, 520 last_route_hdr->next); 521 if (!hdr) 522 break; 523 last_route_hdr = hdr; 524 } 525 } else { 940 route_hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE, NULL); 941 if (!route_hdr) { 526 942 const pjsip_route_hdr *hdr_list; 527 hdr_list = (pjsip_route_hdr*)pjsip_endpt_get_routing(tsx->endpt); 528 if (hdr_list->next != hdr_list) { 529 const pjsip_route_hdr *hdr = (pjsip_route_hdr*)hdr_list->next; 530 first_route_hdr = NULL; 531 topmost_route_uri = &hdr->name_addr; 532 do { 533 last_route_hdr = pjsip_hdr_shallow_clone(tdata->pool, hdr); 534 if (first_route_hdr == NULL) 535 first_route_hdr = last_route_hdr; 536 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)last_route_hdr); 537 hdr = hdr->next; 538 } while (hdr != hdr_list); 539 } else { 540 topmost_route_uri = NULL; 541 } 542 } 543 544 /* If Route headers exist, and the first element indicates loose-route, 545 * the URI is taken from the Request-URI, and we keep all existing Route 546 * headers intact. 547 * If Route headers exist, and the first element DOESN'T indicate loose 548 * route, the URI is taken from the first Route header, and remove the 549 * first Route header from the message. 550 * Otherwise if there's no Route headers, the URI is taken from the 551 * Request-URI. 552 */ 553 if (topmost_route_uri) { 554 pj_bool_t has_lr_param; 555 556 if (PJSIP_URI_SCHEME_IS_SIP(topmost_route_uri) || 557 PJSIP_URI_SCHEME_IS_SIPS(topmost_route_uri)) 558 { 559 const pjsip_url *url = pjsip_uri_get_uri((void*)topmost_route_uri); 560 has_lr_param = url->lr_param; 561 } else { 562 has_lr_param = 0; 563 } 564 565 if (has_lr_param) { 566 new_request_uri = tdata->msg->line.req.uri; 567 /* We shouldn't need to delete topmost Route if it has lr param. 568 * But seems like it breaks some proxy implementation, so we 569 * delete it anyway. 570 */ 571 /* 572 pj_list_erase(first_route_hdr); 573 if (first_route_hdr == last_route_hdr) 574 last_route_hdr = NULL; 575 */ 576 } else { 577 new_request_uri = pjsip_uri_get_uri((void*)topmost_route_uri); 578 pj_list_erase(first_route_hdr); 579 if (first_route_hdr == last_route_hdr) 580 last_route_hdr = NULL; 581 } 582 583 target_uri = (pjsip_uri*)topmost_route_uri; 584 585 } else { 586 target_uri = new_request_uri = tdata->msg->line.req.uri; 587 } 588 589 /* The target URI must be a SIP/SIPS URL so we can resolve it's address. 590 * Otherwise we're in trouble (i.e. there's no host part in tel: URL). 591 */ 592 pj_memset(send_addr, 0, sizeof(*send_addr)); 593 594 if (PJSIP_URI_SCHEME_IS_SIPS(target_uri)) { 595 pjsip_uri *uri = (pjsip_uri*) target_uri; 596 const pjsip_url *url = (const pjsip_url*)pjsip_uri_get_uri(uri); 597 send_addr->flag |= (PJSIP_TRANSPORT_SECURE | PJSIP_TRANSPORT_RELIABLE); 598 pj_strdup(tdata->pool, &send_addr->addr.host, &url->host); 599 send_addr->addr.port = url->port; 600 send_addr->type = 601 pjsip_transport_get_type_from_name(&url->transport_param); 602 603 } else if (PJSIP_URI_SCHEME_IS_SIP(target_uri)) { 604 pjsip_uri *uri = (pjsip_uri*) target_uri; 605 const pjsip_url *url = (const pjsip_url*)pjsip_uri_get_uri(uri); 606 pj_strdup(tdata->pool, &send_addr->addr.host, &url->host); 607 send_addr->addr.port = url->port; 608 send_addr->type = 609 pjsip_transport_get_type_from_name(&url->transport_param); 610 #if PJ_HAS_TCP 611 if (send_addr->type == PJSIP_TRANSPORT_TCP || 612 send_addr->type == PJSIP_TRANSPORT_SCTP) 613 { 614 send_addr->flag |= PJSIP_TRANSPORT_RELIABLE; 615 } 616 #endif 617 } else { 618 pj_assert(!"Unsupported URI scheme!"); 619 return PJSIP_EINVALIDSCHEME; 620 } 621 622 /* If target URI is different than request URI, replace 623 * request URI add put the original URI in the last Route header. 624 */ 625 if (new_request_uri && new_request_uri!=tdata->msg->line.req.uri) { 626 pjsip_route_hdr *route = pjsip_route_hdr_create(tdata->pool); 627 route->name_addr.uri = tdata->msg->line.req.uri; 628 if (last_route_hdr) 629 pj_list_insert_after(last_route_hdr, route); 630 else 631 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)route); 632 tdata->msg->line.req.uri = (pjsip_uri*)new_request_uri; 633 } 634 635 /* Success. */ 636 return PJ_SUCCESS; 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); 637 954 } 638 955 -
pjproject/trunk/pjsip/src/pjsip/sip_transport.c
r105 r106 44 44 pjsip_endpoint *endpt; 45 45 pjsip_tpfactory factory_list; 46 #if defined(PJ_DEBUG) && PJ_DEBUG!=0 47 pj_atomic_t *tdata_counter; 48 #endif 46 49 void (*msg_cb)(pjsip_endpoint*, pj_status_t, pjsip_rx_data*); 47 50 }; … … 205 208 pj_ioqueue_op_key_init(&tdata->op_key.key, sizeof(tdata->op_key)); 206 209 210 #if defined(PJ_DEBUG) && PJ_DEBUG!=0 211 pj_atomic_inc( tdata->mgr->tdata_counter ); 212 #endif 213 207 214 *p_tdata = tdata; 208 215 return PJ_SUCCESS; … … 222 229 * reaches zero. 223 230 */ 224 PJ_DEF( void) pjsip_tx_data_dec_ref( pjsip_tx_data *tdata )231 PJ_DEF(pj_status_t) pjsip_tx_data_dec_ref( pjsip_tx_data *tdata ) 225 232 { 226 233 pj_assert( pj_atomic_get(tdata->ref_cnt) > 0); 227 234 if (pj_atomic_dec_and_get(tdata->ref_cnt) <= 0) { 228 235 PJ_LOG(5,(tdata->obj_name, "destroying txdata")); 236 #if defined(PJ_DEBUG) && PJ_DEBUG!=0 237 pj_atomic_dec( tdata->mgr->tdata_counter ); 238 #endif 229 239 pj_atomic_destroy( tdata->ref_cnt ); 230 240 pj_lock_destroy( tdata->lock ); 231 241 pjsip_endpt_destroy_pool( tdata->mgr->endpt, tdata->pool ); 242 return PJSIP_EBUFDESTROYED; 243 } else { 244 return PJ_SUCCESS; 232 245 } 233 246 } … … 453 466 * Unregister timer, if any. 454 467 */ 455 pj_assert(tp->idle_timer.id == PJ_FALSE);468 //pj_assert(tp->idle_timer.id == PJ_FALSE); 456 469 if (tp->idle_timer.id != PJ_FALSE) { 457 470 pjsip_endpt_cancel_timer(mgr->endpt, &tp->idle_timer); … … 567 580 return status; 568 581 582 #if defined(PJ_DEBUG) && PJ_DEBUG!=0 583 status = pj_atomic_create(pool, 0, &mgr->tdata_counter); 584 if (status != PJ_SUCCESS) 585 return status; 586 #endif 587 569 588 *p_mgr = mgr; 570 589 return PJ_SUCCESS; … … 582 601 583 602 PJ_LOG(5, (THIS_FILE, "pjsip_tpmgr_destroy()")); 603 604 #if defined(PJ_DEBUG) && PJ_DEBUG!=0 605 pj_assert(pj_atomic_get(mgr->tdata_counter) == 0); 606 #endif 584 607 585 608 pj_lock_acquire(mgr->lock); … … 601 624 602 625 pj_lock_release(mgr->lock); 626 pj_lock_destroy(mgr->lock); 603 627 604 628 return PJ_SUCCESS; … … 742 766 743 767 /* 744 * pjsip_tpmgr_a lloc_transport()768 * pjsip_tpmgr_acquire_transport() 745 769 * 746 770 * Get transport suitable to communicate to remote. Create a new one 747 771 * if necessary. 748 772 */ 749 PJ_DEF(pj_status_t) pjsip_tpmgr_a lloc_transport(pjsip_tpmgr *mgr,750 pjsip_transport_type_e type,751 const pj_sockaddr_t *remote,752 int addr_len,753 pjsip_transport **p_transport)773 PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport(pjsip_tpmgr *mgr, 774 pjsip_transport_type_e type, 775 const pj_sockaddr_t *remote, 776 int addr_len, 777 pjsip_transport **tp) 754 778 { 755 779 struct transport_key … … 799 823 pjsip_transport_add_ref(transport); 800 824 pj_lock_release(mgr->lock); 801 * p_transport= transport;825 *tp = transport; 802 826 return PJ_SUCCESS; 803 827 } … … 822 846 /* Request factory to create transport. */ 823 847 status = factory->create_transport(factory, mgr, mgr->endpt, 824 remote, p_transport); 825 848 remote, addr_len, tp); 849 if (status == PJ_SUCCESS) { 850 PJ_ASSERT_ON_FAIL(tp!=NULL, 851 {pj_lock_release(mgr->lock); return PJ_EBUG;}); 852 pjsip_transport_add_ref(*tp); 853 } 826 854 pj_lock_release(mgr->lock); 827 855 return status; -
pjproject/trunk/pjsip/src/pjsip/sip_transport_udp.c
r105 r106 22 22 #include <pj/pool.h> 23 23 #include <pj/sock.h> 24 #include <pj/addr_resolv.h> 24 25 #include <pj/os.h> 25 26 #include <pj/lock.h> … … 268 269 pj_status_t status; 269 270 271 PJ_ASSERT_RETURN(endpt && sock!=PJ_INVALID_SOCKET && a_name && async_cnt>0, 272 PJ_EINVAL); 273 270 274 /* Create pool. */ 271 275 pool = pjsip_endpt_create_pool(endpt, "udp%p", PJSIP_POOL_LEN_TRANSPORT, … … 328 332 pj_inet_ntoa(((pj_sockaddr_in*)&tp->base.local_addr)->sin_addr), 329 333 pj_ntohs(((pj_sockaddr_in*)&tp->base.local_addr)->sin_port), 330 tp->base.local_name.host ,334 tp->base.local_name.host.ptr, 331 335 tp->base.local_name.port); 332 336 … … 368 372 /* Create rdata and put it in the array. */ 369 373 tp->rdata_cnt = 0; 374 tp->rdata = pj_pool_calloc(tp->base.pool, async_cnt, 375 sizeof(pjsip_rx_data*)); 370 376 for (i=0; i<async_cnt; ++i) { 371 377 pj_pool_t *rdata_pool = pjsip_endpt_create_pool(endpt, "rtd%p", … … 383 389 tp->rdata[i]->tp_info.pool = rdata_pool; 384 390 tp->rdata[i]->tp_info.transport = &tp->base; 391 tp->rdata[i]->tp_info.op_key.rdata = tp->rdata[i]; 385 392 pj_ioqueue_op_key_init(&tp->rdata[i]->tp_info.op_key.op_key, 386 393 sizeof(pj_ioqueue_op_key_t)); … … 437 444 pjsip_host_port bound_name; 438 445 446 PJ_ASSERT_RETURN(local != NULL, PJ_EINVAL); 447 439 448 status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock); 440 449 if (status != PJ_SUCCESS) … … 448 457 449 458 if (a_name == NULL) { 459 /* Address name is not specified. 460 * Build a name based on bound address. 461 */ 450 462 a_name = &bound_name; 451 463 bound_name.host.ptr = addr_buf; 452 pj_strcpy2(&bound_name.host, pj_inet_ntoa(local->sin_addr));453 464 bound_name.port = pj_ntohs(local->sin_port); 465 466 /* If bound address specifies "0.0.0.0", get the IP address 467 * of local hostname. 468 */ 469 if (local->sin_addr.s_addr == PJ_INADDR_ANY) { 470 pj_hostent he; 471 const pj_str_t *hostname = pj_gethostname(); 472 status = pj_gethostbyname(hostname, &he); 473 if (status != PJ_SUCCESS) { 474 pj_sock_close(sock); 475 return status; 476 } 477 pj_strcpy2(&bound_name.host, 478 pj_inet_ntoa(*(pj_in_addr*)he.h_addr)); 479 } else { 480 /* Otherwise use bound address. */ 481 pj_strcpy2(&bound_name.host, pj_inet_ntoa(local->sin_addr)); 482 } 483 454 484 } 455 485 -
pjproject/trunk/pjsip/src/pjsip/sip_util.c
r105 r106 24 24 #include <pjsip/sip_transaction.h> 25 25 #include <pjsip/sip_module.h> 26 #include <pjsip/sip_errno.h> 26 27 #include <pj/log.h> 27 28 #include <pj/string.h> … … 52 53 static pj_str_t str_TEXT = { "text", 4}, 53 54 str_PLAIN = { "plain", 5 }; 54 static int aux_mod_id;55 56 struct aux_tsx_data57 {58 void *token;59 void (*cb)(void*,pjsip_event*);60 };61 62 static pj_status_t aux_tsx_init( pjsip_endpoint *endpt,63 struct pjsip_module *mod, pj_uint32_t id )64 {65 PJ_UNUSED_ARG(endpt);66 PJ_UNUSED_ARG(mod);67 68 aux_mod_id = id;69 return 0;70 }71 72 static void aux_tsx_handler( struct pjsip_module *mod, pjsip_event *event )73 {74 pjsip_transaction *tsx;75 struct aux_tsx_data *tsx_data;76 77 PJ_UNUSED_ARG(mod);78 79 if (event->type != PJSIP_EVENT_TSX_STATE)80 return;81 82 pj_assert(event->body.tsx_state.tsx != NULL);83 tsx = event->body.tsx_state.tsx;84 if (tsx == NULL)85 return;86 if (tsx->module_data[aux_mod_id] == NULL)87 return;88 if (tsx->status_code < 200)89 return;90 91 /* Call the callback, if any, and prevent the callback to be called again92 * by clearing the transaction's module_data.93 */94 tsx_data = tsx->module_data[aux_mod_id];95 tsx->module_data[aux_mod_id] = NULL;96 97 if (tsx_data->cb) {98 (*tsx_data->cb)(tsx_data->token, event);99 }100 }101 102 pjsip_module aux_tsx_module =103 {104 { "Aux-Tsx", 7}, /* Name. */105 0, /* Flag */106 128, /* Priority */107 NULL, /* Arbitrary data. */108 0, /* Number of methods supported (none). */109 { 0 }, /* Array of methods (none) */110 &aux_tsx_init, /* init_module() */111 NULL, /* start_module() */112 NULL, /* deinit_module() */113 &aux_tsx_handler, /* tsx_handler() */114 };115 116 PJ_DEF(pj_status_t) pjsip_endpt_send_request( pjsip_endpoint *endpt,117 pjsip_tx_data *tdata,118 int timeout,119 void *token,120 void (*cb)(void*,pjsip_event*))121 {122 pjsip_transaction *tsx;123 struct aux_tsx_data *tsx_data;124 pj_status_t status;125 126 status = pjsip_endpt_create_tsx(endpt, &tsx);127 if (!tsx) {128 pjsip_tx_data_dec_ref(tdata);129 return -1;130 }131 132 tsx_data = pj_pool_alloc(tsx->pool, sizeof(struct aux_tsx_data));133 tsx_data->token = token;134 tsx_data->cb = cb;135 tsx->module_data[aux_mod_id] = tsx_data;136 137 if (pjsip_tsx_init_uac(tsx, tdata) != 0) {138 pjsip_endpt_destroy_tsx(endpt, tsx);139 pjsip_tx_data_dec_ref(tdata);140 return -1;141 }142 143 pjsip_endpt_register_tsx(endpt, tsx);144 pjsip_tx_data_invalidate_msg(tdata);145 pjsip_tsx_on_tx_msg(tsx, tdata);146 pjsip_tx_data_dec_ref(tdata);147 return 0;148 }149 55 150 56 /* … … 170 76 pjsip_msg *msg; 171 77 pjsip_msg_body *body; 78 pjsip_via_hdr *via; 172 79 const pjsip_hdr *endpt_hdr; 173 80 … … 205 112 /* Add CSeq header. */ 206 113 pjsip_msg_add_hdr(msg, (void*)param_cseq); 114 115 /* Add a blank Via header. */ 116 via = pjsip_via_hdr_create(tdata->pool); 117 via->rport_param = 0; 118 pjsip_msg_insert_first_hdr(msg, (void*)via); 207 119 208 120 /* Create message body. */ … … 217 129 msg->body = body; 218 130 } 131 132 PJ_LOG(4,(THIS_FILE, "Request %s (CSeq=%d/%.*s) created.", 133 tdata->obj_name, 134 param_cseq->cseq, 135 param_cseq->method.name.slen, 136 param_cseq->method.name.ptr)); 137 219 138 } 220 139 … … 329 248 PJ_END 330 249 331 PJ_LOG(4,(THIS_FILE, "Request %s (%d %.*s) created.",332 tdata->obj_name,333 cseq->cseq,334 cseq->method.name.slen,335 cseq->method.name.ptr));336 337 250 *p_tdata = tdata; 338 251 return PJ_SUCCESS; … … 367 280 PJ_LOG(5,(THIS_FILE, "Entering pjsip_endpt_create_request_from_hdr()")); 368 281 282 /* Check arguments. */ 283 PJ_ASSERT_RETURN(endpt && method && param_target && param_from && 284 param_to && p_tdata, PJ_EINVAL); 285 286 /* Create new transmit data. */ 369 287 status = pjsip_endpt_create_tdata(endpt, &tdata); 370 288 if (status != PJ_SUCCESS) 371 289 return status; 372 290 291 /* Set initial reference counter to 1. */ 373 292 pjsip_tx_data_add_ref(tdata); 374 293 375 294 PJ_TRY { 295 /* Duplicate target URI and headers. */ 376 296 target = pjsip_uri_clone(tdata->pool, param_target); 377 from = pjsip_hdr_ shallow_clone(tdata->pool, param_from);297 from = pjsip_hdr_clone(tdata->pool, param_from); 378 298 pjsip_fromto_set_from(from); 379 to = pjsip_hdr_ shallow_clone(tdata->pool, param_to);299 to = pjsip_hdr_clone(tdata->pool, param_to); 380 300 pjsip_fromto_set_to(to); 381 301 if (param_contact) 382 contact = pjsip_hdr_ shallow_clone(tdata->pool, param_contact);302 contact = pjsip_hdr_clone(tdata->pool, param_contact); 383 303 else 384 304 contact = NULL; 385 call_id = pjsip_hdr_ shallow_clone(tdata->pool, param_call_id);305 call_id = pjsip_hdr_clone(tdata->pool, param_call_id); 386 306 cseq = pjsip_cseq_hdr_create(tdata->pool); 387 307 if (param_cseq >= 0) … … 391 311 pjsip_method_copy(tdata->pool, &cseq->method, method); 392 312 313 /* Copy headers to the request. */ 393 314 init_request_throw(endpt, tdata, &cseq->method, target, from, to, 394 315 contact, call_id, cseq, param_text); … … 400 321 PJ_END; 401 322 402 PJ_LOG(4,(THIS_FILE, "Request %s (%d %.*s) created.",403 tdata->obj_name,404 cseq->cseq,405 cseq->method.name.slen,406 cseq->method.name.ptr));407 408 323 *p_tdata = tdata; 409 324 return PJ_SUCCESS; … … 419 334 PJ_DEF(pj_status_t) pjsip_endpt_create_response( pjsip_endpoint *endpt, 420 335 const pjsip_rx_data *rdata, 421 int code, 336 int st_code, 337 const pj_str_t *st_text, 422 338 pjsip_tx_data **p_tdata) 423 339 { … … 435 351 /* Log this action. */ 436 352 PJ_LOG(5,(THIS_FILE, "pjsip_endpt_create_response(rdata=%p, code=%d)", 437 rdata, code));353 rdata, st_code)); 438 354 439 355 /* Create a new transmit buffer. */ … … 442 358 return status; 443 359 360 /* Set initial reference count to 1. */ 361 pjsip_tx_data_add_ref(tdata); 362 444 363 /* Create new response message. */ 445 364 tdata->msg = msg = pjsip_msg_create(tdata->pool, PJSIP_RESPONSE_MSG); 446 365 447 366 /* Set status code and reason text. */ 448 msg->line.status.code = code; 449 msg->line.status.reason = *pjsip_get_status_text(code); 367 msg->line.status.code = st_code; 368 if (st_text) 369 pj_strdup(tdata->pool, &msg->line.status.reason, st_text); 370 else 371 msg->line.status.reason = *pjsip_get_status_text(st_code); 450 372 451 373 /* Set TX data attributes. */ … … 501 423 * and one must not use this function to generate such ACK. 502 424 */ 503 PJ_DEF(void) pjsip_endpt_create_ack(pjsip_endpoint *endpt, 504 pjsip_tx_data *tdata, 505 const pjsip_rx_data *rdata ) 506 { 507 pjsip_msg *ack_msg, *invite_msg; 425 PJ_DEF(pj_status_t) pjsip_endpt_create_ack( pjsip_endpoint *endpt, 426 const pjsip_tx_data *tdata, 427 const pjsip_rx_data *rdata, 428 pjsip_tx_data **ack_tdata) 429 { 430 pjsip_tx_data *ack = NULL; 431 const pjsip_msg *invite_msg; 432 const pjsip_from_hdr *from_hdr; 433 const pjsip_to_hdr *to_hdr; 434 const pjsip_cid_hdr *cid_hdr; 435 const pjsip_cseq_hdr *cseq_hdr; 436 const pjsip_hdr *hdr; 508 437 pjsip_to_hdr *to; 509 pjsip_from_hdr *from; 510 pjsip_cseq_hdr *cseq; 511 pjsip_hdr *hdr; 512 513 /* Make compiler happy. */ 514 PJ_UNUSED_ARG(endpt); 438 pj_status_t status; 439 440 /* Log this action. */ 441 PJ_LOG(5,(THIS_FILE, "pjsip_endpt_create_ack(rdata=%p)", rdata)); 515 442 516 443 /* rdata must be a final response. */ … … 518 445 rdata->msg_info.msg->line.status.code >= 300); 519 446 520 /* Log this action. */ 521 PJ_LOG(5,(THIS_FILE, "pjsip_endpt_create_ack(rdata=%p)", rdata)); 522 523 /* Create new request message. */ 524 ack_msg = pjsip_msg_create(tdata->pool, PJSIP_REQUEST_MSG); 525 pjsip_method_set( &ack_msg->line.req.method, PJSIP_ACK_METHOD ); 447 /* Initialize return value to NULL. */ 448 *ack_tdata = NULL; 526 449 527 450 /* The original INVITE message. */ 528 451 invite_msg = tdata->msg; 529 452 530 /* Copy Request-Uri from the original INVITE. */ 531 ack_msg->line.req.uri = invite_msg->line.req.uri; 532 533 /* Copy Call-ID from the original INVITE */ 534 hdr = pjsip_msg_find_remove_hdr( invite_msg, PJSIP_H_CALL_ID, NULL); 535 pjsip_msg_add_hdr( ack_msg, hdr ); 536 537 /* Copy From header from the original INVITE. */ 538 from = (pjsip_from_hdr*)pjsip_msg_find_remove_hdr(invite_msg, 539 PJSIP_H_FROM, NULL); 540 pjsip_msg_add_hdr( ack_msg, (pjsip_hdr*)from ); 541 542 /* Copy To header from the original INVITE. */ 543 to = (pjsip_to_hdr*)pjsip_msg_find_remove_hdr( invite_msg, 544 PJSIP_H_TO, NULL); 545 pj_strdup(tdata->pool, &to->tag, &rdata->msg_info.to->tag); 546 pjsip_msg_add_hdr( ack_msg, (pjsip_hdr*)to ); 453 /* Get the headers from original INVITE request. */ 454 # define FIND_HDR(m,HNAME) pjsip_msg_find_hdr(m, PJSIP_H_##HNAME, NULL) 455 456 from_hdr = (const pjsip_from_hdr*) FIND_HDR(invite_msg, FROM); 457 PJ_ASSERT_ON_FAIL(from_hdr != NULL, goto on_missing_hdr); 458 459 to_hdr = (const pjsip_to_hdr*) FIND_HDR(invite_msg, TO); 460 PJ_ASSERT_ON_FAIL(to_hdr != NULL, goto on_missing_hdr); 461 462 cid_hdr = (const pjsip_cid_hdr*) FIND_HDR(invite_msg, CALL_ID); 463 PJ_ASSERT_ON_FAIL(to_hdr != NULL, goto on_missing_hdr); 464 465 cseq_hdr = (const pjsip_cseq_hdr*) FIND_HDR(invite_msg, CSEQ); 466 PJ_ASSERT_ON_FAIL(to_hdr != NULL, goto on_missing_hdr); 467 468 # undef FIND_HDR 469 470 /* Create new request message from the headers. */ 471 status = pjsip_endpt_create_request_from_hdr(endpt, 472 &pjsip_ack_method, 473 tdata->msg->line.req.uri, 474 from_hdr, to_hdr, 475 NULL, cid_hdr, 476 cseq_hdr->cseq, NULL, 477 &ack); 478 479 if (status != PJ_SUCCESS) 480 return status; 481 482 /* Update tag in To header with the one from the response (if any). */ 483 to = (pjsip_to_hdr*) pjsip_msg_find_hdr(ack->msg, PJSIP_H_TO, NULL); 484 pj_strdup(ack->pool, &to->tag, &rdata->msg_info.to->tag); 547 485 548 486 /* Must contain single Via, just as the original INVITE. */ 549 hdr = pjsip_msg_find_remove_hdr( invite_msg, PJSIP_H_VIA, NULL); 550 pjsip_msg_insert_first_hdr( ack_msg, hdr ); 551 552 /* Must have the same CSeq value as the original INVITE, but method 553 * changed to ACK 554 */ 555 cseq = (pjsip_cseq_hdr*) pjsip_msg_find_remove_hdr( invite_msg, 556 PJSIP_H_CSEQ, NULL); 557 pjsip_method_set( &cseq->method, PJSIP_ACK_METHOD ); 558 pjsip_msg_add_hdr( ack_msg, (pjsip_hdr*) cseq ); 487 hdr = pjsip_msg_find_hdr( invite_msg, PJSIP_H_VIA, NULL); 488 if (hdr) { 489 pjsip_msg_insert_first_hdr( ack->msg, pjsip_hdr_clone(ack->pool,hdr) ); 490 } 559 491 560 492 /* If the original INVITE has Route headers, those header fields MUST 561 493 * appear in the ACK. 562 494 */ 563 hdr = pjsip_msg_find_ remove_hdr( invite_msg, PJSIP_H_ROUTE, NULL);495 hdr = pjsip_msg_find_hdr( invite_msg, PJSIP_H_ROUTE, NULL); 564 496 while (hdr != NULL) { 565 pjsip_msg_add_hdr( ack_msg, hdr ); 566 hdr = pjsip_msg_find_remove_hdr( invite_msg, PJSIP_H_ROUTE, NULL); 567 } 568 569 /* Set the message in the "tdata" to point to the ACK message. */ 570 tdata->msg = ack_msg; 571 572 /* Reset transmit packet buffer, to force 're-printing' of message. */ 573 tdata->buf.cur = tdata->buf.start; 497 pjsip_msg_add_hdr( ack->msg, pjsip_hdr_clone(ack->pool, hdr) ); 498 hdr = hdr->next; 499 if (hdr == &invite_msg->hdr) 500 break; 501 hdr = pjsip_msg_find_hdr( invite_msg, PJSIP_H_ROUTE, hdr); 502 } 574 503 575 504 /* We're done. 576 505 * "tdata" parameter now contains the ACK message. 577 506 */ 507 *ack_tdata = ack; 508 return PJ_SUCCESS; 509 510 on_missing_hdr: 511 if (ack) 512 pjsip_tx_data_dec_ref(ack); 513 return PJSIP_EMISSINGHDR; 578 514 } 579 515 … … 584 520 */ 585 521 PJ_DEF(pj_status_t) pjsip_endpt_create_cancel( pjsip_endpoint *endpt, 586 pjsip_tx_data *req_tdata,522 const pjsip_tx_data *req_tdata, 587 523 pjsip_tx_data **p_tdata) 588 524 { 589 pjsip_ msg *req_msg; /* the original request. */590 pjsip_tx_data *cancel_tdata;591 pjsip_msg *cancel_msg;592 pjsip_hdr *hdr;593 pjsip_cseq_hdr *req_cseq, *cseq;594 pjsip_uri *req_uri;525 pjsip_tx_data *cancel_tdata = NULL; 526 const pjsip_from_hdr *from_hdr; 527 const pjsip_to_hdr *to_hdr; 528 const pjsip_cid_hdr *cid_hdr; 529 const pjsip_cseq_hdr *cseq_hdr; 530 const pjsip_hdr *hdr; 595 531 pj_status_t status; 596 532 … … 598 534 PJ_LOG(5,(THIS_FILE, "pjsip_endpt_create_cancel(tdata=%p)", req_tdata)); 599 535 600 /* Get the original request. */601 req_msg = req_tdata->msg;602 603 536 /* The transmit buffer must INVITE request. */ 604 PJ_ASSERT_RETURN(req_ msg->type == PJSIP_REQUEST_MSG &&605 req_ msg->line.req.method.id == PJSIP_INVITE_METHOD,537 PJ_ASSERT_RETURN(req_tdata->msg->type == PJSIP_REQUEST_MSG && 538 req_tdata->msg->line.req.method.id == PJSIP_INVITE_METHOD, 606 539 PJ_EINVAL); 607 540 608 /* Create new transmit buffer. */ 609 status = pjsip_endpt_create_tdata( endpt, &cancel_tdata); 610 if (status != PJ_SUCCESS) { 541 /* Get the headers from original INVITE request. */ 542 # define FIND_HDR(m,HNAME) pjsip_msg_find_hdr(m, PJSIP_H_##HNAME, NULL) 543 544 from_hdr = (const pjsip_from_hdr*) FIND_HDR(req_tdata->msg, FROM); 545 PJ_ASSERT_ON_FAIL(from_hdr != NULL, goto on_missing_hdr); 546 547 to_hdr = (const pjsip_to_hdr*) FIND_HDR(req_tdata->msg, TO); 548 PJ_ASSERT_ON_FAIL(to_hdr != NULL, goto on_missing_hdr); 549 550 cid_hdr = (const pjsip_cid_hdr*) FIND_HDR(req_tdata->msg, CALL_ID); 551 PJ_ASSERT_ON_FAIL(to_hdr != NULL, goto on_missing_hdr); 552 553 cseq_hdr = (const pjsip_cseq_hdr*) FIND_HDR(req_tdata->msg, CSEQ); 554 PJ_ASSERT_ON_FAIL(to_hdr != NULL, goto on_missing_hdr); 555 556 # undef FIND_HDR 557 558 /* Create new request message from the headers. */ 559 status = pjsip_endpt_create_request_from_hdr(endpt, 560 &pjsip_cancel_method, 561 req_tdata->msg->line.req.uri, 562 from_hdr, to_hdr, 563 NULL, cid_hdr, 564 cseq_hdr->cseq, NULL, 565 &cancel_tdata); 566 567 if (status != PJ_SUCCESS) 611 568 return status; 612 }613 614 /* Create CANCEL request message. */615 cancel_msg = pjsip_msg_create(cancel_tdata->pool, PJSIP_REQUEST_MSG);616 cancel_tdata->msg = cancel_msg;617 618 /* Request-URI, Call-ID, From, To, and the numeric part of the CSeq are619 * copied from the original request.620 */621 /* Set request line. */622 pjsip_method_set(&cancel_msg->line.req.method, PJSIP_CANCEL_METHOD);623 req_uri = req_msg->line.req.uri;624 cancel_msg->line.req.uri = pjsip_uri_clone(cancel_tdata->pool, req_uri);625 626 /* Copy Call-ID */627 hdr = pjsip_msg_find_hdr(req_msg, PJSIP_H_CALL_ID, NULL);628 pjsip_msg_add_hdr(cancel_msg, pjsip_hdr_clone(cancel_tdata->pool, hdr));629 630 /* Copy From header. */631 hdr = pjsip_msg_find_hdr(req_msg, PJSIP_H_FROM, NULL);632 pjsip_msg_add_hdr(cancel_msg, pjsip_hdr_clone(cancel_tdata->pool, hdr));633 634 /* Copy To header. */635 hdr = pjsip_msg_find_hdr(req_msg, PJSIP_H_TO, NULL);636 pjsip_msg_add_hdr(cancel_msg, pjsip_hdr_clone(cancel_tdata->pool, hdr));637 638 /* Create new CSeq with equal number, but method set to CANCEL. */639 req_cseq = (pjsip_cseq_hdr*) pjsip_msg_find_hdr(req_msg, PJSIP_H_CSEQ, NULL);640 cseq = pjsip_cseq_hdr_create(cancel_tdata->pool);641 cseq->cseq = req_cseq->cseq;642 pjsip_method_set(&cseq->method, PJSIP_CANCEL_METHOD);643 pjsip_msg_add_hdr(cancel_msg, (pjsip_hdr*)cseq);644 569 645 570 /* Must only have single Via which matches the top-most Via in the 646 571 * request being cancelled. 647 572 */ 648 hdr = pjsip_msg_find_hdr(req_msg, PJSIP_H_VIA, NULL); 649 pjsip_msg_insert_first_hdr(cancel_msg, 650 pjsip_hdr_clone(cancel_tdata->pool, hdr)); 573 hdr = pjsip_msg_find_hdr(req_tdata->msg, PJSIP_H_VIA, NULL); 574 if (hdr) { 575 pjsip_msg_insert_first_hdr(cancel_tdata->msg, 576 pjsip_hdr_clone(cancel_tdata->pool, hdr)); 577 } 651 578 652 579 /* If the original request has Route header, the CANCEL request must also … … 654 581 * Copy "Route" header from the request. 655 582 */ 656 hdr = pjsip_msg_find_hdr(req_ msg, PJSIP_H_ROUTE, NULL);583 hdr = pjsip_msg_find_hdr(req_tdata->msg, PJSIP_H_ROUTE, NULL); 657 584 while (hdr != NULL) { 658 pjsip_msg_add_hdr(cancel_msg, pjsip_hdr_clone(cancel_tdata->pool, hdr)); 585 pjsip_msg_add_hdr(cancel_tdata->msg, 586 pjsip_hdr_clone(cancel_tdata->pool, hdr)); 659 587 hdr = hdr->next; 660 if (hdr != &cancel_ msg->hdr)661 hdr = pjsip_msg_find_hdr( req_msg, PJSIP_H_ROUTE, hdr);588 if (hdr != &cancel_tdata->msg->hdr) 589 hdr = pjsip_msg_find_hdr(cancel_tdata->msg, PJSIP_H_ROUTE, hdr); 662 590 else 663 591 break; … … 669 597 *p_tdata = cancel_tdata; 670 598 return PJ_SUCCESS; 671 } 672 673 /* Get the address parameters (host, port, flag, TTL, etc) to send the 674 * response. 675 */ 676 PJ_DEF(pj_status_t) pjsip_get_response_addr(pj_pool_t *pool, 677 const pjsip_transport *req_transport, 678 const pjsip_via_hdr *via, 679 pjsip_host_info *send_addr) 680 { 681 /* Determine the destination address (section 18.2.2): 682 * - for TCP, SCTP, or TLS, send the response using the transport where 683 * the request was received. 684 * - if maddr parameter is present, send to this address using the port 685 * in sent-by or 5060. If multicast is used, the TTL in the Via must 686 * be used, or 1 if ttl parameter is not present. 687 * - otherwise if received parameter is present, set to this address. 688 * - otherwise send to the address in sent-by. 599 600 on_missing_hdr: 601 if (cancel_tdata) 602 pjsip_tx_data_dec_ref(cancel_tdata); 603 return PJSIP_EMISSINGHDR; 604 } 605 606 607 /* 608 * Find which destination to be used to send the request message, based 609 * on the request URI and Route headers in the message. The procedure 610 * used here follows the guidelines on sending the request in RFC 3261 611 * chapter 8.1.2. 612 */ 613 PJ_DEF(pj_status_t) pjsip_get_request_addr( pjsip_tx_data *tdata, 614 pjsip_host_info *dest_info ) 615 { 616 const pjsip_uri *new_request_uri, *target_uri; 617 const pjsip_name_addr *topmost_route_uri; 618 pjsip_route_hdr *first_route_hdr, *last_route_hdr; 619 620 PJ_ASSERT_RETURN(tdata->msg->type == PJSIP_REQUEST_MSG, 621 PJSIP_ENOTREQUESTMSG); 622 PJ_ASSERT_RETURN(dest_info != NULL, PJ_EINVAL); 623 624 /* Get the first "Route" header from the message. If the message doesn't 625 * have any "Route" headers but the endpoint has, then copy the "Route" 626 * headers from the endpoint first. 689 627 */ 690 send_addr->flag = req_transport->flag; 691 send_addr->type = req_transport->key.type; 692 693 if (PJSIP_TRANSPORT_IS_RELIABLE(req_transport)) { 694 pj_strdup( pool, &send_addr->addr.host, 695 &req_transport->remote_name.host); 696 send_addr->addr.port = req_transport->remote_name.port; 697 628 last_route_hdr = first_route_hdr = 629 pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE, NULL); 630 if (first_route_hdr) { 631 topmost_route_uri = &first_route_hdr->name_addr; 632 while (last_route_hdr->next != (void*)&tdata->msg->hdr) { 633 pjsip_route_hdr *hdr; 634 hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE, 635 last_route_hdr->next); 636 if (!hdr) 637 break; 638 last_route_hdr = hdr; 639 } 698 640 } else { 699 /* Set the host part */ 700 if (via->maddr_param.slen) { 701 pj_strdup(pool, &send_addr->addr.host, &via->maddr_param); 702 } else if (via->recvd_param.slen) { 703 pj_strdup(pool, &send_addr->addr.host, &via->recvd_param); 641 topmost_route_uri = NULL; 642 } 643 644 /* If Route headers exist, and the first element indicates loose-route, 645 * the URI is taken from the Request-URI, and we keep all existing Route 646 * headers intact. 647 * If Route headers exist, and the first element DOESN'T indicate loose 648 * route, the URI is taken from the first Route header, and remove the 649 * first Route header from the message. 650 * Otherwise if there's no Route headers, the URI is taken from the 651 * Request-URI. 652 */ 653 if (topmost_route_uri) { 654 pj_bool_t has_lr_param; 655 656 if (PJSIP_URI_SCHEME_IS_SIP(topmost_route_uri) || 657 PJSIP_URI_SCHEME_IS_SIPS(topmost_route_uri)) 658 { 659 const pjsip_url *url = pjsip_uri_get_uri((void*)topmost_route_uri); 660 has_lr_param = url->lr_param; 704 661 } else { 705 pj_strdup(pool, &send_addr->addr.host, &via->sent_by.host); 706 } 707 708 /* Set the port */ 709 send_addr->addr.port = via->sent_by.port; 710 } 711 662 has_lr_param = 0; 663 } 664 665 if (has_lr_param) { 666 new_request_uri = tdata->msg->line.req.uri; 667 /* We shouldn't need to delete topmost Route if it has lr param. 668 * But seems like it breaks some proxy implementation, so we 669 * delete it anyway. 670 */ 671 /* 672 pj_list_erase(first_route_hdr); 673 if (first_route_hdr == last_route_hdr) 674 last_route_hdr = NULL; 675 */ 676 } else { 677 new_request_uri = pjsip_uri_get_uri((void*)topmost_route_uri); 678 pj_list_erase(first_route_hdr); 679 if (first_route_hdr == last_route_hdr) 680 last_route_hdr = NULL; 681 } 682 683 target_uri = (pjsip_uri*)topmost_route_uri; 684 685 } else { 686 target_uri = new_request_uri = tdata->msg->line.req.uri; 687 } 688 689 /* The target URI must be a SIP/SIPS URL so we can resolve it's address. 690 * Otherwise we're in trouble (i.e. there's no host part in tel: URL). 691 */ 692 pj_memset(dest_info, 0, sizeof(*dest_info)); 693 694 if (PJSIP_URI_SCHEME_IS_SIPS(target_uri)) { 695 pjsip_uri *uri = (pjsip_uri*) target_uri; 696 const pjsip_url *url = (const pjsip_url*)pjsip_uri_get_uri(uri); 697 dest_info->flag |= (PJSIP_TRANSPORT_SECURE | PJSIP_TRANSPORT_RELIABLE); 698 pj_strdup(tdata->pool, &dest_info->addr.host, &url->host); 699 dest_info->addr.port = url->port; 700 dest_info->type = 701 pjsip_transport_get_type_from_name(&url->transport_param); 702 703 } else if (PJSIP_URI_SCHEME_IS_SIP(target_uri)) { 704 pjsip_uri *uri = (pjsip_uri*) target_uri; 705 const pjsip_url *url = (const pjsip_url*)pjsip_uri_get_uri(uri); 706 pj_strdup(tdata->pool, &dest_info->addr.host, &url->host); 707 dest_info->addr.port = url->port; 708 dest_info->type = 709 pjsip_transport_get_type_from_name(&url->transport_param); 710 #if PJ_HAS_TCP 711 if (dest_info->type == PJSIP_TRANSPORT_TCP || 712 dest_info->type == PJSIP_TRANSPORT_SCTP) 713 { 714 dest_info->flag |= PJSIP_TRANSPORT_RELIABLE; 715 } 716 #endif 717 } else { 718 pj_assert(!"Unsupported URI scheme!"); 719 PJ_TODO(SUPPORT_REQUEST_ADDR_RESOLUTION_FOR_TEL_URI); 720 return PJSIP_EINVALIDSCHEME; 721 } 722 723 /* If target URI is different than request URI, replace 724 * request URI add put the original URI in the last Route header. 725 */ 726 if (new_request_uri && new_request_uri!=tdata->msg->line.req.uri) { 727 pjsip_route_hdr *route = pjsip_route_hdr_create(tdata->pool); 728 route->name_addr.uri = tdata->msg->line.req.uri; 729 if (last_route_hdr) 730 pj_list_insert_after(last_route_hdr, route); 731 else 732 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)route); 733 tdata->msg->line.req.uri = (pjsip_uri*)new_request_uri; 734 } 735 736 /* Success. */ 737 return PJ_SUCCESS; 738 } 739 740 741 /* Transport callback for sending stateless request. 742 * This is one of the most bizzare function in pjsip, so 743 * good luck if you happen to debug this function!! 744 */ 745 static void stateless_send_transport_cb( void *token, 746 pjsip_tx_data *tdata, 747 pj_ssize_t sent ) 748 { 749 pjsip_send_state *stateless_data = token; 750 751 PJ_UNUSED_ARG(tdata); 752 pj_assert(tdata == stateless_data->tdata); 753 754 for (;;) { 755 pj_status_t status; 756 pj_bool_t cont; 757 758 pj_sockaddr_t *cur_addr; 759 pjsip_transport_type_e cur_addr_type; 760 int cur_addr_len; 761 762 pjsip_via_hdr *via; 763 764 if (sent == -PJ_EPENDING) { 765 /* This is the initial process. 766 * When the process started, this function will be called by 767 * stateless_send_resolver_callback() with sent argument set to 768 * -PJ_EPENDING. 769 */ 770 cont = PJ_TRUE; 771 } else { 772 /* There are two conditions here: 773 * (1) Message is sent (i.e. sent > 0), 774 * (2) Failure (i.e. sent <= 0) 775 */ 776 cont = (sent > 0) ? PJ_FALSE : 777 (stateless_data->cur_addr<stateless_data->addr.count-1); 778 if (stateless_data->app_cb) { 779 (*stateless_data->app_cb)(stateless_data, sent, &cont); 780 } else { 781 /* Doesn't have application callback. 782 * Terminate the process. 783 */ 784 cont = PJ_FALSE; 785 } 786 } 787 788 /* Finished with this transport. */ 789 if (stateless_data->cur_transport) { 790 pjsip_transport_dec_ref(stateless_data->cur_transport); 791 stateless_data->cur_transport = NULL; 792 } 793 794 /* Done if application doesn't want to continue. */ 795 if (sent > 0 || !cont) { 796 pjsip_tx_data_dec_ref(tdata); 797 return; 798 } 799 800 /* Try next address, if any, and only when this is not the 801 * first invocation. 802 */ 803 if (sent != -PJ_EPENDING) { 804 stateless_data->cur_addr++; 805 } 806 807 /* Have next address? */ 808 if (stateless_data->cur_addr >= stateless_data->addr.count) { 809 /* This only happens when a rather buggy application has 810 * sent 'cont' to PJ_TRUE when the initial value was PJ_FALSE. 811 * In this case just stop the processing; we don't need to 812 * call the callback again as application has been informed 813 * before. 814 */ 815 pjsip_tx_data_dec_ref(tdata); 816 return; 817 } 818 819 /* Keep current server address information handy. */ 820 cur_addr = &stateless_data->addr.entry[stateless_data->cur_addr].addr; 821 cur_addr_type = stateless_data->addr.entry[stateless_data->cur_addr].type; 822 cur_addr_len = stateless_data->addr.entry[stateless_data->cur_addr].addr_len; 823 824 /* Acquire transport. */ 825 status = pjsip_endpt_acquire_transport( stateless_data->endpt, 826 cur_addr_type, 827 cur_addr, 828 cur_addr_len, 829 &stateless_data->cur_transport); 830 if (status != PJ_SUCCESS) { 831 sent = -status; 832 continue; 833 } 834 835 /* Modify Via header. */ 836 via = (pjsip_via_hdr*) pjsip_msg_find_hdr( tdata->msg, 837 PJSIP_H_VIA, NULL); 838 if (!via) { 839 /* Shouldn't happen if request was created with PJSIP API! 840 * But we handle the case anyway for robustness. 841 */ 842 pj_assert(!"Via header not found!"); 843 via = pjsip_via_hdr_create(tdata->pool); 844 pjsip_msg_insert_first_hdr(tdata->msg, (pjsip_hdr*)via); 845 } 846 847 if (via->branch_param.slen == 0) { 848 pj_str_t tmp; 849 via->branch_param.ptr = pj_pool_alloc(tdata->pool, 850 PJSIP_MAX_BRANCH_LEN); 851 via->branch_param.slen = PJSIP_MAX_BRANCH_LEN; 852 pj_memcpy(via->branch_param.ptr, PJSIP_RFC3261_BRANCH_ID, 853 PJSIP_RFC3261_BRANCH_LEN); 854 tmp.ptr = via->branch_param.ptr + PJSIP_RFC3261_BRANCH_LEN; 855 pj_generate_unique_string(&tmp); 856 } 857 858 via->transport = pj_str(stateless_data->cur_transport->type_name); 859 via->sent_by = stateless_data->cur_transport->local_name; 860 via->rport_param = 0; 861 862 /* Send message using this transport. */ 863 status = pjsip_transport_send( stateless_data->cur_transport, 864 tdata, 865 cur_addr, 866 cur_addr_len, 867 stateless_data, 868 &stateless_send_transport_cb); 869 if (status == PJ_SUCCESS) { 870 /* Recursively call this function. */ 871 sent = tdata->buf.cur - tdata->buf.start; 872 stateless_send_transport_cb( stateless_data, tdata, sent ); 873 return; 874 } else if (status == PJ_EPENDING) { 875 /* This callback will be called later. */ 876 return; 877 } else { 878 /* Recursively call this function. */ 879 sent = -status; 880 stateless_send_transport_cb( stateless_data, tdata, sent ); 881 return; 882 } 883 } 884 885 } 886 887 /* Resolver callback for sending stateless request. */ 888 static void 889 stateless_send_resolver_callback( pj_status_t status, 890 void *token, 891 const struct pjsip_server_addresses *addr) 892 { 893 pjsip_send_state *stateless_data = token; 894 895 /* Fail on server resolution. */ 896 if (status != PJ_SUCCESS) { 897 if (stateless_data->app_cb) { 898 pj_bool_t cont = PJ_FALSE; 899 (*stateless_data->app_cb)(stateless_data, -status, &cont); 900 } 901 pjsip_tx_data_dec_ref(stateless_data->tdata); 902 return; 903 } 904 905 /* Copy server addresses */ 906 pj_memcpy( &stateless_data->addr, addr, sizeof(pjsip_server_addresses)); 907 908 /* Process the addresses. */ 909 stateless_send_transport_cb( stateless_data, stateless_data->tdata, 910 -PJ_EPENDING); 911 } 912 913 /* 914 * Send stateless request. 915 * The sending process consists of several stages: 916 * - determine which host to contact (#pjsip_get_request_addr). 917 * - resolve the host (#pjsip_endpt_resolve) 918 * - establish transport (#pjsip_endpt_acquire_transport) 919 * - send the message (#pjsip_transport_send) 920 */ 921 PJ_DEF(pj_status_t) 922 pjsip_endpt_send_request_stateless(pjsip_endpoint *endpt, 923 pjsip_tx_data *tdata, 924 void *token, 925 void (*cb)(pjsip_send_state*, 926 pj_ssize_t sent, 927 pj_bool_t *cont)) 928 { 929 pjsip_host_info dest_info; 930 pjsip_send_state *stateless_data; 931 pj_status_t status; 932 933 PJ_ASSERT_RETURN(endpt && tdata, PJ_EINVAL); 934 935 /* Get destination name to contact. */ 936 status = pjsip_get_request_addr(tdata, &dest_info); 937 if (status != PJ_SUCCESS) 938 return status; 939 940 /* Keep stateless data. */ 941 stateless_data = pj_pool_zalloc(tdata->pool, sizeof(pjsip_send_state)); 942 stateless_data->token = token; 943 stateless_data->endpt = endpt; 944 stateless_data->tdata = tdata; 945 stateless_data->app_cb = cb; 946 947 /* Resolve destination host. 948 * The processing then resumed when the resolving callback is called. 949 */ 950 pjsip_endpt_resolve( endpt, tdata->pool, &dest_info, stateless_data, 951 &stateless_send_resolver_callback); 712 952 return PJ_SUCCESS; 713 953 } 954 955 /* 956 * Determine which address (and transport) to use to send response message 957 * based on the received request. This function follows the specification 958 * in section 18.2.2 of RFC 3261 and RFC 3581 for calculating the destination 959 * address and transport. 960 */ 961 PJ_DEF(pj_status_t) pjsip_get_response_addr( pj_pool_t *pool, 962 pjsip_rx_data *rdata, 963 pjsip_response_addr *res_addr ) 964 { 965 pjsip_transport *src_transport = rdata->tp_info.transport; 966 967 /* Check arguments. */ 968 PJ_ASSERT_RETURN(pool && rdata && res_addr, PJ_EINVAL); 969 970 /* All requests must have "received" parameter. 971 * This must always be done in transport layer. 972 */ 973 pj_assert(rdata->msg_info.via->recvd_param.slen != 0); 974 975 /* Do the calculation based on RFC 3261 Section 18.2.2 and RFC 3581 */ 976 977 if (PJSIP_TRANSPORT_IS_RELIABLE(src_transport)) { 978 /* For reliable protocol such as TCP or SCTP, or TLS over those, the 979 * response MUST be sent using the existing connection to the source 980 * of the original request that created the transaction, if that 981 * connection is still open. 982 * If that connection is no longer open, the server SHOULD open a 983 * connection to the IP address in the received parameter, if present, 984 * using the port in the sent-by value, or the default port for that 985 * transport, if no port is specified. 986 * If that connection attempt fails, the server SHOULD use the 987 * procedures in [4] for servers in order to determine the IP address 988 * and port to open the connection and send the response to. 989 */ 990 res_addr->transport = rdata->tp_info.transport; 991 pj_memcpy(&res_addr->addr, &rdata->pkt_info.src_addr, 992 rdata->pkt_info.src_addr_len); 993 res_addr->addr_len = rdata->pkt_info.src_addr_len; 994 res_addr->dst_host.type = src_transport->key.type; 995 res_addr->dst_host.flag = src_transport->flag; 996 pj_strdup( pool, &res_addr->dst_host.addr.host, 997 &rdata->msg_info.via->recvd_param); 998 res_addr->dst_host.addr.port = rdata->msg_info.via->sent_by.port; 999 if (res_addr->dst_host.addr.port == 0) { 1000 res_addr->dst_host.addr.port = 1001 pjsip_transport_get_default_port_for_type(res_addr->dst_host.type); 1002 } 1003 1004 } else if (rdata->msg_info.via->maddr_param.slen) { 1005 /* Otherwise, if the Via header field value contains a maddr parameter, 1006 * the response MUST be forwarded to the address listed there, using 1007 * the port indicated in sent-by, or port 5060 if none is present. 1008 * If the address is a multicast address, the response SHOULD be sent 1009 * using the TTL indicated in the ttl parameter, or with a TTL of 1 if 1010 * that parameter is not present. 1011 */ 1012 res_addr->transport = NULL; 1013 res_addr->dst_host.type = src_transport->key.type; 1014 res_addr->dst_host.flag = src_transport->flag; 1015 pj_strdup( pool, &res_addr->dst_host.addr.host, 1016 &rdata->msg_info.via->maddr_param); 1017 res_addr->dst_host.addr.port = rdata->msg_info.via->sent_by.port; 1018 if (res_addr->dst_host.addr.port == 0) 1019 res_addr->dst_host.addr.port = 5060; 1020 1021 } else if (rdata->msg_info.via->rport_param >= 0) { 1022 /* There is both a "received" parameter and an "rport" parameter, 1023 * the response MUST be sent to the IP address listed in the "received" 1024 * parameter, and the port in the "rport" parameter. 1025 * The response MUST be sent from the same address and port that the 1026 * corresponding request was received on. 1027 */ 1028 res_addr->transport = rdata->tp_info.transport; 1029 pj_memcpy(&res_addr->addr, &rdata->pkt_info.src_addr, 1030 rdata->pkt_info.src_addr_len); 1031 res_addr->addr_len = rdata->pkt_info.src_addr_len; 1032 res_addr->dst_host.type = src_transport->key.type; 1033 res_addr->dst_host.flag = src_transport->flag; 1034 pj_strdup( pool, &res_addr->dst_host.addr.host, 1035 &rdata->msg_info.via->recvd_param); 1036 res_addr->dst_host.addr.port = rdata->msg_info.via->sent_by.port; 1037 if (res_addr->dst_host.addr.port == 0) { 1038 res_addr->dst_host.addr.port = 1039 pjsip_transport_get_default_port_for_type(res_addr->dst_host.type); 1040 } 1041 1042 } else { 1043 res_addr->transport = NULL; 1044 res_addr->dst_host.type = src_transport->key.type; 1045 res_addr->dst_host.flag = src_transport->flag; 1046 pj_strdup( pool, &res_addr->dst_host.addr.host, 1047 &rdata->msg_info.via->recvd_param); 1048 res_addr->dst_host.addr.port = rdata->msg_info.via->sent_by.port; 1049 if (res_addr->dst_host.addr.port == 0) { 1050 res_addr->dst_host.addr.port = 1051 pjsip_transport_get_default_port_for_type(res_addr->dst_host.type); 1052 } 1053 } 1054 1055 return PJ_SUCCESS; 1056 } 1057 1058 /* 1059 * Callback called by transport during send_response. 1060 */ 1061 static void send_response_transport_cb(void *token, pjsip_tx_data *tdata, 1062 pj_ssize_t sent) 1063 { 1064 pjsip_send_state *send_state = token; 1065 pj_bool_t cont = PJ_FALSE; 1066 1067 /* Call callback, if any. */ 1068 if (send_state->app_cb) 1069 (*send_state->app_cb)(send_state, sent, &cont); 1070 1071 /* Decrement transport reference counter. */ 1072 pjsip_transport_dec_ref(send_state->cur_transport); 1073 1074 /* Decrement transmit data ref counter. */ 1075 pjsip_tx_data_dec_ref(tdata); 1076 } 1077 1078 /* 1079 * Resolver calback during send_response. 1080 */ 1081 static void send_response_resolver_cb( pj_status_t status, void *token, 1082 const pjsip_server_addresses *addr ) 1083 { 1084 pjsip_send_state *send_state = token; 1085 1086 if (status != PJ_SUCCESS) { 1087 if (send_state->app_cb) { 1088 pj_bool_t cont = PJ_FALSE; 1089 (*send_state->app_cb)(send_state, -status, &cont); 1090 } 1091 pjsip_tx_data_dec_ref(send_state->tdata); 1092 return; 1093 } 1094 1095 /* Only handle the first address resolved. */ 1096 1097 /* Acquire transport. */ 1098 status = pjsip_endpt_acquire_transport( send_state->endpt, 1099 addr->entry[0].type, 1100 &addr->entry[0].addr, 1101 addr->entry[0].addr_len, 1102 &send_state->cur_transport); 1103 if (status != PJ_SUCCESS) { 1104 if (send_state->app_cb) { 1105 pj_bool_t cont = PJ_FALSE; 1106 (*send_state->app_cb)(send_state, -status, &cont); 1107 } 1108 pjsip_tx_data_dec_ref(send_state->tdata); 1109 return; 1110 } 1111 1112 /* Send response using the transoprt. */ 1113 status = pjsip_transport_send( send_state->cur_transport, 1114 send_state->tdata, 1115 &addr->entry[0].addr, 1116 addr->entry[0].addr_len, 1117 send_state, 1118 &send_response_transport_cb); 1119 if (status == PJ_SUCCESS) { 1120 pj_ssize_t sent = send_state->tdata->buf.cur - 1121 send_state->tdata->buf.start; 1122 send_response_transport_cb(send_state, send_state->tdata, sent); 1123 1124 } else if (status == PJ_EPENDING) { 1125 /* Transport callback will be called later. */ 1126 } else { 1127 send_response_transport_cb(send_state, send_state->tdata, -status); 1128 } 1129 } 1130 1131 /* 1132 * Send response. 1133 */ 1134 PJ_DEF(pj_status_t) pjsip_endpt_send_response( pjsip_endpoint *endpt, 1135 pjsip_response_addr *res_addr, 1136 pjsip_tx_data *tdata, 1137 void *token, 1138 void (*cb)(pjsip_send_state*, 1139 pj_ssize_t sent, 1140 pj_bool_t *cont)) 1141 { 1142 /* Determine which transports and addresses to send the response, 1143 * based on Section 18.2.2 of RFC 3261. 1144 */ 1145 pjsip_send_state *send_state; 1146 pj_status_t status; 1147 1148 /* Create structure to keep the sending state. */ 1149 send_state = pj_pool_zalloc(tdata->pool, sizeof(pjsip_send_state)); 1150 send_state->endpt = endpt; 1151 send_state->tdata = tdata; 1152 send_state->token = token; 1153 send_state->app_cb = cb; 1154 1155 if (res_addr->transport != NULL) { 1156 send_state->cur_transport = res_addr->transport; 1157 pjsip_transport_add_ref(send_state->cur_transport); 1158 1159 status = pjsip_transport_send( send_state->cur_transport, tdata, 1160 &res_addr->addr, 1161 res_addr->addr_len, 1162 send_state, 1163 &send_response_transport_cb ); 1164 if (status == PJ_SUCCESS) { 1165 pj_ssize_t sent = tdata->buf.cur - tdata->buf.start; 1166 send_response_transport_cb(send_state, tdata, sent); 1167 return PJ_SUCCESS; 1168 } else if (status == PJ_EPENDING) { 1169 /* Callback will be called later. */ 1170 return PJ_SUCCESS; 1171 } else { 1172 send_response_transport_cb(send_state, tdata, -status); 1173 return status; 1174 } 1175 } else { 1176 pjsip_endpt_resolve(endpt, tdata->pool, &res_addr->dst_host, 1177 send_state, &send_response_resolver_cb); 1178 return PJ_SUCCESS; 1179 } 1180 } 1181 714 1182 715 1183 /* -
pjproject/trunk/pjsip/src/test-pjsip/main.c
r77 r106 18 18 */ 19 19 #include "test.h" 20 #include <stdio.h> 20 21 21 int main( void)22 int main(int argc, char *argv[]) 22 23 { 23 return test_main(); 24 int retval = test_main(); 25 26 if (argc != 1) { 27 char s[10]; 28 printf("<Press ENTER to quit>\n"); 29 fgets(s, sizeof(s), stdin); 30 } 31 32 return retval; 24 33 } -
pjproject/trunk/pjsip/src/test-pjsip/msg_test.c
r105 r106 665 665 /*****************************************************************************/ 666 666 667 pj_status_t msg_test(void)667 int msg_test(void) 668 668 { 669 669 pj_status_t status; -
pjproject/trunk/pjsip/src/test-pjsip/test.c
r82 r106 84 84 DO_TEST(uri_test()); 85 85 DO_TEST(msg_test()); 86 DO_TEST(txdata_test()); 87 DO_TEST(transport_udp_test()); 86 88 87 89 on_return: -
pjproject/trunk/pjsip/src/test-pjsip/test.h
r77 r106 24 24 extern pjsip_endpoint *endpt; 25 25 26 pj_status_t uri_test(void); 27 pj_status_t msg_test(void); 26 #define TEST_UDP_PORT 15060 28 27 28 /* The tests */ 29 int uri_test(void); 30 int msg_test(void); 31 int txdata_test(void); 32 int transport_udp_test(void); 33 34 /* Transport test helpers (transport_test.c). */ 35 int generic_transport_test(pjsip_transport *tp); 36 int transport_send_recv_test( pjsip_transport_type_e tp_type, 37 pjsip_transport *ref_tp, 38 const pj_sockaddr_in *rem_addr ); 39 int transport_rt_test( pjsip_transport_type_e tp_type, 40 pjsip_transport *ref_tp, 41 const pj_sockaddr_in *rem_addr ); 42 43 /* Test main entry */ 29 44 int test_main(void); 45 46 /* Test utilities. */ 30 47 void app_perror(const char *msg, pj_status_t status); 31 48 -
pjproject/trunk/pjsip/src/test-pjsip/uri_test.c
r105 r106 784 784 } 785 785 786 pj_status_t uri_test()786 int uri_test() 787 787 { 788 788 unsigned i, loop;
Note: See TracChangeset
for help on using the changeset viewer.