Example #1
0
/* this callback is called when an incoming re-INVITE modifies the session*/
static void call_updating(SalOp *op){
	LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
	LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
	LinphoneCallState prevstate=LinphoneCallIdle;
	SalMediaDescription *md;
	
	md=sal_call_get_final_media_description(op);
	
	if (md && !sal_media_description_empty(md))
	{
		if (sal_media_description_has_dir(call->localdesc,SalStreamSendRecv)){
			ms_message("Our local status is SalStreamSendRecv");
			if (sal_media_description_has_dir (md,SalStreamRecvOnly) || sal_media_description_has_dir(md,SalStreamInactive)){
				/* we are being paused */
				if(lc->vtable.display_status)
					lc->vtable.display_status(lc,_("We are being paused..."));
				linphone_call_set_state (call,LinphoneCallPausedByRemote,"Call paused by remote");
			}else if (!sal_media_description_has_dir(call->resultdesc,SalStreamSendRecv) && sal_media_description_has_dir(md,SalStreamSendRecv)){
				if(lc->vtable.display_status)
					lc->vtable.display_status(lc,_("We have been resumed..."));
				linphone_call_set_state (call,LinphoneCallStreamsRunning,"Connected (streams running)");
				lc->current_call=call;
			}else{
				prevstate=call->state;
				linphone_call_set_state(call, LinphoneCallUpdatedByRemote,"Call updated by remote");
			}
		}
		/*accept the modification (sends a 200Ok)*/
		sal_call_accept(op);
		linphone_core_update_streams (lc,call,md);
		if (prevstate!=LinphoneCallIdle){
			linphone_call_set_state (call,prevstate,"Connected (streams running)");
		}
	}
}
Example #2
0
static void call_ack(SalOp *op){
	LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
	LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
	if (call==NULL){
		ms_warning("No call to be ACK'd");
		return ;
	}
	if (call->media_pending){
		SalMediaDescription *md=sal_call_get_final_media_description(op);
		if (md && !sal_media_description_empty(md)){
			if (call->state==LinphoneCallStreamsRunning){
				/*media was running before, the remote as acceted a call modification (that is
					a reinvite made by us. We must notify the application this reinvite was accepted*/
				linphone_call_set_state(call, LinphoneCallUpdated, "Call updated");
			}
			linphone_core_update_streams (lc,call,md);
			linphone_call_set_state (call,LinphoneCallStreamsRunning,"Connected (streams running)");
		}else{
			/*send a bye*/
			ms_error("Incompatible SDP response received in ACK, need to abort the call");
			linphone_core_abort_call(lc,call,"No codec intersection");
			return;
		}
	}
}
Example #3
0
static void call_updated_by_remote(LinphoneCore *lc, LinphoneCall *call){
	/*first check if media capabilities are compatible*/
	SalMediaDescription* md;
	linphone_call_make_local_media_description(lc,call);
	sal_call_set_local_media_description(call->op,call->localdesc);
	md=sal_call_get_final_media_description(call->op);
	if (md && (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md))){
		sal_call_decline(call->op,SalReasonNotAcceptable,NULL);
		return;
	}

	if(lc->vtable.display_status)
		lc->vtable.display_status(lc,_("Call is updated by remote."));
	call->defer_update=FALSE;
	linphone_call_set_state(call, LinphoneCallUpdatedByRemote,"Call updated by remote");
	if (call->defer_update==FALSE){
		linphone_core_accept_call_update(lc,call,NULL);
	}
}
Example #4
0
static void call_accept_update(LinphoneCore *lc, LinphoneCall *call){
	SalMediaDescription *md;
	SalMediaDescription *rmd=sal_call_get_remote_media_description(call->op);
	if (rmd!=NULL && call->ice_session!=NULL) {
		linphone_core_update_ice_from_remote_media_description(call,rmd);
		linphone_core_update_local_media_description_from_ice(call->localdesc,call->ice_session);
	}
#ifdef BUILD_UPNP
	if(call->upnp_session != NULL) {
		linphone_core_update_upnp_from_remote_media_description(call, rmd);
		linphone_core_update_local_media_description_from_upnp(call->localdesc,call->upnp_session);
	}
#endif //BUILD_UPNP
	linphone_call_update_remote_session_id_and_ver(call);
	sal_call_accept(call->op);
	md=sal_call_get_final_media_description(call->op);
	if (md && !sal_media_description_empty(md)){
		linphone_core_update_streams(lc,call,md);
	}
}
Example #5
0
static void call_ack(SalOp *op){
	LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
	LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
	if (call==NULL){
		ms_warning("No call to be ACK'd");
		return ;
	}
	if (call->expect_media_in_ack){
		SalMediaDescription *md=sal_call_get_final_media_description(op);
		if (md && !sal_media_description_empty(md)){
			linphone_core_update_streams(lc,call,md);
			linphone_call_set_state (call,LinphoneCallStreamsRunning,"Connected (streams running)");
		}else{
			/*send a bye*/
			ms_error("Incompatible SDP response received in ACK, need to abort the call");
			linphone_core_abort_call(lc,call,"No codec intersection");
			return;
		}
	}
}
Example #6
0
/*
 * could be reach :
 *  - when the call is accepted
 *  - when a request is accepted (pause, resume)
 */
static void call_accepted(SalOp *op){
	LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
	LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
	SalMediaDescription *md;
	
	if (call==NULL){
		ms_warning("No call to accept.");
		return ;
	}
	/*set privacy*/
	call->current_params.privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op);

	/* Handle remote ICE attributes if any. */
	if (call->ice_session != NULL) {
		linphone_core_update_ice_from_remote_media_description(call, sal_call_get_remote_media_description(op));
	}
#ifdef BUILD_UPNP
	if (call->upnp_session != NULL) {
		linphone_core_update_upnp_from_remote_media_description(call, sal_call_get_remote_media_description(op));
	}
#endif //BUILD_UPNP

	md=sal_call_get_final_media_description(op);
	if (md) /*make sure re-invite will not propose video again*/
		call->params.has_video &= linphone_core_media_description_contains_video_stream(md);
	
	if (call->state==LinphoneCallOutgoingProgress ||
	    call->state==LinphoneCallOutgoingRinging ||
	    call->state==LinphoneCallOutgoingEarlyMedia){
		linphone_call_set_state(call,LinphoneCallConnected,"Connected");
		if (call->referer) linphone_core_notify_refer_state(lc,call->referer,call);
	}
	if (md && !sal_media_description_empty(md) && !linphone_core_incompatible_security(lc,md)){
		linphone_call_update_remote_session_id_and_ver(call);
		if (sal_media_description_has_dir(md,SalStreamSendOnly) ||
		    sal_media_description_has_dir(md,SalStreamInactive)){
			if (lc->vtable.display_status){
				char *tmp=linphone_call_get_remote_address_as_string (call);
				char *msg=ms_strdup_printf(_("Call with %s is paused."),tmp);
				lc->vtable.display_status(lc,msg);
				ms_free(tmp);
				ms_free(msg);
			}
			linphone_core_update_streams (lc,call,md);
			linphone_call_set_state(call,LinphoneCallPaused,"Call paused");
			if (call->refer_pending)
				linphone_core_start_refered_call(lc,call,NULL);
		}else if (sal_media_description_has_dir(md,SalStreamRecvOnly)){
			/*we are put on hold when the call is initially accepted */
			if (lc->vtable.display_status){
				char *tmp=linphone_call_get_remote_address_as_string (call);
				char *msg=ms_strdup_printf(_("Call answered by %s - on hold."),tmp);
				lc->vtable.display_status(lc,msg);
				ms_free(tmp);
				ms_free(msg);
			}
			linphone_core_update_streams (lc,call,md);
			linphone_call_set_state(call,LinphoneCallPausedByRemote,"Call paused by remote");
		}else{
			if (call->state!=LinphoneCallUpdating){
				if (call->state==LinphoneCallResuming){
					if (lc->vtable.display_status){
						lc->vtable.display_status(lc,_("Call resumed."));
					}
				}else{
					if (lc->vtable.display_status){
						char *tmp=linphone_call_get_remote_address_as_string (call);
						char *msg=ms_strdup_printf(_("Call answered by %s."),tmp);
						lc->vtable.display_status(lc,msg);
						ms_free(tmp);
						ms_free(msg);
					}
				}
			}
			linphone_core_update_streams(lc,call,md);
			/*also reflect the change if the "wished" params, in order to avoid to propose SAVP or video again
			* further in the call, for example during pause,resume, conferencing reINVITEs*/
			linphone_call_fix_call_parameters(call);
			if (!call->current_params.in_conference)
				lc->current_call=call;
			linphone_call_set_state(call, LinphoneCallStreamsRunning, "Streams running");
		}
	}else{
		/*send a bye*/
		ms_error("Incompatible SDP offer received in 200Ok, need to abort the call");
		linphone_core_abort_call(lc,call,_("Incompatible, check codecs or security settings..."));
	}
}
Example #7
0
/*
 * could be reach :
 *  - when the call is accepted
 *  - when a request is accepted (pause, resume)
 */
static void call_accepted(SalOp *op){
	LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
	LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
	SalMediaDescription *md;
	
	if (call==NULL){
		ms_warning("No call to accept.");
		return ;
	}
	
	md=sal_call_get_final_media_description(op);
	
	if (call->state==LinphoneCallOutgoingProgress ||
	    call->state==LinphoneCallOutgoingRinging ||
	    call->state==LinphoneCallOutgoingEarlyMedia){
		linphone_call_set_state(call,LinphoneCallConnected,"Connected");
	}
	if (md && !sal_media_description_empty(md)){
		if (sal_media_description_has_dir(md,SalStreamSendOnly) ||
		    sal_media_description_has_dir(md,SalStreamInactive)){
			if (lc->vtable.display_status){
				char *tmp=linphone_call_get_remote_address_as_string (call);
				char *msg=ms_strdup_printf(_("Call with %s is paused."),tmp);
				lc->vtable.display_status(lc,msg);
				ms_free(tmp);
				ms_free(msg);
			}
			linphone_core_update_streams (lc,call,md);
			linphone_call_set_state(call,LinphoneCallPaused,"Call paused");
		}else if (sal_media_description_has_dir(md,SalStreamRecvOnly)){
			/*we are put on hold when the call is initially accepted */
			if (lc->vtable.display_status){
				char *tmp=linphone_call_get_remote_address_as_string (call);
				char *msg=ms_strdup_printf(_("Call answered by %s - on hold."),tmp);
				lc->vtable.display_status(lc,msg);
				ms_free(tmp);
				ms_free(msg);
			}
			linphone_core_update_streams (lc,call,md);
			linphone_call_set_state(call,LinphoneCallPausedByRemote,"Call paused by remote");
		}else{
			if (call->state==LinphoneCallStreamsRunning){
				/*media was running before, the remote as acceted a call modification (that is
					a reinvite made by us. We must notify the application this reinvite was accepted*/
				linphone_call_set_state(call, LinphoneCallUpdated, "Call updated");
			}else{
				if (call->state==LinphoneCallResuming){
					if (lc->vtable.display_status){
						lc->vtable.display_status(lc,_("Call resumed."));
					}
				}else{
					if (lc->vtable.display_status){
						char *tmp=linphone_call_get_remote_address_as_string (call);
						char *msg=ms_strdup_printf(_("Call answered by %s."),tmp);
						lc->vtable.display_status(lc,msg);
						ms_free(tmp);
						ms_free(msg);
					}
				}
			}
			linphone_core_update_streams (lc,call,md);
			linphone_call_set_state(call, LinphoneCallStreamsRunning, "Streams running");
			lc->current_call=call;
		}
	}else{
		/*send a bye*/
		ms_error("Incompatible SDP offer received in 200Ok, need to abort the call");
		linphone_core_abort_call(lc,call,"No codec intersection");
	}
}
Example #8
0
static void call_received(SalOp *h){
	LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h));
	char *barmesg;
	LinphoneCall *call;
	const char *from,*to;
	char *tmp;
	LinphoneAddress *from_parsed;
	LinphoneAddress *from_addr, *to_addr;
	SalMediaDescription *md;
	bool_t propose_early_media=lp_config_get_int(lc->config,"sip","incoming_calls_early_media",FALSE);
	const char *ringback_tone=linphone_core_get_remote_ringback_tone (lc);
	
	/* first check if we can answer successfully to this invite */
	if (lc->presence_mode==LinphoneStatusBusy ||
	    lc->presence_mode==LinphoneStatusOffline ||
	    lc->presence_mode==LinphoneStatusDoNotDisturb ||
	    lc->presence_mode==LinphoneStatusMoved){
		if (lc->presence_mode==LinphoneStatusBusy )
			sal_call_decline(h,SalReasonBusy,NULL);
		else if (lc->presence_mode==LinphoneStatusOffline)
			sal_call_decline(h,SalReasonTemporarilyUnavailable,NULL);
		else if (lc->presence_mode==LinphoneStatusDoNotDisturb)
			sal_call_decline(h,SalReasonTemporarilyUnavailable,NULL);
		else if (lc->alt_contact!=NULL && lc->presence_mode==LinphoneStatusMoved)
			sal_call_decline(h,SalReasonRedirect,lc->alt_contact);
		sal_op_release(h);
		return;
	}
	if (!linphone_core_can_we_add_call(lc)){/*busy*/
		sal_call_decline(h,SalReasonBusy,NULL);
		sal_op_release(h);
		return;
	}
	from=sal_op_get_from(h);
	to=sal_op_get_to(h);
	from_addr=linphone_address_new(from);
	to_addr=linphone_address_new(to);

	if (is_duplicate_call(lc,from_addr,to_addr)){
		ms_warning("Receiving duplicated call, refusing this one.");
		sal_call_decline(h,SalReasonBusy,NULL);
		linphone_address_destroy(from_addr);
		linphone_address_destroy(to_addr);
		return;
	}
	
	call=linphone_call_new_incoming(lc,from_addr,to_addr,h);
	sal_call_set_local_media_description(h,call->localdesc);
	md=sal_call_get_final_media_description(h);

	if (md && sal_media_description_empty(md)){
		sal_call_decline(h,SalReasonMedia,NULL);
		linphone_call_unref(call);
		return;
	}
	
	/* the call is acceptable so we can now add it to our list */
	linphone_core_add_call(lc,call);
	
	from_parsed=linphone_address_new(sal_op_get_from(h));
	linphone_address_clean(from_parsed);
	tmp=linphone_address_as_string(from_parsed);
	linphone_address_destroy(from_parsed);
	barmesg=ortp_strdup_printf("%s %s%s",tmp,_("is contacting you"),
	    (sal_call_autoanswer_asked(h)) ?_(" and asked autoanswer."):_("."));
	if (lc->vtable.show) lc->vtable.show(lc);
	if (lc->vtable.display_status) 
	    lc->vtable.display_status(lc,barmesg);

	/* play the ring if this is the only call*/
	if (lc->sound_conf.ring_sndcard!=NULL && ms_list_size(lc->calls)==1){
		lc->current_call=call;
		if (lc->ringstream && lc->dmfs_playing_start_time!=0){
			ring_stop(lc->ringstream);
			lc->ringstream=NULL;
			lc->dmfs_playing_start_time=0;
		}
		if(lc->ringstream==NULL && lc->sound_conf.local_ring){
			MSSndCard *ringcard=lc->sound_conf.lsd_card ?lc->sound_conf.lsd_card : lc->sound_conf.ring_sndcard;
			ms_message("Starting local ring...");
			lc->ringstream=ring_start(lc->sound_conf.local_ring,2000,ringcard);
		}
		else
		{
			ms_message("the local ring is already started");
		}
	}else{
		/*TODO : play a tone within the context of the current call */
	}

	
	linphone_call_ref(call); /*prevent the call from being destroyed while we are notifying, if the user declines within the state callback */
	linphone_call_set_state(call,LinphoneCallIncomingReceived,"Incoming call");
	
	if (call->state==LinphoneCallIncomingReceived){
		sal_call_notify_ringing(h,propose_early_media || ringback_tone!=NULL);

		if (propose_early_media || ringback_tone!=NULL){
			linphone_call_set_state(call,LinphoneCallIncomingEarlyMedia,"Incoming call early media");
			linphone_core_update_streams(lc,call,md);
		}
		if (sal_call_get_replaces(call->op)!=NULL && lp_config_get_int(lc->config,"sip","auto_answer_replacing_calls",1)){
			linphone_core_accept_call(lc,call);
		}
	}
	linphone_call_unref(call);

	ms_free(barmesg);
	ms_free(tmp);
}