コード例 #1
0
ファイル: sal.c プロジェクト: daniele88/linphone
void __sal_op_free(SalOp *op){
	SalOpBase *b=(SalOpBase *)op;
	if (b->from) {
		ms_free(b->from);
		b->from=NULL;
	}
	if (b->to) {
		ms_free(b->to);
		b->to=NULL;
	}
	if (b->route) {
		ms_free(b->route);
		b->route=NULL;
	}
	if (b->contact) {
		ms_free(b->contact);
		b->contact=NULL;
	}
	if (b->origin){
		ms_free(b->origin);
		b->origin=NULL;
	}
	if (b->remote_ua){
		ms_free(b->remote_ua);
		b->remote_ua=NULL;
	}
	if (b->local_media)
		sal_media_description_unref(b->local_media);
	if (b->remote_media)
		sal_media_description_unref(b->remote_media);
	if (b->call_id)
		ms_free((void*)b->call_id);
	ms_free(op);
}
コード例 #2
0
void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md){
	SalMediaDescription *oldmd=call->resultdesc;
	
	if (lc->ringstream!=NULL){
		ring_stop(lc->ringstream);
		lc->ringstream=NULL;
	}
	if (new_md!=NULL){
		sal_media_description_ref(new_md);
		call->media_pending=FALSE;
	}else{
		call->media_pending=TRUE;
	}
	call->resultdesc=new_md;
	if (call->audiostream && call->audiostream->ticker){
		/* we already started media: check if we really need to restart it*/
		if (oldmd){
			if (!media_parameters_changed(call,oldmd,new_md) && !call->playing_ringbacktone){
				sal_media_description_unref(oldmd);
				if (call->all_muted){
					ms_message("Early media finished, unmuting inputs...");
					/*we were in early media, now we want to enable real media */
					linphone_call_enable_camera (call,linphone_call_camera_enabled (call));
					if (call->audiostream)
						linphone_core_mute_mic (lc, linphone_core_is_mic_muted(lc));
#ifdef VIDEO_ENABLED
					if (call->videostream && call->camera_active)
						video_stream_change_camera(call->videostream,lc->video_conf.device );
#endif
				}
				ms_message("No need to restart streams, SDP is unchanged.");
				return;
			}else{
				ms_message("Media descriptions are different, need to restart the streams.");
			}
		}
		linphone_call_stop_media_streams (call);
		linphone_call_init_media_streams (call);
	}
	if (oldmd) 
		sal_media_description_unref(oldmd);
	
	if (new_md) {
		bool_t all_muted=FALSE;
		bool_t send_ringbacktone=FALSE;
		
		if (call->audiostream==NULL){
			/*this happens after pausing the call locally. The streams is destroyed and then we wait the 200Ok to recreate it*/
			linphone_call_init_media_streams (call);
		}
		if (call->state==LinphoneCallIncomingEarlyMedia && linphone_core_get_remote_ringback_tone (lc)!=NULL){
			send_ringbacktone=TRUE;
		}
		if (call->state==LinphoneCallIncomingEarlyMedia ||
		    (call->state==LinphoneCallOutgoingEarlyMedia && !call->params.real_early_media)){
			all_muted=TRUE;
		}
		linphone_call_start_media_streams(call,all_muted,send_ringbacktone);
	}
}
コード例 #3
0
ファイル: linphonecall.c プロジェクト: ApOgEE/linphone-sdk
static void linphone_call_destroy(LinphoneCall *obj)
{
	if (obj->op!=NULL) {
		sal_op_release(obj->op);
		obj->op=NULL;
	}
	if (obj->resultdesc!=NULL) {
		sal_media_description_unref(obj->resultdesc);
		obj->resultdesc=NULL;
	}
	if (obj->localdesc!=NULL) {
		sal_media_description_unref(obj->localdesc);
		obj->localdesc=NULL;
	}
	if (obj->ping_op) {
		sal_op_release(obj->ping_op);
	}
	if (obj->refer_to){
		ms_free(obj->refer_to);
	}
	if (obj->owns_call_log)
		linphone_call_log_destroy(obj->log);
	if (obj->auth_token) {
		ms_free(obj->auth_token);
	}

	ms_free(obj);
}
コード例 #4
0
ファイル: sal_op_call.c プロジェクト: Accontech/ace-ios
static void sal_op_reset_descriptions(SalOp *op) {
	if (op->base.remote_media){
		sal_media_description_unref(op->base.remote_media);
		op->base.remote_media=NULL;
	}
	if (op->result){
		sal_media_description_unref(op->result);
		op->result=NULL;
	}
}
コード例 #5
0
ファイル: sal_op_impl.c プロジェクト: 42p/linphone
void sal_op_release_impl(SalOp *op){
	ms_message("Destroying op [%p] of type [%s]",op,sal_op_type_to_string(op->type));
	if (op->pending_auth_transaction) belle_sip_object_unref(op->pending_auth_transaction);
	sal_remove_pending_auth(op->base.root,op);
	if (op->auth_info) {
		sal_auth_info_delete(op->auth_info);
	}
	if (op->sdp_answer) belle_sip_object_unref(op->sdp_answer);
	if (op->refresher) {
		belle_sip_object_unref(op->refresher);
		op->refresher=NULL;
	}
	if (op->result)
		sal_media_description_unref(op->result);
	if(op->replaces) belle_sip_object_unref(op->replaces);
	if(op->referred_by) belle_sip_object_unref(op->referred_by);

	if (op->pending_client_trans) belle_sip_object_unref(op->pending_client_trans);
	if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans);
	if (op->pending_update_server_trans) belle_sip_object_unref(op->pending_update_server_trans);
	if (op->event) belle_sip_object_unref(op->event);
	sal_error_info_reset(&op->error_info);
	__sal_op_free(op);
	return ;
}
コード例 #6
0
ファイル: sal_op_call.c プロジェクト: zengtaoxian/linphone
static void sdp_process(SalOp *h){
	ms_message("Doing SDP offer/answer process of type %s",h->sdp_offering ? "outgoing" : "incoming");
	if (h->result){
		sal_media_description_unref(h->result);
	}
	h->result=sal_media_description_new();
	if (h->sdp_offering){
		offer_answer_initiate_outgoing(h->base.local_media,h->base.remote_media,h->result);
	}else{
		int i;
		if (h->sdp_answer){
			belle_sip_object_unref(h->sdp_answer);
		}
		offer_answer_initiate_incoming(h->base.local_media,h->base.remote_media,h->result,h->base.root->one_matching_codec);
		h->sdp_answer=(belle_sdp_session_description_t *)belle_sip_object_ref(media_description_to_sdp(h->result));
		/*once we have generated the SDP answer, we modify the result description for processing by the upper layer.
		 It should contains media parameters constraint from the remote offer, not our response*/
		strcpy(h->result->addr,h->base.remote_media->addr);
		h->result->bandwidth=h->base.remote_media->bandwidth;

		for(i=0;i<h->result->n_active_streams;++i){
			strcpy(h->result->streams[i].rtp_addr,h->base.remote_media->streams[i].rtp_addr);
			h->result->streams[i].ptime=h->base.remote_media->streams[i].ptime;
			h->result->streams[i].bandwidth=h->base.remote_media->streams[i].bandwidth;
			h->result->streams[i].rtp_port=h->base.remote_media->streams[i].rtp_port;
			strcpy(h->result->streams[i].rtcp_addr,h->base.remote_media->streams[i].rtcp_addr);
			h->result->streams[i].rtcp_port=h->base.remote_media->streams[i].rtcp_port;

			if (h->result->streams[i].proto == SalProtoRtpSavp) {
				h->result->streams[i].crypto[0] = h->base.remote_media->streams[i].crypto[0];
			}
		}
	}

}
コード例 #7
0
ファイル: linphonecall.c プロジェクト: ApOgEE/linphone-sdk
void update_local_media_description(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription **md){
	if (*md == NULL) {
		*md = _create_local_media_description(lc,call,0,0);
	} else {
		unsigned int id = (*md)->session_id;
		unsigned int ver = (*md)->session_ver+1;
		sal_media_description_unref(*md);
		*md = _create_local_media_description(lc,call,id,ver);
	}
}
コード例 #8
0
ファイル: sal_op_call.c プロジェクト: Accontech/ace-ios
static void sdp_process(SalOp *h){
	ms_message("Doing SDP offer/answer process of type %s",h->sdp_offering ? "outgoing" : "incoming");
	if (h->result){
		sal_media_description_unref(h->result);
		h->result = NULL;
	}

	/* if SDP was invalid */
	if (h->base.remote_media == NULL) return;

	h->result=sal_media_description_new();
	if (h->sdp_offering){
		offer_answer_initiate_outgoing(h->base.local_media,h->base.remote_media,h->result);
	}else{
		int i;
		if (h->sdp_answer){
			belle_sip_object_unref(h->sdp_answer);
		}
		offer_answer_initiate_incoming(h->base.local_media,h->base.remote_media,h->result,h->base.root->one_matching_codec);
		/*for backward compatibility purpose*/
		if(h->cnx_ip_to_0000_if_sendonly_enabled && sal_media_description_has_dir(h->result,SalStreamSendOnly)) {
			set_addr_to_0000(h->result->addr);
			for(i=0;i<h->result->nb_streams;++i){
				if (h->result->streams[i].dir == SalStreamSendOnly)
						set_addr_to_0000(h->result->streams[i].rtp_addr);
						set_addr_to_0000(h->result->streams[i].rtcp_addr);
			}
		}
		h->sdp_answer=(belle_sdp_session_description_t *)belle_sip_object_ref(media_description_to_sdp(h->result));
		/*once we have generated the SDP answer, we modify the result description for processing by the upper layer.
		 It should contains media parameters constraint from the remote offer, not our response*/
		strcpy(h->result->addr,h->base.remote_media->addr);
		h->result->bandwidth=h->base.remote_media->bandwidth;

		for(i=0;i<h->result->nb_streams;++i){
			/*copy back parameters from remote description that we need in our result description*/
			if (h->result->streams[i].rtp_port!=0){ /*if stream was accepted*/
				strcpy(h->result->streams[i].rtp_addr,h->base.remote_media->streams[i].rtp_addr);
				h->result->streams[i].ptime=h->base.remote_media->streams[i].ptime;
				h->result->streams[i].bandwidth=h->base.remote_media->streams[i].bandwidth;
				h->result->streams[i].rtp_port=h->base.remote_media->streams[i].rtp_port;
				strcpy(h->result->streams[i].rtcp_addr,h->base.remote_media->streams[i].rtcp_addr);
				h->result->streams[i].rtcp_port=h->base.remote_media->streams[i].rtcp_port;

				if ((h->result->streams[i].proto == SalProtoRtpSavpf) || (h->result->streams[i].proto == SalProtoRtpSavp)) {
					h->result->streams[i].crypto[0] = h->base.remote_media->streams[i].crypto[0];
				}
			}
		}
	}
}
コード例 #9
0
ファイル: sal_op_call.c プロジェクト: Accontech/ace-ios
static void handle_sdp_from_response(SalOp* op,belle_sip_response_t* response) {
	belle_sdp_session_description_t* sdp;
	SalReason reason;
	if (op->base.remote_media){
		sal_media_description_unref(op->base.remote_media);
		op->base.remote_media=NULL;
	}
	if (extract_sdp(op,BELLE_SIP_MESSAGE(response),&sdp,&reason)==0) {
		if (sdp){
			op->base.remote_media=sal_media_description_new();
			sdp_to_media_description(sdp,op->base.remote_media);
		}/*if no sdp in response, what can we do ?*/
	}
	/* process sdp in any case to reset result media description*/
	if (op->base.local_media) sdp_process(op);
}
コード例 #10
0
ファイル: sal_op_call.c プロジェクト: Accontech/ace-ios
/*Call API*/
int sal_call_set_local_media_description(SalOp *op, SalMediaDescription *desc){
	if (desc)
		sal_media_description_ref(desc);
	if (op->base.local_media)
		sal_media_description_unref(op->base.local_media);
	op->base.local_media=desc;

	if (op->base.remote_media){
		/*case of an incoming call where we modify the local capabilities between the time
		 * the call is ringing and it is accepted (for example if you want to accept without video*/
		/*reset the sdp answer so that it is computed again*/
		if (op->sdp_answer){
			belle_sip_object_unref(op->sdp_answer);
			op->sdp_answer=NULL;
		}
	}
	return 0;
}
コード例 #11
0
void __sal_op_free(SalOp *op){
	SalOpBase *b=(SalOpBase *)op;
	if (b->from_address){
		sal_address_destroy(b->from_address);
		b->from_address=NULL;
	}
	if (b->to_address){
		sal_address_destroy(b->to_address);
		b->to_address=NULL;
	}
	
	if (b->service_route){
		sal_address_destroy(b->service_route);
		b->service_route=NULL;
	}
	
	if (b->origin_address){
		sal_address_destroy(b->origin_address);
		b->origin_address=NULL;
	}
	
	if (b->from) {
		ms_free(b->from);
		b->from=NULL;
	}
	if (b->to) {
		ms_free(b->to);
		b->to=NULL;
	}
	if (b->route) {
		ms_free(b->route);
		b->route=NULL;
	}
#ifndef USE_BELLESIP
	if (b->contact) {
		ms_free(b->contact);
		b->contact=NULL;
	}
#else
	if (b->contact_address) {
		sal_address_destroy(b->contact_address);
	}
#endif
	if (b->origin){
		ms_free(b->origin);
		b->origin=NULL;
	}
	if (b->remote_ua){
		ms_free(b->remote_ua);
		b->remote_ua=NULL;
	}
	if (b->remote_contact){
		ms_free(b->remote_contact);
		b->remote_contact=NULL;
	}
	if (b->local_media)
		sal_media_description_unref(b->local_media);
	if (b->remote_media)
		sal_media_description_unref(b->remote_media);
	if (b->call_id)
		ms_free((void*)b->call_id);
	if (b->service_route) {
		sal_address_destroy(b->service_route);
	}
	if (b->route_addresses){
		ms_list_for_each(b->route_addresses,(void (*)(void*)) sal_address_destroy);
		b->route_addresses=ms_list_free(b->route_addresses);
	}
	if (b->recv_custom_headers)
		sal_custom_header_free(b->recv_custom_headers);
	if (b->sent_custom_headers)
		sal_custom_header_free(b->sent_custom_headers);
	ms_free(op);
}
コード例 #12
0
ファイル: callbacks.c プロジェクト: korobool/liblinphone
void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md){
	SalMediaDescription *oldmd=call->resultdesc;
	bool_t all_muted=FALSE;
	bool_t send_ringbacktone=FALSE;

	linphone_core_stop_ringing(lc);
	if (!new_md) {
		ms_error("linphone_core_update_streams() called with null media description");
		return;
	}
	if (call->biggestdesc==NULL || new_md->n_total_streams>call->biggestdesc->n_total_streams){
		/*we have been offered and now are ready to proceed, or we added a new stream*/
		/*store the media description to remember the mapping of calls*/
		if (call->biggestdesc){
			sal_media_description_unref(call->biggestdesc);
			call->biggestdesc=NULL;
		}
		if (sal_call_is_offerer(call->op))
			call->biggestdesc=sal_media_description_ref(call->localdesc);
		else
			call->biggestdesc=sal_media_description_ref(sal_call_get_remote_media_description(call->op));
	}
	sal_media_description_ref(new_md);
	call->expect_media_in_ack=FALSE;
	call->resultdesc=new_md;
	if ((call->audiostream && call->audiostream->ms.ticker) || (call->videostream && call->videostream->ms.ticker)){
		/* we already started media: check if we really need to restart it*/
		if (oldmd){
			int md_changed = media_parameters_changed(call, oldmd, new_md);
			if ((md_changed & SAL_MEDIA_DESCRIPTION_CODEC_CHANGED) || call->playing_ringbacktone) {
				ms_message("Media descriptions are different, need to restart the streams.");
			} else {
				if (md_changed == SAL_MEDIA_DESCRIPTION_UNCHANGED) {
					if (call->all_muted){
						ms_message("Early media finished, unmuting inputs...");
						/*we were in early media, now we want to enable real media */
						linphone_call_enable_camera (call,linphone_call_camera_enabled (call));
						if (call->audiostream)
							linphone_core_enable_mic(lc, linphone_core_mic_enabled(lc));
#ifdef VIDEO_ENABLED
						if (call->videostream && call->camera_enabled)
							video_stream_change_camera(call->videostream,lc->video_conf.device );
#endif
					}
					ms_message("No need to restart streams, SDP is unchanged.");
					goto end;
				}else {
					if (md_changed & SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED) {
						ms_message("Network parameters have changed, update them.");
						linphone_core_update_streams_destinations(lc, call, oldmd, new_md);
					}
					if (md_changed & SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED) {
						ms_message("Crypto parameters have changed, update them.");
						linphone_call_update_crypto_parameters(call, oldmd, new_md);
					}
					goto end;
				}
			}
		}
		linphone_call_stop_media_streams (call);
		linphone_call_init_media_streams (call);
	}
	
	if (call->audiostream==NULL){
		/*this happens after pausing the call locally. The streams are destroyed and then we wait the 200Ok to recreate them*/
		linphone_call_init_media_streams (call);
	}
	if (call->state==LinphoneCallIncomingEarlyMedia && linphone_core_get_remote_ringback_tone (lc)!=NULL){
		send_ringbacktone=TRUE;
	}
	if (call->state==LinphoneCallIncomingEarlyMedia ||
		(call->state==LinphoneCallOutgoingEarlyMedia && !call->params.real_early_media)){
		all_muted=TRUE;
	}
	linphone_call_start_media_streams(call,all_muted,send_ringbacktone);
	if (call->state==LinphoneCallPausing && call->paused_by_app && ms_list_size(lc->calls)==1){
		linphone_core_play_named_tone(lc,LinphoneToneCallOnHold);
	}
	end:
	if (oldmd) 
		sal_media_description_unref(oldmd);
	
}
コード例 #13
0
ファイル: sal_op_call.c プロジェクト: Accontech/ace-ios
static void process_request_event(void *op_base, const belle_sip_request_event_t *event) {
	SalOp* op = (SalOp*)op_base;
	belle_sip_server_transaction_t* server_transaction=NULL;
	belle_sdp_session_description_t* sdp;
	belle_sip_request_t* req = belle_sip_request_event_get_request(event);
	belle_sip_dialog_state_t dialog_state;
	belle_sip_response_t* resp;
	belle_sip_header_t* call_info;
	const char *method=belle_sip_request_get_method(req);
	bool_t is_update=FALSE;

	if (strcmp("ACK",method)!=0){  /*ACK does'nt create srv transaction*/
		server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,belle_sip_request_event_get_request(event));
		belle_sip_object_ref(server_transaction);
		belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(server_transaction),sal_op_ref(op));
	}

	if (strcmp("INVITE",method)==0) {
		if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans);
		/*updating pending invite transaction*/
		op->pending_server_trans=server_transaction;
		belle_sip_object_ref(op->pending_server_trans);
	}

	if (strcmp("UPDATE",method)==0) {
		if (op->pending_update_server_trans) belle_sip_object_unref(op->pending_update_server_trans);
		/*updating pending update transaction*/
		op->pending_update_server_trans=server_transaction;
		belle_sip_object_ref(op->pending_update_server_trans);
	}

	if (!op->dialog) {
		set_or_update_dialog(op,belle_sip_provider_create_dialog(op->base.root->prov,BELLE_SIP_TRANSACTION(op->pending_server_trans)));
		ms_message("new incoming call from [%s] to [%s]",sal_op_get_from(op),sal_op_get_to(op));
	}
	dialog_state=belle_sip_dialog_get_state(op->dialog);
	switch(dialog_state) {
	case BELLE_SIP_DIALOG_NULL: {
		if (strcmp("INVITE",method)==0) {
			if (!op->replaces && (op->replaces=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_replaces_t))) {
				belle_sip_object_ref(op->replaces);
			} else if(op->replaces) {
				ms_warning("replace header already set");
			}

			if (process_sdp_for_invite(op,req) == 0) {
				if ((call_info=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Call-Info"))) {
					if( strstr(belle_sip_header_get_unparsed_value(call_info),"answer-after=") != NULL) {
						op->auto_answer_asked=TRUE;
						ms_message("The caller asked to automatically answer the call(Emergency?)\n");
					}
				}
				op->base.root->callbacks.call_received(op);
			}
			break;
		} /* else same behavior as for EARLY state*/
	}
	case BELLE_SIP_DIALOG_EARLY: {
		//hmm probably a cancel
		if (strcmp("CANCEL",method)==0) {
			if(belle_sip_request_event_get_server_transaction(event)) {
				/*first answer 200 ok to cancel*/
				belle_sip_server_transaction_send_response(server_transaction
						,sal_op_create_response_from_request(op,req,200));
				/*terminate invite transaction*/
				call_terminated(op
						,op->pending_server_trans
						,belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)),487);


			} else {
				/*call leg does not exist*/
				belle_sip_server_transaction_send_response(server_transaction
							,sal_op_create_response_from_request(op,req,481));
			}
		} else if (strcmp("PRACK",method)==0) {
			resp=sal_op_create_response_from_request(op,req,200);
			belle_sip_server_transaction_send_response(server_transaction,resp);
		} else if (strcmp("UPDATE",method)==0) {
			sal_op_reset_descriptions(op);
			if (process_sdp_for_invite(op,req)==0)
				op->base.root->callbacks.call_updating(op,TRUE);
		} else {
			belle_sip_error("Unexpected method [%s] for dialog state BELLE_SIP_DIALOG_EARLY",belle_sip_request_get_method(req));
			unsupported_method(server_transaction,req);
		}
		break;
	}
	case BELLE_SIP_DIALOG_CONFIRMED:
		/*great ACK received*/
		if (strcmp("ACK",method)==0) {
			if (op->sdp_offering){
				SalReason reason;
				if (extract_sdp(op,BELLE_SIP_MESSAGE(req),&sdp,&reason)==0){
					if (sdp){
						if (op->base.remote_media)
							sal_media_description_unref(op->base.remote_media);
						op->base.remote_media=sal_media_description_new();
						sdp_to_media_description(sdp,op->base.remote_media);
						sdp_process(op);
						belle_sip_object_unref(sdp);
					}else{
						ms_warning("SDP expected in ACK but not found.");
					}
				}
			}
			op->base.root->callbacks.call_ack(op);
		} else if(strcmp("BYE",method)==0) {
			resp=sal_op_create_response_from_request(op,req,200);
			belle_sip_server_transaction_send_response(server_transaction,resp);
			op->base.root->callbacks.call_terminated(op,op->dir==SalOpDirIncoming?sal_op_get_from(op):sal_op_get_to(op));
			op->state=SalOpStateTerminating;
			/*call end not notified by dialog deletion because transaction can end before dialog*/
		} else if(strcmp("INVITE",method)==0 || (is_update=(strcmp("UPDATE",method)==0)) ) {
			if (is_update && !belle_sip_message_get_body(BELLE_SIP_MESSAGE(req))) {
				/*session timer case*/
				/*session expire should be handled. to be done when real session timer (rfc4028) will be implemented*/
				resp=sal_op_create_response_from_request(op,req,200);
				belle_sip_server_transaction_send_response(server_transaction,resp);
				belle_sip_object_unref(op->pending_update_server_trans);
				op->pending_update_server_trans=NULL;
			} else {
				/*re-invite*/
				sal_op_reset_descriptions(op);
				if (process_sdp_for_invite(op,req)==0)
					op->base.root->callbacks.call_updating(op,is_update);
			}
		} else if (strcmp("INFO",method)==0){
			if (belle_sip_message_get_body(BELLE_SIP_MESSAGE(req))
				&&	strstr(belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)),"picture_fast_update")) {
				/*vfu request*/
				ms_message("Receiving VFU request on op [%p]",op);
				if (op->base.root->callbacks.vfu_request){
					op->base.root->callbacks.vfu_request(op);

				}
			}else{
				SalBody salbody;
				if (sal_op_get_body(op,(belle_sip_message_t*)req,&salbody)) {
					if (sal_body_has_type(&salbody,"application","dtmf-relay")){
						char tmp[10];
						if (sal_lines_get_value(salbody.data, "Signal",tmp, sizeof(tmp))){
							op->base.root->callbacks.dtmf_received(op,tmp[0]);
						}
					}else
						op->base.root->callbacks.info_received(op,&salbody);
				} else {
					op->base.root->callbacks.info_received(op,NULL);
				}
			}
			resp=sal_op_create_response_from_request(op,req,200);
			belle_sip_server_transaction_send_response(server_transaction,resp);
		}else if (strcmp("REFER",method)==0) {
			sal_op_process_refer(op,event,server_transaction);
		} else if (strcmp("NOTIFY",method)==0) {
			sal_op_call_process_notify(op,event,server_transaction);
		} else if (strcmp("OPTIONS",method)==0) {
			resp=sal_op_create_response_from_request(op,req,200);
			belle_sip_server_transaction_send_response(server_transaction,resp);
		} else if (strcmp("CANCEL",method)==0) {
			/*call leg does not exist because 200ok already sent*/
			belle_sip_server_transaction_send_response(server_transaction,sal_op_create_response_from_request(op,req,481));
		} else if (strcmp("MESSAGE",method)==0){
			sal_process_incoming_message(op,event);
		}else{
			ms_error("unexpected method [%s] for dialog [%p]",belle_sip_request_get_method(req),op->dialog);
			unsupported_method(server_transaction,req);
		}
		break;
	default:
		ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state));
		break;
	}

	if (server_transaction) belle_sip_object_unref(server_transaction);

}
コード例 #14
0
ファイル: sal_op_call.c プロジェクト: zengtaoxian/linphone
static void process_request_event(void *op_base, const belle_sip_request_event_t *event) {
	SalOp* op = (SalOp*)op_base;
	belle_sip_server_transaction_t* server_transaction=NULL;
	belle_sdp_session_description_t* sdp;
	belle_sip_request_t* req = belle_sip_request_event_get_request(event);
	belle_sip_dialog_state_t dialog_state;
	belle_sip_response_t* resp;
	belle_sip_header_t* call_info;

	if (strcmp("ACK",belle_sip_request_get_method(req))!=0){  /*ACK does'nt create srv transaction*/
		server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,belle_sip_request_event_get_request(event));
		belle_sip_object_ref(server_transaction);
		belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(server_transaction),op);
		sal_op_ref(op);
	}

	if (strcmp("INVITE",belle_sip_request_get_method(req))==0) {
		if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans);
		/*updating pending invite transaction*/
		op->pending_server_trans=server_transaction;
		belle_sip_object_ref(op->pending_server_trans);
	}

	if (!op->dialog) {
		set_or_update_dialog(op,belle_sip_provider_create_dialog(op->base.root->prov,BELLE_SIP_TRANSACTION(op->pending_server_trans)));
		ms_message("new incoming call from [%s] to [%s]",sal_op_get_from(op),sal_op_get_to(op));
	}
	dialog_state=belle_sip_dialog_get_state(op->dialog);
	switch(dialog_state) {

	case BELLE_SIP_DIALOG_NULL: {
		if (strcmp("INVITE",belle_sip_request_get_method(req))==0) {
			if (!op->replaces && (op->replaces=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_replaces_t))) {
				belle_sip_object_ref(op->replaces);
			} else if(op->replaces) {
				ms_warning("replace header already set");
			}

			process_sdp_for_invite(op,req);

			if ((call_info=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Call-Info"))) {
				if( strstr(belle_sip_header_extension_get_value(BELLE_SIP_HEADER_EXTENSION(call_info)),"answer-after=") != NULL) {
					op->auto_answer_asked=TRUE;
					ms_message("The caller asked to automatically answer the call(Emergency?)\n");
				}
			}

			op->base.root->callbacks.call_received(op);

			break;
		} /* else same behavior as for EARLY state*/
	}
	case BELLE_SIP_DIALOG_EARLY: {
		//hmm probably a cancel
		if (strcmp("CANCEL",belle_sip_request_get_method(req))==0) {
			if(belle_sip_request_event_get_server_transaction(event)) {
				/*first answer 200 ok to cancel*/
				belle_sip_server_transaction_send_response(server_transaction
						,sal_op_create_response_from_request(op,req,200));
				/*terminate invite transaction*/
				call_terminated(op
						,op->pending_server_trans
						,belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)),487);


			} else {
				/*call leg does not exist*/
				belle_sip_server_transaction_send_response(server_transaction
							,sal_op_create_response_from_request(op,req,481));
			}
		} else if (strcmp("PRACK",belle_sip_request_get_method(req))==0) {
			resp=sal_op_create_response_from_request(op,req,200);
			belle_sip_server_transaction_send_response(server_transaction,resp);
		} else {
			belle_sip_error("Unexpected method [%s] for dialog state BELLE_SIP_DIALOG_EARLY",belle_sip_request_get_method(req));
			unsupported_method(server_transaction,req);
		}
		break;
	}
	case BELLE_SIP_DIALOG_CONFIRMED:
		/*great ACK received*/
		if (strcmp("ACK",belle_sip_request_get_method(req))==0) {
			if (op->sdp_offering){
				if ((sdp=belle_sdp_session_description_create(BELLE_SIP_MESSAGE(req)))){
					if (op->base.remote_media)
						sal_media_description_unref(op->base.remote_media);
					op->base.remote_media=sal_media_description_new();
					sdp_to_media_description(sdp,op->base.remote_media);
					sdp_process(op);
					belle_sip_object_unref(sdp);
				}
			}
			/*FIXME
		if (op->reinvite){
			op->reinvite=FALSE;
		}*/
			op->base.root->callbacks.call_ack(op);
		} else if(strcmp("BYE",belle_sip_request_get_method(req))==0) {
			resp=sal_op_create_response_from_request(op,req,200);
			belle_sip_server_transaction_send_response(server_transaction,resp);
			op->base.root->callbacks.call_terminated(op,op->dir==SalOpDirIncoming?sal_op_get_from(op):sal_op_get_to(op));
			op->state=SalOpStateTerminating;
			/*call end not notified by dialog deletion because transaction can end before dialog*/
		} else if(strcmp("INVITE",belle_sip_request_get_method(req))==0) {
			/*re-invite*/
			if (op->base.remote_media){
				sal_media_description_unref(op->base.remote_media);
				op->base.remote_media=NULL;
			}
			if (op->result){
				sal_media_description_unref(op->result);
				op->result=NULL;
			}
			process_sdp_for_invite(op,req);

			op->base.root->callbacks.call_updating(op);
		} else if (strcmp("INFO",belle_sip_request_get_method(req))==0){
			if (belle_sip_message_get_body(BELLE_SIP_MESSAGE(req))
				&&	strstr(belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)),"picture_fast_update")) {
				/*vfu request*/
				ms_message("Receiving VFU request on op [%p]",op);
				if (op->base.root->callbacks.vfu_request){
					op->base.root->callbacks.vfu_request(op);

				}
			}else{
				SalBody salbody;
				if (sal_op_get_body(op,(belle_sip_message_t*)req,&salbody)) {
					op->base.root->callbacks.info_received(op,&salbody);
				} else {
					op->base.root->callbacks.info_received(op,NULL);
				}
			}
			resp=sal_op_create_response_from_request(op,req,200);
			belle_sip_server_transaction_send_response(server_transaction,resp);
		}else if (strcmp("REFER",belle_sip_request_get_method(req))==0) {
			sal_op_process_refer(op,event,server_transaction);
		} else if (strcmp("NOTIFY",belle_sip_request_get_method(req))==0) {
			sal_op_call_process_notify(op,event,server_transaction);
		} else if (strcmp("OPTIONS",belle_sip_request_get_method(req))==0) {
			resp=sal_op_create_response_from_request(op,req,200);
			belle_sip_server_transaction_send_response(server_transaction,resp);
		} else if (strcmp("CANCEL",belle_sip_request_get_method(req))==0) {
			/*call leg does not exist because 200ok already sent*/
			belle_sip_server_transaction_send_response(	server_transaction
														,sal_op_create_response_from_request(op,req,481));

		} else{
			ms_error("unexpected method [%s] for dialog [%p]",belle_sip_request_get_method(req),op->dialog);
			unsupported_method(server_transaction,req);
		}
		break;
	default: {
		ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state));
	}
	/* no break */
	}

	if (server_transaction) belle_sip_object_unref(server_transaction);

}
コード例 #15
0
ファイル: sal.c プロジェクト: artur/linphone
void __sal_op_free(SalOp *op){
	SalOpBase *b=(SalOpBase *)op;
	if (b->from_address){
		sal_address_destroy(b->from_address);
		b->from_address=NULL;
	}
	if (b->to_address){
		sal_address_destroy(b->to_address);
		b->to_address=NULL;
	}

	if (b->service_route){
		sal_address_destroy(b->service_route);
		b->service_route=NULL;
	}

	if (b->origin_address){
		sal_address_destroy(b->origin_address);
		b->origin_address=NULL;
	}

	if (b->from) {
		ms_free(b->from);
		b->from=NULL;
	}
	if (b->to) {
		ms_free(b->to);
		b->to=NULL;
	}
	if (b->route) {
		ms_free(b->route);
		b->route=NULL;
	}
	if (b->realm) {
		ms_free(b->realm);
		b->realm=NULL;
	}
	if (b->contact_address) {
		sal_address_destroy(b->contact_address);
	}
	if (b->origin){
		ms_free(b->origin);
		b->origin=NULL;
	}
	if (b->remote_ua){
		ms_free(b->remote_ua);
		b->remote_ua=NULL;
	}
	if (b->remote_contact){
		ms_free(b->remote_contact);
		b->remote_contact=NULL;
	}
	if (b->remote_contact_address){
		sal_address_destroy(b->remote_contact_address);
	}
	if (b->local_media)
		sal_media_description_unref(b->local_media);
	if (b->remote_media)
		sal_media_description_unref(b->remote_media);
	if (b->call_id)
		ms_free((void*)b->call_id);
	if (b->service_route) {
		sal_address_destroy(b->service_route);
	}
	if (b->route_addresses){
		bctbx_list_for_each(b->route_addresses,(void (*)(void*)) sal_address_destroy);
		b->route_addresses=bctbx_list_free(b->route_addresses);
	}
	if (b->recv_custom_headers)
		sal_custom_header_free(b->recv_custom_headers);
	if (b->sent_custom_headers)
		sal_custom_header_free(b->sent_custom_headers);
	
	if (b->entity_tag != NULL){
		ms_free(b->entity_tag);
		b->entity_tag = NULL;
	}
	ms_free(op);
}