case EXOSIP_CALL_INVITE:表示收到了一个呼叫的消息。执行:inc_new_call(Sal *sal, eXosip_event_t *ev);
static void inc_new_call(Sal *sal, eXosip_event_t *ev){
SalOp *op=sal_op_new(sal);
osip_from_t *from,*to;
osip_call_info_t *call_info;
char *tmp=NULL;
sdp_message_t *sdp=eXosip_get_sdp_info(ev->request);s得到sdp信息
osip_call_id_t *callid=osip_message_get_call_id(ev->request);
osip_call_id_to_str(callid,&tmp);
op->base.call_id=ms_strdup(tmp);
osip_free(tmp);
取一些参数如:origin
ua,replaces,from ,to ,sdp,call_info,tid,cid, did,等等
set_network_origin(op,ev->request);
set_remote_contact(op,ev->request);
set_remote_ua(op,ev->request);
set_replaces(op,ev->request);
sal_op_set_custom_header(op,sal_exosip_get_custom_headers(ev->request));
if (sdp){
op->sdp_offering=FALSE;
op->base.remote_media=sal_media_description_new();
sdp_to_media_description(sdp,op->base.remote_media);
sdp_message_free(sdp);
}else op->sdp_offering=TRUE;
from=osip_message_get_from(ev->request);
to=osip_message_get_to(ev->request);
osip_from_to_str(from,&tmp);
sal_op_set_from(op,tmp);
osip_free(tmp);
osip_from_to_str(to,&tmp);
sal_op_set_to(op,tmp);
osip_free(tmp);
osip_message_get_call_info(ev->request,0,&call_info);
if(call_info)
{
osip_call_info_to_str(call_info,&tmp);
if( strstr(tmp,"answer-after=") != NULL)
{
op->auto_answer_asked=TRUE;
ms_message("The caller asked to automatically answer the call(Emergency?)\n");
}
osip_free(tmp);
}
op->tid=ev->tid;
op->cid=ev->cid;
op->did=ev->did;
sal_add_call(op->base.root,op);
sal->callbacks.call_received(op);
}
static void call_received(SalOp *h)
{
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h));
LinphoneCall *call;
const char *from,*to;
LinphoneAddress *from_addr, *to_addr;
bool_t prevent_colliding_calls=lp_config_get_int(lc->config,"sip","prevent_colliding_calls",TRUE);
/* 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 ((already_a_call_with_remote_address(lc,from_addr) && prevent_colliding_calls) || already_a_call_pending(lc)){
ms_warning("Receiving another call while one is ringing or initiated, refusing this one with busy message.");
sal_call_decline(h,SalReasonBusy,NULL);
sal_op_release(h);
linphone_address_destroy(from_addr);
linphone_address_destroy(to_addr);
return;
}
call=linphone_call_new_incoming(lc,from_addr,to_addr,h);
/* the call is acceptable so we can now add it to our list */
linphone_core_add_call(lc,call);
linphone_call_ref(call); /*prevent the call from being destroyed while we are notifying, if the user declines within the state callback */
if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)) {
/* Defer ringing until the end of the ICE candidates gathering process. */
ms_message("Defer ringing to gather ICE candidates");
return;
}
#ifdef BUILD_UPNP
if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseUpnp) && (call->upnp_session != NULL)) {
/* Defer ringing until the end of the ICE candidates gathering process. */
ms_message("Defer ringing to gather uPnP candidates");
return;
}
#endif //BUILD_UPNP
linphone_core_notify_incoming_call(lc,call);
}
LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op){
LinphoneCall *call=ms_new0(LinphoneCall,1);
char *from_str;
const SalMediaDescription *md;
call->dir=LinphoneCallIncoming;
sal_op_set_user_pointer(op,call);
call->op=op;
call->core=lc;
判决是否发ping指令
if (lc->sip_conf.ping_with_options){
#ifdef BUILD_UPNP
if (lc->upnp != NULL && linphone_core_get_firewall_policy(lc)==LinphonePolicyUseUpnp &&
linphone_upnp_context_get_state(lc->upnp) == LinphoneUpnpStateOk) {
#else //BUILD_UPNP
{
#endif //BUILD_UPNP
/*the following sends an option request back to the caller so that
we get a chance to discover our nat'd address before answering.*/
call->ping_op=sal_op_new(lc->sal);
from_str=linphone_address_as_string_uri_only(from);
sal_op_set_route(call->ping_op,sal_op_get_network_origin(op));
sal_op_set_user_pointer(call->ping_op,call);
sal_ping(call->ping_op,linphone_core_find_best_identity(lc,from,NULL),from_str);
ms_free(from_str);
}
}
linphone_address_clean(from);
linphone_core_get_local_ip(lc,NULL,call->localip);
linphone_call_init_common(call, from, to); init一个call
call->log->call_id=ms_strdup(sal_op_get_call_id(op)); /*must be known at that time*/
linphone_core_init_default_params(lc, &call->params);
md=sal_call_get_remote_media_description(op); 拿到发送过来的SDP
call->params.has_video &= !!lc->video_policy.automatically_accept;
if (md) {
// It is licit to receive an INVITE without SDP
// In this case WE chose the media parameters according to policy.
call->params.has_video &= linphone_core_media_description_contains_video_stream(md);
}
switch (linphone_core_get_firewall_policy(call->core)) {
case LinphonePolicyUseIce:
call->ice_session = ice_session_new();
ice_session_set_role(call->ice_session, IR_Controlled);
linphone_core_update_ice_from_remote_media_description(call, sal_call_get_remote_media_description(op));
if (call->ice_session != NULL) {
linphone_call_init_media_streams(call);
linphone_call_start_media_streams_for_ice_gathering(call);
if (linphone_core_gather_ice_candidates(call->core,call)<0) {
/* Ice candidates gathering failed, proceed with the call anyway. */
linphone_call_delete_ice_session(call);
linphone_call_stop_media_streams_for_ice_gathering(call);
}
}
break;
case LinphonePolicyUseStun:
call->ping_time=linphone_core_run_stun_tests(call->core,call);
/* No break to also destroy ice session in this case. */
break;
case LinphonePolicyUseUpnp:
#ifdef BUILD_UPNP
if(!lc->rtp_conf.disable_upnp) {
call->upnp_session = linphone_upnp_session_new(call);
if (call->upnp_session != NULL) {
linphone_call_init_media_streams(call);
if (linphone_core_update_upnp_from_remote_media_description(call, sal_call_get_remote_media_description(op))<0) {
/* uPnP port mappings failed, proceed with the call anyway. */
linphone_call_delete_upnp_session(call);
}
}
}
#endif //BUILD_UPNP
break;
default:
break;
}
call->camera_active=call->params.has_video;
discover_mtu(lc,linphone_address_get_domain(from));
return call;
}
void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call)
{
char *barmesg;
char *tmp;
LinphoneAddress *from_parsed;
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);
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);开始进行sdp,媒体类型协商
if (md){
if (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md)){
sal_call_decline(call->op,SalReasonMedia,NULL);
linphone_call_unref(call);
return;
}
}
from_parsed=linphone_address_new(sal_op_get_from(call->op));
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(call->op)) ?_(" and asked autoanswer."):_("."));
if (lc->vtable.show) lc->vtable.show(lc);
if (lc->vtable.display_status)
lc->vtable.display_status(lc,barmesg);提示电话来了的消息//XX is contacting you?
/* play the ring if this is the only call*/
if (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->sound_conf.ring_sndcard!=NULL){
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...");
与此同时,开始ring_start(),播放ringback(
lc->ringstream=ring_start(lc->sound_conf.local_ring,2000,ringcard);
}
else
{
ms_message("the local ring is already started");
}
}
}else{
/* else play a tone within the context of the current call */
call->ringing_beep=TRUE;
linphone_core_play_named_tone(lc,LinphoneToneCallWaiting);
}
linphone_call_set_state(call,LinphoneCallIncomingReceived,"Incoming call");
if (call->state==LinphoneCallIncomingReceived){
同时发180消息
sal_call_notify_ringing(call->op,propose_early_media || ringback_tone!=NULL);
if (propose_early_media || ringback_tone!=NULL){
linphone_call_set_state(call,LinphoneCallIncomingEarlyMedia,"Incoming call early media");
md=sal_call_get_final_media_description(call->op);
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);
}
Answer 这个call linphone_core_accept_call