Changeset 2191


Ignore:
Timestamp:
Aug 4, 2008 3:01:38 PM (16 years ago)
Author:
nanang
Message:

Ticket #563: Updated SDP offer/answer related to call hold scenario to conform to RFC 3264 section 8.4 (before: 'a=inactive' and 'c=0.0.0.0', now: 'a=sendonly' and muted ports).

Location:
pjproject/trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c

    r2176 r2191  
    22112211    ring_stop(call_id); 
    22122212 
    2213     if (call_info.media_status == PJSUA_CALL_MEDIA_ACTIVE) { 
     2213    /* Connect ports appropriately when media status is ACTIVE or REMOTE HOLD, 
     2214     * otherwise we should NOT connect the ports. 
     2215     */ 
     2216    if (call_info.media_status == PJSUA_CALL_MEDIA_ACTIVE || 
     2217        call_info.media_status == PJSUA_CALL_MEDIA_REMOTE_HOLD) 
     2218    { 
    22142219        pj_bool_t connect_sound = PJ_TRUE; 
    22152220 
     
    22792284            } 
    22802285        } 
    2281  
     2286    } 
     2287 
     2288    /* Handle media status */ 
     2289    switch (call_info.media_status) { 
     2290    case PJSUA_CALL_MEDIA_ACTIVE: 
    22822291        PJ_LOG(3,(THIS_FILE, "Media for call %d is active", call_id)); 
    2283  
    2284     } else if (call_info.media_status == PJSUA_CALL_MEDIA_LOCAL_HOLD) { 
     2292        break; 
     2293 
     2294    case PJSUA_CALL_MEDIA_LOCAL_HOLD: 
    22852295        PJ_LOG(3,(THIS_FILE, "Media for call %d is suspended (hold) by local", 
    22862296                  call_id)); 
    2287     } else if (call_info.media_status == PJSUA_CALL_MEDIA_REMOTE_HOLD) { 
     2297        break; 
     2298 
     2299    case PJSUA_CALL_MEDIA_REMOTE_HOLD: 
    22882300        PJ_LOG(3,(THIS_FILE,  
    22892301                  "Media for call %d is suspended (hold) by remote", 
    22902302                  call_id)); 
    2291     } else if (call_info.media_status == PJSUA_CALL_MEDIA_ERROR) { 
    2292         pj_str_t reason = pj_str("ICE negotiation failed"); 
    2293  
    2294         PJ_LOG(1,(THIS_FILE, 
     2303        break; 
     2304 
     2305    case PJSUA_CALL_MEDIA_ERROR: 
     2306        PJ_LOG(3,(THIS_FILE, 
    22952307                  "Media has reported error, disconnecting call")); 
    2296  
    2297         pjsua_call_hangup(call_id, 500, &reason, NULL); 
    2298  
    2299     } else { 
     2308        { 
     2309            pj_str_t reason = pj_str("ICE negotiation failed"); 
     2310            pjsua_call_hangup(call_id, 500, &reason, NULL); 
     2311        } 
     2312        break; 
     2313 
     2314    case PJSUA_CALL_MEDIA_NONE: 
    23002315        PJ_LOG(3,(THIS_FILE,  
    23012316                  "Media for call %d is inactive", 
    23022317                  call_id)); 
     2318        break; 
     2319 
     2320    default: 
     2321        pj_assert(!"Unhandled media status"); 
     2322        break; 
    23032323    } 
    23042324} 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h

    r2162 r2191  
    6161    pjsua_acc_id         acc_id;    /**< Account index being used.          */ 
    6262    int                  secure_level;/**< Signaling security level.        */ 
     63    pj_bool_t            local_hold;/**< Flag for call-hold by local.       */ 
    6364    pjsua_call_media_status media_st;/**< Media state.                      */ 
    6465    pjmedia_dir          media_dir; /**< Media direction.                   */ 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c

    r2152 r2191  
    6767 
    6868 
    69  
    70 /* Create inactive SDP for call hold. */ 
    71 static pj_status_t create_inactive_sdp(pjsua_call *call, 
    72                                        pjmedia_sdp_session **p_answer); 
     69/* Create SDP for call hold. */ 
     70static pj_status_t create_sdp_of_call_hold(pjsua_call *call, 
     71                                           pjmedia_sdp_session **p_answer); 
    7372 
    7473/* Update SDP version in the offer */ 
     
    118117    call->rem_nat_type = PJ_STUN_NAT_TYPE_UNKNOWN; 
    119118    call->rem_srtp_use = PJMEDIA_SRTP_DISABLED; 
     119    call->local_hold = PJ_FALSE; 
    120120} 
    121121 
     
    14271427    } 
    14281428 
    1429     status = create_inactive_sdp(call, &sdp); 
     1429    status = create_sdp_of_call_hold(call, &sdp); 
    14301430    if (status != PJ_SUCCESS) { 
    14311431        pjsip_dlg_dec_lock(dlg); 
     
    14531453        return status; 
    14541454    } 
     1455 
     1456    /* Set flag that local put the call on hold */ 
     1457    call->local_hold = PJ_TRUE; 
    14551458 
    14561459    pjsip_dlg_dec_lock(dlg); 
     
    14881491 
    14891492    /* Create SDP */ 
    1490     PJ_UNUSED_ARG(unhold); 
    1491     PJ_TODO(create_active_inactive_sdp_based_on_unhold_arg); 
    1492     status = pjsua_media_channel_create_sdp(call->index, call->inv->pool,  
    1493                                             NULL, &sdp, NULL); 
     1493    if (call->local_hold && !unhold) { 
     1494        status = create_sdp_of_call_hold(call, &sdp); 
     1495    } else { 
     1496        status = pjsua_media_channel_create_sdp(call->index, call->inv->pool,  
     1497                                                NULL, &sdp, NULL); 
     1498        call->local_hold = PJ_FALSE; 
     1499    } 
    14941500    if (status != PJ_SUCCESS) { 
    14951501        pjsua_perror(THIS_FILE, "Unable to get SDP from media endpoint",  
     
    15741580    status = pjsip_inv_send_msg( call->inv, tdata); 
    15751581    if (status != PJ_SUCCESS) { 
    1576         pjsua_perror(THIS_FILE, "Unable to send UPDAT Erequest", status); 
     1582        pjsua_perror(THIS_FILE, "Unable to send UPDATE request", status); 
    15771583        pjsip_dlg_dec_lock(dlg); 
    15781584        return status; 
    15791585    } 
     1586 
     1587    call->local_hold = PJ_FALSE; 
    15801588 
    15811589    pjsip_dlg_dec_lock(dlg); 
     
    30133021 
    30143022 
    3015 /* 
    3016  * Create inactive SDP for call hold. 
    3017  */ 
    3018 static pj_status_t create_inactive_sdp(pjsua_call *call, 
    3019                                        pjmedia_sdp_session **p_answer) 
     3023/* Create SDP for call hold. */ 
     3024static pj_status_t create_sdp_of_call_hold(pjsua_call *call, 
     3025                                           pjmedia_sdp_session **p_answer) 
    30203026{ 
    30213027    pj_status_t status; 
    30223028    pj_pool_t *pool; 
    3023     pjmedia_sdp_conn *conn; 
    3024     pjmedia_sdp_attr *attr; 
    3025     pjmedia_transport_info tp_info; 
    30263029    pjmedia_sdp_session *sdp; 
    30273030 
     
    30293032    pool = call->inv->pool; 
    30303033 
    3031     /* Get media socket info */ 
    3032     pjmedia_transport_info_init(&tp_info); 
    3033     pjmedia_transport_get_info(call->med_tp, &tp_info); 
    3034  
    30353034    /* Create new offer */ 
    3036     status = pjmedia_endpt_create_sdp(pjsua_var.med_endpt, pool, 1, 
    3037                                       &tp_info.sock_info, &sdp); 
     3035    status = pjsua_media_channel_create_sdp(call->index, pool, NULL, &sdp,  
     3036                                            NULL); 
    30383037    if (status != PJ_SUCCESS) { 
    30393038        pjsua_perror(THIS_FILE, "Unable to create local SDP", status); 
     
    30413040    } 
    30423041 
    3043     /* Get SDP media connection line */ 
    3044     conn = sdp->media[0]->conn; 
    3045     if (!conn) 
    3046         conn = sdp->conn; 
    3047  
    3048     /* Modify address */ 
    3049     conn->addr = pj_str("0.0.0.0"); 
    3050  
    3051     /* Remove existing directions attributes */ 
    3052     pjmedia_sdp_media_remove_all_attr(sdp->media[0], "sendrecv"); 
    3053     pjmedia_sdp_media_remove_all_attr(sdp->media[0], "sendonly"); 
    3054     pjmedia_sdp_media_remove_all_attr(sdp->media[0], "recvonly"); 
    3055     pjmedia_sdp_media_remove_all_attr(sdp->media[0], "inactive"); 
    3056  
    3057     /* Add inactive attribute */ 
    3058     attr = pjmedia_sdp_attr_create(pool, "inactive", NULL); 
    3059     pjmedia_sdp_media_add_attr(sdp->media[0], attr); 
     3042    /* Call-hold is done by set the media direction to 'sendonly'  
     3043     * (PJMEDIA_DIR_ENCODING), except when current media direction is  
     3044     * 'inactive' (PJMEDIA_DIR_NONE). 
     3045     * (See RFC 3264 Section 8.4 and RFC 4317 Section 3.1) 
     3046     */ 
     3047    if (call->media_dir != PJMEDIA_DIR_ENCODING) { 
     3048        pjmedia_sdp_attr *attr; 
     3049 
     3050        /* Remove existing directions attributes */ 
     3051        pjmedia_sdp_media_remove_all_attr(sdp->media[0], "sendrecv"); 
     3052        pjmedia_sdp_media_remove_all_attr(sdp->media[0], "sendonly"); 
     3053        pjmedia_sdp_media_remove_all_attr(sdp->media[0], "recvonly"); 
     3054        pjmedia_sdp_media_remove_all_attr(sdp->media[0], "inactive"); 
     3055 
     3056        if (call->media_dir == PJMEDIA_DIR_ENCODING_DECODING) { 
     3057            /* Add sendonly attribute */ 
     3058            attr = pjmedia_sdp_attr_create(pool, "sendonly", NULL); 
     3059            pjmedia_sdp_media_add_attr(sdp->media[0], attr); 
     3060        } else { 
     3061            /* Add inactive attribute */ 
     3062            attr = pjmedia_sdp_attr_create(pool, "inactive", NULL); 
     3063            pjmedia_sdp_media_add_attr(sdp->media[0], attr); 
     3064        } 
     3065    } 
    30603066 
    30613067    *p_answer = sdp; 
     
    30633069    return status; 
    30643070} 
    3065  
    30663071 
    30673072/* 
     
    30713076                                   const pjmedia_sdp_session *offer) 
    30723077{ 
    3073     const char *remote_state; 
    30743078    pjsua_call *call; 
    30753079    pjmedia_sdp_conn *conn; 
    30763080    pjmedia_sdp_session *answer; 
    3077     pj_bool_t is_remote_active; 
    30783081    pj_status_t status; 
    30793082 
     
    30813084 
    30823085    call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id]; 
    3083  
    3084     /* 
    3085      * See if remote is offering active media (i.e. not on-hold) 
    3086      */ 
    3087     is_remote_active = PJ_TRUE; 
    30883086 
    30893087    conn = offer->media[0]->conn; 
     
    30913089        conn = offer->conn; 
    30923090 
     3091    /* Supply candidate answer */ 
     3092    PJ_LOG(4,(THIS_FILE, "Call %d: received updated media offer", 
     3093              call->index)); 
     3094 
     3095    status = pjsua_media_channel_create_sdp(call->index, call->inv->pool,  
     3096                                            offer, &answer, NULL); 
     3097    if (status != PJ_SUCCESS) { 
     3098        pjsua_perror(THIS_FILE, "Unable to create local SDP", status); 
     3099        PJSUA_UNLOCK(); 
     3100        return; 
     3101    } 
     3102 
     3103    /* Check if offer's conn address is zero */ 
    30933104    if (pj_strcmp2(&conn->addr, "0.0.0.0")==0 || 
    30943105        pj_strcmp2(&conn->addr, "0")==0) 
    30953106    { 
    3096         is_remote_active = PJ_FALSE; 
    3097  
    3098     }  
    3099     else if (pjmedia_sdp_media_find_attr2(offer->media[0], "inactive", NULL) || 
    3100              pjmedia_sdp_media_find_attr2(offer->media[0], "sendonly", NULL)) 
    3101     { 
    3102         is_remote_active = PJ_FALSE; 
    3103     } 
    3104  
    3105     remote_state = (is_remote_active ? "active" : "inactive"); 
    3106  
    3107     /* Supply candidate answer */ 
    3108     if (call->media_st == PJSUA_CALL_MEDIA_LOCAL_HOLD || !is_remote_active) { 
    3109         PJ_LOG(4,(THIS_FILE,  
    3110                   "Call %d: RX new media offer, creating inactive SDP " 
    3111                   "(media in offer is %s)", call->index, remote_state)); 
    3112         status = create_inactive_sdp( call, &answer ); 
    3113     } else { 
    3114         PJ_LOG(4,(THIS_FILE, "Call %d: received updated media offer", 
    3115                   call->index)); 
    3116  
    3117         status = pjsua_media_channel_create_sdp(call->index, call->inv->pool,  
    3118                                                 offer, &answer, NULL); 
    3119     } 
    3120  
    3121     if (status != PJ_SUCCESS) { 
    3122         pjsua_perror(THIS_FILE, "Unable to create local SDP", status); 
    3123         PJSUA_UNLOCK(); 
    3124         return; 
     3107        /* Modify address */ 
     3108        answer->conn->addr = pj_str("0.0.0.0"); 
     3109    } 
     3110 
     3111    /* Check if call is on-hold */ 
     3112    if (call->local_hold) { 
     3113        pjmedia_sdp_attr *attr; 
     3114 
     3115        /* Remove existing directions attributes */ 
     3116        pjmedia_sdp_media_remove_all_attr(answer->media[0], "sendrecv"); 
     3117        pjmedia_sdp_media_remove_all_attr(answer->media[0], "sendonly"); 
     3118        pjmedia_sdp_media_remove_all_attr(answer->media[0], "recvonly"); 
     3119        pjmedia_sdp_media_remove_all_attr(answer->media[0], "inactive"); 
     3120 
     3121        /* Keep call on-hold by setting 'sendonly' attribute. 
     3122         * (See RFC 3264 Section 8.4 and RFC 4317 Section 3.1) 
     3123         */ 
     3124        attr = pjmedia_sdp_attr_create(call->inv->pool, "sendonly", NULL); 
     3125        pjmedia_sdp_media_add_attr(answer->media[0], attr); 
    31253126    } 
    31263127 
     
    31503151 
    31513152    /* See if we've put call on hold. */ 
    3152     if (call->media_st == PJSUA_CALL_MEDIA_LOCAL_HOLD) { 
     3153    if (call->local_hold) { 
    31533154        PJ_LOG(4,(THIS_FILE,  
    3154                   "Call %d: call is on-hold locally, creating inactive SDP ", 
     3155                  "Call %d: call is on-hold locally, creating call-hold SDP ", 
    31553156                  call->index)); 
    3156         status = create_inactive_sdp( call, offer ); 
     3157        status = create_sdp_of_call_hold( call, offer ); 
    31573158    } else { 
    31583159        PJ_LOG(4,(THIS_FILE, "Call %d: asked to send a new offer", 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c

    r2135 r2191  
    12321232        pj_memcpy(&sess_info.stream_info[0], si, sizeof(pjmedia_stream_info)); 
    12331233 
    1234     /* Check if media is put on-hold */ 
     1234    /* Check if no media is active */ 
    12351235    if (sess_info.stream_cnt == 0 || si->dir == PJMEDIA_DIR_NONE) 
    12361236    { 
    1237  
    1238         /* Determine who puts the call on-hold */ 
    1239         if (prev_media_st == PJSUA_CALL_MEDIA_ACTIVE) { 
    1240             if (pjmedia_sdp_neg_was_answer_remote(call->inv->neg)) { 
    1241                 /* It was local who offer hold */ 
    1242                 call->media_st = PJSUA_CALL_MEDIA_LOCAL_HOLD; 
    1243             } else { 
    1244                 call->media_st = PJSUA_CALL_MEDIA_REMOTE_HOLD; 
    1245             } 
    1246         } 
    1247  
     1237        /* Call media state */ 
     1238        call->media_st = PJSUA_CALL_MEDIA_NONE; 
     1239 
     1240        /* Call media direction */ 
    12481241        call->media_dir = PJMEDIA_DIR_NONE; 
    12491242 
     
    13681361        } 
    13691362 
    1370         /* Call's media state is active */ 
    1371         call->media_st = PJSUA_CALL_MEDIA_ACTIVE; 
     1363        /* Call media direction */ 
    13721364        call->media_dir = si->dir; 
     1365 
     1366        /* Call media state */ 
     1367        if (call->local_hold) 
     1368            call->media_st = PJSUA_CALL_MEDIA_LOCAL_HOLD; 
     1369        else if (call->media_dir == PJMEDIA_DIR_DECODING) 
     1370            call->media_st = PJSUA_CALL_MEDIA_REMOTE_HOLD; 
     1371        else 
     1372            call->media_st = PJSUA_CALL_MEDIA_ACTIVE; 
    13731373    } 
    13741374 
Note: See TracChangeset for help on using the changeset viewer.