]> sjero.net Git - linphone/commitdiff
Merge branch 'master' into dev_sal
authorSimon Morlat <simon.morlat@linphone.org>
Wed, 3 Mar 2010 15:16:16 +0000 (16:16 +0100)
committerSimon Morlat <simon.morlat@linphone.org>
Wed, 3 Mar 2010 15:16:16 +0000 (16:16 +0100)
Conflicts:
coreapi/address.c
coreapi/linphonecore.c

31 files changed:
console/Makefile.am
console/commands.c
console/linphonec.c
coreapi/Makefile.am
coreapi/address.c
coreapi/authentication.c
coreapi/callbacks.c [new file with mode: 0644]
coreapi/chat.c
coreapi/exevents.c
coreapi/friend.c
coreapi/general_state.c
coreapi/linphonecore.c
coreapi/linphonecore.h
coreapi/misc.c
coreapi/offeranswer.c [new file with mode: 0644]
coreapi/offeranswer.h [new file with mode: 0644]
coreapi/presence.c
coreapi/private.h
coreapi/proxy.c
coreapi/sal.c [new file with mode: 0644]
coreapi/sal.h [new file with mode: 0644]
coreapi/sal_eXosip2.c [new file with mode: 0644]
coreapi/sal_eXosip2.h [new file with mode: 0644]
coreapi/sal_eXosip2_presence.c [new file with mode: 0644]
coreapi/sal_eXosip2_sdp.c [new file with mode: 0644]
coreapi/siplogin.c
gtk-glade/friendlist.c
gtk-glade/logging.c
gtk-glade/loginframe.c
gtk-glade/main.c
gtk-glade/propertybox.c

index 45f886580c221912767d80c23373861c67dcfdf5..70c2625b4bf82768627dac716c2e1f134b6cb2d2 100644 (file)
@@ -13,7 +13,7 @@ INCLUDES = \
 
 
 
-bin_PROGRAMS =  linphonec sipomatic linphonecsh
+bin_PROGRAMS =  linphonec linphonecsh
 
 if BUILD_WIN32
 bin_PROGRAMS += linphoned
index d32e62667909e6939035f0b56a673e060a966e6d..c1c33f8eb9ef22d27bdbd09ee3f927628357362a 100644 (file)
@@ -1255,7 +1255,7 @@ linphonec_proxy_use(LinphoneCore *lc, int index)
 static void
 linphonec_friend_display(LinphoneFriend *fr)
 {
-       LinphoneAddress *uri=linphone_address_clone(linphone_friend_get_uri(fr));
+       LinphoneAddress *uri=linphone_address_clone(linphone_friend_get_address(fr));
        char *str;
        
        linphonec_out("name: %s\n", linphone_address_get_display_name(uri));
@@ -1280,7 +1280,7 @@ linphonec_friend_list(LinphoneCore *lc, char *pat)
        {
                if ( pat ) {
                        const char *name = linphone_address_get_display_name(
-                           linphone_friend_get_uri((LinphoneFriend*)friend->data));
+                           linphone_friend_get_address((LinphoneFriend*)friend->data));
                        if (name && ! strstr(name, pat) ) continue;
                }
                linphonec_out("****** Friend %i *******\n",n);
@@ -1302,7 +1302,7 @@ linphonec_friend_call(LinphoneCore *lc, unsigned int num)
                if ( n == num )
                {
                        int ret;
-                       addr = linphone_address_as_string(linphone_friend_get_uri((LinphoneFriend*)friend->data));
+                       addr = linphone_address_as_string(linphone_friend_get_address((LinphoneFriend*)friend->data));
                        ret=lpc_cmd_call(lc, addr);
                        ms_free(addr);
                        return ret;
@@ -1376,17 +1376,16 @@ static int lpc_cmd_register(LinphoneCore *lc, char *args){
                return 1;
        }
        if (passwd[0]!='\0'){
-               osip_from_t *from;
+               LinphoneAddress *from;
                LinphoneAuthInfo *info;
-               osip_from_init(&from);
-               if (osip_from_parse(from,identity)==0){
+               if ((from=linphone_address_new(identity))!=NULL){
                        char realm[128];
-                       snprintf(realm,sizeof(realm)-1,"\"%s\"",from->url->host);
-                       info=linphone_auth_info_new(from->url->username,NULL,passwd,NULL,NULL);
+                       snprintf(realm,sizeof(realm)-1,"\"%s\"",linphone_address_get_domain(from));
+                       info=linphone_auth_info_new(linphone_address_get_username(from),NULL,passwd,NULL,NULL);
                        linphone_core_add_auth_info(lc,info);
+                       linphone_address_destroy(from);
                        linphone_auth_info_destroy(info);
                }
-               osip_from_free(from);
        }
        elem=linphone_core_get_proxy_config_list(lc);
        if (elem) {
@@ -1592,7 +1591,8 @@ static void linphonec_codec_list(LinphoneCore *lc){
        MSList *node;
        for(node=config->audio_codecs;node!=NULL;node=ms_list_next(node)){
                pt=(PayloadType*)(node->data);
-        linphonec_out("%2d: %s (%d) %s\n", index, pt->mime_type, pt->clock_rate, payload_type_enabled(pt) ? "enabled" : "disabled");
+        linphonec_out("%2d: %s (%d) %s\n", index, pt->mime_type, pt->clock_rate, 
+                   linphone_core_payload_type_enabled(lc,pt) ? "enabled" : "disabled");
                index++;
        }
 }
index 2e0ca83426d504c0843b1dddfc314938d2c3258a..f589cf220f5c16c694787e7dfae5048f75eff63e 100644 (file)
@@ -119,8 +119,7 @@ static void linphonec_display_something (LinphoneCore * lc, const char *somethin
 static void linphonec_display_url (LinphoneCore * lc, const char *something, const char *url);
 static void linphonec_display_warning (LinphoneCore * lc, const char *something);
 static void stub () {}
-static void linphonec_notify_received(LinphoneCore *lc,LinphoneFriend *fid,
-               const char *from, const char *status, const char *img);
+static void linphonec_notify_received(LinphoneCore *lc,LinphoneFriend *fid);
 static void linphonec_new_unknown_subscriber(LinphoneCore *lc,
                LinphoneFriend *lf, const char *url);
 static void linphonec_bye_received(LinphoneCore *lc, const char *from);
@@ -283,10 +282,11 @@ linphonec_prompt_for_auth(LinphoneCore *lc, const char *realm, const char *usern
  * Linphone core callback
  */
 static void
-linphonec_notify_received(LinphoneCore *lc,LinphoneFriend *fid,
-               const char *from, const char *status, const char *img)
+linphonec_notify_received(LinphoneCore *lc,LinphoneFriend *fid)
 {
-       printf("Friend %s is %s\n", from, status);
+       char *tmp=linphone_address_as_string(linphone_friend_get_address(fid));
+       printf("Friend %s is %s\n", tmp, linphone_online_status_to_string(linphone_friend_get_status(fid)));
+       ms_free(tmp);
        // todo: update Friend list state (unimplemented)
 }
 
index 944f303e76dd3da6828946d22e7c5635688dc095..014ae308e0398d154b22e3feabb51b6b1e7c6901 100644 (file)
@@ -17,18 +17,22 @@ lib_LTLIBRARIES=liblinphone.la
 
 liblinphone_la_SOURCES=\
        linphonecore.c linphonecore.h private.h\
-       exevents.c exevents.h \
+       offeranswer.c offeranswer.h\
+       sal.c sal.h \
+       sal_eXosip2.c sal_eXosip2.h\
+       sal_eXosip2_sdp.c \
+       sal_eXosip2_presence.c \
+       callbacks.c \
        misc.c  \
        address.c \
        enum.c enum.h \
-       sdphandler.c sdphandler.h \
        presence.c \
        proxy.c \
        friend.c \
        authentication.c \
        lpconfig.c lpconfig.h \
        chat.c \
-        general_state.c \
+       general_state.c \
        sipsetup.c sipsetup.h \
        siplogin.c
 
index 9c69a2641385c51a594dc85a0d308a70a733c8e8..1d893aedea7af3731f8497cb75da396869be299e 100644 (file)
@@ -20,7 +20,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "linphonecore.h"
 #include "lpconfig.h"
 #include "private.h"
-#include <eXosip2/eXosip.h>
 
 /**
  * @addtogroup linphone_address
@@ -31,123 +30,87 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  * Constructs a LinphoneAddress object by parsing the user supplied address,
  * given as a string.
 **/
-LinphoneAddress * linphone_address_new(const char *uri){
-       osip_from_t *from;
-       osip_from_init(&from);
-       if (osip_from_parse(from,uri)!=0){
-               osip_from_free(from);
-               ms_error("Cannot create LinphoneAddress, bad uri [%s]",uri);
-               return NULL;
-       }
-       return from;
+LinphoneAddress * linphone_address_new(const char *addr){
+       SalAddress *saddr=sal_address_new(addr);
+       if (saddr==NULL) ms_error("Cannot create LinphoneAddress, bad uri [%s]",addr);
+       return saddr;
 }
 
 /**
  * Clones a LinphoneAddress object.
 **/
-LinphoneAddress * linphone_address_clone(const LinphoneAddress *uri){
-       osip_from_t *ret=NULL;
-       osip_from_clone(uri,&ret);
-       return ret;
+LinphoneAddress * linphone_address_clone(const LinphoneAddress *addr){
+       return sal_address_clone(addr);
 }
 
-#define null_if_empty(s) (((s)!=NULL && (s)[0]!='\0') ? (s) : NULL )
-
 /**
  * Returns the address scheme, normally "sip".
 **/
 const char *linphone_address_get_scheme(const LinphoneAddress *u){
-       return null_if_empty(u->url->scheme);
+       return sal_address_get_scheme(u);
 }
 
 /**
  * Returns the display name.
 **/
 const char *linphone_address_get_display_name(const LinphoneAddress* u){
-       return null_if_empty(u->displayname);
+       return sal_address_get_display_name(u);
 }
 
 /**
  * Returns the username.
 **/
 const char *linphone_address_get_username(const LinphoneAddress *u){
-       return null_if_empty(u->url->username);
+       return sal_address_get_username(u);
 }
 
 /**
  * Returns the domain name.
 **/
 const char *linphone_address_get_domain(const LinphoneAddress *u){
-       return null_if_empty(u->url->host);
+       return sal_address_get_domain(u);
 }
 
 /**
  * Sets the display name.
 **/
 void linphone_address_set_display_name(LinphoneAddress *u, const char *display_name){
-       if (u->displayname!=NULL){
-               osip_free(u->displayname);
-               u->displayname=NULL;
-       }
-       if (display_name!=NULL)
-               u->displayname=osip_strdup(display_name);
+       sal_address_set_display_name(u,display_name);
 }
 
 /**
  * Sets the username.
 **/
 void linphone_address_set_username(LinphoneAddress *uri, const char *username){
-       if (uri->url->username!=NULL){
-               osip_free(uri->url->username);
-               uri->url->username=NULL;
-       }
-       if (username)
-               uri->url->username=osip_strdup(username);
+       sal_address_set_username(uri,username);
 }
 
 /**
  * Sets the domain.
 **/
 void linphone_address_set_domain(LinphoneAddress *uri, const char *host){
-       if (uri->url->host!=NULL){
-               osip_free(uri->url->host);
-               uri->url->host=NULL;
-       }
-       if (host)
-               uri->url->host=osip_strdup(host);
+       sal_address_set_domain(uri,host);
 }
 
 /**
  * Sets the port number.
 **/
 void linphone_address_set_port(LinphoneAddress *uri, const char *port){
-       if (uri->url->port!=NULL){
-               osip_free(uri->url->port);
-               uri->url->port=NULL;
-       }
-       if (port)
-               uri->url->port=osip_strdup(port);
+       sal_address_set_port(uri,port);
 }
 
 /**
  * Sets the port number.
 **/
 void linphone_address_set_port_int(LinphoneAddress *uri, int port){
-       char tmp[12];
-       if (port==5060){
-               /*this is the default, special case to leave the port field blank*/
-               linphone_address_set_port(uri,NULL);
-               return;
-       }
-       snprintf(tmp,sizeof(tmp),"%i",port);
-       linphone_address_set_port(uri,tmp);
+       sal_address_set_port_int(uri,port);
 }
 
 /**
  * Removes address's tags and uri headers so that it is displayable to the user.
 **/
 void linphone_address_clean(LinphoneAddress *uri){
-       osip_generic_param_freelist(&uri->gen_params);
+       sal_address_clean(uri);
 }
 
 /**
@@ -155,11 +118,7 @@ void linphone_address_clean(LinphoneAddress *uri){
  * The returned char * must be freed by the application. Use ms_free().
 **/
 char *linphone_address_as_string(const LinphoneAddress *u){
-       char *tmp,*ret;
-       osip_from_to_str(u,&tmp);
-       ret=ms_strdup(tmp);
-       osip_free(tmp);
-       return ret;
+       return sal_address_as_string(u);
 }
 
 /**
@@ -167,18 +126,14 @@ char *linphone_address_as_string(const LinphoneAddress *u){
  * The returned char * must be freed by the application. Use ms_free().
 **/
 char *linphone_address_as_string_uri_only(const LinphoneAddress *u){
-       char *tmp=NULL,*ret;
-       osip_uri_to_str(u->url,&tmp);
-       ret=ms_strdup(tmp);
-       osip_free(tmp);
-       return ret;
+       return sal_address_as_string_uri_only(u);
 }
 
 /**
  * Destroys a LinphoneAddress object.
 **/
 void linphone_address_destroy(LinphoneAddress *u){
-       osip_from_free(u);
+       sal_address_destroy(u);
 }
 
 
index 6185048849e5bc8baa79f5df6b2724ded46fcb98..24bed1c437dd22f3d9057d4c01e3879b97a6e949 100644 (file)
  
 #include "linphonecore.h"
 #include "private.h"
-#include <eXosip2/eXosip.h>
-#include <osipparser2/osip_message.h>
 #include "lpconfig.h"
 
-extern LinphoneProxyConfig *linphone_core_get_proxy_config_from_rid(LinphoneCore *lc, int rid);
-
 /**
  * @addtogroup authentication
  * @{
@@ -51,7 +47,6 @@ LinphoneAuthInfo *linphone_auth_info_new(const char *username, const char *useri
        if (ha1!=NULL && (strlen(ha1)>0)) obj->ha1=ms_strdup(ha1);
        if (realm!=NULL && (strlen(realm)>0)) obj->realm=ms_strdup(realm);
        obj->works=FALSE;
-       obj->first_time=TRUE;
        return obj;
 }
 
@@ -63,10 +58,28 @@ static LinphoneAuthInfo *linphone_auth_info_clone(const LinphoneAuthInfo *ai){
        if (ai->ha1)    obj->ha1=ms_strdup(ai->ha1);
        if (ai->realm)  obj->realm=ms_strdup(ai->realm);
        obj->works=FALSE;
-       obj->first_time=TRUE;
+       obj->usecount=0;
        return obj;
 }
 
+/**
+ * Returns username.
+**/
+const char *linphone_auth_info_get_username(const LinphoneAuthInfo *i){
+       return i->username;
+}
+
+/**
+ * Returns password.
+**/
+const char *linphone_auth_info_get_passwd(const LinphoneAuthInfo *i){
+       return i->passwd;
+}
+
+const char *linphone_auth_info_get_userid(const LinphoneAuthInfo *i){
+       return i->userid;
+}
+
 /**
  * Sets the password.
 **/
@@ -224,21 +237,6 @@ const LinphoneAuthInfo *linphone_core_find_auth_info(LinphoneCore *lc, const cha
        return ret;
 }
 
-static void refresh_exosip_auth_info(LinphoneCore *lc){
-       MSList *elem;
-       eXosip_lock();
-       eXosip_clear_authentication_info();
-       for (elem=lc->auth_info;elem!=NULL;elem=ms_list_next(elem)){
-               LinphoneAuthInfo *info=(LinphoneAuthInfo*)elem->data;
-               char *userid;
-               if (info->userid==NULL || info->userid[0]=='\0') userid=info->username;
-               else userid=info->userid;
-               eXosip_add_authentication_info(info->username,userid,
-                               info->passwd,info->ha1,info->realm);
-       }
-       eXosip_unlock();
-}
-
 /**
  * Adds authentication information to the LinphoneCore.
  * 
@@ -247,6 +245,7 @@ static void refresh_exosip_auth_info(LinphoneCore *lc){
 void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info)
 {
        LinphoneAuthInfo *ai;
+       MSList *elem;
        
        /* find if we are attempting to modify an existing auth info */
        ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,info->realm,info->username);
@@ -255,10 +254,23 @@ void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info)
                linphone_auth_info_destroy(ai);
        }
        lc->auth_info=ms_list_append(lc->auth_info,linphone_auth_info_clone(info));
-
-       refresh_exosip_auth_info(lc);
-       /* if the user was prompted, re-allow automatic_action */
-       if (lc->automatic_action>0) lc->automatic_action--;
+       /* retry pending authentication operations */
+       for(elem=sal_get_pending_auths(lc->sal);elem!=NULL;elem=elem->next){
+               const char *username,*realm;
+               SalOp *op=(SalOp*)elem->data;
+               LinphoneAuthInfo *ai;
+               sal_op_get_auth_requested(op,&realm,&username);
+               ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,realm,username);
+               if (ai){
+                       SalAuthInfo sai;
+                       sai.username=ai->username;
+                       sai.userid=ai->userid;
+                       sai.realm=ai->realm;
+                       sai.password=ai->passwd;
+                       sal_op_authenticate(op,&sai);
+                       ai->usecount++;
+               }
+       }
 }
 
 
@@ -267,7 +279,6 @@ void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info)
  * from the auth_info_requested callback of LinphoneCoreVTable.
 **/
 void linphone_core_abort_authentication(LinphoneCore *lc,  LinphoneAuthInfo *info){
-       if (lc->automatic_action>0) lc->automatic_action--;
 }
 
 /**
@@ -286,7 +297,6 @@ void linphone_core_remove_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *in
                        linphone_auth_info_write_config(lc->config,(LinphoneAuthInfo*)elem->data,i);
                }
                linphone_auth_info_write_config(lc->config,NULL,i);
-               refresh_exosip_auth_info(lc);
        }
 }
 
@@ -303,9 +313,6 @@ const MSList *linphone_core_get_auth_info_list(const LinphoneCore *lc){
 void linphone_core_clear_all_auth_info(LinphoneCore *lc){
        MSList *elem;
        int i;
-       eXosip_lock();
-       eXosip_clear_authentication_info();
-       eXosip_unlock();
        for(i=0,elem=lc->auth_info;elem!=NULL;elem=ms_list_next(elem),i++){
                LinphoneAuthInfo *info=(LinphoneAuthInfo*)elem->data;
                linphone_auth_info_destroy(info);
@@ -315,84 +322,6 @@ void linphone_core_clear_all_auth_info(LinphoneCore *lc){
        lc->auth_info=NULL;
 }
 
-void linphone_authentication_ok(LinphoneCore *lc, eXosip_event_t *ev){
-       char *prx_realm=NULL,*www_realm=NULL;
-       osip_proxy_authorization_t *prx_auth;
-       osip_authorization_t *www_auth;
-       osip_message_t *msg=ev->request;
-       char *username;
-       LinphoneAuthInfo *as=NULL;
-
-       username=osip_uri_get_username(msg->from->url);
-       osip_message_get_proxy_authorization(msg,0,&prx_auth);
-       osip_message_get_authorization(msg,0,&www_auth);
-       if (prx_auth!=NULL)
-               prx_realm=osip_proxy_authorization_get_realm(prx_auth);
-       if (www_auth!=NULL)
-               www_realm=osip_authorization_get_realm(www_auth);
-       
-       if (prx_realm==NULL && www_realm==NULL){
-               ms_message("No authentication info in the request, ignoring");
-               return;
-       }
-       /* see if we already have this auth information , not to ask it everytime to the user */
-       if (prx_realm!=NULL)
-               as=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,prx_realm,username);
-       if (www_realm!=NULL) 
-               as=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,www_realm,username);
-       if (as){
-               ms_message("Authentication for user=%s realm=%s is working.",username,prx_realm ? prx_realm : www_realm);
-               as->works=TRUE;
-       }
-}
-
-
-void linphone_core_find_or_ask_for_auth_info(LinphoneCore *lc,const char *username,const char* realm, int tid)
-{
-       LinphoneAuthInfo *as=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,realm,username);
-       if ( as==NULL || (as!=NULL && as->works==FALSE && as->first_time==FALSE)){
-               if (lc->vtable.auth_info_requested!=NULL){
-                       lc->vtable.auth_info_requested(lc,realm,username);
-                       lc->automatic_action++;/*suspends eXosip_automatic_action until the user supplies a password */
-               }
-       }
-       if (as) as->first_time=FALSE;
-}
-
-void linphone_process_authentication(LinphoneCore *lc, eXosip_event_t *ev)
-{
-       char *prx_realm=NULL,*www_realm=NULL;
-       osip_proxy_authenticate_t *prx_auth;
-       osip_www_authenticate_t *www_auth;
-       osip_message_t *resp=ev->response;
-       char *username;
-
-       /*
-       if (strcmp(ev->request->sip_method,"REGISTER")==0) {
-               gstate_new_state(lc, GSTATE_REG_FAILED, "Authentication required");
-       }
-       */
-
-       username=osip_uri_get_username(resp->from->url);
-       prx_auth=(osip_proxy_authenticate_t*)osip_list_get(&resp->proxy_authenticates,0);
-       www_auth=(osip_proxy_authenticate_t*)osip_list_get(&resp->www_authenticates,0);
-       if (prx_auth!=NULL)
-               prx_realm=osip_proxy_authenticate_get_realm(prx_auth);
-       if (www_auth!=NULL)
-               www_realm=osip_www_authenticate_get_realm(www_auth);
-       
-       if (prx_realm==NULL && www_realm==NULL){
-               ms_warning("No realm in the server response.");
-               return;
-       }
-       /* see if we already have this auth information , not to ask it everytime to the user */
-       if (prx_realm!=NULL) 
-               linphone_core_find_or_ask_for_auth_info(lc,username,prx_realm,ev->tid);
-       if (www_realm!=NULL) 
-               linphone_core_find_or_ask_for_auth_info(lc,username,www_realm,ev->tid);
-}
-
-
 /**
  * @}
 **/
diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c
new file mode 100644 (file)
index 0000000..cb0c7b4
--- /dev/null
@@ -0,0 +1,442 @@
+/*
+linphone
+Copyright (C) 2010  Simon MORLAT (simon.morlat@free.fr)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+
+#include "sal.h"
+
+#include "linphonecore.h"
+#include "private.h"
+#include "mediastreamer2/mediastream.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_sal(h));
+       char *barmesg;
+       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(h);
+               return;
+       }
+       if (lc->call!=NULL){/*busy*/
+               sal_call_decline(h,SalReasonBusy,NULL);
+               sal_op_release(h);
+               return;
+       }
+       from=sal_op_get_from(h);
+       to=sal_op_get_to(h);
+       
+       call=linphone_call_new_incoming(lc,linphone_address_new(from),linphone_address_new(to),h);
+       lc->call=call;
+       sal_call_set_local_media_description(h,call->localdesc);
+       call->resultdesc=sal_call_get_final_media_description(h);
+       if (call->resultdesc)
+               sal_media_description_ref(call->resultdesc);
+       if (call->resultdesc && sal_media_description_empty(call->resultdesc)){
+               sal_call_decline(h,SalReasonMedia,NULL);
+               linphone_call_destroy(call);
+               lc->call=NULL;
+               return;
+       }
+       
+       from_parsed=linphone_address_new(sal_op_get_from(h));
+       linphone_address_clean(from_parsed);
+       tmp=linphone_address_as_string(from_parsed);
+       linphone_address_destroy(from_parsed);
+       gstate_new_state(lc, GSTATE_CALL_IN_INVITE, tmp);
+       barmesg=ortp_strdup_printf(_("%s is contacting you"),tmp);
+       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(h);
+       linphone_core_init_media_streams(lc,lc->call);
+       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_sal(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->media_pending=TRUE;
+       }
+       call->state=LCStateRinging;
+}
+
+static void call_accepted(SalOp *op){
+       LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
+       LinphoneCall *call=lc->call;
+       if (call==NULL){
+               ms_warning("No call to accept.");
+               return ;
+       }
+       if (sal_op_get_user_pointer(op)!=lc->call){
+               ms_warning("call_accepted: ignoring.");
+               return;
+       }
+       if (call->state==LCStateAVRunning){
+               return ; /*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_ref(call->resultdesc);
+               call->media_pending=FALSE;
+       }
+       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 *op){
+       LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
+       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 (call->media_pending){
+               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_ref(call->resultdesc);
+               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);
+               }
+               call->media_pending=FALSE;
+       }
+}
+
+static void call_updated(SalOp *op){
+       LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
+       LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
+       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 *op, const char *from){
+       LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
+       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(addr);
+               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 *op, SalError error, SalReason sr, const char *details){
+       LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
+       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.");
+       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->vtable.display_status)
+                       lc->vtable.display_status(lc,_("No response."));
+       }else if (error==SalErrorProtocol){
+               if (lc->vtable.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,_("Not found"));
+                       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,call);
+       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_sal(h));
+       LinphoneAuthInfo *ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,realm,username);
+       if (ai && (ai->works || ai->usecount<3)){
+               SalAuthInfo sai;
+               sai.username=ai->username;
+               sai.userid=ai->userid;
+               sai.realm=ai->realm;
+               sai.password=ai->passwd;
+               sal_op_authenticate(h,&sai);
+               ai->usecount++;
+       }else{
+               if (lc->vtable.auth_info_requested)
+                       lc->vtable.auth_info_requested(lc,realm,username);
+       }
+}
+
+static void auth_success(SalOp *h, const char *realm, const char *username){
+       LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h));
+       LinphoneAuthInfo *ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,realm,username);
+       if (ai)
+               ai->works=TRUE;
+}
+
+static void register_success(SalOp *op, bool_t registered){
+       LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
+       LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)sal_op_get_user_pointer(op);
+       char *msg;
+       gstate_new_state(lc, GSTATE_REG_OK, NULL);
+       cfg->registered=registered;
+       if (cfg->registered) msg=ms_strdup_printf(_("Registration on %s successful."),sal_op_get_proxy(op));
+       else msg=ms_strdup_printf(_("Unregistration on %s done."),sal_op_get_proxy(op));
+       if (lc->vtable.display_status) 
+               lc->vtable.display_status(lc,msg);
+       ms_free(msg);
+}
+
+static void register_failure(SalOp *op, SalError error, SalReason reason, const char *details){
+       LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
+       char *msg=ortp_strdup_printf(_("Registration on %s failed: %s"),sal_op_get_proxy(op),(details!=NULL) ? details : _("no response timeout"));
+       if (lc->vtable.display_status) lc->vtable.display_status(lc,msg);
+       gstate_new_state(lc, GSTATE_REG_FAILED, msg);
+       ms_free(msg);
+}
+
+static void vfu_request(SalOp *op){
+       LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
+#ifdef VIDEO_ENABLED
+       if (lc->videostream)
+               video_stream_send_vfu(lc->videostream);
+#endif
+}
+
+static void dtmf_received(SalOp *op, char dtmf){
+       LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
+       if (lc->vtable.dtmf_received != NULL)
+               lc->vtable.dtmf_received(lc, dtmf);
+}
+
+static void refer_received(Sal *sal, SalOp *op, const char *referto){
+       LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal);
+       if (lc->vtable.refer_received)
+               lc->vtable.refer_received(lc,referto);
+}
+
+static void text_received(Sal *sal, const char *from, const char *msg){
+       LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal);
+       linphone_core_text_received(lc,from,msg);
+}
+
+static void notify(SalOp *op, SalSubscribeState ss, SalPresenceStatus status, const char *msg){
+       LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
+       linphone_notify_recv(lc,op,ss,status);
+}
+
+static void subscribe_received(SalOp *op, const char *from){
+       LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
+       linphone_subscription_new(lc,op,from);
+}
+
+static void subscribe_closed(SalOp *op, const char *from){
+       LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
+       linphone_subscription_closed(lc,op);
+}
+
+static void internal_message(Sal *sal, const char *msg){
+       LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal);
+       if (lc->vtable.show)
+               lc->vtable.show(lc);
+}
+
+SalCallbacks linphone_sal_callbacks={
+       call_received,
+       call_ringing,
+       call_accepted,
+       call_ack,
+       call_updated,
+       call_terminated,
+       call_failure,
+       auth_requested,
+       auth_success,
+       register_success,
+       register_failure,
+       vfu_request,
+       dtmf_received,
+       refer_received,
+       text_received,
+       notify,
+       subscribe_received,
+       subscribe_closed,
+       internal_message
+};
+
+
index 95526274c82b29da23b60811ae2fe81df98e0cc1..11c3c978f4106b85598c25a7110665e98d850f1a 100644 (file)
@@ -24,7 +24,6 @@
  
  #include "linphonecore.h"
  #include "private.h"
- #include <eXosip2/eXosip.h>
  
  LinphoneChatRoom * linphone_core_create_chat_room(LinphoneCore *lc, const char *to){
        LinphoneAddress *parsed_url=NULL;
  
 void linphone_chat_room_send_message(LinphoneChatRoom *cr, const char *msg){
        const char *identity=linphone_core_get_identity(cr->lc);
-       osip_message_t *sip=NULL;
-       eXosip_message_build_request(&sip,"MESSAGE",cr->peer,identity,cr->route);
-       osip_message_set_content_type(sip,"text/plain");
-       osip_message_set_body(sip,msg,strlen(msg));
-       eXosip_message_send_request(sip);
+       SalOp *op=sal_op_new(cr->lc->sal);
+
+       sal_op_set_route(op,cr->route);
+       sal_text_send(op,identity,cr->peer,msg);
 }
 
 bool_t linphone_chat_room_matches(LinphoneChatRoom *cr, const LinphoneAddress *from){
@@ -69,40 +67,29 @@ void linphone_chat_room_text_received(LinphoneChatRoom *cr, LinphoneCore *lc, co
        if (lc->vtable.text_received!=NULL) lc->vtable.text_received(lc, cr, from, msg);
 }
 
-void linphone_core_text_received(LinphoneCore *lc, eXosip_event_t *ev){
+void linphone_core_text_received(LinphoneCore *lc, const char *from, const char *msg){
        MSList *elem;
-       const char *msg;
        LinphoneChatRoom *cr=NULL;
-       char *from;
-       osip_from_t *from_url=ev->request->from;
-       osip_body_t *body=NULL;
-       LinphoneAddress *uri;
+       LinphoneAddress *addr;
+       char *cleanfrom;
 
-       osip_message_get_body(ev->request,0,&body);
-       if (body==NULL){
-               ms_error("Could not get text message from SIP body");
-               return;
-       }
-       msg=body->body;
-       osip_from_to_str(from_url,&from);
-       uri=linphone_address_new(from);
-       osip_free(from);
-       linphone_address_clean(uri);
+       addr=linphone_address_new(from);
+       linphone_address_clean(addr);
        for(elem=lc->chatrooms;elem!=NULL;elem=ms_list_next(elem)){
                cr=(LinphoneChatRoom*)elem->data;
-               if (linphone_chat_room_matches(cr,uri)){
+               if (linphone_chat_room_matches(cr,addr)){
                        break;
                }
                cr=NULL;
        }
-       from=linphone_address_as_string(uri);
+       cleanfrom=linphone_address_as_string(addr);
        if (cr==NULL){
                /* create a new chat room */
-               cr=linphone_core_create_chat_room(lc,from);
+               cr=linphone_core_create_chat_room(lc,cleanfrom);
        }
-       linphone_address_destroy(uri);
-       linphone_chat_room_text_received(cr,lc,from,msg);
-       ms_free(from);
+       linphone_address_destroy(addr);
+       linphone_chat_room_text_received(cr,lc,cleanfrom,msg);
+       ms_free(cleanfrom);
 }
 
 
index 36ed2b6d7e7aeb8f4ade2cf7c9659919c6ebd36b..75dc954ef49a5b7aa103587f084918988e70242d 100644 (file)
@@ -464,7 +464,8 @@ int linphone_set_audio_offer(sdp_context_t *ctx)
        elem=lc->codecs_conf.audio_codecs;
        while(elem!=NULL){
                codec=(PayloadType*) elem->data;
-               if (linphone_core_check_payload_type_usability(lc,codec) && payload_type_enabled(codec)){
+               if (linphone_core_check_payload_type_usability(lc,codec) && 
+                   linphone_core_payload_type_enabled(lc,codec)){
                        sdp_payload_init(&payload);
                        payload.a_rtpmap=ortp_strdup_printf("%s/%i/1",codec->mime_type,codec->clock_rate);
                        payload.pt=rtp_profile_get_payload_number_from_rtpmap(lc->local_profile,payload.a_rtpmap);
@@ -535,7 +536,8 @@ int linphone_set_video_offer(sdp_context_t *ctx)
 
        for(elem=lc->codecs_conf.video_codecs;elem!=NULL;elem=ms_list_next(elem)){
                codec=(PayloadType*) elem->data;
-               if (linphone_core_check_payload_type_usability(lc,codec) && payload_type_enabled(codec)){
+               if (linphone_core_check_payload_type_usability(lc,codec) && 
+                   linphone_core_payload_type_enabled(lc,codec)){
                        sdp_payload_t payload;
                        sdp_payload_init(&payload);
                        payload.line=1;
@@ -587,7 +589,7 @@ SupportLevel linphone_payload_is_supported(LinphoneCore *lc, sdp_payload_t *payl
                                ms_warning("payload %s is not usable",rtppayload->mime_type);
                                return Unsupported;
                        }
-                       if ( !payload_type_enabled(rtppayload)) {
+                       if ( !linphone_core_payload_type_enabled(lc,rtppayload)) {
                                ms_warning("payload %s is not enabled.",rtppayload->mime_type);
                                return Unsupported;
                        }
index 08f072de31b8309b6f86750d0273360f7fd4241b..080dffb4ed7463d2bee6271489b7b7f327101fc8 100644 (file)
@@ -31,9 +31,6 @@
 const char *linphone_online_status_to_string(LinphoneOnlineStatus ss){
        const char *str=NULL;
        switch(ss){
-               case LINPHONE_STATUS_UNKNOWN:
-               str=_("Unknown");
-               break;
                case LINPHONE_STATUS_ONLINE:
                str=_("Online");
                break;
@@ -67,9 +64,6 @@ const char *linphone_online_status_to_string(LinphoneOnlineStatus ss){
                case LINPHONE_STATUS_PENDING:
                str=_("Pending");
                break;
-               case LINPHONE_STATUS_CLOSED:
-               str=_("Closed");
-               break;
                default:
                str=_("Unknown-bug");
        }
@@ -114,20 +108,20 @@ MSList *linphone_find_friend(MSList *fl, const LinphoneAddress *friend, Linphone
        return res;
 }
 
-LinphoneFriend *linphone_find_friend_by_nid(MSList *l, int nid){
+LinphoneFriend *linphone_find_friend_by_inc_subscribe(MSList *l, SalOp *op){
        MSList *elem;
        for (elem=l;elem!=NULL;elem=elem->next){
                LinphoneFriend *lf=(LinphoneFriend*)elem->data;
-               if (lf->nid==nid) return lf;
+               if (lf->insub==op) return lf;
        }
        return NULL;
 }
 
-LinphoneFriend *linphone_find_friend_by_sid(MSList *l, int sid){
+LinphoneFriend *linphone_find_friend_by_out_subscribe(MSList *l, SalOp *op){
        MSList *elem;
        for (elem=l;elem!=NULL;elem=elem->next){
                LinphoneFriend *lf=(LinphoneFriend*)elem->data;
-               if (lf->sid==sid) return lf;
+               if (lf->outsub==op) return lf;
        }
        return NULL;
 }
@@ -136,30 +130,31 @@ void __linphone_friend_do_subscribe(LinphoneFriend *fr){
        char *friend=NULL;
        const char *route=NULL;
        const char *from=NULL;
-       osip_message_t *msg=NULL;
+       LinphoneProxyConfig *cfg;
+       
        friend=linphone_address_as_string(fr->uri);
-       if (fr->proxy!=NULL){
-               route=fr->proxy->reg_route;
-               from=fr->proxy->reg_identity;
+       cfg=linphone_core_lookup_known_proxy(fr->lc,linphone_friend_get_address(fr));
+       if (cfg!=NULL){
+               route=linphone_proxy_config_get_route(cfg);
+               from=linphone_proxy_config_get_identity(cfg);
        }else from=linphone_core_get_primary_contact(fr->lc);
-       if (fr->sid<0){
+       if (fr->outsub==NULL){
                /* people for which we don't have yet an answer should appear as offline */
-               fr->lc->vtable.notify_recv(fr->lc,(LinphoneFriend*)fr,friend,_("Gone"),"sip-closed.png");
-       }
-       eXosip_lock();
-       eXosip_subscribe_build_initial_request(&msg,friend,from,route,"presence",600);
-       eXosip_subscribe_send_initial_request(msg);
-       eXosip_unlock();
+               fr->status=LINPHONE_STATUS_OFFLINE;
+               if (fr->lc->vtable.notify_recv)
+                       fr->lc->vtable.notify_recv(fr->lc,(LinphoneFriend*)fr);
+       }else{
+               sal_op_release(fr->outsub);
+               fr->outsub=NULL;
+       }
+       fr->outsub=sal_op_new(fr->lc->sal);
+       sal_op_set_route(fr->outsub,route);
+       sal_subscribe_presence(fr->outsub,from,friend);
        ms_free(friend);
 }
 
-
 LinphoneFriend * linphone_friend_new(){
        LinphoneFriend *obj=ms_new0(LinphoneFriend,1);
-       obj->out_did=-1;
-       obj->in_did=-1;
-       obj->nid=-1;
-       obj->sid=-1;
        obj->pol=LinphoneSPAccept;
        obj->status=LINPHONE_STATUS_OFFLINE;
        obj->subscribe=TRUE;
@@ -175,6 +170,10 @@ LinphoneFriend *linphone_friend_new_with_addr(const char *addr){
        return fr;
 }
 
+bool_t linphone_friend_in_list(const LinphoneFriend *lf){
+       return lf->lc!=NULL;
+}
+
 void linphone_core_interpret_friend_uri(LinphoneCore *lc, const char *uri, char **result){
        LinphoneAddress *fr=NULL;
        *result=NULL;
@@ -214,6 +213,7 @@ int linphone_friend_set_sip_addr(LinphoneFriend *lf, const char *addr){
                ms_warning("Invalid friend sip uri: %s",addr);
                return -1;
        }
+       linphone_address_clean(fr);
        if (lf->uri!=NULL) linphone_address_destroy(lf->uri);   
        lf->uri=fr;
        return 0;
@@ -240,335 +240,79 @@ int linphone_friend_set_inc_subscribe_policy(LinphoneFriend *fr, LinphoneSubscri
        return 0;
 }
 
-int linphone_friend_set_proxy(LinphoneFriend *fr, struct _LinphoneProxyConfig *cfg){
-       fr->proxy=cfg;
-       return 0;
-}
-
-void linphone_friend_set_sid(LinphoneFriend *lf, int sid){
-       lf->sid=sid;
-}
-void linphone_friend_set_nid(LinphoneFriend *lf, int nid){
-       lf->nid=nid;
-       lf->inc_subscribe_pending=TRUE;
+SalPresenceStatus linphone_online_status_to_sal(LinphoneOnlineStatus os){
+       switch(os){
+               case LINPHONE_STATUS_OFFLINE:
+                       return SalPresenceOffline;
+               break;
+               case LINPHONE_STATUS_ONLINE:
+                       return SalPresenceOnline;
+               break;
+               case LINPHONE_STATUS_BUSY:
+                       return SalPresenceBusy;
+               break;
+               case LINPHONE_STATUS_BERIGHTBACK:
+                       return SalPresenceBerightback;
+               break;
+               case LINPHONE_STATUS_AWAY:
+                       return SalPresenceAway;
+               break;
+               case LINPHONE_STATUS_ONTHEPHONE:
+                       return SalPresenceOnthephone;
+               break;
+               case LINPHONE_STATUS_OUTTOLUNCH:
+                       return SalPresenceOuttolunch;
+               break;
+               case LINPHONE_STATUS_NOT_DISTURB:
+                       return SalPresenceDonotdisturb;
+               break;
+               case LINPHONE_STATUS_MOVED:
+                       return SalPresenceMoved;
+               break;
+               case LINPHONE_STATUS_ALT_SERVICE:
+                       return SalPresenceAltService;
+               break;
+               case LINPHONE_STATUS_PENDING:
+                       return SalPresenceOffline;
+               break;
+               default:
+                       return SalPresenceOffline;
+               break;
+       }
+       return SalPresenceOffline;
 }
 
-void add_presence_body(osip_message_t *notify, LinphoneOnlineStatus online_status)
-{
-       char buf[1000];
-#ifdef SUPPORT_MSN
-       int atom_id = 1000;
-#endif
-       char *contact_info;
-
-       osip_contact_t *ct=NULL;
-       osip_message_get_contact(notify,0,&ct);
-       osip_contact_to_str(ct,&contact_info);
-
-#ifdef SUPPORT_MSN
-
-  if (online_status==LINPHONE_STATUS_ONLINE)
-    {
-      sprintf(buf, "<?xml version=\"1.0\"?>\n\
-<!DOCTYPE presence\n\
-PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
-<presence>\n\
-<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
-<atom id=\"%i\">\n\
-<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
-<status status=\"open\" />\n\
-<msnsubstatus substatus=\"online\" />\n\
-</address>\n\
-</atom>\n\
-</presence>", contact_info, atom_id, contact_info);
-
-    }
-  else if (online_status==LINPHONE_STATUS_BUSY)
-    {
-      sprintf(buf, "<?xml version=\"1.0\"?>\n\
-<!DOCTYPE presence\n\
-PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
-<presence>\n\
-<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
-<atom id=\"%i\">\n\
-<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
-<status status=\"inuse\" />\n\
-<msnsubstatus substatus=\"busy\" />\n\
-</address>\n\
-</atom>\n\
-</presence>", contact_info, atom_id, contact_info);
-
-    }
-  else if (online_status==LINPHONE_STATUS_BERIGHTBACK)
-    {
-      sprintf(buf, "<?xml version=\"1.0\"?>\n\
-<!DOCTYPE presence\n\
-PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
-<presence>\n\
-<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
-<atom id=\"%i\">\n\
-<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
-<status status=\"inactive\" />\n\
-<msnsubstatus substatus=\"berightback\" />\n\
-</address>\n\
-</atom>\n\
-</presence>", contact_info, atom_id, contact_info);
-
-    }
-  else if (online_status==LINPHONE_STATUS_AWAY)
-    {
-      sprintf(buf, "<?xml version=\"1.0\"?>\n\
-<!DOCTYPE presence\n\
-PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
-<presence>\n\
-<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
-<atom id=\"%i\">\n\
-<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
-<status status=\"inactive\" />\n\
-<msnsubstatus substatus=\"away\" />\n\
-</address>\n\
-</atom>\n\
-</presence>", contact_info, atom_id, contact_info);
-
-    }
-  else if (online_status==LINPHONE_STATUS_ONTHEPHONE)
-    {
-      sprintf(buf, "<?xml version=\"1.0\"?>\n\
-<!DOCTYPE presence\n\
-PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
-<presence>\n\
-<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
-<atom id=\"%i\">\n\
-<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
-<status status=\"inuse\" />\n\
-<msnsubstatus substatus=\"onthephone\" />\n\
-</address>\n\
-</atom>\n\
-</presence>", contact_info, atom_id, contact_info);
-
-    }
-  else if (online_status==LINPHONE_STATUS_OUTTOLUNCH)
-    {
-      sprintf(buf, "<?xml version=\"1.0\"?>\n\
-<!DOCTYPE presence\n\
-PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
-<presence>\n\
-<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
-<atom id=\"%i\">\n\
-<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
-<status status=\"inactive\" />\n\
-<msnsubstatus substatus=\"outtolunch\" />\n\
-</address>\n\
-</atom>\n\
-</presence>", contact_info, atom_id, contact_info);
-
-    }
-  else
-    {
-      sprintf(buf, "<?xml version=\"1.0\"?>\n\
-<!DOCTYPE presence\n\
-PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
-<presence>\n\
-<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
-<atom id=\"%i\">\n\
-<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
-<status status=\"inactive\" />\n\
-<msnsubstatus substatus=\"away\" />\n\
-</address>\n\
-</atom>\n\
-</presence>", contact_info, atom_id, contact_info);
-    }
-
-  osip_message_set_body(notify, buf, strlen(buf));
-  osip_message_set_content_type(notify, "application/xpidf+xml");
-#else
-
-  if (online_status==LINPHONE_STATUS_ONLINE)
-    {
-      sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
-<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
-          entity=\"%s\">\n\
-<tuple id=\"sg89ae\">\n\
-<status>\n\
-<basic>open</basic>\n\
-</status>\n\
-<contact priority=\"0.8\">%s</contact>\n\
-<note>online</note>\n\
-</tuple>\n\
-</presence>",
-             contact_info, contact_info);
-    }
-  else if (online_status==LINPHONE_STATUS_BUSY)
-    {
-      sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
-<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
-          xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
-          entity=\"%s\">\n\
-<tuple id=\"sg89ae\">\n\
-<status>\n\
-<basic>open</basic>\n\
-<es:activities>\n\
-  <es:activity>busy</es:activity>\n\
-</es:activities>\n\
-</status>\n\
-<contact priority=\"0.8\">%s</contact>\n\
-<note>busy</note>\n\
-</tuple>\n\
-</presence>",
-             contact_info, contact_info);
-    }
-  else if (online_status==LINPHONE_STATUS_BERIGHTBACK)
-    {
-      sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
-<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
-          xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
-          entity=\"%s\">\n\
-<tuple id=\"sg89ae\">\n\
-<status>\n\
-<basic>open</basic>\n\
-<es:activities>\n\
-  <es:activity>in-transit</es:activity>\n\
-</es:activities>\n\
-</status>\n\
-<contact priority=\"0.8\">%s</contact>\n\
-<note>be right back</note>\n\
-</tuple>\n\
-</presence>",
-             contact_info, contact_info);
-    }
-  else if (online_status==LINPHONE_STATUS_AWAY)
-    {
-      sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
-<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
-          xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
-          entity=\"%s\">\n\
-<tuple id=\"sg89ae\">\n\
-<status>\n\
-<basic>open</basic>\n\
-<es:activities>\n\
-  <es:activity>away</es:activity>\n\
-</es:activities>\n\
-</status>\n\
-<contact priority=\"0.8\">%s</contact>\n\
-<note>away</note>\n\
-</tuple>\n\
-</presence>",
-             contact_info, contact_info);
-    }
-  else if (online_status==LINPHONE_STATUS_ONTHEPHONE)
-    {
-      sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
-<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
-          xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
-          entity=\"%s\">\n\
-<tuple id=\"sg89ae\">\n\
-<status>\n\
-<basic>open</basic>\n\
-<es:activities>\n\
-  <es:activity>on-the-phone</es:activity>\n\
-</es:activities>\n\
-</status>\n\
-<contact priority=\"0.8\">%s</contact>\n\
-<note>on the phone</note>\n\
-</tuple>\n\
-</presence>",
-             contact_info, contact_info);
-    }
-  else if (online_status==LINPHONE_STATUS_OUTTOLUNCH)
-    {
-      sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
-<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
-          xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
-          entity=\"%s\">\n\
-<tuple id=\"sg89ae\">\n\
-<status>\n\
-<basic>open</basic>\n\
-<es:activities>\n\
-  <es:activity>meal</es:activity>\n\
-</es:activities>\n\
-</status>\n\
-<contact priority=\"0.8\">%s</contact>\n\
-<note>out to lunch</note>\n\
-</tuple>\n\
-</presence>",
-             contact_info, contact_info);
-    }
-  else
-    {
-      /* */
-      sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
-<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
-xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
-entity=\"%s\">\n%s",
-             contact_info,
-"<tuple id=\"sg89ae\">\n\
-<status>\n\
-<basic>closed</basic>\n\
-<es:activities>\n\
-  <es:activity>permanent-absence</es:activity>\n\
-</es:activities>\n\
-</status>\n\
-</tuple>\n\
-\n</presence>\n");
-    }
-  osip_message_set_body(notify, buf, strlen(buf));
-  osip_message_set_content_type(notify, "application/pidf+xml");
-
-#endif
-       osip_free(contact_info);
-}
-
-
-void linphone_friend_notify(LinphoneFriend *lf, int ss, LinphoneOnlineStatus os){
+void linphone_friend_notify(LinphoneFriend *lf, LinphoneOnlineStatus os){
        //printf("Wish to notify %p, lf->nid=%i\n",lf,lf->nid);
-       if (lf->in_did!=-1){
-               osip_message_t *msg=NULL;
-               const char *identity;
-               if (lf->proxy!=NULL) identity=lf->proxy->reg_identity;
-               else identity=linphone_core_get_primary_contact(lf->lc);
-               eXosip_lock();
-               eXosip_insubscription_build_notify(lf->in_did,ss,0,&msg);
-               if (msg!=NULL){
-                       osip_message_set_contact(msg,identity);
-                       add_presence_body(msg,os);
-                       eXosip_insubscription_send_request(lf->in_did,msg);
-               }else ms_error("could not create notify for incoming subscription.");
-               eXosip_unlock();
+       if (lf->insub!=NULL){
+               sal_notify_presence(lf->insub,linphone_online_status_to_sal(os),NULL);
        }
 }
 
 static void linphone_friend_unsubscribe(LinphoneFriend *lf){
-       if (lf->out_did!=-1) {
-               osip_message_t *msg=NULL;
-               eXosip_lock();
-               eXosip_subscribe_build_refresh_request(lf->out_did,&msg);
-               if (msg){
-                       osip_message_set_expires(msg,"0");
-                       eXosip_subscribe_send_refresh_request(lf->out_did,msg);
-               }else ms_error("Could not build subscribe refresh request !");
-               eXosip_unlock();
+       if (lf->outsub!=NULL) {
+               sal_unsubscribe(lf->outsub);
+               sal_op_release(lf->outsub);
+               lf->outsub=NULL;
        }
 }
 
 void linphone_friend_destroy(LinphoneFriend *lf){
-       linphone_friend_notify(lf,EXOSIP_SUBCRSTATE_TERMINATED,LINPHONE_STATUS_CLOSED);
+       linphone_friend_notify(lf,LINPHONE_STATUS_OFFLINE);
        linphone_friend_unsubscribe(lf);
+       if (lf->insub){
+               sal_notify_close(lf->insub);
+               sal_op_release(lf->insub);
+       }
        if (lf->uri!=NULL) linphone_address_destroy(lf->uri);
        if (lf->info!=NULL) buddy_info_free(lf->info);
        ms_free(lf);
 }
 
-void linphone_friend_check_for_removed_proxy(LinphoneFriend *lf, LinphoneProxyConfig *cfg){
-       if (lf->proxy==cfg){
-               lf->proxy=NULL;
-       }
-}
-
-const LinphoneAddress *linphone_friend_get_uri(const LinphoneFriend *lf){
+const LinphoneAddress *linphone_friend_get_address(const LinphoneFriend *lf){
        return lf->uri;
 }
 
-
 bool_t linphone_friend_get_send_subscribe(const LinphoneFriend *lf){
        return lf->subscribe;
 }
@@ -597,21 +341,21 @@ void linphone_friend_apply(LinphoneFriend *fr, LinphoneCore *lc){
        if (fr->inc_subscribe_pending){
                switch(fr->pol){
                        case LinphoneSPWait:
-                               linphone_friend_notify(fr,EXOSIP_SUBCRSTATE_PENDING,LINPHONE_STATUS_PENDING);
+                               linphone_friend_notify(fr,LINPHONE_STATUS_PENDING);
                                break;
                        case LinphoneSPAccept:
                                if (fr->lc!=NULL)
                                  {
-                                       linphone_friend_notify(fr,EXOSIP_SUBCRSTATE_ACTIVE,fr->lc->presence_mode);
+                                       linphone_friend_notify(fr,fr->lc->presence_mode);
                                  }
                                break;
                        case LinphoneSPDeny:
-                               linphone_friend_notify(fr,EXOSIP_SUBCRSTATE_TERMINATED,LINPHONE_STATUS_CLOSED);
+                               linphone_friend_notify(fr,LINPHONE_STATUS_OFFLINE);
                                break;
                }
                fr->inc_subscribe_pending=FALSE;
        }
-       if (fr->subscribe && fr->out_did==-1){
+       if (fr->subscribe && fr->outsub==NULL){
                
                __linphone_friend_do_subscribe(fr);
        }
@@ -632,6 +376,14 @@ void linphone_core_add_friend(LinphoneCore *lc, LinphoneFriend *lf)
 {
        ms_return_if_fail(lf->lc==NULL);
        ms_return_if_fail(lf->uri!=NULL);
+       if (ms_list_find(lc->friends,lf)!=NULL){
+               char *tmp=NULL;
+               const LinphoneAddress *addr=linphone_friend_get_address(lf);
+               if (addr) tmp=linphone_address_as_string(addr);
+               ms_warning("Friend %s already in list, ignored.", tmp ? tmp : "unknown");
+               if (tmp) ms_free(tmp);
+               return ;
+       }
        lc->friends=ms_list_append(lc->friends,lf);
        linphone_friend_apply(lf,lc);
        return ;
@@ -667,7 +419,7 @@ static bool_t username_match(const char *u1, const char *u2){
        return FALSE;
 }
 
-LinphoneFriend *linphone_core_get_friend_by_uri(const LinphoneCore *lc, const char *uri){
+LinphoneFriend *linphone_core_get_friend_by_address(const LinphoneCore *lc, const char *uri){
        LinphoneAddress *puri=linphone_address_new(uri);
        const MSList *elem;
        const char *username=linphone_address_get_username(puri);
@@ -752,10 +504,6 @@ LinphoneFriend * linphone_friend_new_from_config_file(LinphoneCore *lc, int inde
        a=lp_config_get_int(config,item,"subscribe",0);
        linphone_friend_send_subscribe(lf,a);
                
-       a=lp_config_get_int(config,item,"proxy",-1);
-       if (a!=-1) {
-               linphone_friend_set_proxy(lf,__index_to_proxy(lc,a));
-       }
        linphone_friend_set_ref_key(lf,lp_config_get_string(config,item,"refkey",NULL));
        return lf;
 }
@@ -779,7 +527,6 @@ const char *__policy_enum_to_str(LinphoneSubscribePolicy pol){
 void linphone_friend_write_to_config_file(LpConfig *config, LinphoneFriend *lf, int index){
        char key[50];
        char *tmp;
-       int a;
        const char *refkey;
        
        sprintf(key,"friend_%i",index);
@@ -798,10 +545,6 @@ void linphone_friend_write_to_config_file(LpConfig *config, LinphoneFriend *lf,
        }
        lp_config_set_string(config,key,"pol",__policy_enum_to_str(lf->pol));
        lp_config_set_int(config,key,"subscribe",lf->subscribe);
-       if (lf->proxy!=NULL){
-               a=ms_list_index(lf->lc->sip_conf.proxies,lf->proxy);
-               lp_config_set_int(config,key,"proxy",a);
-       }else lp_config_set_int(config,key,"proxy",-1);
 
        refkey=linphone_friend_get_ref_key(lf);
        if (refkey){
index 7cf7137731f102bbb7d3f702272861bdaf19b185..210037887791f7319d20f4e48e9ce38b8e7f6883 100644 (file)
@@ -24,7 +24,7 @@
 
 
 #include "linphonecore.h"
-
+#include "private.h"
 #if 0
 static const char *_gstates_text[] = {
   "GSTATE_POWER_OFF",         /* 0 */
index bc12c08e5a5c8ebfc787bab21b7ff606ceb61149..ecb50a0a189a214eba07e9d9fbc1da99f141ba22 100644 (file)
@@ -24,11 +24,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "mediastreamer2/mediastream.h"
 #include "mediastreamer2/msvolume.h"
 #include "mediastreamer2/msequalizer.h"
-#include <eXosip2/eXosip.h>
-#include "sdphandler.h"
 
 #include <ortp/telephonyevents.h>
-#include "exevents.h"
 
 
 #ifdef INET6
@@ -52,15 +49,7 @@ static void toggle_video_preview(LinphoneCore *lc, bool_t val);
 /* same for remote ring (ringback)*/
 #define REMOTE_RING "ringback.wav"
 
-
-sdp_handler_t linphone_sdphandler={
-       linphone_accept_audio_offer,   /*from remote sdp */
-       linphone_accept_video_offer,   /*from remote sdp */
-       linphone_set_audio_offer,       /*to local sdp */
-       linphone_set_video_offer,       /*to local sdp */
-       linphone_read_audio_answer,     /*from incoming answer  */
-       linphone_read_video_answer      /*from incoming answer  */
-};
+extern SalCallbacks linphone_sal_callbacks;
 
 void lc_callback_obj_init(LCCallbackObj *obj,LinphoneCoreCbFunc func,void* ud)
 {
@@ -73,7 +62,54 @@ int lc_callback_obj_invoke(LCCallbackObj *obj, LinphoneCore *lc){
        return 0;
 }
 
-static void  linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from, LinphoneAddress *to){
+
+static MSList *make_codec_list(const MSList *codecs){
+       MSList *l=NULL;
+       const MSList *it;
+       for(it=codecs;it!=NULL;it=it->next){
+               PayloadType *pt=(PayloadType*)it->data;
+               if (pt->flags & PAYLOAD_TYPE_ENABLED){
+                       l=ms_list_append(l,payload_type_clone(pt));
+               }
+       }
+       return l;
+}
+
+static SalMediaDescription *create_local_media_description(LinphoneCore *lc, 
+               const char *localip, const char *username){
+       MSList *l;
+       PayloadType *pt;
+       SalMediaDescription *md=sal_media_description_new();
+       md->nstreams=1;
+       strncpy(md->addr,localip,sizeof(md->addr));
+       strncpy(md->username,username,sizeof(md->username));
+       /*set audio capabilities */
+       strncpy(md->streams[0].addr,localip,sizeof(md->streams[0].addr));
+       md->streams[0].port=linphone_core_get_audio_port(lc);
+       md->streams[0].proto=SalProtoRtpAvp;
+       md->streams[0].type=SalAudio;
+       l=make_codec_list(lc->codecs_conf.audio_codecs);
+       pt=payload_type_clone(rtp_profile_get_payload_from_mime(&av_profile,"telephone-event"));
+       l=ms_list_append(l,pt);
+       md->streams[0].payloads=l;
+       
+       if (lc->dw_audio_bw>0)
+               md->streams[0].bandwidth=lc->dw_audio_bw;
+
+       if (linphone_core_video_enabled (lc)){
+               md->nstreams++;
+               md->streams[1].port=linphone_core_get_video_port(lc);
+               md->streams[1].proto=SalProtoRtpAvp;
+               md->streams[1].type=SalVideo;
+               l=make_codec_list(lc->codecs_conf.video_codecs);
+               md->streams[1].payloads=l;
+               if (lc->dw_video_bw)
+                       md->streams[1].bandwidth=lc->dw_video_bw;
+       }
+       return md;
+}
+
+static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from, LinphoneAddress *to){
        call->state=LCStateInit;
        call->start_time=time(NULL);
        call->media_start_time=0;
@@ -81,12 +117,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");
-}
-
-void linphone_call_init_media_params(LinphoneCall *call){
-       memset(&call->audio_params,0,sizeof(call->audio_params));
-       memset(&call->video_params,0,sizeof(call->video_params));
 }
 
 static void discover_mtu(LinphoneCore *lc, const char *remote){
@@ -106,44 +136,33 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr
 {
        LinphoneCall *call=ms_new0(LinphoneCall,1);
        call->dir=LinphoneCallOutgoing;
-       call->cid=-1;
-       call->did=-1;
-       call->tid=-1;
+       call->op=sal_op_new(lc->sal);
+       sal_op_set_user_pointer(call->op,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,
+               linphone_address_get_username(from));
        linphone_call_init_common(call,from,to);
-       call->sdpctx=sdp_handler_create_context(&linphone_sdphandler,
-               call->audio_params.natd_port>0 ? call->audio_params.natd_addr : call->localip,
-               linphone_address_get_username (from),NULL);
-       sdp_context_set_user_pointer(call->sdpctx,(void*)call);
        discover_mtu(lc,linphone_address_get_domain (to));
        return call;
 }
 
-
-LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, eXosip_event_t *ev){
+LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op){
        LinphoneCall *call=ms_new0(LinphoneCall,1);
        LinphoneAddress *me=linphone_core_get_primary_contact_parsed(lc);
-       osip_header_t *h=NULL;
 
        call->dir=LinphoneCallIncoming;
-       call->cid=ev->cid;
-       call->did=ev->did;
-       call->tid=ev->tid;
+       sal_op_set_user_pointer(op,call);
+       call->op=op;
        call->core=lc;
        
        linphone_address_clean(from);
-       
        linphone_core_get_local_ip(lc,linphone_address_get_domain(from),call->localip);
+       call->localdesc=create_local_media_description (lc,call->localip,
+           linphone_address_get_username(me));
        linphone_call_init_common(call, from, to);
-       call->sdpctx=sdp_handler_create_context(&linphone_sdphandler,
-               call->audio_params.natd_port>0 ? call->audio_params.natd_addr : call->localip,
-               linphone_address_get_username (me),NULL);
-       sdp_context_set_user_pointer(call->sdpctx,(void*)call);
        discover_mtu(lc,linphone_address_get_domain(from));
        linphone_address_destroy(me);
-       osip_message_header_get_byname(ev->request,"Session-expires",0,&h);
-       if (h) call->supports_session_timers=TRUE;
        return call;
 }
 
@@ -152,8 +171,9 @@ 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->sdpctx!=NULL) sdp_context_free(obj->sdpctx);
+       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);
        ms_free(obj);
 }
 
@@ -387,43 +407,6 @@ const LinphoneAddress *linphone_core_get_remote_uri(LinphoneCore *lc){
        return call->dir==LinphoneCallIncoming ? call->log->from : call->log->to;
 }
 
-void _osip_trace_func(char *fi, int li, osip_trace_level_t level, char *chfr, va_list ap){
-       int ortp_level=ORTP_DEBUG;
-       switch(level){
-               case OSIP_INFO1:
-               case OSIP_INFO2:
-               case OSIP_INFO3:
-               case OSIP_INFO4:
-                       ortp_level=ORTP_MESSAGE;
-                       break;
-               case OSIP_WARNING:
-                       ortp_level=ORTP_WARNING;
-                       break;
-               case OSIP_ERROR:
-               case OSIP_BUG:
-                       ortp_level=ORTP_ERROR;
-                       break;
-               case OSIP_FATAL:
-                       ortp_level=ORTP_FATAL;
-                       break;
-               case END_TRACE_LEVEL:
-                       break;
-       }
-       if (ortp_log_level_enabled(level)){
-               int len=strlen(chfr);
-               char *chfrdup=ortp_strdup(chfr);
-               /*need to remove endline*/
-               if (len>1){
-                       if (chfrdup[len-1]=='\n')
-                               chfrdup[len-1]='\0';
-                       if (chfrdup[len-2]=='\r')
-                               chfrdup[len-2]='\0';
-               }
-               ortp_logv(ortp_level,chfrdup,ap);
-               ortp_free(chfrdup);
-       }
-}
-
 /**
  * Enable logs in supplied FILE*.
  *
@@ -436,7 +419,6 @@ void linphone_core_enable_logs(FILE *file){
        if (file==NULL) file=stdout;
        ortp_set_log_file(file);
        ortp_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL);
-       osip_trace_initialize_func (OSIP_INFO4,&_osip_trace_func);
 }
 
 /**
@@ -450,7 +432,6 @@ void linphone_core_enable_logs(FILE *file){
 **/
 void linphone_core_enable_logs_with_cb(OrtpLogFunc logfunc){
        ortp_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL);
-       osip_trace_initialize_func (OSIP_INFO4,&_osip_trace_func);
        ortp_set_log_handler(logfunc);
 }
 
@@ -460,8 +441,6 @@ void linphone_core_enable_logs_with_cb(OrtpLogFunc logfunc){
  * @ingroup misc
 **/
 void linphone_core_disable_logs(){
-       int tl;
-       for (tl=0;tl<=OSIP_INFO4;tl++) osip_trace_disable_level(tl);
        ortp_set_log_level_mask(ORTP_ERROR|ORTP_FATAL);
 }
 
@@ -677,28 +656,100 @@ static void rtp_config_read(LinphoneCore *lc)
        linphone_core_set_nortp_timeout(lc,nortp_timeout);
 }
 
+static PayloadType * find_payload(RtpProfile *prof, const char *mime_type, int clock_rate, const char *recv_fmtp){
+       PayloadType *candidate=NULL;
+       int i;
+       PayloadType *it;
+       for(i=0;i<127;++i){
+               it=rtp_profile_get_payload(prof,i);
+               if (it!=NULL && strcasecmp(mime_type,it->mime_type)==0
+                       && (clock_rate==it->clock_rate || clock_rate<=0) ){
+                       if ( (recv_fmtp && it->recv_fmtp && strcasecmp(recv_fmtp,it->recv_fmtp)==0) ||
+                               (recv_fmtp==NULL && it->recv_fmtp==NULL) ){
+                               /*exact match*/
+                               return it;
+                       }else candidate=it;
+               }
+       }
+       return candidate;
+}
 
-static PayloadType * get_codec(LpConfig *config, char* type,int index){
+static bool_t get_codec(LpConfig *config, char* type, int index, PayloadType **ret){
        char codeckey[50];
        const char *mime,*fmtp;
        int rate,enabled;
        PayloadType *pt;
 
+       *ret=NULL;
        snprintf(codeckey,50,"%s_%i",type,index);
        mime=lp_config_get_string(config,codeckey,"mime",NULL);
-       if (mime==NULL || strlen(mime)==0 ) return NULL;
-
-       pt=payload_type_new();
-       pt->mime_type=ms_strdup(mime);
+       if (mime==NULL || strlen(mime)==0 ) return FALSE;
 
        rate=lp_config_get_int(config,codeckey,"rate",8000);
-       pt->clock_rate=rate;
        fmtp=lp_config_get_string(config,codeckey,"recv_fmtp",NULL);
-       if (fmtp) pt->recv_fmtp=ms_strdup(fmtp);
        enabled=lp_config_get_int(config,codeckey,"enabled",1);
-       if (enabled ) pt->flags|=PAYLOAD_TYPE_ENABLED;
+       pt=find_payload(&av_profile,mime,rate,fmtp);
+       if (pt && enabled ) pt->flags|=PAYLOAD_TYPE_ENABLED;
        //ms_message("Found codec %s/%i",pt->mime_type,pt->clock_rate);
-       return pt;
+       if (pt==NULL) ms_warning("Ignoring codec config %s/%i with fmtp=%s because unsupported",
+                       mime,rate,fmtp ? fmtp : "");
+       *ret=pt;
+       return TRUE;
+}
+
+static const char *codec_pref_order[]={
+       "speex",
+       "gsm",
+       "pcmu",
+       "pcma",
+       "H264",
+       "MP4V-ES",
+       "theora",
+       "H263-1998",
+       "H263",
+       NULL,
+};
+
+static int find_codec_rank(const char *mime){
+       int i;
+       for(i=0;codec_pref_order[i]!=NULL;++i){
+               if (strcasecmp(codec_pref_order[i],mime)==0)
+                       break;
+       }
+       return i;
+}
+
+static int codec_compare(const PayloadType *a, const PayloadType *b){
+       int ra,rb;
+       ra=find_codec_rank(a->mime_type);
+       rb=find_codec_rank(b->mime_type);
+       if (ra>rb) return 1;
+       if (ra<rb) return -1;
+       return 0;
+}
+
+static MSList *add_missing_codecs(SalStreamType mtype, MSList *l){
+       int i;
+       for(i=0;i<127;++i){
+               PayloadType *pt=rtp_profile_get_payload(&av_profile,i);
+               if (pt){
+                       if (mtype==SalVideo && pt->type!=PAYLOAD_VIDEO)
+                               pt=NULL;
+                       else if (mtype==SalAudio && (pt->type!=PAYLOAD_AUDIO_PACKETIZED 
+                           && pt->type!=PAYLOAD_AUDIO_CONTINUOUS)){
+                               pt=NULL;
+                       }
+                       if (pt && ms_filter_codec_supported(pt->mime_type)){
+                               if (ms_list_find(l,pt)==NULL){
+                                       payload_type_set_flag(pt,PAYLOAD_TYPE_ENABLED);
+                                       ms_message("Adding new codec %s/%i with fmtp %s",
+                                           pt->mime_type,pt->clock_rate,pt->recv_fmtp ? pt->recv_fmtp : "");
+                                       l=ms_list_insert_sorted(l,pt,(int (*)(const void *, const void *))codec_compare);
+                               }
+                       }
+               }
+       }
+       return l;
 }
 
 static void codecs_config_read(LinphoneCore *lc)
@@ -707,23 +758,28 @@ static void codecs_config_read(LinphoneCore *lc)
        PayloadType *pt;
        MSList *audio_codecs=NULL;
        MSList *video_codecs=NULL;
-       for (i=0;;i++){
-               pt=get_codec(lc->config,"audio_codec",i);
-               if (pt==NULL) break;
-               audio_codecs=ms_list_append(audio_codecs,(void *)pt);
+       for (i=0;get_codec(lc->config,"audio_codec",i,&pt);i++){
+               if (pt){
+                       if (!ms_filter_codec_supported(pt->mime_type)){
+                               ms_warning("Codec %s is not supported by mediastreamer2, removed.",pt->mime_type);
+                       }else audio_codecs=ms_list_append(audio_codecs,pt);
+               }
        }
-       for (i=0;;i++){
-               pt=get_codec(lc->config,"video_codec",i);
-               if (pt==NULL) break;
-               video_codecs=ms_list_append(video_codecs,(void *)pt);
+       audio_codecs=add_missing_codecs(SalAudio,audio_codecs);
+       for (i=0;get_codec(lc->config,"video_codec",i,&pt);i++){
+               if (pt){
+                       if (!ms_filter_codec_supported(pt->mime_type)){
+                               ms_warning("Codec %s is not supported by mediastreamer2, removed.",pt->mime_type);
+                       }else video_codecs=ms_list_append(video_codecs,(void *)pt);
+               }
        }
+       video_codecs=add_missing_codecs(SalVideo,video_codecs);
        linphone_core_set_audio_codecs(lc,audio_codecs);
        linphone_core_set_video_codecs(lc,video_codecs);
-       linphone_core_setup_local_rtp_profile(lc);
+       linphone_core_update_allocated_audio_bandwidth(lc);
 }
 
-static void video_config_read(LinphoneCore *lc)
-{
+static void video_config_read(LinphoneCore *lc){
        int capture, display, self_view;
        int enabled;
        const char *str;
@@ -871,6 +927,7 @@ static MSList *linphone_payload_types=NULL;
 static void linphone_core_assign_payload_type(PayloadType *const_pt, int number, const char *recv_fmtp){
        PayloadType *pt;
        pt=payload_type_clone(const_pt);
+       payload_type_set_number(pt,number);
        if (recv_fmtp!=NULL) payload_type_set_recv_fmtp(pt,recv_fmtp);
        rtp_profile_set_payload(&av_profile,number,pt);
        linphone_payload_types=ms_list_append(linphone_payload_types,pt);
@@ -894,11 +951,14 @@ static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vta
        gstate_new_state(lc, GSTATE_POWER_STARTUP, NULL);
 
        ortp_init();
+       linphone_core_assign_payload_type(&payload_type_pcmu8000,0,NULL);
+       linphone_core_assign_payload_type(&payload_type_gsm,3,NULL);
+       linphone_core_assign_payload_type(&payload_type_pcma8000,8,NULL);
        linphone_core_assign_payload_type(&payload_type_lpc1015,115,NULL);
        linphone_core_assign_payload_type(&payload_type_speex_nb,110,"vbr=on");
        linphone_core_assign_payload_type(&payload_type_speex_wb,111,"vbr=on");
        linphone_core_assign_payload_type(&payload_type_speex_uwb,112,"vbr=on");
-       linphone_core_assign_payload_type(&payload_type_telephone_event,101,NULL);
+       linphone_core_assign_payload_type(&payload_type_telephone_event,101,"0-11");
        linphone_core_assign_payload_type(&payload_type_ilbc,113,"mode=30");
 
 #ifdef ENABLE_NONSTANDARD_GSM
@@ -931,11 +991,12 @@ static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vta
        if (factory_config_path)
                lp_config_read_file(lc->config,factory_config_path);
 
-#ifdef VINCENT_MAURY_RSVP
-       /* default qos parameters : rsvp on, rpc off */
-       lc->rsvp_enable = 1;
-       lc->rpc_enable = 0;
-#endif
+       lc->sal=sal_init();
+       sal_set_user_pointer(lc->sal,lc);
+       sal_set_callbacks(lc->sal,&linphone_sal_callbacks);
+       if (lp_config_get_int(lc->config,"sip","use_session_timers",0)==1){
+               sal_use_session_timers(lc->sal,200);
+       }
        sip_setup_register_all();
        sound_config_read(lc);
        net_config_read(lc);
@@ -948,7 +1009,6 @@ static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vta
        lc->presence_mode=LINPHONE_STATUS_ONLINE;
        lc->max_call_logs=15;
        ui_config_read(lc);
-       ms_mutex_init(&lc->lock,NULL);
        lc->vtable.display_status(lc,_("Ready"));
         gstate_new_state(lc, GSTATE_POWER_ON, NULL);
        lc->ready=TRUE;
@@ -1014,11 +1074,10 @@ const MSList *linphone_core_get_video_codecs(const LinphoneCore *lc)
 **/
 int linphone_core_set_primary_contact(LinphoneCore *lc, const char *contact)
 {
-       osip_from_t *ctt=NULL;
-       osip_from_init(&ctt);
-       if (osip_from_parse(ctt,contact)!=0){
+       LinphoneAddress *ctt;
+
+       if ((ctt=linphone_address_new(contact))==0) {
                ms_error("Bad contact url: %s",contact);
-               osip_from_free(ctt);
                return -1;
        }
        if (lc->sip_conf.contact!=NULL) ms_free(lc->sip_conf.contact);
@@ -1027,7 +1086,7 @@ int linphone_core_set_primary_contact(LinphoneCore *lc, const char *contact)
                ms_free(lc->sip_conf.guessed_contact);
                lc->sip_conf.guessed_contact=NULL;
        }
-       osip_from_free(ctt);
+       linphone_address_destroy(ctt);
        return 0;
 }
 
@@ -1045,12 +1104,8 @@ void linphone_core_get_local_ip(LinphoneCore *lc, const char *dest, char *result
        if (dest==NULL) dest="87.98.157.38"; /*a public IP address*/
        if (linphone_core_get_local_ip_for(dest,result)==0)
                return;
-       /*else fallback to exosip routine that will attempt to find the most realistic interface */
-       if (eXosip_guess_localip(lc->sip_conf.ipv6_enabled ? AF_INET6 : AF_INET,result,LINPHONE_IPADDR_SIZE)<0){
-               /*default to something */
-               strncpy(result,lc->sip_conf.ipv6_enabled ? "::1" : "127.0.0.1",LINPHONE_IPADDR_SIZE);
-               ms_error("Could not find default routable ip address !");
-       }
+       /*else fallback to SAL routine that will attempt to find the most realistic interface */
+       sal_get_default_local_ip(lc->sal,lc->sip_conf.ipv6_enabled ? AF_INET6 : AF_INET,result,LINPHONE_IPADDR_SIZE);
 }
 
 /**
@@ -1058,42 +1113,33 @@ void linphone_core_get_local_ip(LinphoneCore *lc, const char *dest, char *result
  *
  * @ingroup proxies
 **/
-const char *linphone_core_get_primary_contact(LinphoneCore *lc)
-{
+const char *linphone_core_get_primary_contact(LinphoneCore *lc){
        char *identity;
        char tmp[LINPHONE_IPADDR_SIZE];
+       
        if (lc->sip_conf.guess_hostname){
                if (lc->sip_conf.guessed_contact==NULL || lc->sip_conf.loopback_only){
                        char *guessed=NULL;
-                       osip_from_t *url;
+                       LinphoneAddress *url;
                        if (lc->sip_conf.guessed_contact!=NULL){
                                ms_free(lc->sip_conf.guessed_contact);
                                lc->sip_conf.guessed_contact=NULL;
                        }
-
-                       osip_from_init(&url);
-                       if (osip_from_parse(url,lc->sip_conf.contact)==0){
-
-                       }else ms_error("Could not parse identity contact !");
+                       url=linphone_address_new(lc->sip_conf.contact);
+                       if (!url){
+                               ms_error("Could not parse identity contact !");
+                               url=linphone_address_new("sip:unknown@unkwownhost");
+                       }
                        linphone_core_get_local_ip(lc, NULL, tmp);
                        if (strcmp(tmp,"127.0.0.1")==0 || strcmp(tmp,"::1")==0 ){
                                ms_warning("Local loopback network only !");
                                lc->sip_conf.loopback_only=TRUE;
                        }else lc->sip_conf.loopback_only=FALSE;
-                       osip_free(url->url->host);
-                       url->url->host=osip_strdup(tmp);
-                       if (url->url->port!=NULL){
-                               osip_free(url->url->port);
-                               url->url->port=NULL;
-                       }
-                       if (lc->sip_conf.sip_port!=5060){
-                               url->url->port=ortp_strdup_printf("%i",lc->sip_conf.sip_port);
-                       }
-                       osip_from_to_str(url,&guessed);
+                       linphone_address_set_domain(url,tmp);
+                       linphone_address_set_port_int(url,lc->sip_conf.sip_port);
+                       guessed=linphone_address_as_string(url);
                        lc->sip_conf.guessed_contact=guessed;
-
-                       osip_from_free(url);
-
+                       linphone_address_destroy(url);
                }
                identity=lc->sip_conf.guessed_contact;
        }else{
@@ -1299,7 +1345,11 @@ static bool_t exosip_running=FALSE;
 static char _ua_name[64]="Linphone";
 static char _ua_version[64]=LINPHONE_VERSION;
 
-static void apply_user_agent(void){
+#ifdef HAVE_EXOSIP_GET_VERSION
+extern const char *eXosip_get_version();
+#endif
+
+static void apply_user_agent(LinphoneCore *lc){
        char ua_string[256];
        snprintf(ua_string,sizeof(ua_string),"%s/%s (eXosip2/%s)",_ua_name,_ua_version,
 #ifdef HAVE_EXOSIP_GET_VERSION
@@ -1308,7 +1358,7 @@ static void apply_user_agent(void){
                 "unknown"
 #endif
        );
-       eXosip_set_user_agent(ua_string);
+       if (lc->sal) sal_set_user_agent(lc->sal,ua_string);
 }
 
 /**
@@ -1332,18 +1382,14 @@ void linphone_core_set_sip_port(LinphoneCore *lc,int port)
        int err=0;
        if (port==lc->sip_conf.sip_port) return;
        lc->sip_conf.sip_port=port;
-       if (exosip_running) eXosip_quit();
-       eXosip_init();
-       err=0;
-       eXosip_set_option(13,&err); /*13=EXOSIP_OPT_SRV_WITH_NAPTR, as it is an enum value, we can't use it unless we are sure of the
-                                       version of eXosip, which is not the case*/
-       eXosip_enable_ipv6(lc->sip_conf.ipv6_enabled);
+
+       if (lc->sal==NULL) return;
+       
        if (lc->sip_conf.ipv6_enabled)
                anyaddr="::0";
        else
                anyaddr="0.0.0.0";
-       err=eXosip_listen_addr (IPPROTO_UDP, anyaddr, port,
-               lc->sip_conf.ipv6_enabled ?  PF_INET6 : PF_INET, 0);
+       err=sal_listen_port (lc->sal,anyaddr,port, SalTransportDatagram,FALSE);
        if (err<0){
                char *msg=ortp_strdup_printf("UDP port %i seems already in use ! Cannot initialize.",port);
                ms_warning(msg);
@@ -1351,13 +1397,7 @@ void linphone_core_set_sip_port(LinphoneCore *lc,int port)
                ms_free(msg);
                return;
        }
-#ifdef VINCENT_MAURY_RSVP
-       /* tell exosip the qos settings according to default linphone parameters */
-       eXosip_set_rsvp_mode (lc->rsvp_enable);
-       eXosip_set_rpc_mode (lc->rpc_enable);
-#endif
-       apply_user_agent();
-       exosip_running=TRUE;
+       apply_user_agent(lc);
 }
 
 /**
@@ -1382,7 +1422,7 @@ bool_t linphone_core_ipv6_enabled(LinphoneCore *lc){
 void linphone_core_enable_ipv6(LinphoneCore *lc, bool_t val){
        if (lc->sip_conf.ipv6_enabled!=val){
                lc->sip_conf.ipv6_enabled=val;
-               if (exosip_running){
+               if (lc->sal){
                        /* we need to restart eXosip */
                        linphone_core_set_sip_port(lc, lc->sip_conf.sip_port);
                }
@@ -1410,12 +1450,13 @@ static void proxy_update(LinphoneCore *lc, time_t curtime){
                char result[LINPHONE_IPADDR_SIZE];
                /* only do the network up checking every five seconds */
                if (last_check==0 || (curtime-last_check)>=5){
-                       if (eXosip_guess_localip(lc->sip_conf.ipv6_enabled ? AF_INET6 : AF_INET,result,LINPHONE_IPADDR_SIZE)==0){
-                               if (strcmp(result,"::1")!=0 && strcmp(result,"127.0.0.1")!=0){
-                                       last_status=TRUE;
-                                       ms_message("Network is up, registering now (%s)",result);
-                               }else last_status=FALSE;
-                       }
+                       sal_get_default_local_ip(lc->sal,
+                           lc->sip_conf.ipv6_enabled ? AF_INET6 : AF_INET,
+                           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);
+                       }else last_status=FALSE;
                        last_check=curtime;
                }
                doit=last_status;
@@ -1424,7 +1465,7 @@ static void proxy_update(LinphoneCore *lc, time_t curtime){
 }
 
 static void assign_buddy_info(LinphoneCore *lc, BuddyInfo *info){
-       LinphoneFriend *lf=linphone_core_get_friend_by_uri(lc,info->sip_uri);
+       LinphoneFriend *lf=linphone_core_get_friend_by_address(lc,info->sip_uri);
        if (lf!=NULL){
                lf->info=info;
                ms_message("%s has a BuddyInfo assigned with image %p",info->sip_uri, info->image_data);
@@ -1508,14 +1549,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;
@@ -1529,17 +1568,7 @@ void linphone_core_iterate(LinphoneCore *lc)
                lc_callback_obj_invoke(&lc->preview_finished_cb,lc);
        }
 
-       if (exosip_running){
-               while((ev=eXosip_event_wait(0,0))!=NULL){
-                       linphone_core_process_event(lc,ev);
-               }
-               if (lc->automatic_action==0) {
-                       eXosip_lock();
-                       eXosip_automatic_action();
-                       eXosip_unlock();
-               }
-       }
-
+       sal_iterate(lc->sal);
        proxy_update(lc,curtime);
 
        if (lc->call!=NULL){
@@ -1590,40 +1619,9 @@ void linphone_core_iterate(LinphoneCore *lc)
 }
 
 
-bool_t linphone_core_is_in_main_thread(LinphoneCore *lc){
-       return TRUE;
-}
-
-static char *guess_route_if_any(LinphoneCore *lc, osip_to_t *parsed_url){
-       const MSList *elem=linphone_core_get_proxy_config_list(lc);
-       for(;elem!=NULL;elem=elem->next){
-               LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data;
-               char prx[256];
-               if (cfg->ssctx && sip_setup_context_get_proxy(cfg->ssctx,parsed_url->url->host,prx,sizeof(prx))==0){
-                       ms_message("We have a proxy for domain %s",parsed_url->url->host);
-                       if (strcmp(parsed_url->url->host,prx)!=0){
-                               char *route=NULL;
-                               osip_route_t *rt;
-                               osip_route_init(&rt);
-                               if (osip_route_parse(rt,prx)==0){
-                                       char *rtstr;
-                                       osip_uri_uparam_add(rt->url,osip_strdup("lr"),NULL);
-                                       osip_route_to_str(rt,&rtstr);
-                                       route=ms_strdup(rtstr);
-                                       osip_free(rtstr);
-                               }
-                               osip_route_free(rt);
-                               ms_message("Adding a route: %s",route);
-                               return route;
-                       }
-               }
-       }
-       return NULL;
-}
-
 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=lc->default_proxy;;
        char *tmpurl;
@@ -1676,27 +1674,7 @@ bool_t linphone_core_interpret_url(LinphoneCore *lc, const char *url, LinphoneAd
                        linphone_address_set_username(uri,normalized_username);
                                                                                
                        if (real_parsed_url!=NULL) *real_parsed_url=uri;
-#if 0
-                       /*if the prompted uri was auto-suffixed with proxy domain,
-                       then automatically set a route so that the request goes
-                       through the proxy*/
-                       if (tmproute==NULL){
-                               osip_route_t *rt=NULL;
-                               char *rtstr=NULL;
-                               osip_route_init(&rt);
-                               if (osip_route_parse(rt,linphone_proxy_config_get_addr(proxy))==0){
-                                       osip_uri_uparam_add(rt->url,osip_strdup("lr"),NULL);
-                                       osip_route_to_str(rt,&rtstr);
-                                       *route=ms_strdup(rtstr);
-                                       osip_free(rtstr);
-                               }
-                               ms_message("setting automatically a route to %s",*route);
-                       }
-                       else *route=ms_strdup(tmproute);
-#else
-                       if (tmproute==NULL) *route=guess_route_if_any(lc,*real_parsed_url);
                        if (tmproute) *route=ms_strdup(tmproute);
-#endif
                        return TRUE;
                }else return FALSE;
        }
@@ -1705,7 +1683,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 */
@@ -1745,15 +1723,6 @@ const char * linphone_core_get_route(LinphoneCore *lc){
        return route;
 }
 
-void linphone_set_sdp(osip_message_t *sip, const char *sdpmesg){
-       int sdplen=strlen(sdpmesg);
-       char clen[10];
-       snprintf(clen,sizeof(clen),"%i",sdplen);
-       osip_message_set_body(sip,sdpmesg,sdplen);
-       osip_message_set_content_type(sip,"application/sdp");
-       osip_message_set_content_length(sip,clen);
-}
-
 LinphoneProxyConfig * linphone_core_lookup_known_proxy(LinphoneCore *lc, const LinphoneAddress *uri){
        const MSList *elem;
        LinphoneProxyConfig *found_cfg=NULL;
@@ -1768,37 +1737,29 @@ LinphoneProxyConfig * linphone_core_lookup_known_proxy(LinphoneCore *lc, const L
        return found_cfg;
 }
 
-static void fix_contact(LinphoneCore *lc, osip_message_t *msg, const char *localip, LinphoneProxyConfig *dest_proxy){
-       osip_contact_t *ctt=NULL;
-       const char *ip=NULL;
-       int port=5060;
+static char *get_fixed_contact(LinphoneCore *lc, const char *localip, LinphoneProxyConfig *dest_proxy){
+       LinphoneAddress *ctt;
 
-       osip_message_get_contact(msg,0,&ctt);
-       if (ctt!=NULL){
-               if (dest_proxy!=NULL){
-                       /* if we know the request will go to a known proxy for which we are registered,
-                       we can use the same contact address as in the register */
-                       linphone_proxy_config_get_contact(dest_proxy,&ip,&port);
-               }else{
-                       ip=localip;
-                       port=linphone_core_get_sip_port(lc);
-               }
-               if (ip!=NULL){
-                       osip_free(ctt->url->host);
-                       ctt->url->host=osip_strdup(ip);
-               }
-               if (port!=0){
-                       char tmp[10]={0};
-                       char *str;
-                       snprintf(tmp,sizeof(tmp)-1,"%i",port);
-                       if (ctt->url->port!=NULL)
-                               osip_free(ctt->url->port);
-                       ctt->url->port=osip_strdup(tmp);
-                       osip_contact_to_str(ctt,&str);
-                       ms_message("Contact has been fixed to %s",str);
-                       osip_free(str);
+       if (dest_proxy && dest_proxy->op){
+               const char *fixed_contact=sal_op_get_contact(dest_proxy->op);
+               if (fixed_contact) {
+                       ms_message("Contact has been fixed using proxy to %s",fixed_contact);
+                       return ms_strdup(fixed_contact);
                }
        }
+       ctt=linphone_core_get_primary_contact_parsed(lc);
+       
+       if (ctt!=NULL){
+               char *ret;
+               /*otherwise use supllied localip*/
+               linphone_address_set_domain(ctt,localip);
+               linphone_address_set_port_int(ctt,linphone_core_get_sip_port(lc));
+               ret=linphone_address_as_string_uri_only(ctt);
+               linphone_address_destroy(ctt);
+               ms_message("Contact has been fixed using local ip to %s",ret);
+               return ret;
+       }
+       return NULL;
 }
 
 /**
@@ -1812,17 +1773,16 @@ int linphone_core_invite(LinphoneCore *lc, const char *url)
 {
        char *barmsg;
        int err=0;
-       char *sdpmesg=NULL;
        char *route=NULL;
        const char *from=NULL;
-       osip_message_t *invite=NULL;
-       sdp_context_t *ctx=NULL;
+       char *contact=NULL;
        LinphoneProxyConfig *proxy=NULL;
        LinphoneAddress *parsed_url2=NULL;
        LinphoneAddress *real_parsed_url=NULL;
        char *real_url=NULL;
        LinphoneProxyConfig *dest_proxy=NULL;
-
+       LinphoneCall *call;
+       
        if (lc->call!=NULL){
                lc->vtable.display_warning(lc,_("Sorry, having multiple simultaneous calls is not supported yet !"));
                return -1;
@@ -1848,52 +1808,43 @@ int linphone_core_invite(LinphoneCore *lc, const char *url)
        /* if no proxy or no identity defined for this proxy, default to primary contact*/
        if (from==NULL) from=linphone_core_get_primary_contact(lc);
 
-       err=eXosip_call_build_initial_invite(&invite,real_url,from,
-                                               route,"Phone call");
-       if (err<0){
-               ms_warning("Could not build initial invite cause [%i]",err);
-               goto end;
-       }
-       if (lp_config_get_int(lc->config,"sip","use_session_timers",0)==1){
-               osip_message_set_header(invite, "Session-expires", "200");
-               osip_message_set_supported(invite, "timer");
-       }
-       /* make sdp message */
-
        parsed_url2=linphone_address_new(from);
 
-       lc->call=linphone_call_new_outgoing(lc,parsed_url2,real_parsed_url);
+       call=linphone_call_new_outgoing(lc,parsed_url2,real_parsed_url);
+       sal_op_set_route(call->op,route);
+
        /*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,invite,lc->call->localip,dest_proxy);
+               contact=get_fixed_contact(lc,call->localip,dest_proxy);
+       if (contact){
+               sal_op_set_contact(call->op, contact);
+               ms_free(contact);
+       }
+
+       lc->call=call;
+
+       linphone_core_init_media_streams(lc,lc->call);
+       if (!lc->sip_conf.sdp_200_ack){ 
+               call->media_pending=TRUE;
+               sal_call_set_local_media_description(call->op,call->localdesc);
+       }
+       err=sal_call(call->op,from,real_url);
 
        barmsg=ortp_strdup_printf("%s %s", _("Contacting"), real_url);
        lc->vtable.display_status(lc,barmsg);
        ms_free(barmsg);
-       if (!lc->sip_conf.sdp_200_ack){
-               ctx=lc->call->sdpctx;
-               sdpmesg=sdp_context_get_offer(ctx);
-               linphone_set_sdp(invite,sdpmesg);
-               linphone_core_init_media_streams(lc);
-       }
-       eXosip_lock();
-       err=eXosip_call_send_initial_invite(invite);
-       lc->call->cid=err;
-       eXosip_unlock();
        
        if (err<0){
                ms_warning("Could not initiate call.");
                lc->vtable.display_status(lc,_("could not call"));
-               linphone_call_destroy(lc->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;
-       end:
-               if (real_url!=NULL) ms_free(real_url);
-               if (route!=NULL) ms_free(route);
+       if (real_url!=NULL) ms_free(real_url);
+       if (route!=NULL) ms_free(route);
        return (err<0) ? -1 : 0;
 }
 
@@ -1902,7 +1853,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 */
@@ -1916,11 +1866,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;
 }
 
@@ -1936,81 +1883,9 @@ 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){
-       lc->audiostream=audio_stream_new(linphone_core_get_audio_port(lc),linphone_core_ipv6_enabled(lc));
+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));
        if (linphone_core_echo_limiter_enabled(lc)){
                const char *type=lp_config_get_string(lc->config,"sound","el_type","mic");
                if (strcasecmp(type,"mic")==0)
@@ -2035,8 +1910,8 @@ void linphone_core_init_media_streams(LinphoneCore *lc){
                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)
-               lc->videostream=video_stream_new(linphone_core_get_video_port(lc),linphone_core_ipv6_enabled(lc));
+       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;
 #endif
@@ -2115,99 +1990,129 @@ static void post_configure_audio_streams(LinphoneCore *lc){
        }
 }
 
+static RtpProfile *make_profile(LinphoneCore *lc, const SalStreamDescription *desc, int *used_pt){
+       int bw;
+       const 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;
+               const 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
        {
+               const 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;
@@ -2228,6 +2133,16 @@ void linphone_core_stop_media_streams(LinphoneCore *lc){
                }
        }
 #endif
+       if (call->audio_profile){
+               rtp_profile_clear_all(call->audio_profile);
+               rtp_profile_destroy(call->audio_profile);
+               call->audio_profile=NULL;
+       }
+       if (call->video_profile){
+               rtp_profile_clear_all(call->video_profile);
+               rtp_profile_destroy(call->video_profile);
+               call->video_profile=NULL;
+       }
 }
 
 /**
@@ -2246,17 +2161,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;
        }
@@ -2268,42 +2180,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);
+       }else call->media_pending=TRUE;
        ms_message("call answered.");
        return 0;
 }
@@ -2323,17 +2215,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);
@@ -2385,22 +2274,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);
                /*
@@ -2412,7 +2292,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){
@@ -2784,7 +2663,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)
@@ -2798,26 +2677,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);
        }
 }
 
@@ -2884,7 +2750,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);
@@ -2898,22 +2764,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);
        }
 }
 
@@ -3327,30 +3187,31 @@ void sip_config_uninit(LinphoneCore *lc)
        lp_config_set_int(lc->config,"sip","use_rfc2833",config->use_rfc2833);
        lp_config_set_int(lc->config,"sip","use_ipv6",config->ipv6_enabled);
        lp_config_set_int(lc->config,"sip","register_only_when_network_is_up",config->register_only_when_network_is_up);
+
+       lp_config_set_int(lc->config,"sip","default_proxy",linphone_core_get_default_proxy(lc,NULL));
+       
        for(elem=config->proxies,i=0;elem!=NULL;elem=ms_list_next(elem),i++){
                LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)(elem->data);
                linphone_proxy_config_write_to_config_file(lc->config,cfg,i);
                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
-             }
-         }
+               }
+       }
 
+       ms_list_for_each(config->proxies,(void (*)(void*)) linphone_proxy_config_destroy);
+       ms_list_free(config->proxies);
+       config->proxies=NULL;
+       
        linphone_proxy_config_write_to_config_file(lc->config,NULL,i);  /*mark the end */
 
        for(elem=lc->auth_info,i=0;elem!=NULL;elem=ms_list_next(elem),i++){
@@ -3358,6 +3219,11 @@ 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 */
+       ms_list_for_each(lc->auth_info,(void (*)(void*))linphone_auth_info_destroy);
+       ms_list_free(lc->auth_info);
+       lc->auth_info=NULL;
+       sal_uninit(lc->sal);
+       lc->sal=NULL;
 }
 
 void rtp_config_uninit(LinphoneCore *lc)
@@ -3405,7 +3271,7 @@ void codecs_config_uninit(LinphoneCore *lc)
                sprintf(key,"audio_codec_%i",index);
                lp_config_set_string(lc->config,key,"mime",pt->mime_type);
                lp_config_set_int(lc->config,key,"rate",pt->clock_rate);
-               lp_config_set_int(lc->config,key,"enabled",payload_type_enabled(pt));
+               lp_config_set_int(lc->config,key,"enabled",linphone_core_payload_type_enabled(lc,pt));
                index++;
        }
        index=0;
@@ -3414,14 +3280,10 @@ void codecs_config_uninit(LinphoneCore *lc)
                sprintf(key,"video_codec_%i",index);
                lp_config_set_string(lc->config,key,"mime",pt->mime_type);
                lp_config_set_int(lc->config,key,"rate",pt->clock_rate);
-               lp_config_set_int(lc->config,key,"enabled",payload_type_enabled(pt));
+               lp_config_set_int(lc->config,key,"enabled",linphone_core_payload_type_enabled(lc,pt));
                lp_config_set_string(lc->config,key,"recv_fmtp",pt->recv_fmtp);
                index++;
        }
-       if (lc->local_profile){
-               rtp_profile_destroy(lc->local_profile);
-               lc->local_profile=NULL;
-       }
 }
 
 void ui_config_uninit(LinphoneCore* lc)
@@ -3469,7 +3331,6 @@ static void linphone_core_uninit(LinphoneCore *lc)
        /* save all config */
        net_config_uninit(lc);
        sip_config_uninit(lc);
-       lp_config_set_int(lc->config,"sip","default_proxy",linphone_core_get_default_proxy(lc,NULL));
        rtp_config_uninit(lc);
        sound_config_uninit(lc);
        video_config_uninit(lc);
@@ -3483,7 +3344,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 9ce867053574ac34cb1f6a1158d768e68b1e885d..5f79f693937ae1a2d60ebc54f1fb1965b2aa561c 100644 (file)
@@ -39,109 +39,10 @@ extern "C" {
 
 struct _MSSndCard;
 struct _LinphoneCore;
-
-bool_t payload_type_enabled(struct _PayloadType *pt);
-void payload_type_set_enable(struct _PayloadType *pt,int value);
-const char *payload_type_get_description(struct _PayloadType *pt);
+struct SalOp;
 
 struct _LpConfig;
 
-typedef struct sip_config
-{
-       char *contact;
-       char *guessed_contact;
-       int sip_port;
-       MSList *proxies;
-       MSList *deleted_proxies;
-       int inc_timeout;        /*timeout after an un-answered incoming call is rejected*/
-       bool_t use_info;
-       bool_t use_rfc2833;     /*force RFC2833 to be sent*/
-       bool_t guess_hostname;
-       bool_t loopback_only;
-       bool_t ipv6_enabled;
-       bool_t sdp_200_ack;
-       bool_t only_one_codec; /*in SDP answers*/
-       bool_t register_only_when_network_is_up;
-} sip_config_t;
-
-typedef struct rtp_config
-{
-       int audio_rtp_port;
-       int video_rtp_port;
-       int audio_jitt_comp;  /*jitter compensation*/
-       int video_jitt_comp;  /*jitter compensation*/
-       int nortp_timeout;
-}rtp_config_t;
-
-
-
-typedef struct net_config
-{
-       char *nat_address;
-       char *stun_server;
-       char *relay;
-       int download_bw;
-       int upload_bw;
-       int firewall_policy;
-       int mtu;
-       bool_t nat_sdp_only;
-}net_config_t;
-
-
-typedef struct sound_config
-{
-       struct _MSSndCard * ring_sndcard;       /* the playback sndcard currently used */
-       struct _MSSndCard * play_sndcard;       /* the playback sndcard currently used */
-       struct _MSSndCard * capt_sndcard; /* the capture sndcard currently used */
-       const char **cards;
-       int latency;    /* latency in samples of the current used sound device */
-       char rec_lev;
-       char play_lev;
-       char ring_lev;
-       char source;
-       char *local_ring;
-       char *remote_ring;
-       bool_t ec;
-       bool_t ea;
-       bool_t agc;
-} sound_config_t;
-
-typedef struct codecs_config
-{
-       MSList *audio_codecs;  /* list of audio codecs in order of preference*/
-       MSList *video_codecs;   /* for later use*/
-}codecs_config_t;
-
-typedef struct video_config{
-       struct _MSWebCam *device;
-       const char **cams;
-       MSVideoSize vsize;
-       bool_t capture;
-       bool_t show_local;
-       bool_t display;
-       bool_t selfview; /*during calls*/
-}video_config_t;
-
-typedef struct ui_config
-{
-       int is_daemon;
-       int is_applet;
-       unsigned int timer_id;  /* the timer id for registration */
-}ui_config_t;
-
-
-
-typedef struct autoreplier_config
-{
-       int enabled;
-       int after_seconds;              /* accept the call after x seconds*/
-       int max_users;                  /* maximum number of user that can call simultaneously */
-       int max_rec_time;       /* the max time of incoming voice recorded */
-       int max_rec_msg;                /* maximum number of recorded messages */
-       const char *message;            /* the path of the file to be played */
-}autoreplier_config_t;
-
-struct osip_from;
 
 /**
  * Object that represents a SIP address.
@@ -157,7 +58,7 @@ struct osip_from;
  * @ingroup linphone_address
  * @var LinphoneAddress
  */
-typedef struct osip_from LinphoneAddress;
+typedef struct SalAddress LinphoneAddress;
 
 LinphoneAddress * linphone_address_new(const char *uri);
 LinphoneAddress * linphone_address_clone(const LinphoneAddress *uri);
@@ -176,8 +77,6 @@ char *linphone_address_as_string(const LinphoneAddress *u);
 char *linphone_address_as_string_uri_only(const LinphoneAddress *u);
 void linphone_address_destroy(LinphoneAddress *u);
 
-struct _LinphoneCore;
-struct _sdp_context;
 struct _SipSetupContext;
 struct _LinphoneCall;
 
@@ -240,7 +139,7 @@ typedef enum{
 }LinphoneSubscribePolicy;
 
 typedef enum _LinphoneOnlineStatus{
-       LINPHONE_STATUS_UNKNOWN,
+       LINPHONE_STATUS_OFFLINE,
        LINPHONE_STATUS_ONLINE,
        LINPHONE_STATUS_BUSY,
        LINPHONE_STATUS_BERIGHTBACK,
@@ -250,29 +149,15 @@ typedef enum _LinphoneOnlineStatus{
        LINPHONE_STATUS_NOT_DISTURB,
        LINPHONE_STATUS_MOVED,
        LINPHONE_STATUS_ALT_SERVICE,
-       LINPHONE_STATUS_OFFLINE,
        LINPHONE_STATUS_PENDING,
-       LINPHONE_STATUS_CLOSED,
        LINPHONE_STATUS_END
 }LinphoneOnlineStatus;
 
 const char *linphone_online_status_to_string(LinphoneOnlineStatus ss);
 
-typedef struct _LinphoneFriend{
-       LinphoneAddress *uri;
-       int in_did;
-       int out_did;
-       int sid;
-       int nid;
-       LinphoneSubscribePolicy pol;
-       LinphoneOnlineStatus status;
-       struct _LinphoneProxyConfig *proxy;
-       struct _LinphoneCore *lc;
-       BuddyInfo *info;
-       char *refkey;
-       bool_t subscribe;
-       bool_t inc_subscribe_pending;
-}LinphoneFriend;       
+struct _LinphoneFriend;
+
+typedef struct _LinphoneFriend LinphoneFriend;
 
 LinphoneFriend * linphone_friend_new();
 LinphoneFriend *linphone_friend_new_with_addr(const char *addr);
@@ -280,21 +165,22 @@ int linphone_friend_set_sip_addr(LinphoneFriend *fr, const char *uri);
 int linphone_friend_set_name(LinphoneFriend *fr, const char *name);
 int linphone_friend_send_subscribe(LinphoneFriend *fr, bool_t val);
 int linphone_friend_set_inc_subscribe_policy(LinphoneFriend *fr, LinphoneSubscribePolicy pol);
-int linphone_friend_set_proxy(LinphoneFriend *fr, struct _LinphoneProxyConfig *cfg);
 void linphone_friend_edit(LinphoneFriend *fr);
 void linphone_friend_done(LinphoneFriend *fr);
 void linphone_friend_destroy(LinphoneFriend *lf);
-const LinphoneAddress *linphone_friend_get_uri(const LinphoneFriend *lf);
+const LinphoneAddress *linphone_friend_get_address(const LinphoneFriend *lf);
 bool_t linphone_friend_get_send_subscribe(const LinphoneFriend *lf);
 LinphoneSubscribePolicy linphone_friend_get_inc_subscribe_policy(const LinphoneFriend *lf);
 LinphoneOnlineStatus linphone_friend_get_status(const LinphoneFriend *lf);
 BuddyInfo * linphone_friend_get_info(const LinphoneFriend *lf);
 void linphone_friend_set_ref_key(LinphoneFriend *lf, const char *key);
 const char *linphone_friend_get_ref_key(const LinphoneFriend *lf);
-#define linphone_friend_in_list(lf)    ((lf)->lc!=NULL)
+bool_t linphone_friend_in_list(const LinphoneFriend *lf);
 
 #define linphone_friend_url(lf) ((lf)->url)
 
+struct LinphoneProxyConfig;
+
 /**
  * @addtogroup proxies
  * @{
@@ -315,33 +201,12 @@ const char *linphone_friend_get_ref_key(const LinphoneFriend *lf);
  * The default proxy (see linphone_core_set_default_proxy() ) is the one of the list
  * that is used by default for calls.
 **/
-typedef struct _LinphoneProxyConfig
-{
-       struct _LinphoneCore *lc;
-       char *reg_proxy;
-       char *reg_identity;
-       char *reg_route;
-       char *realm;
-       int expires;
-       int reg_time;
-       int rid;
-       char *type;
-       struct _SipSetupContext *ssctx;
-       int auth_failures;
-       char *contact_addr; /* our IP address as seen by the proxy, read from via 's received= parameter*/
-       int contact_port; /*our IP port as seen by the proxy, read from via's rport= parameter */
-       char *dial_prefix;
-       bool_t commit;
-       bool_t reg_sendregister;
-       bool_t registered;
-       bool_t publish;
-       bool_t dial_escape_plus;
-} LinphoneProxyConfig;
+typedef struct _LinphoneProxyConfig LinphoneProxyConfig;
 
 LinphoneProxyConfig *linphone_proxy_config_new(void);
 int linphone_proxy_config_set_server_addr(LinphoneProxyConfig *obj, const char *server_addr);
-void linphone_proxy_config_set_identity(LinphoneProxyConfig *obj, const char *identity);
-void linphone_proxy_config_set_route(LinphoneProxyConfig *obj, const char *route);
+int linphone_proxy_config_set_identity(LinphoneProxyConfig *obj, const char *identity);
+int linphone_proxy_config_set_route(LinphoneProxyConfig *obj, const char *route);
 void linphone_proxy_config_expires(LinphoneProxyConfig *obj, int expires);
 void linphone_proxy_config_enable_register(LinphoneProxyConfig *obj, bool_t val);
 #define linphone_proxy_config_enableregister linphone_proxy_config_enable_register
@@ -353,18 +218,15 @@ void linphone_proxy_config_set_dial_prefix(LinphoneProxyConfig *cfg, const char
 
 bool_t linphone_proxy_config_is_registered(const LinphoneProxyConfig *obj);
 const char *linphone_proxy_config_get_domain(const LinphoneProxyConfig *cfg);
-/** Returns the proxy configured identity as a const char * */
-#define linphone_proxy_config_get_route(obj)  ((obj)->reg_route)
-/** Returns the proxy configured identity as a const char * */
-#define linphone_proxy_config_get_identity(obj)        ((obj)->reg_identity)
-#define linphone_proxy_config_publish_enabled(obj) ((obj)->publish)
-/** Returns the proxy sip address as const char * */
-#define linphone_proxy_config_get_addr(obj) ((obj)->reg_proxy)
-/** Returns the 'expire' time of the registration */
-#define linphone_proxy_config_get_expires(obj) ((obj)->expires)
-/** Returns TRUE if registration is enabled, FALSE otherwise */
-#define linphone_proxy_config_register_enabled(obj) ((obj)->reg_sendregister)
-#define linphone_proxy_config_get_core(obj) ((obj)->lc)
+
+const char *linphone_proxy_config_get_route(const LinphoneProxyConfig *obj);
+const char *linphone_proxy_config_get_identity(const LinphoneProxyConfig *obj);
+bool_t linphone_proxy_config_publish_enabled(const LinphoneProxyConfig *obj);
+const char *linphone_proxy_config_get_addr(const LinphoneProxyConfig *obj);
+int linphone_proxy_config_get_expires(const LinphoneProxyConfig *obj);
+bool_t linphone_proxy_config_register_enabled(const LinphoneProxyConfig *obj);
+struct _LinphoneCore * linphone_proxy_config_get_core(const LinphoneProxyConfig *obj);
+
 bool_t linphone_proxy_config_get_dial_escape_plus(const LinphoneProxyConfig *cfg);
 const char * linphone_proxy_config_get_dial_prefix(const LinphoneProxyConfig *cfg);
 
@@ -401,6 +263,8 @@ int linphone_account_creator_test_existence(LinphoneAccountCreator *obj);
 LinphoneProxyConfig * linphone_account_creator_validate(LinphoneAccountCreator *obj);
 void linphone_account_creator_destroy(LinphoneAccountCreator *obj);
 
+struct _LinphoneAuthInfo;
+
 /**
  * @ingroup authentication
  * Object holding authentication information.
@@ -425,33 +289,23 @@ void linphone_account_creator_destroy(LinphoneAccountCreator *obj);
  * transactions and retry them with authentication headers.
  *
 **/
-typedef struct _LinphoneAuthInfo
-{
-       char *username;
-       char *realm;
-       char *userid;
-       char *passwd;
-       char *ha1;
-       bool_t works;
-       bool_t first_time;
-}LinphoneAuthInfo;
+typedef struct _LinphoneAuthInfo LinphoneAuthInfo;
 
 LinphoneAuthInfo *linphone_auth_info_new(const char *username, const char *userid,
                const char *passwd, const char *ha1,const char *realm);
 void linphone_auth_info_set_passwd(LinphoneAuthInfo *info, const char *passwd);
 void linphone_auth_info_set_username(LinphoneAuthInfo *info, const char *username);
 void linphone_auth_info_set_userid(LinphoneAuthInfo *info, const char *userid);
+
+const char *linphone_auth_info_get_username(const LinphoneAuthInfo *i);
+const char *linphone_auth_info_get_passwd(const LinphoneAuthInfo *i);
+const char *linphone_auth_info_get_userid(const LinphoneAuthInfo *i);
+
 /* you don't need those function*/
 void linphone_auth_info_destroy(LinphoneAuthInfo *info);
 LinphoneAuthInfo * linphone_auth_info_new_from_config_file(struct _LpConfig *config, int pos);
 
-struct _LinphoneChatRoom{
-       struct _LinphoneCore *lc;
-       char  *peer;
-       char *route;
-       LinphoneAddress *peer_url;
-       void * user_data;
-};
+struct _LinphoneChatRoom;
 typedef struct _LinphoneChatRoom LinphoneChatRoom;
 
 LinphoneChatRoom * linphone_core_create_chat_room(struct _LinphoneCore *lc, const char *to);
@@ -523,7 +377,7 @@ typedef void (*DisplayQuestionCb)(struct _LinphoneCore *lc, const char *message)
 /** Callback prototype */
 typedef void (*LinphoneCoreCbFunc)(struct _LinphoneCore *lc,void * user_data);
 /** Callback prototype */
-typedef void (*NotifyReceivedCb)(struct _LinphoneCore *lc, LinphoneFriend * fid, const char *url, const char *status, const char *img);
+typedef void (*NotifyReceivedCb)(struct _LinphoneCore *lc, LinphoneFriend * fid);
 /** Callback prototype */
 typedef void (*NewUnknownSubscriberCb)(struct _LinphoneCore *lc, LinphoneFriend *lf, const char *url);
 /** Callback prototype */
@@ -555,10 +409,6 @@ typedef struct _LinphoneVTable
        AuthInfoRequested auth_info_requested; /**< Ask the application some authentication information */
        DisplayStatusCb display_status; /**< Callback that notifies various events with human readable text.*/
        DisplayMessageCb display_message;/**< Callback to display a message to the user */
-#ifdef VINCENT_MAURY_RSVP
-       /* the yes/no dialog box */
-       DisplayMessageCb display_yes_no;
-#endif
        DisplayMessageCb display_warning;/** Callback to display a warning to the user */
        DisplayUrlCb display_url;
        DisplayQuestionCb display_question;
@@ -595,71 +445,7 @@ typedef enum _LinphoneWaitingState{
 } LinphoneWaitingState;
 typedef void * (*LinphoneWaitingCallback)(struct _LinphoneCore *lc, void *context, LinphoneWaitingState ws, const char *purpose, float progress);
 
-
-typedef struct _LinphoneCore
-{
-       LinphoneCoreVTable vtable;
-       struct _LpConfig *config;
-       net_config_t net_conf;
-       sip_config_t sip_conf;
-       rtp_config_t rtp_conf;
-       sound_config_t sound_conf;
-       video_config_t video_conf;
-       codecs_config_t codecs_conf;
-       ui_config_t ui_conf;
-       autoreplier_config_t autoreplier_conf;
-       LinphoneProxyConfig *default_proxy;
-       MSList *friends;
-       MSList *auth_info;
-       struct _RingStream *ringstream;
-       LCCallbackObj preview_finished_cb;
-       bool_t preview_finished;
-       struct _LinphoneCall *call;   /* the current call, in the future it will be a list of calls (conferencing)*/
-       int rid; /*registration id*/
-       MSList *queued_calls;   /* used by the autoreplier */
-       MSList *call_logs;
-       MSList *chatrooms;
-       int max_call_logs;
-       int missed_calls;
-       struct _AudioStream *audiostream;  /**/
-       struct _VideoStream *videostream;
-       struct _VideoStream *previewstream;
-       RtpTransport *a_rtp,*a_rtcp;
-       struct _RtpProfile *local_profile;
-       MSList *bl_reqs;
-       MSList *subscribers;    /* unknown subscribers */
-       int minutes_away;
-       LinphoneOnlineStatus presence_mode;
-       LinphoneOnlineStatus prev_mode;
-       char *alt_contact;
-       void *data;
-       ms_mutex_t lock;
-       char *play_file;
-       char *rec_file;
-       time_t prevtime;
-       int dw_audio_bw;
-       int up_audio_bw;
-       int dw_video_bw;
-       int up_video_bw;
-       int audio_bw;
-       int automatic_action;
-       gstate_t gstate_power;
-       gstate_t gstate_reg;
-       gstate_t gstate_call;
-       LinphoneWaitingCallback wait_cb;
-       void *wait_ctx;
-       bool_t use_files;
-       bool_t apply_nat_settings;
-       bool_t ready;
-       bool_t bl_refresh;
-#ifdef VINCENT_MAURY_RSVP
-       /* QoS parameters*/
-       int rsvp_enable;
-       int rpc_enable;
-#endif
-} LinphoneCore;
-
-
+typedef struct _LinphoneCore LinphoneCore;
 
 /* THE main API */
 
@@ -726,6 +512,12 @@ const MSList *linphone_core_get_video_codecs(const LinphoneCore *lc);
 
 int linphone_core_set_video_codecs(LinphoneCore *lc, MSList *codecs);
 
+bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, PayloadType *pt);
+
+int linphone_core_enable_payload_type(LinphoneCore *lc, PayloadType *pt, bool_t enable);
+
+const char *linphone_core_get_payload_type_description(LinphoneCore *lc, PayloadType *pt);
+
 bool_t linphone_core_check_payload_type_usability(LinphoneCore *lc, PayloadType *pt);
 
 int linphone_core_add_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *config);
@@ -849,7 +641,7 @@ void linphone_core_reject_subscriber(LinphoneCore *lc, LinphoneFriend *lf);
 const MSList * linphone_core_get_friend_list(const LinphoneCore *lc);
 /* notify all friends that have subscribed */
 void linphone_core_notify_all_friends(LinphoneCore *lc, LinphoneOnlineStatus os);
-LinphoneFriend *linphone_core_get_friend_by_uri(const LinphoneCore *lc, const char *uri);
+LinphoneFriend *linphone_core_get_friend_by_address(const LinphoneCore *lc, const char *addr);
 LinphoneFriend *linphone_core_get_friend_by_ref_key(const LinphoneCore *lc, const char *key);
 
 /* returns a list of LinphoneCallLog */
@@ -898,8 +690,6 @@ const LinphoneAddress *linphone_core_get_remote_uri(LinphoneCore *lc);
 int linphone_core_get_mtu(const LinphoneCore *lc);
 void linphone_core_set_mtu(LinphoneCore *lc, int mtu);
 
-bool_t linphone_core_is_in_main_thread(LinphoneCore *lc);
-
 void *linphone_core_get_user_data(LinphoneCore *lc);
 
 /* returns LpConfig object to read/write to the config file: usefull if you wish to extend
@@ -925,21 +715,6 @@ void linphone_core_destroy(LinphoneCore *lc);
 /*for advanced users:*/
 void linphone_core_set_audio_transports(LinphoneCore *lc, RtpTransport *rtp, RtpTransport *rtcp);
 
-/* end of lecacy api */
-
-/*internal use only */
-#define linphone_core_lock(lc) ms_mutex_lock(&(lc)->lock)
-#define linphone_core_unlock(lc)       ms_mutex_unlock((&lc)->lock)
-void linphone_core_start_media_streams(LinphoneCore *lc, struct _LinphoneCall *call);
-void linphone_core_stop_media_streams(LinphoneCore *lc);
-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);
-void linphone_core_start_waiting(LinphoneCore *lc, const char *purpose);
-void linphone_core_update_progress(LinphoneCore *lc, const char *purpose, float progresses);
-void linphone_core_stop_waiting(LinphoneCore *lc);
-
-
 #ifdef __cplusplus
 }
 #endif
index db2c9393208bf5a864ed0cfb3a02f39bc5651962..70c75d82abe9debcc85b9dc2ba1369e27982ce78 100644 (file)
@@ -170,21 +170,42 @@ void check_sound_device(LinphoneCore *lc)
 #define RTP_HDR_SZ 12
 #define IP4_HDR_SZ 20   /*20 is the minimum, but there may be some options*/
 
-const char *payload_type_get_description(PayloadType *pt){
-       return _((const char *)pt->user_data);
-}
-
-void payload_type_set_enable(PayloadType *pt,int value)
+static void payload_type_set_enable(PayloadType *pt,int value)
 {
        if ((value)!=0) payload_type_set_flag(pt,PAYLOAD_TYPE_ENABLED); \
        else payload_type_unset_flag(pt,PAYLOAD_TYPE_ENABLED);
 }
 
-
-bool_t payload_type_enabled(PayloadType *pt) {
+static bool_t payload_type_enabled(PayloadType *pt) {
        return (((pt)->flags & PAYLOAD_TYPE_ENABLED)!=0);
 }
 
+bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, PayloadType *pt){
+       if (ms_list_find(lc->codecs_conf.audio_codecs,pt) || ms_list_find(lc->codecs_conf.video_codecs,pt)){
+               return payload_type_enabled(pt);
+       }
+       ms_error("Getting enablement status of codec not in audio or video list of PayloadType !");
+       return FALSE;
+}
+
+int linphone_core_enable_payload_type(LinphoneCore *lc, PayloadType *pt, bool_t enabled){
+       if (ms_list_find(lc->codecs_conf.audio_codecs,pt) || ms_list_find(lc->codecs_conf.video_codecs,pt)){
+               payload_type_set_enable(pt,enabled);
+               return 0;
+       }
+       ms_error("Enabling codec not in audio or video list of PayloadType !");
+       return -1;
+}
+
+const char *linphone_core_get_payload_type_description(LinphoneCore *lc, PayloadType *pt){
+       if (ms_filter_codec_supported(pt->mime_type)){
+               MSFilterDesc *desc=ms_filter_get_encoder(pt->mime_type);
+               return _(desc->text);
+       }
+       return NULL;
+}
+
+
 /*this function makes a special case for speex/8000.
 This codec is variable bitrate. The 8kbit/s mode is interesting when having a low upload bandwidth, but its quality
 is not very good. We 'd better use its 15kbt/s mode when we have enough bandwidth*/
@@ -274,152 +295,6 @@ bool_t linphone_core_check_payload_type_usability(LinphoneCore *lc, PayloadType
        return ret;
 }
 
-static PayloadType * find_payload(RtpProfile *prof, PayloadType *pt /*from config*/){
-       PayloadType *candidate=NULL;
-       int i;
-       PayloadType *it;
-       for(i=0;i<127;++i){
-               it=rtp_profile_get_payload(prof,i);
-               if (it!=NULL && strcasecmp(pt->mime_type,it->mime_type)==0
-                       && (pt->clock_rate==it->clock_rate || pt->clock_rate<=0)
-                       && payload_type_get_user_data(it)==NULL ){
-                       if ( (pt->recv_fmtp && it->recv_fmtp && strcasecmp(pt->recv_fmtp,it->recv_fmtp)==0) ||
-                               (pt->recv_fmtp==NULL && it->recv_fmtp==NULL) ){
-                               /*exact match*/
-                               return it;
-                       }else candidate=it;
-               }
-       }
-       return candidate;
-}
-
-static bool_t check_h264_packmode(PayloadType *payload, MSFilterDesc *desc){
-       if (payload->recv_fmtp==NULL || strstr(payload->recv_fmtp,"packetization-mode")==0){
-               /*this is packetization-mode=0 H264, we only support it with a multislicing
-               enabled version of x264*/
-               if (strstr(desc->text,"x264") && strstr(desc->text,"multislicing")==0){
-                       /*this is x264 without multisclicing*/
-                       ms_message("Disabling packetization-mode=0 H264 codec because "
-                       "of lack of multislicing support");
-                       return FALSE;
-               }
-       }
-       return TRUE;
-}
-
-static MSList *fix_codec_list(RtpProfile *prof, MSList *conflist)
-{
-       MSList *elem;
-       MSList *newlist=NULL;
-       PayloadType *payload,*confpayload;
-
-       for (elem=conflist;elem!=NULL;elem=ms_list_next(elem))
-       {
-               confpayload=(PayloadType*)elem->data;
-               payload=find_payload(prof,confpayload);
-               if (payload!=NULL){
-                       if (ms_filter_codec_supported(confpayload->mime_type)){
-                               MSFilterDesc *desc=ms_filter_get_encoder(confpayload->mime_type);
-                               if (strcasecmp(confpayload->mime_type,"H264")==0){
-                                       if (!check_h264_packmode(confpayload,desc)){
-                                               continue;
-                                       }
-                               }
-                               payload_type_set_user_data(payload,(void*)desc->text);
-                               payload_type_set_enable(payload,payload_type_enabled(confpayload));
-                               newlist=ms_list_append(newlist,payload);
-                       }
-               }
-               else{
-                       ms_warning("Cannot support %s/%i: does not exist.",confpayload->mime_type,
-                                                               confpayload->clock_rate);
-               }
-       }
-       return newlist;
-}
-
-
-void linphone_core_setup_local_rtp_profile(LinphoneCore *lc)
-{
-       int i;
-       MSList *audiopt,*videopt;
-       PayloadType *payload;
-       bool_t prepend;
-       lc->local_profile=rtp_profile_clone_full(&av_profile);
-       /* first look at the list given by configuration file to see if
-       it is correct */
-       audiopt=fix_codec_list(lc->local_profile,lc->codecs_conf.audio_codecs);
-       videopt=fix_codec_list(lc->local_profile,lc->codecs_conf.video_codecs);
-       /* now find and add payloads that are not listed in the configuration
-       codec list */
-       for (i=0;i<127;i++)
-       {
-               payload=rtp_profile_get_payload(lc->local_profile,i);
-               if (payload!=NULL){
-                       if (payload_type_get_user_data(payload)!=NULL) continue;
-                       /* find a mediastreamer codec for this payload type */
-                       if (ms_filter_codec_supported(payload->mime_type)){
-                               MSFilterDesc *desc=ms_filter_get_encoder(payload->mime_type);
-                               ms_message("Adding new codec %s/%i",payload->mime_type,payload->clock_rate);
-                               payload_type_set_enable(payload,1);
-                               payload_type_set_user_data(payload,(void *)desc->text);
-                               prepend=FALSE;
-                               /* by default, put speex, mpeg4, or h264 on top of list*/
-                               if (strcmp(payload->mime_type,"speex")==0)
-                                       prepend=TRUE;
-                               else if (strcmp(payload->mime_type,"MP4V-ES")==0)
-                                       prepend=TRUE;
-                               else if (strcasecmp(payload->mime_type,"H264")==0){
-                                       if (check_h264_packmode(payload,desc))
-                                               prepend=TRUE;
-                                       else continue;
-                               }
-                               switch (payload->type){
-                                       case PAYLOAD_AUDIO_CONTINUOUS:
-                                       case PAYLOAD_AUDIO_PACKETIZED:
-                                                       if (prepend)
-                                                               audiopt=ms_list_prepend(audiopt,(void *)payload);
-                                                       else
-                                                               audiopt=ms_list_append(audiopt,(void *)payload);
-                                               break;
-                                       case PAYLOAD_VIDEO:
-                                                       if (prepend)
-                                                               videopt=ms_list_prepend(videopt,(void *)payload);
-                                                       else
-                                                               videopt=ms_list_append(videopt,(void *)payload);
-                                               break;
-                                       default:
-                                               ms_error("Unsupported rtp media type.");
-                               }
-                       }
-               }
-       }
-       ms_list_for_each(lc->codecs_conf.audio_codecs,(void (*)(void*))payload_type_destroy);
-       ms_list_for_each(lc->codecs_conf.video_codecs,(void (*)(void *))payload_type_destroy);
-       ms_list_free(lc->codecs_conf.audio_codecs);
-       ms_list_free(lc->codecs_conf.video_codecs);
-       /* set the fixed lists instead:*/
-       lc->codecs_conf.audio_codecs=audiopt;
-       lc->codecs_conf.video_codecs=videopt;
-       linphone_core_update_allocated_audio_bandwidth(lc);
-}
-
-int from_2char_without_params(osip_from_t *from,char **str)
-{
-       osip_from_t *tmpfrom=NULL;
-       osip_from_clone(from,&tmpfrom);
-       if (tmpfrom!=NULL){
-               while(!osip_list_eol(&tmpfrom->gen_params,0)){
-                       osip_generic_param_t *param=(osip_generic_param_t*)osip_list_get(&tmpfrom->gen_params,0);
-                       osip_generic_param_free(param);
-                       osip_list_remove(&tmpfrom->gen_params,0);
-               }
-       }else return -1;
-       osip_from_to_str(tmpfrom,str);
-       osip_from_free(tmpfrom);
-       return 0;
-}
-
 bool_t lp_spawn_command_line_sync(const char *command, char **result,int *command_ret){
 #if !defined(_WIN32_WCE)
        FILE *f=popen(command,"r");
@@ -598,6 +473,11 @@ void linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){
                bool_t got_audio,got_video;
                bool_t cone_audio=FALSE,cone_video=FALSE;
                struct timeval init,cur;
+               SalEndpointCandidate *ac,*vc;
+               
+               ac=&call->localdesc->streams[0].candidates[0];
+               vc=&call->localdesc->streams[1].candidates[0];
+               
                if (parse_stun_server_addr(server,&ss,&ss_len)<0){
                        ms_error("Fail to parser stun server address: %s",server);
                        return;
@@ -630,20 +510,20 @@ void linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){
                        usleep(10000);
 #endif
 
-                       if (recvStunResponse(sock1,call->audio_params.natd_addr,
-                                               &call->audio_params.natd_port,&id)>0){
+                       if (recvStunResponse(sock1,ac->addr,
+                                               &ac->port,&id)>0){
                                ms_message("STUN test result: local audio port maps to %s:%i",
-                                               call->audio_params.natd_addr,
-                                               call->audio_params.natd_port);
+                                               ac->addr,
+                                               ac->port);
                                if (id==11)
                                        cone_audio=TRUE;
                                got_audio=TRUE;
                        }
-                       if (recvStunResponse(sock2,call->video_params.natd_addr,
-                                                       &call->video_params.natd_port,&id)>0){
+                       if (recvStunResponse(sock2,vc->addr,
+                                                       &vc->port,&id)>0){
                                ms_message("STUN test result: local video port maps to %s:%i",
-                                       call->video_params.natd_addr,
-                                       call->video_params.natd_port);
+                                       vc->addr,
+                                       vc->port);
                                if (id==22)
                                        cone_video=TRUE;
                                got_video=TRUE;
@@ -657,7 +537,8 @@ void linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){
                }else{
                        if (!cone_audio) {
                                ms_warning("NAT is symmetric for audio port");
-                               call->audio_params.natd_port=0;
+                               ac->addr[0]='\0';
+                               ac->port=0;
                        }
                }
                if (sock2>=0){
@@ -666,7 +547,8 @@ void linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){
                        }else{
                                if (!cone_video) {
                                        ms_warning("NAT is symmetric for video port.");
-                                       call->video_params.natd_port=0;
+                                       vc->addr[0]='\0';
+                                       vc->port=0;
                                }
                        }
                }
diff --git a/coreapi/offeranswer.c b/coreapi/offeranswer.c
new file mode 100644 (file)
index 0000000..2abf717
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+linphone
+Copyright (C) 2010  Simon MORLAT (simon.morlat@free.fr)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+#include "sal.h"
+#include "offeranswer.h"
+
+
+static PayloadType * find_payload_type_best_match(const MSList *l, const PayloadType *refpt){
+       PayloadType *pt;
+       char value[10];
+       const MSList *elem;
+       PayloadType *candidate=NULL;
+
+       for (elem=l;elem!=NULL;elem=elem->next){
+               pt=(PayloadType*)elem->data;
+               if (strcasecmp(pt->mime_type,refpt->mime_type)==0 && pt->clock_rate==refpt->clock_rate){
+                       candidate=pt;
+                       /*good candidate, check fmtp for H264 */
+                       if (strcasecmp(pt->mime_type,"H264")==0){
+                               if (pt->recv_fmtp!=NULL && refpt->recv_fmtp!=NULL){
+                                       int mode1=0,mode2=0;
+                                       if (fmtp_get_value(pt->recv_fmtp,"packetization-mode",value,sizeof(value))){
+                                               mode1=atoi(value);
+                                       }
+                                       if (fmtp_get_value(refpt->recv_fmtp,"packetization-mode",value,sizeof(value))){
+                                               mode2=atoi(value);
+                                       }
+                                       if (mode1==mode2)
+                                           break; /*exact match */
+                               }
+                       }else break;
+               }
+       }
+       return candidate;
+}
+
+static MSList *match_payloads(const MSList *local, const MSList *remote){
+       const MSList *e2;
+       MSList *res=NULL;
+       PayloadType *matched;
+       for(e2=remote;e2!=NULL;e2=e2->next){
+               PayloadType *p2=(PayloadType*)e2->data;
+               matched=find_payload_type_best_match(local,p2);
+               if (matched){
+                       matched=payload_type_clone(matched);
+                       if (p2->recv_fmtp)
+                               payload_type_set_send_fmtp(matched,p2->recv_fmtp);
+                       res=ms_list_append(res,matched);
+                       payload_type_set_number(matched,payload_type_get_number(p2));
+               }else{
+                       ms_message("No match for %s/%i",p2->mime_type,p2->clock_rate);
+               }
+       }
+       return res;
+}
+
+static bool_t only_telephone_event(const MSList *l){
+       PayloadType *p=(PayloadType*)l->data;
+       if (strcasecmp(p->mime_type,"telephone-event")!=0){
+               return FALSE;
+       }
+       return TRUE;
+}
+
+static void initiate_outgoing(const SalStreamDescription *local_offer,
+                                       const SalStreamDescription *remote_answer,
+                                       SalStreamDescription *result){
+       if (remote_answer->port!=0)
+               result->payloads=match_payloads(local_offer->payloads,remote_answer->payloads);
+       result->proto=local_offer->proto;
+       result->type=local_offer->type;
+       if (result->payloads && !only_telephone_event(result->payloads)){
+               strcpy(result->addr,remote_answer->addr);
+               result->port=remote_answer->port;
+               result->bandwidth=remote_answer->bandwidth;
+               result->ptime=remote_answer->ptime;
+       }else{
+               result->port=0;
+       }
+}
+
+
+static void initiate_incoming(const SalStreamDescription *local_cap,
+                                       const SalStreamDescription *remote_offer,
+                                       SalStreamDescription *result){
+       result->payloads=match_payloads(local_cap->payloads,remote_offer->payloads);
+       result->proto=local_cap->proto;
+       result->type=local_cap->type;
+       if (result->payloads && !only_telephone_event(result->payloads)){
+               strcpy(result->addr,local_cap->addr);
+               result->port=local_cap->port;
+               result->bandwidth=local_cap->bandwidth;
+               result->ptime=local_cap->ptime;         
+       }else{
+               result->port=0;
+       }
+}
+
+/**
+ * Returns a media description to run the streams with, based on a local offer
+ * and the returned response (remote).
+**/
+int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer,
+                                                                       const SalMediaDescription *remote_answer,
+                                                       SalMediaDescription *result){
+    int i,j;
+       const SalStreamDescription *ls,*rs;
+    for(i=0,j=0;i<local_offer->nstreams;++i){
+               ms_message("Processing for stream %i",i);
+               ls=&local_offer->streams[i];
+               rs=sal_media_description_find_stream(remote_answer,ls->proto,ls->type);
+       if (rs) {
+                       initiate_outgoing(ls,rs,&result->streams[j]);
+                       ++j;
+               }
+               else ms_warning("No matching stream for %i",i);
+    }
+       result->nstreams=j;
+       strcpy(result->addr,remote_answer->addr);
+       return 0;
+}
+
+/**
+ * Returns a media description to run the streams with, based on the local capabilities and
+ * and the received offer.
+ * The returned media description is an answer and should be sent to the offerer.
+**/
+int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities,
+                                               const SalMediaDescription *remote_offer,
+                                       SalMediaDescription *result){
+    int i,j;
+       const SalStreamDescription *ls,*rs;
+                                                       
+    for(i=0,j=0;i<remote_offer->nstreams;++i){
+               rs=&remote_offer->streams[i];
+               ms_message("Processing for stream %i",i);
+               ls=sal_media_description_find_stream(local_capabilities,rs->proto,rs->type);
+               if (ls){
+               initiate_incoming(ls,rs,&result->streams[j]);
+                       ++j;
+               }
+    }
+       result->nstreams=j;
+       strcpy(result->username, local_capabilities->username);
+       strcpy(result->addr,local_capabilities->addr);
+       return 0;
+}
+                                       
diff --git a/coreapi/offeranswer.h b/coreapi/offeranswer.h
new file mode 100644 (file)
index 0000000..079f41c
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+linphone
+Copyright (C) 2010  Simon MORLAT (simon.morlat@free.fr)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+#ifndef offeranswer_h
+#define offeranswer_h
+
+/** 
+ This header files defines the SDP offer answer API.
+ It can be used by implementations of SAL directly.
+**/
+
+
+/**
+ * Returns a media description to run the streams with, based on a local offer
+ * and the returned response (remote).
+**/
+int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer,
+                                                                       const SalMediaDescription *remote_answer,
+                                                       SalMediaDescription *result);
+
+/**
+ * Returns a media description to run the streams with, based on the local capabilities and
+ * and the received offer.
+ * The returned media description is an answer and should be sent to the offerer.
+**/
+int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities,
+                                               const SalMediaDescription *remote_offer,
+                                       SalMediaDescription *result);
+                                       
+#endif
+
index fc8f46b74a7fe01c4102ba44b5a1f8f667501be3..0ff498ff7a830d7a2f28fab754a80d0e8fb86039 100644 (file)
@@ -18,26 +18,23 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
 
 #include "linphonecore.h"
-#include <eXosip2/eXosip.h>
-#include <osipparser2/osip_message.h>
 #include "private.h"
 
 
 extern const char *__policy_enum_to_str(LinphoneSubscribePolicy pol);
 
 
-void linphone_core_add_subscriber(LinphoneCore *lc, const char *subscriber, int did, int nid){
+void linphone_core_add_subscriber(LinphoneCore *lc, const char *subscriber, SalOp *op){
        LinphoneFriend *fl=linphone_friend_new_with_addr(subscriber);
        if (fl==NULL) return ;
-       fl->in_did=did;
-       linphone_friend_set_nid(fl,nid);
+       fl->insub=op;
        linphone_friend_set_inc_subscribe_policy(fl,LinphoneSPAccept);
        fl->inc_subscribe_pending=TRUE;
        lc->subscribers=ms_list_append(lc->subscribers,(void *)fl);
        if (lc->vtable.new_unknown_subscriber!=NULL) {
-               char *subscriber=linphone_address_as_string(fl->uri);
-               lc->vtable.new_unknown_subscriber(lc,fl,subscriber);
-               ms_free(subscriber);
+               char *tmp=linphone_address_as_string(fl->uri);
+               lc->vtable.new_unknown_subscriber(lc,fl,tmp);
+               ms_free(tmp);
        }
 }
 
@@ -45,167 +42,111 @@ void linphone_core_reject_subscriber(LinphoneCore *lc, LinphoneFriend *lf){
        linphone_friend_set_inc_subscribe_policy(lf,LinphoneSPDeny);
 }
 
-static void __do_notify(void * data, void * user_data){
-       int *tab=(int*)user_data;
-       LinphoneFriend *lf=(LinphoneFriend*)data;
-       linphone_friend_notify(lf,tab[0],tab[1]);
-}
-
-void __linphone_core_notify_all_friends(LinphoneCore *lc, int ss, int os){
-       int tab[2];
-       tab[0]=ss;
-       tab[1]=os;
-       ms_list_for_each2(lc->friends,__do_notify,(void *)tab);
-}
-
 void linphone_core_notify_all_friends(LinphoneCore *lc, LinphoneOnlineStatus os){
+       MSList *elem;
        ms_message("Notifying all friends that we are in status %i",os);
-       __linphone_core_notify_all_friends(lc,EXOSIP_SUBCRSTATE_ACTIVE,os);
-}
-
-/* check presence state before answering to call; returns TRUE if we can proceed, else answer the appropriate answer
-to close the dialog*/
-bool_t linphone_core_check_presence(LinphoneCore *lc){
-       return TRUE;
+       for(elem=lc->friends;elem!=NULL;elem=elem->next){
+               LinphoneFriend *lf=(LinphoneFriend *)elem->data;
+               if (lf->insub){
+                       linphone_friend_notify(lf,os);
+               }
+       }
 }
 
-void linphone_subscription_new(LinphoneCore *lc, eXosip_event_t *ev){
+void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from){
        LinphoneFriend *lf=NULL;
-       osip_from_t *from=ev->request->from;
        char *tmp;
-       osip_message_t *msg=NULL;
        LinphoneAddress *uri;
-       osip_from_to_str(ev->request->from,&tmp);
-       uri=linphone_address_new(tmp);
-       ms_message("Receiving new subscription from %s.",tmp);
+       
+       uri=linphone_address_new(from);
+       linphone_address_clean(uri);
+       tmp=linphone_address_as_string(uri);
+       ms_message("Receiving new subscription from %s.",from);
        /* check if we answer to this subscription */
        if (linphone_find_friend(lc->friends,uri,&lf)!=NULL){
-               lf->in_did=ev->did;
-               linphone_friend_set_nid(lf,ev->nid);
-               eXosip_insubscription_build_answer(ev->tid,202,&msg);
-               eXosip_insubscription_send_answer(ev->tid,202,msg);
-               __eXosip_wakeup_event();
+               lf->insub=op;
+               lf->inc_subscribe_pending=TRUE;
+               sal_subscribe_accept(op);
                linphone_friend_done(lf);       /*this will do all necessary actions */
        }else{
                /* check if this subscriber is in our black list */
                if (linphone_find_friend(lc->subscribers,uri,&lf)){
                        if (lf->pol==LinphoneSPDeny){
                                ms_message("Rejecting %s because we already rejected it once.",from);
-                               eXosip_insubscription_send_answer(ev->tid,401,NULL);
+                               sal_subscribe_decline(op);
                        }
                        else {
                                /* else it is in wait for approval state, because otherwise it is in the friend list.*/
                                ms_message("New subscriber found in friend list, in %s state.",__policy_enum_to_str(lf->pol));
                        }
                }else {
-                       eXosip_insubscription_build_answer(ev->tid,202,&msg);
-                       eXosip_insubscription_send_answer(ev->tid,202,msg);
-                       linphone_core_add_subscriber(lc,tmp,ev->did,ev->nid);
+                       sal_subscribe_accept(op);
+                       linphone_core_add_subscriber(lc,tmp,op);
                }
        }
-       osip_free(tmp);
+       ms_free(tmp);
 }
 
-void linphone_notify_recv(LinphoneCore *lc, eXosip_event_t *ev)
-{
-       const char *status=_("Gone");
-       const char *img="sip-closed.png";
+void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeState ss, SalPresenceStatus sal_status){
        char *tmp;
        LinphoneFriend *lf;
        LinphoneAddress *friend=NULL;
-       osip_from_t *from=NULL;
-       osip_body_t *body=NULL;
-       LinphoneOnlineStatus estatus=LINPHONE_STATUS_UNKNOWN;
-       ms_message("Receiving notify with sid=%i,nid=%i",ev->sid,ev->nid);
-       if (ev->request!=NULL){
-               from=ev->request->from;
-               osip_message_get_body(ev->request,0,&body);
-               if (body==NULL){
-                       ms_error("No body in NOTIFY");
-                       return;
-               }
-               if (strstr(body->body,"pending")!=NULL){
-                       status=_("Waiting for Approval");
-                       img="sip-wfa.png";
-                       estatus=LINPHONE_STATUS_PENDING;
-               }else if ((strstr(body->body,"online")!=NULL) || (strstr(body->body,"open")!=NULL)) {
-                       status=_("Online");
-                       img="sip-online.png";
+       LinphoneOnlineStatus estatus=LINPHONE_STATUS_OFFLINE;
+       
+       switch(sal_status){
+               case SalPresenceOffline:
+                       estatus=LINPHONE_STATUS_OFFLINE;
+               break;
+               case SalPresenceOnline:
                        estatus=LINPHONE_STATUS_ONLINE;
-               }else if (strstr(body->body,"busy")!=NULL){
-                       status=_("Busy");
-                       img="sip-busy.png";
+               break;
+               case SalPresenceBusy:
                        estatus=LINPHONE_STATUS_BUSY;
-               }else if (strstr(body->body,"berightback")!=NULL
-                               || strstr(body->body,"in-transit")!=NULL ){
-                       status=_("Be Right Back");
-                       img="sip-bifm.png";
-                       estatus=LINPHONE_STATUS_BERIGHTBACK;
-               }else if (strstr(body->body,"away")!=NULL){
-                       status=_("Away");
-                       img="sip-away.png";
+               break;
+               case SalPresenceBerightback:
+                       estatus=LINPHONE_STATUS_AWAY;
+               break;
+               case SalPresenceAway:
                        estatus=LINPHONE_STATUS_AWAY;
-               }else if (strstr(body->body,"onthephone")!=NULL
-                       || strstr(body->body,"on-the-phone")!=NULL){
-                       status=_("On The Phone");
-                       img="sip-otp.png";
+               break;
+               case SalPresenceOnthephone:
                        estatus=LINPHONE_STATUS_ONTHEPHONE;
-               }else if (strstr(body->body,"outtolunch")!=NULL
-                               || strstr(body->body,"meal")!=NULL){
-                       status=_("Out To Lunch");
-                       img="sip-otl.png";
+               break;
+               case SalPresenceOuttolunch:
                        estatus=LINPHONE_STATUS_OUTTOLUNCH;
-               }else if (strstr(body->body,"closed")!=NULL){
-                       status=_("Closed");
-                       img="sip-away.png";
-                       estatus=LINPHONE_STATUS_CLOSED;
-               }else{
-                       status=_("Gone");
-                       img="sip-closed.png";
-                       estatus=LINPHONE_STATUS_OFFLINE;
-               }
-               ms_message("We are notified that sip:%s@%s has online status %s",from->url->username,from->url->host,status);
+               break;
+               case SalPresenceDonotdisturb:
+                       estatus=LINPHONE_STATUS_BUSY;
+               break;
+               case SalPresenceMoved:
+               case SalPresenceAltService:
+                       estatus=LINPHONE_STATUS_AWAY;
+               break;
        }
-       lf=linphone_find_friend_by_sid(lc->friends,ev->sid);
+       lf=linphone_find_friend_by_out_subscribe(lc->friends,op);
        if (lf!=NULL){
                friend=lf->uri;
                tmp=linphone_address_as_string(friend);
                lf->status=estatus;
-               lc->vtable.notify_recv(lc,(LinphoneFriend*)lf,tmp,status,img);
+               lc->vtable.notify_recv(lc,(LinphoneFriend*)lf);
                ms_free(tmp);
-               if (ev->ss_status==EXOSIP_SUBCRSTATE_TERMINATED) {
-                       lf->sid=-1;
-                       lf->out_did=-1;
-                       ms_message("Outgoing subscription terminated by remote.");
-               }
        }else{
                ms_message("But this person is not part of our friend list, so we don't care.");
        }
-}
-
-void linphone_subscription_answered(LinphoneCore *lc, eXosip_event_t *ev){
-       LinphoneFriend *lf;
-       osip_from_t *from=ev->response->to;
-       char *tmp;
-       osip_from_to_str(from,&tmp);
-       LinphoneAddress *uri=linphone_address_new(tmp);
-       linphone_find_friend(lc->friends,uri,&lf);
-       if (lf!=NULL){
-               lf->out_did=ev->did;
-               linphone_friend_set_sid(lf,ev->sid);
-       }else{
-               ms_warning("Receiving answer for unknown subscribe sip:%s@%s", from->url->username,from->url->host);
+       if (ss==SalSubscribeTerminated){
+               sal_op_release(op);
+               if (lf)
+                       lf->outsub=NULL;
        }
-       ms_free(tmp);
 }
-void linphone_subscription_closed(LinphoneCore *lc,eXosip_event_t *ev){
+
+void linphone_subscription_closed(LinphoneCore *lc, SalOp *op){
        LinphoneFriend *lf;
-       osip_from_t *from=ev->request->from;
-       lf=linphone_find_friend_by_nid(lc->friends,ev->nid);
+       lf=linphone_find_friend_by_inc_subscribe(lc->friends,op);
+       sal_op_release(op);
        if (lf!=NULL){
-               lf->in_did=-1;
-               linphone_friend_set_nid(lf,-1);
+               lf->insub=NULL;
        }else{
-               ms_warning("Receiving unsuscribe for unknown in-subscribtion from sip:%s@%s", from->url->username, from->url->host);
+               ms_warning("Receiving unsuscribe for unknown in-subscribtion from %s", sal_op_get_from(op));
        }
 }
index 93b1c77be124f3152749e45728c73d0b56e8c23d..bcd9144399a68b5219196b0c177bb51f9400fc65 100644 (file)
@@ -26,7 +26,7 @@
 #define _PRIVATE_H
 
 #include "linphonecore.h"
-#include <eXosip2/eXosip.h>
+#include "sal.h"
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 #endif
 
-       
-typedef struct _StreamParams
-{
-       int initialized;
-       int line;
-       int localport;
-       int remoteport;
-       int remotertcpport;
-       int pt;
-       char *relay_session_id;
-       int natd_port;
-       char remoteaddr[LINPHONE_HOSTNAME_SIZE];
-       char natd_addr[LINPHONE_HOSTNAME_SIZE];
-} StreamParams;
-
 typedef enum _LCState{
        LCStateInit,
        LCStateRinging,
@@ -79,25 +64,22 @@ typedef enum _LCState{
 typedef struct _LinphoneCall
 {
        struct _LinphoneCore *core;
-       StreamParams audio_params;
-       StreamParams video_params;
+       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;
-       int cid; /*call id */
-       int did; /*dialog id */
-       int tid; /*last transaction id*/
+       SalOp *op;
        char localip[LINPHONE_IPADDR_SIZE]; /* our best guess for local ipaddress for this call */
-       struct _sdp_context *sdpctx;
        time_t start_time; /*time at which the call was initiated*/
        time_t media_start_time; /*time at which it was accepted, media streams established*/
        LCState state;
-       bool_t auth_pending;
-       bool_t supports_session_timers;
+       bool_t media_pending;
 } LinphoneCall;
 
 LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to);
-LinphoneCall * linphone_call_new_incoming(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, eXosip_event_t *ev);
+LinphoneCall * linphone_call_new_incoming(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op);
 #define linphone_call_set_state(lcall,st)      (lcall)->state=(st)
 void linphone_call_destroy(struct _LinphoneCall *obj);
 
@@ -107,7 +89,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);
 
@@ -118,26 +100,25 @@ int linphone_proxy_config_send_publish(LinphoneProxyConfig *cfg, LinphoneOnlineS
 
 int linphone_online_status_to_eXosip(LinphoneOnlineStatus os);
 
-void linphone_friend_set_sid(LinphoneFriend *lf, int sid);
-void linphone_friend_set_nid(LinphoneFriend *lf, int nid);
-void linphone_friend_notify(LinphoneFriend *lf, int ss, LinphoneOnlineStatus os);
+void linphone_friend_notify(LinphoneFriend *lf, LinphoneOnlineStatus os);
+LinphoneFriend *linphone_find_friend_by_inc_subscribe(MSList *l, SalOp *op);
+LinphoneFriend *linphone_find_friend_by_out_subscribe(MSList *l, SalOp *op);
+
 
 int set_lock_file();
 int get_lock_file();
 int remove_lock_file();
 int do_registration(LinphoneCore *lc, bool_t doit);
 void check_for_registration(LinphoneCore *lc);
-char *int2str(int number);
-int from_2char_without_params(osip_from_t *from,char **str);
 void check_sound_device(LinphoneCore *lc);
-void linphone_core_setup_local_rtp_profile(LinphoneCore *lc);
+void linphone_core_verify_codecs(LinphoneCore *lc);
 void linphone_core_get_local_ip(LinphoneCore *lc, const char *to, char *result);
 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);
 }
 
@@ -157,24 +138,18 @@ static inline void set_string(char **dest, const char *src){
 }
 
 #define PAYLOAD_TYPE_ENABLED   PAYLOAD_TYPE_USER_FLAG_0
-bool_t linphone_proxy_config_register_again_with_updated_contact(LinphoneProxyConfig *obj, osip_message_t *orig_request, osip_message_t *last_answer);
-void linphone_process_authentication(LinphoneCore* lc, eXosip_event_t *ev);
-void linphone_authentication_ok(LinphoneCore *lc, eXosip_event_t *ev);
-void linphone_subscription_new(LinphoneCore *lc, eXosip_event_t *ev);
-void linphone_notify_recv(LinphoneCore *lc,eXosip_event_t *ev);
-LinphoneProxyConfig *linphone_core_get_proxy_config_from_rid(LinphoneCore *lc, int rid);
-void linphone_proxy_config_process_authentication_failure(LinphoneCore *lc, int code, eXosip_event_t *ev);
-
-void linphone_subscription_answered(LinphoneCore *lc, eXosip_event_t *ev);
-void linphone_subscription_closed(LinphoneCore *lc, eXosip_event_t *ev);
 
-void linphone_call_init_media_params(LinphoneCall *call);
+SalPresenceStatus linphone_online_status_to_sal(LinphoneOnlineStatus os);
+void linphone_process_authentication(LinphoneCore* lc, SalOp *op);
+void linphone_authentication_ok(LinphoneCore *lc, SalOp *op);
+void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from);
+void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeState ss, SalPresenceStatus status);
+void linphone_proxy_config_process_authentication_failure(LinphoneCore *lc, SalOp *op);
 
-void linphone_set_sdp(osip_message_t *sip, const char *sdp);
+void linphone_subscription_answered(LinphoneCore *lc, SalOp *op);
+void linphone_subscription_closed(LinphoneCore *lc, SalOp *op);
 
 MSList *linphone_find_friend(MSList *fl, const LinphoneAddress *fri, LinphoneFriend **lf);
-LinphoneFriend *linphone_find_friend_by_nid(MSList *l, int nid);
-LinphoneFriend *linphone_find_friend_by_sid(MSList *l, int sid);
 
 void linphone_core_update_allocated_audio_bandwidth(LinphoneCore *lc);
 void linphone_core_update_allocated_audio_bandwidth_in_call(LinphoneCore *lc, const PayloadType *pt);
@@ -194,4 +169,223 @@ void linphone_proxy_config_write_to_config_file(struct _LpConfig* config,Linphon
 
 int linphone_proxy_config_normalize_number(LinphoneProxyConfig *cfg, const char *username, char *result, size_t result_len);
 
+void linphone_core_text_received(LinphoneCore *lc, const char *from, const char *msg);
+
+void linphone_core_start_media_streams(LinphoneCore *lc, struct _LinphoneCall *call);
+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);
+void linphone_core_start_waiting(LinphoneCore *lc, const char *purpose);
+void linphone_core_update_progress(LinphoneCore *lc, const char *purpose, float progresses);
+void linphone_core_stop_waiting(LinphoneCore *lc);
+
+
+extern SalCallbacks linphone_sal_callbacks;
+
+
+struct _LinphoneProxyConfig
+{
+       struct _LinphoneCore *lc;
+       char *reg_proxy;
+       char *reg_identity;
+       char *reg_route;
+       char *realm;
+       int expires;
+       int reg_time;
+       SalOp *op;
+       char *type;
+       struct _SipSetupContext *ssctx;
+       int auth_failures;
+       char *dial_prefix;
+       bool_t commit;
+       bool_t reg_sendregister;
+       bool_t registered;
+       bool_t publish;
+       bool_t dial_escape_plus;
+};
+
+struct _LinphoneAuthInfo 
+{
+       char *username;
+       char *realm;
+       char *userid;
+       char *passwd;
+       char *ha1;
+       int usecount;
+       bool_t works;
+};
+
+struct _LinphoneChatRoom{
+       struct _LinphoneCore *lc;
+       char  *peer;
+       char *route;
+       LinphoneAddress *peer_url;
+       void * user_data;
+};
+
+struct _LinphoneFriend{
+       LinphoneAddress *uri;
+       SalOp *insub;
+       SalOp *outsub;
+       LinphoneSubscribePolicy pol;
+       LinphoneOnlineStatus status;
+       struct _LinphoneCore *lc;
+       BuddyInfo *info;
+       char *refkey;
+       bool_t subscribe;
+       bool_t inc_subscribe_pending;
+};     
+
+typedef struct sip_config
+{
+       char *contact;
+       char *guessed_contact;
+       int sip_port;
+       MSList *proxies;
+       MSList *deleted_proxies;
+       int inc_timeout;        /*timeout after an un-answered incoming call is rejected*/
+       bool_t use_info;
+       bool_t use_rfc2833;     /*force RFC2833 to be sent*/
+       bool_t guess_hostname;
+       bool_t loopback_only;
+       bool_t ipv6_enabled;
+       bool_t sdp_200_ack;
+       bool_t only_one_codec; /*in SDP answers*/
+       bool_t register_only_when_network_is_up;
+} sip_config_t;
+
+typedef struct rtp_config
+{
+       int audio_rtp_port;
+       int video_rtp_port;
+       int audio_jitt_comp;  /*jitter compensation*/
+       int video_jitt_comp;  /*jitter compensation*/
+       int nortp_timeout;
+}rtp_config_t;
+
+
+
+typedef struct net_config
+{
+       char *nat_address;
+       char *stun_server;
+       char *relay;
+       int download_bw;
+       int upload_bw;
+       int firewall_policy;
+       int mtu;
+       bool_t nat_sdp_only;
+}net_config_t;
+
+
+typedef struct sound_config
+{
+       struct _MSSndCard * ring_sndcard;       /* the playback sndcard currently used */
+       struct _MSSndCard * play_sndcard;       /* the playback sndcard currently used */
+       struct _MSSndCard * capt_sndcard; /* the capture sndcard currently used */
+       const char **cards;
+       int latency;    /* latency in samples of the current used sound device */
+       char rec_lev;
+       char play_lev;
+       char ring_lev;
+       char source;
+       char *local_ring;
+       char *remote_ring;
+       bool_t ec;
+       bool_t ea;
+       bool_t agc;
+} sound_config_t;
+
+typedef struct codecs_config
+{
+       MSList *audio_codecs;  /* list of audio codecs in order of preference*/
+       MSList *video_codecs;   /* for later use*/
+}codecs_config_t;
+
+typedef struct video_config{
+       struct _MSWebCam *device;
+       const char **cams;
+       MSVideoSize vsize;
+       bool_t capture;
+       bool_t show_local;
+       bool_t display;
+       bool_t selfview; /*during calls*/
+}video_config_t;
+
+typedef struct ui_config
+{
+       int is_daemon;
+       int is_applet;
+       unsigned int timer_id;  /* the timer id for registration */
+}ui_config_t;
+
+
+
+typedef struct autoreplier_config
+{
+       int enabled;
+       int after_seconds;              /* accept the call after x seconds*/
+       int max_users;                  /* maximum number of user that can call simultaneously */
+       int max_rec_time;       /* the max time of incoming voice recorded */
+       int max_rec_msg;                /* maximum number of recorded messages */
+       const char *message;            /* the path of the file to be played */
+}autoreplier_config_t;
+
+
+struct _LinphoneCore
+{
+       LinphoneCoreVTable vtable;
+       Sal *sal;
+       struct _LpConfig *config;
+       net_config_t net_conf;
+       sip_config_t sip_conf;
+       rtp_config_t rtp_conf;
+       sound_config_t sound_conf;
+       video_config_t video_conf;
+       codecs_config_t codecs_conf;
+       ui_config_t ui_conf;
+       autoreplier_config_t autoreplier_conf;
+       LinphoneProxyConfig *default_proxy;
+       MSList *friends;
+       MSList *auth_info;
+       struct _RingStream *ringstream;
+       LCCallbackObj preview_finished_cb;
+       struct _LinphoneCall *call;   /* the current call, in the future it will be a list of calls (conferencing)*/
+       MSList *queued_calls;   /* used by the autoreplier */
+       MSList *call_logs;
+       MSList *chatrooms;
+       int max_call_logs;
+       int missed_calls;
+       struct _AudioStream *audiostream;  /**/
+       struct _VideoStream *videostream;
+       struct _VideoStream *previewstream;
+       RtpTransport *a_rtp,*a_rtcp;
+       MSList *bl_reqs;
+       MSList *subscribers;    /* unknown subscribers */
+       int minutes_away;
+       LinphoneOnlineStatus presence_mode;
+       LinphoneOnlineStatus prev_mode;
+       char *alt_contact;
+       void *data;
+       char *play_file;
+       char *rec_file;
+       time_t prevtime;
+       int dw_audio_bw;
+       int up_audio_bw;
+       int dw_video_bw;
+       int up_video_bw;
+       int audio_bw;
+       gstate_t gstate_power;
+       gstate_t gstate_reg;
+       gstate_t gstate_call;
+       LinphoneWaitingCallback wait_cb;
+       void *wait_ctx;
+       bool_t use_files;
+       bool_t apply_nat_settings;
+       bool_t ready;
+       bool_t bl_refresh;
+       bool_t preview_finished;
+};
+
 #endif /* _PRIVATE_H */
index 4a9720a35a58d42602a0aa96939c1f1aee2ebe7d..01b96bd78977e40eb9ef506bb6d7511806298c49 100644 (file)
@@ -20,8 +20,6 @@ Copyright (C) 2000  Simon MORLAT (simon.morlat@linphone.org)
  
 #include "linphonecore.h"
 #include "sipsetup.h"
-#include <eXosip2/eXosip.h>
-#include <osipparser2/osip_message.h>
 #include "lpconfig.h"
 #include "private.h"
 
@@ -40,7 +38,6 @@ void linphone_proxy_config_write_all_to_config_file(LinphoneCore *lc){
 
 void linphone_proxy_config_init(LinphoneProxyConfig *obj){
        memset(obj,0,sizeof(LinphoneProxyConfig));
-       obj->rid=-1;
        obj->expires=3600;
 }
 
@@ -72,8 +69,8 @@ void linphone_proxy_config_destroy(LinphoneProxyConfig *obj){
        if (obj->ssctx!=NULL) sip_setup_context_free(obj->ssctx);
        if (obj->realm!=NULL) ms_free(obj->realm);
        if (obj->type!=NULL) ms_free(obj->type);
-       if (obj->contact_addr!=NULL) ms_free(obj->contact_addr);
        if (obj->dial_prefix!=NULL) ms_free(obj->dial_prefix);
+       if (obj->op) sal_op_release(obj->op);
 }
 
 /**
@@ -83,79 +80,6 @@ bool_t linphone_proxy_config_is_registered(const LinphoneProxyConfig *obj){
        return obj->registered;
 }
 
-void linphone_proxy_config_get_contact(LinphoneProxyConfig *cfg, const char **ip, int *port){
-       if (cfg->registered){
-               *ip=cfg->contact_addr;
-               *port=cfg->contact_port;
-       }else{
-               *ip=NULL;
-               *port=0;
-       }
-}
-
-static void update_contact(LinphoneProxyConfig *cfg, const char *ip, const char *port){
-       if (cfg->contact_addr){
-               ms_free(cfg->contact_addr);
-       }
-       cfg->contact_addr=ms_strdup(ip);
-       if (port!=NULL)
-               cfg->contact_port=atoi(port);
-       else cfg->contact_port=5060;
-}
-
-bool_t linphone_proxy_config_register_again_with_updated_contact(LinphoneProxyConfig *obj, osip_message_t *orig_request, osip_message_t *last_answer){
-       osip_message_t *msg;
-       const char *rport,*received;
-       osip_via_t *via=NULL;
-       osip_generic_param_t *param=NULL;
-       osip_contact_t *ctt=NULL;
-       osip_message_get_via(last_answer,0,&via);
-       if (!via) return FALSE;
-       osip_via_param_get_byname(via,"rport",&param);
-       if (param) rport=param->gvalue;
-       else return FALSE;
-       param=NULL;
-       osip_via_param_get_byname(via,"received",&param);
-       if (param) received=param->gvalue;
-       else return FALSE;
-       osip_message_get_contact(orig_request,0,&ctt);
-       if (strcmp(ctt->url->host,received)==0){
-               /*ip address matches, check ports*/
-               const char *contact_port=ctt->url->port;
-               const char *via_rport=rport;
-               if (via_rport==NULL || strlen(via_rport)>0)
-                       via_rport="5060";
-               if (contact_port==NULL || strlen(contact_port)>0)
-                       contact_port="5060";
-               if (strcmp(contact_port,via_rport)==0){
-                       ms_message("Register has up to date contact, doing nothing.");
-                       return FALSE;
-               }else ms_message("ports do not match, need to update the register (%s <> %s)", contact_port,via_rport);
-       }
-       eXosip_lock();
-       msg=NULL;
-       eXosip_register_build_register(obj->rid,obj->expires,&msg);
-       if (msg==NULL){
-               eXosip_unlock();
-               ms_warning("Fail to create a contact updated register.");
-               return FALSE;
-       }
-       osip_message_get_contact(msg,0,&ctt);
-       if (ctt->url->host!=NULL){
-               osip_free(ctt->url->host);
-       }
-       ctt->url->host=osip_strdup(received);
-       if (ctt->url->port!=NULL){
-               osip_free(ctt->url->port);
-       }
-       ctt->url->port=osip_strdup(rport);
-       eXosip_register_send_register(obj->rid,msg);
-       eXosip_unlock();
-       update_contact(obj,received,rport);
-       ms_message("Resending new register with updated contact %s:%s",received,rport);
-       return TRUE;
-}
-
 /**
  * Sets the proxy address
  *
@@ -165,19 +89,18 @@ bool_t linphone_proxy_config_register_again_with_updated_contact(LinphoneProxyCo
  * - hostnames : sip:sip.example.net
 **/
 int linphone_proxy_config_set_server_addr(LinphoneProxyConfig *obj, const char *server_addr){
-       int err;
-       osip_from_t *url;
+       LinphoneAddress *addr;
        if (obj->reg_proxy!=NULL) ms_free(obj->reg_proxy);
        obj->reg_proxy=NULL;
        if (server_addr!=NULL && strlen(server_addr)>0){
-               osip_from_init(&url);
-               err=osip_from_parse(url,server_addr);
-               if (err==0 && url->url->host!=NULL){
+               addr=linphone_address_new(server_addr);
+               if (addr){
                        obj->reg_proxy=ms_strdup(server_addr);
+                       linphone_address_destroy(addr);
                }else{
                        ms_warning("Could not parse %s",server_addr);
+                       return -1;
                }
-               osip_from_free(url);
        }
        return 0;
 }
@@ -191,30 +114,30 @@ int linphone_proxy_config_set_server_addr(LinphoneProxyConfig *obj, const char *
  * The REGISTER messages will have from and to set to this identity.
  *
 **/
-void linphone_proxy_config_set_identity(LinphoneProxyConfig *obj, const char *identity){
-       int err=0;
-       osip_from_t *url=NULL;
+int linphone_proxy_config_set_identity(LinphoneProxyConfig *obj, const char *identity){
+       LinphoneAddress *addr;
        if (identity!=NULL && strlen(identity)>0){
-               osip_from_init(&url);
-               err=osip_from_parse(url,identity);
-               if (err<0 || url->url->host==NULL || url->url->username==NULL){
-                       ms_warning("Could not parse %s",identity);
-                       osip_from_free(url);
-                       return;
+               addr=linphone_address_new(identity);
+               if (!addr || linphone_address_get_username(addr)==NULL){
+                       ms_warning("Invalid sip identity: %s",identity);
+                       if (addr)
+                               linphone_address_destroy(addr);
+                       return -1;
+               }else{
+                       if (obj->reg_identity!=NULL) {
+                               ms_free(obj->reg_identity);
+                               obj->reg_identity=NULL;
+                       }
+                       obj->reg_identity=ms_strdup(identity);
+                       if (obj->realm){
+                               ms_free(obj->realm);
+                       }
+                       obj->realm=ms_strdup(linphone_address_get_domain(addr));
+                       linphone_address_destroy(addr);
+                       return 0;
                }
-       } else err=-2;
-       if (obj->reg_identity!=NULL) {
-               ms_free(obj->reg_identity);
-               obj->reg_identity=NULL;
        }
-       if (err==-2) obj->reg_identity=NULL;
-       else {
-               obj->reg_identity=ms_strdup(identity);
-               if (obj->realm)
-                       ms_free(obj->realm);
-               obj->realm=ms_strdup(url->url->host);
-       }
-       if (url) osip_from_free(url);
+       return -1;
 }
 
 const char *linphone_proxy_config_get_domain(const LinphoneProxyConfig *cfg){
@@ -226,37 +149,14 @@ const char *linphone_proxy_config_get_domain(const LinphoneProxyConfig *cfg){
  * When a route is set, all outgoing calls will go to the route's destination if this proxy
  * is the default one (see linphone_core_set_default_proxy() ).
 **/
-void linphone_proxy_config_set_route(LinphoneProxyConfig *obj, const char *route)
+int linphone_proxy_config_set_route(LinphoneProxyConfig *obj, const char *route)
 {
-       int err;
-       osip_uri_param_t *lr_param=NULL;
-       osip_route_t *rt=NULL;
-       char *tmproute=NULL;
-       if (route!=NULL && strlen(route)>0){
-               osip_route_init(&rt);
-               err=osip_route_parse(rt,route);
-               if (err<0){
-                       ms_warning("Could not parse %s",route);
-                       osip_route_free(rt);
-                       return ;
-               }
-               if (obj->reg_route!=NULL) {
-                       ms_free(obj->reg_route);
-                       obj->reg_route=NULL;
-               }
-                       
-               /* check if the lr parameter is set , if not add it */
-               osip_uri_uparam_get_byname(rt->url, "lr", &lr_param);
-               if (lr_param==NULL){
-                       osip_uri_uparam_add(rt->url,osip_strdup("lr"),NULL);
-                       osip_route_to_str(rt,&tmproute);
-                       obj->reg_route=ms_strdup(tmproute);
-                       osip_free(tmproute);
-               }else obj->reg_route=ms_strdup(route);
-       }else{
-               if (obj->reg_route!=NULL) ms_free(obj->reg_route);
+       if (obj->reg_route!=NULL){
+               ms_free(obj->reg_route);
                obj->reg_route=NULL;
        }
+       obj->reg_route=ms_strdup(route);
+       return 0;
 }
 
 bool_t linphone_proxy_config_check(LinphoneCore *lc, LinphoneProxyConfig *obj){
@@ -304,15 +204,10 @@ void linphone_proxy_config_enable_publish(LinphoneProxyConfig *obj, bool_t val){
  * linphone_proxy_config_done() to commit the changes.
 **/
 void linphone_proxy_config_edit(LinphoneProxyConfig *obj){
-       obj->auth_failures=0;
        if (obj->reg_sendregister){
                /* unregister */
                if (obj->registered) {
-                       osip_message_t *msg;
-                       eXosip_lock();
-                       eXosip_register_build_register(obj->rid,0,&msg);
-                       eXosip_register_send_register(obj->rid,msg);
-                       eXosip_unlock();
+                       sal_unregister(obj->op);
                        obj->registered=FALSE;
                }
        }
@@ -329,13 +224,11 @@ static void linphone_proxy_config_register(LinphoneProxyConfig *obj){
        if (obj->reg_identity!=NULL) id_str=obj->reg_identity;
        else id_str=linphone_core_get_primary_contact(obj->lc);
        if (obj->reg_sendregister){
-               char *ct=NULL;
-               osip_message_t *msg=NULL;
-               eXosip_lock();
-               obj->rid=eXosip_register_build_initial_register(id_str,obj->reg_proxy,NULL,obj->expires,&msg);
-               eXosip_register_send_register(obj->rid,msg);
-               eXosip_unlock();
-               if (ct!=NULL) osip_free(ct);
+               if (obj->op)
+                       sal_op_release(obj->op);
+               obj->op=sal_op_new(obj->lc->sal);
+               sal_op_set_user_pointer(obj->op,obj);
+               sal_register(obj->op,obj->reg_proxy,obj->reg_identity,obj->expires);
        }
 }
 
@@ -484,172 +377,62 @@ void linphone_proxy_config_set_realm(LinphoneProxyConfig *cfg, const char *realm
 }
 
 int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy,
-                              LinphoneOnlineStatus presence_mode)
-{
-  osip_message_t *pub;
-  int i;
-  const char *from=NULL;
-  char buf[5000];
+                              LinphoneOnlineStatus presence_mode){
+       int err;
+       SalOp *op=sal_op_new(proxy->lc->sal);
+       err=sal_publish(op,linphone_proxy_config_get_identity(proxy),
+           linphone_proxy_config_get_identity(proxy),linphone_online_status_to_sal(presence_mode));
+       sal_op_release(op);
+       return err;
+}
 
-  if (proxy->publish==FALSE) return 0;
-       
-  if (proxy!=NULL) {
-    from=linphone_proxy_config_get_identity(proxy);
-  }
-  if (from==NULL) from=linphone_core_get_primary_contact(proxy->lc);
-
-  if (presence_mode==LINPHONE_STATUS_ONLINE)
-    {
-      snprintf(buf, 5000, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
-<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
-          entity=\"%s\">\n\
-<tuple id=\"sg89ae\">\n\
-<status>\n\
-<basic>open</basic>\n\
-</status>\n\
-<contact priority=\"0.8\">%s</contact>\n\
-<note>online</note>\n\
-</tuple>\n\
-</presence>",
-              from, from);
-    }
-  else if (presence_mode==LINPHONE_STATUS_BUSY
-          ||presence_mode==LINPHONE_STATUS_NOT_DISTURB)
-    {
-      snprintf(buf, 5000, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
-<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
-          xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
-          entity=\"%s\">\n\
-<tuple id=\"sg89ae\">\n\
-<status>\n\
-<basic>open</basic>\n\
-<es:activities>\n\
-  <es:activity>busy</es:activity>\n\
-</es:activities>\n\
-</status>\n\
-<contact priority=\"0.8\">%s</contact>\n\
-<note>busy</note>\n\
-</tuple>\n\
-</presence>",
-             from, from);
-    }
-  else if (presence_mode==LINPHONE_STATUS_BERIGHTBACK)
-    {
-      snprintf(buf, 5000, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
-<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
-          xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
-          entity=\"%s\">\n\
-<tuple id=\"sg89ae\">\n\
-<status>\n\
-<basic>open</basic>\n\
-<es:activities>\n\
-  <es:activity>in-transit</es:activity>\n\
-</es:activities>\n\
-</status>\n\
-<contact priority=\"0.8\">%s</contact>\n\
-<note>be right back</note>\n\
-</tuple>\n\
-</presence>",
-             from,from);
-    }
-  else if (presence_mode==LINPHONE_STATUS_AWAY
-          ||presence_mode==LINPHONE_STATUS_MOVED
-          ||presence_mode==LINPHONE_STATUS_ALT_SERVICE)
-    {
-      snprintf(buf, 5000, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
-<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
-          xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
-          entity=\"%s\">\n\
-<tuple id=\"sg89ae\">\n\
-<status>\n\
-<basic>open</basic>\n\
-<es:activities>\n\
-  <es:activity>away</es:activity>\n\
-</es:activities>\n\
-</status>\n\
-<contact priority=\"0.8\">%s</contact>\n\
-<note>away</note>\n\
-</tuple>\n\
-</presence>",
-             from, from);
-    }
-  else if (presence_mode==LINPHONE_STATUS_ONTHEPHONE)
-    {
-      snprintf(buf, 5000, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
-<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
-          xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
-          entity=\"%s\">\n\
-<tuple id=\"sg89ae\">\n\
-<status>\n\
-<basic>open</basic>\n\
-<es:activities>\n\
-  <es:activity>on-the-phone</es:activity>\n\
-</es:activities>\n\
-</status>\n\
-<contact priority=\"0.8\">%s</contact>\n\
-<note>on the phone</note>\n\
-</tuple>\n\
-</presence>",
-             from, from);
-    }
-  else if (presence_mode==LINPHONE_STATUS_OUTTOLUNCH)
-    {
-      snprintf(buf, 5000, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
-<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
-          xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
-          entity=\"%s\">\n\
-<tuple id=\"sg89ae\">\n\
-<status>\n\
-<basic>open</basic>\n\
-<es:activities>\n\
-  <es:activity>meal</es:activity>\n\
-</es:activities>\n\
-</status>\n\
-<contact priority=\"0.8\">%s</contact>\n\
-<note>out to lunch</note>\n\
-</tuple>\n\
-</presence>",
-             from, from);
-    }
-  else if (presence_mode==LINPHONE_STATUS_OFFLINE)
-    {
-      /* */
-      snprintf(buf, 5000, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
-<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
-xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
-entity=\"%s\">\n%s",
-             from,
-"<tuple id=\"sg89ae\">\n\
-<status>\n\
-<basic>closed</basic>\n\
-<es:activities>\n\
-  <es:activity>permanent-absence</e:activity>\n\
-</es:activities>\n\
-</status>\n\
-</tuple>\n\
-\n</presence>\n");
-    }
-
-  i = eXosip_build_publish(&pub, (char *)from, (char *)from, NULL, "presence", "1800", "application/pidf+xml", buf);
-
-  if (i<0)
-    {
-      ms_message("Failed to build publish request.");
-      return -1;
-    }
-
-  eXosip_lock();
-  i = eXosip_publish(pub, from); /* should update the sip-if-match parameter
-                                   from sip-etag  from last 200ok of PUBLISH */
-  eXosip_unlock();
-  if (i<0)
-    {
-      ms_message("Failed to send publish request.");
-      return -1;
-    }
-  return 0;
+/**
+ * Returns the route set for this proxy configuration.
+**/
+const char *linphone_proxy_config_get_route(const LinphoneProxyConfig *obj){
+       return obj->reg_route;
+}
+
+/**
+ * Returns the SIP identity that belongs to this proxy configuration.
+ *
+ * The SIP identity is a SIP address (Display Name <sip:username@domain> )
+**/
+const char *linphone_proxy_config_get_identity(const LinphoneProxyConfig *obj){
+       return obj->reg_identity;
+}
+
+/**
+ * Returns TRUE if PUBLISH request is enabled for this proxy.
+**/
+bool_t linphone_proxy_config_publish_enabled(const LinphoneProxyConfig *obj){
+       return obj->publish;
 }
 
+/**
+ * Returns the proxy's SIP address.
+**/
+const char *linphone_proxy_config_get_addr(const LinphoneProxyConfig *obj){
+       return obj->reg_proxy;
+}
+
+/**
+ * Returns the duration of registration.
+**/
+int linphone_proxy_config_get_expires(const LinphoneProxyConfig *obj){
+       return obj->expires;
+}
+
+/**
+ * Returns TRUE if registration to the proxy is enabled.
+**/
+bool_t linphone_proxy_config_register_enabled(const LinphoneProxyConfig *obj){
+       return obj->reg_sendregister;
+}
+
+struct _LinphoneCore * linphone_proxy_config_get_core(const LinphoneProxyConfig *obj){
+       return obj->lc;
+}
 
 /**
  * Add a proxy configuration.
@@ -657,13 +440,15 @@ entity=\"%s\">\n%s",
 **/
 int linphone_core_add_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *cfg){
        if (!linphone_proxy_config_check(lc,cfg)) return -1;
+       if (ms_list_find(lc->sip_conf.proxies,cfg)!=NULL){
+               ms_warning("ProxyConfig already entered, ignored.");
+               return 0;
+       }
        lc->sip_conf.proxies=ms_list_append(lc->sip_conf.proxies,(void *)cfg);
        linphone_proxy_config_apply(cfg,lc);
        return 0;
 }
 
-extern void linphone_friend_check_for_removed_proxy(LinphoneFriend *lf, LinphoneProxyConfig *cfg);
-
 /**
  * Removes a proxy configuration.
  *
@@ -671,7 +456,6 @@ extern void linphone_friend_check_for_removed_proxy(LinphoneFriend *lf, Linphone
  * on a deleted list. For that reason, a removed proxy does NOT need to be freed.
 **/
 void linphone_core_remove_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *cfg){
-       MSList *elem;
        lc->sip_conf.proxies=ms_list_remove(lc->sip_conf.proxies,(void *)cfg);
        /* add to the list of destroyed proxies, so that the possible unREGISTER request can succeed authentication */
        lc->sip_conf.deleted_proxies=ms_list_append(lc->sip_conf.deleted_proxies,(void *)cfg);
@@ -680,11 +464,6 @@ void linphone_core_remove_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *cf
        if (lc->default_proxy==cfg){
                lc->default_proxy=NULL;
        }
-       /* invalidate all references to this proxy in our friend list */
-       for (elem=lc->friends;elem!=NULL;elem=ms_list_next(elem)){
-               linphone_friend_check_for_removed_proxy((LinphoneFriend*)elem->data,cfg);
-       }
-       
 }
 /**
  * Erase all proxies from config.
@@ -735,23 +514,6 @@ int linphone_core_get_default_proxy(LinphoneCore *lc, LinphoneProxyConfig **conf
        return pos;
 }
 
-static int rid_compare(const void *pcfg,const void *prid){
-       const LinphoneProxyConfig *cfg=(const LinphoneProxyConfig*)pcfg;
-       const int *rid=(const int*)prid;
-       ms_message("cfg= %s, cfg->rid=%i, rid=%i",cfg->reg_proxy, cfg->rid, *rid);
-       return cfg->rid-(*rid);
-}
-
-LinphoneProxyConfig *linphone_core_get_proxy_config_from_rid(LinphoneCore *lc, int rid){
-       MSList *elem=ms_list_find_custom(lc->sip_conf.proxies,rid_compare, &rid);
-       if (elem==NULL){
-               ms_message("linphone_core_get_proxy_config_from_rid: searching in deleted proxies...");
-               elem=ms_list_find_custom(lc->sip_conf.deleted_proxies,rid_compare, &rid);
-       }
-       if (elem==NULL) return NULL;
-       else return (LinphoneProxyConfig*)elem->data;
-}
-
 /**
  * Returns an unmodifiable list of entered proxy configurations.
 **/
@@ -759,47 +521,6 @@ const MSList *linphone_core_get_proxy_config_list(const LinphoneCore *lc){
        return lc->sip_conf.proxies;
 }
 
-
-void linphone_proxy_config_process_authentication_failure(LinphoneCore *lc, int code, eXosip_event_t *ev){
-       if (code==403) {
-               LinphoneProxyConfig *cfg=linphone_core_get_proxy_config_from_rid(lc, ev->rid);
-               if (cfg){
-                       cfg->auth_failures++;
-                       /*restart a new register so that the user gets a chance to be prompted for a password*/
-                       if (cfg->auth_failures==1){
-                               linphone_proxy_config_register(cfg);
-                       }
-               }
-       } else {
-               //unknown error (possibly timeout)
-               char *prx_realm=NULL,*www_realm=NULL;
-               osip_proxy_authenticate_t *prx_auth;
-               osip_www_authenticate_t *www_auth;
-               osip_message_t *req=ev->request;
-               char *username;
-               username=osip_uri_get_username(req->from->url);
-               prx_auth=(osip_proxy_authenticate_t*)osip_list_get(&req->proxy_authenticates,0);
-               www_auth=(osip_proxy_authenticate_t*)osip_list_get(&req->www_authenticates,0);
-               if (prx_auth!=NULL)
-                       prx_realm=osip_proxy_authenticate_get_realm(prx_auth);
-               if (www_auth!=NULL)
-                       www_realm=osip_www_authenticate_get_realm(www_auth);
-
-               if (prx_realm==NULL && www_realm==NULL){
-                       ms_warning("No realm in the client request.");
-                       return;
-               }
-               LinphoneAuthInfo *as=NULL;
-               /* see if we already have this auth information , not to ask it everytime to the user */
-               if (prx_realm!=NULL)
-                       as=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,prx_realm,username);
-               if (www_realm!=NULL)
-                       as=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,www_realm,username);
-
-               if (as) as->first_time=TRUE;
-       }
-}
-
 void linphone_proxy_config_write_to_config_file(LpConfig *config, LinphoneProxyConfig *obj, int index)
 {
        char key[50];
diff --git a/coreapi/sal.c b/coreapi/sal.c
new file mode 100644 (file)
index 0000000..ae432d5
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+linphone
+Copyright (C) 2010  Simon MORLAT (simon.morlat@free.fr)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+/** 
+ This header files defines the Signaling Abstraction Layer.
+ The purpose of this layer is too allow experiment different call signaling 
+ protocols and implementations under linphone, for example SIP, JINGLE...
+**/
+
+#include "sal.h"
+
+SalMediaDescription *sal_media_description_new(){
+       SalMediaDescription *md=ms_new0(SalMediaDescription,1);
+       md->refcount=1;
+       return md;
+}
+
+static void sal_media_description_destroy(SalMediaDescription *md){
+       int i;
+       for(i=0;i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS;i++){
+               ms_list_for_each(md->streams[i].payloads,(void (*)(void *))payload_type_destroy);
+               ms_list_free(md->streams[i].payloads);
+               md->streams[i].payloads=NULL;
+       }
+       ms_free(md);
+}
+
+void sal_media_description_ref(SalMediaDescription *md){
+       md->refcount++;
+}
+
+void sal_media_description_unref(SalMediaDescription *md){
+       md->refcount--;
+       if (md->refcount==0){
+               sal_media_description_destroy (md);
+       }
+}
+
+const SalStreamDescription *sal_media_description_find_stream(const SalMediaDescription *md,
+    SalMediaProto proto, SalStreamType type){
+       int i;
+       for(i=0;i<md->nstreams;++i){
+               const SalStreamDescription *ss=&md->streams[i];
+               if (ss->proto==proto && ss->type==type) return ss;
+       }
+       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){
+               ms_free(*str);
+               *str=NULL;
+       }
+       if (arg)
+               *str=ms_strdup(arg);
+}
+
+void sal_op_set_contact(SalOp *op, const char *contact){
+       assign_string(&((SalOpBase*)op)->contact,contact);
+}
+
+void sal_op_set_route(SalOp *op, const char *route){
+       assign_string(&((SalOpBase*)op)->route,route);
+}
+
+void sal_op_set_from(SalOp *op, const char *from){
+       assign_string(&((SalOpBase*)op)->from,from);
+}
+
+void sal_op_set_to(SalOp *op, const char *to){
+       assign_string(&((SalOpBase*)op)->to,to);
+}
+
+void sal_op_set_user_pointer(SalOp *op, void *up){
+       ((SalOpBase*)op)->user_pointer=up;
+}
+
+Sal *sal_op_get_sal(const SalOp *op){
+       return ((SalOpBase*)op)->root;
+}
+
+const char *sal_op_get_from(const SalOp *op){
+       return ((SalOpBase*)op)->from;
+}
+
+const char *sal_op_get_to(const SalOp *op){
+       return ((SalOpBase*)op)->to;
+}
+
+const char *sal_op_get_contact(const SalOp *op){
+       return ((SalOpBase*)op)->contact;
+}
+
+const char *sal_op_get_route(const SalOp *op){
+       return ((SalOpBase*)op)->route;
+}
+
+void *sal_op_get_user_pointer(const SalOp *op){
+       return ((SalOpBase*)op)->user_pointer;
+}
+
+const char *sal_op_get_proxy(const SalOp *op){
+       return ((SalOpBase*)op)->route;
+}
+
+void __sal_op_init(SalOp *b, Sal *sal){
+       memset(b,0,sizeof(SalOpBase));
+       ((SalOpBase*)b)->root=sal;
+}
+
+void __sal_op_free(SalOp *op){
+       SalOpBase *b=(SalOpBase *)op;
+       if (b->from) {
+               ms_free(b->from);
+               b->from=NULL;
+       }
+       if (b->to) {
+               ms_free(b->to);
+               b->to=NULL;
+       }
+       if (b->route) {
+               ms_free(b->route);
+               b->route=NULL;
+       }
+       if (b->contact) {
+               ms_free(b->contact);
+               b->contact=NULL;
+       }
+       if (b->local_media)
+               sal_media_description_unref(b->local_media);
+       if (b->remote_media)
+               sal_media_description_unref(b->remote_media);
+       ms_free(op);
+}
diff --git a/coreapi/sal.h b/coreapi/sal.h
new file mode 100644 (file)
index 0000000..eb80423
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+linphone
+Copyright (C) 2010  Simon MORLAT (simon.morlat@free.fr)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+/** 
+ This header files defines the Signaling Abstraction Layer.
+ The purpose of this layer is too allow experiment different call signaling 
+ protocols and implementations under linphone, for example SIP, JINGLE...
+**/
+
+#ifndef sal_h
+#define sal_h
+
+#include "mediastreamer2/mscommon.h"
+
+struct Sal;
+
+typedef struct Sal Sal;
+
+struct SalOp;
+
+typedef struct SalOp SalOp;
+
+struct SalAddress;
+
+typedef struct SalAddress SalAddress;
+
+/* Address manipulation API*/
+SalAddress * sal_address_new(const char *uri);
+SalAddress * sal_address_clone(const SalAddress *addr);
+const char *sal_address_get_scheme(const SalAddress *addr);
+const char *sal_address_get_display_name(const SalAddress* addr);
+const char *sal_address_get_username(const SalAddress *addr);
+const char *sal_address_get_domain(const SalAddress *addr);
+void sal_address_set_display_name(SalAddress *addr, const char *display_name);
+void sal_address_set_username(SalAddress *addr, const char *username);
+void sal_address_set_domain(SalAddress *addr, const char *host);
+void sal_address_set_port(SalAddress *addr, const char *port);
+void sal_address_set_port_int(SalAddress *uri, int port);
+void sal_address_clean(SalAddress *addr);
+char *sal_address_as_string(const SalAddress *u);
+char *sal_address_as_string_uri_only(const SalAddress *u);
+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,
+       SalTransportStream
+}SalTransport;
+
+typedef enum {
+       SalAudio,
+       SalVideo,
+       SalOther
+} SalStreamType;
+
+typedef enum{
+       SalProtoUnknown,
+       SalProtoRtpAvp,
+       SalProtoRtpSavp
+}SalMediaProto;
+
+typedef struct SalEndpointCandidate{
+       char addr[64];
+       int port;
+}SalEndpointCandidate;
+
+#define SAL_ENDPOINT_CANDIDATE_MAX 2
+
+typedef struct SalStreamDescription{
+       SalMediaProto proto;
+       SalStreamType type;
+       char addr[64];
+       int port;
+       MSList *payloads; //<list of PayloadType
+       int bandwidth;
+       int ptime;
+       SalEndpointCandidate candidates[SAL_ENDPOINT_CANDIDATE_MAX];
+} SalStreamDescription;
+
+#define SAL_MEDIA_DESCRIPTION_MAX_STREAMS 4
+
+typedef struct SalMediaDescription{
+       int refcount;
+       char addr[64];
+       char username[64];
+       int nstreams;
+       SalStreamDescription streams[SAL_MEDIA_DESCRIPTION_MAX_STREAMS];
+} 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);
+const SalStreamDescription *sal_media_description_find_stream(const SalMediaDescription *md,
+    SalMediaProto proto, SalStreamType type);
+
+/*this structure must be at the first byte of the SalOp structure defined by implementors*/
+typedef struct SalOpBase{
+       Sal *root;
+       char *route; /*or request-uri for REGISTER*/
+       char *contact;
+       char *from;
+       char *to;
+       SalMediaDescription *local_media;
+       SalMediaDescription *remote_media;
+       void *user_pointer;
+} SalOpBase;
+
+
+typedef enum SalError{
+       SalErrorNoResponse,
+       SalErrorProtocol,
+       SalErrorFailure, /* see SalReason for more details */
+       SalErrorUnknown
+} SalError;
+
+typedef enum SalReason{
+       SalReasonDeclined,
+       SalReasonBusy,
+       SalReasonRedirect,
+       SalReasonTemporarilyUnavailable,
+       SalReasonNotFound,
+       SalReasonDoNotDisturb,
+       SalReasonMedia,
+       SalReasonForbidden,
+       SalReasonUnknown
+}SalReason;
+
+typedef enum SalPresenceStatus{
+       SalPresenceOffline,
+       SalPresenceOnline,
+       SalPresenceBusy,
+       SalPresenceBerightback,
+       SalPresenceAway,
+       SalPresenceOnthephone,
+       SalPresenceOuttolunch,
+       SalPresenceDonotdisturb,
+       SalPresenceMoved,
+       SalPresenceAltService,
+}SalPresenceStatus;
+
+typedef enum SalSubscribeState{
+       SalSubscribeActive,
+       SalSubscribeTerminated
+}SalSubscribeState;
+
+typedef void (*SalOnCallReceived)(SalOp *op);
+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, 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);
+typedef void (*SalOnRegisterSuccess)(SalOp *op, bool_t registered);
+typedef void (*SalOnRegisterFailure)(SalOp *op, SalError error, SalReason reason, const char *details);
+typedef void (*SalOnVfuRequest)(SalOp *op);
+typedef void (*SalOnDtmfReceived)(SalOp *op, char dtmf);
+typedef void (*SalOnRefer)(Sal *sal, SalOp *op, const char *referto);
+typedef void (*SalOnTextReceived)(Sal *sal, const char *from, const char *msg);
+typedef void (*SalOnNotify)(SalOp *op, SalSubscribeState ss, SalPresenceStatus status, const char *msg);
+typedef void (*SalOnSubscribeReceived)(SalOp *salop, const char *from);
+typedef void (*SalOnSubscribeClosed)(SalOp *salop, const char *from);
+typedef void (*SalOnInternalMsg)(Sal *sal, const char *msg);
+
+typedef struct SalCallbacks{
+       SalOnCallReceived call_received;
+       SalOnCallRinging call_ringing;
+       SalOnCallAccepted call_accepted;
+       SalOnCallAck call_ack;
+       SalOnCallUpdated call_updated;
+       SalOnCallTerminated call_terminated;
+       SalOnCallFailure call_failure;
+       SalOnAuthRequested auth_requested;
+       SalOnAuthSuccess auth_success;
+       SalOnRegisterSuccess register_success;
+       SalOnRegisterFailure register_failure;
+       SalOnVfuRequest vfu_request;
+       SalOnDtmfReceived dtmf_received;
+       SalOnRefer refer_received;
+       SalOnTextReceived text_received;
+       SalOnNotify notify;
+       SalOnSubscribeReceived subscribe_received;
+       SalOnSubscribeClosed subscribe_closed;
+       SalOnInternalMsg internal_message;
+}SalCallbacks;
+
+typedef struct SalAuthInfo{
+       char *username;
+       char *userid;
+       char *password;
+       char *realm;
+}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);
+MSList * sal_get_pending_auths(Sal *sal);
+
+/*create an operation */
+SalOp * sal_op_new(Sal *sal);
+
+/*generic SalOp API, working for all operations */
+Sal *sal_op_get_sal(const SalOp *op);
+void sal_op_set_contact(SalOp *op, const char *contact);
+void sal_op_set_route(SalOp *op, const char *route);
+void sal_op_set_from(SalOp *op, const char *from);
+void sal_op_set_to(SalOp *op, const char *to);
+void sal_op_release(SalOp *h);
+void sal_op_authenticate(SalOp *h, const SalAuthInfo *info);
+void sal_op_set_user_pointer(SalOp *h, void *up);
+int sal_op_get_auth_requested(SalOp *h, const char **realm, const char **username);
+const char *sal_op_get_from(const SalOp *op);
+const char *sal_op_get_to(const SalOp *op);
+const char *sal_op_get_contact(const SalOp *op);
+const char *sal_op_get_route(const SalOp *op);
+const char *sal_op_get_proxy(const SalOp *op);
+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*/);
+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*/
+int sal_register(SalOp *op, const char *proxy, const char *from, int expires);
+int sal_unregister(SalOp *h);
+
+/*Messaging */
+int sal_text_send(SalOp *op, const char *from, const char *to, const char *text);
+
+/*presence Subscribe/notify*/
+int sal_subscribe_presence(SalOp *op, const char *from, const char *to);
+int sal_unsubscribe(SalOp *op);
+int sal_subscribe_accept(SalOp *op);
+int sal_subscribe_decline(SalOp *op);
+int sal_notify_presence(SalOp *op, SalPresenceStatus status, const char *status_message);
+int sal_notify_close(SalOp *op);
+
+/*presence publish */
+int sal_publish(SalOp *op, const char *from, const char *to, SalPresenceStatus status);
+
+#define payload_type_set_number(pt,n)  (pt)->user_data=(void*)((long)n);
+#define payload_type_get_number(pt)            ((int)(long)(pt)->user_data)
+
+/*misc*/
+void sal_get_default_local_ip(Sal *sal, int address_family, char *ip, size_t iplen);
+
+
+/*internal API */
+void __sal_op_init(SalOp *b, Sal *sal);
+void __sal_op_free(SalOp *b);
+
+
+#endif
diff --git a/coreapi/sal_eXosip2.c b/coreapi/sal_eXosip2.c
new file mode 100644 (file)
index 0000000..c4f00da
--- /dev/null
@@ -0,0 +1,1339 @@
+/*
+linphone
+Copyright (C) 2010  Simon MORLAT (simon.morlat@free.fr)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+#include "sal_eXosip2.h"
+
+#include "offeranswer.h"
+
+void sal_get_default_local_ip(Sal *sal, int address_family,char *ip, size_t iplen){
+       if (eXosip_guess_localip(address_family,ip,iplen)<0){
+               /*default to something */
+               strncpy(ip,address_family==AF_INET6 ? "::1" : "127.0.0.1",iplen);
+               ms_error("Could not find default routable ip address !");
+       }
+}
+
+static SalOp * sal_find_register(Sal *sal, int rid){
+       const MSList *elem;
+       SalOp *op;
+       for(elem=sal->registers;elem!=NULL;elem=elem->next){
+               op=(SalOp*)elem->data;
+               if (op->rid==rid) return op;
+       }
+       return NULL;
+}
+
+static void sal_add_register(Sal *sal, SalOp *op){
+       sal->registers=ms_list_append(sal->registers,op);
+}
+
+static void sal_remove_register(Sal *sal, int rid){
+       MSList *elem;
+       SalOp *op;
+       for(elem=sal->registers;elem!=NULL;elem=elem->next){
+               op=(SalOp*)elem->data;
+               if (op->rid==rid) {
+                       sal->registers=ms_list_remove_link(sal->registers,elem);
+                       return;
+               }
+       }
+}
+
+static void sal_add_pending_auth(Sal *sal, SalOp *op){
+       sal->pending_auths=ms_list_append(sal->pending_auths,op);
+}
+
+
+static void sal_remove_pending_auth(Sal *sal, SalOp *op){
+       sal->pending_auths=ms_list_remove(sal->pending_auths,op);
+}
+
+void sal_exosip_fix_route(SalOp *op){
+       if (sal_op_get_route(op)!=NULL){
+               osip_route_t *rt=NULL;
+               osip_uri_param_t *lr_param=NULL;
+               
+               osip_route_init(&rt);
+               if (osip_route_parse(rt,sal_op_get_route(op))<0){
+                       ms_warning("Bad route  %s!",sal_op_get_route(op));
+                       sal_op_set_route(op,NULL);
+               }else{
+                       /* check if the lr parameter is set , if not add it */
+                       osip_uri_uparam_get_byname(rt->url, "lr", &lr_param);
+                       if (lr_param==NULL){
+                               char *tmproute;
+                               osip_uri_uparam_add(rt->url,osip_strdup("lr"),NULL);
+                               osip_route_to_str(rt,&tmproute);
+                               sal_op_set_route(op,tmproute);
+                               osip_free(tmproute);
+                       }
+               }
+               osip_route_free(rt);
+       }
+}
+
+SalOp * sal_op_new(Sal *sal){
+       SalOp *op=ms_new(SalOp,1);
+       __sal_op_init(op,sal);
+       op->cid=op->did=op->tid=op->rid=op->nid=op->sid=-1;
+       op->result=NULL;
+       op->supports_session_timers=FALSE;
+       op->sdp_offering=TRUE;
+       op->pending_auth=NULL;
+       op->sdp_answer=NULL;
+       op->reinvite=FALSE;
+       return op;
+}
+
+void sal_op_release(SalOp *op){
+       if (op->sdp_answer)
+               sdp_message_free(op->sdp_answer);
+       if (op->pending_auth)
+               eXosip_event_free(op->pending_auth);
+       if (op->rid!=-1){
+               sal_remove_register(op->base.root,op->rid);
+       }
+       if (op->cid!=-1){
+               ms_message("Cleaning cid %i",op->cid);
+               eXosip_call_set_reference(op->cid,NULL);
+       }
+       if (op->pending_auth){
+               sal_remove_pending_auth(op->base.root,op);
+       }
+       if (op->result)
+               sal_media_description_unref(op->result);
+       __sal_op_free(op);
+}
+
+static void _osip_trace_func(char *fi, int li, osip_trace_level_t level, char *chfr, va_list ap){
+       int ortp_level=ORTP_DEBUG;
+       switch(level){
+               case OSIP_INFO1:
+               case OSIP_INFO2:
+               case OSIP_INFO3:
+               case OSIP_INFO4:
+                       ortp_level=ORTP_MESSAGE;
+                       break;
+               case OSIP_WARNING:
+                       ortp_level=ORTP_WARNING;
+                       break;
+               case OSIP_ERROR:
+               case OSIP_BUG:
+                       ortp_level=ORTP_ERROR;
+                       break;
+               case OSIP_FATAL:
+                       ortp_level=ORTP_FATAL;
+                       break;
+               case END_TRACE_LEVEL:
+                       break;
+       }
+       if (ortp_log_level_enabled(level)){
+               int len=strlen(chfr);
+               char *chfrdup=ortp_strdup(chfr);
+               /*need to remove endline*/
+               if (len>1){
+                       if (chfrdup[len-1]=='\n')
+                               chfrdup[len-1]='\0';
+                       if (chfrdup[len-2]=='\r')
+                               chfrdup[len-2]='\0';
+               }
+               ortp_logv(ortp_level,chfrdup,ap);
+               ortp_free(chfrdup);
+       }
+}
+
+
+Sal * sal_init(){
+       static bool_t firsttime=TRUE;
+       if (firsttime){
+               osip_trace_initialize_func (OSIP_INFO4,&_osip_trace_func);
+               firsttime=FALSE;
+       }
+       eXosip_init();
+       return ms_new0(Sal,1);
+}
+
+void sal_uninit(Sal* sal){
+       eXosip_quit();
+       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");
+}
+
+void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs){
+       memcpy(&ctx->callbacks,cbs,sizeof(*cbs));
+       if (ctx->callbacks.call_received==NULL) 
+               ctx->callbacks.call_received=(SalOnCallReceived)unimplemented_stub;
+       if (ctx->callbacks.call_ringing==NULL) 
+               ctx->callbacks.call_ringing=(SalOnCallRinging)unimplemented_stub;
+       if (ctx->callbacks.call_accepted==NULL) 
+               ctx->callbacks.call_accepted=(SalOnCallAccepted)unimplemented_stub;
+       if (ctx->callbacks.call_failure==NULL) 
+               ctx->callbacks.call_failure=(SalOnCallFailure)unimplemented_stub;
+       if (ctx->callbacks.call_terminated==NULL) 
+               ctx->callbacks.call_terminated=(SalOnCallTerminated)unimplemented_stub;
+       if (ctx->callbacks.call_updated==NULL) 
+               ctx->callbacks.call_updated=(SalOnCallUpdated)unimplemented_stub;
+       if (ctx->callbacks.auth_requested==NULL) 
+               ctx->callbacks.auth_requested=(SalOnAuthRequested)unimplemented_stub;
+       if (ctx->callbacks.auth_success==NULL) 
+               ctx->callbacks.auth_success=(SalOnAuthSuccess)unimplemented_stub;
+       if (ctx->callbacks.register_success==NULL) 
+               ctx->callbacks.register_success=(SalOnRegisterSuccess)unimplemented_stub;
+       if (ctx->callbacks.register_failure==NULL) 
+               ctx->callbacks.register_failure=(SalOnRegisterFailure)unimplemented_stub;
+       if (ctx->callbacks.dtmf_received==NULL) 
+               ctx->callbacks.dtmf_received=(SalOnDtmfReceived)unimplemented_stub;
+       if (ctx->callbacks.notify==NULL)
+               ctx->callbacks.notify=(SalOnNotify)unimplemented_stub;
+       if (ctx->callbacks.subscribe_received==NULL)
+               ctx->callbacks.subscribe_received=(SalOnSubscribeReceived)unimplemented_stub;
+       if (ctx->callbacks.text_received==NULL)
+               ctx->callbacks.text_received=(SalOnTextReceived)unimplemented_stub;
+       if (ctx->callbacks.internal_message==NULL)
+               ctx->callbacks.internal_message=(SalOnInternalMsg)unimplemented_stub;
+}
+
+int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int is_secure){
+       int err;
+       bool_t ipv6;
+       int proto=IPPROTO_UDP;
+       
+       if (ctx->running) eXosip_quit();
+       eXosip_init();
+       err=0;
+       eXosip_set_option(13,&err); /*13=EXOSIP_OPT_SRV_WITH_NAPTR, as it is an enum value, we can't use it unless we are sure of the
+                                       version of eXosip, which is not the case*/
+       /*see if it looks like an IPv6 address*/
+       ipv6=strchr(addr,':')!=NULL;
+       eXosip_enable_ipv6(ipv6);
+
+       if (tr!=SalTransportDatagram || is_secure){
+               ms_fatal("SIP over TCP or TLS or DTLS is not supported yet.");
+               return -1;
+       }
+       
+       err=eXosip_listen_addr(proto, addr, port, ipv6 ?  PF_INET6 : PF_INET, 0);
+       return err;
+}
+
+void sal_set_user_agent(Sal *ctx, const char *user_agent){
+       eXosip_set_user_agent(user_agent);
+}
+
+void sal_use_session_timers(Sal *ctx, int expires){
+       ctx->session_expires=expires;
+}
+
+MSList *sal_get_pending_auths(Sal *sal){
+       return ms_list_copy(sal->pending_auths);
+}
+
+
+static void set_sdp(osip_message_t *sip,sdp_message_t *msg){
+       int sdplen;
+       char clen[10];
+       char *sdp=NULL;
+       sdp_message_to_str(msg,&sdp);
+       sdplen=strlen(sdp);
+       snprintf(clen,sizeof(clen),"%i",sdplen);
+       osip_message_set_body(sip,sdp,sdplen);
+       osip_message_set_content_type(sip,"application/sdp");
+       osip_message_set_content_length(sip,clen);
+       osip_free(sdp);
+}
+
+static void set_sdp_from_desc(osip_message_t *sip, const SalMediaDescription *desc){
+       sdp_message_t *msg=media_description_to_sdp(desc);
+       if (msg==NULL) {
+               ms_error("Fail to print sdp message !");
+               return;
+       }
+       set_sdp(sip,msg);
+       sdp_message_free(msg);
+}
+
+static void sdp_process(SalOp *h){
+       ms_message("Doing SDP offer/answer process");
+       if (h->result){
+               sal_media_description_unref(h->result);
+       }
+       h->result=sal_media_description_new();
+       if (h->sdp_offering){   
+               offer_answer_initiate_outgoing(h->base.local_media,h->base.remote_media,h->result);
+       }else{
+               int i;
+               offer_answer_initiate_incoming(h->base.local_media,h->base.remote_media,h->result);
+               h->sdp_answer=media_description_to_sdp(h->result);
+               strcpy(h->result->addr,h->base.remote_media->addr);
+               for(i=0;i<h->result->nstreams;++i){
+                       if (h->result->streams[i].port>0){
+                               strcpy(h->result->streams[i].addr,h->base.remote_media->streams[i].addr);
+                               h->result->streams[i].ptime=h->base.remote_media->streams[i].ptime;
+                               h->result->streams[i].bandwidth=h->base.remote_media->streams[i].bandwidth;
+                               h->result->streams[i].port=h->base.remote_media->streams[i].port;
+                       }
+               }
+       }
+       
+}
+
+int sal_call_set_local_media_description(SalOp *h, SalMediaDescription *desc){
+       if (desc)
+               sal_media_description_ref(desc);
+       if (h->base.local_media)
+               sal_media_description_unref(h->base.local_media);
+       h->base.local_media=desc;
+       return 0;
+}
+
+int sal_call(SalOp *h, const char *from, const char *to){
+       int err;
+       osip_message_t *invite=NULL;
+       sal_op_set_from(h,from);
+       sal_op_set_to(h,to);
+       sal_exosip_fix_route(h);
+       err=eXosip_call_build_initial_invite(&invite,to,from,sal_op_get_route(h),"Phone call");
+       if (err!=0){
+               ms_error("Could not create call.");
+               return -1;
+       }
+       if (h->base.contact){
+               osip_list_special_free(&invite->contacts,(void (*)(void*))osip_contact_free);
+               osip_message_set_contact(invite,h->base.contact);
+       }
+       if (h->base.root->session_expires!=0){
+               osip_message_set_header(invite, "Session-expires", "200");
+               osip_message_set_supported(invite, "timer");
+       }
+       if (h->base.local_media){
+               h->sdp_offering=TRUE;
+               set_sdp_from_desc(invite,h->base.local_media);
+       }else h->sdp_offering=FALSE;
+       eXosip_lock();
+       err=eXosip_call_send_initial_invite(invite);
+       eXosip_unlock();
+       h->cid=err;
+       if (err<0){
+               ms_error("Fail to send invite !");
+               return -1;
+       }else{
+               eXosip_call_set_reference(h->cid,h);
+       }
+       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){
+               ms_error("Fail to build answer for call: err=%i",err);
+               return -1;
+       }
+       if (h->base.root->session_expires!=0){
+               if (h->supports_session_timers) osip_message_set_supported(msg, "timer");
+       }
+
+       if (contact) {
+               osip_list_special_free(&msg->contacts,(void (*)(void*))osip_contact_free);
+               osip_message_set_contact(msg,contact);
+       }
+       
+       if (h->base.local_media){
+               /*this is the case where we received an invite without SDP*/
+               if (h->sdp_offering) {
+                       set_sdp_from_desc(msg,h->base.local_media);
+               }else{
+                       if (h->sdp_answer)
+                               set_sdp(msg,h->sdp_answer);
+               }
+       }else{
+               ms_error("You are accepting a call but not defined any media capabilities !");
+       }
+       eXosip_call_send_answer(h->tid,200,msg);
+       return 0;
+}
+
+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_call_set_reference(h->cid,NULL);
+       eXosip_unlock();
+       return 0;
+}
+
+void sal_op_authenticate(SalOp *h, const SalAuthInfo *info){
+       if (h->pending_auth){
+               const char *userid;
+               if (info->userid==NULL || info->userid[0]=='\0') userid=info->username;
+               else userid=info->userid;
+               eXosip_add_authentication_info (info->username,userid,
+                                      info->password, NULL,info->realm);
+               eXosip_lock();
+               eXosip_default_action(h->pending_auth);
+               eXosip_unlock();
+               eXosip_clear_authentication_info();
+               eXosip_event_free(h->pending_auth);
+               sal_remove_pending_auth(sal_op_get_sal(h),h);
+               h->pending_auth=NULL;
+       }
+}
+
+static void inc_new_call(Sal *sal, eXosip_event_t *ev){
+       SalOp *op=sal_op_new(sal);
+       osip_from_t *from,*to;
+       char *tmp;
+       sdp_message_t *sdp=eXosip_get_sdp_info(ev->request);
+       if (sdp){
+               op->sdp_offering=FALSE;
+               op->base.remote_media=sal_media_description_new();
+               sdp_to_media_description(sdp,op->base.remote_media);
+               sdp_message_free(sdp);
+       }else op->sdp_offering=TRUE;
+
+       from=osip_message_get_from(ev->request);
+       to=osip_message_get_to(ev->request);
+       osip_from_to_str(from,&tmp);
+       sal_op_set_from(op,tmp);
+       osip_free(tmp);
+       osip_from_to_str(to,&tmp);
+       sal_op_set_to(op,tmp);
+       osip_free(tmp);
+       
+       op->tid=ev->tid;
+       op->cid=ev->cid;
+       op->did=ev->did;
+       
+       eXosip_call_set_reference(op->cid,op);
+       sal->callbacks.call_received(op);
+}
+
+static void handle_reinvite(Sal *sal,  eXosip_event_t *ev){
+       SalOp *op=(SalOp*)ev->external_reference;
+       sdp_message_t *sdp;
+       osip_message_t *msg=NULL;
+
+       if (op==NULL) {
+               ms_warning("Reinvite for non-existing operation !");
+               return;
+       }
+       op->reinvite=TRUE;
+       op->tid=ev->tid;
+       sdp=eXosip_get_sdp_info(ev->request);
+       if (op->base.remote_media){
+               sal_media_description_unref(op->base.remote_media);
+               op->base.remote_media=NULL;
+       }
+       eXosip_lock();
+       eXosip_call_build_answer(ev->tid,200,&msg);
+       eXosip_unlock();
+       if (msg==NULL) return;
+       if (op->base.root->session_expires!=0){
+               if (op->supports_session_timers) osip_message_set_supported(msg, "timer");
+       }
+       if (op->base.contact){
+               osip_list_special_free(&msg->contacts,(void (*)(void*))osip_contact_free);
+               osip_message_set_contact(msg,op->base.contact);
+       }
+       if (sdp){
+               op->sdp_offering=FALSE;
+               op->base.remote_media=sal_media_description_new();
+               sdp_to_media_description(sdp,op->base.remote_media);
+               sdp_message_free(sdp);
+               sdp_process(op);
+               set_sdp(msg,op->sdp_answer);
+       }else {
+               op->sdp_offering=TRUE;
+               set_sdp_from_desc(msg,op->base.local_media);
+       }
+       eXosip_lock();
+       eXosip_call_send_answer(ev->tid,200,msg);
+       eXosip_unlock();
+}
+
+static void handle_ack(Sal *sal,  eXosip_event_t *ev){
+       SalOp *op=(SalOp*)ev->external_reference;
+       sdp_message_t *sdp;
+
+       if (op==NULL) {
+               ms_warning("ack for non-existing call !");
+               return;
+       }
+       sdp=eXosip_get_sdp_info(ev->ack);
+       if (sdp){
+               op->base.remote_media=sal_media_description_new();
+               sdp_to_media_description(sdp,op->base.remote_media);
+               sdp_process(op);
+               sdp_message_free(sdp);
+       }
+       if (op->reinvite){
+               sal->callbacks.call_updated(op);
+               op->reinvite=FALSE;
+       }else{
+               sal->callbacks.call_ack(op);
+       }
+}
+
+static int call_proceeding(Sal *sal, eXosip_event_t *ev){
+       SalOp *op=(SalOp*)ev->external_reference;
+       if (op==NULL) {
+               ms_warning("This call has been canceled.");
+               eXosip_lock();
+               eXosip_call_terminate(ev->cid,ev->did);
+               eXosip_unlock();
+               return -1;
+       }
+       op->did=ev->did;
+       op->tid=ev->tid;
+       return 0;
+}
+
+static void call_ringing(Sal *sal, eXosip_event_t *ev){
+       sdp_message_t *sdp;
+       SalOp *op;
+       if (call_proceeding(sal, ev)==-1) return;
+       op=(SalOp*)ev->external_reference;
+       sdp=eXosip_get_sdp_info(ev->response);
+       if (sdp){
+               op->base.remote_media=sal_media_description_new();
+               sdp_to_media_description(sdp,op->base.remote_media);
+               sdp_message_free(sdp);
+               if (op->base.local_media) sdp_process(op);
+       }
+       sal->callbacks.call_ringing(op);
+}
+
+static void call_accepted(Sal *sal, eXosip_event_t *ev){
+       sdp_message_t *sdp;
+       osip_message_t *msg=NULL;
+       SalOp *op;
+       op=(SalOp*)ev->external_reference;
+       if (op==NULL){
+               ms_error("A closed call is accepted ?");
+               return;
+       }
+       sdp=eXosip_get_sdp_info(ev->response);
+       if (sdp){
+               op->base.remote_media=sal_media_description_new();
+               sdp_to_media_description(sdp,op->base.remote_media);
+               sdp_message_free(sdp);
+               if (op->base.local_media) sdp_process(op);
+       }
+       eXosip_call_build_ack(ev->did,&msg);
+       if (op->sdp_answer)
+                       set_sdp(msg,op->sdp_answer);
+       eXosip_call_send_ack(ev->did,msg);
+       sal->callbacks.call_accepted(op);
+}
+
+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);
+       op->cid=-1;
+       sal->callbacks.call_terminated(op,from);
+       osip_free(from);
+}
+
+static void call_released(Sal *sal, eXosip_event_t *ev){
+       SalOp *op;
+       op=(SalOp*)ev->external_reference;
+       if (op==NULL){
+               return;
+       }
+       op->cid=-1;
+       if (op->did==-1) 
+               sal->callbacks.call_failure(op,SalErrorNoResponse,SalReasonUnknown,NULL);
+}
+
+static int get_auth_data(eXosip_event_t *ev, const char **realm, const char **username){
+       const char *prx_realm=NULL,*www_realm=NULL;
+       osip_proxy_authenticate_t *prx_auth;
+       osip_www_authenticate_t *www_auth;
+       osip_message_t *resp=ev->response;
+       
+       *username=osip_uri_get_username(resp->from->url);
+       prx_auth=(osip_proxy_authenticate_t*)osip_list_get(&resp->proxy_authenticates,0);
+       www_auth=(osip_proxy_authenticate_t*)osip_list_get(&resp->www_authenticates,0);
+       if (prx_auth!=NULL)
+               prx_realm=osip_proxy_authenticate_get_realm(prx_auth);
+       if (www_auth!=NULL)
+               www_realm=osip_www_authenticate_get_realm(www_auth);
+
+       if (prx_realm){
+               *realm=prx_realm;
+       }else if (www_realm){
+               *realm=www_realm;
+       }else{
+               return -1;
+       }
+       return 0;
+}
+
+int sal_op_get_auth_requested(SalOp *op, const char **realm, const char **username){
+       if (op->pending_auth){
+               return get_auth_data(op->pending_auth,realm,username);
+       }
+       return -1;
+}
+
+static SalOp *find_op(Sal *sal, eXosip_event_t *ev){
+       if (ev->external_reference)
+               return (SalOp*)ev->external_reference;
+       if (ev->rid>0){
+               return sal_find_register(sal,ev->rid);
+       }
+       return NULL;
+}
+
+static bool_t process_authentication(Sal *sal, eXosip_event_t *ev){
+       SalOp *op;
+       const char *username,*realm;
+       op=find_op(sal,ev);
+       if (op==NULL){
+               ms_warning("No operation associated with this authentication !");
+               return TRUE;
+       }
+       if (get_auth_data(ev,&realm,&username)==0){
+               if (op->pending_auth!=NULL)
+                       eXosip_event_free(op->pending_auth);
+               op->pending_auth=ev;
+               sal_add_pending_auth (sal,op);
+               sal->callbacks.auth_requested(op,realm,username);
+               return FALSE;
+       }
+       return TRUE;
+}
+
+static void authentication_ok(Sal *sal, eXosip_event_t *ev){
+       SalOp *op;
+       const char *username,*realm;
+       op=find_op(sal,ev);
+       if (op==NULL){
+               ms_warning("No operation associated with this authentication_ok!");
+               return ;
+       }
+       if (get_auth_data(ev,&realm,&username)==0){
+               sal->callbacks.auth_success(op,realm,username);
+       }
+}
+
+static bool_t call_failure(Sal *sal, eXosip_event_t *ev){
+       SalOp *op;
+       int code=0;
+       const char *reason=NULL;
+       SalError error=SalErrorUnknown;
+       SalReason sr=SalReasonUnknown;
+       
+       op=(SalOp*)ev->external_reference;
+
+       if (op==NULL) {
+               ms_warning("Call failure reported for a closed call, ignored.");
+               return TRUE;
+       }
+
+       if (ev->response){
+               code=osip_message_get_status_code(ev->response);
+               reason=osip_message_get_reason_phrase(ev->response);
+       }
+       switch(code)
+       {
+               case 401:
+               case 407:
+                       return process_authentication(sal,ev);
+                       break;
+               case 400:
+                       error=SalErrorUnknown;
+               break;
+               case 404:
+                       error=SalErrorFailure;
+                       sr=SalReasonNotFound;
+               break;
+               case 415:
+                       error=SalErrorFailure;
+                       sr=SalReasonMedia;
+               break;
+               case 422:
+                       eXosip_default_action(ev);
+                       return TRUE;
+               break;
+               case 480:
+                       error=SalErrorFailure;
+                       sr=SalReasonTemporarilyUnavailable;
+               case 486:
+                       error=SalErrorFailure;
+                       sr=SalReasonBusy;
+               break;
+               case 487:
+               break;
+               case 600:
+                       error=SalErrorFailure;
+                       sr=SalReasonDoNotDisturb;
+               break;
+               case 603:
+                       error=SalErrorFailure;
+                       sr=SalReasonDeclined;
+               break;
+               default:
+                       if (code>0){
+                               error=SalErrorFailure;
+                               sr=SalReasonUnknown;
+                       }else error=SalErrorNoResponse;
+       }
+       if (code!=487) sal->callbacks.call_failure(op,error,sr,reason);
+       return TRUE;
+}
+
+
+static void process_media_control_xml(Sal *sal, eXosip_event_t *ev){
+       SalOp *op=(SalOp*)ev->external_reference;
+       osip_body_t *body=NULL;
+
+       if (op==NULL){
+               ms_warning("media control xml received without operation context!");
+               return ;
+       }
+       
+       osip_message_get_body(ev->request,0,&body);
+       if (body && body->body!=NULL &&
+               strstr(body->body,"picture_fast_update")){
+               osip_message_t *ans=NULL;
+               ms_message("Receiving VFU request !");
+               if (sal->callbacks.vfu_request){
+                       sal->callbacks.vfu_request(op);
+                       eXosip_call_build_answer(ev->tid,200,&ans);
+                       if (ans)
+                               eXosip_call_send_answer(ev->tid,200,ans);
+               }
+       }
+}
+
+static void process_dtmf_relay(Sal *sal, eXosip_event_t *ev){
+       SalOp *op=(SalOp*)ev->external_reference;
+       osip_body_t *body=NULL;
+
+       if (op==NULL){
+               ms_warning("media dtmf relay received without operation context!");
+               return ;
+       }
+       
+       osip_message_get_body(ev->request,0,&body);
+       if (body && body->body!=NULL){
+               osip_message_t *ans=NULL;
+               const char *name=strstr(body->body,"Signal");
+               if (name==NULL) name=strstr(body->body,"signal");
+               if (name==NULL) {
+                       ms_warning("Could not extract the dtmf name from the SIP INFO.");
+               }else{
+                       char tmp[2];
+                       name+=strlen("signal");
+                       if (sscanf(name," = %1s",tmp)==1){
+                               ms_message("Receiving dtmf %s via SIP INFO.",tmp);
+                               if (sal->callbacks.dtmf_received != NULL)
+                                       sal->callbacks.dtmf_received(op, tmp[0]);
+                       }
+               }
+               eXosip_call_build_answer(ev->tid,200,&ans);
+               if (ans)
+                       eXosip_call_send_answer(ev->tid,200,ans);
+       }
+}
+
+static void call_message_new(Sal *sal, eXosip_event_t *ev){
+       osip_message_t *ans=NULL;
+       if (ev->request){
+               if (MSG_IS_INFO(ev->request)){
+                       osip_content_type_t *ct;
+                       ct=osip_message_get_content_type(ev->request);
+                       if (ct && ct->subtype){
+                               if (strcmp(ct->subtype,"media_control+xml")==0)
+                                       process_media_control_xml(sal,ev);
+                               else if (strcmp(ct->subtype,"dtmf-relay")==0)
+                                       process_dtmf_relay(sal,ev);
+                               else {
+                                       ms_message("Unhandled SIP INFO.");
+                                       /*send an "Not implemented" answer*/
+                                       eXosip_lock();
+                                       eXosip_call_build_answer(ev->tid,501,&ans);
+                                       if (ans)
+                                               eXosip_call_send_answer(ev->tid,501,ans);
+                                       eXosip_unlock();
+                               }
+                       }else{
+                               /*empty SIP INFO, probably to test we are alive. Send an empty answer*/
+                               eXosip_lock();
+                               eXosip_call_build_answer(ev->tid,200,&ans);
+                               if (ans)
+                                       eXosip_call_send_answer(ev->tid,200,ans);
+                               eXosip_unlock();
+                       }
+               }
+       }else ms_warning("call_message_new: No request ?");
+}
+
+static void inc_update(Sal *sal, eXosip_event_t *ev){
+       osip_message_t *msg=NULL;
+       ms_message("Processing incoming UPDATE");
+       eXosip_lock();
+       eXosip_message_build_answer(ev->tid,200,&msg);
+       if (msg!=NULL)
+               eXosip_message_send_answer(ev->tid,200,msg);
+       eXosip_unlock();
+}
+
+static bool_t comes_from_local_if(osip_message_t *msg){
+       osip_via_t *via=NULL;
+       osip_message_get_via(msg,0,&via);
+       if (via){
+               const char *host;
+               host=osip_via_get_host(via);
+               if (strcmp(host,"127.0.0.1")==0 || strcmp(host,"::1")==0){
+                       osip_generic_param_t *param=NULL;
+                       osip_via_param_get_byname(via,"received",&param);
+                       if (param==NULL) return TRUE;
+                       if (param->gvalue &&
+                               (strcmp(param->gvalue,"127.0.0.1")==0 || strcmp(param->gvalue,"::1")==0)){
+                               return TRUE;
+                       }
+               }
+       }
+       return FALSE;
+}
+
+static void text_received(Sal *sal, eXosip_event_t *ev){
+       osip_body_t *body=NULL;
+       char *from=NULL,*msg;
+       
+       osip_message_get_body(ev->request,0,&body);
+       if (body==NULL){
+               ms_error("Could not get text message from SIP body");
+               return;
+       }
+       msg=body->body;
+       osip_from_to_str(ev->request->from,&from);
+       sal->callbacks.text_received(sal,from,msg);
+       osip_free(from);
+}
+
+static void other_request(Sal *sal, eXosip_event_t *ev){
+       ms_message("in other_request");
+       if (ev->request==NULL) return;
+       if (strcmp(ev->request->sip_method,"MESSAGE")==0){
+               text_received(sal,ev);
+               eXosip_message_send_answer(ev->tid,200,NULL);
+       }else if (strcmp(ev->request->sip_method,"OPTIONS")==0){
+               osip_message_t *options=NULL;
+               eXosip_options_build_answer(ev->tid,200,&options);
+               osip_message_set_allow(options,"INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, SUBSCRIBE, NOTIFY, INFO");
+               osip_message_set_accept(options,"application/sdp");
+               eXosip_options_send_answer(ev->tid,200,options);
+       }else if (strcmp(ev->request->sip_method,"WAKEUP")==0
+               && comes_from_local_if(ev->request)) {
+               eXosip_message_send_answer(ev->tid,200,NULL);
+               ms_message("Receiving WAKEUP request !");
+               sal->callbacks.internal_message(sal,"WAKEUP");
+       }else if (strncmp(ev->request->sip_method, "REFER", 5) == 0){
+               ms_message("Receiving REFER request !");
+               if (comes_from_local_if(ev->request)) {
+                       osip_header_t *h=NULL;
+                       osip_message_header_get_byname(ev->request,"Refer-To",0,&h);
+                       eXosip_message_send_answer(ev->tid,200,NULL);
+                       if (h){
+                               sal->callbacks.refer_received(sal,NULL,h->hvalue);
+                       }
+               }else ms_warning("Ignored REFER not coming from this local loopback interface.");
+       }else if (strncmp(ev->request->sip_method, "UPDATE", 6) == 0){
+               inc_update(sal,ev);
+    }else {
+               char *tmp=NULL;
+               size_t msglen=0;
+               osip_message_to_str(ev->request,&tmp,&msglen);
+               if (tmp){
+                       ms_message("Unsupported request received:\n%s",tmp);
+                       osip_free(tmp);
+               }
+               /*answer with a 501 Not implemented*/
+               eXosip_message_send_answer(ev->tid,501,NULL);
+       }
+}
+
+static bool_t register_again_with_updated_contact(SalOp *op, osip_message_t *orig_request, osip_message_t *last_answer){
+       osip_message_t *msg;
+       const char *rport,*received;
+       osip_via_t *via=NULL;
+       osip_generic_param_t *param=NULL;
+       osip_contact_t *ctt=NULL;
+       char *tmp;
+       
+       osip_message_get_via(last_answer,0,&via);
+       if (!via) return FALSE;
+       osip_via_param_get_byname(via,"rport",&param);
+       if (param) rport=param->gvalue;
+       else return FALSE;
+       param=NULL;
+       osip_via_param_get_byname(via,"received",&param);
+       if (param) received=param->gvalue;
+       else return FALSE;
+       osip_message_get_contact(orig_request,0,&ctt);
+       if (strcmp(ctt->url->host,received)==0){
+               /*ip address matches, check ports*/
+               const char *contact_port=ctt->url->port;
+               const char *via_rport=rport;
+               if (via_rport==NULL || strlen(via_rport)>0)
+                       via_rport="5060";
+               if (contact_port==NULL || strlen(contact_port)>0)
+                       contact_port="5060";
+               if (strcmp(contact_port,via_rport)==0){
+                       ms_message("Register has up to date contact, doing nothing.");
+                       return FALSE;
+               }else ms_message("ports do not match, need to update the register (%s <> %s)", contact_port,via_rport);
+       }
+       eXosip_lock();
+       msg=NULL;
+       eXosip_register_build_register(op->rid,op->expires,&msg);
+       if (msg==NULL){
+               eXosip_unlock();
+               ms_warning("Fail to create a contact updated register.");
+               return FALSE;
+       }
+       osip_message_get_contact(msg,0,&ctt);
+       if (ctt->url->host!=NULL){
+               osip_free(ctt->url->host);
+       }
+       ctt->url->host=osip_strdup(received);
+       if (ctt->url->port!=NULL){
+               osip_free(ctt->url->port);
+       }
+       ctt->url->port=osip_strdup(rport);
+       eXosip_register_send_register(op->rid,msg);
+       eXosip_unlock();
+       osip_contact_to_str(ctt,&tmp);
+       sal_op_set_contact(op,tmp);
+       ms_message("Resending new register with updated contact %s",tmp);
+       ms_free(tmp);
+       return TRUE;
+}
+
+static void registration_success(Sal *sal, eXosip_event_t *ev){
+       SalOp *op=sal_find_register(sal,ev->rid);
+       osip_header_t *h=NULL;
+       bool_t registered;
+       if (op==NULL){
+               ms_error("Receiving register response for unknown operation");
+               return;
+       }
+       osip_message_get_expires(ev->request,0,&h);
+       if (h!=NULL && atoi(h->hvalue)!=0){
+               registered=TRUE;
+               if (!register_again_with_updated_contact(op,ev->request,ev->response)){
+                       sal->callbacks.register_success(op,registered);
+               }
+       }else registered=FALSE;
+}
+
+static bool_t registration_failure(Sal *sal, eXosip_event_t *ev){
+       int status_code=0;
+       const char *reason=NULL;
+       SalOp *op=sal_find_register(sal,ev->rid);
+       SalReason sr=SalReasonUnknown;
+       SalError se=SalErrorUnknown;
+       
+       if (op==NULL){
+               ms_error("Receiving register failure for unknown operation");
+               return TRUE;
+       }
+       if (ev->response){
+               status_code=osip_message_get_status_code(ev->response);
+               reason=osip_message_get_reason_phrase(ev->response);
+       }else return TRUE;
+       switch(status_code){
+               case 401:
+               case 407:
+                       return process_authentication(sal,ev);
+                       break;
+               default:
+                       /* if contact is up to date, process the failure, otherwise resend a new register with
+                               updated contact first, just in case the faillure is due to incorrect contact */
+                       if (register_again_with_updated_contact(op,ev->request,ev->response))
+                               return TRUE; /*we are retrying with an updated contact*/
+                       if (status_code==403){
+                               se=SalErrorFailure;
+                               sr=SalReasonForbidden;
+                       }else if (status_code==0){
+                               se=SalErrorNoResponse;
+                       }
+                       sal->callbacks.register_failure(op,se,sr,reason);
+       }
+       return TRUE;
+}
+
+static bool_t process_event(Sal *sal, eXosip_event_t *ev){
+       switch(ev->type){
+               case EXOSIP_CALL_ANSWERED:
+                       ms_message("CALL_ANSWERED\n");
+                       call_accepted(sal,ev);
+                       authentication_ok(sal,ev);
+                       break;
+               case EXOSIP_CALL_CLOSED:
+               case EXOSIP_CALL_CANCELLED:
+                       ms_message("CALL_CLOSED or CANCELLED\n");
+                       call_terminated(sal,ev);
+                       break;
+               case EXOSIP_CALL_TIMEOUT:
+               case EXOSIP_CALL_NOANSWER:
+                       ms_message("CALL_TIMEOUT or NOANSWER\n");
+                       return call_failure(sal,ev);
+                       break;
+               case EXOSIP_CALL_REQUESTFAILURE:
+               case EXOSIP_CALL_GLOBALFAILURE:
+               case EXOSIP_CALL_SERVERFAILURE:
+                       ms_message("CALL_REQUESTFAILURE or GLOBALFAILURE or SERVERFAILURE\n");
+                       return call_failure(sal,ev);
+                       break;
+               case EXOSIP_CALL_INVITE:
+                       ms_message("CALL_NEW\n");
+                       inc_new_call(sal,ev);
+                       break;
+               case EXOSIP_CALL_REINVITE:
+                       handle_reinvite(sal,ev);
+                       break;
+               case EXOSIP_CALL_ACK:
+                       ms_message("CALL_ACK");
+                       handle_ack(sal,ev);
+                       break;
+               case EXOSIP_CALL_REDIRECTED:
+                       ms_message("CALL_REDIRECTED");
+                       eXosip_default_action(ev);
+                       break;
+               case EXOSIP_CALL_PROCEEDING:
+                       ms_message("CALL_PROCEEDING");
+                       call_proceeding(sal,ev);
+                       break;
+               case EXOSIP_CALL_RINGING:
+                       ms_message("CALL_RINGING");
+                       call_ringing(sal,ev);
+                       break;
+               case EXOSIP_CALL_MESSAGE_NEW:
+                       ms_message("EXOSIP_CALL_MESSAGE_NEW");
+                       call_message_new(sal,ev);
+                       break;
+               case EXOSIP_CALL_MESSAGE_REQUESTFAILURE:
+                       if (ev->did<0 && ev->response &&
+                               (ev->response->status_code==407 || ev->response->status_code==401)){
+                                return process_authentication(sal,ev);
+                       }
+                       break;
+               case EXOSIP_IN_SUBSCRIPTION_NEW:
+                       ms_message("CALL_SUBSCRIPTION_NEW ");
+                       sal_exosip_subscription_recv(sal,ev);
+                       break;
+               case EXOSIP_SUBSCRIPTION_UPDATE:
+                       ms_message("CALL_SUBSCRIPTION_UPDATE");
+                       break;
+               case EXOSIP_SUBSCRIPTION_NOTIFY:
+                       ms_message("CALL_SUBSCRIPTION_NOTIFY");
+                       sal_exosip_notify_recv(sal,ev);
+                       break;
+               case EXOSIP_SUBSCRIPTION_ANSWERED:
+                       ms_message("EXOSIP_SUBSCRIPTION_ANSWERED, ev->sid=%i\n",ev->sid);
+                       sal_exosip_subscription_answered(sal,ev);
+                       break;
+               case EXOSIP_SUBSCRIPTION_CLOSED:
+                       ms_message("EXOSIP_SUBSCRIPTION_CLOSED\n");
+                       sal_exosip_subscription_closed(sal,ev);
+                       break;
+               case EXOSIP_CALL_RELEASED:
+                       ms_message("CALL_RELEASED\n");
+                       call_released(sal, ev);
+                       break;
+               case EXOSIP_REGISTRATION_FAILURE:
+                       ms_message("REGISTRATION_FAILURE\n");
+                       return registration_failure(sal,ev);
+                       break;
+               case EXOSIP_REGISTRATION_SUCCESS:
+                       authentication_ok(sal,ev);
+                       registration_success(sal,ev);
+                       break;
+               case EXOSIP_MESSAGE_NEW:
+                       other_request(sal,ev);
+                       break;
+               case EXOSIP_MESSAGE_REQUESTFAILURE:
+                       if (ev->response && (ev->response->status_code == 407 || ev->response->status_code == 401)){
+                               return process_authentication(sal,ev);
+                       }
+                       break;
+               default:
+                       ms_message("Unhandled exosip event ! %i");
+                       break;
+       }
+       return TRUE;
+}
+
+int sal_iterate(Sal *sal){
+       eXosip_event_t *ev;
+       while((ev=eXosip_event_wait(0,0))!=NULL){
+               if (process_event(sal,ev))
+                       eXosip_event_free(ev);
+       }
+       eXosip_lock();
+       eXosip_automatic_refresh();
+       eXosip_unlock();
+       return 0;
+}
+
+int sal_register(SalOp *h, const char *proxy, const char *from, int expires){
+       osip_message_t *msg;
+       sal_op_set_route(h,proxy);
+       if (h->rid==-1){
+               eXosip_lock();
+               h->rid=eXosip_register_build_initial_register(from,proxy,sal_op_get_contact(h),expires,&msg);
+               sal_add_register(h->base.root,h);
+       }else{
+               eXosip_lock();
+               eXosip_register_build_register(h->rid,expires,&msg);    
+       }
+       eXosip_register_send_register(h->rid,msg);
+       eXosip_unlock();
+       h->expires=expires;
+       return 0;
+}
+
+int sal_unregister(SalOp *h){
+       osip_message_t *msg=NULL;
+       eXosip_lock();
+       eXosip_register_build_register(h->rid,0,&msg);
+       if (msg) eXosip_register_send_register(h->rid,msg);
+       else ms_warning("Could not build unREGISTER !");
+       eXosip_unlock();
+       return 0;
+}
+
+
+
+SalAddress * sal_address_new(const char *uri){
+       osip_from_t *from;
+       osip_from_init(&from);
+       if (osip_from_parse(from,uri)!=0){
+               osip_from_free(from);
+               return NULL;
+       }
+       return (SalAddress*)from;
+}
+
+SalAddress * sal_address_clone(const SalAddress *addr){
+       osip_from_t *ret=NULL;
+       osip_from_clone((osip_from_t*)addr,&ret);
+       return (SalAddress*)ret;
+}
+
+#define null_if_empty(s) (((s)!=NULL && (s)[0]!='\0') ? (s) : NULL )
+
+const char *sal_address_get_scheme(const SalAddress *addr){
+       const osip_from_t *u=(const osip_from_t*)addr;
+       return null_if_empty(u->url->scheme);
+}
+
+const char *sal_address_get_display_name(const SalAddress* addr){
+       const osip_from_t *u=(const osip_from_t*)addr;
+       return null_if_empty(u->displayname);
+}
+
+const char *sal_address_get_username(const SalAddress *addr){
+       const osip_from_t *u=(const osip_from_t*)addr;
+       return null_if_empty(u->url->username);
+}
+
+const char *sal_address_get_domain(const SalAddress *addr){
+       const osip_from_t *u=(const osip_from_t*)addr;
+       return null_if_empty(u->url->host);
+}
+
+void sal_address_set_display_name(SalAddress *addr, const char *display_name){
+       osip_from_t *u=(osip_from_t*)addr;
+       if (u->displayname!=NULL){
+               osip_free(u->displayname);
+               u->displayname=NULL;
+       }
+       if (display_name!=NULL)
+               u->displayname=osip_strdup(display_name);
+}
+
+void sal_address_set_username(SalAddress *addr, const char *username){
+       osip_from_t *uri=(osip_from_t*)addr;
+       if (uri->url->username!=NULL){
+               osip_free(uri->url->username);
+               uri->url->username=NULL;
+       }
+       if (username)
+               uri->url->username=osip_strdup(username);
+}
+
+void sal_address_set_domain(SalAddress *addr, const char *host){
+       osip_from_t *uri=(osip_from_t*)addr;
+       if (uri->url->host!=NULL){
+               osip_free(uri->url->host);
+               uri->url->host=NULL;
+       }
+       if (host)
+               uri->url->host=osip_strdup(host);
+}
+
+void sal_address_set_port(SalAddress *addr, const char *port){
+       osip_from_t *uri=(osip_from_t*)addr;
+       if (uri->url->port!=NULL){
+               osip_free(uri->url->port);
+               uri->url->port=NULL;
+       }
+       if (port)
+               uri->url->port=osip_strdup(port);
+}
+
+void sal_address_set_port_int(SalAddress *uri, int port){
+       char tmp[12];
+       if (port==5060){
+               /*this is the default, special case to leave the port field blank*/
+               sal_address_set_port(uri,NULL);
+               return;
+       }
+       snprintf(tmp,sizeof(tmp),"%i",port);
+       sal_address_set_port(uri,tmp);
+}
+
+void sal_address_clean(SalAddress *addr){
+       osip_generic_param_freelist(& ((osip_from_t*)addr)->gen_params);
+}
+
+char *sal_address_as_string(const SalAddress *u){
+       char *tmp,*ret;
+       osip_from_to_str((osip_from_t*)u,&tmp);
+       ret=ms_strdup(tmp);
+       osip_free(tmp);
+       return ret;
+}
+
+char *sal_address_as_string_uri_only(const SalAddress *u){
+       char *tmp=NULL,*ret;
+       osip_uri_to_str(((osip_from_t*)u)->url,&tmp);
+       ret=ms_strdup(tmp);
+       osip_free(tmp);
+       return ret;
+}
+
+void sal_address_destroy(SalAddress *u){
+       osip_from_free((osip_from_t*)u);
+}
+
diff --git a/coreapi/sal_eXosip2.h b/coreapi/sal_eXosip2.h
new file mode 100644 (file)
index 0000000..4e5d812
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+linphone
+Copyright (C) 2010  Simon MORLAT (simon.morlat@free.fr)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+#ifndef sal_exosip2_h
+#define sal_exosip2_h
+
+#include "sal.h"
+#include <eXosip2/eXosip.h>
+
+
+
+sdp_message_t *media_description_to_sdp(const SalMediaDescription *sal);
+int sdp_to_media_description(sdp_message_t *sdp, SalMediaDescription *desc);
+
+struct Sal{
+       SalCallbacks callbacks;
+       MSList *registers;/*MSList of SalOp */
+       MSList *out_subscribes;/*MSList of SalOp */
+       MSList *in_subscribes;/*MSList of SalOp */
+       MSList *pending_auths;/*MSList of SalOp */
+       int running;
+       int session_expires;
+       void *up;
+};
+
+struct SalOp{
+       SalOpBase base;
+       int cid;
+       int did;
+       int tid;
+       int rid;
+       int sid;
+       int nid;
+       int expires;
+       SalMediaDescription *result;
+       sdp_message_t *sdp_answer;
+       eXosip_event_t *pending_auth;
+       bool_t supports_session_timers;
+       bool_t sdp_offering;
+       bool_t reinvite;
+};
+
+void sal_exosip_subscription_recv(Sal *sal, eXosip_event_t *ev);
+void sal_exosip_subscription_answered(Sal *sal,eXosip_event_t *ev);
+void sal_exosip_notify_recv(Sal *sal,eXosip_event_t *ev);
+void sal_exosip_subscription_closed(Sal *sal,eXosip_event_t *ev);
+
+void sal_exosip_fix_route(SalOp *op);
+
+
+#endif
diff --git a/coreapi/sal_eXosip2_presence.c b/coreapi/sal_eXosip2_presence.c
new file mode 100644 (file)
index 0000000..d4ab7ba
--- /dev/null
@@ -0,0 +1,690 @@
+/*
+linphone
+Copyright (C) 2010  Simon MORLAT (simon.morlat@free.fr)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+
+#include "sal_eXosip2.h"
+
+
+static SalOp * sal_find_out_subscribe(Sal *sal, int sid){
+       const MSList *elem;
+       SalOp *op;
+       for(elem=sal->out_subscribes;elem!=NULL;elem=elem->next){
+               op=(SalOp*)elem->data;
+               if (op->sid==sid) return op;
+       }
+       return NULL;
+}
+
+static void sal_add_out_subscribe(Sal *sal, SalOp *op){
+       sal->out_subscribes=ms_list_append(sal->out_subscribes,op);
+}
+
+static void sal_remove_out_subscribe(Sal *sal, int sid){
+       MSList *elem;
+       SalOp *op;
+       for(elem=sal->out_subscribes;elem!=NULL;elem=elem->next){
+               op=(SalOp*)elem->data;
+               if (op->sid==sid) {
+                       sal->out_subscribes=ms_list_remove_link(sal->out_subscribes,elem);
+                       return;
+               }
+       }
+}
+
+static SalOp * sal_find_in_subscribe(Sal *sal, int nid){
+       const MSList *elem;
+       SalOp *op;
+       for(elem=sal->in_subscribes;elem!=NULL;elem=elem->next){
+               op=(SalOp*)elem->data;
+               if (op->nid==nid) return op;
+       }
+       return NULL;
+}
+
+static void sal_add_in_subscribe(Sal *sal, SalOp *op){
+       sal->in_subscribes=ms_list_append(sal->in_subscribes,op);
+}
+
+static void sal_remove_in_subscribe(Sal *sal, int nid){
+       MSList *elem;
+       SalOp *op;
+       for(elem=sal->in_subscribes;elem!=NULL;elem=elem->next){
+               op=(SalOp*)elem->data;
+               if (op->nid==nid) {
+                       sal->in_subscribes=ms_list_remove_link(sal->in_subscribes,elem);
+                       return;
+               }
+       }
+}
+
+int sal_text_send(SalOp *op, const char *from, const char *to, const char *msg){
+       osip_message_t *sip=NULL;
+       if (from)
+               sal_op_set_from(op,from);
+       if (to)
+               sal_op_set_to(op,to);
+
+       eXosip_lock();
+       eXosip_message_build_request(&sip,"MESSAGE",sal_op_get_to(op),
+           sal_op_get_from(op),sal_op_get_route(op));
+       osip_message_set_content_type(sip,"text/plain");
+       osip_message_set_body(sip,msg,strlen(msg));
+       eXosip_message_send_request(sip);
+       eXosip_unlock();
+       return 0;
+}
+
+/*presence Subscribe/notify*/
+int sal_subscribe_presence(SalOp *op, const char *from, const char *to){
+       osip_message_t *msg;
+       if (from)
+               sal_op_set_from(op,from);
+       if (to)
+               sal_op_set_to(op,to);
+       sal_exosip_fix_route(op);
+       eXosip_lock();
+       eXosip_subscribe_build_initial_request(&msg,sal_op_get_to(op),sal_op_get_from(op),
+               sal_op_get_route(op),"presence",600);
+       op->sid=eXosip_subscribe_send_initial_request(msg);
+       eXosip_unlock();
+       if (op->sid==-1){
+               osip_message_free(msg);
+               return -1;
+       }
+       sal_add_out_subscribe(op->base.root,op);
+       return 0;
+}
+
+int sal_unsubscribe(SalOp *op){
+       osip_message_t *msg=NULL;
+       if (op->did==-1){
+               ms_error("cannot unsubscribe, no dialog !");
+               return -1;
+       }
+       eXosip_lock();
+       eXosip_subscribe_build_refresh_request(op->did,&msg);
+       if (msg){
+               osip_message_set_expires(msg,"0");
+               eXosip_subscribe_send_refresh_request(op->did,msg);
+       }else ms_error("Could not build subscribe refresh request !");
+       eXosip_unlock();
+       return 0;
+}
+
+int sal_subscribe_accept(SalOp *op){
+       osip_message_t *msg;
+       eXosip_lock();
+       eXosip_insubscription_build_answer(op->tid,202,&msg);
+       eXosip_insubscription_send_answer(op->tid,202,msg);
+       eXosip_unlock();
+       return 0;
+}
+
+int sal_subscribe_decline(SalOp *op){
+       eXosip_lock();
+       eXosip_insubscription_send_answer(op->tid,401,NULL);
+       eXosip_unlock();
+       return 0;
+}
+
+static void add_presence_body(osip_message_t *notify, SalPresenceStatus online_status)
+{
+       char buf[1000];
+#ifdef SUPPORT_MSN
+       int atom_id = 1000;
+#endif
+       char *contact_info;
+
+       osip_contact_t *ct=NULL;
+       osip_message_get_contact(notify,0,&ct);
+       osip_contact_to_str(ct,&contact_info);
+
+#ifdef SUPPORT_MSN
+
+  if (online_status==SalPresenceOnline)
+    {
+      sprintf(buf, "<?xml version=\"1.0\"?>\n\
+<!DOCTYPE presence\n\
+PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
+<presence>\n\
+<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
+<atom id=\"%i\">\n\
+<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
+<status status=\"open\" />\n\
+<msnsubstatus substatus=\"online\" />\n\
+</address>\n\
+</atom>\n\
+</presence>", contact_info, atom_id, contact_info);
+
+    }
+  else if (online_status==SalPresenceBusy)
+    {
+      sprintf(buf, "<?xml version=\"1.0\"?>\n\
+<!DOCTYPE presence\n\
+PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
+<presence>\n\
+<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
+<atom id=\"%i\">\n\
+<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
+<status status=\"inuse\" />\n\
+<msnsubstatus substatus=\"busy\" />\n\
+</address>\n\
+</atom>\n\
+</presence>", contact_info, atom_id, contact_info);
+
+    }
+  else if (online_status==SalPresenceBerightback)
+    {
+      sprintf(buf, "<?xml version=\"1.0\"?>\n\
+<!DOCTYPE presence\n\
+PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
+<presence>\n\
+<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
+<atom id=\"%i\">\n\
+<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
+<status status=\"inactive\" />\n\
+<msnsubstatus substatus=\"berightback\" />\n\
+</address>\n\
+</atom>\n\
+</presence>", contact_info, atom_id, contact_info);
+
+    }
+  else if (online_status==SalPresenceAway)
+    {
+      sprintf(buf, "<?xml version=\"1.0\"?>\n\
+<!DOCTYPE presence\n\
+PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
+<presence>\n\
+<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
+<atom id=\"%i\">\n\
+<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
+<status status=\"inactive\" />\n\
+<msnsubstatus substatus=\"away\" />\n\
+</address>\n\
+</atom>\n\
+</presence>", contact_info, atom_id, contact_info);
+
+    }
+  else if (online_status==SalPresenceOnthephone)
+    {
+      sprintf(buf, "<?xml version=\"1.0\"?>\n\
+<!DOCTYPE presence\n\
+PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
+<presence>\n\
+<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
+<atom id=\"%i\">\n\
+<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
+<status status=\"inuse\" />\n\
+<msnsubstatus substatus=\"onthephone\" />\n\
+</address>\n\
+</atom>\n\
+</presence>", contact_info, atom_id, contact_info);
+
+    }
+  else if (online_status==SalPresenceOuttolunch)
+    {
+      sprintf(buf, "<?xml version=\"1.0\"?>\n\
+<!DOCTYPE presence\n\
+PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
+<presence>\n\
+<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
+<atom id=\"%i\">\n\
+<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
+<status status=\"inactive\" />\n\
+<msnsubstatus substatus=\"outtolunch\" />\n\
+</address>\n\
+</atom>\n\
+</presence>", contact_info, atom_id, contact_info);
+
+    }
+  else
+    {
+      sprintf(buf, "<?xml version=\"1.0\"?>\n\
+<!DOCTYPE presence\n\
+PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
+<presence>\n\
+<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
+<atom id=\"%i\">\n\
+<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
+<status status=\"inactive\" />\n\
+<msnsubstatus substatus=\"away\" />\n\
+</address>\n\
+</atom>\n\
+</presence>", contact_info, atom_id, contact_info);
+    }
+
+  osip_message_set_body(notify, buf, strlen(buf));
+  osip_message_set_content_type(notify, "application/xpidf+xml");
+#else
+
+  if (online_status==SalPresenceOnline)
+    {
+      sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
+<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
+          entity=\"%s\">\n\
+<tuple id=\"sg89ae\">\n\
+<status>\n\
+<basic>open</basic>\n\
+</status>\n\
+<contact priority=\"0.8\">%s</contact>\n\
+<note>online</note>\n\
+</tuple>\n\
+</presence>",
+             contact_info, contact_info);
+    }
+  else if (online_status==SalPresenceBusy)
+    {
+      sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
+<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
+          xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
+          entity=\"%s\">\n\
+<tuple id=\"sg89ae\">\n\
+<status>\n\
+<basic>open</basic>\n\
+<es:activities>\n\
+  <es:activity>busy</es:activity>\n\
+</es:activities>\n\
+</status>\n\
+<contact priority=\"0.8\">%s</contact>\n\
+<note>busy</note>\n\
+</tuple>\n\
+</presence>",
+             contact_info, contact_info);
+    }
+  else if (online_status==SalPresenceBerightback)
+    {
+      sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
+<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
+          xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
+          entity=\"%s\">\n\
+<tuple id=\"sg89ae\">\n\
+<status>\n\
+<basic>open</basic>\n\
+<es:activities>\n\
+  <es:activity>in-transit</es:activity>\n\
+</es:activities>\n\
+</status>\n\
+<contact priority=\"0.8\">%s</contact>\n\
+<note>be right back</note>\n\
+</tuple>\n\
+</presence>",
+             contact_info, contact_info);
+    }
+  else if (online_status==SalPresenceAway)
+    {
+      sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
+<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
+          xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
+          entity=\"%s\">\n\
+<tuple id=\"sg89ae\">\n\
+<status>\n\
+<basic>open</basic>\n\
+<es:activities>\n\
+  <es:activity>away</es:activity>\n\
+</es:activities>\n\
+</status>\n\
+<contact priority=\"0.8\">%s</contact>\n\
+<note>away</note>\n\
+</tuple>\n\
+</presence>",
+             contact_info, contact_info);
+    }
+  else if (online_status==SalPresenceOnthephone)
+    {
+      sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
+<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
+          xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
+          entity=\"%s\">\n\
+<tuple id=\"sg89ae\">\n\
+<status>\n\
+<basic>open</basic>\n\
+<es:activities>\n\
+  <es:activity>on-the-phone</es:activity>\n\
+</es:activities>\n\
+</status>\n\
+<contact priority=\"0.8\">%s</contact>\n\
+<note>on the phone</note>\n\
+</tuple>\n\
+</presence>",
+             contact_info, contact_info);
+    }
+  else if (online_status==SalPresenceOuttolunch)
+    {
+      sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
+<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
+          xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
+          entity=\"%s\">\n\
+<tuple id=\"sg89ae\">\n\
+<status>\n\
+<basic>open</basic>\n\
+<es:activities>\n\
+  <es:activity>meal</es:activity>\n\
+</es:activities>\n\
+</status>\n\
+<contact priority=\"0.8\">%s</contact>\n\
+<note>out to lunch</note>\n\
+</tuple>\n\
+</presence>",
+             contact_info, contact_info);
+    }
+  else
+    {
+      /* */
+      sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
+<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
+xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
+entity=\"%s\">\n%s",
+             contact_info,
+"<tuple id=\"sg89ae\">\n\
+<status>\n\
+<basic>closed</basic>\n\
+<es:activities>\n\
+  <es:activity>permanent-absence</es:activity>\n\
+</es:activities>\n\
+</status>\n\
+</tuple>\n\
+\n</presence>\n");
+    }
+  osip_message_set_body(notify, buf, strlen(buf));
+  osip_message_set_content_type(notify, "application/pidf+xml");
+
+#endif
+       osip_free(contact_info);
+}
+
+
+int sal_notify_presence(SalOp *op, SalPresenceStatus status, const char *status_message){
+       osip_message_t *msg;
+       eXosip_ss_t ss=EXOSIP_SUBCRSTATE_ACTIVE;
+       if (op->nid==-1){
+               ms_warning("Cannot notify, subscription was closed.");
+               return -1;
+       }
+       
+       eXosip_lock();
+       eXosip_insubscription_build_notify(op->did,ss,DEACTIVATED,&msg);
+       if (msg!=NULL){
+               const char *identity=sal_op_get_contact(op);
+               if (identity==NULL) identity=sal_op_get_to(op);
+               osip_message_set_contact(msg,identity);
+               add_presence_body(msg,status);
+               eXosip_insubscription_send_request(op->did,msg);
+       }else ms_error("could not create notify for incoming subscription.");
+       eXosip_unlock();
+       return 0;
+}
+
+int sal_notify_close(SalOp *op){
+       osip_message_t *msg;
+       eXosip_lock();
+       eXosip_insubscription_build_notify(op->did,EXOSIP_SUBCRSTATE_TERMINATED,DEACTIVATED,&msg);
+       if (msg!=NULL){
+               const char *identity=sal_op_get_contact(op);
+               if (identity==NULL) identity=sal_op_get_to(op);
+               osip_message_set_contact(msg,identity);
+               eXosip_insubscription_send_request(op->did,msg);
+       }else ms_error("could not create notify for incoming subscription.");
+       eXosip_unlock();
+       return 0;
+}
+
+int sal_publish(SalOp *op, const char *from, const char *to, SalPresenceStatus presence_mode){
+       osip_message_t *pub;
+       int i;
+       char buf[1024];
+
+       if (presence_mode==SalPresenceOnline)
+       {
+         snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
+       <presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
+                 entity=\"%s\">\n\
+       <tuple id=\"sg89ae\">\n\
+       <status>\n\
+       <basic>open</basic>\n\
+       </status>\n\
+       <contact priority=\"0.8\">%s</contact>\n\
+       <note>online</note>\n\
+       </tuple>\n\
+       </presence>",
+                  from, from);
+       }
+       else if (presence_mode==SalPresenceBusy
+          ||presence_mode==SalPresenceDonotdisturb)
+       {
+         snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
+       <presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
+                 xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
+                 entity=\"%s\">\n\
+       <tuple id=\"sg89ae\">\n\
+       <status>\n\
+       <basic>open</basic>\n\
+       <es:activities>\n\
+       <es:activity>busy</es:activity>\n\
+       </es:activities>\n\
+       </status>\n\
+       <contact priority=\"0.8\">%s</contact>\n\
+       <note>busy</note>\n\
+       </tuple>\n\
+       </presence>",
+                 from, from);
+       }
+       else if (presence_mode==SalPresenceBerightback)
+       {
+               snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
+       <presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
+                 xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
+                 entity=\"%s\">\n\
+       <tuple id=\"sg89ae\">\n\
+       <status>\n\
+       <basic>open</basic>\n\
+       <es:activities>\n\
+       <es:activity>in-transit</es:activity>\n\
+       </es:activities>\n\
+       </status>\n\
+       <contact priority=\"0.8\">%s</contact>\n\
+       <note>be right back</note>\n\
+       </tuple>\n\
+       </presence>",
+                 from,from);
+       }
+       else if (presence_mode==SalPresenceAway
+          ||presence_mode==SalPresenceMoved)
+       {
+               snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
+       <presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
+                 xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
+                 entity=\"%s\">\n\
+       <tuple id=\"sg89ae\">\n\
+       <status>\n\
+       <basic>open</basic>\n\
+       <es:activities>\n\
+       <es:activity>away</es:activity>\n\
+       </es:activities>\n\
+       </status>\n\
+       <contact priority=\"0.8\">%s</contact>\n\
+       <note>away</note>\n\
+       </tuple>\n\
+       </presence>",
+                 from, from);
+       }
+       else if (presence_mode==SalPresenceOnthephone)
+       {
+         snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
+       <presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
+                 xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
+                 entity=\"%s\">\n\
+       <tuple id=\"sg89ae\">\n\
+       <status>\n\
+       <basic>open</basic>\n\
+       <es:activities>\n\
+       <es:activity>on-the-phone</es:activity>\n\
+       </es:activities>\n\
+       </status>\n\
+       <contact priority=\"0.8\">%s</contact>\n\
+       <note>on the phone</note>\n\
+       </tuple>\n\
+       </presence>",
+                 from, from);
+       }
+       else if (presence_mode==SalPresenceOuttolunch)
+       {
+         snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
+       <presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
+                 xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
+                 entity=\"%s\">\n\
+       <tuple id=\"sg89ae\">\n\
+       <status>\n\
+       <basic>open</basic>\n\
+       <es:activities>\n\
+       <es:activity>meal</es:activity>\n\
+       </es:activities>\n\
+       </status>\n\
+       <contact priority=\"0.8\">%s</contact>\n\
+       <note>out to lunch</note>\n\
+       </tuple>\n\
+       </presence>",
+                 from, from);
+       }
+       else{ 
+         /* offline */
+         snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
+       <presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
+       xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
+       entity=\"%s\">\n%s",
+                 from,
+       "<tuple id=\"sg89ae\">\n\
+       <status>\n\
+       <basic>closed</basic>\n\
+       <es:activities>\n\
+       <es:activity>permanent-absence</e:activity>\n\
+       </es:activities>\n\
+       </status>\n\
+       </tuple>\n\
+       \n</presence>\n");
+       }
+
+       i = eXosip_build_publish(&pub,from, to, NULL, "presence", "1800", "application/pidf+xml", buf);
+       if (i<0){
+               ms_warning("Failed to build publish request.");
+               return -1;
+       }
+
+       eXosip_lock();
+       i = eXosip_publish(pub, to); /* should update the sip-if-match parameter
+                                   from sip-etag  from last 200ok of PUBLISH */
+       eXosip_unlock();
+       if (i<0){
+         ms_message("Failed to send publish request.");
+         return -1;
+       }
+       return 0;
+}
+
+void sal_exosip_subscription_recv(Sal *sal, eXosip_event_t *ev){
+       SalOp *op=sal_op_new(sal);
+       char *tmp;
+       op->did=ev->did;
+       op->tid=ev->tid;
+       op->nid=ev->nid;
+       osip_from_to_str(ev->request->from,&tmp);
+       sal_op_set_from(op,tmp);
+       ms_free(tmp);
+       osip_from_to_str(ev->request->to,&tmp);
+       sal_op_set_to(op,tmp);
+       ms_free(tmp);
+       sal_add_in_subscribe(sal,op);
+       sal->callbacks.subscribe_received(op,sal_op_get_from(op));
+}
+
+void sal_exosip_notify_recv(Sal *sal, eXosip_event_t *ev){
+       SalOp *op=sal_find_out_subscribe(sal,ev->sid);
+       char *tmp;
+       osip_from_t *from=NULL;
+       osip_body_t *body=NULL;
+       SalPresenceStatus estatus=SalPresenceOffline;
+       
+       ms_message("Receiving notify with sid=%i,nid=%i",ev->sid,ev->nid);
+
+       if (op==NULL){
+               ms_error("No operation related to this notify !");
+               return;
+       }
+       if (ev->request==NULL) return;
+
+       from=ev->request->from;
+       osip_message_get_body(ev->request,0,&body);
+       if (body==NULL){
+               ms_error("No body in NOTIFY");
+               return;
+       }
+       osip_from_to_str(from,&tmp);
+       if (strstr(body->body,"pending")!=NULL){
+               estatus=SalPresenceOffline;
+       }else if ((strstr(body->body,"online")!=NULL) || (strstr(body->body,"open")!=NULL)) {
+               estatus=SalPresenceOnline;
+       }else if (strstr(body->body,"busy")!=NULL){
+               estatus=SalPresenceBusy;
+       }else if (strstr(body->body,"berightback")!=NULL
+                       || strstr(body->body,"in-transit")!=NULL ){
+               estatus=SalPresenceBerightback;
+       }else if (strstr(body->body,"away")!=NULL){
+               estatus=SalPresenceAway;
+       }else if (strstr(body->body,"onthephone")!=NULL
+               || strstr(body->body,"on-the-phone")!=NULL){
+               estatus=SalPresenceOnthephone;
+       }else if (strstr(body->body,"outtolunch")!=NULL
+                       || strstr(body->body,"meal")!=NULL){
+               estatus=SalPresenceOuttolunch;
+       }else if (strstr(body->body,"closed")!=NULL){
+               estatus=SalPresenceOffline;
+       }else{
+               estatus=SalPresenceOffline;
+       }
+       ms_message("We are notified that %s has online status %i",tmp,estatus);
+       if (ev->ss_status==EXOSIP_SUBCRSTATE_TERMINATED) {
+               sal_remove_out_subscribe(sal,op->sid);
+               op->sid=-1;
+               op->did=-1;
+               ms_message("And outgoing subscription terminated by remote.");
+       }
+       sal->callbacks.notify(op,op->sid!=-1 ? SalSubscribeActive : SalSubscribeTerminated, estatus,NULL);
+       osip_free(tmp);
+}
+
+void sal_exosip_subscription_answered(Sal *sal,eXosip_event_t *ev){
+       SalOp *op=sal_find_out_subscribe(sal,ev->sid);
+       if (op==NULL){
+               ms_error("Subscription answered but no associated op !");
+               return;
+       }
+       op->did=ev->did;
+}
+
+void sal_exosip_subscription_closed(Sal *sal,eXosip_event_t *ev){
+       SalOp *op=sal_find_in_subscribe(sal,ev->sid);
+       if (op==NULL){
+               ms_error("Subscription closed but no associated op !");
+               return;
+       }
+       sal_remove_in_subscribe(sal,op->nid);
+       op->nid=-1;
+       op->did=0;
+}
+
+
diff --git a/coreapi/sal_eXosip2_sdp.c b/coreapi/sal_eXosip2_sdp.c
new file mode 100644 (file)
index 0000000..c1a1761
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+linphone
+Copyright (C) 2010  Simon MORLAT (simon.morlat@free.fr)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+
+#include "ortp/b64.h"
+#include "sal.h"
+#include <eXosip2/eXosip.h>
+
+#define keywordcmp(key,b) strncmp(key,b,sizeof(key))
+
+#ifdef FOR_LATER
+
+static char *make_relay_session_id(const char *username, const char *relay){
+       /*ideally this should be a hash of the parameters with a random part*/
+       char tmp[128];
+       int s1=(int)random();
+       int s2=(int)random();
+       long long int res=((long long int)s1)<<32 | (long long int) s2;
+       void *src=&res;
+       b64_encode(src, sizeof(long long int), tmp, sizeof(tmp));
+       return osip_strdup(tmp);
+}
+
+
+static void add_relay_info(sdp_message_t *sdp, int mline, const char *relay, const char *relay_session_id){
+
+       if (relay) sdp_message_a_attribute_add(sdp, mline,
+                                    osip_strdup ("relay-addr"),osip_strdup(relay));
+       if (relay_session_id) sdp_message_a_attribute_add(sdp, mline,
+                                    osip_strdup ("relay-session-id"), osip_strdup(relay_session_id));
+}
+
+#endif
+
+static char * int_2char(int a){
+       char *p=osip_malloc(16);
+       snprintf(p,16,"%i",a);
+       return p;
+}
+
+/* return the value of attr "field" for payload pt at line pos (field=rtpmap,fmtp...)*/
+static const char *sdp_message_a_attr_value_get_with_pt(sdp_message_t *sdp,int pos,int pt,const char *field)
+{
+       int i,tmppt=0,scanned=0;
+       char *tmp;
+       sdp_attribute_t *attr;
+       for (i=0;(attr=sdp_message_attribute_get(sdp,pos,i))!=NULL;i++){
+               if (keywordcmp(field,attr->a_att_field)==0 && attr->a_att_value!=NULL){
+                       int nb = sscanf(attr->a_att_value,"%i %n",&tmppt,&scanned);
+                       /* the return value may depend on how %n is interpreted by the libc: see manpage*/
+                       if (nb == 1 || nb==2 ){
+                               if (pt==tmppt){
+                                       tmp=attr->a_att_value+scanned;
+                                       if (strlen(tmp)>0)
+                                               return tmp;
+                               }
+                       }else ms_warning("sdp has a strange a= line (%s) nb=%i",attr->a_att_value,nb);
+               }
+       }
+       return NULL;
+}
+
+#ifdef FOR_LATER
+/* return the value of attr "field" */
+static const char *sdp_message_a_attr_value_get(sdp_message_t *sdp,int pos,const char *field)
+{
+       int i;
+       sdp_attribute_t *attr;
+       for (i=0;(attr=sdp_message_attribute_get(sdp,pos,i))!=NULL;i++){
+               if (keywordcmp(field,attr->a_att_field)==0 && attr->a_att_value!=NULL){
+                       return attr->a_att_value;
+               }
+       }
+       return NULL;
+}
+#endif
+
+static int _sdp_message_get_a_ptime(sdp_message_t *sdp, int mline){
+       int i,ret;
+       sdp_attribute_t *attr;
+       for (i=0;(attr=sdp_message_attribute_get(sdp,mline,i))!=NULL;i++){
+               if (keywordcmp("ptime",attr->a_att_field)==0){
+                       int nb = sscanf(attr->a_att_value,"%i",&ret);
+                       /* the return value may depend on how %n is interpreted by the libc: see manpage*/
+                       if (nb == 1){
+                               return ret;
+                       }else ms_warning("sdp has a strange a=ptime line (%s) ",attr->a_att_value);
+               }
+       }
+       return 0;
+}
+
+static sdp_message_t *create_generic_sdp(const SalMediaDescription *desc)
+{
+       sdp_message_t *local;
+       int inet6;
+
+       sdp_message_init (&local);
+       if (strchr(desc->addr,':')!=NULL){
+               inet6=1;
+       }else inet6=0;
+       sdp_message_v_version_set (local, osip_strdup ("0"));
+       sdp_message_o_origin_set (local, osip_strdup (desc->username),
+                         osip_strdup ("123456"), osip_strdup ("654321"),
+                         osip_strdup ("IN"), inet6 ? osip_strdup("IP6") : osip_strdup ("IP4"),
+                         osip_strdup (desc->addr));
+       sdp_message_s_name_set (local, osip_strdup ("A conversation"));
+       sdp_message_c_connection_add (local, -1,
+                             osip_strdup ("IN"), inet6 ? osip_strdup ("IP6") : osip_strdup ("IP4"),
+                             osip_strdup (desc->addr), NULL, NULL);
+       sdp_message_t_time_descr_add (local, osip_strdup ("0"), osip_strdup ("0"));
+       return local;
+}
+
+
+
+static void add_payload(sdp_message_t *msg, int line, const PayloadType *pt)
+{
+       char attr[256];
+       sdp_message_m_payload_add (msg,line, int_2char (payload_type_get_number(pt)));
+       if (pt->channels>0)
+               snprintf (attr,sizeof(attr),"%i %s/%i/%i", payload_type_get_number(pt), 
+                       pt->mime_type, pt->clock_rate,pt->channels);
+       else
+               snprintf (attr,sizeof(attr),"%i %s/%i", payload_type_get_number(pt), 
+                       pt->mime_type, pt->clock_rate);
+       sdp_message_a_attribute_add (msg, line,
+                                    osip_strdup ("rtpmap"), osip_strdup(attr));
+
+       if (pt->recv_fmtp != NULL)
+       {
+               snprintf (attr,sizeof(attr),"%i %s", payload_type_get_number(pt),pt->recv_fmtp);
+               sdp_message_a_attribute_add (msg, line, osip_strdup ("fmtp"),
+                                    osip_strdup(attr));
+       }
+}
+
+
+static void add_line(sdp_message_t *msg, int lineno, const SalStreamDescription *desc){
+       const char *mt=desc->type==SalAudio ? "audio" : "video";
+       const MSList *elem;
+       const char *addr;
+       int port;
+       if (desc->candidates[0].addr[0]!='\0'){
+               addr=desc->candidates[0].addr;
+               port=desc->candidates[0].port;
+       }else{
+               addr=desc->addr;
+               port=desc->port;
+       }
+       /*only add a c= line within the stream description if address are differents*/
+       if (strcmp(addr,sdp_message_c_addr_get(msg, -1, 0))!=0){
+               bool_t inet6;
+               if (strchr(addr,':')!=NULL){
+                       inet6=TRUE;
+               }else inet6=FALSE;
+               sdp_message_c_connection_add (msg, lineno,
+                             osip_strdup ("IN"), inet6 ? osip_strdup ("IP6") : osip_strdup ("IP4"),
+                             osip_strdup (addr), NULL, NULL);
+       }
+       sdp_message_m_media_add (msg, osip_strdup (mt),
+                                int_2char (port), NULL,
+                                osip_strdup ("RTP/AVP"));
+       if (desc->bandwidth>0) sdp_message_b_bandwidth_add (msg, lineno, osip_strdup ("AS"),
+                                    int_2char(desc->bandwidth));
+       for(elem=desc->payloads;elem!=NULL;elem=elem->next){
+               add_payload(msg, lineno, (PayloadType*)elem->data);
+       }
+}
+
+sdp_message_t *media_description_to_sdp(const SalMediaDescription *desc){
+       int i;
+       sdp_message_t *msg=create_generic_sdp(desc);
+       for(i=0;i<desc->nstreams;++i){
+               add_line(msg,i,&desc->streams[i]);
+       }
+       return msg;
+}
+
+static int payload_type_fill_from_rtpmap(PayloadType *pt, const char *rtpmap){
+       if (rtpmap==NULL){
+               PayloadType *refpt=rtp_profile_get_payload(&av_profile,payload_type_get_number(pt));
+               if (refpt){
+                       pt->mime_type=ms_strdup(refpt->mime_type);
+                       pt->clock_rate=refpt->clock_rate;
+               }else{
+                       ms_error("payload number %i has no rtpmap and is unknown in AV Profile, ignored.",
+                           payload_type_get_number(pt));
+                       return -1;
+               }
+       }else{
+               char *mime=ms_strdup(rtpmap);
+               char *p=strchr(mime,'/');
+               if (p){
+                       char *chans;
+                       *p='\0';
+                       p++;
+                       chans=strchr(p,'/');
+                       if (chans){
+                               *chans='\0';
+                               chans++;
+                               pt->channels=atoi(chans);
+                       }else pt->channels=1;
+                       pt->clock_rate=atoi(p);
+               }
+               pt->mime_type=mime;
+       }
+       return 0;
+}
+
+int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
+       int i,j;
+       const char *mtype,*proto,*port,*addr,*number;
+       sdp_bandwidth_t *sbw=NULL;
+       
+       addr=sdp_message_c_addr_get (msg, -1, 0);
+       if (addr)
+               strncpy(desc->addr,addr,sizeof(desc->addr));
+       /* for each m= line */
+       for (i=0; !sdp_message_endof_media (msg, i) && i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++)
+       {
+               SalStreamDescription *stream=&desc->streams[i];
+               
+               memset(stream,0,sizeof(*stream));
+               mtype = sdp_message_m_media_get(msg, i);
+               proto = sdp_message_m_proto_get (msg, i);
+               port = sdp_message_m_port_get(msg, i);
+               stream->proto=SalProtoUnknown;
+               if (proto){
+                       if (strcasecmp(proto,"RTP/AVP")==0)
+                               stream->proto=SalProtoRtpAvp;
+                       else if (strcasecmp(proto,"RTP/SAVP")==0){
+                               stream->proto=SalProtoRtpSavp;
+                       }
+               }
+               addr = sdp_message_c_addr_get (msg, i, 0);
+               if (addr != NULL)
+                       strncpy(stream->addr,addr,sizeof(stream->addr));
+               if (port)
+                       stream->port=atoi(port);
+               
+               stream->ptime=_sdp_message_get_a_ptime(msg,i);
+               if (strcasecmp("audio", mtype) == 0){
+                       stream->type=SalAudio;
+               }else if (strcasecmp("video", mtype) == 0){
+                       stream->type=SalVideo;
+               }else stream->type=SalOther;
+               for(j=0;(sbw=sdp_message_bandwidth_get(msg,i,j))!=NULL;++j){
+                       if (strcasecmp(sbw->b_bwtype,"AS")==0) stream->bandwidth=atoi(sbw->b_bandwidth);
+               }
+               /* for each payload type */
+               for (j=0;((number=sdp_message_m_payload_get (msg, i,j)) != NULL); j++){
+                       const char *rtpmap,*fmtp;
+                       int ptn=atoi(number);
+                       PayloadType *pt=payload_type_new();
+                       payload_type_set_number(pt,ptn);
+                       /* get the rtpmap associated to this codec, if any */
+                       rtpmap=sdp_message_a_attr_value_get_with_pt(msg, i,ptn,"rtpmap");
+                       payload_type_fill_from_rtpmap(pt,rtpmap);
+                       /* get the fmtp, if any */
+                       fmtp=sdp_message_a_attr_value_get_with_pt(msg, i, ptn,"fmtp");
+                       payload_type_set_send_fmtp(pt,fmtp);
+                       stream->payloads=ms_list_append(stream->payloads,pt);
+                       ms_message("Found payload %s/%i fmtp=%s",pt->mime_type,pt->clock_rate,
+                           pt->send_fmtp ? pt->send_fmtp : "");
+               }
+       }
+       desc->nstreams=i;
+       return 0;
+}
index 528e3f3286ea5050c7d986f2a27a1d41a8e22b14..0037fa1d6d7fa9b72a5436454273e1bfdf04e36d 100644 (file)
@@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #endif
 
 #include "linphonecore.h"
+#include "private.h"
 #include <ctype.h>
 
 static void sip_login_init_instance(SipSetupContext *ctx){
index 035a1079d5801888bdc69dd0d3d56c8b3d987f92..25173488de28fcec917b4097538a50ed3752003c 100644 (file)
@@ -39,7 +39,6 @@ typedef struct _status_picture_tab_t{
 } status_picture_tab_t;
 
 status_picture_tab_t status_picture_tab[]={
-       {       LINPHONE_STATUS_UNKNOWN,        "sip-closed.png"        },
        {       LINPHONE_STATUS_ONLINE,         "sip-online.png"        },
        {       LINPHONE_STATUS_BUSY,           "sip-busy.png"          },
        {       LINPHONE_STATUS_BERIGHTBACK,    "sip-bifm.png"          },
@@ -51,7 +50,6 @@ status_picture_tab_t status_picture_tab[]={
        {       LINPHONE_STATUS_ALT_SERVICE,    "sip-closed.png"        },
        {       LINPHONE_STATUS_OFFLINE,        "sip-away.png"          },
        {       LINPHONE_STATUS_PENDING,        "sip-wfa.png"           },
-       {       LINPHONE_STATUS_CLOSED,         "sip-closed.png"        },
        {       LINPHONE_STATUS_END,            NULL                    },
 };
 
@@ -104,7 +102,7 @@ static void linphone_gtk_set_selection_to_uri_bar(GtkTreeView *treeview){
        if (gtk_tree_selection_get_selected (select, &model, &iter))
        {
                gtk_tree_model_get (model, &iter,FRIEND_ID , &lf, -1);
-               friend=linphone_address_as_string(linphone_friend_get_uri(lf));
+               friend=linphone_address_as_string(linphone_friend_get_address(lf));
                gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar")),friend);
                ms_free(friend);
        }
@@ -134,8 +132,7 @@ static GtkWidget * create_presence_menu(){
        GdkPixbuf *pbuf;
        status_picture_tab_t *t;
        for(t=status_picture_tab;t->img!=NULL;++t){
-               if (t->status==LINPHONE_STATUS_UNKNOWN ||
-                       t->status==LINPHONE_STATUS_PENDING){
+               if (t->status==LINPHONE_STATUS_PENDING){
                        continue;
                }
                menu_item=gtk_image_menu_item_new_with_label(linphone_online_status_to_string(t->status));
@@ -309,7 +306,7 @@ void linphone_gtk_show_friends(void){
 
        for(itf=linphone_core_get_friend_list(core);itf!=NULL;itf=ms_list_next(itf)){
                LinphoneFriend *lf=(LinphoneFriend*)itf->data;
-               const LinphoneAddress *f_uri=linphone_friend_get_uri(lf);
+               const LinphoneAddress *f_uri=linphone_friend_get_address(lf);
                char *uri=linphone_address_as_string(f_uri);
                const char *name=linphone_address_get_display_name(f_uri);
                const char *display=name;
@@ -376,7 +373,7 @@ void linphone_gtk_show_contact(LinphoneFriend *lf){
        GtkWidget *w=linphone_gtk_create_window("contact");
        char *uri;
        const char *name;
-       const LinphoneAddress *f_uri=linphone_friend_get_uri(lf);
+       const LinphoneAddress *f_uri=linphone_friend_get_address(lf);
        uri=linphone_address_as_string_uri_only(f_uri);
        name=linphone_address_get_display_name(f_uri);
        if (uri) {
@@ -419,7 +416,7 @@ void linphone_gtk_chat_selected(GtkWidget *item){
        {
                char *uri;
                gtk_tree_model_get (model, &iter,FRIEND_ID , &lf, -1);
-               uri=linphone_address_as_string(linphone_friend_get_uri(lf));
+               uri=linphone_address_as_string(linphone_friend_get_address(lf));
                linphone_gtk_create_chatroom(uri);
                ms_free(uri);
        }
index 5864375f2eb6e5cd6295a0ffe551d72757957051..9bdf1dc0ea5da35e983c36b5e836949eddd78349 100644 (file)
@@ -163,7 +163,7 @@ static void linphone_gtk_log_file(OrtpLogLevel lev, const char *msg)
 
        /* lc->config will turn NULL at exit, close the file to flush and
         return to stop logging */
-       if (lc->config == NULL) {
+       if (linphone_core_get_config(lc) == NULL) {
                linphone_gtk_log_uninit();
                return;
        }
index c6f310b4e24a2199823e7d4ca6c57ae5825f1edd..5b9d7f5c44cb7b57a03d400d3f1252dc78c76fd8 100644 (file)
@@ -60,6 +60,7 @@ void linphone_gtk_show_login_frame(LinphoneProxyConfig *cfg){
        LinphoneAddress *from;
        LinphoneCore *lc=linphone_gtk_get_core();
        int nettype;
+       const char *passwd=NULL;
 
 
        if (linphone_core_get_download_bandwidth(lc)==512 &&
@@ -91,8 +92,9 @@ void linphone_gtk_show_login_frame(LinphoneProxyConfig *cfg){
        if (linphone_address_get_username(from)[0]!='?')
                gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(mw,"login_username")),
                        linphone_address_get_username(from));
+       if (ai) passwd=linphone_auth_info_get_passwd(ai);
        gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(mw,"login_password")),
-               ai!=NULL ? ai->passwd : "");
+               passwd!=NULL ? passwd : "");
        
        linphone_address_destroy(from);
 }
index 75b454c26bceccea2333fcb4ef2130927a1c1739..e492d821ae897691868d6aba47b7a5e1947fd0a5 100644 (file)
@@ -42,7 +42,7 @@ static GtkWidget *the_ui=NULL;
 static void linphone_gtk_show(LinphoneCore *lc);
 static void linphone_gtk_inv_recv(LinphoneCore *lc, const char *from);
 static void linphone_gtk_bye_recv(LinphoneCore *lc, const char *from);
-static void linphone_gtk_notify_recv(LinphoneCore *lc, LinphoneFriend * fid, const char *url, const char *status, const char *img);
+static void linphone_gtk_notify_recv(LinphoneCore *lc, LinphoneFriend * fid);
 static void linphone_gtk_new_unknown_subscriber(LinphoneCore *lc, LinphoneFriend *lf, const char *url);
 static void linphone_gtk_auth_info_requested(LinphoneCore *lc, const char *realm, const char *username);
 static void linphone_gtk_display_status(LinphoneCore *lc, const char *status);
@@ -762,7 +762,7 @@ static void linphone_gtk_bye_recv(LinphoneCore *lc, const char *from){
        
 }
 
-static void linphone_gtk_notify_recv(LinphoneCore *lc, LinphoneFriend * fid, const char *url, const char *status, const char *img){
+static void linphone_gtk_notify_recv(LinphoneCore *lc, LinphoneFriend * fid){
 }
 
 static void linphone_gtk_new_subscriber_response(GtkWidget *dialog, guint response_id, LinphoneFriend *lf){
index cbc7b5c7398e63ab2f305a2605bc61eb5443ef34..09af0709e94df3c61512b30d3fb82ce43a0a209e 100644 (file)
@@ -295,7 +295,7 @@ static void linphone_gtk_show_codecs(GtkTreeView *listview, const MSList *codecl
                gchar *color;
                const char *params="";
                struct _PayloadType *pt=(struct _PayloadType *)elem->data;
-               if (payload_type_enabled(pt)) status=_("Enabled");
+               if (linphone_core_payload_type_enabled(linphone_gtk_get_core(),pt)) status=_("Enabled");
                else status=_("Disabled");
                if (linphone_core_check_payload_type_usability(linphone_gtk_get_core(),pt)) color="blue";
                else color="red";
@@ -311,7 +311,7 @@ static void linphone_gtk_show_codecs(GtkTreeView *listview, const MSList *codecl
                                        CODEC_PARAMS,params,
                                        CODEC_PRIVDATA,(gpointer)pt,
                                        CODEC_COLOR,(gpointer)color,
-                                       CODEC_INFO,(gpointer)payload_type_get_description(pt),
+                                       CODEC_INFO,(gpointer)linphone_core_get_payload_type_description(linphone_gtk_get_core(),pt),
                                        -1);
        }
        
@@ -433,7 +433,7 @@ static void linphone_gtk_codec_set_enable(GtkWidget *button, gboolean enabled){
        if (gtk_tree_selection_get_selected(sel,&mod,&iter)){
                store=GTK_LIST_STORE(mod);
                gtk_tree_model_get(mod,&iter,CODEC_PRIVDATA,&pt,-1);
-               payload_type_set_enable(pt,enabled);
+               linphone_core_enable_payload_type(linphone_gtk_get_core(),pt,enabled);
                gtk_list_store_set(store,&iter,CODEC_STATUS, enabled ? _("Enabled") : _("Disabled"), -1);
        }
 }