Changeset 123


Ignore:
Timestamp:
Jan 18, 2006 11:34:15 PM (18 years ago)
Author:
bennylp
Message:

Complete tsx layer selftest, implemented authentication framework

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  
    490490 * @param state     Variable to store scanner's state. 
    491491 */ 
    492 PJ_DECL(void) pj_scan_save_state( pj_scanner *scanner, pj_scan_state *state); 
     492PJ_DECL(void) pj_scan_save_state( const pj_scanner *scanner,  
     493                                  pj_scan_state *state); 
    493494 
    494495 
     
    502503 */ 
    503504PJ_DECL(void) pj_scan_restore_state( pj_scanner *scanner,  
    504                                       pj_scan_state *state); 
     505                                     pj_scan_state *state); 
    505506 
    506507/** 
     
    511512 * @return          The column position. 
    512513 */ 
    513 PJ_INLINE(int) pj_scan_get_col( pj_scanner *scanner ) 
     514PJ_INLINE(int) pj_scan_get_col( const pj_scanner *scanner ) 
    514515{ 
    515516    return scanner->curptr - scanner->start_line; 
  • pjproject/trunk/pjlib-util/include/pjlib-util/xml.h

    r65 r123  
    9898 
    9999/** 
     100 * Create an empty node. 
     101 * 
     102 * @param pool      Pool. 
     103 * @param name      Node name. 
     104 * 
     105 * @return          The new node. 
     106 */ 
     107PJ_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 */ 
     119PJ_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/** 
    100123 * Add node to another node. 
    101124 * 
  • pjproject/trunk/pjlib-util/src/pjlib-util/scanner.c

    r81 r123  
    528528} 
    529529 
    530 PJ_DEF(void) pj_scan_save_state( pj_scanner *scanner, pj_scan_state *state) 
     530PJ_DEF(void) pj_scan_save_state( const pj_scanner *scanner,  
     531                                 pj_scan_state *state) 
    531532{ 
    532533    state->curptr = scanner->curptr; 
     
    537538 
    538539PJ_DEF(void) pj_scan_restore_state( pj_scanner *scanner,  
    539                                      pj_scan_state *state) 
     540                                    pj_scan_state *state) 
    540541{ 
    541542    scanner->curptr = state->curptr; 
  • pjproject/trunk/pjlib-util/src/pjlib-util/xml.c

    r77 r123  
    3838    pj_xml_node *node; 
    3939 
    40     node = pj_pool_calloc(pool, 1, sizeof(pj_xml_node)); 
     40    node = pj_pool_zalloc(pool, sizeof(pj_xml_node)); 
    4141    pj_list_init( &node->attr_head ); 
    4242    pj_list_init( &node->node_head ); 
     
    314314} 
    315315 
     316PJ_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 
     323PJ_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} 
    316331 
    317332PJ_DEF(void) pj_xml_add_node( pj_xml_node *parent, pj_xml_node *node ) 
  • pjproject/trunk/pjmedia/bin

    • Property svn:ignore set to
      *
  • pjproject/trunk/pjmedia/lib

    • Property svn:ignore set to
      *
  • pjproject/trunk/pjsip/build/pjsip_core.dsp

    r119 r123  
    8888# Begin Source File 
    8989 
    90 SOURCE=..\src\pjsip\sip_auth.c 
     90SOURCE=..\src\pjsip\sip_auth_client.c 
    9191# End Source File 
    9292# Begin Source File 
     
    9797 
    9898SOURCE=..\src\pjsip\sip_auth_parser.c 
     99# End Source File 
     100# Begin Source File 
     101 
     102SOURCE=..\src\pjsip\sip_auth_server.c 
    99103# End Source File 
    100104# Begin Source File 
  • pjproject/trunk/pjsip/build/pjsip_ua.dsp

    r65 r123  
    108108# Begin Source File 
    109109 
    110 SOURCE=..\src\pjsip_ua.h 
     110SOURCE="..\include\pjsip-ua\sip_dialog.h" 
    111111# End Source File 
    112112# Begin Source File 
    113113 
    114 SOURCE=..\src\pjsip_mod_ua\sip_dialog.h 
     114SOURCE="..\include\pjsip-ua\sip_regc.h" 
    115115# End Source File 
    116116# Begin Source File 
    117117 
    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 
     118SOURCE="..\include\pjsip-ua\sip_ua.h" 
    127119# End Source File 
    128120# End Group 
  • pjproject/trunk/pjsip/include/pjsip-ua/sip_ua.h

    • Property svn:keywords set to Id
    r65 r123  
    2121 
    2222/** 
    23  * @file ua.h 
    24  * @brief SIP User Agent Library 
     23 * @file sip_ua.h 
     24 * @brief SIP User Agent Module 
    2525 */ 
    2626 
    27 #include <pjsip_mod_ua/sip_dialog.h> 
    2827 
    2928PJ_BEGIN_DECL 
     
    4140 */ 
    4241 
    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. */ 
     43typedef pjsip_module pjsip_user_agent; 
    6444 
    6545 
    6646/** 
    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. 
    6853 */ 
    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  
     54PJ_DECL(pj_status_t) pjsip_ua_init(pjsip_endpoint *endpt); 
    7855 
    7956/** 
    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. 
    8160 */ 
    82 PJ_DECL(pjsip_module*) pjsip_ua_get_module(void); 
    83  
     61PJ_DECL(pjsip_user_agent*) pjsip_ua_instance(void); 
    8462 
    8563/** 
    86  * Dump user agent state to log file. 
     64 * Destroy the user agent layer. 
     65 * 
     66 * @return              PJ_SUCCESS on success. 
    8767 */ 
    88 PJ_DECL(void) pjsip_ua_dump( pjsip_user_agent *ua ); 
     68PJ_DECL(pj_status_t) pjsip_ua_destroy(void); 
     69 
    8970 
    9071/** 
     
    9475PJ_END_DECL 
    9576 
     77 
    9678#endif  /* __PJSIP_UA_H__ */ 
    9779 
  • pjproject/trunk/pjsip/include/pjsip/sip_auth.h

    r65 r123  
    3030PJ_BEGIN_DECL 
    3131 
     32 
    3233/** 
    3334 * @defgroup PJSIP_AUTH_API Authorization API's 
     
    3637 */ 
    3738 
    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. */ 
    3944typedef enum pjsip_cred_data_type 
    4045{ 
     
    7883    PJ_DECL_LIST_MEMBER(struct pjsip_cached_auth_hdr); 
    7984 
    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.         */ 
    8287 
    8388} pjsip_cached_auth_hdr; 
     
    9499 * that have been sent in the cache list. 
    95100 */ 
    96 typedef struct pjsip_auth_session 
    97 { 
    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; 
     101typedef 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.    */ 
    103108#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.              */ 
    106111#endif 
    107112#if PJSIP_AUTH_AUTO_SEND_NEXT 
    108     pjsip_www_authenticate_hdr  *last_chal; 
     113    pjsip_www_authenticate_hdr  *last_chal; /**< Last challenge seen.       */ 
    109114#endif 
    110115#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.               */ 
    112118#endif 
    113119 
    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 */ 
     128typedef 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 */ 
     152typedef 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 */ 
     163typedef 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 */ 
     184PJ_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 */ 
     201PJ_DECL(pj_status_t) pjsip_auth_clt_set_credentials( pjsip_auth_clt_sess *sess, 
     202                                                     int cred_cnt, 
     203                                                     const pjsip_cred_info *c); 
    179204 
    180205 
     
    195220 * Authorization/Proxy-Authorization to respond 401/407 response. 
    196221 * 
    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. 
    199223 * @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 */ 
     227PJ_DECL(pj_status_t) pjsip_auth_clt_init_req( pjsip_auth_clt_sess *sess, 
     228                                              pjsip_tx_data *tdata ); 
     229 
    211230 
    212231/** 
     
    216235 * new authorization header in the authorization cache. 
    217236 * 
    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. 
    228241 * @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 */ 
     251PJ_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 */ 
     273PJ_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 */ 
     299PJ_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 */ 
     320PJ_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 
    239327 
    240328/** 
     
    242330 */ 
    243331 
     332 
    244333PJ_END_DECL 
    245334 
     335 
    246336#endif  /* __PJSIP_AUTH_SIP_AUTH_H__ */ 
    247337 
  • pjproject/trunk/pjsip/include/pjsip/sip_errno.h

    r109 r123  
    8080 
    8181/************************************************************ 
    82  * GENERIC SIP ERRORS 
     82 * GENERIC/GENERAL SIP ERRORS 
    8383 ***********************************************************/ 
    8484/** 
     
    9797 */ 
    9898#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 */ 
    99104 
    100105 
     
    109114/** 
    110115 * @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 
    111143 * Unsupported URL scheme. 
    112144 */ 
    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 */ 
    124146/** 
    125147 * @hideinitializer 
    126148 * Missing Request-URI. 
    127149 */ 
    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 
    129162/** 
    130163 * @hideinitializer 
    131164 * Missing required header(s). 
    132165 */ 
    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 */ 
    134182/** 
    135183 * @hideinitializer 
    136184 * Missing message body. 
    137185 */ 
    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 */ 
    169187 
    170188 
     
    176194 * Unsupported transport type. 
    177195 */ 
    178 #define PJSIP_EUNSUPTRANSPORT   (PJSIP_ERRNO_START_PJSIP + 40)  /* 171040 */ 
     196#define PJSIP_EUNSUPTRANSPORT   (PJSIP_ERRNO_START_PJSIP + 60)  /* 171060 */ 
    179197/** 
    180198 * @hideinitializer 
    181199 * Buffer is being sent, operation still pending. 
    182200 */ 
    183 #define PJSIP_EPENDINGTX        (PJSIP_ERRNO_START_PJSIP + 41)  /* 171041 */ 
     201#define PJSIP_EPENDINGTX        (PJSIP_ERRNO_START_PJSIP + 61)  /* 171061 */ 
    184202/** 
    185203 * @hideinitializer 
    186204 * Rx buffer overflow. See also PJSIP_EMSGTOOLONG. 
    187205 */ 
    188 #define PJSIP_ERXOVERFLOW       (PJSIP_ERRNO_START_PJSIP + 42)  /* 171042 */ 
     206#define PJSIP_ERXOVERFLOW       (PJSIP_ERRNO_START_PJSIP + 62)  /* 171062 */ 
    189207/** 
    190208 * @hideinitializer 
     
    192210 * transmit data has been deleted on return of pjsip_tx_data_dec_ref(). 
    193211 */ 
    194 #define PJSIP_EBUFDESTROYED     (PJSIP_ERRNO_START_PJSIP + 43)  /* 171043 */ 
     212#define PJSIP_EBUFDESTROYED     (PJSIP_ERRNO_START_PJSIP + 63)  /* 171063 */ 
    195213 
    196214 
     
    202220 * Transaction has just been destroyed. 
    203221 */ 
    204 #define PJSIP_ETSXDESTROYED     (PJSIP_ERRNO_START_PJSIP + 60)  /* 171060 */ 
     222#define PJSIP_ETSXDESTROYED     (PJSIP_ERRNO_START_PJSIP + 70)  /* 171070 */ 
    205223 
    206224 
     
    270288 
    271289 
     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 
    272349 
    273350PJ_END_DECL 
  • pjproject/trunk/pjsip/include/pjsip/sip_transport.h

    r109 r123  
    219219 
    220220        /** The Call-ID header as found in the message. */ 
    221         pj_str_t                 call_id; 
     221        pjsip_cid_hdr           *cid; 
    222222 
    223223        /** The From header as found in the message. */ 
  • pjproject/trunk/pjsip/src/pjsip-ua/sip_ua.c

    r65 r123  
    4242 * Static prototypes. 
    4343 */ 
    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 ); 
     44static pj_status_t ua_load(pjsip_endpoint *endpt); 
     45static pj_status_t ua_unload(void); 
    4846static void ua_tsx_handler( struct pjsip_module *mod, pjsip_event *evt ); 
    4947static pjsip_dlg *find_dialog( pjsip_user_agent *ua, 
     
    5452 
    5553/* 
    56  * Default UA instance. 
    57  */ 
    58 static pjsip_user_agent ua_instance; 
    59  
    60 /* 
    6154 * Module interface. 
    6255 */ 
    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()    */ 
     56static 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  } 
    7585}; 
    7686 
     
    7888 * Initialize user agent instance. 
    7989 */ 
    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; 
     90static pj_status_t ua_load( pjsip_endpoint *endpt ) 
     91{ 
    8592    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; 
    9794 
    9895    /* 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); 
    115111 
    116112    /* Initialize dialog lock. */ 
     
    121117    pj_thread_local_set(pjsip_dlg_lock_tls_id, NULL); 
    122118 
    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; 
    133120} 
    134121 
     
    136123 * Destroy user agent. 
    137124 */ 
    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); 
     125static pj_status_t ua_unload() 
     126{ 
     127    pj_mutex_unlock(mod_ua.mutex); 
    143128 
    144129    /* 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; 
    167134} 
    168135 
  • pjproject/trunk/pjsip/src/pjsip/sip_auth_client.c

    r112 r123  
    1717 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  
    1818 */ 
     19 
    1920#include <pjsip/sip_auth.h> 
    2021#include <pjsip/sip_auth_parser.h>      /* just to get pjsip_DIGEST_STR */ 
    2122#include <pjsip/sip_transport.h> 
    2223#include <pjsip/sip_endpoint.h> 
     24#include <pjsip/sip_errno.h> 
    2325#include <pjlib-util/md5.h> 
    2426#include <pj/log.h> 
     
    2931#include <pj/ctype.h> 
    3032 
    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 
    3634 
    3735/* A macro just to get rid of type mismatch between char and unsigned char */ 
     
    3937 
    4038/* Logging. */ 
    41 #define THIS_FILE   "sip_auth.c" 
     39#define THIS_FILE   "sip_auth_client.c" 
    4240#if 0 
    4341#  define AUTH_TRACE_(expr)  PJ_LOG(3, expr) 
     
    4644#endif 
    4745 
    48 static const char hex[] = "0123456789abcdef"; 
    49  
    5046/* Transform digest to string. 
    51  * output must be at least MD5STRLEN+1 bytes. 
     47 * output must be at least PJSIP_MD5STRLEN+1 bytes. 
    5248 * 
    5349 * NOTE: THE OUTPUT STRING IS NOT NULL TERMINATED! 
     
    5551static void digest2str(const unsigned char digest[], char *output) 
    5652{ 
    57     char *p = output; 
    5853    int i; 
    59  
    6054    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 
    6660 
    6761/* 
     
    6963 * digest ASCII in 'result'.  
    7064 */ 
    71 static void create_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]; 
     65void 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]; 
    8276    unsigned char digest[16]; 
    8377    pj_md5_context pms; 
    8478 
    85     pj_assert(result->slen >= MD5STRLEN); 
     79    pj_assert(result->slen >= PJSIP_MD5STRLEN); 
    8680 
    8781    AUTH_TRACE_((THIS_FILE, "Begin creating digest")); 
     
    128122     ***/ 
    129123    pj_md5_init(&pms); 
    130     MD5_APPEND( &pms, ha1, MD5STRLEN); 
     124    MD5_APPEND( &pms, ha1, PJSIP_MD5STRLEN); 
    131125    MD5_APPEND( &pms, ":", 1); 
    132126    MD5_APPEND( &pms, nonce->ptr, nonce->slen); 
     
    140134    } 
    141135    MD5_APPEND( &pms, ":", 1); 
    142     MD5_APPEND( &pms, ha2, MD5STRLEN); 
     136    MD5_APPEND( &pms, ha2, PJSIP_MD5STRLEN); 
    143137 
    144138    /* This is the final response digest. */ 
     
    146140     
    147141    /* Convert digest to string and store in chal->response. */ 
    148     result->slen = MD5STRLEN; 
     142    result->slen = PJSIP_MD5STRLEN; 
    149143    digest2str(digest, result->ptr); 
    150144 
     
    207201        PJ_LOG(4,(THIS_FILE, "Unsupported digest algorithm \"%.*s\"", 
    208202                  chal->algorithm.slen, chal->algorithm.ptr)); 
    209         return -1; 
     203        return PJSIP_EINVALIDALGORITHM; 
    210204    } 
    211205 
     
    219213     
    220214    /* 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; 
    223217 
    224218    if (chal->qop.slen == 0) { 
     
    226220 
    227221        /* Convert digest to string and store in chal->response. */ 
    228         create_digest( &cred->response, &cred->nonce, NULL, NULL, NULL, 
    229                       uri, cred_info, method); 
     222        pjsip_auth_create_digest( &cred->response, &cred->nonce, NULL, NULL,  
     223                                  NULL, uri, cred_info, method); 
    230224 
    231225    } else if (has_auth_qop(pool, &chal->qop)) { 
     
    244238        } 
    245239 
    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 ); 
    248243 
    249244    } else { 
     
    251246        PJ_LOG(4,(THIS_FILE, "Unsupported qop offer %.*s",  
    252247                  chal->qop.slen, chal->qop.ptr)); 
    253         return -1; 
    254     } 
    255  
    256     return 0; 
    257 } 
    258  
    259 #if PJSIP_AUTH_QOP_SUPPORT 
     248        return PJSIP_EINVALIDQOP; 
     249    } 
     250 
     251    return PJ_SUCCESS; 
     252} 
     253 
     254#if defined(PJSIP_AUTH_QOP_SUPPORT) && PJSIP_AUTH_QOP_SUPPORT!=0 
    260255/* 
    261256 * Update authentication session with a challenge. 
    262257 */ 
    263258static void update_digest_session( pj_pool_t *ses_pool,  
    264                                    pjsip_auth_session *auth_sess, 
     259                                   pjsip_cached_auth *cached_auth, 
    265260                                   const pjsip_www_authenticate_hdr *hdr ) 
    266261{ 
     
    269264 
    270265    /* Initialize cnonce and qop if not present. */ 
    271     if (auth_sess->cnonce.slen == 0) { 
     266    if (cached_auth->cnonce.slen == 0) { 
    272267        /* 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); 
    274269 
    275270        /* Create cnonce */ 
    276         pj_create_unique_string( ses_pool, &auth_sess->cnonce ); 
     271        pj_create_unique_string( ses_pool, &cached_auth->cnonce ); 
    277272 
    278273        /* Initialize nonce-count */ 
    279         auth_sess->nc = 1; 
     274        cached_auth->nc = 1; 
    280275 
    281276        /* 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,  
    285280                      &hdr->challenge.digest.realm); 
    286281        } 
     
    289284        /* Update last_nonce and nonce-count */ 
    290285        if (!pj_strcmp(&hdr->challenge.digest.nonce,  
    291                        &auth_sess->last_chal->challenge.digest.nonce))  
     286                       &cached_auth->last_chal->challenge.digest.nonce))  
    292287        { 
    293288            /* Same nonce, increment nonce-count */ 
    294             ++auth_sess->nc; 
     289            ++cached_auth->nc; 
    295290        } else { 
    296291            /* 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, 
    298293                      &hdr->challenge.digest.nonce); 
    299294            /* 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, 
    301296                          &hdr->challenge.digest.opaque))  
    302297            { 
    303298                pj_strdup(ses_pool,  
    304                           &auth_sess->last_chal->challenge.digest.opaque, 
     299                          &cached_auth->last_chal->challenge.digest.opaque, 
    305300                          &hdr->challenge.digest.opaque); 
    306301            } 
    307             auth_sess->nc = 1; 
     302            cached_auth->nc = 1; 
    308303        } 
    309304    } 
     
    312307 
    313308 
    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. */ 
     310static 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; 
    323318    } 
    324319 
    325320    return NULL; 
    326321} 
     322 
     323/* Find credential to use for the specified realm and auth scheme. */ 
     324static 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. */ 
     339PJ_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. */ 
     357PJ_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 
    327370 
    328371/*  
     
    330373 * in WWW-Authenticate/Proxy-Authenticate header. 
    331374 */ 
    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; 
     375static 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; 
    342385    char tmp[PJSIP_MAX_URL_SIZE]; 
    343386    pj_str_t uri_str; 
    344387    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); 
    350393 
    351394    /* Print URL in the original request. */ 
    352395    uri_str.ptr = tmp; 
    353     uri_str.slen = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, uri, tmp, sizeof(tmp)); 
     396    uri_str.slen = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, uri, tmp,sizeof(tmp)); 
    354397    if (uri_str.slen < 1) { 
    355398        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; 
    358400    } 
    359401 
     
    371413 
    372414    if (hdr->type == PJSIP_H_WWW_AUTHENTICATE) 
    373         auth = pjsip_authorization_hdr_create(pool); 
     415        hauth = pjsip_authorization_hdr_create(pool); 
    374416    else if (hdr->type == PJSIP_H_PROXY_AUTHENTICATE) 
    375         auth = pjsip_proxy_authorization_hdr_create(pool); 
     417        hauth = pjsip_proxy_authorization_hdr_create(pool); 
    376418    else { 
    377         pj_assert(0); 
    378         return NULL; 
     419        pj_assert(!"Invalid response header!"); 
     420        return PJSIP_EINVALIDHDR; 
    379421    } 
    380422 
    381423    /* Only support digest scheme at the moment. */ 
    382424    if (!pj_stricmp(&hdr->scheme, &pjsip_DIGEST_STR)) { 
    383         pj_status_t rc; 
    384425        pj_str_t *cnonce = NULL; 
    385426        pj_uint32_t nc = 1; 
     
    388429#       if PJSIP_AUTH_QOP_SUPPORT 
    389430        { 
    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; 
    395436            } 
    396437        } 
    397438#       endif   /* PJSIP_AUTH_QOP_SUPPORT */ 
    398439 
    399         auth->scheme = pjsip_DIGEST_STR; 
    400         rc = respond_digest( pool, &auth->credential.digest, 
    401                             &hdr->challenge.digest, &uri_str, cred_info, 
    402                             cnonce, nc, &method->name); 
    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; 
    405446 
    406447        /* 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; 
    410451                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; 
    412453                } else { 
    413                     auth_sess->qop_value = PJSIP_AUTH_QOP_UNKNOWN; 
     454                    cached_auth->qop_value = PJSIP_AUTH_QOP_UNKNOWN; 
    414455                } 
    415456            } 
    416457        } 
    417458    } else { 
    418         auth = NULL; 
     459        return PJSIP_EINVALIDAUTHSCHEME; 
    419460    } 
    420461 
     
    424465#   if PJSIP_AUTH_HEADER_CACHING 
    425466    { 
    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) { 
    427468            pjsip_cached_auth_hdr *cached_hdr; 
    428469 
    429470            /* 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) { 
    432473                if (pjsip_method_cmp(method, &cached_hdr->method)==0) 
    433474                    break; 
     
    436477 
    437478            /* 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; 
    440481            } else { 
    441482                cached_hdr = pj_pool_alloc(pool, sizeof(*cached_hdr)); 
    442483                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 ); 
    445486            } 
    446487        } 
     
    448489#   endif 
    449490 
    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 
     498static 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) 
    518502{ 
    519503    const pjsip_cred_info *cred; 
    520504    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 ); 
    526511    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; 
    529520     
    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; 
    537527} 
    538528#endif 
    539529 
    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. */ 
     533PJ_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 
    574553            { 
    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) { 
    577556                    if (pjsip_method_cmp(&entry->method, method)==0) { 
    578557                        pjsip_authorization_hdr *hauth; 
     
    580559                        pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hauth); 
    581560                    } else { 
    582 #                       if (PJSIP_AUTH_AUTO_SEND_NEXT) 
     561#                       if defined(PJSIP_AUTH_AUTO_SEND_NEXT) && \ 
     562                           PJSIP_AUTH_AUTO_SEND_NEXT!=0 
    583563                        { 
    584                             new_auth_for_req( tdata, sess_pool, sess,  
    585                                               cred_count, cred_info); 
     564                            new_auth_for_req( tdata, sess, auth, NULL); 
    586565                        } 
    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 
    594567                    } 
    595568                    entry = entry->next; 
    596569                } 
    597570            } 
    598 #           elif (PJSIP_AUTH_AUTO_SEND_NEXT) 
     571#           elif defined(PJSIP_AUTH_AUTO_SEND_NEXT) && \ 
     572                 PJSIP_AUTH_AUTO_SEND_NEXT!=0 
    599573            { 
    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 
    610577 
    611578        }  
    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) { 
    614583            /* For qop="auth", we have to re-create the authorization header.  
    615584             */ 
     
    617586            pjsip_authorization_hdr *hauth; 
    618587 
    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); 
    622590            if (!cred) { 
    623                 sess = sess->next; 
     591                auth = auth->next; 
    624592                continue; 
    625593            } 
    626594 
    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); 
    635604        } 
    636605#       endif   /* PJSIP_AUTH_QOP_SUPPORT && PJSIP_AUTH_AUTO_SEND_NEXT */ 
    637606 
    638         sess = sess->next; 
    639     } 
    640     return 0; 
    641 } 
     607        auth = auth->next; 
     608    } 
     609 
     610    return PJ_SUCCESS; 
     611} 
     612 
    642613 
    643614/* 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) 
     615static 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) 
    652622{ 
    653623    const pjsip_cred_info *cred; 
    654     pjsip_authorization_hdr *sent_auth = NULL, *hauth; 
     624    pjsip_authorization_hdr *sent_auth = NULL; 
    655625    pjsip_hdr *hdr; 
     626    pj_status_t status; 
    656627 
    657628    /* See if we have sent authorization header for this realm */ 
     
    686657                       sent_auth->credential.digest.realm.slen, 
    687658                       sent_auth->credential.digest.realm.ptr)); 
    688             return NULL; 
     659            return PJSIP_EFAILEDCREDENTIAL; 
    689660        } 
    690661 
     
    696667 
    697668    /* 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); 
    700671    if (!cred) { 
    701672        const pj_str_t *realm = &hchal->challenge.common.realm; 
     
    705676                  realm->slen, realm->ptr, 
    706677                  hchal->scheme.slen, hchal->scheme.ptr)); 
    707         return NULL; 
     678        return PJSIP_ENOCREDENTIAL; 
    708679    } 
    709680 
    710681    /* Respond to authorization challenge. */ 
    711     hauth = pjsip_auth_respond( req_pool, hchal, uri, cred,  
    712                                 &tdata->msg->line.req.method,  
    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; 
    715686} 
    716687 
     
    722693 *    in cached_list. 
    723694 */ 
    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 { 
     695PJ_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; 
    732701    const pjsip_hdr *hdr; 
    733702    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     
    741718    /* 
    742719     * Respond to each authentication challenge. 
     
    744721    hdr = rdata->msg_info.msg->hdr.next; 
    745722    while (hdr != &rdata->msg_info.msg->hdr) { 
    746         pjsip_auth_session *sess; 
     723        pjsip_cached_auth *cached_auth; 
    747724        const pjsip_www_authenticate_hdr *hchal; 
    748725        pjsip_authorization_hdr *hauth; 
     
    763740         * if not present. 
    764741         */ 
    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); 
    770747#           if (PJSIP_AUTH_HEADER_CACHING) 
    771748            { 
    772                 pj_list_init(&sess->cached_hdr); 
     749                pj_list_init(&cached_auth->cached_hdr); 
    773750            } 
    774751#           endif 
    775             pj_list_insert_before( sess_list, sess ); 
     752            pj_list_insert_before( &sess->cached_auth, cached_auth ); 
    776753        } 
    777754 
     
    779756         * authorization session. 
    780757         */ 
    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; 
    785762 
    786763        /* Add to the message. */ 
     
    800777 
    801778    /* 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  
    3535    { PJSIP_ETYPEEXISTS ,       "Object with the same type exists" }, 
    3636    { PJSIP_ESHUTDOWN,          "SIP stack shutting down" }, 
     37    { PJSIP_ENOTINITIALIZED,    "SIP object is not initialized." }, 
    3738 
    3839    /* Messaging errors */ 
    3940    { PJSIP_EINVALIDMSG,        "Invalid message/syntax error" }, 
    40     { PJSIP_EINVALIDSCHEME,     "Invalid URI scheme" }, 
     41    { PJSIP_ENOTREQUESTMSG,     "Expecting request message"}, 
     42    { PJSIP_ENOTRESPONSEMSG,    "Expecting response message"}, 
    4143    { PJSIP_EMSGTOOLONG,        "Message too long" }, 
    4244    { PJSIP_EPARTIALMSG,        "Partial message" }, 
     45 
     46    { PJSIP_EINVALIDSTATUS,     "Invalid status code"}, 
     47 
     48    { PJSIP_EINVALIDSCHEME,     "Invalid URI scheme" }, 
    4349    { PJSIP_EMISSINGREQURI,     "Missing Request-URI" }, 
     50    { PJSIP_EINVALIDREQURI,     "Invalid Request URI" }, 
     51    { PJSIP_EURITOOLONG,        "URI is too long" },  
     52 
    4453    { PJSIP_EMISSINGHDR,        "Missing required header(s)" }, 
    45     { PJSIP_EMISSINGBODY,       "Missing message body" }, 
     54    { PJSIP_EINVALIDHDR,        "Invalid header field"}, 
    4655    { PJSIP_EINVALIDVIA,        "Invalid Via header" }, 
    4756    { 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" }, 
    5259 
    5360    /* Transport errors */ 
     
    5966    /* Transaction errors */ 
    6067    { 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" } 
    6181}; 
    6282 
  • pjproject/trunk/pjsip/src/pjsip/sip_parser.c

    r119 r123  
    14001400 
    14011401    if (ctx->rdata) 
    1402         ctx->rdata->msg_info.call_id = hdr->id; 
     1402        ctx->rdata->msg_info.cid = hdr; 
    14031403 
    14041404    return (pjsip_hdr*)hdr; 
  • pjproject/trunk/pjsip/src/pjsip/sip_transaction.c

    r119 r123  
    270270    len_required = 9 +                      /* CSeq number */ 
    271271                   rdata->msg_info.from->tag.slen +   /* From tag. */ 
    272                    rdata->msg_info.call_id.slen +    /* Call-ID */ 
     272                   rdata->msg_info.cid->id.slen +    /* Call-ID */ 
    273273                   host->slen +             /* Via host. */ 
    274274                   9 +                      /* Via port. */ 
     
    300300 
    301301    /* Add Call-ID. */ 
    302     len = rdata->msg_info.call_id.slen; 
    303     pj_memcpy( p, rdata->msg_info.call_id.ptr, len ); 
     302    len = rdata->msg_info.cid->id.slen; 
     303    pj_memcpy( p, rdata->msg_info.cid->id.ptr, len ); 
    304304    p += len; 
    305305    *p++ = SEPARATOR; 
     
    15901590    ++tsx->retransmit_count; 
    15911591 
    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     */ 
    15971595    if (resched) { 
     1596        pj_assert(tsx->state != PJSIP_TSX_STATE_CONFIRMED); 
    15981597        if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) { 
    15991598            tsx->transport_flag |= TSX_HAS_PENDING_RESCHED; 
     
    16011600            tsx_resched_retransmission(tsx); 
    16021601        } 
     1602    } 
     1603 
     1604    status = tsx_send_msg( tsx, tsx->last_tx); 
     1605    if (status != PJ_SUCCESS) { 
     1606        return status; 
    16031607    } 
    16041608 
  • pjproject/trunk/pjsip/src/pjsip/sip_transport.c

    r119 r123  
    879879 
    880880        /* Perform basic header checking. */ 
    881         if (rdata->msg_info.call_id.ptr == NULL ||  
     881        if (rdata->msg_info.cid->id.ptr == NULL ||  
    882882            rdata->msg_info.from == NULL ||  
    883883            rdata->msg_info.to == NULL ||  
  • pjproject/trunk/pjsip/src/pjsip/sip_transport_loop.c

    r110 r123  
    251251 
    252252/* Worker thread for loop transport. */ 
    253 static int loop_thread(void *arg) 
     253static int loop_transport_worker_thread(void *arg) 
    254254{ 
    255255    struct loop_transport *loop = arg; 
     
    385385 
    386386    /* 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,  
    388389                              PJ_THREAD_SUSPENDED, &loop->thread); 
    389390    if (status != PJ_SUCCESS) 
  • pjproject/trunk/pjsip/src/pjsip/sip_util.c

    r119 r123  
    351351    pjsip_rr_hdr *rr; 
    352352    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); 
    353359 
    354360    /* rdata must be a request message. */ 
  • pjproject/trunk/pjsip/src/test-pjsip/transport_test.c

    r109 r123  
    117117{ 
    118118    /* Check that this is our request. */ 
    119     if (pj_strcmp2(&rdata->msg_info.call_id, CALL_ID_HDR) == 0) { 
     119    if (pj_strcmp2(&rdata->msg_info.cid->id, CALL_ID_HDR) == 0) { 
    120120        /* It is! */ 
    121121        /* Send response. */ 
     
    150150static pj_bool_t my_on_rx_response(pjsip_rx_data *rdata) 
    151151{ 
    152     if (pj_strcmp2(&rdata->msg_info.call_id, CALL_ID_HDR) == 0) { 
     152    if (pj_strcmp2(&rdata->msg_info.cid->id, CALL_ID_HDR) == 0) { 
    153153        pj_get_timestamp(&my_recv_time); 
    154154        recv_status = PJ_SUCCESS; 
     
    335335static pj_bool_t rt_on_rx_request(pjsip_rx_data *rdata) 
    336336{ 
    337     if (!pj_strncmp(&rdata->msg_info.call_id, &rt_call_id, rt_call_id.slen)) { 
    338         char *pos = pj_strchr(&rdata->msg_info.call_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, '/'); 
    339339        int thread_id = (*pos - '0'); 
    340340 
     
    423423static pj_bool_t rt_on_rx_response(pjsip_rx_data *rdata) 
    424424{ 
    425     if (!pj_strncmp(&rdata->msg_info.call_id, &rt_call_id, rt_call_id.slen)) { 
    426         char *pos = pj_strchr(&rdata->msg_info.call_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; 
    427427        int thread_id = (*pos - '0'); 
    428428        pj_timestamp recv_time; 
  • pjproject/trunk/pjsip/src/test-pjsip/tsx_uac_test.c

    r117 r123  
    399399            } 
    400400 
    401             /* last_tx is ACK in this case. */ 
     401            /* last_tx MUST be the INVITE request 
     402             * (authorization depends on this behavior) 
     403             */ 
    402404            if (tsx->last_tx && tsx->last_tx->msg->line.req.method.id != 
    403                 PJSIP_ACK_METHOD) 
     405                PJSIP_INVITE_METHOD) 
    404406            { 
    405407                PJ_LOG(3,(THIS_FILE,  
    406                           "    error: last_tx is not ACK")); 
     408                          "    error: last_tx is not INVITE")); 
    407409                test_complete = -748; 
    408410            } 
     
    462464            } 
    463465 
    464             /* last_tx is ACK in this case. */ 
     466            /* last_tx MUST be INVITE.  
     467             * (authorization depends on this behavior) 
     468             */ 
    465469            if (tsx->last_tx && tsx->last_tx->msg->line.req.method.id != 
    466                 PJSIP_ACK_METHOD) 
     470                PJSIP_INVITE_METHOD) 
    467471            { 
    468472                PJ_LOG(3,(THIS_FILE,  
    469                           "    error: last_tx is not ACK")); 
     473                          "    error: last_tx is not INVITE")); 
    470474                test_complete = -764; 
    471475            } 
  • pjproject/trunk/pjsip/src/test-pjsip/tsx_uas_test.c

    r119 r123  
    6767 **     Transaction also MUST terminate in T4 seconds. 
    6868 ** 
    69  ** TEST10_BRANCH_ID 
    70  **     Test where INVITE UAS transaction never receives ACK 
    71  ** 
    7269 ** 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 
    7382 **     When UAS failed to deliver the response with the selected transport, 
    7483 **     it should try contacting the client with other transport or begin 
     
    7988 **            upon receiving request retransmission). 
    8089 **         c. COMPLETED state. 
    81  ** 
    82  ** TEST12_BRANCH_ID 
    83  **     Variant of previous test, where transaction fails to deliver the  
    84  **     response using any kind of transports. Transaction should report 
    85  **     transport error to its transaction user. 
    8690 ** 
    8791 **/ 
     
    99103static char *TEST11_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test11"; 
    100104static char *TEST12_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test12"; 
     105static char *TEST13_BRANCH_ID = PJSIP_RFC3261_BRANCH_ID "-UAS-Test13"; 
    101106 
    102107#define TEST1_STATUS_CODE       200 
     
    116121#define TEST7_STATUS_CODE       301 
    117122#define TEST8_STATUS_CODE       302 
     123#define TEST9_STATUS_CODE       301 
    118124 
    119125 
     
    211217    status = pjsip_tsx_send_msg(tsx, r->tdata); 
    212218    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); 
    214222        pjsip_tx_data_dec_ref(r->tdata); 
    215223        return; 
    216224    } 
     225 
     226    pj_mutex_unlock(tsx->mutex); 
    217227} 
    218228 
     
    235245    status = pjsip_tsx_send_msg(tsx, tdata); 
    236246    if (status != PJ_SUCCESS) { 
    237         app_perror("    error: unable to send response", status); 
    238247        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; 
    240251        return; 
    241252    } 
     
    250261    pj_status_t status; 
    251262    pjsip_tx_data *tdata; 
     263    pj_timer_entry *t; 
    252264    struct response *r; 
    253265    pj_time_val delay; 
     
    269281    pj_time_val_normalize(&delay); 
    270282 
    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); 
    275288    if (status != PJ_SUCCESS) { 
     289        pjsip_tx_data_dec_ref(tdata); 
    276290        app_perror("    error: unable to schedule timer", status); 
    277291        test_complete = -199; 
    278         pjsip_tx_data_dec_ref(tdata); 
    279292        return; 
    280293    } 
     
    575588        } 
    576589 
     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        } 
    577667    } 
    578668 
     
    613703 
    614704        if (msg->type == PJSIP_REQUEST_MSG) { 
    615             /* On received response, create UAS and respond with final  
     705            /* On received request, create UAS and respond with final  
    616706             * response.  
    617707             */ 
     
    653743 
    654744        if (msg->type == PJSIP_REQUEST_MSG) { 
    655             /* On received response, create UAS and respond with provisional 
     745            /* On received request, create UAS and respond with provisional 
    656746             * response, then schedule timer to send final response. 
    657747             */ 
     
    706796 
    707797        if (msg->type == PJSIP_REQUEST_MSG) { 
    708             /* On received response, create UAS. */ 
     798            /* On received request, create UAS. */ 
    709799            pjsip_transaction *tsx; 
    710800 
     
    787877        if (msg->type == PJSIP_REQUEST_MSG) { 
    788878 
    789             /* On received response, create UAS. */ 
     879            /* On received request, create UAS. */ 
    790880            pjsip_transaction *tsx; 
    791881 
     
    862952        return PJ_TRUE; 
    863953 
    864     } else if (pj_strcmp2(&branch_param, TEST9_BRANCH_ID)) { 
     954    } else if (pj_strcmp2(&branch_param, TEST9_BRANCH_ID) == 0) { 
    865955 
    866956        /* 
     
    871961        if (msg->type == PJSIP_REQUEST_MSG) { 
    872962 
    873             /* On received response, create UAS. */ 
     963            /* On received request, create UAS. */ 
    874964            pjsip_transaction *tsx; 
    875965 
     
    877967            if (status != PJ_SUCCESS) { 
    878968                app_perror("    error: unable to create transaction", status); 
    879                 test_complete = -140; 
     969                test_complete = -150; 
    880970                return PJ_TRUE; 
    881971            } 
    882972 
    883973            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 
    894976 
    895977        } else { 
    896             int code; 
    897978 
    898979            ++recv_count; 
    899980 
    900             if (pj_strcmp2(&branch_param, TEST7_BRANCH_ID) == 0) 
    901                 code = TEST7_STATUS_CODE; 
    902             else 
    903                 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            } 
    904985 
    905986            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                 } 
    911987 
    912988                recv_last = rdata->pkt_info.timestamp; 
    913989 
    914             } else { 
    915  
     990            } else if (recv_count < 5) { 
     991 
     992                /* Let UAS retransmit some messages before we send ACK. */ 
    916993                pj_time_val now; 
    917994                unsigned msec, msec_expected; 
     
    9311008                              "time (%d ms expected, %d ms received", 
    9321009                              msec_expected, msec)); 
    933                     test_complete = -142; 
     1010                    test_complete = -152; 
    9341011                } 
    9351012 
    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; 
    9401034                } 
    9411035 
    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 
    9461094        return PJ_TRUE; 
    9471095    } 
     
    12131361 
    12141362 
     1363/***************************************************************************** 
     1364 ** 
     1365 ** TEST9_BRANCH_ID: retransmission of non-2xx INVITE final response must  
     1366 ** cease when ACK is received 
     1367 ** 
     1368 ***************************************************************************** 
     1369 */ 
     1370static 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 */ 
     1400static 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} 
    12151470 
    12161471/***************************************************************************** 
     
    12451500    } 
    12461501 
    1247 #if 0 
    12481502    /* TEST1_BRANCH_ID: Basic 2xx final response.  
    12491503     * TEST2_BRANCH_ID: Basic non-2xx final response.  
     
    12941548        return status; 
    12951549 
    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 
    12971566 
    12981567    pjsip_transport_dec_ref(loop); 
  • pjproject/trunk/pjsip/src/test-pjsip/txdata_test.c

    r119 r123  
    155155     * many more fields need to be initialized!! 
    156156     */ 
    157     dummy_rdata.msg_info.call_id = (HFIND(invite->msg, cid, CALL_ID))->id; 
     157    dummy_rdata.msg_info.cid = HFIND(invite->msg, cid, CALL_ID); 
    158158    dummy_rdata.msg_info.clen = NULL; 
    159159    dummy_rdata.msg_info.cseq = HFIND(invite->msg, cseq, CSEQ); 
Note: See TracChangeset for help on using the changeset viewer.