Changeset 123 for pjproject/trunk
- Timestamp:
- Jan 18, 2006 11:34:15 PM (19 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 1 added
- 23 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjlib-util/include/pjlib-util/scanner.h
r81 r123 490 490 * @param state Variable to store scanner's state. 491 491 */ 492 PJ_DECL(void) pj_scan_save_state( pj_scanner *scanner, pj_scan_state *state); 492 PJ_DECL(void) pj_scan_save_state( const pj_scanner *scanner, 493 pj_scan_state *state); 493 494 494 495 … … 502 503 */ 503 504 PJ_DECL(void) pj_scan_restore_state( pj_scanner *scanner, 504 505 pj_scan_state *state); 505 506 506 507 /** … … 511 512 * @return The column position. 512 513 */ 513 PJ_INLINE(int) pj_scan_get_col( pj_scanner *scanner )514 PJ_INLINE(int) pj_scan_get_col( const pj_scanner *scanner ) 514 515 { 515 516 return scanner->curptr - scanner->start_line; -
pjproject/trunk/pjlib-util/include/pjlib-util/xml.h
r65 r123 98 98 99 99 /** 100 * Create an empty node. 101 * 102 * @param pool Pool. 103 * @param name Node name. 104 * 105 * @return The new node. 106 */ 107 PJ_DECL(pj_xml_node*) pj_xml_node_new(pj_pool_t *pool, const pj_str_t *name); 108 109 110 /** 111 * Create new XML attribute. 112 * 113 * @param pool Pool. 114 * @param name Attribute name. 115 * @param attr Attribute value. 116 * 117 * @return The new XML attribute. 118 */ 119 PJ_DECL(pj_xml_attr*) pj_xml_attr_new(pj_pool_t *pool, const pj_str_t *name, 120 const pj_str_t *value); 121 122 /** 100 123 * Add node to another node. 101 124 * -
pjproject/trunk/pjlib-util/src/pjlib-util/scanner.c
r81 r123 528 528 } 529 529 530 PJ_DEF(void) pj_scan_save_state( pj_scanner *scanner, pj_scan_state *state) 530 PJ_DEF(void) pj_scan_save_state( const pj_scanner *scanner, 531 pj_scan_state *state) 531 532 { 532 533 state->curptr = scanner->curptr; … … 537 538 538 539 PJ_DEF(void) pj_scan_restore_state( pj_scanner *scanner, 539 540 pj_scan_state *state) 540 541 { 541 542 scanner->curptr = state->curptr; -
pjproject/trunk/pjlib-util/src/pjlib-util/xml.c
r77 r123 38 38 pj_xml_node *node; 39 39 40 node = pj_pool_ calloc(pool, 1, sizeof(pj_xml_node));40 node = pj_pool_zalloc(pool, sizeof(pj_xml_node)); 41 41 pj_list_init( &node->attr_head ); 42 42 pj_list_init( &node->node_head ); … … 314 314 } 315 315 316 PJ_DEF(pj_xml_node*) pj_xml_node_new(pj_pool_t *pool, const pj_str_t *name) 317 { 318 pj_xml_node *node = alloc_node(pool); 319 pj_strdup(pool, &node->name, name); 320 return node; 321 } 322 323 PJ_DEF(pj_xml_attr*) pj_xml_attr_new( pj_pool_t *pool, const pj_str_t *name, 324 const pj_str_t *value) 325 { 326 pj_xml_attr *attr = alloc_attr(pool); 327 pj_strdup( pool, &attr->name, name); 328 pj_strdup( pool, &attr->value, value); 329 return attr; 330 } 316 331 317 332 PJ_DEF(void) pj_xml_add_node( pj_xml_node *parent, pj_xml_node *node ) -
pjproject/trunk/pjmedia/bin
-
Property
svn:ignore
set to
*
-
Property
svn:ignore
set to
-
pjproject/trunk/pjmedia/lib
-
Property
svn:ignore
set to
*
-
Property
svn:ignore
set to
-
pjproject/trunk/pjsip/build/pjsip_core.dsp
r119 r123 88 88 # Begin Source File 89 89 90 SOURCE=..\src\pjsip\sip_auth .c90 SOURCE=..\src\pjsip\sip_auth_client.c 91 91 # End Source File 92 92 # Begin Source File … … 97 97 98 98 SOURCE=..\src\pjsip\sip_auth_parser.c 99 # End Source File 100 # Begin Source File 101 102 SOURCE=..\src\pjsip\sip_auth_server.c 99 103 # End Source File 100 104 # Begin Source File -
pjproject/trunk/pjsip/build/pjsip_ua.dsp
r65 r123 108 108 # Begin Source File 109 109 110 SOURCE= ..\src\pjsip_ua.h110 SOURCE="..\include\pjsip-ua\sip_dialog.h" 111 111 # End Source File 112 112 # Begin Source File 113 113 114 SOURCE= ..\src\pjsip_mod_ua\sip_dialog.h114 SOURCE="..\include\pjsip-ua\sip_regc.h" 115 115 # End Source File 116 116 # Begin Source File 117 117 118 SOURCE=..\src\pjsip_mod_ua\sip_reg.h 119 # End Source File 120 # Begin Source File 121 122 SOURCE=..\src\pjsip_mod_ua\sip_ua.h 123 # End Source File 124 # Begin Source File 125 126 SOURCE=..\src\pjsip_mod_ua\sip_ua_private.h 118 SOURCE="..\include\pjsip-ua\sip_ua.h" 127 119 # End Source File 128 120 # End Group -
pjproject/trunk/pjsip/include/pjsip-ua/sip_ua.h
- Property svn:keywords set to Id
r65 r123 21 21 22 22 /** 23 * @file ua.h24 * @brief SIP User Agent Library23 * @file sip_ua.h 24 * @brief SIP User Agent Module 25 25 */ 26 26 27 #include <pjsip_mod_ua/sip_dialog.h>28 27 29 28 PJ_BEGIN_DECL … … 41 40 */ 42 41 43 typedef struct pjsip_dlg_callback pjsip_dlg_callback; 44 45 /** 46 * \brief This structure describes a User Agent instance. 47 */ 48 struct pjsip_user_agent 49 { 50 pjsip_endpoint *endpt; 51 pj_pool_t *pool; 52 pj_mutex_t *mutex; 53 pj_uint32_t mod_id; 54 pj_hash_table_t *dlg_table; 55 pjsip_dlg_callback *dlg_cb; 56 pj_list dlg_list; 57 }; 58 59 /** 60 * Create a new dialog. 61 */ 62 PJ_DECL(pjsip_dlg*) pjsip_ua_create_dialog( pjsip_user_agent *ua, 63 pjsip_role_e role ); 42 /** User agent type. */ 43 typedef pjsip_module pjsip_user_agent; 64 44 65 45 66 46 /** 67 * Destroy dialog. 47 * Initialize user agent layer and register it to the specified endpoint. 48 * 49 * @param endpt The endpoint where the user agent will be 50 * registered. 51 * 52 * @return PJ_SUCCESS on success. 68 53 */ 69 PJ_DECL(void) pjsip_ua_destroy_dialog( pjsip_dlg *dlg ); 70 71 72 /** 73 * Register callback to receive dialog notifications. 74 */ 75 PJ_DECL(void) pjsip_ua_set_dialog_callback( pjsip_user_agent *ua, 76 pjsip_dlg_callback *cb ); 77 54 PJ_DECL(pj_status_t) pjsip_ua_init(pjsip_endpoint *endpt); 78 55 79 56 /** 80 * Get the module interface for the UA module. 57 * Get the instance of the user agent. 58 * 59 * @return The user agent module instance. 81 60 */ 82 PJ_DECL(pjsip_module*) pjsip_ua_get_module(void); 83 61 PJ_DECL(pjsip_user_agent*) pjsip_ua_instance(void); 84 62 85 63 /** 86 * Dump user agent state to log file. 64 * Destroy the user agent layer. 65 * 66 * @return PJ_SUCCESS on success. 87 67 */ 88 PJ_DECL(void) pjsip_ua_dump( pjsip_user_agent *ua ); 68 PJ_DECL(pj_status_t) pjsip_ua_destroy(void); 69 89 70 90 71 /** … … 94 75 PJ_END_DECL 95 76 77 96 78 #endif /* __PJSIP_UA_H__ */ 97 79 -
pjproject/trunk/pjsip/include/pjsip/sip_auth.h
r65 r123 30 30 PJ_BEGIN_DECL 31 31 32 32 33 /** 33 34 * @defgroup PJSIP_AUTH_API Authorization API's … … 36 37 */ 37 38 38 /** Type of data in the credential information. */ 39 /* Length of digest string. */ 40 #define PJSIP_MD5STRLEN 32 41 42 43 /** Type of data in the credential information. */ 39 44 typedef enum pjsip_cred_data_type 40 45 { … … 78 83 PJ_DECL_LIST_MEMBER(struct pjsip_cached_auth_hdr); 79 84 80 pjsip_method method; 81 pjsip_authorization_hdr *hdr; 85 pjsip_method method; /**< To quickly see the method. */ 86 pjsip_authorization_hdr *hdr; /**< The cached header. */ 82 87 83 88 } pjsip_cached_auth_hdr; … … 94 99 * that have been sent in the cache list. 95 100 */ 96 typedef struct pjsip_ auth_session97 { 98 PJ_DECL_LIST_MEMBER(struct pjsip_ auth_session);99 100 pj_str_t realm; 101 pj_bool_t is_proxy; 102 pjsip_auth_qop_type qop_value; 101 typedef struct pjsip_cached_auth 102 { 103 PJ_DECL_LIST_MEMBER(struct pjsip_cached_auth); 104 105 pj_str_t realm; /**< Realm. */ 106 pj_bool_t is_proxy; /**< Server type (401/407) */ 107 pjsip_auth_qop_type qop_value; /**< qop required by server. */ 103 108 #if PJSIP_AUTH_QOP_SUPPORT 104 pj_uint32_t nc; 105 pj_str_t cnonce; 109 pj_uint32_t nc; /**< Nonce count. */ 110 pj_str_t cnonce; /**< Cnonce value. */ 106 111 #endif 107 112 #if PJSIP_AUTH_AUTO_SEND_NEXT 108 pjsip_www_authenticate_hdr *last_chal; 113 pjsip_www_authenticate_hdr *last_chal; /**< Last challenge seen. */ 109 114 #endif 110 115 #if PJSIP_AUTH_HEADER_CACHING 111 pjsip_cached_auth_hdr cached_hdr; 116 pjsip_cached_auth_hdr cached_hdr;/**< List of cached header for 117 each method. */ 112 118 #endif 113 119 114 } pjsip_auth_session; 115 116 117 /** 118 * Create authorization header for the specified credential. 119 * Application calls this function to create Authorization or Proxy-Authorization 120 * header after receiving WWW-Authenticate or Proxy-Authenticate challenge 121 * (normally in 401/407 response). 122 * If authorization session argument is specified, this function will update 123 * the session with the updated information if required (e.g. to update 124 * nonce-count when qop is "auth" or "auth-int"). This function will also 125 * save the authorization header in the session's cached header list. 126 * 127 * @param req_pool Pool to allocate new header for the request. 128 * @param hdr The WWW-Authenticate or Proxy-Authenticate found in 129 * the response. 130 * @param uri The URI for which authorization is targeted to. 131 * @param cred_info The credential to be used for authentication. 132 * @param method The method. 133 * @param sess_pool Session pool to update session or to allocate message 134 * in the cache. May be NULL if auth_sess is NULL. 135 * @param auth_sess If not NULL, this specifies the specific authentication 136 * session to be used or updated. 137 * 138 * @return The Authorization header, which can be typecasted to 139 * Proxy-Authorization. 140 */ 141 PJ_DECL(pjsip_authorization_hdr*) pjsip_auth_respond( 142 pj_pool_t *req_pool, 143 const pjsip_www_authenticate_hdr *hdr, 144 const pjsip_uri *uri, 145 const pjsip_cred_info *cred_info, 146 const pjsip_method *method, 147 pj_pool_t *sess_pool, 148 pjsip_auth_session *auth_sess); 149 150 /** 151 * Verify digest in the authorization request. 152 * 153 * @param hdr The incoming Authorization/Proxy-Authorization header. 154 * @param method The method. 155 * @param password The plaintext password to verify. 156 * 157 * @return Non-zero if authorization succeed. 158 */ 159 PJ_DECL(pj_bool_t) pjsip_auth_verify( const pjsip_authorization_hdr *hdr, 160 const pj_str_t *method, 161 const pjsip_cred_info *cred_info ); 162 163 164 /** 165 * This function can be used to find credential information which matches 166 * the specified realm. 167 * 168 * @param count Number of credentials in the parameter. 169 * @param cred The array of credentials. 170 * @param realm Realm to search. 171 * @param scheme Authentication scheme. 172 * 173 * @return The credential which matches the specified realm. 174 */ 175 PJ_DECL(const pjsip_cred_info*) pjsip_auth_find_cred( unsigned count, 176 const pjsip_cred_info cred[], 177 const pj_str_t *realm, 178 const pj_str_t *scheme ); 120 } pjsip_cached_auth; 121 122 123 /** 124 * This structure describes client authentication sessions. It keeps 125 * all the information needed to authorize the client against all downstream 126 * servers. 127 */ 128 typedef struct pjsip_auth_clt_sess 129 { 130 pj_pool_t *pool; /**< Pool to use. */ 131 pjsip_endpoint *endpt; /**< Endpoint where this belongs. */ 132 unsigned cred_cnt; /**< Number of credentials. */ 133 pjsip_cred_info *cred_info; /**< Array of credential information*/ 134 pjsip_cached_auth cached_auth; /**< Cached authorization info. */ 135 136 } pjsip_auth_clt_sess; 137 138 139 /** 140 * Type of function to lookup credential for the specified name. 141 * 142 * @param pool Pool to initialize the credential info. 143 * @param realm Realm to find the account. 144 * @param acc_name Account name to look for. 145 * @param cred_info The structure to put the credential when it's found. 146 * 147 * @return The function MUST return PJ_SUCCESS when it found 148 * a correct credential for the specified account and 149 * realm. Otherwise it may return PJSIP_EAUTHACCNOTFOUND 150 * or PJSIP_EAUTHACCDISABLED. 151 */ 152 typedef pj_status_t pjsip_auth_lookup_cred( pj_pool_t *pool, 153 const pj_str_t *realm, 154 const pj_str_t *acc_name, 155 pjsip_cred_info *cred_info ); 156 157 /** Flag to specify that server is a proxy. */ 158 #define PJSIP_AUTH_SRV_IS_PROXY 1 159 160 /** 161 * This structure describes server authentication information. 162 */ 163 typedef struct pjsip_auth_srv 164 { 165 pj_str_t realm; /**< Realm to serve. */ 166 pj_bool_t is_proxy; /**< Will issue 407 instead of 401 */ 167 pjsip_auth_lookup_cred *lookup; /**< Lookup function. */ 168 169 } pjsip_auth_srv; 170 171 172 /** 173 * Initialize client authentication session data structure, and set the 174 * session to use pool for its subsequent memory allocation. The argument 175 * options should be set to zero for this PJSIP version. 176 * 177 * @param sess The client authentication session. 178 * @param endpt Endpoint where this session belongs. 179 * @param pool Pool to use. 180 * @param options Must be zero. 181 * 182 * @return PJ_SUCCESS on success. 183 */ 184 PJ_DECL(pj_status_t) pjsip_auth_clt_init( pjsip_auth_clt_sess *sess, 185 pjsip_endpoint *endpt, 186 pj_pool_t *pool, 187 unsigned options); 188 189 190 191 /** 192 * Set the credentials to be used during the session. This will duplicate 193 * the specified credentials using client authentication's pool. 194 * 195 * @param sess The client authentication session. 196 * @param cred_cnt Number of credentials. 197 * @param c Array of credentials. 198 * 199 * @return PJ_SUCCESS on success. 200 */ 201 PJ_DECL(pj_status_t) pjsip_auth_clt_set_credentials( pjsip_auth_clt_sess *sess, 202 int cred_cnt, 203 const pjsip_cred_info *c); 179 204 180 205 … … 195 220 * Authorization/Proxy-Authorization to respond 401/407 response. 196 221 * 197 * @param sess_pool Session level pool, where memory will be allocated from 198 * for data that persists across requests (e.g. caching). 222 * @param sess The client authentication session. 199 223 * @param tdata The request message to be initialized. 200 * @param sess_list List of authorization sessions that have been recorded. 201 * @param cred_count Number of credentials. 202 * @param cred_info Array of credentials. 203 * 204 * @return Zero if successfull. 205 */ 206 PJ_DECL(pj_status_t) pjsip_auth_init_req( pj_pool_t *sess_pool, 207 pjsip_tx_data *tdata, 208 pjsip_auth_session *sess_list, 209 int cred_count, 210 const pjsip_cred_info cred_info[]); 224 * 225 * @return PJ_SUCCESS if successfull. 226 */ 227 PJ_DECL(pj_status_t) pjsip_auth_clt_init_req( pjsip_auth_clt_sess *sess, 228 pjsip_tx_data *tdata ); 229 211 230 212 231 /** … … 216 235 * new authorization header in the authorization cache. 217 236 * 218 * Note that upon return the reference counter of the transmit data 219 * will be incremented. 220 * 221 * @param endpt Endpoint. 222 * @param pool The pool to allocate memory for new cred_info. 223 * @param cached_list Cached authorization headers. 224 * @param cred_count Number of credentials. 225 * @param cred_info Array of credentials to use. 226 * @param tdata The original request message, which normally can be 227 * retrieved from tsx->last_tx. 237 * Note that upon return the reference counter of the new transmit data 238 * will be set to 1. 239 * 240 * @param sess The client authentication session. 228 241 * @param rdata The response message containing 401/407 status. 229 * 230 * @return New transmit data buffer, or NULL if the dialog 231 * can not respond to the authorization challenge. 232 */ 233 PJ_DECL(pjsip_tx_data*) 234 pjsip_auth_reinit_req( pjsip_endpoint *endpt, 235 pj_pool_t *ses_pool, 236 pjsip_auth_session *sess_list, 237 int cred_count, const pjsip_cred_info cred_info[], 238 pjsip_tx_data *tdata, const pjsip_rx_data *rdata); 242 * @param old_request The original request message, which will be re- 243 * created with authorization info. 244 * @param new_request Pointer to receive new request message which 245 * will contain all required authorization headers. 246 * 247 * @return PJ_SUCCESS if new request can be successfully 248 * created to respond all the authentication 249 * challenges. 250 */ 251 PJ_DECL(pj_status_t) pjsip_auth_clt_reinit_req( pjsip_auth_clt_sess *sess, 252 const pjsip_rx_data *rdata, 253 pjsip_tx_data *old_request, 254 pjsip_tx_data **new_request ); 255 256 /** 257 * Initialize server authorization session data structure to serve the 258 * specified realm and to use lookup_func function to look for the credential 259 * info. 260 * 261 * @param pool Pool used to initialize the authentication server. 262 * @param auth_srv The authentication server structure. 263 * @param realm Realm to be served by the server. 264 * @param lookup Account lookup function. 265 * @param options Options, bitmask of: 266 * - PJSIP_AUTH_SRV_IS_PROXY: to specify that the server 267 * will authorize clients as a proxy server (instead of 268 * as UAS), which means that Proxy-Authenticate will 269 * be used instead of WWW-Authenticate. 270 * 271 * @return PJ_SUCCESS on success. 272 */ 273 PJ_DECL(pj_status_t) pjsip_auth_srv_init( pj_pool_t *pool, 274 pjsip_auth_srv *auth_srv, 275 const pj_str_t *realm, 276 pjsip_auth_lookup_cred *lookup, 277 unsigned options ); 278 279 280 /** 281 * Request the authorization server framework to verify the authorization 282 * information in the specified request in rdata. 283 * 284 * @param auth_srv The server authentication structure. 285 * @param rdata Incoming request to be authenticated. 286 * @param status_code When not null, it will be filled with suitable 287 * status code to be sent to the client. 288 * 289 * @return PJ_SUCCESS if request is successfully authenticated. 290 * Otherwise the function may return one of the 291 * following error codes: 292 * - PJSIP_EAUTHNOAUTH 293 * - PJSIP_EINVALIDAUTHSCHEME 294 * - PJSIP_EAUTHACCNOTFOUND 295 * - PJSIP_EAUTHACCDISABLED 296 * - PJSIP_EAUTHINVALIDREALM 297 * - PJSIP_EAUTHINVALIDDIGEST 298 */ 299 PJ_DECL(pj_status_t) pjsip_auth_srv_verify( pjsip_auth_srv *auth_srv, 300 pjsip_rx_data *rdata, 301 int *status_code ); 302 303 304 /** 305 * Add authentication challenge headers to the outgoing response in tdata. 306 * Application may specify its customized nonce and opaque for the challenge, 307 * or can leave the value to NULL to make the function fills them in with 308 * random characters. 309 * 310 * @param auth_srv The server authentication structure. 311 * @param qop Optional qop value. 312 * @param nonce Optional nonce value. 313 * @param opaque Optional opaque value. 314 * @param stale Stale indication. 315 * @param tdata The outgoing response message. The response must have 316 * 401 or 407 response code. 317 * 318 * @return PJ_SUCCESS on success. 319 */ 320 PJ_DECL(pj_status_t) pjsip_auth_srv_challenge( pjsip_auth_srv *auth_srv, 321 const pj_str_t *qop, 322 const pj_str_t *nonce, 323 const pj_str_t *opaque, 324 pj_bool_t stale, 325 pjsip_tx_data *tdata); 326 239 327 240 328 /** … … 242 330 */ 243 331 332 244 333 PJ_END_DECL 245 334 335 246 336 #endif /* __PJSIP_AUTH_SIP_AUTH_H__ */ 247 337 -
pjproject/trunk/pjsip/include/pjsip/sip_errno.h
r109 r123 80 80 81 81 /************************************************************ 82 * GENERIC SIP ERRORS82 * GENERIC/GENERAL SIP ERRORS 83 83 ***********************************************************/ 84 84 /** … … 97 97 */ 98 98 #define PJSIP_ESHUTDOWN (PJSIP_ERRNO_START_PJSIP + 3) /* 171003 */ 99 /** 100 * @hideinitializer 101 * SIP object is not initialized. 102 */ 103 #define PJSIP_ENOTINITIALIZED (PJSIP_ERRNO_START_PJSIP + 4) /* 171004 */ 99 104 100 105 … … 109 114 /** 110 115 * @hideinitializer 116 * Expecting request message. 117 */ 118 #define PJSIP_ENOTREQUESTMSG (PJSIP_ERRNO_START_PJSIP + 21) /* 171021 */ 119 /** 120 * @hideinitializer 121 * Expecting response message. 122 */ 123 #define PJSIP_ENOTRESPONSEMSG (PJSIP_ERRNO_START_PJSIP + 22) /* 171022 */ 124 /** 125 * @hideinitializer 126 * Message too long. See also PJSIP_ERXOVERFLOW. 127 */ 128 #define PJSIP_EMSGTOOLONG (PJSIP_ERRNO_START_PJSIP + 23) /* 171023 */ 129 /** 130 * @hideinitializer 131 * Message not completely received. 132 */ 133 #define PJSIP_EPARTIALMSG (PJSIP_ERRNO_START_PJSIP + 24) /* 171024 */ 134 135 /** 136 * @hideinitializer 137 * Status code is invalid. 138 */ 139 #define PJSIP_EINVALIDSTATUS (PJSIP_ERRNO_START_PJSIP + 30) /* 171030 */ 140 141 /** 142 * @hideinitializer 111 143 * Unsupported URL scheme. 112 144 */ 113 #define PJSIP_EINVALIDSCHEME (PJSIP_ERRNO_START_PJSIP + 21) /* 171021 */ 114 /** 115 * @hideinitializer 116 * Message too long. See also PJSIP_ERXOVERFLOW. 117 */ 118 #define PJSIP_EMSGTOOLONG (PJSIP_ERRNO_START_PJSIP + 22) /* 171022 */ 119 /** 120 * @hideinitializer 121 * Message not completely received. 122 */ 123 #define PJSIP_EPARTIALMSG (PJSIP_ERRNO_START_PJSIP + 23) /* 171023 */ 145 #define PJSIP_EINVALIDSCHEME (PJSIP_ERRNO_START_PJSIP + 40) /* 171040 */ 124 146 /** 125 147 * @hideinitializer 126 148 * Missing Request-URI. 127 149 */ 128 #define PJSIP_EMISSINGREQURI (PJSIP_ERRNO_START_PJSIP + 24) /* 171024 */ 150 #define PJSIP_EMISSINGREQURI (PJSIP_ERRNO_START_PJSIP + 41) /* 171041 */ 151 /** 152 * @hideinitializer 153 * Invalid request URI. 154 */ 155 #define PJSIP_EINVALIDREQURI (PJSIP_ERRNO_START_PJSIP + 42) /* 171042 */ 156 /** 157 * @hideinitializer 158 * URI is too long. 159 */ 160 #define PJSIP_EURITOOLONG (PJSIP_ERRNO_START_PJSIP + 43) /* 171043 */ 161 129 162 /** 130 163 * @hideinitializer 131 164 * Missing required header(s). 132 165 */ 133 #define PJSIP_EMISSINGHDR (PJSIP_ERRNO_START_PJSIP + 25) /* 171025 */ 166 #define PJSIP_EMISSINGHDR (PJSIP_ERRNO_START_PJSIP + 50) /* 171050 */ 167 /** 168 * @hideinitializer 169 * Invalid header field. 170 */ 171 #define PJSIP_EINVALIDHDR (PJSIP_ERRNO_START_PJSIP + 51) /* 171051 */ 172 /** 173 * @hideinitializer 174 * Invalid Via header in response (sent-by, etc). 175 */ 176 #define PJSIP_EINVALIDVIA (PJSIP_ERRNO_START_PJSIP + 52) /* 171052 */ 177 /** 178 * @hideinitializer 179 * Multiple Via headers in response. 180 */ 181 #define PJSIP_EMULTIPLEVIA (PJSIP_ERRNO_START_PJSIP + 53) /* 171053 */ 134 182 /** 135 183 * @hideinitializer 136 184 * Missing message body. 137 185 */ 138 #define PJSIP_EMISSINGBODY (PJSIP_ERRNO_START_PJSIP + 26) /* 171026 */ 139 /** 140 * @hideinitializer 141 * Invalid Via header in response (sent-by, etc). 142 */ 143 #define PJSIP_EINVALIDVIA (PJSIP_ERRNO_START_PJSIP + 27) /* 171027 */ 144 /** 145 * @hideinitializer 146 * Multiple Via headers in response. 147 */ 148 #define PJSIP_EMULTIPLEVIA (PJSIP_ERRNO_START_PJSIP + 28) /* 171028 */ 149 /** 150 * @hideinitializer 151 * Invalid request URI. 152 */ 153 #define PJSIP_EINVALIDREQURI (PJSIP_ERRNO_START_PJSIP + 29) /* 171029 */ 154 /** 155 * @hideinitializer 156 * Expecting request message. 157 */ 158 #define PJSIP_ENOTREQUESTMSG (PJSIP_ERRNO_START_PJSIP + 30) /* 171030 */ 159 /** 160 * @hideinitializer 161 * Expecting response message. 162 */ 163 #define PJSIP_ENOTRESPONSEMSG (PJSIP_ERRNO_START_PJSIP + 31) /* 171031 */ 164 /** 165 * @hideinitializer 166 * Invalid header field. 167 */ 168 #define PJSIP_EINVALIDHDR (PJSIP_ERRNO_START_PJSIP + 32) /* 171032 */ 186 #define PJSIP_EMISSINGBODY (PJSIP_ERRNO_START_PJSIP + 54) /* 171054 */ 169 187 170 188 … … 176 194 * Unsupported transport type. 177 195 */ 178 #define PJSIP_EUNSUPTRANSPORT (PJSIP_ERRNO_START_PJSIP + 40) /* 171040 */196 #define PJSIP_EUNSUPTRANSPORT (PJSIP_ERRNO_START_PJSIP + 60) /* 171060 */ 179 197 /** 180 198 * @hideinitializer 181 199 * Buffer is being sent, operation still pending. 182 200 */ 183 #define PJSIP_EPENDINGTX (PJSIP_ERRNO_START_PJSIP + 41) /* 171041 */201 #define PJSIP_EPENDINGTX (PJSIP_ERRNO_START_PJSIP + 61) /* 171061 */ 184 202 /** 185 203 * @hideinitializer 186 204 * Rx buffer overflow. See also PJSIP_EMSGTOOLONG. 187 205 */ 188 #define PJSIP_ERXOVERFLOW (PJSIP_ERRNO_START_PJSIP + 42) /* 171042 */206 #define PJSIP_ERXOVERFLOW (PJSIP_ERRNO_START_PJSIP + 62) /* 171062 */ 189 207 /** 190 208 * @hideinitializer … … 192 210 * transmit data has been deleted on return of pjsip_tx_data_dec_ref(). 193 211 */ 194 #define PJSIP_EBUFDESTROYED (PJSIP_ERRNO_START_PJSIP + 43) /* 171043 */212 #define PJSIP_EBUFDESTROYED (PJSIP_ERRNO_START_PJSIP + 63) /* 171063 */ 195 213 196 214 … … 202 220 * Transaction has just been destroyed. 203 221 */ 204 #define PJSIP_ETSXDESTROYED (PJSIP_ERRNO_START_PJSIP + 60) /* 171060 */222 #define PJSIP_ETSXDESTROYED (PJSIP_ERRNO_START_PJSIP + 70) /* 171070 */ 205 223 206 224 … … 270 288 271 289 290 /************************************************************ 291 * AUTHENTICATION FRAMEWORK 292 ***********************************************************/ 293 /** 294 * @hideinitializer 295 * Credential failed to authenticate. 296 */ 297 #define PJSIP_EFAILEDCREDENTIAL (PJSIP_ERRNO_START_PJSIP + 100) /* 171100 */ 298 /** 299 * @hideinitializer 300 * No suitable credential. 301 */ 302 #define PJSIP_ENOCREDENTIAL (PJSIP_ERRNO_START_PJSIP + 101) /* 171101 */ 303 /** 304 * @hideinitializer 305 * Invalid/unsupported algorithm. 306 */ 307 #define PJSIP_EINVALIDALGORITHM (PJSIP_ERRNO_START_PJSIP + 102) /* 171102 */ 308 /** 309 * @hideinitializer 310 * Invalid/unsupported qop. 311 */ 312 #define PJSIP_EINVALIDQOP (PJSIP_ERRNO_START_PJSIP + 103) /* 171103 */ 313 /** 314 * @hideinitializer 315 * Invalid/unsupported authentication scheme. 316 */ 317 #define PJSIP_EINVALIDAUTHSCHEME (PJSIP_ERRNO_START_PJSIP + 104)/* 171104 */ 318 /** 319 * @hideinitializer 320 * No previous challenge. 321 */ 322 #define PJSIP_EAUTHNOPREVCHAL (PJSIP_ERRNO_START_PJSIP + 105) /* 171105 */ 323 /** 324 * @hideinitializer 325 * No authorization is found. 326 */ 327 #define PJSIP_EAUTHNOAUTH (PJSIP_ERRNO_START_PJSIP + 106) /* 171106 */ 328 /** 329 * @hideinitializer 330 * Account not found. 331 */ 332 #define PJSIP_EAUTHACCNOTFOUND (PJSIP_ERRNO_START_PJSIP + 107) /* 171107 */ 333 /** 334 * @hideinitializer 335 * Account is disabled. 336 */ 337 #define PJSIP_EAUTHACCDISABLED (PJSIP_ERRNO_START_PJSIP + 108) /* 171108 */ 338 /** 339 * @hideinitializer 340 * Invalid realm. 341 */ 342 #define PJSIP_EAUTHINVALIDREALM (PJSIP_ERRNO_START_PJSIP + 109) /* 171109 */ 343 /** 344 * @hideinitializer 345 * Invalid digest. 346 */ 347 #define PJSIP_EAUTHINVALIDDIGEST (PJSIP_ERRNO_START_PJSIP+110) /* 171110 */ 348 272 349 273 350 PJ_END_DECL -
pjproject/trunk/pjsip/include/pjsip/sip_transport.h
r109 r123 219 219 220 220 /** The Call-ID header as found in the message. */ 221 pj _str_t call_id;221 pjsip_cid_hdr *cid; 222 222 223 223 /** The From header as found in the message. */ -
pjproject/trunk/pjsip/src/pjsip-ua/sip_ua.c
r65 r123 42 42 * Static prototypes. 43 43 */ 44 static pj_status_t ua_init( pjsip_endpoint *endpt, 45 struct pjsip_module *mod, pj_uint32_t id ); 46 static pj_status_t ua_start( struct pjsip_module *mod ); 47 static pj_status_t ua_deinit( struct pjsip_module *mod ); 44 static pj_status_t ua_load(pjsip_endpoint *endpt); 45 static pj_status_t ua_unload(void); 48 46 static void ua_tsx_handler( struct pjsip_module *mod, pjsip_event *evt ); 49 47 static pjsip_dlg *find_dialog( pjsip_user_agent *ua, … … 54 52 55 53 /* 56 * Default UA instance.57 */58 static pjsip_user_agent ua_instance;59 60 /*61 54 * Module interface. 62 55 */ 63 static struct pjsip_module mod_ua = 64 { 65 { "User-Agent", 10 }, /* Name. */ 66 0, /* Flag */ 67 128, /* Priority */ 68 NULL, /* User agent instance, initialized by APP. */ 69 0, /* Number of methods supported (will be initialized later). */ 70 { 0 }, /* Array of methods (will be initialized later) */ 71 &ua_init, /* init_module() */ 72 &ua_start, /* start_module() */ 73 &ua_deinit, /* deinit_module() */ 74 &ua_tsx_handler, /* tsx_handler() */ 56 static struct user_agent 57 { 58 pjsip_module mod; 59 pj_pool_t *pool; 60 pjsip_endpoint *endpt; 61 pj_mutex_t *mutex; 62 pj_hash_table_t *dlg_table; 63 pjsip_dialog dlg_list; 64 65 } mod_ua = 66 { 67 { 68 NULL, NULL, /* prev, next. */ 69 { "mod-ua", 6 }, /* Name. */ 70 -1, /* Id */ 71 PJSIP_MOD_PRIORITY_UA_PROXY_LAYER, /* Priority */ 72 NULL, /* User data. */ 73 0, /* Number of methods supported. */ 74 { 0 }, /* Array of methods */ 75 &ua_load, /* load() */ 76 NULL, /* start() */ 77 NULL, /* stop() */ 78 &ua_unload, /* unload() */ 79 NULL, /* on_rx_request() */ 80 NULL, /* on_rx_response() */ 81 NULL, /* on_tx_request. */ 82 NULL, /* on_tx_response() */ 83 NULL, /* on_tsx_state() */ 84 } 75 85 }; 76 86 … … 78 88 * Initialize user agent instance. 79 89 */ 80 static pj_status_t ua_init( pjsip_endpoint *endpt, 81 struct pjsip_module *mod, pj_uint32_t id ) 82 { 83 static pjsip_method m_invite, m_ack, m_cancel, m_bye; 84 pjsip_user_agent *ua = mod->mod_data; 90 static pj_status_t ua_load( pjsip_endpoint *endpt ) 91 { 85 92 extern int pjsip_dlg_lock_tls_id; /* defined in sip_dialog.c */ 86 87 pjsip_method_set( &m_invite, PJSIP_INVITE_METHOD ); 88 pjsip_method_set( &m_ack, PJSIP_ACK_METHOD ); 89 pjsip_method_set( &m_cancel, PJSIP_CANCEL_METHOD ); 90 pjsip_method_set( &m_bye, PJSIP_BYE_METHOD ); 91 92 mod->method_cnt = 4; 93 mod->methods[0] = &m_invite; 94 mod->methods[1] = &m_ack; 95 mod->methods[2] = &m_cancel; 96 mod->methods[3] = &m_bye; 93 pj_status_t status; 97 94 98 95 /* Initialize the user agent. */ 99 ua->endpt = endpt; 100 ua->pool = pjsip_endpt_create_pool(endpt, "pua%p", PJSIP_POOL_LEN_UA, 101 PJSIP_POOL_INC_UA); 102 if (!ua->pool) { 103 return -1; 104 } 105 ua->mod_id = id; 106 ua->mutex = pj_mutex_create(ua->pool, " ua%p", 0); 107 if (!ua->mutex) { 108 return -1; 109 } 110 ua->dlg_table = pj_hash_create(ua->pool, PJSIP_MAX_DIALOG_COUNT); 111 if (ua->dlg_table == NULL) { 112 return -1; 113 } 114 pj_list_init(&ua->dlg_list); 96 mod_ua.endpt = endpt; 97 status = pjsip_endpt_create_pool( endpt, "pua%p", PJSIP_POOL_LEN_UA, 98 PJSIP_POOL_INC_UA, &mod_ua.pool); 99 if (status != PJ_SUCCESS) 100 return status; 101 102 status = pj_mutex_create_recursive(mod_ua.pool, " ua%p", &mod_ua.mutex); 103 if (status != PJ_SUCCESS) 104 return status; 105 106 mod_ua.dlg_table = pj_hash_create(mod_ua.pool, PJSIP_MAX_DIALOG_COUNT); 107 if (ua->dlg_table == NULL) 108 return PJ_ENOMEM; 109 110 pj_list_init(&mod_ua.dlg_list); 115 111 116 112 /* Initialize dialog lock. */ … … 121 117 pj_thread_local_set(pjsip_dlg_lock_tls_id, NULL); 122 118 123 return 0; 124 } 125 126 /* 127 * Start user agent instance. 128 */ 129 static pj_status_t ua_start( struct pjsip_module *mod ) 130 { 131 PJ_UNUSED_ARG(mod) 132 return 0; 119 return PJ_SUCCESS; 133 120 } 134 121 … … 136 123 * Destroy user agent. 137 124 */ 138 static pj_status_t ua_deinit( struct pjsip_module *mod ) 139 { 140 pjsip_user_agent *ua = mod->mod_data; 141 142 pj_mutex_unlock(ua->mutex); 125 static pj_status_t ua_unload() 126 { 127 pj_mutex_unlock(mod_ua.mutex); 143 128 144 129 /* Release pool */ 145 if (ua->pool) { 146 pjsip_endpt_destroy_pool( ua->endpt, ua->pool ); 147 } 148 return 0; 149 } 150 151 /* 152 * Get the module interface for the UA module. 153 */ 154 PJ_DEF(pjsip_module*) pjsip_ua_get_module(void) 155 { 156 mod_ua.mod_data = &ua_instance; 157 return &mod_ua; 158 } 159 160 /* 161 * Register callback to receive dialog notifications. 162 */ 163 PJ_DEF(void) pjsip_ua_set_dialog_callback( pjsip_user_agent *ua, 164 pjsip_dlg_callback *cb ) 165 { 166 ua->dlg_cb = cb; 130 if (mod_ua.pool) { 131 pjsip_endpt_destroy_pool( mod_ua.endpt, mod_ua.pool ); 132 } 133 return PJ_SUCCESS; 167 134 } 168 135 -
pjproject/trunk/pjsip/src/pjsip/sip_auth_client.c
r112 r123 17 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 18 */ 19 19 20 #include <pjsip/sip_auth.h> 20 21 #include <pjsip/sip_auth_parser.h> /* just to get pjsip_DIGEST_STR */ 21 22 #include <pjsip/sip_transport.h> 22 23 #include <pjsip/sip_endpoint.h> 24 #include <pjsip/sip_errno.h> 23 25 #include <pjlib-util/md5.h> 24 26 #include <pj/log.h> … … 29 31 #include <pj/ctype.h> 30 32 31 /* Length of digest string. */ 32 #define MD5STRLEN 32 33 34 /* Maximum stack size we use for storing username+realm+password etc. */ 35 #define MAX_TEMP 128 33 36 34 37 35 /* A macro just to get rid of type mismatch between char and unsigned char */ … … 39 37 40 38 /* Logging. */ 41 #define THIS_FILE "sip_auth .c"39 #define THIS_FILE "sip_auth_client.c" 42 40 #if 0 43 41 # define AUTH_TRACE_(expr) PJ_LOG(3, expr) … … 46 44 #endif 47 45 48 static const char hex[] = "0123456789abcdef";49 50 46 /* Transform digest to string. 51 * output must be at least MD5STRLEN+1 bytes.47 * output must be at least PJSIP_MD5STRLEN+1 bytes. 52 48 * 53 49 * NOTE: THE OUTPUT STRING IS NOT NULL TERMINATED! … … 55 51 static void digest2str(const unsigned char digest[], char *output) 56 52 { 57 char *p = output;58 53 int i; 59 60 54 for (i = 0; i<16; ++i) { 61 int val = digest[i];62 *p++ = hex[val >> 4];63 *p++ = hex[val & 0x0F]; 64 65 } 55 pj_val_to_hex_digit(digest[i], output); 56 output += 2; 57 } 58 } 59 66 60 67 61 /* … … 69 63 * digest ASCII in 'result'. 70 64 */ 71 static voidcreate_digest( pj_str_t *result,72 const pj_str_t *nonce,73 const pj_str_t *nc,74 const pj_str_t *cnonce,75 const pj_str_t *qop,76 const pj_str_t *uri,77 const pjsip_cred_info *cred_info,78 const pj_str_t *method)79 { 80 char ha1[ MD5STRLEN];81 char ha2[ MD5STRLEN];65 void pjsip_auth_create_digest( pj_str_t *result, 66 const pj_str_t *nonce, 67 const pj_str_t *nc, 68 const pj_str_t *cnonce, 69 const pj_str_t *qop, 70 const pj_str_t *uri, 71 const pjsip_cred_info *cred_info, 72 const pj_str_t *method) 73 { 74 char ha1[PJSIP_MD5STRLEN]; 75 char ha2[PJSIP_MD5STRLEN]; 82 76 unsigned char digest[16]; 83 77 pj_md5_context pms; 84 78 85 pj_assert(result->slen >= MD5STRLEN);79 pj_assert(result->slen >= PJSIP_MD5STRLEN); 86 80 87 81 AUTH_TRACE_((THIS_FILE, "Begin creating digest")); … … 128 122 ***/ 129 123 pj_md5_init(&pms); 130 MD5_APPEND( &pms, ha1, MD5STRLEN);124 MD5_APPEND( &pms, ha1, PJSIP_MD5STRLEN); 131 125 MD5_APPEND( &pms, ":", 1); 132 126 MD5_APPEND( &pms, nonce->ptr, nonce->slen); … … 140 134 } 141 135 MD5_APPEND( &pms, ":", 1); 142 MD5_APPEND( &pms, ha2, MD5STRLEN);136 MD5_APPEND( &pms, ha2, PJSIP_MD5STRLEN); 143 137 144 138 /* This is the final response digest. */ … … 146 140 147 141 /* Convert digest to string and store in chal->response. */ 148 result->slen = MD5STRLEN;142 result->slen = PJSIP_MD5STRLEN; 149 143 digest2str(digest, result->ptr); 150 144 … … 207 201 PJ_LOG(4,(THIS_FILE, "Unsupported digest algorithm \"%.*s\"", 208 202 chal->algorithm.slen, chal->algorithm.ptr)); 209 return -1;203 return PJSIP_EINVALIDALGORITHM; 210 204 } 211 205 … … 219 213 220 214 /* Allocate memory. */ 221 cred->response.ptr = pj_pool_alloc(pool, MD5STRLEN);222 cred->response.slen = MD5STRLEN;215 cred->response.ptr = pj_pool_alloc(pool, PJSIP_MD5STRLEN); 216 cred->response.slen = PJSIP_MD5STRLEN; 223 217 224 218 if (chal->qop.slen == 0) { … … 226 220 227 221 /* Convert digest to string and store in chal->response. */ 228 create_digest( &cred->response, &cred->nonce, NULL, NULL, NULL,229 222 pjsip_auth_create_digest( &cred->response, &cred->nonce, NULL, NULL, 223 NULL, uri, cred_info, method); 230 224 231 225 } else if (has_auth_qop(pool, &chal->qop)) { … … 244 238 } 245 239 246 create_digest( &cred->response, &cred->nonce, &cred->nc, cnonce, 247 &pjsip_AUTH_STR, uri, cred_info, method ); 240 pjsip_auth_create_digest( &cred->response, &cred->nonce, &cred->nc, 241 cnonce, &pjsip_AUTH_STR, uri, cred_info, 242 method ); 248 243 249 244 } else { … … 251 246 PJ_LOG(4,(THIS_FILE, "Unsupported qop offer %.*s", 252 247 chal->qop.slen, chal->qop.ptr)); 253 return -1;254 } 255 256 return 0;257 } 258 259 #if PJSIP_AUTH_QOP_SUPPORT248 return PJSIP_EINVALIDQOP; 249 } 250 251 return PJ_SUCCESS; 252 } 253 254 #if defined(PJSIP_AUTH_QOP_SUPPORT) && PJSIP_AUTH_QOP_SUPPORT!=0 260 255 /* 261 256 * Update authentication session with a challenge. 262 257 */ 263 258 static void update_digest_session( pj_pool_t *ses_pool, 264 pjsip_ auth_session *auth_sess,259 pjsip_cached_auth *cached_auth, 265 260 const pjsip_www_authenticate_hdr *hdr ) 266 261 { … … 269 264 270 265 /* Initialize cnonce and qop if not present. */ 271 if ( auth_sess->cnonce.slen == 0) {266 if (cached_auth->cnonce.slen == 0) { 272 267 /* Save the whole challenge */ 273 auth_sess->last_chal = pjsip_hdr_clone(ses_pool, hdr);268 cached_auth->last_chal = pjsip_hdr_clone(ses_pool, hdr); 274 269 275 270 /* Create cnonce */ 276 pj_create_unique_string( ses_pool, & auth_sess->cnonce );271 pj_create_unique_string( ses_pool, &cached_auth->cnonce ); 277 272 278 273 /* Initialize nonce-count */ 279 auth_sess->nc = 1;274 cached_auth->nc = 1; 280 275 281 276 /* Save realm. */ 282 pj_assert( auth_sess->realm.slen != 0);283 if ( auth_sess->realm.slen == 0) {284 pj_strdup(ses_pool, & auth_sess->realm,277 pj_assert(cached_auth->realm.slen != 0); 278 if (cached_auth->realm.slen == 0) { 279 pj_strdup(ses_pool, &cached_auth->realm, 285 280 &hdr->challenge.digest.realm); 286 281 } … … 289 284 /* Update last_nonce and nonce-count */ 290 285 if (!pj_strcmp(&hdr->challenge.digest.nonce, 291 & auth_sess->last_chal->challenge.digest.nonce))286 &cached_auth->last_chal->challenge.digest.nonce)) 292 287 { 293 288 /* Same nonce, increment nonce-count */ 294 ++ auth_sess->nc;289 ++cached_auth->nc; 295 290 } else { 296 291 /* Server gives new nonce. */ 297 pj_strdup(ses_pool, & auth_sess->last_chal->challenge.digest.nonce,292 pj_strdup(ses_pool, &cached_auth->last_chal->challenge.digest.nonce, 298 293 &hdr->challenge.digest.nonce); 299 294 /* Has the opaque changed? */ 300 if (pj_strcmp(& auth_sess->last_chal->challenge.digest.opaque,295 if (pj_strcmp(&cached_auth->last_chal->challenge.digest.opaque, 301 296 &hdr->challenge.digest.opaque)) 302 297 { 303 298 pj_strdup(ses_pool, 304 & auth_sess->last_chal->challenge.digest.opaque,299 &cached_auth->last_chal->challenge.digest.opaque, 305 300 &hdr->challenge.digest.opaque); 306 301 } 307 auth_sess->nc = 1;302 cached_auth->nc = 1; 308 303 } 309 304 } … … 312 307 313 308 314 /* Find authentication session in the list. */315 static pjsip_ auth_session *find_session( pjsip_auth_session *sess_list,316 const pj_str_t *realm )317 { 318 pjsip_ auth_session *sess = sess_list->next;319 while ( sess != sess_list) {320 if (pj_stricmp(& sess->realm, realm) == 0)321 return sess;322 sess = sess->next;309 /* Find cached authentication in the list for the specified realm. */ 310 static pjsip_cached_auth *find_cached_auth( pjsip_auth_clt_sess *sess, 311 const pj_str_t *realm ) 312 { 313 pjsip_cached_auth *auth = sess->cached_auth.next; 314 while (auth != &sess->cached_auth) { 315 if (pj_stricmp(&auth->realm, realm) == 0) 316 return auth; 317 auth = auth->next; 323 318 } 324 319 325 320 return NULL; 326 321 } 322 323 /* Find credential to use for the specified realm and auth scheme. */ 324 static const pjsip_cred_info* auth_find_cred( const pjsip_auth_clt_sess *sess, 325 const pj_str_t *realm, 326 const pj_str_t *auth_scheme) 327 { 328 unsigned i; 329 PJ_UNUSED_ARG(auth_scheme); 330 for (i=0; i<sess->cred_cnt; ++i) { 331 if (pj_stricmp(&sess->cred_info[i].realm, realm) == 0) 332 return &sess->cred_info[i]; 333 } 334 return NULL; 335 } 336 337 338 /* Init client session. */ 339 PJ_DEF(pj_status_t) pjsip_auth_clt_init( pjsip_auth_clt_sess *sess, 340 pjsip_endpoint *endpt, 341 pj_pool_t *pool, 342 unsigned options) 343 { 344 PJ_ASSERT_RETURN(sess && endpt && pool && (options==0), PJ_EINVAL); 345 346 sess->pool = pool; 347 sess->endpt = endpt; 348 sess->cred_cnt = 0; 349 sess->cred_info = NULL; 350 pj_list_init(&sess->cached_auth); 351 352 return PJ_SUCCESS; 353 } 354 355 356 /* Set client credentials. */ 357 PJ_DEF(pj_status_t) pjsip_auth_clt_set_credentials( pjsip_auth_clt_sess *sess, 358 int cred_cnt, 359 const pjsip_cred_info *c) 360 { 361 PJ_ASSERT_RETURN(sess && cred_cnt && c, PJ_EINVAL); 362 363 sess->cred_info = pj_pool_alloc(sess->pool, cred_cnt * sizeof(*c)); 364 pj_memcpy(sess->cred_info, c, cred_cnt * sizeof(*c)); 365 sess->cred_cnt = cred_cnt; 366 367 return PJ_SUCCESS; 368 } 369 327 370 328 371 /* … … 330 373 * in WWW-Authenticate/Proxy-Authenticate header. 331 374 */ 332 PJ_DEF(pjsip_authorization_hdr*) 333 pjsip_auth_respond( pj_pool_t *req_pool,334 const pjsip_www_authenticate_hdr *hdr,335 const pjsip_uri *uri,336 const pjsip_cred_info *cred_info,337 const pjsip_method *method,338 pj_pool_t *sess_pool,339 pjsip_auth_session *auth_sess)340 { 341 pjsip_authorization_hdr * auth;375 static pj_status_t auth_respond( pj_pool_t *req_pool, 376 const pjsip_www_authenticate_hdr *hdr, 377 const pjsip_uri *uri, 378 const pjsip_cred_info *cred_info, 379 const pjsip_method *method, 380 pj_pool_t *sess_pool, 381 pjsip_cached_auth *cached_auth, 382 pjsip_authorization_hdr **p_h_auth) 383 { 384 pjsip_authorization_hdr *hauth; 342 385 char tmp[PJSIP_MAX_URL_SIZE]; 343 386 pj_str_t uri_str; 344 387 pj_pool_t *pool; 345 346 pj_assert(hdr != NULL); 347 pj_assert(uri != NULL);348 pj_assert(cred_info != NULL);349 pj_assert(method != NULL);388 pj_status_t status; 389 390 /* Verify arguments. */ 391 PJ_ASSERT_RETURN(req_pool && hdr && uri && cred_info && method && 392 sess_pool && cached_auth && p_h_auth, PJ_EINVAL); 350 393 351 394 /* Print URL in the original request. */ 352 395 uri_str.ptr = tmp; 353 uri_str.slen = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, uri, tmp, 396 uri_str.slen = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, uri, tmp,sizeof(tmp)); 354 397 if (uri_str.slen < 1) { 355 398 pj_assert(!"URL is too long!"); 356 PJ_LOG(4,(THIS_FILE, "Unable to authorize: URI is too long!")); 357 return NULL; 399 return PJSIP_EURITOOLONG; 358 400 } 359 401 … … 371 413 372 414 if (hdr->type == PJSIP_H_WWW_AUTHENTICATE) 373 auth = pjsip_authorization_hdr_create(pool);415 hauth = pjsip_authorization_hdr_create(pool); 374 416 else if (hdr->type == PJSIP_H_PROXY_AUTHENTICATE) 375 auth = pjsip_proxy_authorization_hdr_create(pool);417 hauth = pjsip_proxy_authorization_hdr_create(pool); 376 418 else { 377 pj_assert( 0);378 return NULL;419 pj_assert(!"Invalid response header!"); 420 return PJSIP_EINVALIDHDR; 379 421 } 380 422 381 423 /* Only support digest scheme at the moment. */ 382 424 if (!pj_stricmp(&hdr->scheme, &pjsip_DIGEST_STR)) { 383 pj_status_t rc;384 425 pj_str_t *cnonce = NULL; 385 426 pj_uint32_t nc = 1; … … 388 429 # if PJSIP_AUTH_QOP_SUPPORT 389 430 { 390 if ( auth_sess) {391 update_digest_session( sess_pool, auth_sess, hdr );392 393 cnonce = & auth_sess->cnonce;394 nc = auth_sess->nc;431 if (cached_auth) { 432 update_digest_session( sess_pool, cached_auth, hdr ); 433 434 cnonce = &cached_auth->cnonce; 435 nc = cached_auth->nc; 395 436 } 396 437 } 397 438 # endif /* PJSIP_AUTH_QOP_SUPPORT */ 398 439 399 auth->scheme = pjsip_DIGEST_STR;400 rc = respond_digest( pool, &auth->credential.digest,401 402 403 if ( rc != 0)404 return NULL;440 hauth->scheme = pjsip_DIGEST_STR; 441 status = respond_digest( pool, &hauth->credential.digest, 442 &hdr->challenge.digest, &uri_str, cred_info, 443 cnonce, nc, &method->name); 444 if (status != PJ_SUCCESS) 445 return status; 405 446 406 447 /* Set qop type in auth session the first time only. */ 407 if (hdr->challenge.digest.qop.slen != 0 && auth_sess) {408 if ( auth_sess->qop_value == PJSIP_AUTH_QOP_NONE) {409 pj_str_t *qop_val = & auth->credential.digest.qop;448 if (hdr->challenge.digest.qop.slen != 0 && cached_auth) { 449 if (cached_auth->qop_value == PJSIP_AUTH_QOP_NONE) { 450 pj_str_t *qop_val = &hauth->credential.digest.qop; 410 451 if (!pj_strcmp(qop_val, &pjsip_AUTH_STR)) { 411 auth_sess->qop_value = PJSIP_AUTH_QOP_AUTH;452 cached_auth->qop_value = PJSIP_AUTH_QOP_AUTH; 412 453 } else { 413 auth_sess->qop_value = PJSIP_AUTH_QOP_UNKNOWN;454 cached_auth->qop_value = PJSIP_AUTH_QOP_UNKNOWN; 414 455 } 415 456 } 416 457 } 417 458 } else { 418 auth = NULL;459 return PJSIP_EINVALIDAUTHSCHEME; 419 460 } 420 461 … … 424 465 # if PJSIP_AUTH_HEADER_CACHING 425 466 { 426 if ( auth && auth_sess && auth_sess->qop_value == PJSIP_AUTH_QOP_NONE) {467 if (hauth && cached_auth && cached_auth->qop_value == PJSIP_AUTH_QOP_NONE) { 427 468 pjsip_cached_auth_hdr *cached_hdr; 428 469 429 470 /* Delete old header with the same method. */ 430 cached_hdr = auth_sess->cached_hdr.next;431 while (cached_hdr != & auth_sess->cached_hdr) {471 cached_hdr = cached_auth->cached_hdr.next; 472 while (cached_hdr != &cached_auth->cached_hdr) { 432 473 if (pjsip_method_cmp(method, &cached_hdr->method)==0) 433 474 break; … … 436 477 437 478 /* Save the header to the list. */ 438 if (cached_hdr != & auth_sess->cached_hdr) {439 cached_hdr->hdr = auth;479 if (cached_hdr != &cached_auth->cached_hdr) { 480 cached_hdr->hdr = hauth; 440 481 } else { 441 482 cached_hdr = pj_pool_alloc(pool, sizeof(*cached_hdr)); 442 483 pjsip_method_copy( pool, &cached_hdr->method, method); 443 cached_hdr->hdr = auth;444 pj_list_insert_before( & auth_sess->cached_hdr, cached_hdr );484 cached_hdr->hdr = hauth; 485 pj_list_insert_before( &cached_auth->cached_hdr, cached_hdr ); 445 486 } 446 487 } … … 448 489 # endif 449 490 450 return auth; 451 452 } 453 454 /* Verify incoming Authorization/Proxy-Authorization header against existing 455 * credentials. Will return TRUE if the authorization request matches any of 456 * the credential. 457 */ 458 PJ_DEF(pj_bool_t) pjsip_auth_verify(const pjsip_authorization_hdr *hdr, 459 const pj_str_t *method, 460 const pjsip_cred_info *cred_info ) 461 { 462 if (pj_stricmp(&hdr->scheme, &pjsip_DIGEST_STR) == 0) { 463 char digest_buf[MD5STRLEN]; 464 pj_str_t digest; 465 const pjsip_digest_credential *dig = &hdr->credential.digest; 466 467 /* Check that username match. */ 468 if (pj_strcmp(&dig->username, &cred_info->username) != 0) 469 return PJ_FALSE; 470 471 /* Check that realm match. */ 472 if (pj_strcmp(&dig->realm, &cred_info->realm) != 0) 473 return PJ_FALSE; 474 475 /* Prepare for our digest calculation. */ 476 digest.ptr = digest_buf; 477 digest.slen = MD5STRLEN; 478 479 /* Create digest for comparison. */ 480 create_digest( &digest, 481 &hdr->credential.digest.nonce, 482 &hdr->credential.digest.nc, 483 &hdr->credential.digest.cnonce, 484 &hdr->credential.digest.qop, 485 &hdr->credential.digest.uri, 486 cred_info, 487 method ); 488 489 return pj_stricmp(&digest, &hdr->credential.digest.response) == 0; 490 491 } else { 492 pj_assert(0); 493 return PJ_FALSE; 494 } 495 } 496 497 /* Find credential to use for the specified realm and scheme. */ 498 PJ_DEF(const pjsip_cred_info*) pjsip_auth_find_cred( unsigned count, 499 const pjsip_cred_info cred[], 500 const pj_str_t *realm, 501 const pj_str_t *scheme) 502 { 503 unsigned i; 504 PJ_UNUSED_ARG(scheme); 505 for (i=0; i<count; ++i) { 506 if (pj_stricmp(&cred[i].realm, realm) == 0) 507 return &cred[i]; 508 } 509 return NULL; 510 } 511 512 #if PJSIP_AUTH_AUTO_SEND_NEXT 513 static void new_auth_for_req( pjsip_tx_data *tdata, 514 pj_pool_t *sess_pool, 515 pjsip_auth_session *sess, 516 int cred_count, 517 const pjsip_cred_info cred_info[]) 491 *p_h_auth = hauth; 492 return PJ_SUCCESS; 493 494 } 495 496 497 #if defined(PJSIP_AUTH_AUTO_SEND_NEXT) && PJSIP_AUTH_AUTO_SEND_NEXT!=0 498 static pj_status_t new_auth_for_req( pjsip_tx_data *tdata, 499 pjsip_auth_clt_sess *sess, 500 pjsip_cached_auth *auth, 501 pjsip_authorization_hdr **p_h_auth) 518 502 { 519 503 const pjsip_cred_info *cred; 520 504 pjsip_authorization_hdr *hauth; 521 522 pj_assert(sess->last_chal != NULL); 523 524 cred = pjsip_auth_find_cred( cred_count, cred_info, &sess->realm, 525 &sess->last_chal->scheme ); 505 pj_status_t status; 506 507 PJ_ASSERT_RETURN(tdata && sess && auth, PJ_EINVAL); 508 PJ_ASSERT_RETURN(auth->last_chal != NULL, PJSIP_EAUTHNOPREVCHAL); 509 510 cred = auth_find_cred( sess, &auth->realm, &auth->last_chal->scheme ); 526 511 if (!cred) 527 return; 528 512 return PJSIP_ENOCREDENTIAL; 513 514 status = auth_respond( tdata->pool, auth->last_chal, 515 tdata->msg->line.req.uri, 516 cred, &tdata->msg->line.req.method, 517 sess->pool, auth, &hauth); 518 if (status != PJ_SUCCESS) 519 return status; 529 520 530 hauth = pjsip_auth_respond( tdata->pool, sess->last_chal, 531 tdata->msg->line.req.uri, 532 cred, &tdata->msg->line.req.method, 533 sess_pool, sess); 534 if (hauth) { 535 pjsip_msg_add_hdr( tdata->msg, (pjsip_hdr*)hauth); 536 } 521 pjsip_msg_add_hdr( tdata->msg, (pjsip_hdr*)hauth); 522 523 if (p_h_auth) 524 *p_h_auth = hauth; 525 526 return PJ_SUCCESS; 537 527 } 538 528 #endif 539 529 540 /* 541 * Initialize new request message with authorization headers. 542 * This function will put Authorization/Proxy-Authorization headers to the 543 * outgoing request message. If caching is enabled (PJSIP_AUTH_HEADER_CACHING) 544 * and the session has previously sent Authorization/Proxy-Authorization header 545 * with the same method, then the same Authorization/Proxy-Authorization header 546 * will be resent from the cache only if qop is not present. If the stack is 547 * configured to automatically generate next Authorization/Proxy-Authorization 548 * headers (PJSIP_AUTH_AUTO_SEND_NEXT flag), then new Authorization/Proxy- 549 * Authorization headers are calculated and generated when they are not present 550 * in the case or if authorization session has qop. 551 * 552 * If both PJSIP_AUTH_HEADER_CACHING flag and PJSIP_AUTH_AUTO_SEND_NEXT flag 553 * are not set, this function will do nothing. The stack then will only send 554 * Authorization/Proxy-Authorization to respond 401/407 response. 555 */ 556 PJ_DEF(pj_status_t) pjsip_auth_init_req( pj_pool_t *sess_pool, 557 pjsip_tx_data *tdata, 558 pjsip_auth_session *sess_list, 559 int cred_count, 560 const pjsip_cred_info cred_info[]) 561 { 562 pjsip_auth_session *sess; 563 pjsip_method *method = &tdata->msg->line.req.method; 564 565 pj_assert(tdata->msg->type == PJSIP_REQUEST_MSG); 566 567 if (!sess_list) 568 return 0; 569 570 sess = sess_list->next; 571 while (sess != sess_list) { 572 if (sess->qop_value == PJSIP_AUTH_QOP_NONE) { 573 # if (PJSIP_AUTH_HEADER_CACHING) 530 531 532 /* Initialize outgoing request. */ 533 PJ_DEF(pj_status_t) pjsip_auth_clt_init_req( pjsip_auth_clt_sess *sess, 534 pjsip_tx_data *tdata ) 535 { 536 const pjsip_method *method; 537 pjsip_cached_auth *auth; 538 pj_status_t status; 539 540 PJ_ASSERT_RETURN(sess && tdata, PJ_EINVAL); 541 PJ_ASSERT_RETURN(sess->pool, PJSIP_ENOTINITIALIZED); 542 PJ_ASSERT_RETURN(tdata->msg->type==PJSIP_REQUEST_MSG, 543 PJSIP_ENOTREQUESTMSG); 544 545 /* Get the method. */ 546 method = &tdata->msg->line.req.method; 547 548 auth = sess->cached_auth.next; 549 while (auth != &sess->cached_auth) { 550 if (auth->qop_value == PJSIP_AUTH_QOP_NONE) { 551 # if defined(PJSIP_AUTH_HEADER_CACHING) && \ 552 PJSIP_AUTH_HEADER_CACHING!=0 574 553 { 575 pjsip_cached_auth_hdr *entry = sess->cached_hdr.next;576 while (entry != & sess->cached_hdr) {554 pjsip_cached_auth_hdr *entry = auth->cached_hdr.next; 555 while (entry != &auth->cached_hdr) { 577 556 if (pjsip_method_cmp(&entry->method, method)==0) { 578 557 pjsip_authorization_hdr *hauth; … … 580 559 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hauth); 581 560 } else { 582 # if (PJSIP_AUTH_AUTO_SEND_NEXT) 561 # if defined(PJSIP_AUTH_AUTO_SEND_NEXT) && \ 562 PJSIP_AUTH_AUTO_SEND_NEXT!=0 583 563 { 584 new_auth_for_req( tdata, sess_pool, sess, 585 cred_count, cred_info); 564 new_auth_for_req( tdata, sess, auth, NULL); 586 565 } 587 # else 588 { 589 PJ_UNUSED_ARG(sess_pool); 590 PJ_UNUSED_ARG(cred_count); 591 PJ_UNUSED_ARG(cred_info); 592 } 593 # endif /* PJSIP_AUTH_AUTO_SEND_NEXT */ 566 # endif 594 567 } 595 568 entry = entry->next; 596 569 } 597 570 } 598 # elif (PJSIP_AUTH_AUTO_SEND_NEXT) 571 # elif defined(PJSIP_AUTH_AUTO_SEND_NEXT) && \ 572 PJSIP_AUTH_AUTO_SEND_NEXT!=0 599 573 { 600 new_auth_for_req( tdata, sess_pool, sess, 601 cred_count, cred_info); 602 } 603 # else 604 { 605 PJ_UNUSED_ARG(sess_pool); 606 PJ_UNUSED_ARG(cred_count); 607 PJ_UNUSED_ARG(cred_info); 608 } 609 # endif /* PJSIP_AUTH_HEADER_CACHING */ 574 new_auth_for_req( tdata, sess, auth, NULL); 575 } 576 # endif 610 577 611 578 } 612 # if (PJSIP_AUTH_QOP_SUPPORT && PJSIP_AUTH_AUTO_SEND_NEXT) 613 else if (sess->qop_value == PJSIP_AUTH_QOP_AUTH) { 579 # if defined(PJSIP_AUTH_QOP_SUPPORT) && \ 580 defined(PJSIP_AUTH_AUTO_SEND_NEXT) && \ 581 (PJSIP_AUTH_QOP_SUPPORT && PJSIP_AUTH_AUTO_SEND_NEXT) 582 else if (auth->qop_value == PJSIP_AUTH_QOP_AUTH) { 614 583 /* For qop="auth", we have to re-create the authorization header. 615 584 */ … … 617 586 pjsip_authorization_hdr *hauth; 618 587 619 cred = pjsip_auth_find_cred( cred_count, cred_info, 620 &sess->realm, 621 &sess->last_chal->scheme); 588 cred = auth_find_cred(sess, &auth->realm, 589 &auth->last_chal->scheme); 622 590 if (!cred) { 623 sess = sess->next;591 auth = auth->next; 624 592 continue; 625 593 } 626 594 627 hauth = pjsip_auth_respond( tdata->pool, sess->last_chal, 628 tdata->msg->line.req.uri, 629 cred, 630 &tdata->msg->line.req.method, 631 sess_pool, sess ); 632 if (hauth) { 633 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hauth); 634 } 595 status = auth_respond( tdata->pool, auth->last_chal, 596 tdata->msg->line.req.uri, 597 cred, 598 &tdata->msg->line.req.method, 599 sess->pool, auth, &hauth); 600 if (status != PJ_SUCCESS) 601 return status; 602 603 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hauth); 635 604 } 636 605 # endif /* PJSIP_AUTH_QOP_SUPPORT && PJSIP_AUTH_AUTO_SEND_NEXT */ 637 606 638 sess = sess->next; 639 } 640 return 0; 641 } 607 auth = auth->next; 608 } 609 610 return PJ_SUCCESS; 611 } 612 642 613 643 614 /* Process authorization challenge */ 644 static pjsip_authorization_hdr *process_auth( pj_pool_t *req_pool, 645 const pjsip_www_authenticate_hdr *hchal, 646 const pjsip_uri *uri, 647 pjsip_tx_data *tdata, 648 int cred_count, 649 const pjsip_cred_info cred_info[], 650 pj_pool_t *ses_pool, 651 pjsip_auth_session *auth_sess) 615 static pj_status_t process_auth( pj_pool_t *req_pool, 616 const pjsip_www_authenticate_hdr *hchal, 617 const pjsip_uri *uri, 618 pjsip_tx_data *tdata, 619 pjsip_auth_clt_sess *sess, 620 pjsip_cached_auth *cached_auth, 621 pjsip_authorization_hdr **h_auth) 652 622 { 653 623 const pjsip_cred_info *cred; 654 pjsip_authorization_hdr *sent_auth = NULL , *hauth;624 pjsip_authorization_hdr *sent_auth = NULL; 655 625 pjsip_hdr *hdr; 626 pj_status_t status; 656 627 657 628 /* See if we have sent authorization header for this realm */ … … 686 657 sent_auth->credential.digest.realm.slen, 687 658 sent_auth->credential.digest.realm.ptr)); 688 return NULL;659 return PJSIP_EFAILEDCREDENTIAL; 689 660 } 690 661 … … 696 667 697 668 /* Find credential to be used for the challenge. */ 698 cred = pjsip_auth_find_cred( cred_count, cred_info,699 &hchal->challenge.common.realm,&hchal->scheme);669 cred = auth_find_cred( sess, &hchal->challenge.common.realm, 670 &hchal->scheme); 700 671 if (!cred) { 701 672 const pj_str_t *realm = &hchal->challenge.common.realm; … … 705 676 realm->slen, realm->ptr, 706 677 hchal->scheme.slen, hchal->scheme.ptr)); 707 return NULL;678 return PJSIP_ENOCREDENTIAL; 708 679 } 709 680 710 681 /* Respond to authorization challenge. */ 711 hauth = pjsip_auth_respond( req_pool, hchal, uri, cred,712 713 ses_pool, auth_sess);714 return hauth;682 status = auth_respond( req_pool, hchal, uri, cred, 683 &tdata->msg->line.req.method, 684 sess->pool, cached_auth, h_auth); 685 return status; 715 686 } 716 687 … … 722 693 * in cached_list. 723 694 */ 724 PJ_DEF(pjsip_tx_data*) pjsip_auth_reinit_req( pjsip_endpoint *endpt, 725 pj_pool_t *ses_pool, 726 pjsip_auth_session *sess_list, 727 int cred_count, 728 const pjsip_cred_info cred_info[], 729 pjsip_tx_data *tdata, 730 const pjsip_rx_data *rdata) 731 { 695 PJ_DEF(pj_status_t) pjsip_auth_clt_reinit_req( pjsip_auth_clt_sess *sess, 696 const pjsip_rx_data *rdata, 697 pjsip_tx_data *old_request, 698 pjsip_tx_data **new_request ) 699 { 700 pjsip_tx_data *tdata; 732 701 const pjsip_hdr *hdr; 733 702 pjsip_via_hdr *via; 734 735 PJ_UNUSED_ARG(endpt); 736 737 pj_assert(rdata->msg_info.msg->type == PJSIP_RESPONSE_MSG); 738 pj_assert(rdata->msg_info.msg->line.status.code == 401 || 739 rdata->msg_info.msg->line.status.code == 407 ); 740 703 pj_status_t status; 704 705 PJ_ASSERT_RETURN(sess && rdata && old_request && new_request, 706 PJ_EINVAL); 707 PJ_ASSERT_RETURN(sess->pool, PJSIP_ENOTINITIALIZED); 708 PJ_ASSERT_RETURN(rdata->msg_info.msg->type == PJSIP_RESPONSE_MSG, 709 PJSIP_ENOTRESPONSEMSG); 710 PJ_ASSERT_RETURN(old_request->msg->type == PJSIP_REQUEST_MSG, 711 PJSIP_ENOTREQUESTMSG); 712 PJ_ASSERT_RETURN(rdata->msg_info.msg->line.status.code == 401 || 713 rdata->msg_info.msg->line.status.code == 407, 714 PJSIP_EINVALIDSTATUS); 715 716 tdata = old_request; 717 741 718 /* 742 719 * Respond to each authentication challenge. … … 744 721 hdr = rdata->msg_info.msg->hdr.next; 745 722 while (hdr != &rdata->msg_info.msg->hdr) { 746 pjsip_ auth_session *sess;723 pjsip_cached_auth *cached_auth; 747 724 const pjsip_www_authenticate_hdr *hchal; 748 725 pjsip_authorization_hdr *hauth; … … 763 740 * if not present. 764 741 */ 765 sess = find_session(sess_list, &hchal->challenge.common.realm );766 if (! sess) {767 sess = pj_pool_calloc( ses_pool, 1, sizeof(*sess));768 pj_strdup( ses _pool, &sess->realm, &hchal->challenge.common.realm);769 sess->is_proxy = (hchal->type == PJSIP_H_PROXY_AUTHENTICATE);742 cached_auth = find_cached_auth(sess, &hchal->challenge.common.realm ); 743 if (!cached_auth) { 744 cached_auth = pj_pool_zalloc( sess->pool, sizeof(*cached_auth)); 745 pj_strdup( sess->pool, &cached_auth->realm, &hchal->challenge.common.realm); 746 cached_auth->is_proxy = (hchal->type == PJSIP_H_PROXY_AUTHENTICATE); 770 747 # if (PJSIP_AUTH_HEADER_CACHING) 771 748 { 772 pj_list_init(& sess->cached_hdr);749 pj_list_init(&cached_auth->cached_hdr); 773 750 } 774 751 # endif 775 pj_list_insert_before( sess_list, sess);752 pj_list_insert_before( &sess->cached_auth, cached_auth ); 776 753 } 777 754 … … 779 756 * authorization session. 780 757 */ 781 hauth= process_auth( tdata->pool, hchal, tdata->msg->line.req.uri,782 tdata, cred_count, cred_info, ses_pool, sess);783 if ( !hauth)784 return NULL;758 status = process_auth( tdata->pool, hchal, tdata->msg->line.req.uri, 759 tdata, sess, cached_auth, &hauth); 760 if (status != PJ_SUCCESS) 761 return status; 785 762 786 763 /* Add to the message. */ … … 800 777 801 778 /* Done. */ 802 return tdata; 803 } 804 779 *new_request = tdata; 780 return PJ_SUCCESS; 781 782 } 783 -
pjproject/trunk/pjsip/src/pjsip/sip_errno.c
r109 r123 35 35 { PJSIP_ETYPEEXISTS , "Object with the same type exists" }, 36 36 { PJSIP_ESHUTDOWN, "SIP stack shutting down" }, 37 { PJSIP_ENOTINITIALIZED, "SIP object is not initialized." }, 37 38 38 39 /* Messaging errors */ 39 40 { PJSIP_EINVALIDMSG, "Invalid message/syntax error" }, 40 { PJSIP_EINVALIDSCHEME, "Invalid URI scheme" }, 41 { PJSIP_ENOTREQUESTMSG, "Expecting request message"}, 42 { PJSIP_ENOTRESPONSEMSG, "Expecting response message"}, 41 43 { PJSIP_EMSGTOOLONG, "Message too long" }, 42 44 { PJSIP_EPARTIALMSG, "Partial message" }, 45 46 { PJSIP_EINVALIDSTATUS, "Invalid status code"}, 47 48 { PJSIP_EINVALIDSCHEME, "Invalid URI scheme" }, 43 49 { PJSIP_EMISSINGREQURI, "Missing Request-URI" }, 50 { PJSIP_EINVALIDREQURI, "Invalid Request URI" }, 51 { PJSIP_EURITOOLONG, "URI is too long" }, 52 44 53 { PJSIP_EMISSINGHDR, "Missing required header(s)" }, 45 { PJSIP_E MISSINGBODY, "Missing message body"},54 { PJSIP_EINVALIDHDR, "Invalid header field"}, 46 55 { PJSIP_EINVALIDVIA, "Invalid Via header" }, 47 56 { PJSIP_EMULTIPLEVIA, "Multiple Via headers in response" }, 48 { PJSIP_EINVALIDREQURI, "Invalid Request URI" }, 49 { PJSIP_ENOTREQUESTMSG, "Expecting request message"}, 50 { PJSIP_ENOTRESPONSEMSG, "Expecting response message"}, 51 { PJSIP_EINVALIDHDR, "Invalid header field"}, 57 58 { PJSIP_EMISSINGBODY, "Missing message body" }, 52 59 53 60 /* Transport errors */ … … 59 66 /* Transaction errors */ 60 67 { PJSIP_ETSXDESTROYED, "Transaction has been destroyed"}, 68 69 /* Authentication. */ 70 { PJSIP_EFAILEDCREDENTIAL, "Credential failed to authenticate"}, 71 { PJSIP_ENOCREDENTIAL, "No suitable credential"}, 72 { PJSIP_EINVALIDALGORITHM, "Invalid/unsupported digest algorithm" }, 73 { PJSIP_EINVALIDQOP, "Invalid/unsupported digest qop" }, 74 { PJSIP_EINVALIDAUTHSCHEME, "Unsupported authentication scheme" }, 75 { PJSIP_EAUTHNOPREVCHAL, "No previous challenge" }, 76 { PJSIP_EAUTHNOAUTH, "No suitable authorization header" }, 77 { PJSIP_EAUTHACCNOTFOUND, "Account or credential not found" }, 78 { PJSIP_EAUTHACCDISABLED, "Account or credential is disabled" }, 79 { PJSIP_EAUTHINVALIDREALM, "Invalid authorization realm"}, 80 { PJSIP_EAUTHINVALIDDIGEST, "Invalid authorization digest" } 61 81 }; 62 82 -
pjproject/trunk/pjsip/src/pjsip/sip_parser.c
r119 r123 1400 1400 1401 1401 if (ctx->rdata) 1402 ctx->rdata->msg_info.c all_id = hdr->id;1402 ctx->rdata->msg_info.cid = hdr; 1403 1403 1404 1404 return (pjsip_hdr*)hdr; -
pjproject/trunk/pjsip/src/pjsip/sip_transaction.c
r119 r123 270 270 len_required = 9 + /* CSeq number */ 271 271 rdata->msg_info.from->tag.slen + /* From tag. */ 272 rdata->msg_info.c all_id.slen + /* Call-ID */272 rdata->msg_info.cid->id.slen + /* Call-ID */ 273 273 host->slen + /* Via host. */ 274 274 9 + /* Via port. */ … … 300 300 301 301 /* Add Call-ID. */ 302 len = rdata->msg_info.c all_id.slen;303 pj_memcpy( p, rdata->msg_info.c all_id.ptr, len );302 len = rdata->msg_info.cid->id.slen; 303 pj_memcpy( p, rdata->msg_info.cid->id.ptr, len ); 304 304 p += len; 305 305 *p++ = SEPARATOR; … … 1590 1590 ++tsx->retransmit_count; 1591 1591 1592 status = tsx_send_msg( tsx, tsx->last_tx); 1593 if (status != PJ_SUCCESS) 1594 return status; 1595 1596 /* Restart timer T1. */ 1592 /* Restart timer T1 first before sending the message to ensure that 1593 * retransmission timer is not engaged when loop transport is used. 1594 */ 1597 1595 if (resched) { 1596 pj_assert(tsx->state != PJSIP_TSX_STATE_CONFIRMED); 1598 1597 if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) { 1599 1598 tsx->transport_flag |= TSX_HAS_PENDING_RESCHED; … … 1601 1600 tsx_resched_retransmission(tsx); 1602 1601 } 1602 } 1603 1604 status = tsx_send_msg( tsx, tsx->last_tx); 1605 if (status != PJ_SUCCESS) { 1606 return status; 1603 1607 } 1604 1608 -
pjproject/trunk/pjsip/src/pjsip/sip_transport.c
r119 r123 879 879 880 880 /* Perform basic header checking. */ 881 if (rdata->msg_info.c all_id.ptr == NULL ||881 if (rdata->msg_info.cid->id.ptr == NULL || 882 882 rdata->msg_info.from == NULL || 883 883 rdata->msg_info.to == NULL || -
pjproject/trunk/pjsip/src/pjsip/sip_transport_loop.c
r110 r123 251 251 252 252 /* Worker thread for loop transport. */ 253 static int loop_t hread(void *arg)253 static int loop_transport_worker_thread(void *arg) 254 254 { 255 255 struct loop_transport *loop = arg; … … 385 385 386 386 /* Create worker thread. */ 387 status = pj_thread_create(pool, "loop", &loop_thread, loop, 0, 387 status = pj_thread_create(pool, "loop", 388 &loop_transport_worker_thread, loop, 0, 388 389 PJ_THREAD_SUSPENDED, &loop->thread); 389 390 if (status != PJ_SUCCESS) -
pjproject/trunk/pjsip/src/pjsip/sip_util.c
r119 r123 351 351 pjsip_rr_hdr *rr; 352 352 pj_status_t status; 353 354 /* Check arguments. */ 355 PJ_ASSERT_RETURN(endpt && rdata && p_tdata, PJ_EINVAL); 356 357 /* Check status code. */ 358 PJ_ASSERT_RETURN(st_code >= 100 && st_code <= 699, PJ_EINVAL); 353 359 354 360 /* rdata must be a request message. */ -
pjproject/trunk/pjsip/src/test-pjsip/transport_test.c
r109 r123 117 117 { 118 118 /* Check that this is our request. */ 119 if (pj_strcmp2(&rdata->msg_info.c all_id, CALL_ID_HDR) == 0) {119 if (pj_strcmp2(&rdata->msg_info.cid->id, CALL_ID_HDR) == 0) { 120 120 /* It is! */ 121 121 /* Send response. */ … … 150 150 static pj_bool_t my_on_rx_response(pjsip_rx_data *rdata) 151 151 { 152 if (pj_strcmp2(&rdata->msg_info.c all_id, CALL_ID_HDR) == 0) {152 if (pj_strcmp2(&rdata->msg_info.cid->id, CALL_ID_HDR) == 0) { 153 153 pj_get_timestamp(&my_recv_time); 154 154 recv_status = PJ_SUCCESS; … … 335 335 static pj_bool_t rt_on_rx_request(pjsip_rx_data *rdata) 336 336 { 337 if (!pj_strncmp(&rdata->msg_info.c all_id, &rt_call_id, rt_call_id.slen)) {338 char *pos = pj_strchr(&rdata->msg_info.c all_id, '/');337 if (!pj_strncmp(&rdata->msg_info.cid->id, &rt_call_id, rt_call_id.slen)) { 338 char *pos = pj_strchr(&rdata->msg_info.cid->id, '/'); 339 339 int thread_id = (*pos - '0'); 340 340 … … 423 423 static pj_bool_t rt_on_rx_response(pjsip_rx_data *rdata) 424 424 { 425 if (!pj_strncmp(&rdata->msg_info.c all_id, &rt_call_id, rt_call_id.slen)) {426 char *pos = pj_strchr(&rdata->msg_info.c all_id, '/')+1;425 if (!pj_strncmp(&rdata->msg_info.cid->id, &rt_call_id, rt_call_id.slen)) { 426 char *pos = pj_strchr(&rdata->msg_info.cid->id, '/')+1; 427 427 int thread_id = (*pos - '0'); 428 428 pj_timestamp recv_time; -
pjproject/trunk/pjsip/src/test-pjsip/tsx_uac_test.c
r117 r123 399 399 } 400 400 401 /* last_tx is ACK in this case. */ 401 /* last_tx MUST be the INVITE request 402 * (authorization depends on this behavior) 403 */ 402 404 if (tsx->last_tx && tsx->last_tx->msg->line.req.method.id != 403 PJSIP_ ACK_METHOD)405 PJSIP_INVITE_METHOD) 404 406 { 405 407 PJ_LOG(3,(THIS_FILE, 406 " error: last_tx is not ACK"));408 " error: last_tx is not INVITE")); 407 409 test_complete = -748; 408 410 } … … 462 464 } 463 465 464 /* last_tx is ACK in this case. */ 466 /* last_tx MUST be INVITE. 467 * (authorization depends on this behavior) 468 */ 465 469 if (tsx->last_tx && tsx->last_tx->msg->line.req.method.id != 466 PJSIP_ ACK_METHOD)470 PJSIP_INVITE_METHOD) 467 471 { 468 472 PJ_LOG(3,(THIS_FILE, 469 " error: last_tx is not ACK"));473 " error: last_tx is not INVITE")); 470 474 test_complete = -764; 471 475 } -
pjproject/trunk/pjsip/src/test-pjsip/tsx_uas_test.c
r119 r123 67 67 ** Transaction also MUST terminate in T4 seconds. 68 68 ** 69 ** TEST10_BRANCH_ID70 ** Test where INVITE UAS transaction never receives ACK71 **72 69 ** TEST11_BRANCH_ID 70 ** Test scenario where transport fails before response is sent (i.e. 71 ** in TRYING state). 72 ** 73 ** TEST12_BRANCH_ID 74 ** As above, after provisional response is sent but before final 75 ** response is sent (i.e. in PROCEEDING state). 76 ** 77 ** TEST13_BRANCH_ID 78 ** As above, for INVITE, after final response has been sent but before 79 ** ACK is received (i.e. in CONNECTED state). 80 ** 81 ** TEST14_BRANCH_ID 73 82 ** When UAS failed to deliver the response with the selected transport, 74 83 ** it should try contacting the client with other transport or begin … … 79 88 ** upon receiving request retransmission). 80 89 ** c. COMPLETED state. 81 **82 ** TEST12_BRANCH_ID83 ** Variant of previous test, where transaction fails to deliver the84 ** response using any kind of transports. Transaction should report85 ** transport error to its transaction user.86 90 ** 87 91 **/ … … 99 103 static char *TEST11_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test11"; 100 104 static char *TEST12_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test12"; 105 static char *TEST13_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test13"; 101 106 102 107 #define TEST1_STATUS_CODE 200 … … 116 121 #define TEST7_STATUS_CODE 301 117 122 #define TEST8_STATUS_CODE 302 123 #define TEST9_STATUS_CODE 301 118 124 119 125 … … 211 217 status = pjsip_tsx_send_msg(tsx, r->tdata); 212 218 if (status != PJ_SUCCESS) { 213 PJ_LOG(3,(THIS_FILE," error: timer unable to send response")); 219 // Some tests do expect failure! 220 //PJ_LOG(3,(THIS_FILE," error: timer unable to send response")); 221 pj_mutex_unlock(tsx->mutex); 214 222 pjsip_tx_data_dec_ref(r->tdata); 215 223 return; 216 224 } 225 226 pj_mutex_unlock(tsx->mutex); 217 227 } 218 228 … … 235 245 status = pjsip_tsx_send_msg(tsx, tdata); 236 246 if (status != PJ_SUCCESS) { 237 app_perror(" error: unable to send response", status);238 247 pjsip_tx_data_dec_ref(tdata); 239 test_complete = -197; 248 // Some tests do expect failure! 249 //app_perror(" error: unable to send response", status); 250 //test_complete = -197; 240 251 return; 241 252 } … … 250 261 pj_status_t status; 251 262 pjsip_tx_data *tdata; 263 pj_timer_entry *t; 252 264 struct response *r; 253 265 pj_time_val delay; … … 269 281 pj_time_val_normalize(&delay); 270 282 271 timer.user_data = r; 272 timer.cb = &send_response_timer; 273 274 status = pjsip_endpt_schedule_timer(endpt, &timer, &delay); 283 t = pj_pool_zalloc(tdata->pool, sizeof(*t)); 284 t->user_data = r; 285 t->cb = &send_response_timer; 286 287 status = pjsip_endpt_schedule_timer(endpt, t, &delay); 275 288 if (status != PJ_SUCCESS) { 289 pjsip_tx_data_dec_ref(tdata); 276 290 app_perror(" error: unable to schedule timer", status); 277 291 test_complete = -199; 278 pjsip_tx_data_dec_ref(tdata);279 292 return; 280 293 } … … 575 588 } 576 589 590 591 } else 592 if (pj_strcmp2(&tsx->branch, TEST9_BRANCH_ID)==0) { 593 /* 594 * TEST9_BRANCH_ID tests that retransmission of INVITE final response 595 * must cease when ACK is received. 596 */ 597 598 if (tsx->state == PJSIP_TSX_STATE_TERMINATED) { 599 600 if (test_complete == 0) 601 test_complete = 1; 602 603 /* Check status code. */ 604 if (tsx->status_code != TEST9_STATUS_CODE) { 605 PJ_LOG(3,(THIS_FILE, " error: incorrect status code")); 606 test_complete = -160; 607 } 608 609 /* Previous state. */ 610 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_CONFIRMED) { 611 PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state")); 612 test_complete = -161; 613 } 614 615 } else if (tsx->state == PJSIP_TSX_STATE_COMPLETED) { 616 617 /* Check that status code is status_code. */ 618 if (tsx->status_code != TEST9_STATUS_CODE) { 619 PJ_LOG(3,(THIS_FILE, " error: incorrect status code")); 620 test_complete = -162; 621 } 622 623 /* Previous state. */ 624 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_TRYING) { 625 PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state")); 626 test_complete = -163; 627 } 628 629 630 } else if (tsx->state == PJSIP_TSX_STATE_CONFIRMED) { 631 632 /* Check that status code is status_code. */ 633 if (tsx->status_code != TEST9_STATUS_CODE) { 634 PJ_LOG(3,(THIS_FILE, " error: incorrect status code")); 635 test_complete = -164; 636 } 637 638 /* Previous state. */ 639 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) { 640 PJ_LOG(3,(THIS_FILE, " error: incorrect prev_state")); 641 test_complete = -165; 642 } 643 644 } else if (tsx->state != PJSIP_TSX_STATE_DESTROYED) { 645 646 PJ_LOG(3,(THIS_FILE, " error: unexpected state")); 647 test_complete = -166; 648 649 } 650 651 652 } else 653 if (pj_strcmp2(&tsx->branch, TEST10_BRANCH_ID)==0 || 654 pj_strcmp2(&tsx->branch, TEST11_BRANCH_ID)==0 || 655 pj_strcmp2(&tsx->branch, TEST12_BRANCH_ID)==0) 656 { 657 if (tsx->state == PJSIP_TSX_STATE_TERMINATED) { 658 659 if (!test_complete) 660 test_complete = 1; 661 662 if (tsx->status_code != PJSIP_SC_TSX_TRANSPORT_ERROR) { 663 PJ_LOG(3,(THIS_FILE," error: incorrect status code")); 664 test_complete = -170; 665 } 666 } 577 667 } 578 668 … … 613 703 614 704 if (msg->type == PJSIP_REQUEST_MSG) { 615 /* On received re sponse, create UAS and respond with final705 /* On received request, create UAS and respond with final 616 706 * response. 617 707 */ … … 653 743 654 744 if (msg->type == PJSIP_REQUEST_MSG) { 655 /* On received re sponse, create UAS and respond with provisional745 /* On received request, create UAS and respond with provisional 656 746 * response, then schedule timer to send final response. 657 747 */ … … 706 796 707 797 if (msg->type == PJSIP_REQUEST_MSG) { 708 /* On received re sponse, create UAS. */798 /* On received request, create UAS. */ 709 799 pjsip_transaction *tsx; 710 800 … … 787 877 if (msg->type == PJSIP_REQUEST_MSG) { 788 878 789 /* On received re sponse, create UAS. */879 /* On received request, create UAS. */ 790 880 pjsip_transaction *tsx; 791 881 … … 862 952 return PJ_TRUE; 863 953 864 } else if (pj_strcmp2(&branch_param, TEST9_BRANCH_ID) ) {954 } else if (pj_strcmp2(&branch_param, TEST9_BRANCH_ID) == 0) { 865 955 866 956 /* … … 871 961 if (msg->type == PJSIP_REQUEST_MSG) { 872 962 873 /* On received re sponse, create UAS. */963 /* On received request, create UAS. */ 874 964 pjsip_transaction *tsx; 875 965 … … 877 967 if (status != PJ_SUCCESS) { 878 968 app_perror(" error: unable to create transaction", status); 879 test_complete = -1 40;969 test_complete = -150; 880 970 return PJ_TRUE; 881 971 } 882 972 883 973 save_key(tsx); 884 885 if (pj_strcmp2(&branch_param, TEST7_BRANCH_ID) == 0) { 886 887 send_response(rdata, tsx, TEST7_STATUS_CODE); 888 889 } else { 890 891 send_response(rdata, tsx, TEST8_STATUS_CODE); 892 893 } 974 send_response(rdata, tsx, TEST9_STATUS_CODE); 975 894 976 895 977 } else { 896 int code;897 978 898 979 ++recv_count; 899 980 900 if ( pj_strcmp2(&branch_param, TEST7_BRANCH_ID) == 0)901 code = TEST7_STATUS_CODE;902 else903 code = TEST8_STATUS_CODE;981 if (rdata->msg_info.msg->line.status.code != TEST9_STATUS_CODE) { 982 PJ_LOG(3,(THIS_FILE," error: invalid status code")); 983 test_complete = -151; 984 } 904 985 905 986 if (recv_count==1) { 906 907 if (rdata->msg_info.msg->line.status.code != code) {908 PJ_LOG(3,(THIS_FILE," error: invalid status code"));909 test_complete = -141;910 }911 987 912 988 recv_last = rdata->pkt_info.timestamp; 913 989 914 } else { 915 990 } else if (recv_count < 5) { 991 992 /* Let UAS retransmit some messages before we send ACK. */ 916 993 pj_time_val now; 917 994 unsigned msec, msec_expected; … … 931 1008 "time (%d ms expected, %d ms received", 932 1009 msec_expected, msec)); 933 test_complete = -1 42;1010 test_complete = -152; 934 1011 } 935 1012 936 if (recv_count > 11) { 937 PJ_LOG(3,(THIS_FILE," error: too many responses (%d)", 938 recv_count)); 939 test_complete = -143; 1013 recv_last = rdata->pkt_info.timestamp; 1014 1015 } else if (recv_count == 5) { 1016 pjsip_tx_data *tdata; 1017 pjsip_sip_uri *uri; 1018 pjsip_via_hdr *via; 1019 1020 status = pjsip_endpt_create_request_from_hdr( 1021 endpt, &pjsip_ack_method, 1022 rdata->msg_info.to->uri, 1023 rdata->msg_info.from, 1024 rdata->msg_info.to, 1025 NULL, 1026 rdata->msg_info.cid, 1027 rdata->msg_info.cseq->cseq, 1028 NULL, 1029 &tdata); 1030 if (status != PJ_SUCCESS) { 1031 app_perror(" error: unable to create ACK", status); 1032 test_complete = -153; 1033 return PJ_TRUE; 940 1034 } 941 1035 942 recv_last = rdata->pkt_info.timestamp; 943 } 944 945 } 1036 uri=(pjsip_sip_uri*)pjsip_uri_get_uri(tdata->msg->line.req.uri); 1037 uri->transport_param = pj_str("loop-dgram"); 1038 1039 via = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL); 1040 via->branch_param = pj_str(TEST9_BRANCH_ID); 1041 1042 status = pjsip_endpt_send_request_stateless(endpt, tdata, 1043 NULL, NULL); 1044 if (status != PJ_SUCCESS) { 1045 app_perror(" error: unable to send ACK", status); 1046 test_complete = -154; 1047 } 1048 1049 } else { 1050 PJ_LOG(3,(THIS_FILE," error: too many responses (%d)", 1051 recv_count)); 1052 test_complete = -155; 1053 } 1054 1055 } 1056 return PJ_TRUE; 1057 1058 } else if (pj_strcmp2(&branch_param, TEST10_BRANCH_ID) == 0 || 1059 pj_strcmp2(&branch_param, TEST11_BRANCH_ID) == 0 || 1060 pj_strcmp2(&branch_param, TEST12_BRANCH_ID) == 0) 1061 { 1062 int test_num, code1, code2; 1063 1064 if (pj_strcmp2(&branch_param, TEST10_BRANCH_ID) == 0) 1065 test_num=10, code1 = 100, code2 = 0; 1066 else if (pj_strcmp2(&branch_param, TEST11_BRANCH_ID) == 0) 1067 test_num=11, code1 = 100, code2 = 200; 1068 else 1069 test_num=12, code1 = 200, code2 = 0; 1070 1071 if (rdata->msg_info.msg->type == PJSIP_REQUEST_MSG) { 1072 1073 /* On received response, create UAS. */ 1074 pjsip_transaction *tsx; 1075 1076 status = pjsip_tsx_create_uas(&tsx_user, rdata, &tsx); 1077 if (status != PJ_SUCCESS) { 1078 app_perror(" error: unable to create transaction", status); 1079 test_complete = -150; 1080 return PJ_TRUE; 1081 } 1082 1083 save_key(tsx); 1084 1085 schedule_send_response(rdata, &tsx_key, code1, 1000); 1086 1087 if (code2) 1088 schedule_send_response(rdata, &tsx_key, code2, 2000); 1089 1090 } else { 1091 1092 } 1093 946 1094 return PJ_TRUE; 947 1095 } … … 1213 1361 1214 1362 1363 /***************************************************************************** 1364 ** 1365 ** TEST9_BRANCH_ID: retransmission of non-2xx INVITE final response must 1366 ** cease when ACK is received 1367 ** 1368 ***************************************************************************** 1369 */ 1370 static int tsx_ack_test(void) 1371 { 1372 int status; 1373 1374 PJ_LOG(3,(THIS_FILE, 1375 " test9: receiving ACK for non-2xx final response")); 1376 1377 status = perform_test("sip:129.0.0.1;transport=loop-dgram", 1378 "sip:129.0.0.1;transport=loop-dgram", 1379 TEST9_BRANCH_ID, 1380 20, /* allow 5 retransmissions */ 1381 &pjsip_invite_method, 1, 0, 0); 1382 if (status != 0) 1383 return status; 1384 1385 1386 return 0; 1387 } 1388 1389 1390 1391 /***************************************************************************** 1392 ** 1393 ** TEST10_BRANCH_ID: test transport failure in TRYING state. 1394 ** TEST11_BRANCH_ID: test transport failure in PROCEEDING state. 1395 ** TEST12_BRANCH_ID: test transport failure in CONNECTED state. 1396 ** TEST13_BRANCH_ID: test transport failure in CONFIRMED state. 1397 ** 1398 ***************************************************************************** 1399 */ 1400 static int tsx_transport_failure_test(void) 1401 { 1402 struct test_desc 1403 { 1404 int transport_delay; 1405 int fail_delay; 1406 char *branch_id; 1407 char *title; 1408 } tests[] = 1409 { 1410 { 0, 10, TEST10_BRANCH_ID, "test10: failed transport in TRYING state (no delay)" }, 1411 { 50, 10, TEST10_BRANCH_ID, "test10: failed transport in TRYING state (50 ms delay)" }, 1412 { 0, 1500, TEST11_BRANCH_ID, "test11: failed transport in PROCEEDING state (no delay)" }, 1413 { 50, 1500, TEST11_BRANCH_ID, "test11: failed transport in PROCEEDING state (50 ms delay)" }, 1414 { 0, 2500, TEST12_BRANCH_ID, "test12: failed transport in COMPLETED state (no delay)" }, 1415 { 50, 2500, TEST12_BRANCH_ID, "test12: failed transport in COMPLETED state (50 ms delay)" }, 1416 }; 1417 int i, status; 1418 1419 for (i=0; i<PJ_ARRAY_SIZE(tests); ++i) { 1420 pj_time_val fail_time, end_test, now; 1421 1422 PJ_LOG(3,(THIS_FILE, " %s", tests[i].title)); 1423 pjsip_loop_set_failure(loop, 0, NULL); 1424 pjsip_loop_set_delay(loop, tests[i].transport_delay); 1425 1426 status = perform_test("sip:129.0.0.1;transport=loop-dgram", 1427 "sip:129.0.0.1;transport=loop-dgram", 1428 tests[i].branch_id, 1429 0, 1430 &pjsip_invite_method, 1, 0, 1); 1431 if (status && status != TEST_TIMEOUT_ERROR) 1432 return status; 1433 if (!status) { 1434 PJ_LOG(3,(THIS_FILE, " error: expecting timeout")); 1435 return -40; 1436 } 1437 1438 pj_gettimeofday(&fail_time); 1439 fail_time.msec += tests[i].fail_delay; 1440 pj_time_val_normalize(&fail_time); 1441 1442 do { 1443 pj_time_val interval = { 0, 1 }; 1444 pj_gettimeofday(&now); 1445 pjsip_endpt_handle_events(endpt, &interval); 1446 } while (PJ_TIME_VAL_LT(now, fail_time)); 1447 1448 pjsip_loop_set_failure(loop, 1, NULL); 1449 1450 end_test = now; 1451 end_test.sec += 5; 1452 1453 do { 1454 pj_time_val interval = { 0, 1 }; 1455 pj_gettimeofday(&now); 1456 pjsip_endpt_handle_events(endpt, &interval); 1457 } while (!test_complete && PJ_TIME_VAL_LT(now, end_test)); 1458 1459 if (test_complete == 0) { 1460 PJ_LOG(3,(THIS_FILE, " error: test has timed out")); 1461 return -41; 1462 } 1463 1464 if (test_complete != 1) 1465 return test_complete; 1466 } 1467 1468 return 0; 1469 } 1215 1470 1216 1471 /***************************************************************************** … … 1245 1500 } 1246 1501 1247 #if 01248 1502 /* TEST1_BRANCH_ID: Basic 2xx final response. 1249 1503 * TEST2_BRANCH_ID: Basic non-2xx final response. … … 1294 1548 return status; 1295 1549 1296 #endif 1550 /* TEST9_BRANCH_ID: retransmission of non-2xx INVITE final response must 1551 * cease when ACK is received 1552 */ 1553 status = tsx_ack_test(); 1554 if (status != 0) 1555 return status; 1556 1557 /* TEST10_BRANCH_ID: test transport failure in TRYING state. 1558 * TEST11_BRANCH_ID: test transport failure in PROCEEDING state. 1559 * TEST12_BRANCH_ID: test transport failure in CONNECTED state. 1560 * TEST13_BRANCH_ID: test transport failure in CONFIRMED state. 1561 */ 1562 status = tsx_transport_failure_test(); 1563 if (status != 0) 1564 return status; 1565 1297 1566 1298 1567 pjsip_transport_dec_ref(loop); -
pjproject/trunk/pjsip/src/test-pjsip/txdata_test.c
r119 r123 155 155 * many more fields need to be initialized!! 156 156 */ 157 dummy_rdata.msg_info.c all_id = (HFIND(invite->msg, cid, CALL_ID))->id;157 dummy_rdata.msg_info.cid = HFIND(invite->msg, cid, CALL_ID); 158 158 dummy_rdata.msg_info.clen = NULL; 159 159 dummy_rdata.msg_info.cseq = HFIND(invite->msg, cseq, CSEQ);
Note: See TracChangeset
for help on using the changeset viewer.