Ticket #563: ticket563.patch
File ticket563.patch, 12.1 KB (added by nanang, 16 years ago) |
---|
-
pjsip-apps/src/pjsua/pjsua_app.c
2210 2210 /* Stop ringback */ 2211 2211 ring_stop(call_id); 2212 2212 2213 if (call_info.media_status == PJSUA_CALL_MEDIA_ACTIVE) { 2213 /* Connect ports appropriately when media status is ACTIVE or 2214 * HELD by REMOTE (only the initiator of call-hold should mute its ports, 2215 * so when call-hold is initated by remote, local ports should be still 2216 * normally connected). 2217 */ 2218 if (call_info.media_status == PJSUA_CALL_MEDIA_ACTIVE || 2219 call_info.media_status == PJSUA_CALL_MEDIA_REMOTE_HOLD) 2220 { 2214 2221 pj_bool_t connect_sound = PJ_TRUE; 2215 2222 2216 2223 /* Loopback sound, if desired */ … … 2278 2285 pjsua_conf_connect(0, app_config.rec_port); 2279 2286 } 2280 2287 } 2288 } 2281 2289 2290 /* Handle media status */ 2291 switch (call_info.media_status) { 2292 case PJSUA_CALL_MEDIA_ACTIVE: 2282 2293 PJ_LOG(3,(THIS_FILE, "Media for call %d is active", call_id)); 2294 break; 2283 2295 2284 } else if (call_info.media_status == PJSUA_CALL_MEDIA_LOCAL_HOLD) {2296 case PJSUA_CALL_MEDIA_LOCAL_HOLD: 2285 2297 PJ_LOG(3,(THIS_FILE, "Media for call %d is suspended (hold) by local", 2286 2298 call_id)); 2287 } else if (call_info.media_status == PJSUA_CALL_MEDIA_REMOTE_HOLD) { 2299 break; 2300 2301 case PJSUA_CALL_MEDIA_REMOTE_HOLD: 2288 2302 PJ_LOG(3,(THIS_FILE, 2289 2303 "Media for call %d is suspended (hold) by remote", 2290 2304 call_id)); 2291 } else if (call_info.media_status == PJSUA_CALL_MEDIA_ERROR) { 2292 pj_str_t reason = pj_str("ICE negotiation failed"); 2305 break; 2293 2306 2294 PJ_LOG(1,(THIS_FILE, 2307 case PJSUA_CALL_MEDIA_ERROR: 2308 PJ_LOG(3,(THIS_FILE, 2295 2309 "Media has reported error, disconnecting call")); 2310 { 2311 pj_str_t reason = pj_str("ICE negotiation failed"); 2312 pjsua_call_hangup(call_id, 500, &reason, NULL); 2313 } 2314 break; 2296 2315 2297 pjsua_call_hangup(call_id, 500, &reason, NULL); 2298 2299 } else { 2316 case PJSUA_CALL_MEDIA_NONE: 2300 2317 PJ_LOG(3,(THIS_FILE, 2301 2318 "Media for call %d is inactive", 2302 2319 call_id)); 2320 break; 2321 2322 default: 2323 pj_assert(!"Unhandled media status"); 2324 break; 2303 2325 } 2304 2326 } 2305 2327 -
pjsip/src/pjsua-lib/pjsua_call.c
66 66 pjsip_event *e); 67 67 68 68 69 /* Create SDP for call hold. */ 70 static pj_status_t create_sdp_of_call_hold(pjsua_call *call, 71 pjmedia_sdp_session **p_answer); 69 72 70 /* Create inactive SDP for call hold. */71 static pj_status_t create_inactive_sdp(pjsua_call *call,72 pjmedia_sdp_session **p_answer);73 74 73 /* Update SDP version in the offer */ 75 74 static void update_sdp_version(pjsua_call *call, 76 75 pjmedia_sdp_session *sdp) … … 117 116 call->res_time.msec = 0; 118 117 call->rem_nat_type = PJ_STUN_NAT_TYPE_UNKNOWN; 119 118 call->rem_srtp_use = PJMEDIA_SRTP_DISABLED; 119 call->on_hold = PJ_FALSE; 120 120 } 121 121 122 122 … … 1426 1426 return PJSIP_ESESSIONSTATE; 1427 1427 } 1428 1428 1429 status = create_ inactive_sdp(call, &sdp);1429 status = create_sdp_of_call_hold(call, &sdp); 1430 1430 if (status != PJ_SUCCESS) { 1431 1431 pjsip_dlg_dec_lock(dlg); 1432 1432 return status; … … 1453 1453 return status; 1454 1454 } 1455 1455 1456 call->on_hold = PJ_TRUE; 1457 1456 1458 pjsip_dlg_dec_lock(dlg); 1457 1459 1458 1460 return PJ_SUCCESS; … … 1487 1489 } 1488 1490 1489 1491 /* 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); 1492 if (call->on_hold && !unhold) { 1493 status = create_sdp_of_call_hold(call, &sdp); 1494 } else { 1495 status = pjsua_media_channel_create_sdp(call->index, call->inv->pool, 1496 NULL, &sdp, NULL); 1497 call->on_hold = PJ_FALSE; 1498 } 1494 1499 if (status != PJ_SUCCESS) { 1495 1500 pjsua_perror(THIS_FILE, "Unable to get SDP from media endpoint", 1496 1501 status); … … 1573 1578 /* Send the request */ 1574 1579 status = pjsip_inv_send_msg( call->inv, tdata); 1575 1580 if (status != PJ_SUCCESS) { 1576 pjsua_perror(THIS_FILE, "Unable to send UPDAT Erequest", status);1581 pjsua_perror(THIS_FILE, "Unable to send UPDATE request", status); 1577 1582 pjsip_dlg_dec_lock(dlg); 1578 1583 return status; 1579 1584 } 1580 1585 1586 call->on_hold = PJ_FALSE; 1587 1581 1588 pjsip_dlg_dec_lock(dlg); 1582 1589 1583 1590 return PJ_SUCCESS; … … 3012 3019 } 3013 3020 3014 3021 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) 3022 /* Create SDP for call hold. */ 3023 static pj_status_t create_sdp_of_call_hold(pjsua_call *call, 3024 pjmedia_sdp_session **p_answer) 3020 3025 { 3021 3026 pj_status_t status; 3022 3027 pj_pool_t *pool; 3023 pjmedia_sdp_conn *conn;3024 pjmedia_sdp_attr *attr;3025 3028 pjmedia_transport_info tp_info; 3026 3029 pjmedia_sdp_session *sdp; 3027 3030 … … 3040 3043 return status; 3041 3044 } 3042 3045 3043 /* Get SDP media connection line */ 3044 conn = sdp->media[0]->conn; 3045 if (!conn) 3046 conn = sdp->conn; 3046 /* Call-hold is done by set the media direction to 'sendonly' 3047 * (PJMEDIA_DIR_ENCODING), except when current media direction is 3048 * 'inactive' (PJMEDIA_DIR_NONE). 3049 * (See RFC 3264 Section 8.4 and RFC 4317 Section 3.1) 3050 */ 3051 if (call->media_dir != PJMEDIA_DIR_ENCODING) { 3052 pjmedia_sdp_attr *attr; 3047 3053 3048 /* Modify address */ 3049 conn->addr = pj_str("0.0.0.0"); 3054 /* Remove existing directions attributes */ 3055 pjmedia_sdp_media_remove_all_attr(sdp->media[0], "sendrecv"); 3056 pjmedia_sdp_media_remove_all_attr(sdp->media[0], "sendonly"); 3057 pjmedia_sdp_media_remove_all_attr(sdp->media[0], "recvonly"); 3058 pjmedia_sdp_media_remove_all_attr(sdp->media[0], "inactive"); 3050 3059 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"); 3060 if (call->media_dir == PJMEDIA_DIR_ENCODING_DECODING) { 3061 /* Add sendonly attribute */ 3062 attr = pjmedia_sdp_attr_create(pool, "sendonly", NULL); 3063 pjmedia_sdp_media_add_attr(sdp->media[0], attr); 3064 } else { 3065 /* Add inactive attribute */ 3066 attr = pjmedia_sdp_attr_create(pool, "inactive", NULL); 3067 pjmedia_sdp_media_add_attr(sdp->media[0], attr); 3068 } 3069 } 3056 3070 3057 /* Add inactive attribute */3058 attr = pjmedia_sdp_attr_create(pool, "inactive", NULL);3059 pjmedia_sdp_media_add_attr(sdp->media[0], attr);3060 3061 3071 *p_answer = sdp; 3062 3072 3063 3073 return status; 3064 3074 } 3065 3075 3066 3067 3076 /* 3068 3077 * Called when session received new offer. 3069 3078 */ 3070 3079 static void pjsua_call_on_rx_offer(pjsip_inv_session *inv, 3071 3080 const pjmedia_sdp_session *offer) 3072 3081 { 3073 const char *remote_state;3074 3082 pjsua_call *call; 3075 3083 pjmedia_sdp_conn *conn; 3076 3084 pjmedia_sdp_session *answer; 3077 pj_bool_t is_remote_active;3078 3085 pj_status_t status; 3079 3086 3080 3087 PJSUA_LOCK(); 3081 3088 3082 3089 call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id]; 3083 3090 3084 /*3085 * See if remote is offering active media (i.e. not on-hold)3086 */3087 is_remote_active = PJ_TRUE;3088 3089 3091 conn = offer->media[0]->conn; 3090 3092 if (!conn) 3091 3093 conn = offer->conn; 3092 3094 3095 /* Supply candidate answer */ 3096 PJ_LOG(4,(THIS_FILE, "Call %d: received updated media offer", 3097 call->index)); 3098 3099 status = pjsua_media_channel_create_sdp(call->index, call->inv->pool, 3100 offer, &answer, NULL); 3101 if (status != PJ_SUCCESS) { 3102 pjsua_perror(THIS_FILE, "Unable to create local SDP", status); 3103 PJSUA_UNLOCK(); 3104 return; 3105 } 3106 3107 /* Check if offer's conn address is zero */ 3093 3108 if (pj_strcmp2(&conn->addr, "0.0.0.0")==0 || 3094 3109 pj_strcmp2(&conn->addr, "0")==0) 3095 3110 { 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; 3111 /* Modify address */ 3112 answer->conn->addr = pj_str("0.0.0.0"); 3103 3113 } 3104 3114 3105 remote_state = (is_remote_active ? "active" : "inactive"); 3115 /* Check if call is on-hold */ 3116 if (call->on_hold) { 3117 pjmedia_sdp_attr *attr; 3106 3118 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)); 3119 /* Remove existing directions attributes */ 3120 pjmedia_sdp_media_remove_all_attr(answer->media[0], "sendrecv"); 3121 pjmedia_sdp_media_remove_all_attr(answer->media[0], "sendonly"); 3122 pjmedia_sdp_media_remove_all_attr(answer->media[0], "recvonly"); 3123 pjmedia_sdp_media_remove_all_attr(answer->media[0], "inactive"); 3116 3124 3117 status = pjsua_media_channel_create_sdp(call->index, call->inv->pool, 3118 offer, &answer, NULL); 3125 /* Keep call on-hold by setting 'sendonly' attribute. 3126 * (See RFC 3264 Section 8.4 and RFC 4317 Section 3.1) 3127 */ 3128 attr = pjmedia_sdp_attr_create(call->inv->pool, "sendonly", NULL); 3129 pjmedia_sdp_media_add_attr(answer->media[0], attr); 3119 3130 } 3120 3131 3121 if (status != PJ_SUCCESS) {3122 pjsua_perror(THIS_FILE, "Unable to create local SDP", status);3123 PJSUA_UNLOCK();3124 return;3125 }3126 3127 3132 status = pjsip_inv_set_sdp_answer(call->inv, answer); 3128 3133 if (status != PJ_SUCCESS) { 3129 3134 pjsua_perror(THIS_FILE, "Unable to set answer", status); … … 3149 3154 call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id]; 3150 3155 3151 3156 /* See if we've put call on hold. */ 3152 if (call-> media_st == PJSUA_CALL_MEDIA_LOCAL_HOLD) {3157 if (call->on_hold) { 3153 3158 PJ_LOG(4,(THIS_FILE, 3154 "Call %d: call is on-hold locally, creating inactiveSDP ",3159 "Call %d: call is on-hold locally, creating call-hold SDP ", 3155 3160 call->index)); 3156 status = create_ inactive_sdp( call, offer );3161 status = create_sdp_of_call_hold( call, offer ); 3157 3162 } else { 3158 3163 PJ_LOG(4,(THIS_FILE, "Call %d: asked to send a new offer", 3159 3164 call->index)); -
pjsip/src/pjsua-lib/pjsua_media.c
1231 1231 if (si != &sess_info.stream_info[0]) 1232 1232 pj_memcpy(&sess_info.stream_info[0], si, sizeof(pjmedia_stream_info)); 1233 1233 1234 /* Check if media is put on-hold*/1234 /* Check if no media is active */ 1235 1235 if (sess_info.stream_cnt == 0 || si->dir == PJMEDIA_DIR_NONE) 1236 1236 { 1237 /* Call media state */ 1238 call->media_st = PJSUA_CALL_MEDIA_NONE; 1237 1239 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 1240 /* Call media direction */ 1248 1241 call->media_dir = PJMEDIA_DIR_NONE; 1249 1242 1250 1243 /* Shutdown transport's session */ … … 1367 1360 } 1368 1361 } 1369 1362 1370 /* Call's media state is active */ 1371 call->media_st = PJSUA_CALL_MEDIA_ACTIVE; 1363 /* Call media direction */ 1372 1364 call->media_dir = si->dir; 1365 1366 /* Call media state */ 1367 if (call->on_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; 1373 1373 } 1374 1374 1375 1375 /* Print info. */ -
pjsip/include/pjsua-lib/pjsua_internal.h
60 60 pj_time_val dis_time; /**< Disconnect time. */ 61 61 pjsua_acc_id acc_id; /**< Account index being used. */ 62 62 int secure_level;/**< Signaling security level. */ 63 pj_bool_t on_hold; /**< Flag for call-hold by local. */ 63 64 pjsua_call_media_status media_st;/**< Media state. */ 64 65 pjmedia_dir media_dir; /**< Media direction. */ 65 66 pjmedia_session *session; /**< The media session. */