Ignore:
Timestamp:
Feb 21, 2006 11:47:00 PM (18 years ago)
Author:
bennylp
Message:

Implemented major feature: call hold and transfer

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c

    r184 r212  
    201201     * move state to CONFIRMED. 
    202202     */ 
    203     if (method->id == PJSIP_ACK_METHOD && inv && 
    204         inv->state != PJSIP_INV_STATE_CONFIRMED) 
    205     { 
    206         pjsip_event event; 
     203    if (method->id == PJSIP_ACK_METHOD && inv) { 
    207204 
    208205        /* Terminate INVITE transaction, if it's still present. */ 
     
    215212        } 
    216213 
    217         PJSIP_EVENT_INIT_RX_MSG(event, rdata); 
    218         inv_set_state(inv, PJSIP_INV_STATE_CONFIRMED, &event); 
     214        if (inv->state != PJSIP_INV_STATE_CONFIRMED) { 
     215            pjsip_event event; 
     216 
     217            PJSIP_EVENT_INIT_RX_MSG(event, rdata); 
     218            inv_set_state(inv, PJSIP_INV_STATE_CONFIRMED, &event); 
     219        } 
    219220    } 
    220221 
     
    251252     */ 
    252253    if (msg->type == PJSIP_RESPONSE_MSG && msg->line.status.code/100==2 && 
    253         rdata->msg_info.cseq->method.id == PJSIP_INVITE_METHOD) { 
     254        rdata->msg_info.cseq->method.id == PJSIP_INVITE_METHOD && 
     255        inv->invite_tsx == NULL)  
     256    { 
    254257 
    255258        inv_send_ack(inv, rdata); 
     
    866869    pjsip_tx_data *tdata; 
    867870    const pjsip_hdr *hdr; 
     871    pj_bool_t has_sdp; 
    868872    pj_status_t status; 
    869873 
     
    871875    PJ_ASSERT_RETURN(inv && p_tdata, PJ_EINVAL); 
    872876 
    873     /* State MUST be NULL. */ 
    874     PJ_ASSERT_RETURN(inv->state == PJSIP_INV_STATE_NULL, PJ_EINVAL); 
     877    /* State MUST be NULL or CONFIRMED. */ 
     878    PJ_ASSERT_RETURN(inv->state == PJSIP_INV_STATE_NULL || 
     879                     inv->state == PJSIP_INV_STATE_CONFIRMED,  
     880                     PJ_EINVALIDOP); 
    875881 
    876882    /* Create the INVITE request. */ 
     
    880886        return status; 
    881887 
     888    /* If this is the first INVITE, then copy the headers from inv_hdr. 
     889     * These are the headers parsed from the request URI when the 
     890     * dialog was created. 
     891     */ 
     892    if (inv->state == PJSIP_INV_STATE_NULL) { 
     893        hdr = inv->dlg->inv_hdr.next; 
     894 
     895        while (hdr != &inv->dlg->inv_hdr) { 
     896            pjsip_msg_add_hdr(tdata->msg, 
     897                              pjsip_hdr_shallow_clone(tdata->pool, hdr)); 
     898            hdr = hdr->next; 
     899        } 
     900    } 
     901 
     902    /* See if we have SDP to send. */ 
     903    if (inv->neg) { 
     904        pjmedia_sdp_neg_state neg_state; 
     905 
     906        neg_state = pjmedia_sdp_neg_get_state(inv->neg); 
     907 
     908        has_sdp = (neg_state == PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER || 
     909                   (neg_state == PJMEDIA_SDP_NEG_STATE_WAIT_NEGO && 
     910                    pjmedia_sdp_neg_has_local_answer(inv->neg))); 
     911 
     912 
     913    } else { 
     914        has_sdp = PJ_FALSE; 
     915    } 
     916 
    882917    /* Add SDP, if any. */ 
    883     if (inv->neg &&  
    884         pjmedia_sdp_neg_get_state(inv->neg)==PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER) 
    885     { 
     918    if (has_sdp) { 
    886919        const pjmedia_sdp_session *offer; 
    887920 
     
    941974 * Check in incoming message for SDP offer/answer. 
    942975 */ 
    943 static void inv_check_sdp_in_incoming_msg( pjsip_inv_session *inv, 
    944                                            pjsip_transaction *tsx, 
    945                                            pjsip_rx_data *rdata) 
     976static pj_status_t inv_check_sdp_in_incoming_msg( pjsip_inv_session *inv, 
     977                                                  pjsip_transaction *tsx, 
     978                                                  pjsip_rx_data *rdata) 
    946979{ 
    947980    struct tsx_inv_data *tsx_inv_data; 
     
    964997 
    965998    if (tsx_inv_data->sdp_done) 
    966         return; 
     999        return PJ_SUCCESS; 
    9671000 
    9681001    /* Check if SDP is present in the message. */ 
     
    9711004    if (msg->body == NULL) { 
    9721005        /* Message doesn't have body. */ 
    973         return; 
     1006        return PJ_SUCCESS; 
    9741007    } 
    9751008 
     
    9781011    { 
    9791012        /* Message body is not "application/sdp" */ 
    980         return; 
     1013        return PJMEDIA_SDP_EINSDP; 
    9811014    } 
    9821015 
     
    9901023        PJ_LOG(4,(THIS_FILE, "Error parsing SDP in %s: %s", 
    9911024                  pjsip_rx_data_get_info(rdata), errmsg)); 
    992         return; 
     1025        return PJMEDIA_SDP_EINSDP; 
    9931026    } 
    9941027 
     
    10161049            PJ_LOG(4,(THIS_FILE, "Error processing SDP offer in %s: %s", 
    10171050                      pjsip_rx_data_get_info(rdata), errmsg)); 
    1018             return; 
     1051            return PJMEDIA_SDP_EINSDP; 
    10191052        } 
    10201053 
    10211054        /* Inform application about remote offer. */ 
    10221055 
    1023         if (mod_inv.cb.on_rx_offer) 
    1024             (*mod_inv.cb.on_rx_offer)(inv); 
     1056        if (mod_inv.cb.on_rx_offer) { 
     1057 
     1058            (*mod_inv.cb.on_rx_offer)(inv, sdp); 
     1059 
     1060        } 
    10251061 
    10261062    } else if (pjmedia_sdp_neg_get_state(inv->neg) ==  
     
    10421078            PJ_LOG(4,(THIS_FILE, "Error processing SDP answer in %s: %s", 
    10431079                      pjsip_rx_data_get_info(rdata), errmsg)); 
    1044             return; 
     1080            return PJMEDIA_SDP_EINSDP; 
    10451081        } 
    10461082 
     
    10601096    } 
    10611097 
    1062 } 
    1063  
    1064  
    1065  
    1066 /* 
    1067  * Answer initial INVITE. 
     1098    return PJ_SUCCESS; 
     1099} 
     1100 
     1101 
     1102/* 
     1103 * Process INVITE answer, for both initial and subsequent re-INVITE 
     1104 */ 
     1105static pj_status_t process_answer( pjsip_inv_session *inv, 
     1106                                   int st_code, 
     1107                                   pjsip_tx_data *tdata ) 
     1108{ 
     1109    pj_status_t status; 
     1110    pjmedia_sdp_session *sdp = NULL; 
     1111 
     1112    /* Include SDP for 18x and 2xx response.  
     1113     * Also if SDP negotiator is ready, start negotiation. 
     1114     */ 
     1115    if (st_code/10 == 18 || st_code/10 == 20) { 
     1116 
     1117        pjmedia_sdp_neg_state neg_state; 
     1118 
     1119        neg_state = inv->neg ? pjmedia_sdp_neg_get_state(inv->neg) : 
     1120                    PJMEDIA_SDP_NEG_STATE_NULL; 
     1121 
     1122        if (neg_state == PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER) { 
     1123 
     1124            status = pjmedia_sdp_neg_get_neg_local(inv->neg, &sdp); 
     1125 
     1126        } else if (neg_state == PJMEDIA_SDP_NEG_STATE_WAIT_NEGO && 
     1127                   pjmedia_sdp_neg_has_local_answer(inv->neg) ) 
     1128        { 
     1129 
     1130            status = inv_negotiate_sdp(inv); 
     1131            if (status != PJ_SUCCESS) 
     1132                return status; 
     1133             
     1134            status = pjmedia_sdp_neg_get_active_local(inv->neg, &sdp); 
     1135        } 
     1136 
     1137    } 
     1138 
     1139 
     1140 
     1141    /* Include SDP when it's available. 
     1142     * Subsequent response will include this SDP. 
     1143     */ 
     1144    if (sdp) { 
     1145        tdata->msg->body = create_sdp_body(tdata->pool, sdp); 
     1146    } 
     1147 
     1148    /* Remove message body if this is a non-2xx final response */ 
     1149    if (st_code >= 300) 
     1150        tdata->msg->body = NULL; 
     1151 
     1152 
     1153    return PJ_SUCCESS; 
     1154} 
     1155 
     1156 
     1157/* 
     1158 * Answer initial INVITE 
     1159 * Re-INVITE will be answered automatically, and will not use this function. 
    10681160 */  
    10691161PJ_DEF(pj_status_t) pjsip_inv_answer(   pjsip_inv_session *inv, 
     
    10881180     * offer before.  
    10891181     */ 
    1090     if (local_sdp) { 
     1182    if (local_sdp && (st_code/100==1 || st_code/100==2)) { 
    10911183 
    10921184        if (inv->neg == NULL) { 
     
    11091201    } 
    11101202 
     1203 
     1204 
     1205 
     1206    /* Modify last response. */ 
    11111207    last_res = inv->invite_tsx->last_tx; 
    1112  
    1113     /* Modify last response. */ 
    11141208    status = pjsip_dlg_modify_response(inv->dlg, last_res, st_code, st_text); 
    11151209    if (status != PJ_SUCCESS) 
    11161210        return status; 
    11171211 
    1118     /* Include SDP for 18x and 2xx response.  
    1119      * Also if SDP negotiator is ready, start negotiation. 
    1120      */ 
    1121     if (st_code/10 == 18 || st_code/10 == 20) { 
    1122  
    1123         pjmedia_sdp_neg_state neg_state; 
    1124  
    1125         neg_state = inv->neg ? pjmedia_sdp_neg_get_state(inv->neg) : 
    1126                     PJMEDIA_SDP_NEG_STATE_NULL; 
    1127  
    1128         if (neg_state == PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER || 
    1129             neg_state == PJMEDIA_SDP_NEG_STATE_WAIT_NEGO) 
    1130         { 
    1131             const pjmedia_sdp_session *local; 
    1132  
    1133             status = pjmedia_sdp_neg_get_neg_local(inv->neg, &local); 
    1134             if (status == PJ_SUCCESS) 
    1135                 last_res->msg->body = create_sdp_body(last_res->pool, local); 
    1136         } 
    1137  
    1138         /* Start negotiation, if ready. */ 
    1139         if (neg_state == PJMEDIA_SDP_NEG_STATE_WAIT_NEGO) { 
    1140             status = inv_negotiate_sdp(inv); 
    1141             if (status != PJ_SUCCESS) { 
    1142                 pjsip_tx_data_dec_ref(last_res); 
    1143                 return status; 
    1144             } 
    1145         } 
    1146     } 
     1212 
     1213    /* Process SDP in answer */ 
     1214    status = process_answer(inv, st_code, last_res); 
     1215    if (status != PJ_SUCCESS) 
     1216        return status; 
    11471217 
    11481218 
     
    11501220 
    11511221    return PJ_SUCCESS; 
     1222} 
     1223 
     1224 
     1225/* 
     1226 * Set SDP answer. 
     1227 */ 
     1228PJ_DEF(pj_status_t) pjsip_inv_set_sdp_answer( pjsip_inv_session *inv, 
     1229                                              const pjmedia_sdp_session *sdp ) 
     1230{ 
     1231    pj_status_t status; 
     1232 
     1233    PJ_ASSERT_RETURN(inv && sdp, PJ_EINVAL); 
     1234 
     1235    pjsip_dlg_inc_lock(inv->dlg); 
     1236    status = pjmedia_sdp_neg_set_local_answer( inv->pool, inv->neg, sdp); 
     1237    pjsip_dlg_dec_lock(inv->dlg); 
     1238 
     1239    return status; 
    11521240} 
    11531241 
     
    12061294            PJ_ASSERT_RETURN(tdata != NULL, PJ_EINVALIDOP); 
    12071295 
    1208             status = pjsip_dlg_modify_response(inv->dlg, tdata, st_code, 
    1209                                                st_text); 
     1296            //status = pjsip_dlg_modify_response(inv->dlg, tdata, st_code, 
     1297            //                                 st_text); 
     1298            status = pjsip_inv_answer(inv, st_code, st_text, NULL, &tdata); 
    12101299        } 
    12111300        break; 
     
    12481337                                        pjsip_tx_data **p_tdata ) 
    12491338{ 
    1250     PJ_UNUSED_ARG(inv); 
    1251     PJ_UNUSED_ARG(new_contact); 
    1252     PJ_UNUSED_ARG(new_offer); 
    1253     PJ_UNUSED_ARG(p_tdata); 
    1254  
    1255     PJ_TODO(CREATE_REINVITE_REQUEST); 
    1256     return PJ_ENOTSUP; 
     1339    pj_status_t status; 
     1340    pjsip_contact_hdr *contact_hdr = NULL; 
     1341 
     1342    /* Check arguments. */ 
     1343    PJ_ASSERT_RETURN(inv && p_tdata, PJ_EINVAL); 
     1344 
     1345    /* Must NOT have a pending INVITE transaction */ 
     1346    PJ_ASSERT_RETURN(inv->invite_tsx==NULL, PJ_EINVALIDOP); 
     1347 
     1348 
     1349    pjsip_dlg_inc_lock(inv->dlg); 
     1350 
     1351    if (new_contact) { 
     1352        pj_str_t tmp; 
     1353        const pj_str_t STR_CONTACT = { "Contact", 7 }; 
     1354 
     1355        pj_strdup_with_null(inv->dlg->pool, &tmp, new_contact); 
     1356        contact_hdr = pjsip_parse_hdr(inv->dlg->pool, &STR_CONTACT,  
     1357                                      tmp.ptr, tmp.slen, NULL); 
     1358        if (!contact_hdr) { 
     1359            status = PJSIP_EINVALIDURI; 
     1360            goto on_return; 
     1361        } 
     1362    } 
     1363 
     1364 
     1365    if (new_offer) { 
     1366        if (!inv->neg) { 
     1367            status = pjmedia_sdp_neg_create_w_local_offer(inv->pool, new_offer, 
     1368                                                          &inv->neg); 
     1369            if (status != PJ_SUCCESS) 
     1370                goto on_return; 
     1371 
     1372        } else switch (pjmedia_sdp_neg_get_state(inv->neg)) { 
     1373 
     1374            case PJMEDIA_SDP_NEG_STATE_NULL: 
     1375                pj_assert(!"Unexpected SDP neg state NULL"); 
     1376                status = PJ_EBUG; 
     1377                goto on_return; 
     1378 
     1379            case PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER: 
     1380                PJ_LOG(4,(inv->obj_name,  
     1381                          "pjsip_inv_reinvite: already have an offer, new " 
     1382                          "offer is ignored")); 
     1383                break; 
     1384 
     1385            case PJMEDIA_SDP_NEG_STATE_REMOTE_OFFER: 
     1386                status = pjmedia_sdp_neg_set_local_answer(inv->pool, inv->neg, 
     1387                                                          new_offer); 
     1388                if (status != PJ_SUCCESS) 
     1389                    goto on_return; 
     1390                break; 
     1391 
     1392            case PJMEDIA_SDP_NEG_STATE_WAIT_NEGO: 
     1393                PJ_LOG(4,(inv->obj_name,  
     1394                          "pjsip_inv_reinvite: SDP in WAIT_NEGO state, new " 
     1395                          "offer is ignored")); 
     1396                break; 
     1397 
     1398            case PJMEDIA_SDP_NEG_STATE_DONE: 
     1399                status = pjmedia_sdp_neg_modify_local_offer(inv->pool,inv->neg, 
     1400                                                            new_offer); 
     1401                if (status != PJ_SUCCESS) 
     1402                    goto on_return; 
     1403                break; 
     1404        } 
     1405    } 
     1406 
     1407    if (contact_hdr) 
     1408        inv->dlg->local.contact = contact_hdr; 
     1409 
     1410    status = pjsip_inv_invite(inv, p_tdata); 
     1411 
     1412on_return: 
     1413    pjsip_dlg_dec_lock(inv->dlg); 
     1414    return status; 
    12571415} 
    12581416 
     
    19092067 
    19102068    } 
     2069    else if (tsx->method.id == PJSIP_INVITE_METHOD && 
     2070             tsx->role == PJSIP_ROLE_UAS) 
     2071    { 
     2072 
     2073        /* 
     2074         * Handle incoming re-INVITE 
     2075         */ 
     2076        if (tsx->state == PJSIP_TSX_STATE_TRYING) { 
     2077             
     2078            pjsip_rx_data *rdata = e->body.tsx_state.src.rdata; 
     2079            pjsip_tx_data *tdata; 
     2080            pj_status_t status; 
     2081 
     2082            /* Check if we have INVITE pending. */ 
     2083            if (inv->invite_tsx && inv->invite_tsx!=tsx) { 
     2084 
     2085                /* Can not receive re-INVITE while another one is pending. */ 
     2086                status = pjsip_dlg_create_response( inv->dlg, rdata, 500, NULL, 
     2087                                                    &tdata); 
     2088                if (status != PJ_SUCCESS) 
     2089                    return; 
     2090 
     2091                status = pjsip_dlg_send_response( inv->dlg, tsx, tdata); 
     2092                 
     2093 
     2094                return; 
     2095            } 
     2096 
     2097            /* Save the invite transaction. */ 
     2098            inv->invite_tsx = tsx; 
     2099 
     2100            /* Process SDP in incoming message. */ 
     2101            status = inv_check_sdp_in_incoming_msg(inv, tsx, rdata); 
     2102 
     2103            if (status != PJ_SUCCESS) { 
     2104 
     2105                /* Not Acceptable */ 
     2106                const pjsip_hdr *accept; 
     2107 
     2108                status = pjsip_dlg_create_response(inv->dlg, rdata,  
     2109                                                   488, NULL, &tdata); 
     2110                if (status != PJ_SUCCESS) 
     2111                    return; 
     2112 
     2113 
     2114                accept = pjsip_endpt_get_capability(dlg->endpt, PJSIP_H_ACCEPT, 
     2115                                                    NULL); 
     2116                if (accept) { 
     2117                    pjsip_msg_add_hdr(tdata->msg, 
     2118                                      pjsip_hdr_clone(tdata->pool, accept)); 
     2119                } 
     2120 
     2121                status = pjsip_dlg_send_response(dlg, tsx, tdata); 
     2122 
     2123                return; 
     2124            } 
     2125 
     2126            /* Create 2xx ANSWER */ 
     2127            status = pjsip_dlg_create_response(dlg, rdata, 200, NULL, &tdata); 
     2128            if (status != PJ_SUCCESS) 
     2129                return; 
     2130 
     2131            /* Process SDP in the answer */ 
     2132            status = process_answer(inv, 200, tdata); 
     2133            if (status != PJ_SUCCESS) 
     2134                return; 
     2135 
     2136            status = pjsip_inv_send_msg(inv, tdata, NULL); 
     2137 
     2138        } 
     2139 
     2140    } 
     2141    else if (tsx->method.id == PJSIP_INVITE_METHOD && 
     2142             tsx->role == PJSIP_ROLE_UAC) 
     2143    { 
     2144        /* 
     2145         * Handle outgoing re-INVITE 
     2146         */ 
     2147        if (tsx->state == PJSIP_TSX_STATE_TERMINATED && 
     2148            tsx->status_code/100 == 2)  
     2149        { 
     2150 
     2151            /* Re-INVITE was accepted. */ 
     2152 
     2153            /* Process SDP */ 
     2154            inv_check_sdp_in_incoming_msg(inv, tsx,  
     2155                                          e->body.tsx_state.src.rdata); 
     2156 
     2157            /* Send ACK */ 
     2158            inv_send_ack(inv, e->body.tsx_state.src.rdata); 
     2159 
     2160        } else if (tsx->state == PJSIP_TSX_STATE_COMPLETED && 
     2161                   (tsx->status_code==401 || tsx->status_code==407)) 
     2162        { 
     2163            pjsip_tx_data *tdata; 
     2164            pj_status_t status; 
     2165 
     2166            /* Handle authentication challenge. */ 
     2167            status = pjsip_auth_clt_reinit_req( &dlg->auth_sess, 
     2168                                                e->body.tsx_state.src.rdata, 
     2169                                                tsx->last_tx, 
     2170                                                &tdata); 
     2171            if (status != PJ_SUCCESS) 
     2172                return; 
     2173 
     2174            /* Send re-INVITE */ 
     2175            status = pjsip_inv_send_msg( inv, tdata, NULL); 
     2176 
     2177        } else if (tsx->status_code==PJSIP_SC_CALL_TSX_DOES_NOT_EXIST || 
     2178                   tsx->status_code==PJSIP_SC_REQUEST_TIMEOUT || 
     2179                   tsx->status_code >= 700) 
     2180        { 
     2181            /* 
     2182             * Handle responses that terminates dialog. 
     2183             */ 
     2184            inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); 
     2185        } 
     2186    } 
    19112187} 
    19122188 
Note: See TracChangeset for help on using the changeset viewer.