From 0267c3213f4af3140959f73fcf95b87e641ed7a3 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Mon, 1 Feb 2010 18:30:15 +0100 Subject: [PATCH] work in progress --- coreapi/Makefile.am | 1 - coreapi/callbacks.c | 279 +++++++++++++++++++++++++++- coreapi/linphonecore.c | 408 ++++++++++++++++------------------------- coreapi/private.h | 11 +- coreapi/sal.c | 9 + coreapi/sal.h | 14 +- coreapi/sal_eXosip2.c | 107 ++++++++++- coreapi/sal_eXosip2.h | 2 +- 8 files changed, 554 insertions(+), 277 deletions(-) diff --git a/coreapi/Makefile.am b/coreapi/Makefile.am index 2410f2d4e..517780594 100644 --- a/coreapi/Makefile.am +++ b/coreapi/Makefile.am @@ -21,7 +21,6 @@ liblinphone_la_SOURCES=\ sal_eXosip2_sdp.c \ sal_eXosip2_presence.c \ callbacks.c \ - exevents.c sdphandler.c\ misc.c \ address.c \ enum.c enum.h \ diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 73eeca56e..08267a30d 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -23,28 +23,301 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "linphonecore.h" #include "private.h" +static void linphone_connect_incoming(LinphoneCore *lc, LinphoneCall *call){ + if (lc->vtable.show) + lc->vtable.show(lc); + if (lc->vtable.display_status) + lc->vtable.display_status(lc,_("Connected.")); + call->state=LCStateAVRunning; + if (lc->ringstream!=NULL){ + ring_stop(lc->ringstream); + lc->ringstream=NULL; + } + linphone_core_start_media_streams(lc,call); +} + static void call_received(SalOp *h){ + LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h)); + char *barmesg; + int err; + LinphoneCall *call; + const char *from,*to; + char *tmp; + LinphoneAddress *from_parsed; + + /* first check if we can answer successfully to this invite */ + if (lc->presence_mode!=LINPHONE_STATUS_ONLINE){ + ms_message("Not present !! presence mode : %d\n",lc->presence_mode); + if (lc->presence_mode==LINPHONE_STATUS_BUSY) + sal_call_decline(h,SalReasonBusy,NULL); + else if (lc->presence_mode==LINPHONE_STATUS_AWAY + ||lc->presence_mode==LINPHONE_STATUS_BERIGHTBACK + ||lc->presence_mode==LINPHONE_STATUS_ONTHEPHONE + ||lc->presence_mode==LINPHONE_STATUS_OUTTOLUNCH + ||lc->presence_mode==LINPHONE_STATUS_OFFLINE) + sal_call_decline(h,SalReasonTemporarilyUnavailable,NULL); + else if (lc->presence_mode==LINPHONE_STATUS_NOT_DISTURB) + sal_call_decline(h,SalReasonTemporarilyUnavailable,NULL); + else if (lc->alt_contact!=NULL && lc->presence_mode==LINPHONE_STATUS_MOVED) + sal_call_decline(h,SalReasonRedirect,lc->alt_contact); + else + sal_call_decline(h,SalReasonBusy,NULL); + sal_op_release(op); + return; + } + if (lc->call!=NULL){/*busy*/ + sal_call_decline(h,SalReasonBusy,NULL); + sal_op_release(op); + return; + } + from=sal_op_get_from(op); + to=sal_op_get_to(op); + + call=linphone_call_new_incoming(lc,linphone_address_new(from),linphone_address_new(to),op); + lc->call=call; + sal_call_set_local_media_description(op,call->localdesc); + call->resultdesc=sal_call_get_final_media_description(op); + if (call->resultdesc && sal_media_description_empty(call->resultdesc){ + sal_call_decline(op,SalReasonMedia,NULL); + linphone_call_destroy(call); + lc->call=NULL; + return; + } + + from_parsed=linphone_address_new(sal_op_get_from(op)); + linphone_address_clean(from_parsed); + tmp=linphone_address_as_string(from_parsed); + linphone_address_destroy(from_parsed); + gstate_new_state(lc, GSTATE_CALL_IN_INVITE, tmp); + barmesg=ortp_strdup_printf("%s %s",tmp,_("is contacting you.")); + if (lc->vtable.show) lc->vtable.show(lc); + if (lc->vtable.display_status) + lc->vtable.display_status(lc,barmesg); + + /* play the ring */ + if (lc->sound_conf.ring_sndcard!=NULL){ + ms_message("Starting local ring..."); + lc->ringstream=ring_start(lc->sound_conf.local_ring,2000,lc->sound_conf.ring_sndcard); + } + linphone_call_set_state(call,LCStateRinging); + sal_call_notify_ringing(op); + + if (lc->vtable.inv_recv) lc->vtable.inv_recv(lc,tmp); + ms_free(barmesg); + ms_free(tmp); } static void call_ringing(SalOp *h){ + LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h)); + LinphoneCall *call=lc->call; + SalMediaDescription *md; + if (call==NULL) return; + if (lc->vtable.display_status) + lc->vtable.display_status(lc,_("Remote ringing.")); + md=sal_call_get_final_media_description(h); + if (md==NULL){ + if (lc->ringstream!=NULL) return; /*already ringing !*/ + if (lc->sound_conf.play_sndcard!=NULL){ + ms_message("Remote ringing..."); + lc->ringstream=ring_start(lc->sound_conf.remote_ring,2000,lc->sound_conf.play_sndcard); + } + }else{ + /*accept early media */ + if (lc->audiostream->ticker!=NULL){ + /*streams already started */ + ms_message("Early media already started."); + return; + } + sal_media_description_ref(md); + call->resultdesc=md; + if (lc->vtable.show) lc->vtable.show(lc); + if (lc->vtable.display_status) + lc->vtable.display_status(lc,_("Early media.")); + gstate_new_state(lc, GSTATE_CALL_OUT_CONNECTED, NULL); + if (lc->ringstream!=NULL){ + ring_stop(lc->ringstream); + lc->ringstream=NULL; + } + ms_message("Doing early media..."); + linphone_core_start_media_streams(lc,call); + } + call->state=LCStateRinging; } -static void call_accepted(SalOp *h){ +static void call_accepted(SalOp *op){ + LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h)); + LinphoneCall *call=lc->call; + if (call==NULL){ + ms_warning("No call to accept."); + return 0; + } + if (sal_op_get_user_pointer(op)!=lc->call){ + ms_warning("call_accepted: ignoring."); + return; + } + if (call->state==LCStateAVRunning){ + return 0; /*already accepted*/ + } + if (lc->audiostream->ticker!=NULL){ + /*case where we accepted early media */ + linphone_core_stop_media_streams(lc,call); + linphone_core_init_media_streams(lc,call); + } + if (call->resultdesc) + sal_media_description_unref(call->resultdesc); + call->resultdesc=sal_call_get_final_media_description(op); + if (call->resultdesc && !sal_media_description_empty(call->resultdesc)){ + gstate_new_state(lc, GSTATE_CALL_OUT_CONNECTED, NULL); + linphone_connect_incoming(lc,call); + }else{ + /*send a bye*/ + ms_error("Incompatible SDP offer received in 200Ok, need to abort the call"); + linphone_core_terminate_call(lc,NULL); + } } static void call_ack(SalOp *h){ + LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h)); + LinphoneCall *call=lc->call; + if (call==NULL){ + ms_warning("No call to be ACK'd"); + return ; + } + if (sal_op_get_user_pointer(op)!=lc->call){ + ms_warning("call_ack: ignoring."); + return; + } + if (lc->audiostream->ticker!=NULL){ + /*case where we accepted early media */ + linphone_core_stop_media_streams(lc,call); + linphone_core_init_media_streams(lc,call); + } + if (call->resultdesc) + sal_media_description_unref(call->resultdesc); + call->resultdesc=sal_call_get_final_media_description(op); + if (call->resultdesc && !sal_media_description_empty(call->resultdesc)){ + gstate_new_state(lc, GSTATE_CALL_IN_CONNECTED, NULL); + linphone_connect_incoming(lc,call); + }else{ + /*send a bye*/ + ms_error("Incompatible SDP response received in ACK, need to abort the call"); + linphone_core_terminate_call(lc,NULL); + } } static void call_updated(SalOp *){ + LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h)); + linphone_core_stop_media_streams(lc,call); + linphone_core_init_media_streams(lc,call); + if (call->resultdesc) + sal_media_description_unref(call->resultdesc); + call->resultdesc=sal_call_get_final_media_description(op); + if (call->resultdesc && !sal_media_description_empty(call->resultdesc)){ + linphone_connect_incoming(lc,call); + } } -static void call_terminated(SalOp *h){ +static void call_terminated(SalOp *h, const char *from){ + LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h)); + if (sal_op_get_user_pointer(op)!=lc->call){ + ms_warning("call_terminated: ignoring."); + return; + } + ms_message("Current call terminated..."); + if (lc->ringstream!=NULL) { + ring_stop(lc->ringstream); + lc->ringstream=NULL; + } + linphone_core_stop_media_streams(lc,lc->call); + lc->vtable.show(lc); + lc->vtable.display_status(lc,_("Call terminated.")); + gstate_new_state(lc, GSTATE_CALL_END, NULL); + if (lc->vtable.bye_recv!=NULL){ + LinphoneAddress *addr=linphone_address_new(from); + char *tmp; + linphone_address_clean(addr); + tmp=linphone_address_as_string(from); + lc->vtable.bye_recv(lc,tmp); + ms_free(tmp); + linphone_address_destroy(addr); + } + linphone_call_destroy(lc->call); + lc->call=NULL; } -static void call_failure(SalOp *h, SalError error, SalReason reason, const char *details){ +static void call_failure(SalOp *op, SalError error, SalReason sr, const char *details){ + LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h)); + const char *reason=""; + char *msg486=_("User is busy."); + char *msg480=_("User is temporarily unavailable."); + /*char *retrymsg=_("%s. Retry after %i minute(s).");*/ + char *msg600=_("User does not want to be disturbed."); + char *msg603=_("Call declined."); + char* tmpmsg=msg486; + int code; + LinphoneCall *call=lc->call; + if (sal_op_get_user_pointer(op)!=lc->call){ + ms_warning("call_failure: ignoring."); + return; + } + if (lc->vtable.show) lc->vtable.show(lc); + + if (error==SalErrorNoResponse){ + if (lc->vtale.display_status) + lc->vtable.display_status(lc,_("No response.")); + }else if (error==SalErrorProtocol){ + if (lc->vtale.display_status) + lc->vtable.display_status(lc, details ? details : _("Error.")); + }else if (error==SalErrorFailure){ + switch(sr){ + case SalReasonDeclined: + if (lc->vtable.display_status) + lc->vtable.display_status(lc,msg603); + break; + case SalReasonBusy: + if (lc->vtable.display_status) + lc->vtable.display_status(lc,msg486); + break; + case SalReasonRedirect: + if (lc->vtable.display_status) + lc->vtable.display_status(lc,_("Redirected")); + break; + case SalReasonTemporarilyUnavailable: + if (lc->vtable.display_status) + lc->vtable.display_status(lc,msg480); + break; + case SalReasonNotFound: + if (lc->vtable.display_status) + lc->vtable.display_status(lc,msg404); + break; + case SalReasonDoNotDisturb: + if (lc->vtable.display_status) + lc->vtable.display_status(lc,msg600); + break; + case SalReasonMedia: + if (lc->vtable.display_status) + lc->vtable.display_status(lc,_("No common codecs")); + break; + default: + if (lc->vtable.display_status) + lc->vtable.display_status(lc,_("Call failed.")); + } + } + if (lc->ringstream!=NULL) { + ring_stop(lc->ringstream); + lc->ringstream=NULL; + } + linphone_core_stop_media_streams(lc); + if (call!=NULL) { + linphone_call_destroy(call); + gstate_new_state(lc, GSTATE_CALL_ERROR, NULL); + lc->call=NULL; + } } static void auth_requested(SalOp *h, const char *realm, const char *username){ + LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h)); + LinphoneAuthInfo *ai=linphone_core_find_auth_info(lc); } static void auth_success(SalOp *h, const char *realm, const char *username){ diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index f9f47c9e4..33a8d588c 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -115,7 +115,6 @@ static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from, linphone_core_notify_all_friends(call->core,LINPHONE_STATUS_ONTHEPHONE); if (linphone_core_get_firewall_policy(call->core)==LINPHONE_POLICY_USE_STUN) linphone_core_run_stun_tests(call->core,call); - call->profile=rtp_profile_new("Call RTP profile"); } static void discover_mtu(LinphoneCore *lc, const char *remote){ @@ -136,6 +135,7 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr LinphoneCall *call=ms_new0(LinphoneCall,1); call->dir=LinphoneCallOutgoing; call->op=sal_op_new(lc->sal); + sal_op_set_user_pointer(call->op,lc->call); call->core=lc; linphone_core_get_local_ip(lc,linphone_address_get_domain(to),call->localip); call->localdesc=create_local_media_description (lc,call->localip, @@ -150,6 +150,7 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro LinphoneAddress *me=linphone_core_get_primary_contact_parsed(lc); call->dir=LinphoneCallIncoming; + sal_op_set_user_pointer(op,call); call->op=op; call->core=lc; @@ -168,7 +169,6 @@ void linphone_call_destroy(LinphoneCall *obj) linphone_core_notify_all_friends(obj->core,obj->core->prev_mode); linphone_call_log_completed(obj->log,obj); linphone_core_update_allocated_audio_bandwidth(obj->core); - if (obj->profile!=NULL) rtp_profile_destroy(obj->profile); if (obj->op!=NULL) sal_op_release(obj->op); if (obj->resultdesc!=NULL) sal_media_description_unref(obj->resultdesc); if (obj->localdesc!=NULL) sal_media_description_unref(obj->localdesc); @@ -910,6 +910,7 @@ static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vta lc->rpc_enable = 0; #endif lc->sal=sal_init(); + sal_set_user_pointer(lc->sal,lc); if (lp_config_get_int(lc->config,"sip","use_session_timers",0)==1){ sal_use_session_timers(lc->sal,200); } @@ -1313,7 +1314,7 @@ void linphone_core_set_sip_port(LinphoneCore *lc,int port) ms_free(msg); return; } - apply_user_agent(lc->sal); + apply_user_agent(lc); } /** @@ -1368,7 +1369,7 @@ static void proxy_update(LinphoneCore *lc, time_t curtime){ if (last_check==0 || (curtime-last_check)>=5){ sal_get_default_local_ip(lc->sal, lc->sip_conf.ipv6_enabled ? AF_INET6 : AF_INET, - ,result,LINPHONE_IPADDR_SIZE); + result,LINPHONE_IPADDR_SIZE); if (strcmp(result,"::1")!=0 && strcmp(result,"127.0.0.1")!=0){ last_status=TRUE; ms_message("Network is up, registering now (%s)",result); @@ -1465,14 +1466,12 @@ static void linphone_core_do_plugin_tasks(LinphoneCore *lc){ * other liblinphone methods. In not the case make sure all liblinphone calls are * serialized with a mutex. **/ -void linphone_core_iterate(LinphoneCore *lc) -{ - eXosip_event_t *ev; - bool_t disconnected=FALSE; +void linphone_core_iterate(LinphoneCore *lc){ int disconnect_timeout = linphone_core_get_nortp_timeout(lc); time_t curtime=time(NULL); int elapsed; bool_t one_second_elapsed=FALSE; + bool_t disconnected=FALSE; if (curtime-lc->prevtime>=1){ lc->prevtime=curtime; @@ -1539,7 +1538,7 @@ void linphone_core_iterate(LinphoneCore *lc) bool_t linphone_core_interpret_url(LinphoneCore *lc, const char *url, LinphoneAddress **real_parsed_url, char **route){ enum_lookup_res_t *enumres=NULL; - osip_to_t *parsed_url=NULL; + LinphoneAddress *parsed_url=NULL; char *enum_domain=NULL; LinphoneProxyConfig *proxy; char *tmpurl; @@ -1590,7 +1589,7 @@ bool_t linphone_core_interpret_url(LinphoneCore *lc, const char *url, LinphoneAd if (real_parsed_url!=NULL) *real_parsed_url=parsed_url; else linphone_address_destroy(parsed_url); if (tmproute) *route=ms_strdup(tmproute); - else *route=guess_route_if_any(lc,*real_parsed_url); + return TRUE; } /* else we could not do anything with url given by user, so display an error */ @@ -1742,9 +1741,9 @@ int linphone_core_invite(LinphoneCore *lc, const char *url) if (err<0){ ms_warning("Could not initiate call."); lc->vtable.display_status(lc,_("could not call")); + linphone_core_stop_media_streams(lc,call); linphone_call_destroy(call); lc->call=NULL; - linphone_core_stop_media_streams(lc); }else gstate_new_state(lc, GSTATE_CALL_OUT_INVITE, url); goto end; @@ -1759,7 +1758,6 @@ int linphone_core_refer(LinphoneCore *lc, const char *url) char *real_url=NULL; LinphoneAddress *real_parsed_url=NULL; LinphoneCall *call; - osip_message_t *msg=NULL; char *route; if (!linphone_core_interpret_url(lc,url,&real_parsed_url, &route)){ /* bad url */ @@ -1773,11 +1771,8 @@ int linphone_core_refer(LinphoneCore *lc, const char *url) } lc->call=NULL; real_url=linphone_address_as_string (real_parsed_url); - eXosip_call_build_refer(call->did, real_url, &msg); + sal_refer(call->op,real_url); ms_free(real_url); - eXosip_lock(); - eXosip_call_send_request(call->did, msg); - eXosip_unlock(); return 0; } @@ -1793,79 +1788,6 @@ bool_t linphone_core_inc_invite_pending(LinphoneCore*lc){ return FALSE; } -#ifdef VINCENT_MAURY_RSVP -/* on=1 for RPC_ENABLE=1...*/ -int linphone_core_set_rpc_mode(LinphoneCore *lc, int on) -{ - if (on==1) - printf("RPC_ENABLE set on\n"); - else - printf("RPC_ENABLE set off\n"); - lc->rpc_enable = (on==1); - /* need to tell eXosip the new setting */ - if (eXosip_set_rpc_mode (lc->rpc_enable)!=0) - return -1; - return 0; -} - -/* on=1 for RSVP_ENABLE=1...*/ -int linphone_core_set_rsvp_mode(LinphoneCore *lc, int on) -{ - if (on==1) - printf("RSVP_ENABLE set on\n"); - else - printf("RSVP_ENABLE set off\n"); - lc->rsvp_enable = (on==1); - /* need to tell eXosip the new setting */ - if (eXosip_set_rsvp_mode (lc->rsvp_enable)!=0) - return -1; - return 0; -} - -/* answer : 1 for yes, 0 for no */ -int linphone_core_change_qos(LinphoneCore *lc, int answer) -{ - char *sdpmesg; - if (lc->call==NULL){ - return -1; - } - - if (lc->rsvp_enable && answer==1) - { - /* answer is yes, local setting is with qos, so - * the user chose to continue with no qos ! */ - /* so switch in normal mode : ring and 180 */ - lc->rsvp_enable = 0; /* no more rsvp */ - eXosip_set_rsvp_mode (lc->rsvp_enable); - /* send 180 */ - eXosip_lock(); - eXosip_answer_call(lc->call->did,180,NULL); - eXosip_unlock(); - /* play the ring */ - ms_message("Starting local ring..."); - lc->ringstream=ring_start(lc->sound_conf.local_ring, - 2000,ms_snd_card_manager_get_card(ms_snd_card_manager_get(),lc->sound_conf.ring_sndcard)); - } - else if (!lc->rsvp_enable && answer==1) - { - /* switch to QoS mode on : answer 183 session progress */ - lc->rsvp_enable = 1; - eXosip_set_rsvp_mode (lc->rsvp_enable); - /* take the sdp already computed, see osipuacb.c */ - sdpmesg=lc->call->sdpctx->answerstr; - eXosip_lock(); - eXosip_answer_call_with_body(lc->call->did,183,"application/sdp",sdpmesg); - eXosip_unlock(); - } - else - { - /* decline offer (603) */ - linphone_core_terminate_call(lc, NULL); - } - return 0; -} -#endif - void linphone_core_init_media_streams(LinphoneCore *lc, LinphoneCall *call){ SalMediaDescription *md=call->localdesc; lc->audiostream=audio_stream_new(md->streams[0].port,linphone_core_ipv6_enabled(lc)); @@ -1893,7 +1815,7 @@ void linphone_core_init_media_streams(LinphoneCore *lc, LinphoneCall *call){ rtp_session_set_transports(lc->audiostream->session,lc->a_rtp,lc->a_rtcp); #ifdef VIDEO_ENABLED - if (lc->video_conf.display || lc->video_conf.capture && md->streams[1].port>0) + if ((lc->video_conf.display || lc->video_conf.capture) && md->streams[1].port>0) lc->videostream=video_stream_new(md->streams[1].port,linphone_core_ipv6_enabled(lc)); #else lc->videostream=NULL; @@ -1973,99 +1895,129 @@ static void post_configure_audio_streams(LinphoneCore *lc){ } } +static RtpProfile *make_profile(LinphoneCore *lc, SalStreamDescription *desc, int *used_pt){ + int bw; + MSList *elem; + RtpProfile *prof=rtp_profile_new("Call profile"); + bool_t first=TRUE; + if (desc->type==SalAudio){ + bw=get_min_bandwidth(lc->up_audio_bw,desc->bandwidth); + } + else bw=get_min_bandwidth(lc->up_video_bw,desc->bandwidth); + for(elem=desc->payloads;elem!=NULL;elem=elem->next){ + PayloadType *pt=(PayloadType*)elem->data; + if (bw>0) pt->normal_bitrate=bw*1000; + else if (desc->type==SalAudio){ + pt->normal_bitrate=-1; + } + if (first) { + *used_pt=payload_type_get_number(pt); + first=FALSE; + } + if (desc->ptime>0){ + char tmp[40]; + snprintf(tmp,sizeof(tmp),"ptime=%i",desc->ptime); + payload_type_append_send_fmtp(pt,tmp); + } + rtp_profile_set_payload(prof,payload_type_get_number(pt),pt); + } + return prof; +} + void linphone_core_start_media_streams(LinphoneCore *lc, LinphoneCall *call){ LinphoneAddress *me=linphone_core_get_primary_contact_parsed(lc); const char *tool="linphone-" LINPHONE_VERSION; char *cname; + int used_pt=-1; /* adjust rtp jitter compensation. It must be at least the latency of the sound card */ int jitt_comp=MAX(lc->sound_conf.latency,lc->rtp_conf.audio_jitt_comp); if (call->media_start_time==0) call->media_start_time=time(NULL); - cname=ortp_strdup_printf("%s@%s",me->url->username,me->url->host); + cname=linphone_address_as_string_uri_only(me); { - StreamParams *audio_params=&call->audio_params; - if (!lc->use_files){ - MSSndCard *playcard=lc->sound_conf.play_sndcard; - MSSndCard *captcard=lc->sound_conf.capt_sndcard; - if (playcard==NULL) { - ms_warning("No card defined for playback !"); - goto end; + SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc, + SalProtoRtpAvp,SalAudio); + if (stream){ + call->audio_profile=make_profile(lc,stream,&used_pt); + if (!lc->use_files){ + MSSndCard *playcard=lc->sound_conf.play_sndcard; + MSSndCard *captcard=lc->sound_conf.capt_sndcard; + if (playcard==NULL) { + ms_warning("No card defined for playback !"); + goto end; + } + if (captcard==NULL) { + ms_warning("No card defined for capture !"); + goto end; + } + audio_stream_start_now( + lc->audiostream, + call->audio_profile, + stream->addr[0]!='\0' ? stream->addr : call->resultdesc->addr, + stream->port, + stream->port+1, + used_pt, + jitt_comp, + playcard, + captcard, + linphone_core_echo_cancellation_enabled(lc)); + }else{ + audio_stream_start_with_files( + lc->audiostream, + call->audio_profile, + stream->addr[0]!='\0' ? stream->addr : call->resultdesc->addr, + stream->port, + stream->port+1, + used_pt, + 100, + lc->play_file, + lc->rec_file); } - if (captcard==NULL) { - ms_warning("No card defined for capture !"); - goto end; - } - if (audio_params->relay_session_id!=NULL) - audio_stream_set_relay_session_id(lc->audiostream,audio_params->relay_session_id); - audio_stream_start_now( - lc->audiostream, - call->profile, - audio_params->remoteaddr, - audio_params->remoteport, - audio_params->remotertcpport, - audio_params->pt, - jitt_comp, - playcard, - captcard, - linphone_core_echo_cancellation_enabled(lc)); - }else{ - audio_stream_start_with_files( - lc->audiostream, - call->profile, - audio_params->remoteaddr, - audio_params->remoteport, - audio_params->remotertcpport, - audio_params->pt, - 100, - lc->play_file, - lc->rec_file); - } - post_configure_audio_streams(lc); - audio_stream_set_rtcp_information(lc->audiostream, cname, tool); + post_configure_audio_streams(lc); + audio_stream_set_rtcp_information(lc->audiostream, cname, tool); + }else ms_warning("No audio stream defined ?"); } #ifdef VIDEO_ENABLED { + SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc, + SalProtoRtpAvp,SalVideo); /* shutdown preview */ if (lc->previewstream!=NULL) { video_preview_stop(lc->previewstream); lc->previewstream=NULL; } - if (lc->video_conf.display || lc->video_conf.capture) { - StreamParams *video_params=&call->video_params; - - if (video_params->remoteport>0){ - if (video_params->relay_session_id!=NULL) - video_stream_set_relay_session_id(lc->videostream,video_params->relay_session_id); - video_stream_set_sent_video_size(lc->videostream,linphone_core_get_preferred_video_size(lc)); - video_stream_enable_self_view(lc->videostream,lc->video_conf.selfview); - if (lc->video_conf.display && lc->video_conf.capture) - video_stream_start(lc->videostream, - call->profile, video_params->remoteaddr, video_params->remoteport, - video_params->remotertcpport, - video_params->pt, jitt_comp, lc->video_conf.device); - else if (lc->video_conf.display) - video_stream_recv_only_start(lc->videostream, - call->profile, video_params->remoteaddr, video_params->remoteport, - video_params->pt, jitt_comp); - else if (lc->video_conf.capture) - video_stream_send_only_start(lc->videostream, - call->profile, video_params->remoteaddr, video_params->remoteport, - video_params->remotertcpport, - video_params->pt, jitt_comp, lc->video_conf.device); - video_stream_set_rtcp_information(lc->videostream, cname,tool); - } + if (stream && (lc->video_conf.display || lc->video_conf.capture)) { + const char *addr=stream->addr[0]!='\0' ? stream->addr : call->resultdesc->addr; + call->video_profile=make_profile(lc,stream,&used_pt); + video_stream_set_sent_video_size(lc->videostream,linphone_core_get_preferred_video_size(lc)); + video_stream_enable_self_view(lc->videostream,lc->video_conf.selfview); + if (lc->video_conf.display && lc->video_conf.capture) + video_stream_start(lc->videostream, + call->video_profile, addr, stream->port, + stream->port+1, + used_pt, jitt_comp, lc->video_conf.device); + else if (lc->video_conf.display) + video_stream_recv_only_start(lc->videostream, + call->video_profile, addr, stream->port, + used_pt, jitt_comp); + else if (lc->video_conf.capture) + video_stream_send_only_start(lc->videostream, + call->video_profile, addr, stream->port, + stream->port+1, + used_pt, jitt_comp, lc->video_conf.device); + video_stream_set_rtcp_information(lc->videostream, cname,tool); } } #endif goto end; end: - ms_free(cname); - linphone_address_destroy(me); - lc->call->state=LCStateAVRunning; + ms_free(cname); + linphone_address_destroy(me); + lc->call->state=LCStateAVRunning; } -void linphone_core_stop_media_streams(LinphoneCore *lc){ +void linphone_core_stop_media_streams(LinphoneCore *lc, LinphoneCall *call){ if (lc->audiostream!=NULL) { audio_stream_stop(lc->audiostream); lc->audiostream=NULL; @@ -2086,6 +2038,14 @@ void linphone_core_stop_media_streams(LinphoneCore *lc){ } } #endif + if (call->audio_profile){ + rtp_profile_destroy(call->audio_profile); + call->audio_profile=NULL; + } + if (call->video_profile){ + rtp_profile_destroy(call->video_profile); + call->video_profile=NULL; + } } /** @@ -2104,17 +2064,14 @@ void linphone_core_stop_media_streams(LinphoneCore *lc){ **/ int linphone_core_accept_call(LinphoneCore *lc, const char *url) { - char *sdpmesg; - osip_message_t *msg=NULL; LinphoneCall *call=lc->call; - int err; - bool_t offering=FALSE; - + const char *contact=NULL; + if (call==NULL){ return -1; } - if (lc->call->state==LCStateAVRunning){ + if (call->state==LCStateAVRunning){ /*call already accepted*/ return -1; } @@ -2126,42 +2083,22 @@ int linphone_core_accept_call(LinphoneCore *lc, const char *url) ms_message("ring stopped"); lc->ringstream=NULL; } - /* sends a 200 OK */ - err=eXosip_call_build_answer(call->tid,200,&msg); - if (err<0 || msg==NULL){ - ms_error("Fail to build answer for call: err=%i",err); - return -1; - } - if (lp_config_get_int(lc->config,"sip","use_session_timers",0)==1){ - if (call->supports_session_timers) osip_message_set_supported(msg, "timer"); - } + /*try to be best-effort in giving real local or routable contact address, except when the user choosed to override the ipaddress */ if (linphone_core_get_firewall_policy(lc)!=LINPHONE_POLICY_USE_NAT_ADDRESS) - fix_contact(lc,msg,call->localip,NULL); - /*if a sdp answer is computed, send it, else send an offer */ - sdpmesg=call->sdpctx->answerstr; - if (sdpmesg==NULL){ - offering=TRUE; - ms_message("generating sdp offer"); - sdpmesg=sdp_context_get_offer(call->sdpctx); - - if (sdpmesg==NULL){ - ms_error("fail to generate sdp offer !"); - return -1; - } - linphone_set_sdp(msg,sdpmesg); - linphone_core_init_media_streams(lc); - }else{ - linphone_set_sdp(msg,sdpmesg); - } - eXosip_lock(); - eXosip_call_send_answer(call->tid,200,msg); - eXosip_unlock(); + contact=get_fixed_contact(lc,call->localip,NULL); + if (contact) + sal_op_set_contact(call->op,contact); + + sal_call_accept(call->op); lc->vtable.display_status(lc,_("Connected.")); gstate_new_state(lc, GSTATE_CALL_IN_CONNECTED, NULL); - - if (!offering) linphone_core_start_media_streams(lc, lc->call); + call->resultdesc=sal_call_get_final_media_description(call->op); + if (call->resultdesc){ + sal_media_description_ref(call->resultdesc); + linphone_core_start_media_streams(lc, call); + } ms_message("call answered."); return 0; } @@ -2181,17 +2118,14 @@ int linphone_core_terminate_call(LinphoneCore *lc, const char *url) return -1; } lc->call=NULL; - - eXosip_lock(); - eXosip_call_terminate(call->cid,call->did); - eXosip_unlock(); + sal_call_terminate(call->op); /*stop ringing*/ if (lc->ringstream!=NULL) { ring_stop(lc->ringstream); lc->ringstream=NULL; } - linphone_core_stop_media_streams(lc); + linphone_core_stop_media_streams(lc,call); lc->vtable.display_status(lc,_("Call ended") ); gstate_new_state(lc, GSTATE_CALL_END, NULL); linphone_call_destroy(call); @@ -2243,22 +2177,13 @@ void linphone_core_set_presence_info(LinphoneCore *lc,int minutes_away, const char *contact, LinphoneOnlineStatus presence_mode) { - int contactok=-1; if (minutes_away>0) lc->minutes_away=minutes_away; - if (contact!=NULL) { - osip_from_t *url; - osip_from_init(&url); - contactok=osip_from_parse(url,contact); - if (contactok>=0) { - ms_message("contact url is correct."); - } - osip_from_free(url); - - } - if (contactok>=0){ - if (lc->alt_contact!=NULL) ms_free(lc->alt_contact); - lc->alt_contact=ms_strdup(contact); + + if (lc->alt_contact!=NULL) { + ms_free(lc->alt_contact); + lc->alt_contact=NULL; } + if (contact) lc->alt_contact=ms_strdup(contact); if (lc->presence_mode!=presence_mode){ linphone_core_notify_all_friends(lc,presence_mode); /* @@ -2270,7 +2195,6 @@ void linphone_core_set_presence_info(LinphoneCore *lc,int minutes_away, } lc->prev_mode=lc->presence_mode; lc->presence_mode=presence_mode; - } LinphoneOnlineStatus linphone_core_get_presence_info(const LinphoneCore *lc){ @@ -2642,7 +2566,7 @@ bool_t linphone_core_agc_enabled(const LinphoneCore *lc){ * @param dtmf The dtmf name specified as a char, such as '0', '#' etc... * **/ -void linphone_core_send_dtmf(LinphoneCore *lc,char dtmf) +void linphone_core_send_dtmf(LinphoneCore *lc, char dtmf) { /*By default we send DTMF RFC2833 if we do not have enabled SIP_INFO but we can also send RFC2833 and SIP_INFO*/ if (linphone_core_get_use_rfc2833_for_dtmf(lc)!=0 || linphone_core_get_use_info_for_dtmf(lc)==0) @@ -2656,26 +2580,13 @@ void linphone_core_send_dtmf(LinphoneCore *lc,char dtmf) ms_error("we cannot send RFC2833 dtmf when we are not in communication"); } } - if (linphone_core_get_use_info_for_dtmf(lc)!=0) - { - char dtmf_body[1000]; - char clen[10]; - osip_message_t *msg=NULL; + if (linphone_core_get_use_info_for_dtmf(lc)!=0){ /* Out of Band DTMF (use INFO method) */ LinphoneCall *call=lc->call; if (call==NULL){ return; } - eXosip_call_build_info(call->did,&msg); - snprintf(dtmf_body, 999, "Signal=%c\r\nDuration=250\r\n", dtmf); - osip_message_set_body(msg,dtmf_body,strlen(dtmf_body)); - osip_message_set_content_type(msg,"application/dtmf-relay"); - snprintf(clen,sizeof(clen),"%lu",(unsigned long)strlen(dtmf_body)); - osip_message_set_content_length(msg,clen); - - eXosip_lock(); - eXosip_call_send_request(call->did,msg); - eXosip_unlock(); + sal_call_send_dtmf(call->op,dtmf); } } @@ -2742,7 +2653,7 @@ static void apply_nat_settings(LinphoneCore *lc){ if (err!=0){ wmsg=ortp_strdup_printf(_("Invalid nat address '%s' : %s"), addr, gai_strerror(err)); - ms_warning(wmsg); // what is this for ? + ms_warning("%s",wmsg); // what is this for ? lc->vtable.display_warning(lc, wmsg); ms_free(wmsg); ms_free(tmp); @@ -2756,22 +2667,16 @@ static void apply_nat_settings(LinphoneCore *lc){ if (lc->net_conf.firewall_policy==LINPHONE_POLICY_USE_NAT_ADDRESS){ if (tmp!=NULL){ if (!lc->net_conf.nat_sdp_only){ - eXosip_set_option(EXOSIP_OPT_SET_IPV4_FOR_GATEWAY,tmp); - /* the following does not work in all cases */ - /* - eXosip_masquerade_contact(tmp,lc->sip_conf.sip_port); - */ + sal_masquerade(lc->sal,tmp); } ms_free(tmp); } else{ - eXosip_set_option(EXOSIP_OPT_SET_IPV4_FOR_GATEWAY,NULL); - eXosip_masquerade_contact("",0); + sal_masquerade(lc->sal,NULL); } } else { - eXosip_set_option(EXOSIP_OPT_SET_IPV4_FOR_GATEWAY,NULL); - eXosip_masquerade_contact("",0); + sal_masquerade(lc->sal,NULL); } } @@ -3197,23 +3102,17 @@ void sip_config_uninit(LinphoneCore *lc) linphone_proxy_config_edit(cfg); /* to unregister */ } - if (exosip_running) - { + if (lc->sal){ int i; - for (i=0;i<20;i++) - { - eXosip_event_t *ev; - while((ev=eXosip_event_wait(0,0))!=NULL){ - linphone_core_process_event(lc,ev); - } - eXosip_automatic_action(); + for (i=0;i<20;i++){ + sal_iterate(lc->sal); #ifndef WIN32 - usleep(100000); + usleep(100000); #else - Sleep(100); + Sleep(100); #endif - } - } + } + } linphone_proxy_config_write_to_config_file(lc->config,NULL,i); /*mark the end */ @@ -3222,6 +3121,8 @@ void sip_config_uninit(LinphoneCore *lc) linphone_auth_info_write_config(lc->config,ai,i); } linphone_auth_info_write_config(lc->config,NULL,i); /* mark the end */ + sal_uninit(lc->sal); + lc->sal=NULL; } void rtp_config_uninit(LinphoneCore *lc) @@ -3341,7 +3242,6 @@ static void linphone_core_uninit(LinphoneCore *lc) linphone_core_free_payload_types(); ortp_exit(); - eXosip_quit(); exosip_running=FALSE; gstate_new_state(lc, GSTATE_POWER_OFF, NULL); } diff --git a/coreapi/private.h b/coreapi/private.h index 93832080c..667fdb7ac 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -67,7 +67,8 @@ typedef struct _LinphoneCall SalMediaDescription *localdesc; SalMediaDescription *resultdesc; LinphoneCallDir dir; - struct _RtpProfile *profile; /*points to the local_profile or to the remote "guessed" profile*/ + struct _RtpProfile *audio_profile; + struct _RtpProfile *video_profile; struct _LinphoneCallLog *log; SalOp *op; char localip[LINPHONE_IPADDR_SIZE]; /* our best guess for local ipaddress for this call */ @@ -87,7 +88,7 @@ void linphone_call_log_completed(LinphoneCallLog *calllog, LinphoneCall *call); void linphone_call_log_destroy(LinphoneCallLog *cl); -void linphone_core_init_media_streams(LinphoneCore *lc); +void linphone_core_init_media_streams(LinphoneCore *lc, LinphoneCall *call); void linphone_auth_info_write_config(struct _LpConfig *config, LinphoneAuthInfo *obj, int pos); @@ -112,8 +113,8 @@ bool_t host_has_ipv6_network(); bool_t lp_spawn_command_line_sync(const char *command, char **result,int *command_ret); static inline int get_min_bandwidth(int dbw, int ubw){ - if (dbw<0) return ubw; - if (ubw<0) return dbw; + if (dbw<=0) return ubw; + if (ubw<=0) return dbw; return MIN(dbw,ubw); } @@ -165,7 +166,7 @@ int linphone_proxy_config_normalize_number(LinphoneProxyConfig *cfg, const char /*internal use only */ void linphone_core_start_media_streams(LinphoneCore *lc, struct _LinphoneCall *call); -void linphone_core_stop_media_streams(LinphoneCore *lc); +void linphone_core_stop_media_streams(LinphoneCore *lc, struct _LinphoneCall *call); const char * linphone_core_get_identity(LinphoneCore *lc); const char * linphone_core_get_route(LinphoneCore *lc); bool_t linphone_core_interpret_url(LinphoneCore *lc, const char *url, LinphoneAddress **real_parsed_url, char **route); diff --git a/coreapi/sal.c b/coreapi/sal.c index 150d7d94a..6ff25bc10 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. SalMediaDescription *sal_media_description_new(){ SalMediaDescription *md=ms_new0(SalMediaDescription,1); md->refcount=1; + return md; } static void sal_media_description_destroy(SalMediaDescription *md){ @@ -60,6 +61,14 @@ SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md, return NULL; } +bool_t sal_media_description_empty(SalMediaDescription *md){ + int i; + for(i=0;instreams;++i){ + SalStreamDescription *ss=&md->streams[i]; + if (ss->port!=0) return FALSE; + } + return TRUE; +} static void assign_string(char **str, const char *arg){ if (*str){ diff --git a/coreapi/sal.h b/coreapi/sal.h index 37b28c189..ebd8bc1e0 100644 --- a/coreapi/sal.h +++ b/coreapi/sal.h @@ -62,6 +62,8 @@ void sal_address_destroy(SalAddress *u); Sal * sal_init(); void sal_uninit(Sal* sal); +void sal_set_user_pointer(Sal *sal, void *user_data); +void *sal_get_user_pointer(const Sal *sal); typedef enum { SalTransportDatagram, @@ -103,6 +105,7 @@ typedef struct SalMediaDescription{ SalMediaDescription *sal_media_description_new(); void sal_media_description_ref(SalMediaDescription *md); void sal_media_description_unref(SalMediaDescription *md); +bool_t sal_media_description_empty(SalMediaDescription *md); SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md, SalMediaProto proto, SalStreamType type); @@ -121,7 +124,7 @@ typedef struct SalOpBase{ typedef enum SalError{ SalErrorNoResponse, - SalErrorMedia, + SalErrorProtocol, SalErrorFailure, /* see SalReason for more details */ SalErrorUnknown } SalError; @@ -133,6 +136,7 @@ typedef enum SalReason{ SalReasonTemporarilyUnavailable, SalReasonNotFound, SalReasonDoNotDisturb, + SalReasonMedia, SalReasonForbidden, SalReasonUnknown }SalReason; @@ -155,7 +159,7 @@ typedef void (*SalOnCallRinging)(SalOp *op); typedef void (*SalOnCallAccepted)(SalOp *op); typedef void (*SalOnCallAck)(SalOp *op); typedef void (*SalOnCallUpdated)(SalOp *op); -typedef void (*SalOnCallTerminated)(SalOp *op); +typedef void (*SalOnCallTerminated)(SalOp *op, const char *from); typedef void (*SalOnCallFailure)(SalOp *op, SalError error, SalReason reason, const char *details); typedef void (*SalOnAuthRequested)(SalOp *op, const char *realm, const char *username); typedef void (*SalOnAuthSuccess)(SalOp *op, const char *realm, const char *username); @@ -200,6 +204,7 @@ typedef struct SalAuthInfo{ void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs); int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int is_secure); void sal_set_user_agent(Sal *ctx, const char *user_agent); +void sal_masquerade(Sal *ctx, const char *ip); void sal_use_session_timers(Sal *ctx, int expires); int sal_iterate(Sal *sal); @@ -223,9 +228,12 @@ void *sal_op_get_user_pointer(const SalOp *op); /*Call API*/ int sal_call_set_local_media_description(SalOp *h, SalMediaDescription *desc); int sal_call(SalOp *h, const char *from, const char *to); +int sal_call_notify_ringing(SalOp *h); int sal_call_accept(SalOp*h); int sal_call_decline(SalOp *h, SalReason reason, const char *redirection /*optional*/); -const SalMediaDescription * sal_call_get_final_media_description(SalOp *h); +SalMediaDescription * sal_call_get_final_media_description(SalOp *h); +int sal_refer(SalOp *h, const char *refer_to); +int sal_call_send_dtmf(SalOp *h, char dtmf); int sal_call_terminate(SalOp *h); /*Registration*/ diff --git a/coreapi/sal_eXosip2.c b/coreapi/sal_eXosip2.c index 5af843c9f..6056533b9 100644 --- a/coreapi/sal_eXosip2.c +++ b/coreapi/sal_eXosip2.c @@ -134,6 +134,18 @@ void sal_uninit(Sal* sal){ ms_free(sal); } +void sal_set_user_pointer(Sal *sal, void *user_data){ + sal->up=user_data; +} + +void *sal_get_user_pointer(const Sal *sal){ + return sal->up; +} + +void sal_masquerade(Sal *ctx, const char *ip){ + eXosip_set_option(EXOSIP_OPT_SET_IPV4_FOR_GATEWAY,ip); +} + static void unimplemented_stub(){ ms_warning("Unimplemented SAL callback"); } @@ -293,8 +305,16 @@ int sal_call(SalOp *h, const char *from, const char *to){ return 0; } +int sal_call_notify_ringing(SalOp *h){ + eXosip_lock(); + eXosip_call_send_answer(h->tid,180,NULL); + eXosip_unlock(); + return 0; +} + int sal_call_accept(SalOp * h){ osip_message_t *msg; + const char *contact=sal_op_get_contact(h); /* sends a 200 OK */ int err=eXosip_call_build_answer(h->tid,200,&msg); if (err<0 || msg==NULL){ @@ -304,6 +324,8 @@ int sal_call_accept(SalOp * h){ if (h->base.root->session_expires!=0){ if (h->supports_session_timers) osip_message_set_supported(msg, "timer"); } + + if (contact) osip_message_set_contact(msg,contact); if (h->base.local_media){ /*this is the case where we received an invite without SDP*/ @@ -320,18 +342,80 @@ int sal_call_accept(SalOp * h){ return 0; } -const SalMediaDescription * sal_call_get_final_media_description(SalOp *h){ +int sal_call_decline(SalOp *h, SalReason reason, const char *redirect){ + if (reason==SalReasonBusy){ + eXosip_lock(); + eXosip_call_send_answer(h->tid,486,NULL); + eXosip_unlock(); + } + else if (reason==SalReasonTemporarilyUnavailable){ + eXosip_lock(); + eXosip_call_send_answer(h->tid,480,NULL); + eXosip_unlock(); + }else if (reason==SalReasonDoNotDisturb){ + eXosip_lock(); + eXosip_call_send_answer(h->tid,600,NULL); + eXosip_unlock(); + }else if (reason==SalReasonMedia){ + eXosip_lock(); + eXosip_call_send_answer(h->tid,415,NULL); + eXosip_unlock(); + }else if (redirect!=NULL && reason==SalReasonRedirect){ + osip_message_t *msg; + int code; + if (strstr(redirect,"sip:")!=0) code=302; + else code=380; + eXosip_lock(); + eXosip_call_build_answer(h->tid,code,&msg); + osip_message_set_contact(msg,redirect); + eXosip_call_send_answer(h->tid,code,msg); + eXosip_unlock(); + }else sal_call_terminate(h); + return 0; +} + +SalMediaDescription * sal_call_get_final_media_description(SalOp *h){ if (h->base.local_media && h->base.remote_media && !h->result){ sdp_process(h); } return h->result; } +int sal_refer(SalOp *h, const char *refer_to){ + osip_message_t *msg=NULL; + int err=0; + eXosip_lock(); + eXosip_call_build_refer(h->did,refer_to, &msg); + if (msg) err=eXosip_call_send_request(h->did, msg); + else err=-1; + eXosip_unlock(); + return err; +} + +int sal_call_send_dtmf(SalOp *h, char dtmf){ + osip_message_t *msg=NULL; + char dtmf_body[128]; + char clen[10]; + + eXosip_lock(); + eXosip_call_build_info(h->did,&msg); + if (msg){ + snprintf(dtmf_body, sizeof(dtmf_body), "Signal=%c\r\nDuration=250\r\n", dtmf); + osip_message_set_body(msg,dtmf_body,strlen(dtmf_body)); + osip_message_set_content_type(msg,"application/dtmf-relay"); + snprintf(clen,sizeof(clen),"%lu",(unsigned long)strlen(dtmf_body)); + osip_message_set_content_length(msg,clen); + eXosip_call_send_request(h->did,msg); + } + eXosip_unlock(); + return 0; +} + int sal_call_terminate(SalOp *h){ eXosip_lock(); eXosip_call_terminate(h->cid,h->did); - eXosip_unlock(); eXosip_call_set_reference(h->cid,NULL); + eXosip_unlock(); return 0; } @@ -494,13 +578,17 @@ static void call_accepted(Sal *sal, eXosip_event_t *ev){ static void call_terminated(Sal *sal, eXosip_event_t *ev){ SalOp *op; + char *from; op=(SalOp*)ev->external_reference; if (op==NULL){ ms_warning("Call terminated for already closed call ?"); return; } + osip_from_to_str(ev->request->from,&from); eXosip_call_set_reference(ev->cid,NULL); - sal->callbacks.call_terminated(op); + op->cid=-1; + sal->callbacks.call_terminated(op,from); + osip_free(from); } static void call_released(Sal *sal, eXosip_event_t *ev){ @@ -510,7 +598,7 @@ static void call_released(Sal *sal, eXosip_event_t *ev){ return; } eXosip_call_set_reference(ev->cid,NULL); - sal->callbacks.call_terminated(op); + /*sal->callbacks.call_terminated(op);*/ } static int get_auth_data(eXosip_event_t *ev, const char **realm, const char **username){ @@ -600,7 +688,8 @@ static bool_t call_failure(Sal *sal, eXosip_event_t *ev){ sr=SalReasonNotFound; break; case 415: - error=SalErrorMedia; + error=SalErrorFailure; + sr=SalReasonMedia; break; case 422: eXosip_default_action(ev); @@ -1031,11 +1120,9 @@ int sal_iterate(Sal *sal){ if (process_event(sal,ev)) eXosip_event_free(ev); } - if (sal->automatic_action==0) { - eXosip_lock(); - eXosip_automatic_refresh(); - eXosip_unlock(); - } + eXosip_lock(); + eXosip_automatic_refresh(); + eXosip_unlock(); } return 0; } diff --git a/coreapi/sal_eXosip2.h b/coreapi/sal_eXosip2.h index c0d32fe0e..a2bae79f4 100644 --- a/coreapi/sal_eXosip2.h +++ b/coreapi/sal_eXosip2.h @@ -35,7 +35,7 @@ struct Sal{ MSList *in_subscribes;/*MSList of SalOp */ int running; int session_expires; - int automatic_action; + void *up; }; struct SalOp{