Commit 0d87a22d authored by Simon Morlat's avatar Simon Morlat

fix bugs in Paused state management. It was possible to transition from Paused...

fix bugs in Paused state management. It was possible to transition from Paused to PausedByRemote, which actually breaks the Paused state, and eventually allows the pauser to be resumed by the paused.
parent a4594aec
......@@ -43,6 +43,9 @@ SalStreamDir sal_dir_from_call_params_dir(LinphoneMediaDirection cpdir) {
return SalStreamRecvOnly;
case LinphoneMediaDirectionSendRecv:
return SalStreamSendRecv;
case LinphoneMediaDirectionInvalid:
ms_error("LinphoneMediaDirectionInvalid shall not be used.");
return SalStreamInactive;
}
return SalStreamSendRecv;
}
......
......@@ -34,11 +34,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* Indicates for a given media the stream direction
* */
enum _LinphoneMediaDirection {
LinphoneMediaDirectionInvalid = -1,
LinphoneMediaDirectionInactive, /** No active media not supported yet*/
LinphoneMediaDirectionSendOnly, /** Send only mode*/
LinphoneMediaDirectionRecvOnly, /** recv only mode*/
LinphoneMediaDirectionSendRecv, /** send receive*/
};
/**
* Typedef for enum
......
......@@ -329,7 +329,7 @@ static void call_received(SalOp *h){
call=linphone_call_new_incoming(lc,from_addr,to_addr,h);
linphone_call_make_local_media_description(lc,call);
linphone_call_make_local_media_description(call);
sal_call_set_local_media_description(call->op,call->localdesc);
md=sal_call_get_final_media_description(call->op);
if (md){
......@@ -637,7 +637,12 @@ static void call_updated(LinphoneCore *lc, LinphoneCall *call, SalOp *op, bool_t
if (sal_media_description_has_dir(rmd,SalStreamSendRecv) || sal_media_description_has_dir(rmd,SalStreamRecvOnly)){
call_resumed(lc,call);
}else{
_linphone_core_accept_call_update(lc,call,NULL,call->state,linphone_call_state_to_string(call->state));
/*we are staying in PausedByRemote*/
linphone_core_notify_display_status(lc,_("Call is updated by remote."));
linphone_call_set_state(call, LinphoneCallUpdatedByRemote,"Call updated by remote");
if (call->defer_update == FALSE){
linphone_core_accept_call_update(lc,call,NULL);
}
}
break;
/*SIP UPDATE CASE*/
......@@ -662,12 +667,8 @@ static void call_updated(LinphoneCore *lc, LinphoneCall *call, SalOp *op, bool_t
}
break;
case LinphoneCallPaused:
if (sal_media_description_has_dir(rmd,SalStreamSendOnly) || sal_media_description_has_dir(rmd,SalStreamInactive)){
call_paused_by_remote(lc,call);
}else{
/*we'll remain in pause state but accept the offer anyway according to default parameters*/
_linphone_core_accept_call_update(lc,call,NULL,call->state,linphone_call_state_to_string(call->state));
}
/*we'll remain in pause state but accept the offer anyway according to default parameters*/
_linphone_core_accept_call_update(lc,call,NULL,call->state,linphone_call_state_to_string(call->state));
break;
case LinphoneCallUpdating:
case LinphoneCallPausing:
......@@ -702,7 +703,7 @@ static void call_updating(SalOp *op, bool_t is_update){
}
if (call->state!=LinphoneCallPaused){
/*Refresh the local description, but in paused state, we don't change anything.*/
linphone_call_make_local_media_description(lc,call);
linphone_call_make_local_media_description(call);
sal_call_set_local_media_description(call->op,call->localdesc);
}
if (rmd == NULL){
......
......@@ -582,11 +582,30 @@ static const char *linphone_call_get_public_ip_for_stream(LinphoneCall *call, in
return public_ip;
}
void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *call) {
linphone_call_make_local_media_description_with_params(lc, call, call->params);
static void force_streams_dir_according_to_state(LinphoneCall *call, SalMediaDescription *md){
int i;
switch (call->state){
case LinphoneCallPausing:
case LinphoneCallPaused:
break;
default:
return;
break;
}
for (i=0; i<2; ++i){
SalStreamDescription *sd = &md->streams[i];
sd->dir = SalStreamSendOnly;
if (sd->type == SalVideo){
if (lp_config_get_int(call->core->config, "sip", "inactive_video_on_pause", 0)) {
sd->dir = SalStreamInactive;
}
}
}
}
void linphone_call_make_local_media_description_with_params(LinphoneCore *lc, LinphoneCall *call, LinphoneCallParams *params) {
void linphone_call_make_local_media_description(LinphoneCall *call) {
MSList *l;
SalMediaDescription *old_md=call->localdesc;
int i;
......@@ -595,6 +614,9 @@ void linphone_call_make_local_media_description_with_params(LinphoneCore *lc, Li
LinphoneAddress *addr;
const char *subject;
CodecConstraints codec_hints={0};
LinphoneCallParams *params = call->params;
LinphoneCore *lc = call->core;
/*multicast is only set in case of outgoing call*/
if (call->dir == LinphoneCallOutgoing && linphone_call_params_audio_multicast_enabled(params)) {
......@@ -718,6 +740,7 @@ void linphone_call_make_local_media_description_with_params(LinphoneCore *lc, Li
call->localdesc_changed=sal_media_description_equals(md,old_md);
sal_media_description_unref(old_md);
}
force_streams_dir_according_to_state(call, md);
}
static int find_port_offset(LinphoneCore *lc, int stream_index, int base_port){
......
......@@ -2768,7 +2768,7 @@ int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call, const Linph
linphone_call_set_contact_op(call);
linphone_core_stop_dtmf_stream(lc);
linphone_call_make_local_media_description(lc,call);
linphone_call_make_local_media_description(call);
if (lc->ringstream==NULL) {
if (lc->sound_conf.play_sndcard && lc->sound_conf.capt_sndcard){
......@@ -3171,7 +3171,7 @@ int linphone_core_accept_early_media_with_params(LinphoneCore* lc, LinphoneCall*
// if parameters are passed, update the media description
if ( params ) {
linphone_call_set_new_params(call,params);
linphone_call_make_local_media_description ( lc,call );
linphone_call_make_local_media_description (call);
sal_call_set_local_media_description ( call->op,call->localdesc );
sal_op_set_sent_custom_header ( call->op,params->custom_headers );
}
......@@ -3209,7 +3209,7 @@ int linphone_core_start_update_call(LinphoneCore *lc, LinphoneCall *call){
linphone_call_fill_media_multicast_addr(call);
if (!no_user_consent) linphone_call_make_local_media_description(lc,call);
if (!no_user_consent) linphone_call_make_local_media_description(call);
#ifdef BUILD_UPNP
if(call->upnp_session != NULL) {
linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
......@@ -3350,15 +3350,24 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho
* the call state notification, to deactivate the automatic answer that would just confirm the audio but reject the video.
* Then, when the user responds to dialog prompt, it becomes possible to call linphone_core_accept_call_update() to answer
* the reINVITE, with eventually video enabled in the LinphoneCallParams argument.
*
* The #LinphoneCallUpdatedByRemote notification can also arrive when receiving an INVITE without SDP. In such case, an unchanged offer is made
* in the 200Ok, and when the ACK containing the SDP answer is received, #LinphoneCallUpdatedByRemote is triggered to notify the application of possible
* changes in the media session. However in such case defering the update has no meaning since we just generating an offer.
*
* @return 0 if successful, -1 if the linphone_core_defer_call_update() was done outside a #LinphoneCallUpdatedByRemote notification, which is illegal.
* @return 0 if successful, -1 if the linphone_core_defer_call_update() was done outside a valid #LinphoneCallUpdatedByRemote notification.
**/
int linphone_core_defer_call_update(LinphoneCore *lc, LinphoneCall *call){
if (call->state==LinphoneCallUpdatedByRemote){
if (call->expect_media_in_ack){
ms_error("linphone_core_defer_call_update() is not possible during a late offer incoming reINVITE (INVITE without SDP)");
return -1;
}
call->defer_update=TRUE;
return 0;
}else{
ms_error("linphone_core_defer_call_update() not done in state LinphoneCallUpdatedByRemote");
}
ms_error("linphone_core_defer_call_update() not done in state LinphoneCallUpdatedByRemote");
return -1;
}
......@@ -3370,7 +3379,7 @@ int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call,
return 0;
}
}
linphone_call_make_local_media_description(lc,call);
linphone_call_make_local_media_description(call);
linphone_call_update_remote_session_id_and_ver(call);
linphone_call_stop_ice_for_inactive_streams(call);
......@@ -3587,7 +3596,7 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call,
linphone_call_set_compatible_incoming_call_parameters(call, md);
}
linphone_call_prepare_ice(call,TRUE);
linphone_call_make_local_media_description(lc,call);
linphone_call_make_local_media_description(call);
sal_call_set_local_media_description(call->op,call->localdesc);
sal_op_set_sent_custom_header(call->op,params->custom_headers);
}
......@@ -3797,10 +3806,8 @@ int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call){
}
/* Internal version that does not play tone indication*/
int _linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call)
{
int _linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call){
const char *subject=NULL;
LinphoneCallParams *params;
if (call->state!=LinphoneCallStreamsRunning && call->state!=LinphoneCallPausedByRemote){
ms_warning("Cannot pause this call, it is not active.");
......@@ -3814,15 +3821,8 @@ int _linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call)
ms_error("No reason to pause this call, it is already paused or inactive.");
return -1;
}
params = linphone_call_params_copy(call->params);
linphone_call_params_set_audio_direction(params, LinphoneMediaDirectionSendOnly);
if (lp_config_get_int(lc->config, "sip", "inactive_video_on_pause", 0)) {
linphone_call_params_set_video_direction(params, LinphoneMediaDirectionInactive);
} else {
linphone_call_params_set_video_direction(params, LinphoneMediaDirectionSendOnly);
}
linphone_call_make_local_media_description_with_params(lc, call, params);
linphone_call_params_unref(params);
linphone_call_set_state(call, LinphoneCallPausing, "Pausing call");
linphone_call_make_local_media_description(call);
#ifdef BUILD_UPNP
if(call->upnp_session != NULL) {
linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
......@@ -3836,7 +3836,6 @@ int _linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call)
linphone_core_notify_display_status(lc,_("Pausing the current call..."));
if (call->audiostream || call->videostream)
linphone_call_stop_media_streams (call);
linphone_call_set_state(call,LinphoneCallPausing,"Pausing call");
call->paused_by_app=FALSE;
return 0;
}
......@@ -3903,7 +3902,7 @@ int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *call){
prevents the participants to hear it while the 200OK comes back.*/
if (call->audiostream) audio_stream_play(call->audiostream, NULL);
linphone_call_make_local_media_description(lc,call);
linphone_call_make_local_media_description(call);
#ifdef BUILD_UPNP
if(call->upnp_session != NULL) {
linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
......
......@@ -897,7 +897,7 @@ int linphone_core_set_as_current_call(LinphoneCore *lc, LinphoneCall *call);
int linphone_core_get_calls_nb(const LinphoneCore *lc);
void linphone_core_set_state(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message);
void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *call);
void linphone_call_make_local_media_description(LinphoneCall *call);
void linphone_call_make_local_media_description_with_params(LinphoneCore *lc, LinphoneCall *call, LinphoneCallParams *params);
void linphone_call_increment_local_media_description(LinphoneCall *call);
void linphone_call_fill_media_multicast_addr(LinphoneCall *call);
......
......@@ -160,26 +160,27 @@ static bool_t is_null_address(const char *addr){
/*check for the presence of at least one stream with requested direction */
static bool_t has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){
int i;
/* we are looking for at least one stream with requested direction, inactive streams are ignored*/
for(i=0;i<md->nb_streams;++i){
const SalStreamDescription *ss=&md->streams[i];
if (!sal_stream_description_active(ss)) continue;
if (ss->dir==stream_dir) return TRUE;
if (ss->dir==stream_dir) {
return TRUE;
}
/*compatibility check for phones that only used the null address and no attributes */
if (ss->dir==SalStreamSendRecv && stream_dir==SalStreamSendOnly && (is_null_address(md->addr) || is_null_address(ss->rtp_addr)))
if (ss->dir==SalStreamSendRecv && stream_dir==SalStreamSendOnly && (is_null_address(md->addr) || is_null_address(ss->rtp_addr))){
return TRUE;
}
}
return FALSE;
}
bool_t sal_media_description_has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){
if (stream_dir==SalStreamRecvOnly){
if (has_dir(md,SalStreamSendOnly) || has_dir(md,SalStreamSendRecv)) return FALSE;
else return TRUE;
return has_dir(md, SalStreamRecvOnly) && !(has_dir(md,SalStreamSendOnly) || has_dir(md,SalStreamSendRecv));
}else if (stream_dir==SalStreamSendOnly){
if (has_dir(md,SalStreamRecvOnly) || has_dir(md,SalStreamSendRecv)) return FALSE;
else return TRUE;
return has_dir(md, SalStreamSendOnly) && !(has_dir(md,SalStreamRecvOnly) || has_dir(md,SalStreamSendRecv));
}else if (stream_dir==SalStreamSendRecv){
return has_dir(md,SalStreamSendRecv);
}else{
......
This diff is collapsed.
......@@ -335,6 +335,8 @@ int liblinphone_tester_setup();
void liblinphone_tester_init(void(*ftester_printf)(int level, const char *fmt, va_list args));
void liblinphone_tester_uninit(void);
extern const char *liblinphone_tester_mire_id;
#ifdef __cplusplus
};
......
......@@ -44,6 +44,8 @@ const char* test_password="secret";
const char* test_route="sip2.linphone.org";
const char *userhostsfile = "tester_hosts";
const char *liblinphone_tester_mire_id="Mire: Mire (synthetic moving picture)";
static void network_reachable(LinphoneCore *lc, bool_t reachable) {
stats* counters;
ms_message("Network reachable [%s]",reachable?"TRUE":"FALSE");
......@@ -237,6 +239,10 @@ bool_t transport_supported(LinphoneTransportType transport) {
}
static void display_status(LinphoneCore *lc, const char *status){
ms_message("display_status(): %s",status);
}
LinphoneCoreManager* linphone_core_manager_init(const char* rc_file) {
LinphoneCoreManager* mgr= ms_new0(LinphoneCoreManager,1);
char *rc_path = NULL;
......@@ -260,6 +266,7 @@ LinphoneCoreManager* linphone_core_manager_init(const char* rc_file) {
mgr->v_table.network_reachable=network_reachable;
mgr->v_table.dtmf_received=dtmf_received;
mgr->v_table.call_stats_updated=call_stats_updated;
mgr->v_table.display_status=display_status;
reset_counters(&mgr->stat);
if (rc_file) rc_path = ms_strdup_printf("rcfiles/%s", rc_file);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment