Ignore:
Timestamp:
Jun 13, 2006 10:57:13 PM (18 years ago)
Author:
bennylp
Message:

-- REWRITE OF PJSUA API --

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c

    r492 r503  
    1818 */ 
    1919#include <pjsua-lib/pjsua.h> 
    20 #include <pj/log.h> 
    21 #include "pjsua_imp.h" 
    22  
    23 /* 
    24  * pjsua_call.c 
    25  * 
    26  * Call (INVITE) related stuffs. 
    27  */ 
    28  
    29 #define THIS_FILE   "pjsua_call.c" 
    30  
    31  
    32 #define REFRESH_CALL_TIMER      0x63 
    33 #define HANGUP_CALL_TIMER       0x64 
    34  
    35 /* Proto */ 
    36 static void schedule_call_timer( pjsua_call *call, pj_timer_entry *e, 
    37                                  int timer_type, int duration ); 
    38  
    39 /* 
    40  * Timer callback when UAS needs to send re-INVITE to see if remote 
    41  * is still there. 
    42  */ 
    43 static void call_on_timer(pj_timer_heap_t *ht, pj_timer_entry *e) 
    44 { 
    45     pjsua_call *call = e->user_data; 
    46  
    47     PJ_UNUSED_ARG(ht); 
    48  
    49     if (e->id == REFRESH_CALL_TIMER) { 
    50  
    51         /* If call is still not connected, hangup. */ 
    52         if (call->inv->state != PJSIP_INV_STATE_CONFIRMED) { 
    53             PJ_LOG(3,(THIS_FILE, "Refresh call timer is called when " 
    54                       "invite is still not confirmed. Call %d will " 
    55                       "disconnect.", call->index)); 
    56             pjsua_call_hangup(call->index); 
    57         } else { 
    58             PJ_LOG(3,(THIS_FILE, "Refreshing call %d", call->index)); 
    59             schedule_call_timer(call,e,REFRESH_CALL_TIMER, 
    60                                 pjsua.config.uas_refresh); 
    61             pjsua_call_reinvite(call->index); 
    62         } 
    63  
    64     } else if (e->id == HANGUP_CALL_TIMER) { 
    65         PJ_LOG(3,(THIS_FILE, "Call %d duration exceeded, disconnecting call", 
    66                              call->index)); 
    67         pjsua_call_hangup(call->index); 
    68  
    69     } 
    70 } 
    71  
    72 /* 
    73  * Schedule call timer. 
    74  */ 
    75 static void schedule_call_timer( pjsua_call *call, pj_timer_entry *e, 
    76                                  int timer_type, int duration ) 
    77 { 
    78     pj_time_val timeout; 
    79  
    80     if (duration == 0) { 
    81         /* Cancel timer. */ 
    82         if (e->id != 0) { 
    83             pjsip_endpt_cancel_timer(pjsua.endpt, e); 
    84             e->id = 0; 
    85         } 
    86  
    87     } else { 
    88         /* Schedule timer. */ 
    89         timeout.sec = duration; 
    90         timeout.msec = 0; 
    91  
    92         e->cb = &call_on_timer; 
    93         e->id = timer_type; 
    94         e->user_data = call; 
    95  
    96         pjsip_endpt_schedule_timer( pjsua.endpt, e, &timeout); 
    97     } 
    98 } 
    99  
    100  
    101 /* 
    102  * Destroy the call's media 
    103  */ 
    104 static pj_status_t call_destroy_media(int call_index) 
    105 { 
    106     pjsua_call *call = &pjsua.calls[call_index]; 
    107  
    108     if (call->conf_slot > 0) { 
    109         pjmedia_conf_remove_port(pjsua.mconf, call->conf_slot); 
    110         call->conf_slot = 0; 
    111     } 
    112  
    113     if (call->session) { 
    114         /* Destroy session (this will also close RTP/RTCP sockets). */ 
    115         pjmedia_session_destroy(call->session); 
    116         call->session = NULL; 
    117  
    118         PJ_LOG(3,(THIS_FILE, "Media session for call %d is destroyed",  
    119                              call_index)); 
    120  
    121     } 
    122  
     20#include <pjsua-lib/pjsua_internal.h> 
     21 
     22 
     23#define THIS_FILE               "pjsua_call.c" 
     24 
     25 
     26/* This callback receives notification from invite session when the 
     27 * session state has changed. 
     28 */ 
     29static void pjsua_call_on_state_changed(pjsip_inv_session *inv,  
     30                                        pjsip_event *e); 
     31 
     32/* This callback is called by invite session framework when UAC session 
     33 * has forked. 
     34 */ 
     35static void pjsua_call_on_forked( pjsip_inv_session *inv,  
     36                                  pjsip_event *e); 
     37 
     38/* 
     39 * Callback to be called when SDP offer/answer negotiation has just completed 
     40 * in the session. This function will start/update media if negotiation 
     41 * has succeeded. 
     42 */ 
     43static void pjsua_call_on_media_update(pjsip_inv_session *inv, 
     44                                       pj_status_t status); 
     45 
     46/* 
     47 * Called when session received new offer. 
     48 */ 
     49static void pjsua_call_on_rx_offer(pjsip_inv_session *inv, 
     50                                   const pjmedia_sdp_session *offer); 
     51 
     52/* 
     53 * This callback is called when transaction state has changed in INVITE 
     54 * session. We use this to trap: 
     55 *  - incoming REFER request. 
     56 *  - incoming MESSAGE request. 
     57 */ 
     58static void pjsua_call_on_tsx_state_changed(pjsip_inv_session *inv, 
     59                                            pjsip_transaction *tsx, 
     60                                            pjsip_event *e); 
     61 
     62 
     63/* Destroy the call's media */ 
     64static pj_status_t call_destroy_media(int call_id); 
     65 
     66/* Create inactive SDP for call hold. */ 
     67static pj_status_t create_inactive_sdp(pjsua_call *call, 
     68                                       pjmedia_sdp_session **p_answer); 
     69 
     70 
     71/* 
     72 * Reset call descriptor. 
     73 */ 
     74static void reset_call(pjsua_call_id id) 
     75{ 
     76    pjsua_call *call = &pjsua_var.calls[id]; 
     77 
     78    call->index = id; 
     79    call->inv = NULL; 
     80    call->user_data = NULL; 
     81    call->session = NULL; 
     82    call->xfer_sub = NULL; 
     83    call->last_code = 0; 
     84    call->conf_slot = PJSUA_INVALID_ID; 
     85    call->last_text.ptr = call->last_text_buf_; 
     86    call->last_text.slen = 0; 
     87} 
     88 
     89 
     90/* 
     91 * Init call subsystem. 
     92 */ 
     93pj_status_t pjsua_call_subsys_init(const pjsua_config *cfg) 
     94{ 
     95    pjsip_inv_callback inv_cb; 
     96    unsigned i; 
     97    pj_status_t status; 
     98 
     99    /* Init calls array. */ 
     100    for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.calls); ++i) 
     101        reset_call(i); 
     102 
     103    /* Copy config */ 
     104    pjsua_config_dup(pjsua_var.pool, &pjsua_var.ua_cfg, cfg); 
     105 
     106    /* Initialize invite session callback. */ 
     107    pj_memset(&inv_cb, 0, sizeof(inv_cb)); 
     108    inv_cb.on_state_changed = &pjsua_call_on_state_changed; 
     109    inv_cb.on_new_session = &pjsua_call_on_forked; 
     110    inv_cb.on_media_update = &pjsua_call_on_media_update; 
     111    inv_cb.on_rx_offer = &pjsua_call_on_rx_offer; 
     112    inv_cb.on_tsx_state_changed = &pjsua_call_on_tsx_state_changed; 
     113 
     114 
     115    /* Initialize invite session module: */ 
     116    status = pjsip_inv_usage_init(pjsua_var.endpt, &inv_cb); 
     117    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); 
     118 
     119    return status; 
     120} 
     121 
     122 
     123/* 
     124 * Start call subsystem. 
     125 */ 
     126pj_status_t pjsua_call_subsys_start(void) 
     127{ 
     128    /* Nothing to do */ 
    123129    return PJ_SUCCESS; 
    124130} 
    125131 
    126132 
    127 /** 
     133/* 
    128134 * Get maximum number of calls configured in pjsua. 
    129135 */ 
    130136PJ_DEF(unsigned) pjsua_call_get_max_count(void) 
    131137{ 
    132     return pjsua.config.max_calls; 
    133 } 
    134  
    135  
    136 /** 
    137  * Get current number of active calls. 
     138    return pjsua_var.ua_cfg.max_calls; 
     139} 
     140 
     141 
     142/* 
     143 * Get number of currently active calls. 
    138144 */ 
    139145PJ_DEF(unsigned) pjsua_call_get_count(void) 
    140146{ 
    141     return pjsua.call_cnt; 
    142 } 
    143  
    144  
    145 /** 
    146  * Check if the specified call is active. 
    147  */ 
    148 PJ_DEF(pj_bool_t) pjsua_call_is_active(unsigned call_index) 
    149 { 
    150     PJ_ASSERT_RETURN(call_index < pjsua.config.max_calls, 
    151                      PJ_EINVAL); 
    152     return pjsua.calls[call_index].inv != NULL && 
    153            pjsua.calls[call_index].inv->state != PJSIP_INV_STATE_DISCONNECTED; 
    154 } 
    155  
    156 /** 
    157  * Check if call has a media session. 
    158  */ 
    159 PJ_DEF(pj_bool_t) pjsua_call_has_media(unsigned call_index) 
    160 { 
    161     PJ_ASSERT_RETURN(call_index < pjsua.config.max_calls, PJ_EINVAL); 
    162     return pjsua.calls[call_index].session != NULL; 
    163 } 
    164  
    165  
    166 /** 
    167  * Get call info. 
    168  */ 
    169 PJ_DEF(pj_status_t) pjsua_call_get_info( unsigned call_index, 
    170                                          pjsua_call_info *info) 
    171 { 
    172     pjsua_call *call; 
    173  
    174     PJ_ASSERT_RETURN(call_index < pjsua.config.max_calls, 
    175                      PJ_EINVAL); 
    176  
    177     pj_memset(info, 0, sizeof(pjsua_call_info)); 
    178  
    179     call = &pjsua.calls[call_index]; 
    180     info->active = pjsua_call_is_active(call_index); 
    181  
    182     if (call->inv == NULL) 
    183         return PJ_SUCCESS; 
    184  
    185     info->index = call_index; 
    186     info->role = call->inv->role; 
    187     info->local_info = call->inv->dlg->local.info_str; 
    188     info->remote_info = call->inv->dlg->remote.info_str; 
    189     info->state = call->inv->state; 
    190     info->state_text = pj_str((char*)pjsip_inv_state_name(info->state)); 
    191      
    192     if (info->state >= PJSIP_INV_STATE_DISCONNECTED) { 
    193  
    194         info->total_duration = call->dis_time; 
    195         PJ_TIME_VAL_SUB(info->total_duration, call->start_time); 
    196  
    197         if (call->conn_time.sec) { 
    198             info->connect_duration = call->dis_time; 
    199             PJ_TIME_VAL_SUB(info->total_duration, call->conn_time); 
    200         } 
    201  
    202     } else if (info->state == PJSIP_INV_STATE_CONFIRMED) { 
    203  
    204         pj_gettimeofday(&info->total_duration); 
    205         PJ_TIME_VAL_SUB(info->total_duration, call->start_time); 
    206  
    207         pj_gettimeofday(&info->connect_duration); 
    208         PJ_TIME_VAL_SUB(info->connect_duration, call->conn_time); 
    209  
    210     } else { 
    211         pj_gettimeofday(&info->total_duration); 
    212         PJ_TIME_VAL_SUB(info->total_duration, call->start_time); 
    213     } 
    214  
    215     info->last_status = call->last_code; 
    216     info->last_status_text = *pjsip_get_status_text(info->last_status); 
    217  
    218     info->has_media = (call->session != NULL); 
    219     info->conf_slot = call->conf_slot; 
     147    return pjsua_var.call_cnt; 
     148} 
     149 
     150 
     151/* 
     152 * Enum calls. 
     153 */ 
     154PJ_DEF(pj_status_t) pjsua_enum_calls( pjsua_call_id ids[], 
     155                                      unsigned *count) 
     156{ 
     157    unsigned i, c; 
     158 
     159    PJ_ASSERT_RETURN(ids && *count, PJ_EINVAL); 
     160 
     161    PJSUA_LOCK(); 
     162 
     163    for (i=0, c=0; c<*count && i<pjsua_var.ua_cfg.max_calls; ++i) { 
     164        if (!pjsua_var.calls[i].inv) 
     165            continue; 
     166        ids[c] = i; 
     167        ++c; 
     168    } 
     169 
     170    *count = c; 
     171 
     172    PJSUA_UNLOCK(); 
    220173 
    221174    return PJ_SUCCESS; 
     
    223176 
    224177 
    225 /** 
    226  * Duplicate call info. 
    227  */ 
    228 PJ_DEF(void) pjsua_call_info_dup( pj_pool_t *pool, 
    229                                   pjsua_call_info *dst_info, 
    230                                   const pjsua_call_info *src_info) 
    231 { 
    232     PJ_ASSERT_ON_FAIL(pool && dst_info && src_info, return); 
    233  
    234     pj_memcpy(dst_info, src_info, sizeof(pjsua_call_info)); 
    235  
    236     pj_strdup(pool, &dst_info->local_info, &src_info->local_info); 
    237     pj_strdup(pool, &dst_info->remote_info, &src_info->remote_info); 
    238      
    239     /* state_text and cause_text belong to pjsip, so don't need to be 
    240      * duplicated because they'll always be available. 
    241      */ 
    242 } 
    243  
    244  
    245 /** 
    246  * Make outgoing call. 
    247  */ 
    248 PJ_DEF(pj_status_t) pjsua_call_make_call(unsigned acc_index, 
    249                                          const pj_str_t *dest_uri, 
    250                                          int *p_call_index) 
     178/* 
     179 * Make outgoing call to the specified URI using the specified account. 
     180 */ 
     181PJ_DEF(pj_status_t) pjsua_call_make_call( pjsua_acc_id acc_id, 
     182                                          const pj_str_t *dest_uri, 
     183                                          unsigned options, 
     184                                          void *user_data, 
     185                                          const pjsua_msg_data *msg_data, 
     186                                          pjsua_call_id *p_call_id) 
    251187{ 
    252188    pjsip_dialog *dlg = NULL; 
    253189    pjmedia_sdp_session *offer; 
    254190    pjsip_inv_session *inv = NULL; 
    255     unsigned call_index; 
     191    pjsua_acc *acc; 
     192    pjsua_call *call; 
     193    unsigned call_id; 
    256194    pjsip_tx_data *tdata; 
    257195    pj_status_t status; 
    258196 
    259197 
    260     PJ_ASSERT_RETURN(acc_index==0 || acc_index < pjsua.config.acc_cnt,  
     198    /* Check that account is valid */ 
     199    PJ_ASSERT_RETURN(acc_id>=0 || acc_id<PJ_ARRAY_SIZE(pjsua_var.acc),  
    261200                     PJ_EINVAL); 
    262201 
     202    /* Options must be zero for now */ 
     203    PJ_ASSERT_RETURN(options == 0, PJ_EINVAL); 
     204 
     205    PJSUA_LOCK(); 
     206 
     207    acc = &pjsua_var.acc[acc_id]; 
     208    if (!acc->valid) { 
     209        pjsua_perror(THIS_FILE, "Unable to make call because account " 
     210                     "is not valid", PJ_EINVALIDOP); 
     211        PJSUA_UNLOCK(); 
     212        return PJ_EINVALIDOP; 
     213    } 
    263214 
    264215    /* Find free call slot. */ 
    265     for (call_index=0; call_index<pjsua.config.max_calls; ++call_index) { 
    266         if (pjsua.calls[call_index].inv == NULL) 
     216    for (call_id=0; call_id<pjsua_var.ua_cfg.max_calls; ++call_id) { 
     217        if (pjsua_var.calls[call_id].inv == NULL) 
    267218            break; 
    268219    } 
    269220 
    270     if (call_index == pjsua.config.max_calls) { 
    271         PJ_LOG(3,(THIS_FILE, "Error: too many calls!")); 
     221    if (call_id == pjsua_var.ua_cfg.max_calls) { 
     222        pjsua_perror(THIS_FILE, "Error making file", PJ_ETOOMANY); 
     223        PJSUA_UNLOCK(); 
    272224        return PJ_ETOOMANY; 
    273225    } 
    274226 
     227    call = &pjsua_var.calls[call_id]; 
     228 
    275229    /* Mark call start time. */ 
    276     pj_gettimeofday(&pjsua.calls[call_index].start_time); 
     230    pj_gettimeofday(&call->start_time); 
    277231 
    278232    /* Reset first response time */ 
    279     pjsua.calls[call_index].res_time.sec = 0; 
     233    call->res_time.sec = 0; 
    280234 
    281235    /* Create outgoing dialog: */ 
    282236    status = pjsip_dlg_create_uac( pjsip_ua_instance(),  
    283                                    &pjsua.config.acc_config[acc_index].id, 
    284                                    &pjsua.config.acc_config[acc_index].contact, 
    285                                    dest_uri, dest_uri, 
    286                                    &dlg); 
     237                                   &acc->cfg.id, &acc->cfg.contact, 
     238                                   dest_uri, dest_uri, &dlg); 
    287239    if (status != PJ_SUCCESS) { 
    288240        pjsua_perror(THIS_FILE, "Dialog creation failed", status); 
     241        PJSUA_UNLOCK(); 
    289242        return status; 
    290243    } 
     
    292245    /* Get media capability from media endpoint: */ 
    293246 
    294     status = pjmedia_endpt_create_sdp( pjsua.med_endpt, dlg->pool, 1,  
    295                                        &pjsua.calls[call_index].skinfo,  
    296                                        &offer); 
     247    status = pjmedia_endpt_create_sdp( pjsua_var.med_endpt, dlg->pool, 1,  
     248                                       &call->skinfo, &offer); 
    297249    if (status != PJ_SUCCESS) { 
    298250        pjsua_perror(THIS_FILE, "pjmedia unable to create SDP", status); 
     
    311263    /* Create and associate our data in the session. */ 
    312264 
    313     pjsua.calls[call_index].inv = inv; 
    314  
    315     dlg->mod_data[pjsua.mod.id] = &pjsua.calls[call_index]; 
    316     inv->mod_data[pjsua.mod.id] = &pjsua.calls[call_index]; 
    317  
     265    call->inv = inv; 
     266 
     267    dlg->mod_data[pjsua_var.mod.id] = call; 
     268    inv->mod_data[pjsua_var.mod.id] = call; 
     269 
     270    /* Attach user data */ 
     271    call->user_data = user_data; 
    318272 
    319273    /* Set dialog Route-Set: */ 
    320  
    321     if (!pj_list_empty(&pjsua.acc[acc_index].route_set)) 
    322         pjsip_dlg_set_route_set(dlg, &pjsua.acc[acc_index].route_set); 
     274    if (!pj_list_empty(&acc->route_set)) 
     275        pjsip_dlg_set_route_set(dlg, &acc->route_set); 
    323276 
    324277 
    325278    /* Set credentials: */ 
    326     if (pjsua.config.acc_config[acc_index].cred_count) { 
    327         pjsua_acc_config *acc_cfg = &pjsua.config.acc_config[acc_index]; 
     279    if (acc->cred_cnt) { 
    328280        pjsip_auth_clt_set_credentials( &dlg->auth_sess,  
    329                                         acc_cfg->cred_count, 
    330                                         acc_cfg->cred_info); 
     281                                        acc->cred_cnt, acc->cred); 
    331282    } 
    332283 
     
    341292    } 
    342293 
     294 
     295    /* Add additional headers etc */ 
     296 
     297    pjsua_process_msg_data( tdata, msg_data); 
    343298 
    344299    /* Send initial INVITE: */ 
     
    357312    } 
    358313 
    359  
    360314    /* Done. */ 
    361315 
    362     ++pjsua.call_cnt; 
    363  
    364     if (p_call_index) 
    365         *p_call_index = call_index; 
     316    ++pjsua_var.call_cnt; 
     317 
     318    if (p_call_id) 
     319        *p_call_id = call_id; 
     320 
     321    PJSUA_UNLOCK(); 
    366322 
    367323    return PJ_SUCCESS; 
     
    375331    } 
    376332 
    377     if (call_index != -1) { 
    378         pjsua.calls[call_index].inv = NULL; 
    379     } 
    380     return status; 
    381 } 
    382  
    383  
    384 /** 
    385  * Answer call. 
    386  */ 
    387 PJ_DEF(pj_status_t) pjsua_call_answer(int call_index, int code) 
    388 { 
    389     pjsip_tx_data *tdata; 
    390     pj_status_t status; 
    391  
    392     PJ_ASSERT_RETURN( call_index >= 0 &&  
    393                       call_index < (int)pjsua.config.max_calls, 
    394                       PJ_EINVAL); 
    395  
    396     if (pjsua.calls[call_index].inv == NULL) { 
    397         PJ_LOG(3,(THIS_FILE, "Call %d already disconnected")); 
    398         return PJSIP_ESESSIONTERMINATED; 
    399     } 
    400  
    401     status = pjsip_inv_answer(pjsua.calls[call_index].inv, 
    402                               code, NULL, NULL, &tdata); 
    403     if (status == PJ_SUCCESS) 
    404         status = pjsip_inv_send_msg(pjsua.calls[call_index].inv, 
    405                                     tdata); 
    406  
    407     if (status != PJ_SUCCESS) 
    408         pjsua_perror(THIS_FILE, "Unable to create/send response",  
    409                      status); 
    410  
     333    if (call_id != -1) { 
     334        reset_call(call_id); 
     335    } 
     336 
     337    PJSUA_UNLOCK(); 
    411338    return status; 
    412339} 
     
    415342/** 
    416343 * Handle incoming INVITE request. 
     344 * Called by pjsua_core.c 
    417345 */ 
    418346pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata) 
     
    424352    unsigned options = 0; 
    425353    pjsip_inv_session *inv = NULL; 
    426     int acc_index; 
    427     unsigned call_index; 
     354    int acc_id; 
     355    pjsua_call *call; 
     356    int call_id = -1; 
    428357    pjmedia_sdp_session *answer; 
    429358    pj_status_t status; 
     
    442371    /* Verify that we can handle the request. */ 
    443372    status = pjsip_inv_verify_request(rdata, &options, NULL, NULL, 
    444                                       pjsua.endpt, &response); 
     373                                      pjsua_var.endpt, &response); 
    445374    if (status != PJ_SUCCESS) { 
    446375 
     
    453382 
    454383            pjsip_get_response_addr(response->pool, rdata, &res_addr); 
    455             pjsip_endpt_send_response(pjsua.endpt, &res_addr, response,  
     384            pjsip_endpt_send_response(pjsua_var.endpt, &res_addr, response,  
    456385                                      NULL, NULL); 
    457386 
     
    459388 
    460389            /* Respond with 500 (Internal Server Error) */ 
    461             pjsip_endpt_respond_stateless(pjsua.endpt, rdata, 500, NULL, 
     390            pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 500, NULL, 
    462391                                          NULL, NULL); 
    463392        } 
     
    472401 
    473402    /* Find free call slot. */ 
    474     for (call_index=0; call_index < pjsua.config.max_calls; ++call_index) { 
    475         if (pjsua.calls[call_index].inv == NULL) 
     403    for (call_id=0; call_id<(int)pjsua_var.ua_cfg.max_calls; ++call_id) { 
     404        if (pjsua_var.calls[call_id].inv == NULL) 
    476405            break; 
    477406    } 
    478407 
    479     if (call_index == PJSUA_MAX_CALLS) { 
    480         pjsip_endpt_respond_stateless(pjsua.endpt, rdata,  
     408    if (call_id == (int)pjsua_var.ua_cfg.max_calls) { 
     409        pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata,  
    481410                                      PJSIP_SC_BUSY_HERE, NULL, 
    482411                                      NULL, NULL); 
     
    484413    } 
    485414 
     415    /* Clear call descriptor */ 
     416    reset_call(call_id); 
     417 
     418    call = &pjsua_var.calls[call_id]; 
     419 
    486420    /* Mark call start time. */ 
    487     pj_gettimeofday(&pjsua.calls[call_index].start_time); 
    488  
    489     /* Reset first response time */ 
    490     pjsua.calls[call_index].res_time.sec = 0; 
     421    pj_gettimeofday(&call->start_time); 
    491422 
    492423    /* Get media capability from media endpoint: */ 
    493  
    494     status = pjmedia_endpt_create_sdp( pjsua.med_endpt, rdata->tp_info.pool, 1, 
    495                                        &pjsua.calls[call_index].skinfo,  
    496                                        &answer ); 
    497     if (status != PJ_SUCCESS) { 
    498         pjsip_endpt_respond_stateless(pjsua.endpt, rdata, 500, NULL, 
     424    status = pjmedia_endpt_create_sdp( pjsua_var.med_endpt,  
     425                                       rdata->tp_info.pool, 1, 
     426                                       &call->skinfo, &answer ); 
     427    if (status != PJ_SUCCESS) { 
     428        pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 500, NULL, 
    499429                                      NULL, NULL); 
    500  
    501430        return PJ_TRUE; 
    502431    } 
    503432 
    504     /* TODO:  
    505      * 
     433    /*  
    506434     * Get which account is most likely to be associated with this incoming 
    507435     * call. We need the account to find which contact URI to put for 
    508436     * the call. 
    509437     */ 
    510     acc_index = 0; 
     438    acc_id = pjsua_acc_find_for_incoming(rdata); 
    511439 
    512440    /* Create dialog: */ 
    513  
    514441    status = pjsip_dlg_create_uas( pjsip_ua_instance(), rdata, 
    515                                    &pjsua.config.acc_config[acc_index].contact, 
     442                                   &pjsua_var.acc[acc_id].cfg.contact,  
    516443                                   &dlg); 
    517444    if (status != PJ_SUCCESS) { 
    518         pjsip_endpt_respond_stateless(pjsua.endpt, rdata, 500, NULL, 
     445        pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 500, NULL, 
    519446                                      NULL, NULL); 
    520447 
     
    522449    } 
    523450 
     451    /* Set credentials */ 
     452    if (pjsua_var.acc[acc_id].cred_cnt) { 
     453        pjsip_auth_clt_set_credentials(&dlg->auth_sess,  
     454                                       pjsua_var.acc[acc_id].cred_cnt, 
     455                                       pjsua_var.acc[acc_id].cred); 
     456    } 
    524457 
    525458    /* Create invite session: */ 
    526  
    527459    status = pjsip_inv_create_uas( dlg, rdata, answer, 0, &inv); 
    528460    if (status != PJ_SUCCESS) { 
    529  
    530461        pjsip_dlg_respond(dlg, rdata, 500, NULL, NULL, NULL); 
    531462        pjsip_dlg_terminate(dlg); 
     
    534465 
    535466 
    536     /* Create and attach pjsua data to the dialog: */ 
    537  
    538     pjsua.calls[call_index].inv = inv; 
    539  
    540     dlg->mod_data[pjsua.mod.id] = &pjsua.calls[call_index]; 
    541     inv->mod_data[pjsua.mod.id] = &pjsua.calls[call_index]; 
     467    /* Create and attach pjsua_var data to the dialog: */ 
     468    call->inv = inv; 
     469 
     470    dlg->mod_data[pjsua_var.mod.id] = call; 
     471    inv->mod_data[pjsua_var.mod.id] = call; 
    542472 
    543473 
     
    545475     * If auto-answer flag is set, send 200 straight away, otherwise send 100. 
    546476     */ 
    547      
    548477    status = pjsip_inv_initial_answer(inv, rdata,  
    549                                       (pjsua.config.auto_answer ?  
    550                                       pjsua.config.auto_answer : 100),  
    551                                       NULL, NULL, &response); 
    552     if (status != PJ_SUCCESS) { 
    553          
    554         int st_code; 
    555  
     478                                      100, NULL, NULL, &response); 
     479    if (status != PJ_SUCCESS) { 
    556480        pjsua_perror(THIS_FILE, "Unable to send answer to incoming INVITE",  
    557481                     status); 
    558482 
    559         /* If failed to send 2xx response, there's a good chance that it is 
    560          * because SDP negotiation has failed. 
    561          */ 
    562         if (pjsua.config.auto_answer/100 == 2) 
    563             st_code = PJSIP_SC_UNSUPPORTED_MEDIA_TYPE; 
    564         else 
    565             st_code = 500; 
    566  
    567         pjsip_dlg_respond(dlg, rdata, st_code, NULL, NULL, NULL); 
    568         pjsip_inv_terminate(inv, st_code, PJ_FALSE); 
     483        pjsip_dlg_respond(dlg, rdata, 500, NULL, NULL, NULL); 
     484        pjsip_inv_terminate(inv, 500, PJ_FALSE); 
    569485        return PJ_TRUE; 
    570486 
     
    575491    } 
    576492 
    577     if (pjsua.config.auto_answer < 200) { 
    578         PJ_LOG(3,(THIS_FILE, 
    579                   "\nIncoming call!!\n" 
    580                   "From: %.*s\n" 
    581                   "To:   %.*s\n" 
    582                   "(press 'a' to answer, 'h' to decline)", 
    583                   (int)dlg->remote.info_str.slen, 
    584                   dlg->remote.info_str.ptr, 
    585                   (int)dlg->local.info_str.slen, 
    586                   dlg->local.info_str.ptr)); 
    587     } else { 
    588         PJ_LOG(3,(THIS_FILE, 
    589                   "Call From:%.*s To:%.*s was answered with %d (%s)", 
    590                   (int)dlg->remote.info_str.slen, 
    591                   dlg->remote.info_str.ptr, 
    592                   (int)dlg->local.info_str.slen, 
    593                   dlg->local.info_str.ptr, 
    594                   pjsua.config.auto_answer, 
    595                   pjsip_get_status_text(pjsua.config.auto_answer)->ptr )); 
    596     } 
    597  
    598     ++pjsua.call_cnt; 
    599  
    600     /* Schedule timer to refresh. */ 
    601     if (pjsua.config.uas_refresh > 0) { 
    602         schedule_call_timer( &pjsua.calls[call_index],  
    603                              &pjsua.calls[call_index].refresh_tm, 
    604                              REFRESH_CALL_TIMER, 
    605                              pjsua.config.uas_refresh); 
    606     } 
    607  
    608     /* Schedule timer to hangup call. */ 
    609     if (pjsua.config.uas_duration > 0) { 
    610         schedule_call_timer( &pjsua.calls[call_index],  
    611                              &pjsua.calls[call_index].hangup_tm, 
    612                              HANGUP_CALL_TIMER, 
    613                              pjsua.config.uas_duration); 
    614     } 
     493    ++pjsua_var.call_cnt; 
     494 
    615495 
    616496    /* Notify application */ 
    617     if (pjsua.cb.on_incoming_call) 
    618         pjsua.cb.on_incoming_call(acc_index, call_index, rdata); 
    619  
     497    if (pjsua_var.ua_cfg.cb.on_incoming_call) 
     498        pjsua_var.ua_cfg.cb.on_incoming_call(acc_id, call_id, rdata); 
    620499 
    621500    /* This INVITE request has been handled. */ 
     
    624503 
    625504 
     505 
     506/* 
     507 * Check if the specified call has active INVITE session and the INVITE 
     508 * session has not been disconnected. 
     509 */ 
     510PJ_DEF(pj_bool_t) pjsua_call_is_active(pjsua_call_id call_id) 
     511{ 
     512    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     513                     PJ_EINVAL); 
     514    return pjsua_var.calls[call_id].inv != NULL && 
     515           pjsua_var.calls[call_id].inv->state != PJSIP_INV_STATE_DISCONNECTED; 
     516} 
     517 
     518 
     519/* 
     520 * Check if call has an active media session. 
     521 */ 
     522PJ_DEF(pj_bool_t) pjsua_call_has_media(pjsua_call_id call_id) 
     523{ 
     524    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,  
     525                     PJ_EINVAL); 
     526    return pjsua_var.calls[call_id].session != NULL; 
     527} 
     528 
     529 
     530/* 
     531 * Get the conference port identification associated with the call. 
     532 */ 
     533PJ_DEF(pjsua_conf_port_id) pjsua_call_get_conf_port(pjsua_call_id call_id) 
     534{ 
     535    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,  
     536                     PJ_EINVAL); 
     537    return pjsua_var.calls[call_id].conf_slot; 
     538} 
     539 
     540 
     541/* 
     542 * Obtain detail information about the specified call. 
     543 */ 
     544PJ_DEF(pj_status_t) pjsua_call_get_info( pjsua_call_id call_id, 
     545                                         pjsua_call_info *info) 
     546{ 
     547    pjsua_call *call; 
     548 
     549    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     550                     PJ_EINVAL); 
     551 
     552    pj_memset(info, 0, sizeof(*info)); 
     553 
     554    PJSUA_LOCK(); 
     555 
     556    call = &pjsua_var.calls[call_id]; 
     557 
     558    if (call->inv == NULL) { 
     559        PJSUA_UNLOCK(); 
     560        return PJ_SUCCESS; 
     561    } 
     562 
     563    pjsip_dlg_inc_lock(call->inv->dlg); 
     564 
     565 
     566    /* id and role */ 
     567    info->id = call_id; 
     568    info->role = call->inv->role; 
     569 
     570    /* local info */ 
     571    info->local_info.ptr = info->buf_.local_info; 
     572    pj_strncpy(&info->local_info, &call->inv->dlg->local.info_str, 
     573               sizeof(info->buf_.local_info)); 
     574 
     575    /* local contact */ 
     576    info->local_contact.ptr = info->buf_.local_contact; 
     577    info->local_contact.slen = pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, 
     578                                               call->inv->dlg->local.contact->uri, 
     579                                               info->local_contact.ptr, 
     580                                               sizeof(info->buf_.local_contact)); 
     581 
     582    /* remote info */ 
     583    info->remote_info.ptr = info->buf_.remote_info; 
     584    pj_strncpy(&info->remote_info, &call->inv->dlg->remote.info_str, 
     585               sizeof(info->buf_.remote_info)); 
     586 
     587    /* remote contact */ 
     588    if (call->inv->dlg->remote.contact) { 
     589        int len; 
     590        info->remote_contact.ptr = info->buf_.remote_contact; 
     591        len = pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, 
     592                              call->inv->dlg->remote.contact->uri, 
     593                              info->remote_contact.ptr, 
     594                              sizeof(info->buf_.remote_contact)); 
     595        if (len < 0) len = 0; 
     596        info->remote_contact.slen = len; 
     597    } else { 
     598        info->remote_contact.slen = 0; 
     599    } 
     600 
     601    /* call id */ 
     602    info->call_id.ptr = info->buf_.call_id; 
     603    pj_strncpy(&info->call_id, &call->inv->dlg->call_id->id, 
     604               sizeof(info->buf_.call_id)); 
     605 
     606    /* state, state_text */ 
     607    info->state = call->inv->state; 
     608    info->state_text = pj_str((char*)pjsip_inv_state_name(info->state)); 
     609 
     610    /* If call is disconnected, set the last_status from the cause code */ 
     611    if (call->inv->state >= PJSIP_INV_STATE_DISCONNECTED) { 
     612        /* last_status, last_status_text */ 
     613        info->last_status = call->inv->cause; 
     614 
     615        info->last_status_text.ptr = info->buf_.last_status_text; 
     616        pj_strncpy(&info->last_status_text, &call->inv->cause_text, 
     617                   sizeof(info->buf_.last_status_text)); 
     618    } else { 
     619        /* last_status, last_status_text */ 
     620        info->last_status = call->last_code; 
     621 
     622        info->last_status_text.ptr = info->buf_.last_status_text; 
     623        pj_strncpy(&info->last_status_text, &call->last_text, 
     624                   sizeof(info->buf_.last_status_text)); 
     625    } 
     626     
     627    /* media status and dir */ 
     628    info->media_status = call->media_st; 
     629    info->media_dir = call->media_dir; 
     630 
     631 
     632    /* conference slot number */ 
     633    info->conf_slot = call->conf_slot; 
     634 
     635    /* calculate duration */ 
     636    if (info->state >= PJSIP_INV_STATE_DISCONNECTED) { 
     637 
     638        info->total_duration = call->dis_time; 
     639        PJ_TIME_VAL_SUB(info->total_duration, call->start_time); 
     640 
     641        if (call->conn_time.sec) { 
     642            info->connect_duration = call->dis_time; 
     643            PJ_TIME_VAL_SUB(info->connect_duration, call->conn_time); 
     644        } 
     645 
     646    } else if (info->state == PJSIP_INV_STATE_CONFIRMED) { 
     647 
     648        pj_gettimeofday(&info->total_duration); 
     649        PJ_TIME_VAL_SUB(info->total_duration, call->start_time); 
     650 
     651        pj_gettimeofday(&info->connect_duration); 
     652        PJ_TIME_VAL_SUB(info->connect_duration, call->conn_time); 
     653 
     654    } else { 
     655        pj_gettimeofday(&info->total_duration); 
     656        PJ_TIME_VAL_SUB(info->total_duration, call->start_time); 
     657    } 
     658 
     659    pjsip_dlg_dec_lock(call->inv->dlg); 
     660    PJSUA_UNLOCK(); 
     661 
     662    return PJ_SUCCESS; 
     663} 
     664 
     665 
     666/* 
     667 * Attach application specific data to the call. 
     668 */ 
     669PJ_DEF(pj_status_t) pjsua_call_set_user_data( pjsua_call_id call_id, 
     670                                              void *user_data) 
     671{ 
     672    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     673                     PJ_EINVAL); 
     674    pjsua_var.calls[call_id].user_data = user_data; 
     675 
     676    return PJ_SUCCESS; 
     677} 
     678 
     679 
     680/* 
     681 * Get user data attached to the call. 
     682 */ 
     683PJ_DEF(void*) pjsua_call_get_user_data(pjsua_call_id call_id) 
     684{ 
     685    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     686                     NULL); 
     687    return pjsua_var.calls[call_id].user_data; 
     688} 
     689 
     690 
     691/* 
     692 * Send response to incoming INVITE request. 
     693 */ 
     694PJ_DEF(pj_status_t) pjsua_call_answer( pjsua_call_id call_id,  
     695                                       unsigned code, 
     696                                       const pj_str_t *reason, 
     697                                       const pjsua_msg_data *msg_data) 
     698{ 
     699    pjsua_call *call; 
     700    pjsip_tx_data *tdata; 
     701    pj_status_t status; 
     702 
     703    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     704                     PJ_EINVAL); 
     705 
     706    PJSUA_LOCK(); 
     707 
     708    call = &pjsua_var.calls[call_id]; 
     709 
     710    if (call->inv == NULL) { 
     711        PJ_LOG(3,(THIS_FILE, "Call %d already disconnected", call_id)); 
     712        PJSUA_UNLOCK(); 
     713        return PJSIP_ESESSIONTERMINATED; 
     714    } 
     715 
     716    /* Create response message */ 
     717    status = pjsip_inv_answer(call->inv, code, reason, NULL, &tdata); 
     718    if (status != PJ_SUCCESS) { 
     719        pjsua_perror(THIS_FILE, "Error creating response",  
     720                     status); 
     721        PJSUA_UNLOCK(); 
     722        return status; 
     723    } 
     724 
     725    /* Add additional headers etc */ 
     726    pjsua_process_msg_data( tdata, msg_data); 
     727 
     728    /* Send the message */ 
     729    status = pjsip_inv_send_msg(call->inv, tdata); 
     730    if (status != PJ_SUCCESS) 
     731        pjsua_perror(THIS_FILE, "Error sending response",  
     732                     status); 
     733 
     734    PJSUA_UNLOCK(); 
     735 
     736    return status; 
     737} 
     738 
     739 
     740/* 
     741 * Hangup call by using method that is appropriate according to the 
     742 * call state. 
     743 */ 
     744PJ_DEF(pj_status_t) pjsua_call_hangup(pjsua_call_id call_id, 
     745                                      unsigned code, 
     746                                      const pj_str_t *reason, 
     747                                      const pjsua_msg_data *msg_data) 
     748{ 
     749    pjsua_call *call; 
     750    pj_status_t status; 
     751    pjsip_tx_data *tdata; 
     752 
     753 
     754    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     755                     PJ_EINVAL); 
     756 
     757    PJSUA_LOCK(); 
     758 
     759    call = &pjsua_var.calls[call_id]; 
     760 
     761    if (!call->inv) { 
     762        PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 
     763        PJSUA_UNLOCK(); 
     764        return PJ_EINVAL; 
     765    } 
     766 
     767    if (code==0) { 
     768        if (call->inv->state == PJSIP_INV_STATE_CONFIRMED) 
     769            code = PJSIP_SC_OK; 
     770        else if (call->inv->role == PJSIP_ROLE_UAS) 
     771            code = PJSIP_SC_DECLINE; 
     772        else 
     773            code = PJSIP_SC_REQUEST_TERMINATED; 
     774    } 
     775 
     776    status = pjsip_inv_end_session(call->inv, code, reason, &tdata); 
     777    if (status != PJ_SUCCESS) { 
     778        pjsua_perror(THIS_FILE,  
     779                     "Failed to create end session message",  
     780                     status); 
     781        PJSUA_UNLOCK(); 
     782        return status; 
     783    } 
     784 
     785    /* pjsip_inv_end_session may return PJ_SUCCESS with NULL  
     786     * as p_tdata when INVITE transaction has not been answered 
     787     * with any provisional responses. 
     788     */ 
     789    if (tdata == NULL) { 
     790        PJSUA_UNLOCK(); 
     791        return PJ_SUCCESS; 
     792    } 
     793 
     794    /* Add additional headers etc */ 
     795    pjsua_process_msg_data( tdata, msg_data); 
     796 
     797    /* Send the message */ 
     798    status = pjsip_inv_send_msg(call->inv, tdata); 
     799    if (status != PJ_SUCCESS) { 
     800        pjsua_perror(THIS_FILE,  
     801                     "Failed to send end session message",  
     802                     status); 
     803        PJSUA_UNLOCK(); 
     804        return status; 
     805    } 
     806 
     807    PJSUA_UNLOCK(); 
     808 
     809    return PJ_SUCCESS; 
     810} 
     811 
     812 
     813/* 
     814 * Put the specified call on hold. 
     815 */ 
     816PJ_DEF(pj_status_t) pjsua_call_set_hold(pjsua_call_id call_id, 
     817                                        const pjsua_msg_data *msg_data) 
     818{ 
     819    pjmedia_sdp_session *sdp; 
     820    pjsua_call *call; 
     821    pjsip_tx_data *tdata; 
     822    pj_status_t status; 
     823 
     824    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     825                     PJ_EINVAL); 
     826 
     827    PJSUA_LOCK(); 
     828 
     829    call = &pjsua_var.calls[call_id]; 
     830     
     831    if (!call->inv) { 
     832        PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 
     833        PJSUA_UNLOCK(); 
     834        return PJSIP_ESESSIONTERMINATED; 
     835    } 
     836 
     837    if (call->inv->state != PJSIP_INV_STATE_CONFIRMED) { 
     838        PJ_LOG(3,(THIS_FILE, "Can not hold call that is not confirmed")); 
     839        PJSUA_UNLOCK(); 
     840        return PJSIP_ESESSIONSTATE; 
     841    } 
     842 
     843    status = create_inactive_sdp(call, &sdp); 
     844    if (status != PJ_SUCCESS) { 
     845        PJSUA_UNLOCK(); 
     846        return status; 
     847    } 
     848 
     849    /* Create re-INVITE with new offer */ 
     850    status = pjsip_inv_reinvite( call->inv, NULL, sdp, &tdata); 
     851    if (status != PJ_SUCCESS) { 
     852        pjsua_perror(THIS_FILE, "Unable to create re-INVITE", status); 
     853        PJSUA_UNLOCK(); 
     854        return status; 
     855    } 
     856 
     857    /* Add additional headers etc */ 
     858    pjsua_process_msg_data( tdata, msg_data); 
     859 
     860    /* Send the request */ 
     861    status = pjsip_inv_send_msg( call->inv, tdata); 
     862    if (status != PJ_SUCCESS) { 
     863        pjsua_perror(THIS_FILE, "Unable to send re-INVITE", status); 
     864        PJSUA_UNLOCK(); 
     865        return status; 
     866    } 
     867 
     868    PJSUA_UNLOCK(); 
     869 
     870    return PJ_SUCCESS; 
     871} 
     872 
     873 
     874/* 
     875 * Send re-INVITE (to release hold). 
     876 */ 
     877PJ_DEF(pj_status_t) pjsua_call_reinvite( pjsua_call_id call_id, 
     878                                         pj_bool_t unhold, 
     879                                         const pjsua_msg_data *msg_data) 
     880{ 
     881    pjmedia_sdp_session *sdp; 
     882    pjsip_tx_data *tdata; 
     883    pjsua_call *call; 
     884    pj_status_t status; 
     885 
     886 
     887    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     888                     PJ_EINVAL); 
     889 
     890    PJSUA_LOCK(); 
     891 
     892    call = &pjsua_var.calls[call_id]; 
     893 
     894    if (!call->inv) { 
     895        PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 
     896        PJSUA_UNLOCK(); 
     897        return PJSIP_ESESSIONTERMINATED; 
     898    } 
     899 
     900 
     901    if (call->inv->state != PJSIP_INV_STATE_CONFIRMED) { 
     902        PJ_LOG(3,(THIS_FILE, "Can not re-INVITE call that is not confirmed")); 
     903        PJSUA_UNLOCK(); 
     904        return PJSIP_ESESSIONSTATE; 
     905    } 
     906 
     907    /* Create SDP */ 
     908    status = pjmedia_endpt_create_sdp( pjsua_var.med_endpt, call->inv->pool,  
     909                                       1, &call->skinfo, &sdp); 
     910    if (status != PJ_SUCCESS) { 
     911        pjsua_perror(THIS_FILE, "Unable to get SDP from media endpoint",  
     912                     status); 
     913        PJSUA_UNLOCK(); 
     914        return status; 
     915    } 
     916 
     917    /* Create re-INVITE with new offer */ 
     918    status = pjsip_inv_reinvite( call->inv, NULL, sdp, &tdata); 
     919    if (status != PJ_SUCCESS) { 
     920        pjsua_perror(THIS_FILE, "Unable to create re-INVITE", status); 
     921        PJSUA_UNLOCK(); 
     922        return status; 
     923    } 
     924 
     925    /* Add additional headers etc */ 
     926    pjsua_process_msg_data( tdata, msg_data); 
     927 
     928    /* Send the request */ 
     929    status = pjsip_inv_send_msg( call->inv, tdata); 
     930    if (status != PJ_SUCCESS) { 
     931        pjsua_perror(THIS_FILE, "Unable to send re-INVITE", status); 
     932        PJSUA_UNLOCK(); 
     933        return status; 
     934    } 
     935 
     936    PJSUA_UNLOCK(); 
     937 
     938    return PJ_SUCCESS; 
     939} 
     940 
     941 
     942/* 
     943 * Initiate call transfer to the specified address. 
     944 */ 
     945PJ_DEF(pj_status_t) pjsua_call_xfer( pjsua_call_id call_id,  
     946                                     const pj_str_t *dest, 
     947                                     const pjsua_msg_data *msg_data) 
     948{ 
     949    pjsip_evsub *sub; 
     950    pjsip_tx_data *tdata; 
     951    pjsua_call *call; 
     952    pj_status_t status; 
     953 
     954 
     955    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     956                     PJ_EINVAL); 
     957     
     958    PJSUA_LOCK(); 
     959 
     960    call = &pjsua_var.calls[call_id]; 
     961 
     962    if (!call->inv) { 
     963        PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 
     964        PJSUA_UNLOCK(); 
     965        return PJSIP_ESESSIONTERMINATED; 
     966    } 
     967    
     968    /* Create xfer client subscription. 
     969     * We're not interested in knowing the transfer result, so we 
     970     * put NULL as the callback. 
     971     */ 
     972    status = pjsip_xfer_create_uac(call->inv->dlg, NULL, &sub); 
     973    if (status != PJ_SUCCESS) { 
     974        pjsua_perror(THIS_FILE, "Unable to create xfer", status); 
     975        PJSUA_UNLOCK(); 
     976        return status; 
     977    } 
     978 
     979    /* 
     980     * Create REFER request. 
     981     */ 
     982    status = pjsip_xfer_initiate(sub, dest, &tdata); 
     983    if (status != PJ_SUCCESS) { 
     984        pjsua_perror(THIS_FILE, "Unable to create REFER request", status); 
     985        PJSUA_UNLOCK(); 
     986        return status; 
     987    } 
     988 
     989    /* Add additional headers etc */ 
     990    pjsua_process_msg_data( tdata, msg_data); 
     991 
     992    /* Send. */ 
     993    status = pjsip_xfer_send_request(sub, tdata); 
     994    if (status != PJ_SUCCESS) { 
     995        pjsua_perror(THIS_FILE, "Unable to send REFER request", status); 
     996        PJSUA_UNLOCK(); 
     997        return status; 
     998    } 
     999 
     1000    /* For simplicity (that's what this program is intended to be!),  
     1001     * leave the original invite session as it is. More advanced application 
     1002     * may want to hold the INVITE, or terminate the invite, or whatever. 
     1003     */ 
     1004 
     1005    PJSUA_UNLOCK(); 
     1006 
     1007    return PJ_SUCCESS; 
     1008 
     1009} 
     1010 
     1011 
     1012/* 
     1013 * Send DTMF digits to remote using RFC 2833 payload formats. 
     1014 */ 
     1015PJ_DEF(pj_status_t) pjsua_call_dial_dtmf( pjsua_call_id call_id,  
     1016                                          const pj_str_t *digits) 
     1017{ 
     1018    pjsua_call *call; 
     1019    pj_status_t status; 
     1020 
     1021    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     1022                     PJ_EINVAL); 
     1023     
     1024    PJSUA_LOCK(); 
     1025 
     1026    call = &pjsua_var.calls[call_id]; 
     1027 
     1028    if (!call->session) { 
     1029        PJ_LOG(3,(THIS_FILE, "Media is not established yet!")); 
     1030        PJSUA_UNLOCK(); 
     1031        return PJ_EINVALIDOP; 
     1032    } 
     1033 
     1034    status = pjmedia_session_dial_dtmf( call->session, 0, digits); 
     1035 
     1036    PJSUA_UNLOCK(); 
     1037 
     1038    return status; 
     1039} 
     1040 
     1041 
     1042/** 
     1043 * Send instant messaging inside INVITE session. 
     1044 */ 
     1045PJ_DEF(pj_status_t) pjsua_call_send_im( pjsua_call_id call_id,  
     1046                                        const pj_str_t *mime_type, 
     1047                                        const pj_str_t *content, 
     1048                                        const pjsua_msg_data *msg_data, 
     1049                                        void *user_data) 
     1050{ 
     1051    pjsua_call *call; 
     1052    const pj_str_t mime_text_plain = pj_str("text/plain"); 
     1053    pjsip_media_type ctype; 
     1054    pjsua_im_data *im_data; 
     1055    pjsip_tx_data *tdata; 
     1056    pj_status_t status; 
     1057 
     1058 
     1059    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     1060                     PJ_EINVAL); 
     1061 
     1062    PJSUA_LOCK(); 
     1063 
     1064    call = &pjsua_var.calls[call_id]; 
     1065 
     1066    if (!call->inv) { 
     1067        PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 
     1068        PJSUA_UNLOCK(); 
     1069        return PJSIP_ESESSIONTERMINATED; 
     1070    } 
     1071 
     1072    /* Lock dialog. */ 
     1073    pjsip_dlg_inc_lock(call->inv->dlg); 
     1074 
     1075    /* Set default media type if none is specified */ 
     1076    if (mime_type == NULL) { 
     1077        mime_type = &mime_text_plain; 
     1078    } 
     1079 
     1080    /* Create request message. */ 
     1081    status = pjsip_dlg_create_request( call->inv->dlg, &pjsip_message_method, 
     1082                                       -1, &tdata); 
     1083    if (status != PJ_SUCCESS) { 
     1084        pjsua_perror(THIS_FILE, "Unable to create MESSAGE request", status); 
     1085        goto on_return; 
     1086    } 
     1087 
     1088    /* Add accept header. */ 
     1089    pjsip_msg_add_hdr( tdata->msg,  
     1090                       (pjsip_hdr*)pjsua_im_create_accept(tdata->pool)); 
     1091 
     1092    /* Parse MIME type */ 
     1093    pjsua_parse_media_type(tdata->pool, mime_type, &ctype); 
     1094 
     1095    /* Create "text/plain" message body. */ 
     1096    tdata->msg->body = pjsip_msg_body_create( tdata->pool, &ctype.type, 
     1097                                              &ctype.subtype, content); 
     1098    if (tdata->msg->body == NULL) { 
     1099        pjsua_perror(THIS_FILE, "Unable to create msg body", PJ_ENOMEM); 
     1100        pjsip_tx_data_dec_ref(tdata); 
     1101        goto on_return; 
     1102    } 
     1103 
     1104    /* Add additional headers etc */ 
     1105    pjsua_process_msg_data( tdata, msg_data); 
     1106 
     1107    /* Create IM data and attach to the request. */ 
     1108    im_data = pj_pool_zalloc(tdata->pool, sizeof(*im_data)); 
     1109    im_data->acc_id = call->acc_id; 
     1110    im_data->call_id = call_id; 
     1111    im_data->to = call->inv->dlg->remote.info_str; 
     1112    pj_strdup_with_null(tdata->pool, &im_data->body, content); 
     1113    im_data->user_data = user_data; 
     1114 
     1115 
     1116    /* Send the request. */ 
     1117    status = pjsip_dlg_send_request( call->inv->dlg, tdata,  
     1118                                     pjsua_var.mod.id, im_data); 
     1119    if (status != PJ_SUCCESS) { 
     1120        pjsua_perror(THIS_FILE, "Unable to send MESSAGE request", status); 
     1121        goto on_return; 
     1122    } 
     1123 
     1124on_return: 
     1125    pjsip_dlg_dec_lock(call->inv->dlg); 
     1126    PJSUA_UNLOCK(); 
     1127    return status; 
     1128} 
     1129 
     1130 
     1131/* 
     1132 * Send IM typing indication inside INVITE session. 
     1133 */ 
     1134PJ_DEF(pj_status_t) pjsua_call_send_typing_ind( pjsua_call_id call_id,  
     1135                                                pj_bool_t is_typing, 
     1136                                                const pjsua_msg_data*msg_data) 
     1137{ 
     1138    pjsua_call *call; 
     1139    pjsip_tx_data *tdata; 
     1140    pj_status_t status; 
     1141 
     1142 
     1143    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     1144                     PJ_EINVAL); 
     1145 
     1146    PJSUA_LOCK(); 
     1147 
     1148    call = &pjsua_var.calls[call_id]; 
     1149 
     1150    if (!call->inv) { 
     1151        PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 
     1152        PJSUA_UNLOCK(); 
     1153        return PJSIP_ESESSIONTERMINATED; 
     1154    } 
     1155 
     1156    /* Lock dialog. */ 
     1157    pjsip_dlg_inc_lock(call->inv->dlg); 
     1158     
     1159    /* Create request message. */ 
     1160    status = pjsip_dlg_create_request( call->inv->dlg, &pjsip_message_method, 
     1161                                       -1, &tdata); 
     1162    if (status != PJ_SUCCESS) { 
     1163        pjsua_perror(THIS_FILE, "Unable to create MESSAGE request", status); 
     1164        goto on_return; 
     1165    } 
     1166 
     1167    /* Create "application/im-iscomposing+xml" msg body. */ 
     1168    tdata->msg->body = pjsip_iscomposing_create_body(tdata->pool, is_typing, 
     1169                                                     NULL, NULL, -1); 
     1170 
     1171    /* Add additional headers etc */ 
     1172    pjsua_process_msg_data( tdata, msg_data); 
     1173 
     1174    /* Send the request. */ 
     1175    status = pjsip_dlg_send_request( call->inv->dlg, tdata, -1, NULL); 
     1176    if (status != PJ_SUCCESS) { 
     1177        pjsua_perror(THIS_FILE, "Unable to send MESSAGE request", status); 
     1178        goto on_return; 
     1179    } 
     1180 
     1181on_return: 
     1182    pjsip_dlg_dec_lock(call->inv->dlg); 
     1183    PJSUA_UNLOCK(); 
     1184    return status; 
     1185} 
     1186 
     1187 
     1188/* 
     1189 * Terminate all calls. 
     1190 */ 
     1191PJ_DEF(void) pjsua_call_hangup_all(void) 
     1192{ 
     1193    unsigned i; 
     1194 
     1195    PJSUA_LOCK(); 
     1196 
     1197    for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) { 
     1198        if (pjsua_var.calls[i].inv) 
     1199            pjsua_call_hangup(i, 0, NULL, NULL); 
     1200    } 
     1201 
     1202    PJSUA_UNLOCK(); 
     1203} 
     1204 
     1205 
     1206static const char *good_number(char *buf, pj_int32_t val) 
     1207{ 
     1208    if (val < 1000) { 
     1209        pj_ansi_sprintf(buf, "%d", val); 
     1210    } else if (val < 1000000) { 
     1211        pj_ansi_sprintf(buf, "%d.%dK",  
     1212                        val / 1000, 
     1213                        (val % 1000) / 100); 
     1214    } else { 
     1215        pj_ansi_sprintf(buf, "%d.%02dM",  
     1216                        val / 1000000, 
     1217                        (val % 1000000) / 10000); 
     1218    } 
     1219 
     1220    return buf; 
     1221} 
     1222 
     1223 
     1224/* Dump media session */ 
     1225static void dump_media_session(const char *indent,  
     1226                               char *buf, unsigned maxlen, 
     1227                               pjmedia_session *session) 
     1228{ 
     1229    unsigned i; 
     1230    char *p = buf, *end = buf+maxlen; 
     1231    int len; 
     1232    pjmedia_session_info info; 
     1233 
     1234    pjmedia_session_get_info(session, &info); 
     1235 
     1236    for (i=0; i<info.stream_cnt; ++i) { 
     1237        pjmedia_rtcp_stat stat; 
     1238        const char *rem_addr; 
     1239        int rem_port; 
     1240        const char *dir; 
     1241        char last_update[40]; 
     1242        char packets[16], bytes[16], ipbytes[16]; 
     1243        pj_time_val now; 
     1244 
     1245        pjmedia_session_get_stream_stat(session, i, &stat); 
     1246        rem_addr = pj_inet_ntoa(info.stream_info[i].rem_addr.sin_addr); 
     1247        rem_port = pj_ntohs(info.stream_info[i].rem_addr.sin_port); 
     1248 
     1249        if (info.stream_info[i].dir == PJMEDIA_DIR_ENCODING) 
     1250            dir = "sendonly"; 
     1251        else if (info.stream_info[i].dir == PJMEDIA_DIR_DECODING) 
     1252            dir = "recvonly"; 
     1253        else if (info.stream_info[i].dir == PJMEDIA_DIR_ENCODING_DECODING) 
     1254            dir = "sendrecv"; 
     1255        else 
     1256            dir = "inactive"; 
     1257 
     1258         
     1259        len = pj_ansi_snprintf(buf, end-p,  
     1260                  "%s  #%d %.*s @%dKHz, %s, peer=%s:%d", 
     1261                  indent, i, 
     1262                  info.stream_info[i].fmt.encoding_name.slen, 
     1263                  info.stream_info[i].fmt.encoding_name.ptr, 
     1264                  info.stream_info[i].fmt.clock_rate / 1000, 
     1265                  dir, 
     1266                  rem_addr, rem_port); 
     1267        if (len < 1 || len > end-p) { 
     1268            *p = '\0'; 
     1269            return; 
     1270        } 
     1271 
     1272        p += len; 
     1273        *p++ = '\n'; 
     1274        *p = '\0'; 
     1275 
     1276        if (stat.rx.update_cnt == 0) 
     1277            strcpy(last_update, "never"); 
     1278        else { 
     1279            pj_gettimeofday(&now); 
     1280            PJ_TIME_VAL_SUB(now, stat.rx.update); 
     1281            sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago", 
     1282                    now.sec / 3600, 
     1283                    (now.sec % 3600) / 60, 
     1284                    now.sec % 60, 
     1285                    now.msec); 
     1286        } 
     1287 
     1288        len = pj_ansi_snprintf(p, end-p, 
     1289               "%s     RX pt=%d, stat last update: %s\n" 
     1290               "%s        total %spkt %sB (%sB +IP hdr)\n" 
     1291               "%s        pkt loss=%d (%3.1f%%), dup=%d (%3.1f%%), reorder=%d (%3.1f%%)\n" 
     1292               "%s              (msec)    min     avg     max     last\n" 
     1293               "%s        loss period: %7.3f %7.3f %7.3f %7.3f\n" 
     1294               "%s        jitter     : %7.3f %7.3f %7.3f %7.3f%s", 
     1295               indent, info.stream_info[i].fmt.pt, 
     1296               last_update, 
     1297               indent, 
     1298               good_number(packets, stat.rx.pkt), 
     1299               good_number(bytes, stat.rx.bytes), 
     1300               good_number(ipbytes, stat.rx.bytes + stat.rx.pkt * 32), 
     1301               indent, 
     1302               stat.rx.loss, 
     1303               stat.rx.loss * 100.0 / stat.rx.pkt, 
     1304               stat.rx.dup,  
     1305               stat.rx.dup * 100.0 / stat.rx.pkt, 
     1306               stat.rx.reorder,  
     1307               stat.rx.reorder * 100.0 / stat.rx.pkt, 
     1308               indent, indent, 
     1309               stat.rx.loss_period.min / 1000.0,  
     1310               stat.rx.loss_period.avg / 1000.0,  
     1311               stat.rx.loss_period.max / 1000.0, 
     1312               stat.rx.loss_period.last / 1000.0, 
     1313               indent, 
     1314               stat.rx.jitter.min / 1000.0, 
     1315               stat.rx.jitter.avg / 1000.0, 
     1316               stat.rx.jitter.max / 1000.0, 
     1317               stat.rx.jitter.last / 1000.0, 
     1318               "" 
     1319               ); 
     1320 
     1321        if (len < 1 || len > end-p) { 
     1322            *p = '\0'; 
     1323            return; 
     1324        } 
     1325 
     1326        p += len; 
     1327        *p++ = '\n'; 
     1328        *p = '\0'; 
     1329         
     1330        if (stat.tx.update_cnt == 0) 
     1331            strcpy(last_update, "never"); 
     1332        else { 
     1333            pj_gettimeofday(&now); 
     1334            PJ_TIME_VAL_SUB(now, stat.tx.update); 
     1335            sprintf(last_update, "%02ldh:%02ldm:%02ld.%03lds ago", 
     1336                    now.sec / 3600, 
     1337                    (now.sec % 3600) / 60, 
     1338                    now.sec % 60, 
     1339                    now.msec); 
     1340        } 
     1341 
     1342        len = pj_ansi_snprintf(p, end-p, 
     1343               "%s     TX pt=%d, ptime=%dms, stat last update: %s\n" 
     1344               "%s        total %spkt %sB (%sB +IP hdr)\n" 
     1345               "%s        pkt loss=%d (%3.1f%%), dup=%d (%3.1f%%), reorder=%d (%3.1f%%)\n" 
     1346               "%s              (msec)    min     avg     max     last\n" 
     1347               "%s        loss period: %7.3f %7.3f %7.3f %7.3f\n" 
     1348               "%s        jitter     : %7.3f %7.3f %7.3f %7.3f%s", 
     1349               indent, 
     1350               info.stream_info[i].tx_pt, 
     1351               info.stream_info[i].param->info.frm_ptime * 
     1352                info.stream_info[i].param->setting.frm_per_pkt, 
     1353               last_update, 
     1354 
     1355               indent, 
     1356               good_number(packets, stat.tx.pkt), 
     1357               good_number(bytes, stat.tx.bytes), 
     1358               good_number(ipbytes, stat.tx.bytes + stat.tx.pkt * 32), 
     1359 
     1360               indent, 
     1361               stat.tx.loss, 
     1362               stat.tx.loss * 100.0 / stat.tx.pkt, 
     1363               stat.tx.dup,  
     1364               stat.tx.dup * 100.0 / stat.tx.pkt, 
     1365               stat.tx.reorder,  
     1366               stat.tx.reorder * 100.0 / stat.tx.pkt, 
     1367 
     1368               indent, indent, 
     1369               stat.tx.loss_period.min / 1000.0,  
     1370               stat.tx.loss_period.avg / 1000.0,  
     1371               stat.tx.loss_period.max / 1000.0, 
     1372               stat.tx.loss_period.last / 1000.0, 
     1373               indent, 
     1374               stat.tx.jitter.min / 1000.0, 
     1375               stat.tx.jitter.avg / 1000.0, 
     1376               stat.tx.jitter.max / 1000.0, 
     1377               stat.tx.jitter.last / 1000.0, 
     1378               "" 
     1379               ); 
     1380 
     1381        if (len < 1 || len > end-p) { 
     1382            *p = '\0'; 
     1383            return; 
     1384        } 
     1385 
     1386        p += len; 
     1387        *p++ = '\n'; 
     1388        *p = '\0'; 
     1389 
     1390        len = pj_ansi_snprintf(p, end-p, 
     1391               "%s    RTT msec       : %7.3f %7.3f %7.3f %7.3f",  
     1392               indent, 
     1393               stat.rtt.min / 1000.0, 
     1394               stat.rtt.avg / 1000.0, 
     1395               stat.rtt.max / 1000.0, 
     1396               stat.rtt.last / 1000.0 
     1397               ); 
     1398        if (len < 1 || len > end-p) { 
     1399            *p = '\0'; 
     1400            return; 
     1401        } 
     1402 
     1403        p += len; 
     1404        *p++ = '\n'; 
     1405        *p = '\0'; 
     1406    } 
     1407} 
     1408 
     1409 
     1410/* Print call info */ 
     1411static void print_call(const char *title, 
     1412                       int call_id,  
     1413                       char *buf, pj_size_t size) 
     1414{ 
     1415    int len; 
     1416    pjsip_inv_session *inv = pjsua_var.calls[call_id].inv; 
     1417    pjsip_dialog *dlg = inv->dlg; 
     1418    char userinfo[128]; 
     1419 
     1420    /* Dump invite sesion info. */ 
     1421 
     1422    len = pjsip_hdr_print_on(dlg->remote.info, userinfo, sizeof(userinfo)); 
     1423    if (len < 1) 
     1424        pj_ansi_strcpy(userinfo, "<--uri too long-->"); 
     1425    else 
     1426        userinfo[len] = '\0'; 
     1427     
     1428    len = pj_ansi_snprintf(buf, size, "%s[%s] %s", 
     1429                           title, 
     1430                           pjsip_inv_state_name(inv->state), 
     1431                           userinfo); 
     1432    if (len < 1 || len >= (int)size) { 
     1433        pj_ansi_strcpy(buf, "<--uri too long-->"); 
     1434        len = 18; 
     1435    } else 
     1436        buf[len] = '\0'; 
     1437} 
     1438 
     1439 
     1440/* 
     1441 * Dump call and media statistics to string. 
     1442 */ 
     1443PJ_DEF(pj_status_t) pjsua_call_dump( pjsua_call_id call_id,  
     1444                                     pj_bool_t with_media,  
     1445                                     char *buffer,  
     1446                                     unsigned maxlen, 
     1447                                     const char *indent) 
     1448{ 
     1449    pjsua_call *call; 
     1450    pj_time_val duration, res_delay, con_delay; 
     1451    char tmp[128]; 
     1452    char *p, *end; 
     1453    int len; 
     1454 
     1455    PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 
     1456                     PJ_EINVAL); 
     1457 
     1458    PJSUA_LOCK(); 
     1459 
     1460    call = &pjsua_var.calls[call_id]; 
     1461 
     1462    *buffer = '\0'; 
     1463    p = buffer; 
     1464    end = buffer + maxlen; 
     1465    len = 0; 
     1466 
     1467    if (call->inv == NULL) { 
     1468        PJSUA_UNLOCK(); 
     1469        return PJ_EINVALIDOP; 
     1470    } 
     1471 
     1472    print_call(indent, call_id, tmp, sizeof(tmp)); 
     1473     
     1474    len = pj_ansi_strlen(tmp); 
     1475    pj_ansi_strcpy(buffer, tmp); 
     1476 
     1477    p += len; 
     1478    *p++ = '\r'; 
     1479    *p++ = '\n'; 
     1480 
     1481    /* Calculate call duration */ 
     1482    if (call->inv->state >= PJSIP_INV_STATE_CONFIRMED) { 
     1483        pj_gettimeofday(&duration); 
     1484        PJ_TIME_VAL_SUB(duration, call->conn_time); 
     1485        con_delay = call->conn_time; 
     1486        PJ_TIME_VAL_SUB(con_delay, call->start_time); 
     1487    } else { 
     1488        duration.sec = duration.msec = 0; 
     1489        con_delay.sec = con_delay.msec = 0; 
     1490    } 
     1491 
     1492    /* Calculate first response delay */ 
     1493    if (call->inv->state >= PJSIP_INV_STATE_EARLY) { 
     1494        res_delay = call->res_time; 
     1495        PJ_TIME_VAL_SUB(res_delay, call->start_time); 
     1496    } else { 
     1497        res_delay.sec = res_delay.msec = 0; 
     1498    } 
     1499 
     1500    /* Print duration */ 
     1501    len = pj_ansi_snprintf(p, end-p,  
     1502                           "%s  Call time: %02dh:%02dm:%02ds, " 
     1503                           "1st res in %d ms, conn in %dms", 
     1504                           indent, 
     1505                           (duration.sec / 3600), 
     1506                           ((duration.sec % 3600)/60), 
     1507                           (duration.sec % 60), 
     1508                           PJ_TIME_VAL_MSEC(res_delay),  
     1509                           PJ_TIME_VAL_MSEC(con_delay)); 
     1510     
     1511    if (len > 0 && len < end-p) { 
     1512        p += len; 
     1513        *p++ = '\n'; 
     1514        *p = '\0'; 
     1515    } 
     1516 
     1517    /* Dump session statistics */ 
     1518    if (with_media && call->session) 
     1519        dump_media_session(indent, p, end-p, call->session); 
     1520 
     1521    PJSUA_UNLOCK(); 
     1522 
     1523    return PJ_SUCCESS; 
     1524} 
     1525 
     1526 
     1527/* 
     1528 * Destroy the call's media 
     1529 */ 
     1530static pj_status_t call_destroy_media(int call_id) 
     1531{ 
     1532    pjsua_call *call = &pjsua_var.calls[call_id]; 
     1533 
     1534    if (call->conf_slot != PJSUA_INVALID_ID) { 
     1535        pjmedia_conf_remove_port(pjsua_var.mconf, call->conf_slot); 
     1536        call->conf_slot = PJSUA_INVALID_ID; 
     1537    } 
     1538 
     1539    if (call->session) { 
     1540        /* Destroy session (this will also close RTP/RTCP sockets). */ 
     1541        pjmedia_session_destroy(call->session); 
     1542        call->session = NULL; 
     1543 
     1544        PJ_LOG(4,(THIS_FILE, "Media session for call %d is destroyed",  
     1545                             call_id)); 
     1546 
     1547    } 
     1548 
     1549    call->media_st = PJSUA_CALL_MEDIA_NONE; 
     1550 
     1551    return PJ_SUCCESS; 
     1552} 
     1553 
     1554 
    6261555/* 
    6271556 * This callback receives notification from invite session when the 
     
    6311560                                        pjsip_event *e) 
    6321561{ 
    633     pjsua_call *call = inv->dlg->mod_data[pjsua.mod.id]; 
    634  
    635     if (!call) 
     1562    pjsua_call *call; 
     1563 
     1564    PJSUA_LOCK(); 
     1565 
     1566    call = inv->dlg->mod_data[pjsua_var.mod.id]; 
     1567 
     1568    if (!call) { 
     1569        PJSUA_UNLOCK(); 
    6361570        return; 
     1571    } 
     1572 
    6371573 
    6381574    /* Get call times */ 
     
    6431579                pj_gettimeofday(&call->res_time); 
    6441580            call->last_code = e->body.tsx_state.tsx->status_code; 
     1581            pj_strncpy(&call->last_text,  
     1582                       &e->body.tsx_state.tsx->status_text, 
     1583                       sizeof(call->last_text_buf_)); 
    6451584            break; 
    6461585        case PJSIP_INV_STATE_CONFIRMED: 
     
    6511590            if (e->body.tsx_state.tsx->status_code > call->last_code) { 
    6521591                call->last_code = e->body.tsx_state.tsx->status_code; 
     1592                pj_strncpy(&call->last_text,  
     1593                           &e->body.tsx_state.tsx->status_text, 
     1594                           sizeof(call->last_text_buf_)); 
    6531595            } 
    6541596            break; 
    6551597        default: 
    6561598            call->last_code = e->body.tsx_state.tsx->status_code; 
     1599            pj_strncpy(&call->last_text,  
     1600                       &e->body.tsx_state.tsx->status_text, 
     1601                       sizeof(call->last_text_buf_)); 
    6571602            break; 
    6581603    } 
     
    7171662 
    7181663 
    719     if (pjsua.cb.on_call_state) 
    720         (*pjsua.cb.on_call_state)(call->index, e); 
     1664    if (pjsua_var.ua_cfg.cb.on_call_state) 
     1665        (*pjsua_var.ua_cfg.cb.on_call_state)(call->index, e); 
    7211666 
    7221667    /* call->inv may be NULL now */ 
     
    7301675            call_destroy_media(call->index); 
    7311676 
    732         /* Remove timers. */ 
    733         schedule_call_timer(call, &call->refresh_tm, REFRESH_CALL_TIMER, 0); 
    734         schedule_call_timer(call, &call->hangup_tm, HANGUP_CALL_TIMER, 0); 
    735  
    7361677        /* Free call */ 
    7371678        call->inv = NULL; 
    738         --pjsua.call_cnt; 
    739     } 
    740 } 
    741  
    742  
    743 /* 
    744  * Callback called by event framework when the xfer subscription state 
    745  * has changed. 
    746  */ 
    747 static void xfer_on_evsub_state( pjsip_evsub *sub, pjsip_event *event) 
    748 { 
    749      
    750     PJ_UNUSED_ARG(event); 
    751  
    752     /* 
    753      * We're only interested when subscription is terminated, to  
    754      * clear the xfer_sub member of the inv_data. 
    755      */ 
    756     if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) { 
    757         pjsua_call *call; 
    758  
    759         call = pjsip_evsub_get_mod_data(sub, pjsua.mod.id); 
    760         if (!call) 
    761             return; 
    762  
    763         pjsip_evsub_set_mod_data(sub, pjsua.mod.id, NULL); 
    764         call->xfer_sub = NULL; 
    765  
    766         PJ_LOG(3,(THIS_FILE, "Xfer subscription terminated")); 
    767     } 
    768 } 
    769  
    770  
    771 /* 
    772  * Follow transfer (REFER) request. 
    773  */ 
    774 static void on_call_transfered( pjsip_inv_session *inv, 
    775                                 pjsip_rx_data *rdata ) 
    776 { 
    777     pj_status_t status; 
    778     pjsip_tx_data *tdata; 
    779     pjsua_call *existing_call; 
    780     int new_call; 
    781     const pj_str_t str_refer_to = { "Refer-To", 8}; 
    782     pjsip_generic_string_hdr *refer_to; 
    783     char *uri; 
    784     pj_str_t tmp; 
    785     struct pjsip_evsub_user xfer_cb; 
    786     pjsip_status_code code; 
    787     pjsip_evsub *sub; 
    788  
    789     existing_call = inv->dlg->mod_data[pjsua.mod.id]; 
    790  
    791     /* Find the Refer-To header */ 
    792     refer_to = (pjsip_generic_string_hdr*) 
    793         pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_refer_to, NULL); 
    794  
    795     if (refer_to == NULL) { 
    796         /* Invalid Request. 
    797          * No Refer-To header! 
    798          */ 
    799         PJ_LOG(4,(THIS_FILE, "Received REFER without Refer-To header!")); 
    800         pjsip_dlg_respond( inv->dlg, rdata, 400, NULL, NULL, NULL); 
    801         return; 
    802     } 
    803  
    804     /* Notify callback */ 
    805     code = PJSIP_SC_OK; 
    806     if (pjsua.cb.on_call_transfered) 
    807         (*pjsua.cb.on_call_transfered)(existing_call->index, 
    808                                        &refer_to->hvalue, &code); 
    809  
    810     if (code < 200) 
    811         code = 200; 
    812     if (code >= 300) { 
    813         /* Application rejects call transfer request */ 
    814         pjsip_dlg_respond( inv->dlg, rdata, code, NULL, NULL, NULL); 
    815         return; 
    816     } 
    817  
    818     PJ_LOG(3,(THIS_FILE, "Call to %.*s is being transfered to %.*s", 
    819               (int)inv->dlg->remote.info_str.slen, 
    820               inv->dlg->remote.info_str.ptr, 
    821               (int)refer_to->hvalue.slen,  
    822               refer_to->hvalue.ptr)); 
    823  
    824     /* Init callback */ 
    825     pj_memset(&xfer_cb, 0, sizeof(xfer_cb)); 
    826     xfer_cb.on_evsub_state = &xfer_on_evsub_state; 
    827  
    828     /* Create transferee event subscription */ 
    829     status = pjsip_xfer_create_uas( inv->dlg, &xfer_cb, rdata, &sub); 
    830     if (status != PJ_SUCCESS) { 
    831         pjsua_perror(THIS_FILE, "Unable to create xfer uas", status); 
    832         pjsip_dlg_respond( inv->dlg, rdata, 500, NULL, NULL, NULL); 
    833         return; 
    834     } 
    835  
    836     /* Accept the REFER request, send 200 (OK). */ 
    837     pjsip_xfer_accept(sub, rdata, code, NULL); 
    838  
    839     /* Create initial NOTIFY request */ 
    840     status = pjsip_xfer_notify( sub, PJSIP_EVSUB_STATE_ACTIVE, 
    841                                 100, NULL, &tdata); 
    842     if (status != PJ_SUCCESS) { 
    843         pjsua_perror(THIS_FILE, "Unable to create NOTIFY to REFER", status); 
    844         return; 
    845     } 
    846  
    847     /* Send initial NOTIFY request */ 
    848     status = pjsip_xfer_send_request( sub, tdata); 
    849     if (status != PJ_SUCCESS) { 
    850         pjsua_perror(THIS_FILE, "Unable to send NOTIFY to REFER", status); 
    851         return; 
    852     } 
    853  
    854     /* We're cheating here. 
    855      * We need to get a null terminated string from a pj_str_t. 
    856      * So grab the pointer from the hvalue and NULL terminate it, knowing 
    857      * that the NULL position will be occupied by a newline.  
    858      */ 
    859     uri = refer_to->hvalue.ptr; 
    860     uri[refer_to->hvalue.slen] = '\0'; 
    861  
    862     /* Now make the outgoing call. */ 
    863     tmp = pj_str(uri); 
    864     status = pjsua_call_make_call(existing_call->acc_index, &tmp, &new_call); 
    865     if (status != PJ_SUCCESS) { 
    866  
    867         /* Notify xferer about the error */ 
    868         status = pjsip_xfer_notify(sub, PJSIP_EVSUB_STATE_TERMINATED, 
    869                                    500, NULL, &tdata); 
    870         if (status != PJ_SUCCESS) { 
    871             pjsua_perror(THIS_FILE, "Unable to create NOTIFY to REFER",  
    872                           status); 
    873             return; 
    874         } 
    875         status = pjsip_xfer_send_request(sub, tdata); 
    876         if (status != PJ_SUCCESS) { 
    877             pjsua_perror(THIS_FILE, "Unable to send NOTIFY to REFER",  
    878                           status); 
    879             return; 
    880         } 
    881         return; 
    882     } 
    883  
    884     /* Put the server subscription in inv_data. 
    885      * Subsequent state changed in pjsua_inv_on_state_changed() will be 
    886      * reported back to the server subscription. 
    887      */ 
    888     pjsua.calls[new_call].xfer_sub = sub; 
    889  
    890     /* Put the invite_data in the subscription. */ 
    891     pjsip_evsub_set_mod_data(sub, pjsua.mod.id, &pjsua.calls[new_call]); 
    892 } 
    893  
    894  
    895 /* 
    896  * This callback is called when transaction state has changed in INVITE 
    897  * session. We use this to trap: 
    898  *  - incoming REFER request. 
    899  *  - incoming MESSAGE request. 
    900  */ 
    901 static void pjsua_call_on_tsx_state_changed(pjsip_inv_session *inv, 
    902                                             pjsip_transaction *tsx, 
    903                                             pjsip_event *e) 
    904 { 
    905     pjsua_call *call = inv->dlg->mod_data[pjsua.mod.id]; 
    906  
    907     if (tsx->role==PJSIP_ROLE_UAS && 
    908         tsx->state==PJSIP_TSX_STATE_TRYING && 
    909         pjsip_method_cmp(&tsx->method, &pjsip_refer_method)==0) 
    910     { 
    911         /* 
    912          * Incoming REFER request. 
    913          */ 
    914         on_call_transfered(call->inv, e->body.tsx_state.src.rdata); 
    915  
    916     } 
    917     else if (tsx->role==PJSIP_ROLE_UAS && 
    918              tsx->state==PJSIP_TSX_STATE_TRYING && 
    919              pjsip_method_cmp(&tsx->method, &pjsip_message_method)==0) 
    920     { 
    921         /* 
    922          * Incoming MESSAGE request! 
    923          */ 
    924         pjsip_rx_data *rdata; 
    925         pjsip_msg *msg; 
    926         pjsip_accept_hdr *accept_hdr; 
    927         pj_status_t status; 
    928  
    929         rdata = e->body.tsx_state.src.rdata; 
    930         msg = rdata->msg_info.msg; 
    931  
    932         /* Request MUST have message body, with Content-Type equal to 
    933          * "text/plain". 
    934          */ 
    935         if (pjsua_im_accept_pager(rdata, &accept_hdr) == PJ_FALSE) { 
    936  
    937             pjsip_hdr hdr_list; 
    938  
    939             pj_list_init(&hdr_list); 
    940             pj_list_push_back(&hdr_list, accept_hdr); 
    941  
    942             pjsip_dlg_respond( inv->dlg, rdata, PJSIP_SC_NOT_ACCEPTABLE_HERE,  
    943                                NULL, &hdr_list, NULL ); 
    944             return; 
    945         } 
    946  
    947         /* Respond with 200 first, so that remote doesn't retransmit in case 
    948          * the UI takes too long to process the message.  
    949          */ 
    950         status = pjsip_dlg_respond( inv->dlg, rdata, 200, NULL, NULL, NULL); 
    951  
    952         /* Process MESSAGE request */ 
    953         pjsua_im_process_pager(call->index, &inv->dlg->remote.info_str, 
    954                                &inv->dlg->local.info_str, rdata); 
    955     } 
    956  
    957 } 
    958  
     1679        --pjsua_var.call_cnt; 
     1680    } 
     1681 
     1682    PJSUA_UNLOCK(); 
     1683} 
    9591684 
    9601685/* 
     
    9711696} 
    9721697 
    973  
    974 /* 
    975  * Create inactive SDP for call hold. 
    976  */ 
    977 static pj_status_t create_inactive_sdp(pjsua_call *call, 
    978                                        pjmedia_sdp_session **p_answer) 
    979 { 
    980     pj_status_t status; 
    981     pjmedia_sdp_conn *conn; 
    982     pjmedia_sdp_attr *attr; 
    983     pjmedia_sdp_session *sdp; 
    984  
    985     /* Create new offer */ 
    986     status = pjmedia_endpt_create_sdp(pjsua.med_endpt, pjsua.pool, 1, 
    987                                       &call->skinfo, &sdp); 
    988     if (status != PJ_SUCCESS) { 
    989         pjsua_perror(THIS_FILE, "Unable to create local SDP", status); 
    990         return status; 
    991     } 
    992  
    993     /* Get SDP media connection line */ 
    994     conn = sdp->media[0]->conn; 
    995     if (!conn) 
    996         conn = sdp->conn; 
    997  
    998     /* Modify address */ 
    999     conn->addr = pj_str("0.0.0.0"); 
    1000  
    1001     /* Remove existing directions attributes */ 
    1002     pjmedia_sdp_media_remove_all_attr(sdp->media[0], "sendrecv"); 
    1003     pjmedia_sdp_media_remove_all_attr(sdp->media[0], "sendonly"); 
    1004     pjmedia_sdp_media_remove_all_attr(sdp->media[0], "recvonly"); 
    1005     pjmedia_sdp_media_remove_all_attr(sdp->media[0], "inactive"); 
    1006  
    1007     /* Add inactive attribute */ 
    1008     attr = pjmedia_sdp_attr_create(pjsua.pool, "inactive", NULL); 
    1009     pjmedia_sdp_media_add_attr(sdp->media[0], attr); 
    1010  
    1011     *p_answer = sdp; 
    1012  
    1013     return status; 
    1014 } 
    1015  
    1016 /* 
    1017  * Called when session received new offer. 
    1018  */ 
    1019 static void pjsua_call_on_rx_offer(pjsip_inv_session *inv, 
    1020                                    const pjmedia_sdp_session *offer) 
    1021 { 
    1022     pjsua_call *call; 
    1023     pjmedia_sdp_conn *conn; 
    1024     pjmedia_sdp_session *answer; 
    1025     pj_bool_t is_remote_active; 
    1026     pj_status_t status; 
    1027  
    1028     call = inv->dlg->mod_data[pjsua.mod.id]; 
    1029  
    1030     /* 
    1031      * See if remote is offering active media (i.e. not on-hold) 
    1032      */ 
    1033     is_remote_active = PJ_TRUE; 
    1034  
    1035     conn = offer->media[0]->conn; 
    1036     if (!conn) 
    1037         conn = offer->conn; 
    1038  
    1039     if (pj_strcmp2(&conn->addr, "0.0.0.0")==0 || 
    1040         pj_strcmp2(&conn->addr, "0")==0) 
    1041     { 
    1042         is_remote_active = PJ_FALSE; 
    1043  
    1044     }  
    1045     else if (pjmedia_sdp_media_find_attr2(offer->media[0], "inactive", NULL)) 
    1046     { 
    1047         is_remote_active = PJ_FALSE; 
    1048     } 
    1049  
    1050     PJ_LOG(4,(THIS_FILE, "Received SDP offer, remote media is %s", 
    1051               (is_remote_active ? "active" : "inactive"))); 
    1052  
    1053     /* Supply candidate answer */ 
    1054     if (is_remote_active) { 
    1055         status = pjmedia_endpt_create_sdp( pjsua.med_endpt, call->inv->pool, 1, 
    1056                                            &call->skinfo, &answer); 
    1057     } else { 
    1058         status = create_inactive_sdp( call, &answer ); 
    1059     } 
    1060  
    1061     if (status != PJ_SUCCESS) { 
    1062         pjsua_perror(THIS_FILE, "Unable to create local SDP", status); 
    1063         return; 
    1064     } 
    1065  
    1066     status = pjsip_inv_set_sdp_answer(call->inv, answer); 
    1067     if (status != PJ_SUCCESS) { 
    1068         pjsua_perror(THIS_FILE, "Unable to set answer", status); 
    1069         return; 
    1070     } 
    1071  
    1072 } 
    1073  
    1074 #if 0 
    1075 /* Disconnect call */ 
    1076 static void call_disconnect(pjsip_inv_session *inv, 
    1077                             int st_code) 
    1078 { 
    1079     pjsip_tx_data *tdata; 
    1080     pj_status_t status; 
    1081  
    1082     status = pjsip_inv_end_session(inv, st_code, NULL, &tdata); 
    1083     if (status == PJ_SUCCESS) 
    1084         status = pjsip_inv_send_msg(inv, tdata); 
    1085  
    1086     if (status != PJ_SUCCESS) { 
    1087         pjsua_perror(THIS_FILE, "Unable to disconnect call", status); 
    1088     } 
    1089 } 
    1090 #endif 
    10911698 
    10921699/* 
     
    10981705                                       pj_status_t status) 
    10991706{ 
     1707    int prev_media_st = 0; 
    11001708    pjsua_call *call; 
    11011709    pjmedia_session_info sess_info; 
     
    11061714    char tmp[PJSIP_MAX_URL_SIZE]; 
    11071715 
    1108     call = inv->dlg->mod_data[pjsua.mod.id]; 
     1716    PJSUA_LOCK(); 
     1717 
     1718    call = inv->dlg->mod_data[pjsua_var.mod.id]; 
    11091719 
    11101720    if (status != PJ_SUCCESS) { 
     
    11201730            //call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE); 
    11211731        } 
     1732 
     1733        PJSUA_UNLOCK(); 
    11221734        return; 
    1123  
    11241735    } 
    11251736 
    11261737    /* Destroy existing media session, if any. */ 
    11271738 
    1128     if (call) 
     1739    if (call) { 
     1740        prev_media_st = call->media_st; 
    11291741        call_destroy_media(call->index); 
     1742    } 
    11301743 
    11311744    /* Get local and remote SDP */ 
     
    11371750                     status); 
    11381751        //call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE); 
     1752        PJSUA_UNLOCK(); 
    11391753        return; 
    11401754    } 
     
    11471761                     status); 
    11481762        //call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE); 
     1763        PJSUA_UNLOCK(); 
    11491764        return; 
    11501765    } 
    1151  
    1152     if (pjsua.config.null_audio) 
    1153         return; 
    11541766 
    11551767    /* Create media session info based on SDP parameters.  
     
    11571769     */     
    11581770    status = pjmedia_session_info_from_sdp( call->inv->dlg->pool,  
    1159                                             pjsua.med_endpt,  
     1771                                            pjsua_var.med_endpt,  
    11601772                                            1,&sess_info,  
    11611773                                            local_sdp, remote_sdp); 
     
    11641776                     status); 
    11651777        //call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE); 
     1778        PJSUA_UNLOCK(); 
    11661779        return; 
    11671780    } 
    11681781 
    1169     /* Override ptime, if this option is specified. */ 
    1170     if (pjsua.config.ptime) { 
    1171         sess_info.stream_info[0].param->setting.frm_per_pkt = (pj_uint8_t) 
    1172             (pjsua.config.ptime /  
    1173               sess_info.stream_info[0].param->info.frm_ptime); 
    1174         if (sess_info.stream_info[0].param->setting.frm_per_pkt==0) 
    1175             sess_info.stream_info[0].param->setting.frm_per_pkt = 1; 
    1176     } 
    1177  
    1178     /* Optionally, application may modify other stream settings here 
    1179      * (such as jitter buffer parameters, codec ptime, etc.) 
    1180      */ 
    1181  
    1182     /* Create session based on session info. */ 
    1183     status = pjmedia_session_create( pjsua.med_endpt, &sess_info, 
    1184                                      &call->med_tp, 
    1185                                      call, &call->session ); 
    1186     if (status != PJ_SUCCESS) { 
    1187         pjsua_perror(THIS_FILE, "Unable to create media session",  
    1188                      status); 
    1189         //call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE); 
    1190         return; 
    1191     } 
    1192  
    1193  
    1194     /* Get the port interface of the first stream in the session. 
    1195      * We need the port interface to add to the conference bridge. 
    1196      */ 
    1197     pjmedia_session_get_port(call->session, 0, &media_port); 
    1198  
    1199  
    1200     /* 
    1201      * Add the call to conference bridge. 
    1202      */ 
    1203     port_name.ptr = tmp; 
    1204     port_name.slen = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, 
    1205                                      call->inv->dlg->remote.info->uri, 
    1206                                      tmp, sizeof(tmp)); 
    1207     if (port_name.slen < 1) { 
    1208         port_name = pj_str("call"); 
    1209     } 
    1210     status = pjmedia_conf_add_port( pjsua.mconf, call->inv->pool, 
    1211                                     media_port,  
    1212                                     &port_name, 
    1213                                     &call->conf_slot); 
    1214     if (status != PJ_SUCCESS) { 
    1215         pjsua_perror(THIS_FILE, "Unable to create conference slot",  
    1216                      status); 
    1217         call_destroy_media(call->index); 
    1218         //call_disconnect(inv, PJSIP_SC_INTERNAL_SERVER_ERROR); 
    1219         return; 
    1220     } 
    1221  
    1222     /* If auto-play is configured, connect the call to the file player  
    1223      * port  
    1224      */ 
    1225     if (pjsua.config.auto_play && pjsua.config.wav_file.slen &&  
    1226         call->inv->role == PJSIP_ROLE_UAS)  
     1782    /* Check if media is put on-hold */ 
     1783    if (sess_info.stream_cnt == 0 ||  
     1784        sess_info.stream_info[0].dir == PJMEDIA_DIR_NONE) 
    12271785    { 
    12281786 
    1229         pjmedia_conf_connect_port( pjsua.mconf, pjsua.player[0].slot,  
    1230                                    call->conf_slot, 0); 
    1231  
    1232     } 
    1233     if (pjsua.config.auto_loop && call->inv->role == PJSIP_ROLE_UAS) { 
    1234  
    1235         pjmedia_conf_connect_port( pjsua.mconf, call->conf_slot,  
    1236                                    call->conf_slot, 0); 
    1237  
    1238     } 
    1239     if (pjsua.config.auto_conf) { 
    1240         unsigned i; 
    1241  
    1242         pjmedia_conf_connect_port( pjsua.mconf, 0, call->conf_slot, 0); 
    1243         pjmedia_conf_connect_port( pjsua.mconf, call->conf_slot, 0, 0); 
    1244  
    1245         for (i=0; i < pjsua.config.max_calls; ++i) { 
    1246  
    1247             if (!pjsua.calls[i].session) 
    1248                 continue; 
    1249  
    1250             pjmedia_conf_connect_port( pjsua.mconf, call->conf_slot,  
    1251                                        pjsua.calls[i].conf_slot, 0); 
    1252             pjmedia_conf_connect_port( pjsua.mconf, pjsua.calls[i].conf_slot, 
    1253                                        call->conf_slot, 0); 
     1787        /* Determine who puts the call on-hold */ 
     1788        if (prev_media_st == PJSUA_CALL_MEDIA_ACTIVE) { 
     1789            if (pjmedia_sdp_neg_was_answer_remote(call->inv->neg)) { 
     1790                /* It was local who offer hold */ 
     1791                call->media_st = PJSUA_CALL_MEDIA_LOCAL_HOLD; 
     1792            } else { 
     1793                call->media_st = PJSUA_CALL_MEDIA_REMOTE_HOLD; 
     1794            } 
    12541795        } 
    12551796 
    1256     }  
    1257      
    1258     /* Normal operation: if no auto_xx is given, connect new call to  
    1259      * the sound device port (port zero) in the main conference bridge. 
    1260      */ 
    1261     if (pjsua.config.auto_play == 0 && pjsua.config.auto_loop == 0 && 
    1262         pjsua.config.auto_conf == 0) 
     1797        call->media_dir = PJMEDIA_DIR_NONE; 
     1798 
     1799    } else { 
     1800 
     1801        /* Override ptime, if this option is specified. */ 
     1802        PJ_TODO(set_codec_ptime_in_call); 
     1803 
     1804 
     1805        /* Optionally, application may modify other stream settings here 
     1806         * (such as jitter buffer parameters, codec ptime, etc.) 
     1807         */ 
     1808 
     1809        /* Create session based on session info. */ 
     1810        status = pjmedia_session_create( pjsua_var.med_endpt, &sess_info, 
     1811                                         &call->med_tp, 
     1812                                         call, &call->session ); 
     1813        if (status != PJ_SUCCESS) { 
     1814            pjsua_perror(THIS_FILE, "Unable to create media session",  
     1815                         status); 
     1816            //call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE); 
     1817            PJSUA_UNLOCK(); 
     1818            return; 
     1819        } 
     1820 
     1821 
     1822        /* Get the port interface of the first stream in the session. 
     1823         * We need the port interface to add to the conference bridge. 
     1824         */ 
     1825        pjmedia_session_get_port(call->session, 0, &media_port); 
     1826 
     1827 
     1828        /* 
     1829         * Add the call to conference bridge. 
     1830         */ 
     1831        port_name.ptr = tmp; 
     1832        port_name.slen = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, 
     1833                                         call->inv->dlg->remote.info->uri, 
     1834                                         tmp, sizeof(tmp)); 
     1835        if (port_name.slen < 1) { 
     1836            port_name = pj_str("call"); 
     1837        } 
     1838        status = pjmedia_conf_add_port( pjsua_var.mconf, call->inv->pool, 
     1839                                        media_port,  
     1840                                        &port_name, 
     1841                                        (unsigned*)&call->conf_slot); 
     1842        if (status != PJ_SUCCESS) { 
     1843            pjsua_perror(THIS_FILE, "Unable to create conference slot",  
     1844                         status); 
     1845            call_destroy_media(call->index); 
     1846            //call_disconnect(inv, PJSIP_SC_INTERNAL_SERVER_ERROR); 
     1847            PJSUA_UNLOCK(); 
     1848            return; 
     1849        } 
     1850 
     1851        /* Call's media state is active */ 
     1852        call->media_st = PJSUA_CALL_MEDIA_ACTIVE; 
     1853        call->media_dir = sess_info.stream_info[0].dir; 
     1854    } 
     1855 
     1856    /* Print info. */ 
    12631857    { 
    1264         pjmedia_conf_connect_port( pjsua.mconf, 0, call->conf_slot, 0); 
    1265         pjmedia_conf_connect_port( pjsua.mconf, call->conf_slot, 0, 0); 
    1266     } 
    1267  
    1268  
    1269     /* Done. */ 
    1270     { 
    1271         struct pjmedia_session_info sess_info; 
    12721858        char info[80]; 
    12731859        int info_len = 0; 
    12741860        unsigned i; 
    12751861 
    1276         pjmedia_session_get_info(call->session, &sess_info); 
    12771862        for (i=0; i<sess_info.stream_cnt; ++i) { 
    12781863            int len; 
     
    13051890                info_len += len; 
    13061891        } 
    1307         PJ_LOG(3,(THIS_FILE,"Media started%s", info)); 
    1308     } 
    1309 } 
    1310  
    1311  
    1312 /* 
    1313  * Hangup call. 
    1314  */ 
    1315 PJ_DEF(void) pjsua_call_hangup(int call_index) 
    1316 { 
     1892        PJ_LOG(4,(THIS_FILE,"Media updates%s", info)); 
     1893    } 
     1894 
     1895    /* Call application callback, if any */ 
     1896    if (pjsua_var.ua_cfg.cb.on_call_media_state) 
     1897        pjsua_var.ua_cfg.cb.on_call_media_state(call->index); 
     1898 
     1899 
     1900    PJSUA_UNLOCK(); 
     1901} 
     1902 
     1903 
     1904/* 
     1905 * Create inactive SDP for call hold. 
     1906 */ 
     1907static pj_status_t create_inactive_sdp(pjsua_call *call, 
     1908                                       pjmedia_sdp_session **p_answer) 
     1909{ 
     1910    pj_status_t status; 
     1911    pjmedia_sdp_conn *conn; 
     1912    pjmedia_sdp_attr *attr; 
     1913    pjmedia_sdp_session *sdp; 
     1914 
     1915    /* Create new offer */ 
     1916    status = pjmedia_endpt_create_sdp(pjsua_var.med_endpt, pjsua_var.pool, 1, 
     1917                                      &call->skinfo, &sdp); 
     1918    if (status != PJ_SUCCESS) { 
     1919        pjsua_perror(THIS_FILE, "Unable to create local SDP", status); 
     1920        return status; 
     1921    } 
     1922 
     1923    /* Get SDP media connection line */ 
     1924    conn = sdp->media[0]->conn; 
     1925    if (!conn) 
     1926        conn = sdp->conn; 
     1927 
     1928    /* Modify address */ 
     1929    conn->addr = pj_str("0.0.0.0"); 
     1930 
     1931    /* Remove existing directions attributes */ 
     1932    pjmedia_sdp_media_remove_all_attr(sdp->media[0], "sendrecv"); 
     1933    pjmedia_sdp_media_remove_all_attr(sdp->media[0], "sendonly"); 
     1934    pjmedia_sdp_media_remove_all_attr(sdp->media[0], "recvonly"); 
     1935    pjmedia_sdp_media_remove_all_attr(sdp->media[0], "inactive"); 
     1936 
     1937    /* Add inactive attribute */ 
     1938    attr = pjmedia_sdp_attr_create(pjsua_var.pool, "inactive", NULL); 
     1939    pjmedia_sdp_media_add_attr(sdp->media[0], attr); 
     1940 
     1941    *p_answer = sdp; 
     1942 
     1943    return status; 
     1944} 
     1945 
     1946 
     1947/* 
     1948 * Called when session received new offer. 
     1949 */ 
     1950static void pjsua_call_on_rx_offer(pjsip_inv_session *inv, 
     1951                                   const pjmedia_sdp_session *offer) 
     1952{ 
     1953    const char *remote_state; 
    13171954    pjsua_call *call; 
    1318     int code; 
     1955    pjmedia_sdp_conn *conn; 
     1956    pjmedia_sdp_session *answer; 
     1957    pj_bool_t is_remote_active; 
     1958    pj_status_t status; 
     1959 
     1960    PJSUA_LOCK(); 
     1961 
     1962    call = inv->dlg->mod_data[pjsua_var.mod.id]; 
     1963 
     1964    /* 
     1965     * See if remote is offering active media (i.e. not on-hold) 
     1966     */ 
     1967    is_remote_active = PJ_TRUE; 
     1968 
     1969    conn = offer->media[0]->conn; 
     1970    if (!conn) 
     1971        conn = offer->conn; 
     1972 
     1973    if (pj_strcmp2(&conn->addr, "0.0.0.0")==0 || 
     1974        pj_strcmp2(&conn->addr, "0")==0) 
     1975    { 
     1976        is_remote_active = PJ_FALSE; 
     1977 
     1978    }  
     1979    else if (pjmedia_sdp_media_find_attr2(offer->media[0], "inactive", NULL)) 
     1980    { 
     1981        is_remote_active = PJ_FALSE; 
     1982    } 
     1983 
     1984    remote_state = (is_remote_active ? "active" : "inactive"); 
     1985 
     1986    /* Supply candidate answer */ 
     1987    if (call->media_st == PJSUA_CALL_MEDIA_LOCAL_HOLD || !is_remote_active) { 
     1988        PJ_LOG(4,(THIS_FILE,  
     1989                  "Call %d: RX new media offer, creating inactive SDP " 
     1990                  "(media in offer is %s)", call->index, remote_state)); 
     1991        status = create_inactive_sdp( call, &answer ); 
     1992    } else { 
     1993        PJ_LOG(4,(THIS_FILE, "Call %d: received updated media offer", 
     1994                  call->index)); 
     1995        status = pjmedia_endpt_create_sdp( pjsua_var.med_endpt,  
     1996                                           call->inv->pool, 1, 
     1997                                           &call->skinfo, &answer);      
     1998    } 
     1999 
     2000    if (status != PJ_SUCCESS) { 
     2001        pjsua_perror(THIS_FILE, "Unable to create local SDP", status); 
     2002        PJSUA_UNLOCK(); 
     2003        return; 
     2004    } 
     2005 
     2006    status = pjsip_inv_set_sdp_answer(call->inv, answer); 
     2007    if (status != PJ_SUCCESS) { 
     2008        pjsua_perror(THIS_FILE, "Unable to set answer", status); 
     2009        PJSUA_UNLOCK(); 
     2010        return; 
     2011    } 
     2012 
     2013    PJSUA_UNLOCK(); 
     2014} 
     2015 
     2016 
     2017/* 
     2018 * Callback called by event framework when the xfer subscription state 
     2019 * has changed. 
     2020 */ 
     2021static void xfer_on_evsub_state( pjsip_evsub *sub, pjsip_event *event) 
     2022{ 
     2023     
     2024    PJ_UNUSED_ARG(event); 
     2025 
     2026    /* 
     2027     * We're only interested when subscription is terminated, to  
     2028     * clear the xfer_sub member of the inv_data. 
     2029     */ 
     2030    if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) { 
     2031        pjsua_call *call; 
     2032 
     2033        call = pjsip_evsub_get_mod_data(sub, pjsua_var.mod.id); 
     2034        if (!call) 
     2035            return; 
     2036 
     2037        pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, NULL); 
     2038        call->xfer_sub = NULL; 
     2039 
     2040        PJ_LOG(3,(THIS_FILE, "Xfer subscription terminated")); 
     2041    } 
     2042} 
     2043 
     2044 
     2045/* 
     2046 * Follow transfer (REFER) request. 
     2047 */ 
     2048static void on_call_transfered( pjsip_inv_session *inv, 
     2049                                pjsip_rx_data *rdata ) 
     2050{ 
    13192051    pj_status_t status; 
    13202052    pjsip_tx_data *tdata; 
    1321  
    1322  
    1323     call = &pjsua.calls[call_index]; 
    1324  
    1325     if (!call->inv) { 
    1326         PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 
     2053    pjsua_call *existing_call; 
     2054    int new_call; 
     2055    const pj_str_t str_refer_to = { "Refer-To", 8}; 
     2056    pjsip_generic_string_hdr *refer_to; 
     2057    char *uri; 
     2058    pj_str_t tmp; 
     2059    struct pjsip_evsub_user xfer_cb; 
     2060    pjsip_status_code code; 
     2061    pjsip_evsub *sub; 
     2062 
     2063    existing_call = inv->dlg->mod_data[pjsua_var.mod.id]; 
     2064 
     2065    /* Find the Refer-To header */ 
     2066    refer_to = (pjsip_generic_string_hdr*) 
     2067        pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_refer_to, NULL); 
     2068 
     2069    if (refer_to == NULL) { 
     2070        /* Invalid Request. 
     2071         * No Refer-To header! 
     2072         */ 
     2073        PJ_LOG(4,(THIS_FILE, "Received REFER without Refer-To header!")); 
     2074        pjsip_dlg_respond( inv->dlg, rdata, 400, NULL, NULL, NULL); 
    13272075        return; 
    13282076    } 
    13292077 
    1330     if (call->inv->state == PJSIP_INV_STATE_CONFIRMED) 
    1331         code = PJSIP_SC_OK; 
    1332     else if (call->inv->role == PJSIP_ROLE_UAS) 
    1333         code = PJSIP_SC_DECLINE; 
    1334     else 
    1335         code = PJSIP_SC_REQUEST_TERMINATED; 
    1336  
    1337     status = pjsip_inv_end_session(call->inv, code, NULL, &tdata); 
    1338     if (status != PJ_SUCCESS) { 
    1339         pjsua_perror(THIS_FILE,  
    1340                      "Failed to create end session message",  
    1341                      status); 
     2078    /* Notify callback */ 
     2079    code = PJSIP_SC_OK; 
     2080    if (pjsua_var.ua_cfg.cb.on_call_transfered) 
     2081        (*pjsua_var.ua_cfg.cb.on_call_transfered)(existing_call->index, 
     2082                                                  &refer_to->hvalue, &code); 
     2083 
     2084    if (code < 200) 
     2085        code = 200; 
     2086    if (code >= 300) { 
     2087        /* Application rejects call transfer request */ 
     2088        pjsip_dlg_respond( inv->dlg, rdata, code, NULL, NULL, NULL); 
    13422089        return; 
    13432090    } 
    13442091 
    1345     /* pjsip_inv_end_session may return PJ_SUCCESS with NULL  
    1346      * as p_tdata when INVITE transaction has not been answered 
    1347      * with any provisional responses. 
     2092    PJ_LOG(3,(THIS_FILE, "Call to %.*s is being transfered to %.*s", 
     2093              (int)inv->dlg->remote.info_str.slen, 
     2094              inv->dlg->remote.info_str.ptr, 
     2095              (int)refer_to->hvalue.slen,  
     2096              refer_to->hvalue.ptr)); 
     2097 
     2098    /* Init callback */ 
     2099    pj_memset(&xfer_cb, 0, sizeof(xfer_cb)); 
     2100    xfer_cb.on_evsub_state = &xfer_on_evsub_state; 
     2101 
     2102    /* Create transferee event subscription */ 
     2103    status = pjsip_xfer_create_uas( inv->dlg, &xfer_cb, rdata, &sub); 
     2104    if (status != PJ_SUCCESS) { 
     2105        pjsua_perror(THIS_FILE, "Unable to create xfer uas", status); 
     2106        pjsip_dlg_respond( inv->dlg, rdata, 500, NULL, NULL, NULL); 
     2107        return; 
     2108    } 
     2109 
     2110    /* Accept the REFER request, send 200 (OK). */ 
     2111    pjsip_xfer_accept(sub, rdata, code, NULL); 
     2112 
     2113    /* Create initial NOTIFY request */ 
     2114    status = pjsip_xfer_notify( sub, PJSIP_EVSUB_STATE_ACTIVE, 
     2115                                100, NULL, &tdata); 
     2116    if (status != PJ_SUCCESS) { 
     2117        pjsua_perror(THIS_FILE, "Unable to create NOTIFY to REFER", status); 
     2118        return; 
     2119    } 
     2120 
     2121    /* Send initial NOTIFY request */ 
     2122    status = pjsip_xfer_send_request( sub, tdata); 
     2123    if (status != PJ_SUCCESS) { 
     2124        pjsua_perror(THIS_FILE, "Unable to send NOTIFY to REFER", status); 
     2125        return; 
     2126    } 
     2127 
     2128    /* We're cheating here. 
     2129     * We need to get a null terminated string from a pj_str_t. 
     2130     * So grab the pointer from the hvalue and NULL terminate it, knowing 
     2131     * that the NULL position will be occupied by a newline.  
    13482132     */ 
    1349     if (tdata == NULL) 
     2133    uri = refer_to->hvalue.ptr; 
     2134    uri[refer_to->hvalue.slen] = '\0'; 
     2135 
     2136    /* Now make the outgoing call. */ 
     2137    tmp = pj_str(uri); 
     2138    status = pjsua_call_make_call(existing_call->acc_id, &tmp, 0, 
     2139                                  existing_call->user_data, NULL,  
     2140                                  &new_call); 
     2141    if (status != PJ_SUCCESS) { 
     2142 
     2143        /* Notify xferer about the error */ 
     2144        status = pjsip_xfer_notify(sub, PJSIP_EVSUB_STATE_TERMINATED, 
     2145                                   500, NULL, &tdata); 
     2146        if (status != PJ_SUCCESS) { 
     2147            pjsua_perror(THIS_FILE, "Unable to create NOTIFY to REFER",  
     2148                          status); 
     2149            return; 
     2150        } 
     2151        status = pjsip_xfer_send_request(sub, tdata); 
     2152        if (status != PJ_SUCCESS) { 
     2153            pjsua_perror(THIS_FILE, "Unable to send NOTIFY to REFER",  
     2154                          status); 
     2155            return; 
     2156        } 
    13502157        return; 
    1351  
    1352     status = pjsip_inv_send_msg(call->inv, tdata); 
    1353     if (status != PJ_SUCCESS) { 
    1354         pjsua_perror(THIS_FILE,  
    1355                      "Failed to send end session message",  
    1356                      status); 
    1357         return; 
    1358     } 
    1359 } 
    1360  
    1361  
    1362 /* 
    1363  * Put call on-Hold. 
    1364  */ 
    1365 PJ_DEF(pj_status_t) pjsua_call_set_hold(int call_index) 
    1366 { 
    1367     pjmedia_sdp_session *sdp; 
    1368     pjsua_call *call; 
    1369     pjsip_tx_data *tdata; 
    1370     pj_status_t status; 
    1371  
    1372     call = &pjsua.calls[call_index]; 
    1373      
    1374     if (!call->inv) { 
    1375         PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 
    1376         return PJSIP_ESESSIONTERMINATED; 
    1377     } 
    1378  
    1379     if (call->inv->state != PJSIP_INV_STATE_CONFIRMED) { 
    1380         PJ_LOG(3,(THIS_FILE, "Can not hold call that is not confirmed")); 
    1381         return PJSIP_ESESSIONSTATE; 
    1382     } 
    1383  
    1384     status = create_inactive_sdp(call, &sdp); 
    1385     if (status != PJ_SUCCESS) 
    1386         return status; 
    1387  
    1388     /* Send re-INVITE with new offer */ 
    1389     status = pjsip_inv_reinvite( call->inv, NULL, sdp, &tdata); 
    1390     if (status != PJ_SUCCESS) { 
    1391         pjsua_perror(THIS_FILE, "Unable to create re-INVITE", status); 
    1392         return status; 
    1393     } 
    1394  
    1395     status = pjsip_inv_send_msg( call->inv, tdata); 
    1396     if (status != PJ_SUCCESS) { 
    1397         pjsua_perror(THIS_FILE, "Unable to send re-INVITE", status); 
    1398         return status; 
    1399     } 
    1400  
    1401     return PJ_SUCCESS; 
    1402 } 
    1403  
    1404  
    1405 /* 
    1406  * re-INVITE. 
    1407  */ 
    1408 PJ_DEF(pj_status_t) pjsua_call_reinvite(int call_index) 
    1409 { 
    1410     pjmedia_sdp_session *sdp; 
    1411     pjsip_tx_data *tdata; 
    1412     pjsua_call *call; 
    1413     pj_status_t status; 
    1414  
    1415     call = &pjsua.calls[call_index]; 
    1416  
    1417     if (!call->inv) { 
    1418         PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 
    1419         return PJSIP_ESESSIONTERMINATED; 
    1420     } 
    1421  
    1422  
    1423     if (call->inv->state != PJSIP_INV_STATE_CONFIRMED) { 
    1424         PJ_LOG(3,(THIS_FILE, "Can not re-INVITE call that is not confirmed")); 
    1425         return PJSIP_ESESSIONSTATE; 
    1426     } 
    1427  
    1428     /* Create SDP */ 
    1429     status = pjmedia_endpt_create_sdp( pjsua.med_endpt, call->inv->pool, 1, 
    1430                                        &call->skinfo, &sdp); 
    1431     if (status != PJ_SUCCESS) { 
    1432         pjsua_perror(THIS_FILE, "Unable to get SDP from media endpoint",  
    1433                      status); 
    1434         return status; 
    1435     } 
    1436  
    1437     /* Send re-INVITE with new offer */ 
    1438     status = pjsip_inv_reinvite( call->inv, NULL, sdp, &tdata); 
    1439     if (status != PJ_SUCCESS) { 
    1440         pjsua_perror(THIS_FILE, "Unable to create re-INVITE", status); 
    1441         return status; 
    1442     } 
    1443  
    1444     status = pjsip_inv_send_msg( call->inv, tdata); 
    1445     if (status != PJ_SUCCESS) { 
    1446         pjsua_perror(THIS_FILE, "Unable to send re-INVITE", status); 
    1447         return status; 
    1448     } 
    1449  
    1450     return PJ_SUCCESS; 
    1451 } 
    1452  
    1453  
    1454 /* 
    1455  * Transfer call. 
    1456  */ 
    1457 PJ_DEF(pj_status_t) pjsua_call_xfer(unsigned call_index, const pj_str_t *dest) 
    1458 { 
    1459     pjsip_evsub *sub; 
    1460     pjsip_tx_data *tdata; 
    1461     pjsua_call *call; 
    1462     pj_status_t status; 
    1463  
    1464      
    1465     call = &pjsua.calls[call_index]; 
    1466  
    1467     if (!call->inv) { 
    1468         PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 
    1469         return PJSIP_ESESSIONTERMINATED; 
    1470     } 
    1471     
    1472     /* Create xfer client subscription. 
    1473      * We're not interested in knowing the transfer result, so we 
    1474      * put NULL as the callback. 
     2158    } 
     2159 
     2160    /* Put the server subscription in inv_data. 
     2161     * Subsequent state changed in pjsua_inv_on_state_changed() will be 
     2162     * reported back to the server subscription. 
    14752163     */ 
    1476     status = pjsip_xfer_create_uac(call->inv->dlg, NULL, &sub); 
    1477     if (status != PJ_SUCCESS) { 
    1478         pjsua_perror(THIS_FILE, "Unable to create xfer", status); 
    1479         return status; 
    1480     } 
    1481  
    1482     /* 
    1483      * Create REFER request. 
    1484      */ 
    1485     status = pjsip_xfer_initiate(sub, dest, &tdata); 
    1486     if (status != PJ_SUCCESS) { 
    1487         pjsua_perror(THIS_FILE, "Unable to create REFER request", status); 
    1488         return status; 
    1489     } 
    1490  
    1491     /* Send. */ 
    1492     status = pjsip_xfer_send_request(sub, tdata); 
    1493     if (status != PJ_SUCCESS) { 
    1494         pjsua_perror(THIS_FILE, "Unable to send REFER request", status); 
    1495         return status; 
    1496     } 
    1497  
    1498     /* For simplicity (that's what this program is intended to be!),  
    1499      * leave the original invite session as it is. More advanced application 
    1500      * may want to hold the INVITE, or terminate the invite, or whatever. 
    1501      */ 
    1502  
    1503     return PJ_SUCCESS; 
    1504 } 
    1505  
    1506  
    1507 /** 
    1508  * Dial DTMF. 
    1509  */ 
    1510 PJ_DEF(pj_status_t) pjsua_call_dial_dtmf( unsigned call_index,  
    1511                                           const pj_str_t *digits) 
    1512 { 
    1513     pjsua_call *call = &pjsua.calls[call_index]; 
    1514  
    1515     PJ_ASSERT_RETURN(call_index < pjsua.config.max_calls, PJ_EINVAL); 
    1516  
    1517     if (!call->session) { 
    1518         PJ_LOG(3,(THIS_FILE, "Media is not established yet!")); 
    1519         return -1; 
    1520     } 
    1521  
    1522     return pjmedia_session_dial_dtmf( call->session, 0, digits); 
    1523 } 
    1524  
    1525  
    1526 /** 
    1527  * Send instant messaging inside INVITE session. 
    1528  */ 
    1529 PJ_DEF(pj_status_t) pjsua_call_send_im(int call_index, const pj_str_t *str) 
    1530 { 
    1531     pjsua_call *call; 
    1532     const pj_str_t mime_text = pj_str("text"); 
    1533     const pj_str_t mime_plain = pj_str("plain"); 
    1534     pjsip_tx_data *tdata; 
    1535     pj_status_t status; 
    1536  
    1537     call = &pjsua.calls[call_index]; 
    1538  
    1539     if (!call->inv) { 
    1540         PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 
    1541         return PJSIP_ESESSIONTERMINATED; 
    1542     } 
    1543  
    1544     /* Lock dialog. */ 
    1545     pjsip_dlg_inc_lock(call->inv->dlg); 
    1546      
    1547     /* Create request message. */ 
    1548     status = pjsip_dlg_create_request( call->inv->dlg, &pjsip_message_method, 
    1549                                        -1, &tdata); 
    1550     if (status != PJ_SUCCESS) { 
    1551         pjsua_perror(THIS_FILE, "Unable to create MESSAGE request", status); 
    1552         goto on_return; 
    1553     } 
    1554  
    1555     /* Add accept header. */ 
    1556     pjsip_msg_add_hdr( tdata->msg,  
    1557                        (pjsip_hdr*)pjsua_im_create_accept(tdata->pool)); 
    1558  
    1559     /* Create "text/plain" message body. */ 
    1560     tdata->msg->body = pjsip_msg_body_create( tdata->pool, &mime_text, 
    1561                                               &mime_plain, str); 
    1562     if (tdata->msg->body == NULL) { 
    1563         pjsua_perror(THIS_FILE, "Unable to create msg body", PJ_ENOMEM); 
    1564         pjsip_tx_data_dec_ref(tdata); 
    1565         goto on_return; 
    1566     } 
    1567  
    1568     /* Send the request. */ 
    1569     status = pjsip_dlg_send_request( call->inv->dlg, tdata, -1, NULL); 
    1570     if (status != PJ_SUCCESS) { 
    1571         pjsua_perror(THIS_FILE, "Unable to send MESSAGE request", status); 
    1572         goto on_return; 
    1573     } 
    1574  
    1575 on_return: 
    1576     pjsip_dlg_dec_lock(call->inv->dlg); 
    1577     return status; 
    1578 } 
    1579  
    1580  
    1581 /** 
    1582  * Send IM typing indication inside INVITE session. 
    1583  */ 
    1584 PJ_DEF(pj_status_t) pjsua_call_send_typing_ind(int call_index,  
    1585                                                pj_bool_t is_typing) 
    1586 { 
    1587     pjsua_call *call; 
    1588     pjsip_tx_data *tdata; 
    1589     pj_status_t status; 
    1590  
    1591     call = &pjsua.calls[call_index]; 
    1592  
    1593     if (!call->inv) { 
    1594         PJ_LOG(3,(THIS_FILE,"Call has been disconnected")); 
    1595         return PJSIP_ESESSIONTERMINATED; 
    1596     } 
    1597  
    1598     /* Lock dialog. */ 
    1599     pjsip_dlg_inc_lock(call->inv->dlg); 
    1600      
    1601     /* Create request message. */ 
    1602     status = pjsip_dlg_create_request( call->inv->dlg, &pjsip_message_method, 
    1603                                        -1, &tdata); 
    1604     if (status != PJ_SUCCESS) { 
    1605         pjsua_perror(THIS_FILE, "Unable to create MESSAGE request", status); 
    1606         goto on_return; 
    1607     } 
    1608  
    1609     /* Create "application/im-iscomposing+xml" msg body. */ 
    1610     tdata->msg->body = pjsip_iscomposing_create_body(tdata->pool, is_typing, 
    1611                                                      NULL, NULL, -1); 
    1612  
    1613     /* Send the request. */ 
    1614     status = pjsip_dlg_send_request( call->inv->dlg, tdata, -1, NULL); 
    1615     if (status != PJ_SUCCESS) { 
    1616         pjsua_perror(THIS_FILE, "Unable to send MESSAGE request", status); 
    1617         goto on_return; 
    1618     } 
    1619  
    1620 on_return: 
    1621     pjsip_dlg_dec_lock(call->inv->dlg); 
    1622     return status; 
    1623 } 
    1624  
    1625  
    1626 /* 
    1627  * Terminate all calls. 
    1628  */ 
    1629 PJ_DEF(void) pjsua_call_hangup_all(void) 
    1630 { 
    1631     unsigned i; 
    1632  
    1633     for (i=0; i<pjsua.config.max_calls; ++i) { 
    1634         pjsip_tx_data *tdata; 
    1635         int st_code; 
    1636         pjsua_call *call; 
    1637  
    1638         if (pjsua.calls[i].inv == NULL) 
    1639             continue; 
    1640  
    1641         call = &pjsua.calls[i]; 
    1642  
    1643         if (call->inv->state == PJSIP_INV_STATE_CONFIRMED) { 
    1644             st_code = 200; 
    1645         } else { 
    1646             st_code = PJSIP_SC_GONE; 
     2164    pjsua_var.calls[new_call].xfer_sub = sub; 
     2165 
     2166    /* Put the invite_data in the subscription. */ 
     2167    pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id,  
     2168                             &pjsua_var.calls[new_call]); 
     2169} 
     2170 
     2171 
     2172 
     2173/* 
     2174 * This callback is called when transaction state has changed in INVITE 
     2175 * session. We use this to trap: 
     2176 *  - incoming REFER request. 
     2177 *  - incoming MESSAGE request. 
     2178 */ 
     2179static void pjsua_call_on_tsx_state_changed(pjsip_inv_session *inv, 
     2180                                            pjsip_transaction *tsx, 
     2181                                            pjsip_event *e) 
     2182{ 
     2183    pjsua_call *call = inv->dlg->mod_data[pjsua_var.mod.id]; 
     2184 
     2185    PJSUA_LOCK(); 
     2186 
     2187    if (tsx->role==PJSIP_ROLE_UAS && 
     2188        tsx->state==PJSIP_TSX_STATE_TRYING && 
     2189        pjsip_method_cmp(&tsx->method, &pjsip_refer_method)==0) 
     2190    { 
     2191        /* 
     2192         * Incoming REFER request. 
     2193         */ 
     2194        on_call_transfered(call->inv, e->body.tsx_state.src.rdata); 
     2195 
     2196    } 
     2197    else if (tsx->role==PJSIP_ROLE_UAS && 
     2198             tsx->state==PJSIP_TSX_STATE_TRYING && 
     2199             pjsip_method_cmp(&tsx->method, &pjsip_message_method)==0) 
     2200    { 
     2201        /* 
     2202         * Incoming MESSAGE request! 
     2203         */ 
     2204        pjsip_rx_data *rdata; 
     2205        pjsip_msg *msg; 
     2206        pjsip_accept_hdr *accept_hdr; 
     2207        pj_status_t status; 
     2208 
     2209        rdata = e->body.tsx_state.src.rdata; 
     2210        msg = rdata->msg_info.msg; 
     2211 
     2212        /* Request MUST have message body, with Content-Type equal to 
     2213         * "text/plain". 
     2214         */ 
     2215        if (pjsua_im_accept_pager(rdata, &accept_hdr) == PJ_FALSE) { 
     2216 
     2217            pjsip_hdr hdr_list; 
     2218 
     2219            pj_list_init(&hdr_list); 
     2220            pj_list_push_back(&hdr_list, accept_hdr); 
     2221 
     2222            pjsip_dlg_respond( inv->dlg, rdata, PJSIP_SC_NOT_ACCEPTABLE_HERE,  
     2223                               NULL, &hdr_list, NULL ); 
     2224            PJSUA_UNLOCK(); 
     2225            return; 
    16472226        } 
    16482227 
    1649         if (pjsip_inv_end_session(call->inv, st_code, NULL, &tdata)==0) { 
    1650             if (tdata) 
    1651                 pjsip_inv_send_msg(call->inv, tdata); 
     2228        /* Respond with 200 first, so that remote doesn't retransmit in case 
     2229         * the UI takes too long to process the message.  
     2230         */ 
     2231        status = pjsip_dlg_respond( inv->dlg, rdata, 200, NULL, NULL, NULL); 
     2232 
     2233        /* Process MESSAGE request */ 
     2234        pjsua_im_process_pager(call->index, &inv->dlg->remote.info_str, 
     2235                               &inv->dlg->local.info_str, rdata); 
     2236 
     2237    } 
     2238    else if (tsx->role == PJSIP_ROLE_UAC && 
     2239             pjsip_method_cmp(&tsx->method, &pjsip_message_method)==0) 
     2240    { 
     2241        /* Handle outgoing pager status */ 
     2242        if (tsx->status_code >= 200) { 
     2243            pjsua_im_data *im_data; 
     2244 
     2245            im_data = tsx->mod_data[pjsua_var.mod.id]; 
     2246            /* im_data can be NULL if this is typing indication */ 
     2247 
     2248            if (im_data && pjsua_var.ua_cfg.cb.on_pager_status) { 
     2249                pjsua_var.ua_cfg.cb.on_pager_status(im_data->call_id, 
     2250                                                    &im_data->to, 
     2251                                                    &im_data->body, 
     2252                                                    im_data->user_data, 
     2253                                                    tsx->status_code, 
     2254                                                    &tsx->status_text); 
     2255            } 
    16522256        } 
    16532257    } 
    1654 } 
    1655  
    1656  
    1657 pj_status_t pjsua_call_init(void) 
    1658 { 
    1659     /* Initialize invite session callback. */ 
    1660     pjsip_inv_callback inv_cb; 
    1661     pj_status_t status; 
    1662  
    1663     pj_memset(&inv_cb, 0, sizeof(inv_cb)); 
    1664     inv_cb.on_state_changed = &pjsua_call_on_state_changed; 
    1665     inv_cb.on_new_session = &pjsua_call_on_forked; 
    1666     inv_cb.on_media_update = &pjsua_call_on_media_update; 
    1667     inv_cb.on_rx_offer = &pjsua_call_on_rx_offer; 
    1668     inv_cb.on_tsx_state_changed = &pjsua_call_on_tsx_state_changed; 
    1669  
    1670  
    1671     /* Initialize invite session module: */ 
    1672     status = pjsip_inv_usage_init(pjsua.endpt, &inv_cb); 
    1673      
    1674     return status; 
    1675 } 
    1676  
    1677 /** 
    1678  * Replace media transport. 
    1679  */ 
    1680 PJ_DEF(pj_status_t) pjsua_set_call_media_transport( unsigned call_index, 
    1681                                                     const pjmedia_sock_info *i, 
    1682                                                     pjmedia_transport *tp) 
    1683 { 
    1684     pjsua_call *call = &pjsua.calls[call_index]; 
    1685  
    1686     if (i) 
    1687         pj_memcpy(&call->skinfo, i, sizeof(pjmedia_sock_info)); 
    1688      
    1689     if (call->med_tp) 
    1690         (*call->med_tp->op->destroy)(call->med_tp); 
    1691  
    1692     call->med_tp = tp; 
    1693     return PJ_SUCCESS; 
    1694 } 
     2258 
     2259 
     2260    PJSUA_UNLOCK(); 
     2261} 
Note: See TracChangeset for help on using the changeset viewer.