]> sjero.net Git - linphone/commitdiff
work in progress
authorSimon Morlat <simon.morlat@linphone.org>
Mon, 1 Feb 2010 17:30:15 +0000 (18:30 +0100)
committerSimon Morlat <simon.morlat@linphone.org>
Mon, 1 Feb 2010 17:30:15 +0000 (18:30 +0100)
coreapi/Makefile.am
coreapi/callbacks.c
coreapi/linphonecore.c
coreapi/private.h
coreapi/sal.c
coreapi/sal.h
coreapi/sal_eXosip2.c
coreapi/sal_eXosip2.h

index 2410f2d4e5d8b2428d6bd0c1ca4ba006c3d41309..51778059480a40ab76753f7cdac1cc8ea66ab846 100644 (file)
@@ -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 \
index 73eeca56ee03f9388b5b3367cf2f425419fda50d..08267a30d5205791481e69524d37655ba732f7f4 100644 (file)
@@ -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){
index f9f47c9e4912692ea928df400faecc0127791efc..33a8d588c85ec334fbdebb2d4a5b7e686ddb0368 100644 (file)
@@ -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;
-                       }
-                       if (captcard==NULL) {
-                               ms_warning("No card defined for capture !");
-                               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 (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);
 }
index 93832080ceb31d5d04756ff0e0546e28f953544f..667fdb7ac06ce7a6bd9300031cad6b1dcbeebae4 100644 (file)
@@ -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);
index 150d7d94a3dc4c90f30249552439cae51bb14c9c..6ff25bc10dd45fe23341896a16faaaa79c97f174 100644 (file)
@@ -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;i<md->nstreams;++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){
index 37b28c189a242525b6d5c09758df1be77815ce7c..ebd8bc1e0342993ae1683af56b357346b034a721 100644 (file)
@@ -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*/
index 5af843c9f0a7e4a24105cd3eaf6259fb5fe632a6..6056533b953e3e0629a6e56c0d88041f1af6da05 100644 (file)
@@ -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;
 }
index c0d32fe0e0f922e837d7de8a86f9eae5a8dec376..a2bae79f4678d5c2b1ca3a85714d35ebda123388 100644 (file)
@@ -35,7 +35,7 @@ struct Sal{
        MSList *in_subscribes;/*MSList of SalOp */
        int running;
        int session_expires;
-       int automatic_action;
+       void *up;
 };
 
 struct SalOp{