Ignore:
Timestamp:
Jan 8, 2019 9:43:21 AM (6 years ago)
Author:
riza
Message:

Close #2173: On PJSUA2, application will not be notified when when SDP nego fails due to unsupported codec.

File:
1 edited

Legend:

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

    r5918 r5928  
    10851085} 
    10861086 
     1087pj_status_t create_temp_sdp(pj_pool_t *pool, 
     1088                            const pjmedia_sdp_session *rem_sdp, 
     1089                            pjmedia_sdp_session **p_sdp) 
     1090{ 
     1091    const pj_str_t STR_AUDIO = { "audio", 5 }; 
     1092    const pj_str_t STR_VIDEO = { "video", 5 }; 
     1093    const pj_str_t STR_IP6 = { "IP6", 3}; 
     1094 
     1095    pjmedia_sdp_session *sdp; 
     1096    pj_sockaddr origin; 
     1097    pj_uint16_t tmp_port = 50123; 
     1098    pj_status_t status = PJ_SUCCESS; 
     1099    pj_str_t tmp_st; 
     1100    unsigned i = 0; 
     1101    pj_bool_t sess_use_ipv4 = PJ_TRUE; 
     1102 
     1103    /* Get one address to use in the origin field */ 
     1104    pj_sockaddr_init(PJ_AF_INET, &origin, pj_strset2(&tmp_st, "127.0.0.1"), 0); 
     1105 
     1106    /* Create the base (blank) SDP */ 
     1107    status = pjmedia_endpt_create_base_sdp(pjsua_var.med_endpt, pool, NULL, 
     1108                                           &origin, &sdp); 
     1109    if (status != PJ_SUCCESS) 
     1110        return status; 
     1111 
     1112    if (rem_sdp->conn && pj_stricmp(&rem_sdp->conn->addr_type, &STR_IP6)==0) { 
     1113        sess_use_ipv4 = PJ_FALSE; 
     1114    } 
     1115 
     1116    for (; i< rem_sdp->media_count ; ++i) { 
     1117        pjmedia_sdp_media *m = NULL; 
     1118        pjmedia_sock_info sock_info; 
     1119        pj_bool_t med_use_ipv4 = sess_use_ipv4; 
     1120 
     1121        if (rem_sdp->media[i]->conn &&  
     1122            pj_stricmp(&rem_sdp->media[i]->conn->addr_type, &STR_IP6) == 0)  
     1123        { 
     1124            med_use_ipv4 = PJ_FALSE; 
     1125        } 
     1126 
     1127        pj_sockaddr_init(med_use_ipv4?PJ_AF_INET:PJ_AF_INET6,  
     1128                         &sock_info.rtp_addr_name,  
     1129                         med_use_ipv4?pj_strset2(&tmp_st, "127.0.0.1"): 
     1130                                      pj_strset2(&tmp_st, "::1"),  
     1131                         tmp_port++); 
     1132 
     1133        pj_sockaddr_init(med_use_ipv4?PJ_AF_INET:PJ_AF_INET6,  
     1134                         &sock_info.rtcp_addr_name,  
     1135                         med_use_ipv4?pj_strset2(&tmp_st, "127.0.0.1"): 
     1136                                      pj_strset2(&tmp_st, "::1"),  
     1137                         tmp_port++); 
     1138 
     1139        if (pj_stricmp(&rem_sdp->media[i]->desc.media, &STR_AUDIO)==0) { 
     1140            m = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_media); 
     1141            status = pjmedia_endpt_create_audio_sdp(pjsua_var.med_endpt, 
     1142                                                    pool, &sock_info, 0, &m); 
     1143 
     1144            if (status != PJ_SUCCESS) 
     1145                return status; 
     1146         
     1147        } else if (pj_stricmp(&rem_sdp->media[i]->desc.media, &STR_VIDEO)==0) { 
     1148#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0) 
     1149            m = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_media); 
     1150 
     1151            pj_sockaddr_set_port(&sock_info.rtp_addr_name, ++tmp_port); 
     1152            status = pjmedia_endpt_create_video_sdp(pjsua_var.med_endpt, pool, 
     1153                                                    &sock_info, 0, &m); 
     1154            if (status != PJ_SUCCESS) 
     1155                return status; 
     1156#else        
     1157            m = pjmedia_sdp_media_clone_deactivate(pool, rem_sdp->media[i]); 
     1158#endif       
     1159        } else { 
     1160            m = pjmedia_sdp_media_clone_deactivate(pool, rem_sdp->media[i]); 
     1161        } 
     1162        if (status != PJ_SUCCESS) 
     1163            return status; 
     1164        sdp->media[sdp->media_count++] = m; 
     1165    }       
     1166 
     1167    *p_sdp = sdp; 
     1168    return PJ_SUCCESS; 
     1169} 
     1170 
     1171static pj_status_t verify_request(const pjsua_call *call, 
     1172                                  pjsip_rx_data *rdata, 
     1173                                  pj_bool_t use_tmp_sdp, 
     1174                                  int *sip_err_code, 
     1175                                  pjsip_tx_data **response) 
     1176{ 
     1177    const pjmedia_sdp_session *offer = NULL; 
     1178    pjmedia_sdp_session *answer;     
     1179    int err_code = 0; 
     1180    pj_status_t status; 
     1181     
     1182    /* Get remote SDP offer (if any). */ 
     1183    if (call->inv->neg) 
     1184    { 
     1185        pjmedia_sdp_neg_get_neg_remote(call->inv->neg, &offer); 
     1186    } 
     1187 
     1188    if (use_tmp_sdp) { 
     1189        if (offer == NULL) 
     1190            return PJ_SUCCESS; 
     1191 
     1192        /* Create temporary SDP to check for codec support and capability  
     1193         * to handle the required SIP extensions. 
     1194         */ 
     1195        status = create_temp_sdp(call->inv->pool_prov, offer, &answer); 
     1196 
     1197        if (status != PJ_SUCCESS) { 
     1198            err_code = PJSIP_SC_NOT_ACCEPTABLE_HERE; 
     1199            pjsua_perror(THIS_FILE, "Error creating SDP answer", status); 
     1200        } 
     1201    } else { 
     1202        status = pjsua_media_channel_create_sdp(call->index, 
     1203                                                call->async_call.dlg->pool, 
     1204                                                offer, &answer, sip_err_code); 
     1205 
     1206        if (status != PJ_SUCCESS) { 
     1207            pjsua_perror(THIS_FILE, "Error creating SDP answer", status); 
     1208        } else { 
     1209            status = pjsip_inv_set_local_sdp(call->inv, answer); 
     1210            if (status != PJ_SUCCESS) { 
     1211                pjsua_perror(THIS_FILE, "Error setting local SDP", status); 
     1212                err_code = PJSIP_SC_NOT_ACCEPTABLE_HERE;                 
     1213            } 
     1214        } 
     1215    } 
     1216 
     1217    if (status == PJ_SUCCESS) { 
     1218        unsigned options = 0; 
     1219 
     1220        /* Verify that we can handle the request. */ 
     1221        status = pjsip_inv_verify_request3(rdata, 
     1222                                           call->inv->pool_prov, &options,  
     1223                                           offer, answer, NULL,  
     1224                                           pjsua_var.endpt, response); 
     1225        if (status != PJ_SUCCESS) { 
     1226            /* 
     1227             * No we can't handle the incoming INVITE request. 
     1228             */ 
     1229            if (response) 
     1230                err_code = (*response)->msg->line.status.code; 
     1231            else 
     1232                err_code = PJSIP_ERRNO_TO_SIP_STATUS(status); 
     1233        } 
     1234    } 
     1235    if (sip_err_code) 
     1236        *sip_err_code = err_code; 
     1237 
     1238    return status; 
     1239} 
    10871240 
    10881241/* Incoming call callback when media transport creation is completed. */ 
    10891242static pj_status_t 
    1090 on_incoming_call_med_tp_complete(pjsua_call_id call_id, 
    1091                                  const pjsua_med_tp_state_info *info) 
     1243on_incoming_call_med_tp_complete2(pjsua_call_id call_id, 
     1244                                  const pjsua_med_tp_state_info *info, 
     1245                                  pjsip_rx_data *rdata, 
     1246                                  int *sip_err_code, 
     1247                                  pjsip_tx_data **tdata) 
    10921248{ 
    10931249    pjsua_call *call = &pjsua_var.calls[call_id]; 
    1094     const pjmedia_sdp_session *offer=NULL; 
    1095     pjmedia_sdp_session *answer; 
     1250    pjsip_dialog *dlg = call->async_call.dlg;     
     1251    pj_status_t status = (info? info->status: PJ_SUCCESS); 
     1252    int err_code = (info? info->sip_err_code: 0); 
    10961253    pjsip_tx_data *response = NULL; 
    1097     unsigned options = 0; 
    1098     pjsip_dialog *dlg = call->async_call.dlg; 
    1099     int sip_err_code = (info? info->sip_err_code: 0); 
    1100     pj_status_t status = (info? info->status: PJ_SUCCESS); 
    11011254 
    11021255    PJSUA_LOCK(); 
    1103      
     1256 
     1257    if (sip_err_code) 
     1258        *sip_err_code = err_code; 
     1259 
    11041260    /* Increment the dialog's lock to prevent it to be destroyed prematurely, 
    11051261     * such as in case of transport error. 
     
    11241280    } 
    11251281 
    1126     /* Get remote SDP offer (if any). */ 
    1127     if (call->inv->neg) 
    1128         pjmedia_sdp_neg_get_neg_remote(call->inv->neg, &offer); 
    1129  
    1130     status = pjsua_media_channel_create_sdp(call_id, 
    1131                                             call->async_call.dlg->pool, 
    1132                                             offer, &answer, &sip_err_code); 
    1133     if (status != PJ_SUCCESS) { 
    1134         pjsua_perror(THIS_FILE, "Error creating SDP answer", status); 
    1135         goto on_return; 
    1136     } 
    1137  
    1138     status = pjsip_inv_set_local_sdp(call->inv, answer); 
    1139     if (status != PJ_SUCCESS) { 
    1140         pjsua_perror(THIS_FILE, "Error setting local SDP", status); 
    1141         sip_err_code = PJSIP_SC_NOT_ACCEPTABLE_HERE; 
    1142         goto on_return; 
    1143     } 
    1144  
    1145     /* Verify that we can handle the request. */ 
    1146     status = pjsip_inv_verify_request3(NULL, 
    1147                                        call->inv->pool_prov, &options, offer, 
    1148                                        answer, NULL, pjsua_var.endpt, &response); 
    1149     if (status != PJ_SUCCESS) { 
    1150         /* 
    1151          * No we can't handle the incoming INVITE request. 
    1152          */ 
    1153         sip_err_code = PJSIP_ERRNO_TO_SIP_STATUS(status); 
    1154         goto on_return; 
    1155     } 
     1282    status = verify_request(call, rdata, PJ_FALSE, &err_code, &response); 
    11561283 
    11571284on_return: 
     
    11611288         * will be terminated later, otherwise we end the session here. 
    11621289         */ 
    1163         if (call->inv->state > PJSIP_INV_STATE_NULL) { 
    1164             pjsip_tx_data *tdata; 
    1165             pj_status_t status_; 
    1166  
    1167             status_ = pjsip_inv_end_session(call->inv, sip_err_code, NULL, 
    1168                                             &tdata); 
    1169             if (status_ == PJ_SUCCESS && tdata) 
    1170                 status_ = pjsip_inv_send_msg(call->inv, tdata); 
    1171         } 
    1172  
     1290        if (call->inv->state > PJSIP_INV_STATE_NULL) {             
     1291            pj_status_t status_ = PJ_SUCCESS; 
     1292 
     1293            if (response == NULL) { 
     1294                status_ = pjsip_inv_end_session(call->inv, err_code, NULL, 
     1295                                                &response); 
     1296            } 
     1297 
     1298            if (status_ == PJ_SUCCESS && response) 
     1299                status_ = pjsip_inv_send_msg(call->inv, response); 
     1300        } 
    11731301        pjsua_media_channel_deinit(call->index); 
    11741302    } 
     
    11931321     
    11941322    pjsip_dlg_dec_lock(dlg); 
     1323 
     1324    if (sip_err_code) 
     1325        *sip_err_code = err_code; 
     1326 
     1327    if (tdata) 
     1328        *tdata = response; 
    11951329     
    11961330    PJSUA_UNLOCK(); 
    11971331    return status; 
     1332} 
     1333 
     1334static pj_status_t 
     1335on_incoming_call_med_tp_complete(pjsua_call_id call_id, 
     1336                                 const pjsua_med_tp_state_info *info) 
     1337{ 
     1338    return on_incoming_call_med_tp_complete2(call_id, info, NULL, NULL, NULL); 
    11981339} 
    11991340 
     
    16111752     */ 
    16121753    if (offer || replaced_dlg) { 
     1754 
     1755        /* This is only for initial verification, it will check the SDP for 
     1756         * codec support and the capability to handle the required 
     1757         * SIP extensions. 
     1758         */ 
     1759        status = verify_request(call, rdata, PJ_TRUE, &sip_err_code,  
     1760                                &response); 
     1761 
     1762        if (status != PJ_SUCCESS) { 
     1763            pjsip_dlg_inc_lock(dlg); 
     1764 
     1765            if (response) { 
     1766                pjsip_dlg_send_response(dlg, call->inv->invite_tsx, response); 
     1767 
     1768            } else { 
     1769                pjsip_dlg_respond(dlg, rdata, sip_err_code, NULL, NULL, NULL); 
     1770            } 
     1771                 
     1772            if (call->inv && call->inv->dlg) { 
     1773                pjsip_inv_terminate(call->inv, sip_err_code, PJ_FALSE); 
     1774            } 
     1775            pjsip_dlg_dec_lock(dlg); 
     1776 
     1777            call->inv = NULL; 
     1778            call->async_call.dlg = NULL; 
     1779            goto on_return; 
     1780        } 
    16131781        status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAS, 
    16141782                                          call->secure_level, 
     
    16181786                                          &on_incoming_call_med_tp_complete); 
    16191787        if (status == PJ_SUCCESS) { 
    1620             status = on_incoming_call_med_tp_complete(call_id, NULL); 
    1621             if (status != PJ_SUCCESS) { 
    1622                 sip_err_code = PJSIP_SC_NOT_ACCEPTABLE; 
     1788            status = on_incoming_call_med_tp_complete2(call_id, NULL,  
     1789                                                       rdata, &sip_err_code,  
     1790                                                       &response); 
     1791            if (status != PJ_SUCCESS) {          
    16231792                /* Since the call invite's state is still PJSIP_INV_STATE_NULL, 
    16241793                 * the invite session was not ended in 
     
    16271796                 */ 
    16281797                pjsip_dlg_inc_lock(dlg); 
    1629                 pjsip_dlg_respond(dlg, rdata, sip_err_code, NULL, NULL, NULL); 
     1798 
     1799                if (response) { 
     1800                    pjsip_dlg_send_response(dlg, call->inv->invite_tsx,  
     1801                                            response); 
     1802 
     1803                } else { 
     1804                    pjsip_dlg_respond(dlg, rdata, sip_err_code, NULL, NULL,  
     1805                                      NULL); 
     1806                }                
     1807 
    16301808                if (call->inv && call->inv->dlg) { 
    16311809                    pjsip_inv_terminate(call->inv, sip_err_code, PJ_FALSE); 
     
    17341912     * above) 
    17351913     */ 
    1736     dlg->mod_data[pjsua_var.mod.id] = call; 
    1737     inv->mod_data[pjsua_var.mod.id] = call; 
    1738  
    1739     ++pjsua_var.call_cnt; 
     1914    if (dlg->mod_data[pjsua_var.mod.id] == NULL) { 
     1915        /* In PJSUA2, on_incoming_call() may be called from  
     1916         * on_media_transport_created() hence this might already set 
     1917         * to allow notification about fail events via on_call_state() and 
     1918         * on_call_tsx_state(). 
     1919         */ 
     1920        dlg->mod_data[pjsua_var.mod.id] = call; 
     1921        inv->mod_data[pjsua_var.mod.id] = call; 
     1922        ++pjsua_var.call_cnt; 
     1923    } 
    17401924 
    17411925    /* Check if this request should replace existing call */ 
Note: See TracChangeset for help on using the changeset viewer.