Changeset 141 for pjproject/trunk


Ignore:
Timestamp:
Feb 7, 2006 6:48:01 PM (19 years ago)
Author:
bennylp
Message:

Tested initial implementation: basic UAC, client registration, authentication, etc

Location:
pjproject/trunk
Files:
23 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib/include/pj/config.h

    r125 r141  
    176176 * flag is set. 
    177177 * 
    178  * Default: 800 
     178 * Default: 1500 
    179179 */ 
    180180#ifndef PJ_LOG_MAX_SIZE 
    181 #  define PJ_LOG_MAX_SIZE           800 
     181#  define PJ_LOG_MAX_SIZE           1500 
    182182#endif 
    183183 
  • pjproject/trunk/pjlib/include/pj/log.h

    r125 r141  
    113113/** 
    114114 * Default logging writer function used by front end logger function. 
     115 * This function will print the log message to stdout only. 
    115116 * Application normally should NOT need to call this function, but 
    116117 * rather use the PJ_LOG macro. 
  • pjproject/trunk/pjlib/src/pj/config.c

    r108 r141  
    2222 
    2323static const char *id = "config.c"; 
    24 const char *PJ_VERSION = "0.5"; 
     24const char *PJ_VERSION = "0.5.1"; 
    2525 
    2626PJ_DEF(void) pj_dump_config(void) 
  • pjproject/trunk/pjlib/src/pj/log.c

    r125 r141  
    7474    char log_buffer[PJ_LOG_MAX_SIZE]; 
    7575#endif 
    76     int len; 
     76    int len, print_len; 
    7777 
    7878    PJ_CHECK_STACK(); 
     
    138138 
    139139    /* Print the whole message to the string log_buffer. */ 
    140     len = len + vsnprintf(pre, sizeof(log_buffer)-len, format, marker); 
     140    print_len = vsnprintf(pre, sizeof(log_buffer)-len, format, marker); 
     141    if (print_len < 0) { 
     142        print_len = pj_snprintf(pre, sizeof(log_buffer)-len,  
     143                                "<logging error: msg too long>"); 
     144    } 
     145    len = len + print_len; 
    141146    if (len > 0 && len < sizeof(log_buffer)-2) { 
    142147        if (log_decor & PJ_LOG_HAS_CR) { 
  • pjproject/trunk/pjsip/build/pjsip_core.dsp

    r127 r141  
    180180 
    181181SOURCE=..\src\pjsip\sip_util_statefull.c 
    182 # PROP Exclude_From_Build 1 
    183182# End Source File 
    184183# End Group 
  • pjproject/trunk/pjsip/build/pjsip_ua.dsp

    r139 r141  
    9898!ELSEIF  "$(CFG)" == "pjsip_ua - Win32 Debug" 
    9999 
    100 # PROP Exclude_From_Build 1 
    101  
    102100!ENDIF  
    103101 
     
    107105 
    108106# PROP Default_Filter "h;hpp;hxx;hm;inl" 
     107# Begin Source File 
     108 
     109SOURCE=..\include\pjsip_ua.h 
     110# End Source File 
    109111# Begin Source File 
    110112 
  • pjproject/trunk/pjsip/build/pjsua.dsp

    r139 r141  
    101101!ELSEIF  "$(CFG)" == "pjsua - Win32 Debug" 
    102102 
     103!ENDIF  
     104 
     105# End Source File 
     106# Begin Source File 
     107 
     108SOURCE=..\src\pjsua\main_old.c 
     109 
     110!IF  "$(CFG)" == "pjsua - Win32 Release" 
     111 
     112!ELSEIF  "$(CFG)" == "pjsua - Win32 Debug" 
     113 
    103114# PROP Exclude_From_Build 1 
    104115 
     
    111122# PROP Exclude_From_Build 1 
    112123# End Source File 
     124# Begin Source File 
     125 
     126SOURCE=..\src\pjsua\pjsua.c 
     127# End Source File 
     128# Begin Source File 
     129 
     130SOURCE=..\src\pjsua\pjsua_reg.c 
     131# End Source File 
    113132# End Group 
    114133# Begin Group "Header Files" 
     
    119138SOURCE=..\src\pjsua\getopt.h 
    120139# End Source File 
     140# Begin Source File 
     141 
     142SOURCE=..\src\pjsua\pjsua.h 
     143# End Source File 
    121144# End Group 
    122145# Begin Group "Resource Files" 
  • pjproject/trunk/pjsip/include/pjsip-ua/sip_inv.h

    r139 r141  
    3939    PJSIP_INV_STATE_CONFIRMED,      /**< After ACK is sent/received.        */ 
    4040    PJSIP_INV_STATE_DISCONNECTED,   /**< Session is terminated.             */ 
    41     PJSIP_INV_STATE_TERMINATED,     /**< Session will be destroyed soon.    */ 
    4241}; 
    4342 
  • pjproject/trunk/pjsip/include/pjsip-ua/sip_regc.h

    r65 r141  
    2727#include <pjsip/sip_types.h> 
    2828#include <pjsip/sip_auth.h> 
    29 #include <pjsip_mod_ua/sip_ua.h> 
     29//#include <pjsip/sip_ua.h> 
    3030 
    3131PJ_BEGIN_DECL 
     
    8686 * @param token     A data to be associated with the client registration struct. 
    8787 * @param cb        Pointer to callback function to receive registration status. 
    88  * 
    89  * @return          client registration structure. 
    90  */ 
    91 PJ_DECL(pjsip_regc*) pjsip_regc_create( pjsip_endpoint *endpt, void *token, 
    92                                         pjsip_regc_cb *cb); 
     88 * @param p_regc    Pointer to receive client registration structure. 
     89 * 
     90 * @return          PJ_SUCCESS on success. 
     91 */ 
     92PJ_DECL(pj_status_t) pjsip_regc_create( pjsip_endpoint *endpt, void *token, 
     93                                        pjsip_regc_cb *cb,  
     94                                        pjsip_regc **p_regc); 
    9395 
    9496 
     
    99101 * 
    100102 * @param regc      The client registration structure. 
    101  */ 
    102 PJ_DECL(void) pjsip_regc_destroy(pjsip_regc *regc); 
     103 * 
     104 * @return          PJ_SUCCESS on success. 
     105 */ 
     106PJ_DECL(pj_status_t) pjsip_regc_destroy(pjsip_regc *regc); 
    103107 
    104108/** 
     
    138142 * Set authentication credentials to use by this registration. 
    139143 * 
    140  * @param dlg           The registration structure. 
    141  * @param count         Number of credentials in the array. 
    142  * @param cred          Array of credentials. 
    143  * 
    144  * @return              Zero on success. 
     144 * @param dlg       The registration structure. 
     145 * @param count     Number of credentials in the array. 
     146 * @param cred      Array of credentials. 
     147 * 
     148 * @return          PJ_SUCCESS on success. 
    145149 */ 
    146150PJ_DECL(pj_status_t) pjsip_regc_set_credentials( pjsip_regc *regc, 
     
    158162 * @param autoreg   If non zero, the library will automatically refresh the 
    159163 *                  next registration until application unregister. 
    160  * 
    161  * @return          SIP REGISTER request. 
    162  */ 
    163 PJ_DECL(pjsip_tx_data*) pjsip_regc_register(pjsip_regc *regc, pj_bool_t autoreg); 
     164 * @param p_tdata   Pointer to receive the REGISTER request. 
     165 * 
     166 * @return          PJ_SUCCESS on success. 
     167 */ 
     168PJ_DECL(pj_status_t) pjsip_regc_register(pjsip_regc *regc, pj_bool_t autoreg, 
     169                                         pjsip_tx_data **p_tdata); 
    164170 
    165171 
     
    168174 * 
    169175 * @param regc      The client registration structure. 
    170  * 
    171  * @return          SIP REGISTER request. 
    172  */ 
    173 PJ_DECL(pjsip_tx_data*) pjsip_regc_unregister(pjsip_regc *regc); 
     176 * @param p_tdata   Pointer to receive the REGISTER request. 
     177 * 
     178 * @return          PJ_SUCCESS on success. 
     179 */ 
     180PJ_DECL(pj_status_t) pjsip_regc_unregister(pjsip_regc *regc, 
     181                                           pjsip_tx_data **p_tdata); 
    174182 
    175183/** 
     
    202210 * @param regc      The client registration structure. 
    203211 * @param tdata     Transmit data. 
    204  */ 
    205 PJ_DECL(void) pjsip_regc_send(pjsip_regc *regc, pjsip_tx_data *tdata); 
     212 * 
     213 * @return          PJ_SUCCESS on success. 
     214 */ 
     215PJ_DECL(pj_status_t) pjsip_regc_send(pjsip_regc *regc, pjsip_tx_data *tdata); 
    206216 
    207217 
  • pjproject/trunk/pjsip/include/pjsip/sip_dialog.h

    r139 r141  
    6868 
    6969    /* Dialog's session properties. */ 
     70    pj_bool_t           established;/**< Dialog is established?             */ 
    7071    pjsip_uri          *target;     /**< Current target.                    */ 
    7172    pjsip_dlg_party     local;      /**< Local party info.                  */ 
  • pjproject/trunk/pjsip/include/pjsip_ua.h

    r139 r141  
    2121 
    2222#include <pjsip-ua/sip_inv.h> 
     23#include <pjsip-ua/sip_regc.h> 
     24 
    2325 
    2426#endif  /* __PJSIP_UA_H__ */ 
  • pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c

    r139 r141  
    107107static pj_bool_t mod_inv_on_rx_request(pjsip_rx_data *rdata) 
    108108{ 
     109    pjsip_dialog *dlg; 
     110 
    109111    /* Ignore requests outside dialog */ 
    110     if (pjsip_rdata_get_dlg(rdata) == NULL) 
     112    dlg = pjsip_rdata_get_dlg(rdata); 
     113    if (dlg == NULL) 
    111114        return PJ_FALSE; 
    112115 
    113     /* Ignore all. */ 
     116    /* Answer BYE with 200/OK. */ 
     117    if (rdata->msg_info.msg->line.req.method.id == PJSIP_BYE_METHOD) { 
     118        pj_status_t status; 
     119        pjsip_tx_data *tdata; 
     120 
     121        status = pjsip_dlg_create_response(dlg, rdata, 200, NULL, &tdata); 
     122        if (status == PJ_SUCCESS) 
     123            status = pjsip_dlg_send_response(dlg, pjsip_rdata_get_tsx(rdata), 
     124                                             tdata); 
     125 
     126        return status==PJ_SUCCESS ? PJ_TRUE : PJ_FALSE; 
     127    } 
     128 
    114129    return PJ_FALSE; 
    115130} 
     
    915930 
    916931    case PJSIP_INV_STATE_DISCONNECTED: 
    917     case PJSIP_INV_STATE_TERMINATED: 
    918932        /* No need to do anything. */ 
    919933        PJ_TODO(RETURN_A_PROPER_STATUS_CODE_HERE); 
     
    10671081    pjsip_transaction *tsx = e->body.tsx_state.tsx; 
    10681082    pjsip_dialog *dlg = pjsip_tsx_get_dlg(tsx); 
     1083    pj_status_t status; 
    10691084 
    10701085    PJ_ASSERT_ON_FAIL(tsx && dlg, return); 
    10711086     
    1072     if (tsx->method.id == PJSIP_INVITE_METHOD) { 
     1087    if (tsx == s->invite_tsx) { 
    10731088 
    10741089        switch (tsx->state) { 
     
    10931108                inv_set_state(s, PJSIP_INV_STATE_CONNECTING, e); 
    10941109 
     1110            } else if (tsx->status_code==401 || tsx->status_code==407) { 
     1111 
     1112                /* Handle authentication failure: 
     1113                 * Resend the request with Authorization header. 
     1114                 */ 
     1115                pjsip_tx_data *tdata; 
     1116 
     1117                status = pjsip_auth_clt_reinit_req(&s->dlg->auth_sess,  
     1118                                                   e->body.tsx_state.src.rdata, 
     1119                                                   tsx->last_tx, 
     1120                                                   &tdata); 
     1121 
     1122                if (status != PJ_SUCCESS) { 
     1123 
     1124                    /* Does not have proper credentials.  
     1125                     * End the session. 
     1126                     */ 
     1127                    inv_set_state(s, PJSIP_INV_STATE_DISCONNECTED, e); 
     1128 
     1129                } else { 
     1130 
     1131                    /* Restart session. */ 
     1132                    s->state = PJSIP_INV_STATE_NULL; 
     1133                    s->invite_tsx = NULL; 
     1134 
     1135                    /* Send the request. */ 
     1136                    status = pjsip_inv_send_msg(s, tdata, NULL ); 
     1137                } 
     1138 
    10951139            } else { 
     1140 
    10961141                inv_set_state(s, PJSIP_INV_STATE_DISCONNECTED, e); 
     1142 
    10971143            } 
    10981144            break; 
     
    11161162            } else  { 
    11171163                inv_set_state(s, PJSIP_INV_STATE_DISCONNECTED, e); 
    1118                 inv_set_state(s, PJSIP_INV_STATE_TERMINATED, e); 
    11191164            } 
    11201165            break; 
     
    11361181    PJ_ASSERT_ON_FAIL(tsx && dlg, return); 
    11371182 
    1138     if (tsx->method.id == PJSIP_INVITE_METHOD) { 
     1183    if (tsx == s->invite_tsx) { 
    11391184        switch (tsx->state) { 
    11401185        case PJSIP_TSX_STATE_PROCEEDING: 
     
    11511196            /* This happens on transport error */ 
    11521197            inv_set_state(s, PJSIP_INV_STATE_DISCONNECTED, e); 
    1153             inv_set_state(s, PJSIP_INV_STATE_TERMINATED, e); 
    11541198            break; 
    11551199        default: 
     
    11681212    PJ_ASSERT_ON_FAIL(tsx && dlg, return); 
    11691213 
    1170     if (tsx->method.id == PJSIP_INVITE_METHOD) { 
     1214    if (tsx == s->invite_tsx) { 
    11711215 
    11721216        switch (tsx->state) { 
     
    12071251            } else  { 
    12081252                inv_set_state(s, PJSIP_INV_STATE_DISCONNECTED, e); 
    1209                 inv_set_state(s, PJSIP_INV_STATE_TERMINATED, e); 
    12101253            } 
    12111254            break; 
     
    12441287        } 
    12451288 
     1289    } else if (tsx->method.id == PJSIP_INVITE_METHOD) { 
     1290 
     1291        /* Ignore previously failed INVITE transaction event 
     1292         * (e.g. when rejected with 401/407) 
     1293         */ 
     1294 
    12461295    } else { 
    12471296        pj_assert(!"Unexpected transaction type"); 
     
    12561305    PJ_ASSERT_ON_FAIL(tsx && dlg, return); 
    12571306 
    1258     if (tsx->method.id == PJSIP_INVITE_METHOD) { 
     1307    if (tsx == s->invite_tsx) { 
    12591308 
    12601309        switch (tsx->state) { 
     
    12701319            if (tsx->status_code/100 != 2) { 
    12711320                inv_set_state(s, PJSIP_INV_STATE_DISCONNECTED, e); 
    1272                 inv_set_state(s, PJSIP_INV_STATE_TERMINATED, e); 
    12731321            } 
    12741322            break; 
     
    12971345        inv_set_state(s, PJSIP_INV_STATE_DISCONNECTED, e); 
    12981346 
    1299     } else if (tsx->method.id == PJSIP_INVITE_METHOD) { 
     1347    } else if (tsx == s->invite_tsx) { 
    13001348         
    13011349        switch (tsx->state) { 
     
    13081356        } 
    13091357 
     1358    } else if (tsx->method.id == PJSIP_INVITE_METHOD) { 
     1359 
     1360        /* Re-INVITE */ 
    13101361 
    13111362    } else { 
  • pjproject/trunk/pjsip/src/pjsip-ua/sip_reg.c

    r65 r141  
    1717 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  
    1818 */ 
    19 #include <pjsip_mod_ua/sip_reg.h> 
     19#include <pjsip-ua/sip_regc.h> 
    2020#include <pjsip/sip_endpoint.h> 
    2121#include <pjsip/sip_parser.h> 
     
    2525#include <pjsip/sip_util.h> 
    2626#include <pjsip/sip_auth_msg.h> 
     27#include <pjsip/sip_errno.h> 
    2728#include <pj/pool.h> 
    2829#include <pj/string.h> 
    2930#include <pj/guid.h> 
    3031#include <pj/log.h> 
     32#include <pj/assert.h> 
     33 
    3134 
    3235#define REFRESH_TIMER           1 
     
    4245    pjsip_endpoint      *endpt; 
    4346    pj_bool_t            _delete_flag; 
    44     int                 pending_tsx; 
     47    int                  pending_tsx; 
    4548 
    4649    void                *token; 
    4750    pjsip_regc_cb       *cb; 
    4851 
    49     pj_str_t            str_srv_url; 
     52    pj_str_t             str_srv_url; 
    5053    pjsip_uri           *srv_url; 
    5154    pjsip_cid_hdr       *cid_hdr; 
     
    6063    pj_uint32_t          expires; 
    6164 
    62     /* Credentials. */ 
    63     int                  cred_count; 
    64     pjsip_cred_info     *cred_info; 
    65      
    6665    /* Authorization sessions. */ 
    67     pjsip_auth_session   auth_sess_list; 
     66    pjsip_auth_clt_sess  auth_sess; 
    6867 
    6968    /* Auto refresh registration. */ 
     
    7473 
    7574 
    76 PJ_DEF(pjsip_regc*) pjsip_regc_create( pjsip_endpoint *endpt, void *token, 
    77                                        pjsip_regc_cb *cb) 
     75PJ_DEF(pj_status_t) pjsip_regc_create( pjsip_endpoint *endpt, void *token, 
     76                                       pjsip_regc_cb *cb, 
     77                                       pjsip_regc **p_regc) 
    7878{ 
    7979    pj_pool_t *pool; 
    8080    pjsip_regc *regc; 
    81  
    82     if (cb == NULL) 
    83         return NULL; 
     81    pj_status_t status; 
     82 
     83    /* Verify arguments. */ 
     84    PJ_ASSERT_RETURN(endpt && cb && p_regc, PJ_EINVAL); 
    8485 
    8586    pool = pjsip_endpt_create_pool(endpt, "regc%p", 1024, 1024); 
    86     regc = pj_pool_calloc(pool, 1, sizeof(struct pjsip_regc)); 
     87    PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM); 
     88 
     89    regc = pj_pool_zalloc(pool, sizeof(struct pjsip_regc)); 
    8790 
    8891    regc->pool = pool; 
     
    9396    regc->expires = PJSIP_REGC_EXPIRATION_NOT_SPECIFIED; 
    9497 
    95     pj_list_init(&regc->auth_sess_list); 
    96  
    97     return regc; 
    98 } 
    99  
    100  
    101 PJ_DEF(void) pjsip_regc_destroy(pjsip_regc *regc) 
     98    status = pjsip_auth_clt_init(&regc->auth_sess, endpt, regc->pool, 0); 
     99    if (status != PJ_SUCCESS) 
     100        return status; 
     101 
     102    /* Done */ 
     103    *p_regc = regc; 
     104    return PJ_SUCCESS; 
     105} 
     106 
     107 
     108PJ_DEF(pj_status_t) pjsip_regc_destroy(pjsip_regc *regc) 
    102109{ 
    103110    if (regc->pending_tsx) { 
     
    105112        regc->cb = NULL; 
    106113    } else { 
    107         pjsip_endpt_destroy_pool(regc->endpt, regc->pool); 
    108     } 
     114        pjsip_endpt_release_pool(regc->endpt, regc->pool); 
     115    } 
     116 
     117    return PJ_SUCCESS; 
    109118} 
    110119 
     
    118127{ 
    119128    if (expires != regc->expires) { 
    120         regc->expires_hdr = pjsip_expires_hdr_create(regc->pool); 
    121         regc->expires_hdr->ivalue = expires; 
     129        regc->expires_hdr = pjsip_expires_hdr_create(regc->pool, expires); 
    122130    } else { 
    123131        regc->expires_hdr = NULL; 
     
    137145    for (i=0, s=regc->contact_buf; i<contact_cnt; ++i) { 
    138146        if ((s-regc->contact_buf) + contact[i].slen + 2 > PJSIP_REGC_CONTACT_BUF_SIZE) { 
    139             return -1; 
     147            return PJSIP_EURITOOLONG; 
    140148        } 
    141149        pj_memcpy(s, contact[i].ptr, contact[i].slen); 
     
    149157 
    150158    /* Set "Contact" header. */ 
    151     regc->contact_hdr = pjsip_generic_string_hdr_create( regc->pool, &contact_STR); 
     159    regc->contact_hdr = pjsip_generic_string_hdr_create(regc->pool,  
     160                                                        &contact_STR, 
     161                                                        NULL); 
    152162    regc->contact_hdr->hvalue.ptr = regc->contact_buf; 
    153163    regc->contact_hdr->hvalue.slen = (s - regc->contact_buf); 
    154164 
    155     return 0; 
     165    return PJ_SUCCESS; 
    156166} 
    157167 
     
    166176{ 
    167177    pj_str_t tmp; 
     178    pj_status_t status; 
     179 
     180    PJ_ASSERT_RETURN(regc && srv_url && from_url && to_url &&  
     181                     contact_cnt && contact && expires, PJ_EINVAL); 
    168182 
    169183    /* Copy server URL. */ 
     
    174188    regc->srv_url = pjsip_parse_uri( regc->pool, tmp.ptr, tmp.slen, 0); 
    175189    if (regc->srv_url == NULL) { 
    176         return -1; 
     190        return PJSIP_EINVALIDURI; 
    177191    } 
    178192 
     
    183197                                          PJSIP_PARSE_URI_AS_NAMEADDR); 
    184198    if (!regc->from_hdr->uri) { 
    185         PJ_LOG(4,(THIS_FILE, "regc: invalid source URI %.*s", from_url->slen, from_url->ptr)); 
    186         return -1; 
     199        PJ_LOG(4,(THIS_FILE, "regc: invalid source URI %.*s",  
     200                  from_url->slen, from_url->ptr)); 
     201        return PJSIP_EINVALIDURI; 
    187202    } 
    188203 
     
    194209    if (!regc->to_hdr->uri) { 
    195210        PJ_LOG(4,(THIS_FILE, "regc: invalid target URI %.*s", to_url->slen, to_url->ptr)); 
    196         return -1; 
     211        return PJSIP_EINVALIDURI; 
    197212    } 
    198213 
    199214 
    200215    /* Set "Contact" header. */ 
    201     if (set_contact( regc, contact_cnt, contact) != 0) 
    202         return -1; 
     216    status = set_contact( regc, contact_cnt, contact); 
     217    if (status != PJ_SUCCESS) 
     218        return status; 
    203219 
    204220    /* Set "Expires" header, if required. */ 
     
    219235 
    220236    /* Create "Expires" header used in unregistration. */ 
    221     regc->unreg_expires_hdr = pjsip_expires_hdr_create( regc->pool); 
    222     regc->unreg_expires_hdr->ivalue = 0; 
     237    regc->unreg_expires_hdr = pjsip_expires_hdr_create( regc->pool, 0); 
    223238 
    224239    /* Done. */ 
    225     return 0; 
     240    return PJ_SUCCESS; 
    226241} 
    227242 
     
    230245                                                const pjsip_cred_info cred[] ) 
    231246{ 
    232     if (count > 0) { 
    233         regc->cred_info = pj_pool_alloc(regc->pool, count * sizeof(pjsip_cred_info)); 
    234         pj_memcpy(regc->cred_info, cred, count * sizeof(pjsip_cred_info)); 
    235     } 
    236     regc->cred_count = count; 
    237     return 0; 
    238 } 
    239  
    240 static pjsip_tx_data *create_request(pjsip_regc *regc) 
    241 { 
     247    PJ_ASSERT_RETURN(regc && count && cred, PJ_EINVAL); 
     248    return pjsip_auth_clt_set_credentials(&regc->auth_sess, count, cred); 
     249} 
     250 
     251static pj_status_t create_request(pjsip_regc *regc,  
     252                                  pjsip_tx_data **p_tdata) 
     253{ 
     254    pj_status_t status; 
    242255    pjsip_tx_data *tdata; 
     256 
     257    PJ_ASSERT_RETURN(regc && p_tdata, PJ_EINVAL); 
     258 
     259    /* Create the request. */ 
     260    status = pjsip_endpt_create_request_from_hdr( regc->endpt,  
     261                                                  &pjsip_register_method, 
     262                                                  regc->srv_url, 
     263                                                  regc->from_hdr, 
     264                                                  regc->to_hdr, 
     265                                                  NULL, 
     266                                                  regc->cid_hdr, 
     267                                                  regc->cseq_hdr->cseq, 
     268                                                  NULL, 
     269                                                  &tdata); 
     270    if (status != PJ_SUCCESS) 
     271        return status; 
     272 
     273    /* Add cached authorization headers. */ 
     274    pjsip_auth_clt_init_req( &regc->auth_sess, tdata ); 
     275 
     276    /* Done. */ 
     277    *p_tdata = tdata; 
     278    return PJ_SUCCESS; 
     279} 
     280 
     281 
     282PJ_DEF(pj_status_t) pjsip_regc_register(pjsip_regc *regc, pj_bool_t autoreg, 
     283                                        pjsip_tx_data **p_tdata) 
     284{ 
    243285    pjsip_msg *msg; 
    244  
    245     /* Create transmit data. */ 
    246     tdata = pjsip_endpt_create_tdata(regc->endpt); 
    247     if (!tdata) { 
    248         return NULL; 
    249     } 
    250  
    251     /* Create request message. */ 
    252     msg = pjsip_msg_create(tdata->pool, PJSIP_REQUEST_MSG); 
    253     tdata->msg = msg; 
    254  
    255     /* Initialize request line. */ 
    256     pjsip_method_set(&msg->line.req.method, PJSIP_REGISTER_METHOD); 
    257     msg->line.req.uri = regc->srv_url; 
    258  
    259     /* Add headers. */ 
    260     pjsip_msg_add_hdr(msg, (pjsip_hdr*) regc->from_hdr); 
    261     pjsip_msg_add_hdr(msg, (pjsip_hdr*) regc->to_hdr); 
    262     pjsip_msg_add_hdr(msg, (pjsip_hdr*) regc->cid_hdr); 
    263     pjsip_msg_add_hdr(msg, (pjsip_hdr*) regc->cseq_hdr); 
    264      
    265     /* Add cached authorization headers. */ 
    266     pjsip_auth_init_req( regc->pool, tdata, &regc->auth_sess_list, 
    267                          regc->cred_count, regc->cred_info ); 
    268  
    269     /* Add reference counter to transmit data. */ 
    270     pjsip_tx_data_add_ref(tdata); 
    271  
    272     return tdata; 
    273 } 
    274  
    275  
    276 PJ_DEF(pjsip_tx_data*) pjsip_regc_register(pjsip_regc *regc, pj_bool_t autoreg) 
    277 { 
    278     pjsip_msg *msg; 
     286    pj_status_t status; 
    279287    pjsip_tx_data *tdata; 
    280288 
    281     tdata = create_request(regc); 
    282     if (!tdata) 
    283         return NULL; 
    284  
     289    status = create_request(regc, &tdata); 
     290    if (status != PJ_SUCCESS) 
     291        return status; 
     292 
     293    /* Add Contact header. */ 
    285294    msg = tdata->msg; 
    286295    pjsip_msg_add_hdr(msg, (pjsip_hdr*) regc->contact_hdr); 
     
    295304    regc->auto_reg = autoreg; 
    296305 
    297     return tdata; 
    298 } 
    299  
    300  
    301 PJ_DEF(pjsip_tx_data*) pjsip_regc_unregister(pjsip_regc *regc) 
     306    /* Done */ 
     307    *p_tdata = tdata; 
     308    return PJ_SUCCESS; 
     309} 
     310 
     311 
     312PJ_DEF(pj_status_t) pjsip_regc_unregister(pjsip_regc *regc, 
     313                                          pjsip_tx_data **p_tdata) 
    302314{ 
    303315    pjsip_tx_data *tdata; 
    304316    pjsip_msg *msg; 
     317    pj_status_t status; 
    305318 
    306319    if (regc->timer.id != 0) { 
     
    309322    } 
    310323 
    311     tdata = create_request(regc); 
    312     if (!tdata) 
    313         return NULL; 
     324    status = create_request(regc, &tdata); 
     325    if (status != PJ_SUCCESS) 
     326        return status; 
    314327 
    315328    msg = tdata->msg; 
     
    317330    pjsip_msg_add_hdr( msg, (pjsip_hdr*)regc->unreg_expires_hdr); 
    318331 
    319     return tdata; 
     332    *p_tdata = tdata; 
     333    return PJ_SUCCESS; 
    320334} 
    321335 
     
    333347{ 
    334348    set_expires( regc, expires ); 
    335     return 0; 
     349    return PJ_SUCCESS; 
    336350} 
    337351 
     
    364378    pjsip_regc *regc = entry->user_data; 
    365379    pjsip_tx_data *tdata; 
     380    pj_status_t status; 
    366381     
    367     PJ_UNUSED_ARG(timer_heap) 
     382    PJ_UNUSED_ARG(timer_heap); 
    368383 
    369384    entry->id = 0; 
    370     tdata = pjsip_regc_register(regc, 1); 
    371     if (tdata) { 
     385    status = pjsip_regc_register(regc, 1, &tdata); 
     386    if (status == PJ_SUCCESS) { 
    372387        pjsip_regc_send(regc, tdata); 
    373388    } else { 
    374         pj_str_t reason = pj_str("Unable to create txdata"); 
     389        char errmsg[PJ_ERR_MSG_SIZE]; 
     390        pj_str_t reason = pj_strerror(status, errmsg, sizeof(errmsg)); 
    375391        call_callback(regc, -1, &reason, NULL, -1, 0, NULL); 
    376392    } 
     
    379395static void tsx_callback(void *token, pjsip_event *event) 
    380396{ 
     397    pj_status_t status; 
    381398    pjsip_regc *regc = token; 
    382     pjsip_transaction *tsx = event->obj.tsx; 
     399    pjsip_transaction *tsx = event->body.tsx_state.tsx; 
    383400     
    384401    /* If registration data has been deleted by user then remove registration  
     
    391408               tsx->status_code == PJSIP_SC_UNAUTHORIZED) 
    392409    { 
    393         pjsip_rx_data *rdata = event->src.rdata; 
     410        pjsip_rx_data *rdata = event->body.tsx_state.src.rdata; 
    394411        pjsip_tx_data *tdata; 
    395412 
    396         tdata = pjsip_auth_reinit_req( regc->endpt, 
    397                                        regc->pool, &regc->auth_sess_list, 
    398                                        regc->cred_count, regc->cred_info, 
    399                                        tsx->last_tx, event->src.rdata ); 
    400  
    401         if (tdata) { 
     413        status = pjsip_auth_clt_reinit_req( &regc->auth_sess, 
     414                                            rdata,  
     415                                            tsx->last_tx,   
     416                                            &tdata); 
     417 
     418        if (status == PJ_SUCCESS) { 
    402419            --regc->pending_tsx; 
    403420            pjsip_regc_send(regc, tdata); 
    404421            return; 
    405422        } else { 
    406             call_callback(regc, tsx->status_code, &rdata->msg->line.status.reason, 
     423            call_callback(regc, tsx->status_code, &rdata->msg_info.msg->line.status.reason, 
    407424                          rdata, -1, 0, NULL); 
    408425            --regc->pending_tsx; 
     
    420437            pjsip_expires_hdr *expires; 
    421438 
    422             rdata = event->src.rdata; 
    423             msg = rdata->msg; 
     439            rdata = event->body.tsx_state.src.rdata; 
     440            msg = rdata->msg_info.msg; 
    424441            hdr = pjsip_msg_find_hdr( msg, PJSIP_H_CONTACT, NULL); 
    425442            while (hdr) { 
     
    460477 
    461478        } else { 
    462             rdata = (event->src_type==PJSIP_EVENT_RX_MSG) ? event->src.rdata : NULL; 
     479            rdata = (event->body.tsx_state.type==PJSIP_EVENT_RX_MSG) ?  
     480                        event->body.tsx_state.src.rdata : NULL; 
    463481        } 
    464482 
     
    467485        if (expiration == 0xFFFF) expiration = -1; 
    468486        call_callback(regc, tsx->status_code,  
    469                       (rdata ? &rdata->msg->line.status.reason  
     487                      (rdata ? &rdata->msg_info.msg->line.status.reason  
    470488                        : pjsip_get_status_text(tsx->status_code)), 
    471489                      rdata, expiration,  
     
    481499} 
    482500 
    483 PJ_DEF(void) pjsip_regc_send(pjsip_regc *regc, pjsip_tx_data *tdata) 
    484 { 
    485     int status; 
     501PJ_DEF(pj_status_t) pjsip_regc_send(pjsip_regc *regc, pjsip_tx_data *tdata) 
     502{ 
     503    pj_status_t status; 
    486504 
    487505    /* Make sure we don't have pending transaction. */ 
     
    490508        call_callback(regc, -1, &reason, NULL, -1, 0, NULL); 
    491509        pjsip_tx_data_dec_ref( tdata ); 
    492         return; 
     510        return PJ_EINVALIDOP; 
    493511    } 
    494512 
     
    501519    /* Send. */ 
    502520    status = pjsip_endpt_send_request(regc->endpt, tdata, -1, regc, &tsx_callback); 
    503     if (status==0) 
     521    if (status==PJ_SUCCESS) 
    504522        ++regc->pending_tsx; 
    505523    else { 
    506         pj_str_t reason = pj_str("Unable to send request."); 
     524        char errmsg[PJ_ERR_MSG_SIZE]; 
     525        pj_str_t reason = pj_strerror(status, errmsg, sizeof(errmsg)); 
    507526        call_callback(regc, status, &reason, NULL, -1, 0, NULL); 
    508527    } 
    509 } 
    510  
    511  
     528 
     529    return status; 
     530} 
     531 
     532 
  • pjproject/trunk/pjsip/src/pjsip/sip_auth_client.c

    r127 r141  
    395395                                                    const pjsip_cred_info *c) 
    396396{ 
    397     PJ_ASSERT_RETURN(sess && cred_cnt && c, PJ_EINVAL); 
    398  
    399     sess->cred_info = pj_pool_alloc(sess->pool, cred_cnt * sizeof(*c)); 
    400     pj_memcpy(sess->cred_info, c, cred_cnt * sizeof(*c)); 
    401     sess->cred_cnt = cred_cnt; 
     397    PJ_ASSERT_RETURN(sess && c, PJ_EINVAL); 
     398 
     399    if (cred_cnt == 0) { 
     400        sess->cred_cnt = 0; 
     401    } else { 
     402        sess->cred_info = pj_pool_alloc(sess->pool, cred_cnt * sizeof(*c)); 
     403        pj_memcpy(sess->cred_info, c, cred_cnt * sizeof(*c)); 
     404        sess->cred_cnt = cred_cnt; 
     405    } 
    402406 
    403407    return PJ_SUCCESS; 
     
    522526            } 
    523527        } 
     528 
     529#       if defined(PJSIP_AUTH_AUTO_SEND_NEXT) && PJSIP_AUTH_AUTO_SEND_NEXT!=0 
     530            if (hdr != cached_auth->last_chal) { 
     531                cached_auth->last_chal = pjsip_hdr_clone(sess_pool, hdr); 
     532            } 
     533#       endif 
    524534    } 
    525535#   endif 
  • pjproject/trunk/pjsip/src/pjsip/sip_dialog.c

    r139 r141  
    698698    } 
    699699 
    700     /* Copy authorization headers. */ 
    701     status = pjsip_auth_clt_init_req( &dlg->auth_sess, tdata ); 
    702     if (status != PJ_SUCCESS) 
    703         return status; 
     700    /* Copy authorization headers, if request is not ACK or CANCEL. */ 
     701    if (method->id != PJSIP_ACK_METHOD && method->id != PJSIP_CANCEL_METHOD) { 
     702        status = pjsip_auth_clt_init_req( &dlg->auth_sess, tdata ); 
     703        if (status != PJ_SUCCESS) 
     704            return status; 
     705    } 
    704706 
    705707    /* Done. */ 
     
    11331135{ 
    11341136    unsigned i; 
     1137    int res_code; 
    11351138 
    11361139    /* Lock the dialog. */ 
     
    11401143    pj_assert(pjsip_rdata_get_dlg(rdata) == dlg); 
    11411144 
    1142     /* Update the remote tag, if none is specified yet. */ 
    1143     if (dlg->remote.info->tag.slen == 0 && rdata->msg_info.to->tag.slen != 0) { 
     1145    /* Update the remote tag if it is different. */ 
     1146    if (pj_strcmp(&dlg->remote.info->tag, &rdata->msg_info.to->tag) != 0) { 
    11441147 
    11451148        pj_strdup(dlg->pool, &dlg->remote.info->tag, &rdata->msg_info.to->tag); 
     
    11481151    } 
    11491152 
    1150     /* Update remote target when receiving certain response messages. */ 
    1151     if (pjsip_method_creates_dialog(&rdata->msg_info.cseq->method) && 
    1152         rdata->msg_info.msg->line.status.code/100 == 2) 
     1153    /* Keep the response's status code */ 
     1154    res_code = rdata->msg_info.msg->line.status.code; 
     1155 
     1156    /* When we receive response that establishes dialog, update the route 
     1157     * set and dialog target. 
     1158     */ 
     1159    if (!dlg->established &&  
     1160        pjsip_method_creates_dialog(&rdata->msg_info.cseq->method) && 
     1161        (res_code > 100 && res_code < 300) && 
     1162        rdata->msg_info.to->tag.slen) 
    11531163    { 
     1164        /* RFC 3271 Section 12.1.2: 
     1165         * The route set MUST be set to the list of URIs in the Record-Route 
     1166         * header field from the response, taken in reverse order and  
     1167         * preserving all URI parameters. If no Record-Route header field  
     1168         * is present in the response, the route set MUST be set to the  
     1169         * empty set. This route set, even if empty, overrides any pre-existing 
     1170         * route set for future requests in this dialog. 
     1171         */ 
     1172        pjsip_hdr *hdr, *end_hdr; 
    11541173        pjsip_contact_hdr *contact; 
    11551174 
     1175        pj_list_init(&dlg->route_set); 
     1176 
     1177        end_hdr = &rdata->msg_info.msg->hdr; 
     1178        for (hdr=rdata->msg_info.msg->hdr.prev; hdr!=end_hdr; hdr=hdr->prev) { 
     1179            if (hdr->type == PJSIP_H_RECORD_ROUTE) { 
     1180                pjsip_route_hdr *r; 
     1181                r = pjsip_hdr_clone(dlg->pool, hdr); 
     1182                pjsip_routing_hdr_set_route(r); 
     1183                pj_list_push_back(&dlg->route_set, r); 
     1184            } 
     1185        } 
     1186 
     1187        /* The remote target MUST be set to the URI from the Contact header  
     1188         * field of the response. 
     1189         */ 
    11561190        contact = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT,  
    11571191                                     NULL); 
     
    11601194            dlg->target = dlg->remote.contact->uri; 
    11611195        } 
    1162     } 
     1196 
     1197        dlg->established = 1; 
     1198    } 
     1199 
     1200    /* Update remote target (again) when receiving 2xx response messages 
     1201     * that's defined as target refresh.  
     1202     */ 
     1203    if (pjsip_method_creates_dialog(&rdata->msg_info.cseq->method) && 
     1204        res_code/100 == 2) 
     1205    { 
     1206        pjsip_contact_hdr *contact; 
     1207 
     1208        contact = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT,  
     1209                                     NULL); 
     1210        if (contact) { 
     1211            dlg->remote.contact = pjsip_hdr_clone(dlg->pool, contact); 
     1212            dlg->target = dlg->remote.contact->uri; 
     1213        } 
     1214    } 
     1215 
    11631216 
    11641217    /* Pass to dialog usages. */ 
  • pjproject/trunk/pjsip/src/pjsip/sip_endpoint.c

    r139 r141  
    104104pj_status_t pjsip_tel_uri_subsys_init(void); 
    105105 
     106/* Defined in sip_util_statefull.c */ 
     107extern pjsip_module mod_stateful_util; 
    106108 
    107109/* 
     
    490492    /* Initialize capability header list. */ 
    491493    pj_list_init(&endpt->cap_hdr); 
     494 
     495    /* Register mod_stateful_util module (sip_util_statefull.c) */ 
     496    status = pjsip_endpt_register_module(endpt, &mod_stateful_util); 
     497    if (status != PJ_SUCCESS) 
     498        goto on_error; 
    492499 
    493500    /* Done. */ 
  • pjproject/trunk/pjsip/src/pjsip/sip_transaction.c

    r139 r141  
    21962196 
    21972197    } else if (tsx->status_code >= 300 && tsx->status_code <= 699) { 
     2198 
     2199 
     2200#if 0 
     2201        /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ 
     2202        /* 
     2203         * This is the old code; it's broken for authentication. 
     2204         */ 
    21982205        pj_time_val timeout; 
    21992206        pj_status_t status; 
     
    22432250        tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED,  
    22442251                       PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata ); 
     2252 
     2253        /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ 
     2254#endif 
     2255 
     2256        /* New code, taken from 0.2.9.x branch */ 
     2257        pj_time_val timeout; 
     2258        pjsip_tx_data *ack_tdata = NULL; 
     2259 
     2260        /* Stop timer B. */ 
     2261        pjsip_endpt_cancel_timer( tsx->endpt, &tsx->timeout_timer ); 
     2262 
     2263        /* Generate ACK now (for INVITE) but send it later because 
     2264         * dialog need to use last_tx. 
     2265         */ 
     2266        if (tsx->method.id == PJSIP_INVITE_METHOD) { 
     2267            pj_status_t status; 
     2268 
     2269            status = pjsip_endpt_create_ack( tsx->endpt, tsx->last_tx,  
     2270                                             event->body.rx_msg.rdata, 
     2271                                             &ack_tdata); 
     2272            if (status != PJ_SUCCESS) 
     2273                return status; 
     2274        } 
     2275 
     2276        /* Inform TU. */ 
     2277        tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED,  
     2278                       PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata); 
     2279 
     2280        /* Generate and send ACK for INVITE. */ 
     2281        if (tsx->method.id == PJSIP_INVITE_METHOD) { 
     2282            pj_status_t status; 
     2283 
     2284            status = tsx_send_msg( tsx, ack_tdata); 
     2285 
     2286            if (ack_tdata != tsx->last_tx) { 
     2287                pjsip_tx_data_dec_ref(tsx->last_tx); 
     2288                tsx->last_tx = ack_tdata; 
     2289                pjsip_tx_data_add_ref(ack_tdata); 
     2290            } 
     2291 
     2292            if (status != PJ_SUCCESS) { 
     2293                return status; 
     2294            } 
     2295        } 
     2296 
     2297        /* Start Timer D with TD/T4 timer if unreliable transport is used. */ 
     2298        if (PJSIP_TRANSPORT_IS_RELIABLE(tsx->transport) == 0) { 
     2299            if (tsx->method.id == PJSIP_INVITE_METHOD) { 
     2300                timeout = td_timer_val; 
     2301            } else { 
     2302                timeout = t4_timer_val; 
     2303            } 
     2304        } else { 
     2305            timeout.sec = timeout.msec = 0; 
     2306        } 
     2307        pjsip_endpt_schedule_timer( tsx->endpt, &tsx->timeout_timer, &timeout); 
    22452308 
    22462309    } else { 
  • pjproject/trunk/pjsip/src/pjsip/sip_ua_layer.c

    r139 r141  
    618618     * Request will fork only for the initial INVITE request. 
    619619     */ 
    620     if (rdata->msg_info.cseq->method.id == PJSIP_INVITE_METHOD && 
    621         rdata->msg_info.cseq->cseq == dlg_set->dlg_list.next->local.first_cseq) 
    622     { 
     620 
     621    //This doesn't work when there is authentication challenge, since  
     622    //first_cseq evaluation will yield false. 
     623    //if (rdata->msg_info.cseq->method.id == PJSIP_INVITE_METHOD && 
     624    //  rdata->msg_info.cseq->cseq == dlg_set->dlg_list.next->local.first_cseq) 
     625 
     626    if (rdata->msg_info.cseq->method.id == PJSIP_INVITE_METHOD) { 
    623627        pj_str_t *to_tag = &rdata->msg_info.to->tag; 
    624628 
     
    627631 
    628632        dlg = dlg_set->dlg_list.next; 
     633 
     634        /* Forking handling is temporarily disabled. */ 
     635        PJ_TODO(UA_LAYER_HANDLE_FORKING); 
     636 
     637#if 0 
    629638        while (dlg != (pjsip_dialog*)&dlg_set->dlg_list) { 
    630639 
     
    670679            } 
    671680        } 
     681#endif 
    672682 
    673683        /* Done with the dialog set. */ 
  • pjproject/trunk/pjsip/src/pjsip/sip_util.c

    r139 r141  
    442442    const pjsip_cseq_hdr *cseq_hdr; 
    443443    const pjsip_hdr *hdr; 
     444    pjsip_hdr *via; 
    444445    pjsip_to_hdr *to; 
    445446    pj_status_t status; 
    446447 
    447     /* rdata must be a final response. */ 
     448    /* rdata must be a non-2xx final response. */ 
    448449    pj_assert(rdata->msg_info.msg->type==PJSIP_RESPONSE_MSG && 
    449450              rdata->msg_info.msg->line.status.code >= 300); 
     
    488489    pj_strdup(ack->pool, &to->tag, &rdata->msg_info.to->tag); 
    489490 
     491 
     492    /* Clear Via headers in the new request. */ 
     493    while ((via=pjsip_msg_find_hdr(ack->msg, PJSIP_H_VIA, NULL)) != NULL) 
     494        pj_list_erase(via); 
     495 
    490496    /* Must contain single Via, just as the original INVITE. */ 
    491497    hdr = pjsip_msg_find_hdr( invite_msg, PJSIP_H_VIA, NULL); 
    492     if (hdr) { 
    493         pjsip_msg_insert_first_hdr( ack->msg, pjsip_hdr_clone(ack->pool,hdr) ); 
    494     } 
     498    pjsip_msg_insert_first_hdr( ack->msg, pjsip_hdr_clone(ack->pool,hdr) ); 
    495499 
    496500    /* If the original INVITE has Route headers, those header fields MUST  
  • pjproject/trunk/pjsip/src/pjsip/sip_util_statefull.c

    r107 r141  
    2222#include <pjsip/sip_transaction.h> 
    2323#include <pjsip/sip_event.h> 
     24#include <pjsip/sip_errno.h> 
    2425#include <pj/pool.h> 
     26#include <pj/assert.h> 
    2527 
    26 struct aux_tsx_data 
     28struct tsx_data 
    2729{ 
    2830    void *token; 
    29     void (*cb)(void*,pjsip_event*); 
     31    void (*cb)(void*, pjsip_event*); 
    3032}; 
    3133 
    32 static void aux_tsx_handler( pjsip_transaction *tsx, pjsip_event *event ); 
     34static void mod_util_on_tsx_state(pjsip_transaction*, pjsip_event*); 
    3335 
    34 pjsip_module aux_tsx_module =  
     36/* This module will be registered in pjsip_endpt.c */ 
     37 
     38pjsip_module mod_stateful_util =  
    3539{ 
    36     NULL, NULL,                         /* prev and next        */ 
    37     { "Aux-Tsx", 7},                    /* Name.                */ 
    38     -1,                                 /* Id           */ 
    39     PJSIP_MOD_PRIORITY_APPLICATION-1,   /* Priority             */ 
    40     NULL,                               /* User data.   */ 
    41     0,                                  /* Number of methods supported (=0). */ 
    42     { 0 },                              /* Array of methods (none) */ 
    43     NULL,                               /* load()               */ 
    44     NULL,                               /* start()              */ 
    45     NULL,                               /* stop()               */ 
    46     NULL,                               /* unload()             */ 
    47     NULL,                               /* on_rx_request()      */ 
    48     NULL,                               /* on_rx_response()     */ 
    49     &aux_tsx_handler,                   /* tsx_handler()        */ 
     40    NULL, NULL,                     /* prev, next.                      */ 
     41    { "mod-stateful-util", 17 },    /* Name.                            */ 
     42    -1,                             /* Id                               */ 
     43    PJSIP_MOD_PRIORITY_APPLICATION, /* Priority                         */ 
     44    NULL,                           /* User data.                       */ 
     45    NULL,                           /* load()                           */ 
     46    NULL,                           /* start()                          */ 
     47    NULL,                           /* stop()                           */ 
     48    NULL,                           /* unload()                         */ 
     49    NULL,                           /* on_rx_request()                  */ 
     50    NULL,                           /* on_rx_response()                 */ 
     51    NULL,                           /* on_tx_request.                   */ 
     52    NULL,                           /* on_tx_response()                 */ 
     53    &mod_util_on_tsx_state,         /* on_tsx_state()                   */ 
    5054}; 
    5155 
    52 static void aux_tsx_handler( pjsip_transaction *tsx, pjsip_event *event ) 
     56static void mod_util_on_tsx_state(pjsip_transaction *tsx, pjsip_event *event) 
    5357{ 
    54     struct aux_tsx_data *tsx_data; 
     58    struct tsx_data *tsx_data; 
    5559 
    5660    if (event->type != PJSIP_EVENT_TSX_STATE) 
    5761        return; 
    58     if (tsx->module_data[aux_tsx_module.id] == NULL) 
     62 
     63    tsx_data = tsx->mod_data[mod_stateful_util.id]; 
     64    if (tsx_data == NULL) 
    5965        return; 
     66 
    6067    if (tsx->status_code < 200) 
    6168        return; 
     
    6471     * by clearing the transaction's module_data. 
    6572     */ 
    66     tsx_data = tsx->module_data[aux_tsx_module.id]; 
    67     tsx->module_data[aux_tsx_module.id] = NULL; 
     73    tsx->mod_data[mod_stateful_util.id] = NULL; 
    6874 
    6975    if (tsx_data->cb) { 
     
    8086{ 
    8187    pjsip_transaction *tsx; 
    82     struct aux_tsx_data *tsx_data; 
     88    struct tsx_data *tsx_data; 
    8389    pj_status_t status; 
    8490 
    85     status = pjsip_endpt_create_tsx(endpt, &tsx); 
    86     if (!tsx) { 
     91    PJ_ASSERT_RETURN(endpt && tdata && (timeout==-1 || timeout>0), PJ_EINVAL); 
     92 
     93    status = pjsip_tsx_create_uac(&mod_stateful_util, tdata, &tsx); 
     94    if (status != PJ_SUCCESS) { 
    8795        pjsip_tx_data_dec_ref(tdata); 
    88         return -1; 
     96        return status; 
    8997    } 
    9098 
    91     tsx_data = pj_pool_alloc(tsx->pool, sizeof(struct aux_tsx_data)); 
     99    tsx_data = pj_pool_alloc(tsx->pool, sizeof(struct tsx_data)); 
    92100    tsx_data->token = token; 
    93101    tsx_data->cb = cb; 
    94     tsx->module_data[aux_tsx_module.id] = tsx_data; 
     102    tsx->mod_data[mod_stateful_util.id] = tsx_data; 
    95103 
    96     if (pjsip_tsx_init_uac(tsx, tdata) != 0) { 
    97         pjsip_endpt_destroy_tsx(endpt, tsx); 
    98         pjsip_tx_data_dec_ref(tdata); 
    99         return -1; 
    100     } 
     104    PJ_TODO(IMPLEMENT_TIMEOUT_FOR_SEND_REQUEST); 
    101105 
    102     pjsip_endpt_register_tsx(endpt, tsx); 
    103     pjsip_tx_data_invalidate_msg(tdata); 
    104     pjsip_tsx_on_tx_msg(tsx, tdata); 
    105     pjsip_tx_data_dec_ref(tdata); 
    106     return 0; 
     106    return pjsip_tsx_send_msg(tsx, NULL); 
    107107} 
    108108 
  • pjproject/trunk/pjsip/src/pjsua/main.c

    r139 r141  
    1818 */ 
    1919#include "pjsua.h" 
     20#include "getopt.h" 
     21 
    2022 
    2123/* For debugging, disable threading. */ 
     
    3335 * Notify UI when invite state has changed. 
    3436 */ 
    35 void ui_inv_on_state_changed(pjsip_inv_session *inv, pjsip_event *e) 
     37void pjsua_ui_inv_on_state_changed(pjsip_inv_session *inv, pjsip_event *e) 
    3638{ 
    3739    const char *state_names[] = 
     
    5153    PJ_LOG(3,(THIS_FILE, "INVITE session state changed to %s", state_names[inv->state])); 
    5254 
    53     if (inv->state == PJSIP_INV_STATE_DISCONNECTED || 
    54         inv->state == PJSIP_INV_STATE_TERMINATED) 
    55     { 
     55    if (inv->state == PJSIP_INV_STATE_DISCONNECTED) { 
    5656        if (inv == inv_session) 
    5757            inv_session = NULL; 
     
    104104            } 
    105105 
    106 #if 0 
     106#if 1 
    107107            printf("Enter URL to call: "); 
    108108            fgets(buf, sizeof(buf), stdin); 
     
    122122 
    123123            pjsua_invite(buf, &inv); 
     124 
     125#else 
     126 
     127            pjsua_invite("sip:localhost:5061", &inv); 
    124128#endif 
    125  
    126             pjsua_invite("sip:localhost:5061", &inv); 
    127129            break; 
    128130 
     
    163165} 
    164166 
     167 
     168/***************************************************************************** 
     169 * This is a very simple PJSIP module, whose sole purpose is to display 
     170 * incoming and outgoing messages to log. This module will have priority 
     171 * higher than transport layer, which means: 
     172 * 
     173 *  - incoming messages will come to this module first before reaching 
     174 *    transaction layer. 
     175 * 
     176 *  - outgoing messages will come to this module last, after the message 
     177 *    has been 'printed' to contiguous buffer by transport layer and 
     178 *    appropriate transport instance has been decided for this message. 
     179 * 
     180 */ 
     181 
     182/* Notification on incoming messages */ 
    165183static pj_bool_t console_on_rx_msg(pjsip_rx_data *rdata) 
    166184{ 
     
    174192                         rdata->msg_info.msg_buf)); 
    175193     
    176     /* Must return false for logger! */ 
     194    /* Always return false, otherwise messages will not get processed! */ 
    177195    return PJ_FALSE; 
    178196} 
    179197 
     198/* Notification on outgoing messages */ 
    180199static pj_status_t console_on_tx_msg(pjsip_tx_data *tdata) 
    181200{ 
     201     
     202    /* Important note: 
     203     *  tp_info field is only valid after outgoing messages has passed 
     204     *  transport layer. So don't try to access tp_info when the module 
     205     *  has lower priority than transport layer. 
     206     */ 
     207 
    182208    PJ_LOG(4,(THIS_FILE, "TX %d bytes %s to %s:%d:\n" 
    183209                         "%s\n" 
     
    189215                         tdata->buf.start)); 
    190216 
     217    /* Always return success, otherwise message will not get sent! */ 
    191218    return PJ_SUCCESS; 
    192219} 
    193220 
     221/* The module instance. */ 
    194222static pjsip_module console_msg_logger =  
    195223{ 
     
    212240 
    213241 
    214 int main() 
     242 
     243/***************************************************************************** 
     244 * Console application custom logging: 
     245 */ 
     246 
     247 
     248static FILE *log_file; 
     249 
     250 
     251static void app_log_writer(int level, const char *buffer, int len) 
     252{ 
     253    /* Write to both stdout and file. */ 
     254 
     255    if (level <= pjsua.app_log_level) 
     256        pj_log_write(level, buffer, len); 
     257 
     258    if (log_file) { 
     259        fwrite(buffer, len, 1, log_file); 
     260        fflush(log_file); 
     261    } 
     262} 
     263 
     264 
     265void app_logging_init(void) 
     266{ 
     267    /* Redirect log function to ours */ 
     268 
     269    pj_log_set_log_func( &app_log_writer ); 
     270 
     271    /* If output log file is desired, create the file: */ 
     272 
     273    if (pjsua.log_filename) 
     274        log_file = fopen(pjsua.log_filename, "wt"); 
     275} 
     276 
     277 
     278void app_logging_shutdown(void) 
     279{ 
     280    /* Close logging file, if any: */ 
     281 
     282    if (log_file) { 
     283        fclose(log_file); 
     284        log_file = NULL; 
     285    } 
     286} 
     287 
     288/***************************************************************************** 
     289 * Command line argument processing: 
     290 */ 
     291 
     292 
     293/* Show usage */ 
     294static void usage(void) 
     295{ 
     296    puts("Usage:"); 
     297    puts("  pjsua [options] [sip-url]"); 
     298    puts(""); 
     299    puts("  [sip-url]   Default URL to invite."); 
     300    puts(""); 
     301    puts("General options:"); 
     302    puts("  --config-file=file  Read the config/arguments from file."); 
     303    puts("  --log-file=fname    Log to filename (default stderr)"); 
     304    puts("  --log-level=N       Set log max level to N (0(none) to 6(trace))"); 
     305    puts("  --app-log-level=N   Set log max level for stdout display to N"); 
     306    puts("  --help              Display this help screen"); 
     307    puts("  --version           Display version info"); 
     308    puts(""); 
     309    puts("Media options:"); 
     310    puts("  --null-audio        Use NULL audio device"); 
     311    puts(""); 
     312    puts("User Agent options:"); 
     313    puts("  --auto-answer=sec   Auto-answer all incoming calls after sec seconds."); 
     314    puts("  --auto-hangup=sec   Auto-hangup all calls after sec seconds."); 
     315    puts(""); 
     316    puts("SIP options:"); 
     317    puts("  --local-port=port   Set TCP/UDP port"); 
     318    puts("  --id=url            Set the URL of local ID (used in From header)"); 
     319    puts("  --contact=url       Override the Contact information"); 
     320    puts("  --proxy=url         Set the URL of proxy server"); 
     321    puts("  --outbound=url      Set the URL of outbound proxy server"); 
     322    puts("  --registrar=url     Set the URL of registrar server"); 
     323    puts("  --reg-timeout=secs  Set registration interval to secs (default 3600)"); 
     324    puts(""); 
     325    puts("Authentication options:"); 
     326    puts("  --realm=string      Set realm"); 
     327    puts("  --username=string   Set authentication username"); 
     328    puts("  --password=string   Set authentication password"); 
     329    puts(""); 
     330    puts("STUN options (all must be specified):"); 
     331    puts("  --use-stun1=host[:port]"); 
     332    puts("  --use-stun2=host[:port]  Use STUN and set host name and port of STUN servers"); 
     333    puts(""); 
     334    puts("SIMPLE options (may be specified more than once):"); 
     335    puts("  --add-buddy url     Add the specified URL to the buddy list."); 
     336    puts("  --offer-x-ms-msg    Offer \"x-ms-message\" in outgoing INVITE"); 
     337    puts("  --no-presence       Do not subscribe presence of buddies"); 
     338    puts(""); 
     339    fflush(stdout); 
     340} 
     341 
     342 
     343/* 
     344 * Verify that valid SIP url is given. 
     345 */ 
     346static pj_status_t verify_sip_url(char *url) 
     347{ 
     348    pjsip_uri *p; 
     349    pj_pool_t *pool; 
     350    int len = (url ? strlen(url) : 0); 
     351 
     352    if (!len) return -1; 
     353 
     354    pool = pj_pool_create(&pjsua.cp.factory, "check%p", 1024, 0, NULL); 
     355    if (!pool) return -1; 
     356 
     357    p = pjsip_parse_uri(pool, url, len, 0); 
     358    if (!p || pj_stricmp2(pjsip_uri_get_scheme(p), "sip") != 0) 
     359        p = NULL; 
     360 
     361    pj_pool_release(pool); 
     362    return p ? 0 : -1; 
     363} 
     364 
     365 
     366/* 
     367 * Read command arguments from config file. 
     368 */ 
     369static int read_config_file(pj_pool_t *pool, const char *filename,  
     370                            int *app_argc, char ***app_argv) 
     371{ 
     372    int i; 
     373    FILE *fhnd; 
     374    char line[200]; 
     375    int argc = 0; 
     376    char **argv; 
     377    enum { MAX_ARGS = 64 }; 
     378 
     379    /* Allocate MAX_ARGS+1 (argv needs to be terminated with NULL argument) */ 
     380    argv = pj_pool_calloc(pool, MAX_ARGS+1, sizeof(char*)); 
     381    argv[argc++] = *app_argv[0]; 
     382 
     383    /* Open config file. */ 
     384    fhnd = fopen(filename, "rt"); 
     385    if (!fhnd) { 
     386        printf("Unable to open config file %s\n", filename); 
     387        return -1; 
     388    } 
     389 
     390    /* Scan tokens in the file. */ 
     391    while (argc < MAX_ARGS && !feof(fhnd)) { 
     392        char *token, *p = line; 
     393 
     394        if (fgets(line, sizeof(line), fhnd) == NULL) break; 
     395 
     396        for (token = strtok(p, " \t\r\n"); argc < MAX_ARGS;  
     397             token = strtok(NULL, " \t\r\n")) 
     398        { 
     399            int token_len; 
     400             
     401            if (!token) break; 
     402            if (*token == '#') break; 
     403 
     404            token_len = strlen(token); 
     405            if (!token_len) 
     406                continue; 
     407            argv[argc] = pj_pool_alloc(pool, token_len+1); 
     408            pj_memcpy(argv[argc], token, token_len+1); 
     409            ++argc; 
     410        } 
     411    } 
     412 
     413    /* Copy arguments from command line */ 
     414    for (i=1; i<*app_argc && argc < MAX_ARGS; ++i) 
     415        argv[argc++] = (*app_argv)[i]; 
     416 
     417    if (argc == MAX_ARGS && (i!=*app_argc || !feof(fhnd))) { 
     418        printf("Too many arguments specified in cmd line/config file\n"); 
     419        fclose(fhnd); 
     420        return -1; 
     421    } 
     422 
     423    fclose(fhnd); 
     424 
     425    /* Assign the new command line back to the original command line. */ 
     426    *app_argc = argc; 
     427    *app_argv = argv; 
     428    return 0; 
     429 
     430} 
     431 
     432 
     433/* Parse arguments. */ 
     434static pj_status_t parse_args(int argc, char *argv[]) 
     435{ 
     436    int c; 
     437    int option_index; 
     438    enum { OPT_CONFIG_FILE, OPT_LOG_FILE, OPT_LOG_LEVEL, OPT_APP_LOG_LEVEL,  
     439           OPT_HELP, OPT_VERSION, OPT_NULL_AUDIO, 
     440           OPT_LOCAL_PORT, OPT_PROXY, OPT_OUTBOUND_PROXY, OPT_REGISTRAR, 
     441           OPT_REG_TIMEOUT, OPT_ID, OPT_CONTACT,  
     442           OPT_REALM, OPT_USERNAME, OPT_PASSWORD, 
     443           OPT_USE_STUN1, OPT_USE_STUN2,  
     444           OPT_ADD_BUDDY, OPT_OFFER_X_MS_MSG, OPT_NO_PRESENCE, 
     445           OPT_AUTO_ANSWER, OPT_AUTO_HANGUP}; 
     446    struct option long_options[] = { 
     447        { "config-file",1, 0, OPT_CONFIG_FILE}, 
     448        { "log-file",   1, 0, OPT_LOG_FILE}, 
     449        { "log-level",  1, 0, OPT_LOG_LEVEL}, 
     450        { "app-log-level",1,0,OPT_APP_LOG_LEVEL}, 
     451        { "help",       0, 0, OPT_HELP}, 
     452        { "version",    0, 0, OPT_VERSION}, 
     453        { "null-audio", 0, 0, OPT_NULL_AUDIO}, 
     454        { "local-port", 1, 0, OPT_LOCAL_PORT}, 
     455        { "proxy",      1, 0, OPT_PROXY}, 
     456        { "outbound",   1, 0, OPT_OUTBOUND_PROXY}, 
     457        { "registrar",  1, 0, OPT_REGISTRAR}, 
     458        { "reg-timeout",1, 0, OPT_REG_TIMEOUT}, 
     459        { "id",         1, 0, OPT_ID}, 
     460        { "contact",    1, 0, OPT_CONTACT}, 
     461        { "realm",      1, 0, OPT_REALM}, 
     462        { "username",   1, 0, OPT_USERNAME}, 
     463        { "password",   1, 0, OPT_PASSWORD}, 
     464        { "use-stun1",  1, 0, OPT_USE_STUN1}, 
     465        { "use-stun2",  1, 0, OPT_USE_STUN2}, 
     466        { "add-buddy",  1, 0, OPT_ADD_BUDDY}, 
     467        { "offer-x-ms-msg",0,0,OPT_OFFER_X_MS_MSG}, 
     468        { "no-presence", 0, 0, OPT_NO_PRESENCE}, 
     469        { "auto-answer",1, 0, OPT_AUTO_ANSWER}, 
     470        { "auto-hangup",1, 0, OPT_AUTO_HANGUP}, 
     471        { NULL, 0, 0, 0} 
     472    }; 
     473    pj_status_t status; 
     474    char *config_file = NULL; 
     475 
     476    /* Run getopt once to see if user specifies config file to read. */ 
     477    while ((c=getopt_long(argc, argv, "", long_options, &option_index)) != -1) { 
     478        switch (c) { 
     479        case OPT_CONFIG_FILE: 
     480            config_file = optarg; 
     481            break; 
     482        } 
     483        if (config_file) 
     484            break; 
     485    } 
     486 
     487    if (config_file) { 
     488        status = read_config_file(pjsua.pool, config_file, &argc, &argv); 
     489        if (status != 0) 
     490            return status; 
     491    } 
     492 
     493 
     494    /* Reinitialize and re-run getopt again, possibly with new arguments 
     495     * read from config file. 
     496     */ 
     497    optind = 0; 
     498    while ((c=getopt_long(argc, argv, "", long_options, &option_index)) != -1) { 
     499        char *p; 
     500        pj_str_t tmp; 
     501        long lval; 
     502 
     503        switch (c) { 
     504 
     505        case OPT_LOG_FILE: 
     506            pjsua.log_filename = optarg; 
     507            break; 
     508 
     509        case OPT_LOG_LEVEL: 
     510            c = pj_strtoul(pj_cstr(&tmp, optarg)); 
     511            if (c < 0 || c > 6) { 
     512                printf("Error: expecting integer value 0-6 for --log-level\n"); 
     513                return PJ_EINVAL; 
     514            } 
     515            pj_log_set_level( c ); 
     516            break; 
     517 
     518        case OPT_APP_LOG_LEVEL: 
     519            pjsua.app_log_level = pj_strtoul(pj_cstr(&tmp, optarg)); 
     520            if (pjsua.app_log_level < 0 || pjsua.app_log_level > 6) { 
     521                printf("Error: expecting integer value 0-6 for --app-log-level\n"); 
     522                return PJ_EINVAL; 
     523            } 
     524            break; 
     525 
     526        case OPT_HELP: 
     527            usage(); 
     528            return PJ_EINVAL; 
     529 
     530        case OPT_VERSION:   /* version */ 
     531            pj_dump_config(); 
     532            return PJ_EINVAL; 
     533 
     534        case OPT_NULL_AUDIO: 
     535            pjsua.null_audio = 1; 
     536            break; 
     537 
     538        case OPT_LOCAL_PORT:   /* local-port */ 
     539            lval = pj_strtoul(pj_cstr(&tmp, optarg)); 
     540            if (lval < 1 || lval > 65535) { 
     541                printf("Error: expecting integer value for --local-port\n"); 
     542                return PJ_EINVAL; 
     543            } 
     544            pjsua.sip_port = (pj_uint16_t)lval; 
     545            break; 
     546 
     547        case OPT_PROXY:   /* proxy */ 
     548            if (verify_sip_url(optarg) != 0) { 
     549                printf("Error: invalid SIP URL '%s' in proxy argument\n", optarg); 
     550                return PJ_EINVAL; 
     551            } 
     552            pjsua.proxy = pj_str(optarg); 
     553            break; 
     554 
     555        case OPT_OUTBOUND_PROXY:   /* outbound proxy */ 
     556            if (verify_sip_url(optarg) != 0) { 
     557                printf("Error: invalid SIP URL '%s' in outbound proxy argument\n", optarg); 
     558                return PJ_EINVAL; 
     559            } 
     560            pjsua.outbound_proxy = pj_str(optarg); 
     561            break; 
     562 
     563        case OPT_REGISTRAR:   /* registrar */ 
     564            if (verify_sip_url(optarg) != 0) { 
     565                printf("Error: invalid SIP URL '%s' in registrar argument\n", optarg); 
     566                return PJ_EINVAL; 
     567            } 
     568            pjsua.registrar_uri = pj_str(optarg); 
     569            break; 
     570 
     571        case OPT_REG_TIMEOUT:   /* reg-timeout */ 
     572            pjsua.reg_timeout = pj_strtoul(pj_cstr(&tmp,optarg)); 
     573            if (pjsua.reg_timeout < 1 || pjsua.reg_timeout > 3600) { 
     574                printf("Error: invalid value for --reg-timeout (expecting 1-3600)\n"); 
     575                return PJ_EINVAL; 
     576            } 
     577            break; 
     578 
     579        case OPT_ID:   /* id */ 
     580            if (verify_sip_url(optarg) != 0) { 
     581                printf("Error: invalid SIP URL '%s' in local id argument\n", optarg); 
     582                return PJ_EINVAL; 
     583            } 
     584            pjsua.local_uri = pj_str(optarg); 
     585            break; 
     586 
     587        case OPT_CONTACT:   /* contact */ 
     588            if (verify_sip_url(optarg) != 0) { 
     589                printf("Error: invalid SIP URL '%s' in contact argument\n", optarg); 
     590                return PJ_EINVAL; 
     591            } 
     592            pjsua.contact_uri = pj_str(optarg); 
     593            break; 
     594 
     595        case OPT_USERNAME:   /* Default authentication user */ 
     596            if (!pjsua.cred_count) pjsua.cred_count = 1; 
     597            pjsua.cred_info[0].username = pj_str(optarg); 
     598            break; 
     599 
     600        case OPT_REALM:     /* Default authentication realm. */ 
     601            if (!pjsua.cred_count) pjsua.cred_count = 1; 
     602            pjsua.cred_info[0].realm = pj_str(optarg); 
     603            break; 
     604 
     605        case OPT_PASSWORD:   /* authentication password */ 
     606            if (!pjsua.cred_count) pjsua.cred_count = 1; 
     607            pjsua.cred_info[0].data_type = 0; 
     608            pjsua.cred_info[0].data = pj_str(optarg); 
     609            break; 
     610 
     611        case OPT_USE_STUN1:   /* STUN server 1 */ 
     612            p = pj_native_strchr(optarg, ':'); 
     613            if (p) { 
     614                *p = '\0'; 
     615                pjsua.stun_srv1 = pj_str(optarg); 
     616                pjsua.stun_port1 = pj_strtoul(pj_cstr(&tmp, p+1)); 
     617                if (pjsua.stun_port1 < 1 || pjsua.stun_port1 > 65535) { 
     618                    printf("Error: expecting port number with option --use-stun1\n"); 
     619                    return PJ_EINVAL; 
     620                } 
     621            } else { 
     622                pjsua.stun_port1 = 3478; 
     623                pjsua.stun_srv1 = pj_str(optarg); 
     624            } 
     625            break; 
     626 
     627        case OPT_USE_STUN2:   /* STUN server 2 */ 
     628            p = pj_native_strchr(optarg, ':'); 
     629            if (p) { 
     630                *p = '\0'; 
     631                pjsua.stun_srv2 = pj_str(optarg); 
     632                pjsua.stun_port2 = pj_strtoul(pj_cstr(&tmp,p+1)); 
     633                if (pjsua.stun_port2 < 1 || pjsua.stun_port2 > 65535) { 
     634                    printf("Error: expecting port number with option --use-stun2\n"); 
     635                    return PJ_EINVAL; 
     636                } 
     637            } else { 
     638                pjsua.stun_port2 = 3478; 
     639                pjsua.stun_srv2 = pj_str(optarg); 
     640            } 
     641            break; 
     642        } 
     643    } 
     644 
     645    if (optind != argc) { 
     646        printf("Error: unknown options %s\n", argv[optind]); 
     647        return PJ_EINVAL; 
     648    } 
     649 
     650    if (pjsua.reg_timeout == 0) 
     651        pjsua.reg_timeout = 3600; 
     652 
     653 
     654    return PJ_SUCCESS; 
     655} 
     656 
     657 
     658 
     659/***************************************************************************** 
     660 * main(): 
     661 */ 
     662int main(int argc, char *argv[]) 
    215663{ 
    216664    /* Init default settings. */ 
     
    224672 
    225673 
    226     /* Initialize pjsua. 
    227      * This will start worker thread, client registration, etc. 
     674    /* Initialize pjsua (to create pool etc). 
    228675     */ 
    229676 
    230677    if (pjsua_init() != PJ_SUCCESS) 
    231678        return 1; 
     679 
     680 
     681    /* Parse command line arguments: */ 
     682 
     683    if (parse_args(argc, argv) != PJ_SUCCESS) 
     684        return 1; 
     685 
     686 
     687    /* Init logging: */ 
     688 
     689    app_logging_init(); 
     690 
    232691 
    233692    /* Register message logger to print incoming and outgoing 
     
    238697 
    239698 
     699    /* Start pjsua! */ 
     700 
     701    if (pjsua_start() != PJ_SUCCESS) { 
     702 
     703        pjsua_destroy(); 
     704        return 1; 
     705    } 
     706 
     707 
    240708    /* Sleep for a while, let any messages get printed to console: */ 
    241709 
     
    252720    pjsua_destroy(); 
    253721 
     722 
     723    /* Close logging: */ 
     724 
     725    app_logging_shutdown(); 
     726 
     727 
    254728    /* Exit... */ 
    255729 
  • pjproject/trunk/pjsip/src/pjsua/pjsua.c

    r139 r141  
    2424 
    2525 
    26 #define PJSUA_LOCAL_URI     "<sip:bennylp@192.168.0.7>" 
    27 #define PJSUA_CONTACT_URI   "<sip:bennylp@192.168.0.7>" 
     26#define PJSUA_LOCAL_URI     "<sip:user@127.0.0.1>" 
    2827 
    2928static char *PJSUA_DUMMY_SDP_OFFER =  
     
    7271 
    7372    pjsua.stun_port1 = pjsua.stun_port2 = 0; 
     73 
     74    /* Default URIs: */ 
     75 
     76    pjsua.local_uri = pj_str(PJSUA_LOCAL_URI); 
    7477} 
    7578 
     
    130133static void pjsua_inv_on_state_changed(pjsip_inv_session *inv, pjsip_event *e) 
    131134{ 
    132     ui_inv_on_state_changed(inv, e); 
     135    pjsua_ui_inv_on_state_changed(inv, e); 
    133136} 
    134137 
     
    397400 
    398401 
     402    /* Done */ 
     403 
     404    return PJ_SUCCESS; 
     405 
     406 
     407on_error: 
     408    pjsip_endpt_destroy(pjsua.endpt); 
     409    pjsua.endpt = NULL; 
     410    return status; 
     411} 
     412 
     413 
     414static int PJ_THREAD_FUNC pjsua_worker_thread(void *arg) 
     415{ 
     416    PJ_UNUSED_ARG(arg); 
     417 
     418    while (!pjsua.quit_flag) { 
     419        pj_time_val timeout = { 0, 10 }; 
     420        pjsip_endpt_handle_events (pjsua.endpt, &timeout); 
     421    } 
     422 
     423    return 0; 
     424} 
     425 
     426/* 
     427 * Initialize pjsua application. 
     428 * This will initialize all libraries, create endpoint instance, and register 
     429 * pjsip modules. 
     430 */ 
     431pj_status_t pjsua_init(void) 
     432{ 
     433    pj_status_t status; 
     434 
     435    /* Init PJLIB logging: */ 
     436 
     437    pj_log_set_level(pjsua.log_level); 
     438    pj_log_set_decor(pjsua.log_decor); 
     439 
     440 
     441    /* Init PJLIB: */ 
     442 
     443    status = pj_init(); 
     444    if (status != PJ_SUCCESS) { 
     445        pjsua_perror("pj_init() error", status); 
     446        return status; 
     447    } 
     448 
     449    /* Init memory pool: */ 
     450 
     451    /* Init caching pool. */ 
     452    pj_caching_pool_init(&pjsua.cp, &pj_pool_factory_default_policy, 0); 
     453 
     454    /* Create memory pool for application. */ 
     455    pjsua.pool = pj_pool_create(&pjsua.cp.factory, "pjsua", 4000, 4000, NULL); 
     456 
     457 
     458    /* Init PJSIP and all the modules: */ 
     459 
     460    status = init_stack(); 
     461    if (status != PJ_SUCCESS) { 
     462        pj_caching_pool_destroy(&pjsua.cp); 
     463        pjsua_perror("Stack initialization has returned error", status); 
     464        return status; 
     465    } 
     466 
     467    /* Done. */ 
     468    return PJ_SUCCESS; 
     469} 
     470 
     471 
     472 
     473/* 
     474 * Start pjsua stack. 
     475 * This will start the registration process, if registration is configured. 
     476 */ 
     477pj_status_t pjsua_start(void) 
     478{ 
     479    int i;  /* Must be signed */ 
     480    pjsip_transport *udp_transport; 
     481    pj_status_t status; 
     482 
     483    /* Init sockets (STUN etc): */ 
     484 
     485    status = init_sockets(); 
     486    if (status != PJ_SUCCESS) { 
     487        pj_caching_pool_destroy(&pjsua.cp); 
     488        pjsua_perror("init_sockets() has returned error", status); 
     489        return status; 
     490    } 
     491 
     492 
    399493    /* Add UDP transport: */ 
    400494 
     
    413507 
    414508        status = pjsip_udp_transport_attach( pjsua.endpt, pjsua.sip_sock, 
    415                                              &addr_name, 1, NULL); 
     509                                             &addr_name, 1,  
     510                                             &udp_transport); 
    416511        if (status != PJ_SUCCESS) { 
    417512            pjsua_perror("Unable to start UDP transport", status); 
    418             goto on_error; 
    419         } 
    420     } 
    421  
    422     /* Initialize local user info and contact: */ 
    423  
    424     { 
    425         pj_strdup2(pjsua.pool, &pjsua.local_uri, PJSUA_LOCAL_URI); 
    426         pj_strdup2(pjsua.pool, &pjsua.contact_uri, PJSUA_CONTACT_URI); 
     513            return status; 
     514        } 
     515    } 
     516 
     517    /* Initialize Contact URI, if one is not specified: */ 
     518 
     519    if (pjsua.contact_uri.slen == 0 && pjsua.local_uri.slen) { 
     520 
     521        pjsip_uri *uri; 
     522        pjsip_sip_uri *sip_uri; 
     523        char contact[128]; 
     524        int len; 
     525 
     526        /* The local Contact is the username@ip-addr, where 
     527         *  - username is taken from the local URI, 
     528         *  - ip-addr in UDP transport's address name (which may have been 
     529         *    resolved from STUN. 
     530         */ 
     531         
     532        /* Need to parse local_uri to get the elements: */ 
     533 
     534        uri = pjsip_parse_uri(pjsua.pool, pjsua.local_uri.ptr,  
     535                              pjsua.local_uri.slen, 0); 
     536        if (uri == NULL) { 
     537            pjsua_perror("Invalid local URI", PJSIP_EINVALIDURI); 
     538            return PJSIP_EINVALIDURI; 
     539        } 
     540 
     541 
     542        /* Local URI MUST be a SIP or SIPS: */ 
     543 
     544        if (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri)) { 
     545            pjsua_perror("Invalid local URI", PJSIP_EINVALIDSCHEME); 
     546            return PJSIP_EINVALIDSCHEME; 
     547        } 
     548 
     549 
     550        /* Get the SIP URI object: */ 
     551 
     552        sip_uri = (pjsip_sip_uri*) pjsip_uri_get_uri(uri); 
     553 
     554         
     555        /* Build temporary contact string. */ 
     556 
     557        if (sip_uri->user.slen) { 
     558 
     559            /* With the user part. */ 
     560            len = pj_snprintf(contact, sizeof(contact), 
     561                              "<sip:%.*s@%.*s:%d>", 
     562                              sip_uri->user.slen, 
     563                              sip_uri->user.ptr, 
     564                              udp_transport->local_name.host.slen, 
     565                              udp_transport->local_name.host.ptr, 
     566                              udp_transport->local_name.port); 
     567        } else { 
     568 
     569            /* Without user part */ 
     570 
     571            len = pj_snprintf(contact, sizeof(contact), 
     572                              "<sip:%.*s:%d>", 
     573                              udp_transport->local_name.host.slen, 
     574                              udp_transport->local_name.host.ptr, 
     575                              udp_transport->local_name.port); 
     576        } 
     577 
     578        if (len < 1 || len >= sizeof(contact)) { 
     579            pjsua_perror("Invalid Contact", PJSIP_EURITOOLONG); 
     580            return PJSIP_EURITOOLONG; 
     581        } 
     582 
     583        /* Duplicate Contact uri. */ 
     584 
     585        pj_strdup2(pjsua.pool, &pjsua.contact_uri, contact); 
     586 
    427587    } 
    428588 
     
    431591    PJ_TODO(INIT_GLOBAL_ROUTE_SET); 
    432592 
    433  
    434     /* Start registration: */ 
    435  
    436     PJ_TODO(START_REGISTRATION); 
    437  
    438     /* Done? */ 
    439  
    440     return PJ_SUCCESS; 
    441  
    442  
    443 on_error: 
    444     pjsip_endpt_destroy(pjsua.endpt); 
    445     pjsua.endpt = NULL; 
    446     return status; 
    447 } 
    448  
    449  
    450 static int PJ_THREAD_FUNC pjsua_worker_thread(void *arg) 
    451 { 
    452     PJ_UNUSED_ARG(arg); 
    453  
    454     while (!pjsua.quit_flag) { 
    455         pj_time_val timeout = { 0, 10 }; 
    456         pjsip_endpt_handle_events (pjsua.endpt, &timeout); 
    457     } 
    458  
    459     return 0; 
    460 } 
    461  
    462 /* 
    463  * Initialize pjsua application. 
    464  * This will start the registration process, if registration is configured. 
    465  */ 
    466 pj_status_t pjsua_init(void) 
    467 { 
    468     int i;  /* Must be signed */ 
    469     pj_status_t status; 
    470  
    471     /* Init PJLIB logging: */ 
    472  
    473     pj_log_set_level(pjsua.log_level); 
    474     pj_log_set_decor(pjsua.log_decor); 
    475  
    476  
    477     /* Init PJLIB: */ 
    478  
    479     status = pj_init(); 
    480     if (status != PJ_SUCCESS) { 
    481         pjsua_perror("pj_init() error", status); 
    482         return status; 
    483     } 
    484  
    485     /* Init memory pool: */ 
    486  
    487     /* Init caching pool. */ 
    488     pj_caching_pool_init(&pjsua.cp, &pj_pool_factory_default_policy, 0); 
    489  
    490     /* Create memory pool for application. */ 
    491     pjsua.pool = pj_pool_create(&pjsua.cp.factory, "pjsua", 4000, 4000, NULL); 
    492  
    493  
    494     /* Init sockets (STUN etc): */ 
    495  
    496     status = init_sockets(); 
    497     if (status != PJ_SUCCESS) { 
    498         pj_caching_pool_destroy(&pjsua.cp); 
    499         pjsua_perror("init_sockets() has returned error", status); 
    500         return status; 
    501     } 
    502  
    503  
    504     /* Init PJSIP and all the modules: */ 
    505  
    506     status = init_stack(); 
    507     if (status != PJ_SUCCESS) { 
    508         pj_caching_pool_destroy(&pjsua.cp); 
    509         pjsua_perror("Stack initialization has returned error", status); 
    510         return status; 
    511     } 
    512593 
    513594    /* Create worker thread(s), if required: */ 
     
    527608    } 
    528609 
    529     /* Done. */ 
     610    /* Start registration: */ 
     611 
     612    /* Create client registration session: */ 
     613 
     614    status = pjsua_regc_init(); 
     615    if (status != PJ_SUCCESS) 
     616        return status; 
     617 
     618    /* Perform registration, if required. */ 
     619    if (pjsua.regc) { 
     620        pjsua_regc_update(1); 
     621    } 
     622 
     623 
     624 
    530625    return PJ_SUCCESS; 
    531626} 
     
    538633{ 
    539634    int i; 
     635 
     636    /* Unregister, if required: */ 
     637    if (pjsua.regc) { 
     638 
     639        pjsua_regc_update(0); 
     640 
     641        /* Wait for some time to allow unregistration to complete: */ 
     642 
     643        pj_thread_sleep(500); 
     644    } 
    540645 
    541646    /* Signal threads to quit: */ 
     
    611716 
    612717 
     718    /* Set dialog Route-Set: */ 
     719 
     720    PJ_TODO(INIT_DIALOG_ROUTE_SET); 
     721 
    613722    /* Set credentials: */ 
    614723 
    615     PJ_TODO(SET_DIALOG_CREDENTIALS); 
     724    pjsip_auth_clt_set_credentials( &dlg->auth_sess, pjsua.cred_count,  
     725                                    pjsua.cred_info); 
    616726 
    617727 
  • pjproject/trunk/pjsip/src/pjsua/pjsua.h

    r139 r141  
    4848 
    4949    /* User info: */ 
     50 
    5051    pj_str_t         local_uri;     /**< Uri in From: header.           */ 
    5152    pj_str_t         contact_uri;   /**< Uri in Contact: header.        */ 
     53 
     54    /* Proxy URLs: */ 
     55 
     56    pj_str_t         proxy; 
     57    pj_str_t         outbound_proxy; 
     58 
     59    /* Registration: */ 
     60 
     61    pj_str_t         registrar_uri; 
     62    pjsip_regc      *regc; 
     63    pj_int32_t       reg_timeout; 
     64    pj_timer_entry   regc_timer; 
     65 
     66 
     67    /* Authentication credentials: */ 
     68 
     69    int              cred_count; 
     70    pjsip_cred_info  cred_info[4]; 
     71 
    5272 
    5373    /* Threading: */ 
     
    7797 
    7898 
     99    /* Media stack: */ 
     100 
     101    pj_bool_t        null_audio; 
     102    pj_med_mgr_t    *mmgr; 
     103 
     104 
    79105    /* Misc: */ 
    80106     
     
    82108    int              app_log_level; /**< stdout log verbosity.          */ 
    83109    unsigned         log_decor;     /**< Log decoration.                */ 
     110    char            *log_filename;  /**< Log filename.                  */ 
    84111 
    85112} pjsua; 
     
    103130 
    104131/** 
    105  * Initialize pjsua application. 
    106  * This will start the registration process, if registration is configured. 
     132 * Initialize pjsua application. Application can call this before parsing 
     133 * application settings. 
     134 * 
     135 * This will initialize all libraries, create endpoint instance, and register 
     136 * pjsip modules. Transport will NOT be created however. 
     137 * 
     138 * Application may register module after calling this function. 
    107139 */ 
    108140pj_status_t pjsua_init(void); 
     141 
     142 
     143/** 
     144 * Start pjsua stack. Application calls this after pjsua settings has been 
     145 * configured. 
     146 * 
     147 * This will start the transport, worker threads (if any), and registration  
     148 * process, if registration is configured. 
     149 */ 
     150pj_status_t pjsua_start(void); 
    109151 
    110152 
     
    123165 
    124166/***************************************************************************** 
     167 * PJSUA Client Registration API. 
     168 */ 
     169 
     170/** 
     171 * Initialize client registration session. 
     172 * 
     173 * @param app_callback  Optional callback 
     174 */ 
     175pj_status_t pjsua_regc_init(void); 
     176 
     177/** 
     178 * Update registration or perform unregistration. If renew argument is zero, 
     179 * this will start unregistration process. 
     180 */ 
     181void pjsua_regc_update(pj_bool_t renew); 
     182 
     183 
     184/***************************************************************************** 
    125185 * User Interface API. 
    126186 * The UI API specifies functions that will be called by pjsua upon 
     
    131191 * Notify UI when invite state has changed. 
    132192 */ 
    133 void ui_inv_on_state_changed(pjsip_inv_session *inv, pjsip_event *e); 
     193void pjsua_ui_inv_on_state_changed(pjsip_inv_session *inv, pjsip_event *e); 
    134194 
    135195 
Note: See TracChangeset for help on using the changeset viewer.