From 3b6eceaad48d5adc40e1693a2e82fea715cd18f3 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Fri, 6 Nov 2015 11:06:35 +0100 Subject: [PATCH 01/30] Add the LinphoneFriendList object. --- coreapi/CMakeLists.txt | 2 + coreapi/Makefile.am | 2 + coreapi/friendlist.c | 111 +++++++++++++++++++++++++++++++++ coreapi/friendlist.h | 136 +++++++++++++++++++++++++++++++++++++++++ coreapi/private.h | 13 ++++ 5 files changed, 264 insertions(+) create mode 100644 coreapi/friendlist.c create mode 100644 coreapi/friendlist.h diff --git a/coreapi/CMakeLists.txt b/coreapi/CMakeLists.txt index 2f2d59712..1acb41227 100644 --- a/coreapi/CMakeLists.txt +++ b/coreapi/CMakeLists.txt @@ -37,6 +37,7 @@ set(LINPHONE_HEADER_FILES call_params.h content.h event.h + friendlist.h linphonecore.h linphonecore_utils.h linphonefriend.h @@ -82,6 +83,7 @@ set(LINPHONE_SOURCE_FILES_C enum.h event.c friend.c + friendlist.c info.c ldap/ldapprovider.c lime.c diff --git a/coreapi/Makefile.am b/coreapi/Makefile.am index 02c7f442d..6f777c228 100644 --- a/coreapi/Makefile.am +++ b/coreapi/Makefile.am @@ -31,6 +31,7 @@ linphone_include_HEADERS=\ call_params.h \ content.h \ event.h \ + friendlist.h \ linphonecore.h \ linphonecore_utils.h \ linphonefriend.h \ @@ -63,6 +64,7 @@ liblinphone_la_SOURCES=\ enum.c enum.h \ event.c \ friend.c \ + friendlist.c \ info.c \ ldap/ldapprovider.c ldap/ldapprovider.h \ linphonecall.c \ diff --git a/coreapi/friendlist.c b/coreapi/friendlist.c new file mode 100644 index 000000000..b221717fb --- /dev/null +++ b/coreapi/friendlist.c @@ -0,0 +1,111 @@ +/* +linphone +Copyright (C) 2010-2015 Belledonne Communications SARL + +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 "linphonecore.h" +#include "private.h" + + + +static void linphone_friend_list_destroy(LinphoneFriendList *list) { + if (list->display_name != NULL) ms_free(list->display_name); + if (list->rls_uri != NULL) ms_free(list->rls_uri); +} + +BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneFriendList); + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneFriendList, belle_sip_object_t, + (belle_sip_object_destroy_t)linphone_friend_list_destroy, + NULL, // clone + NULL, // marshal + TRUE +); + + +LinphoneFriendList * linphone_friend_list_new(void) { + LinphoneFriendList *list = belle_sip_object_new(LinphoneFriendList); + belle_sip_object_ref(list); + return list; +} + +LinphoneFriendList * linphone_friend_list_ref(LinphoneFriendList *list) { + belle_sip_object_ref(list); + return list; +} + +void linphone_friend_list_unref(LinphoneFriendList *list) { + belle_sip_object_unref(list); +} + +void * linphone_friend_list_get_user_data(const LinphoneFriendList *list) { + return list->user_data; +} + +void linphone_friend_list_set_user_data(LinphoneFriendList *list, void *ud) { + list->user_data = ud; +} + +const char * linphone_friend_list_get_display_name(const LinphoneFriendList *list) { + return list->display_name; +} + +void linphone_friend_list_set_display_name(LinphoneFriendList *list, const char *display_name) { + if (list->display_name != NULL) { + ms_free(list->display_name); + list->display_name = NULL; + } + if (display_name != NULL) { + list->display_name = ms_strdup(display_name); + } +} + +const char * linphone_friend_list_get_rls_uri(const LinphoneFriendList *list) { + return list->rls_uri; +} + +void linphone_friend_list_set_rls_uri(LinphoneFriendList *list, const char *rls_uri) { + if (list->rls_uri != NULL) { + ms_free(list->rls_uri); + list->rls_uri = NULL; + } + if (rls_uri != NULL) { + list->rls_uri = ms_strdup(rls_uri); + } +} + +LinphoneFriendListStatus linphone_friend_list_add_friend(LinphoneFriendList *list, LinphoneFriend *friend) { + if ((friend->lc != NULL) || (friend->uri == NULL)) return LinphoneFriendListInvalidFriend; + if (ms_list_find(list->friends, friend) != NULL) { + char *tmp = NULL; + const LinphoneAddress *addr = linphone_friend_get_address(friend); + if (addr) tmp = linphone_address_as_string(addr); + ms_warning("Friend %s already in list [%s], ignored.", tmp ? tmp : "unknown", list->display_name); + if (tmp) ms_free(tmp); + } else { + list->friends = ms_list_append(list->friends, linphone_friend_ref(friend)); + } + return LinphoneFriendListOK; +} + +LinphoneFriendListStatus linphone_friend_list_remove_friend(LinphoneFriendList *list, LinphoneFriend *friend) { + MSList *el = ms_list_find(list->friends, friend); + if (el == NULL) return LinphoneFriendListNonExistentFriend; + linphone_friend_unref((LinphoneFriend *)el->data); + list->friends = ms_list_remove_link(list->friends, el); + return LinphoneFriendListOK; +} diff --git a/coreapi/friendlist.h b/coreapi/friendlist.h new file mode 100644 index 000000000..1d01bce39 --- /dev/null +++ b/coreapi/friendlist.h @@ -0,0 +1,136 @@ +/* +friendlist.h +Copyright (C) 2010-2015 Belledonne Communications SARL + +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 LINPHONE_FRIENDLIST_H_ +#define LINPHONE_FRIENDLIST_H_ + + +#include "linphonefriend.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup buddy_list + * @{ + */ + +/** +* Enum describing the status of a LinphoneFriendList operation. +**/ +typedef enum _LinphoneFriendListStatus { + LinphoneFriendListOK, + LinphoneFriendListNonExistentFriend, + LinphoneFriendListInvalidFriend +} LinphoneFriendListStatus; + +/** + * The LinphoneFriendList object representing a list of friends. +**/ +typedef struct _LinphoneFriendList LinphoneFriendList; + +/** + * Create a new empty LinphoneFriendList object. + * @return A new LinphoneFriendList object. + */ +LINPHONE_PUBLIC LinphoneFriendList * linphone_friend_list_new(void); + +/** + * Acquire a reference to the friend list. + * @param[in] list LinphoneFriendList object. + * @return The same LinphoneFriendList object. +**/ +LINPHONE_PUBLIC LinphoneFriendList * linphone_friend_list_ref(LinphoneFriendList *list); + +/** + * Release reference to the friend list. + * @param[in] list LinphoneFriendList object. +**/ +LINPHONE_PUBLIC void linphone_friend_list_unref(LinphoneFriendList *list); + +/** + * Retrieve the user pointer associated with the friend list. + * @param[in] list LinphoneFriendList object. + * @return The user pointer associated with the friend list. +**/ +LINPHONE_PUBLIC void * linphone_friend_list_get_user_data(const LinphoneFriendList *list); + +/** + * Assign a user pointer to the friend list. + * @param[in] list LinphoneFriendList object. + * @param[in] ud The user pointer to associate with the friend list. +**/ +LINPHONE_PUBLIC void linphone_friend_list_set_user_data(LinphoneFriendList *list, void *ud); + +/** + * Get the display name of the friend list. + * @param[in] list LinphoneFriendList object. + * @return The display name of the friend list. +**/ +LINPHONE_PUBLIC const char * linphone_friend_list_get_display_name(const LinphoneFriendList *list); + +/** + * Set the display name of the friend list. + * @param[in] list LinphoneFriendList object. + * @param[in] display_name The new display name of the friend list. +**/ +LINPHONE_PUBLIC void linphone_friend_list_set_display_name(LinphoneFriendList *list, const char *display_name); + +/** + * Get the RLS (Resource List Server) URI associated with the friend list to subscribe to these friends presence. + * @param[in] list LinphoneFriendList object. + * @return The RLS URI associated with the friend list. +**/ +LINPHONE_PUBLIC const char * linphone_friend_list_get_rls_uri(const LinphoneFriendList *list); + +/** + * Set the RLS (Resource List Server) URI associated with the friend list to subscribe to these friends presence. + * @param[in] list LinphoneFriendList object. + * @param[in] rls_uri The RLS URI to associate with the friend list. +**/ +LINPHONE_PUBLIC void linphone_friend_list_set_rls_uri(LinphoneFriendList *list, const char *rls_uri); + +/** + * Add a friend to a friend list. + * @param[in] list LinphoneFriendList object. + * @param[in] friend LinphoneFriend object to add to the friend list. + * @return LinphoneFriendListOK if successfully added, LinphoneFriendListInvalidFriend if the friend is not valid. +**/ +LINPHONE_PUBLIC LinphoneFriendListStatus linphone_friend_list_add_friend(LinphoneFriendList *list, LinphoneFriend *friend); + +/** + * Remove a friend from a friend list. + * @param[in] list LinphoneFriendList object. + * @param[in] friend LinphoneFriend object to remove from the friend list. + * @return LinphoneFriendListOK if removed successfully, LinphoneFriendListNonExistentFriend if the friend is not in the list. +**/ +LINPHONE_PUBLIC LinphoneFriendListStatus linphone_friend_list_remove_friend(LinphoneFriendList *list, LinphoneFriend *friend); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* LINPHONE_FRIENDLIST_H_ */ diff --git a/coreapi/private.h b/coreapi/private.h index 84d26357e..078ed768b 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -30,6 +30,7 @@ extern "C" { #endif #include "linphonecore.h" #include "linphonefriend.h" +#include "friendlist.h" #include "linphone_tunnel.h" #include "linphonecore_utils.h" #include "sal/sal.h" @@ -648,6 +649,17 @@ struct _LinphoneFriend{ BELLE_SIP_DECLARE_VPTR(LinphoneFriend); +struct _LinphoneFriendList { + belle_sip_object_t base; + void *user_data; + char *display_name; + char *rls_uri; + MSList *friends; +}; + +BELLE_SIP_DECLARE_VPTR(LinphoneFriendList); + + typedef struct sip_config { char *contact; @@ -1278,6 +1290,7 @@ BELLE_SIP_TYPE_ID(LinphoneLDAPContactProvider), BELLE_SIP_TYPE_ID(LinphoneLDAPContactSearch), BELLE_SIP_TYPE_ID(LinphoneProxyConfig), BELLE_SIP_TYPE_ID(LinphoneFriend), +BELLE_SIP_TYPE_ID(LinphoneFriendList), BELLE_SIP_TYPE_ID(LinphoneXmlRpcRequest), BELLE_SIP_TYPE_ID(LinphoneXmlRpcRequestCbs), BELLE_SIP_TYPE_ID(LinphoneXmlRpcSession), From 89aa523d7167e5292277afdee0b4f8aae34e5cda Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Mon, 9 Nov 2015 15:10:11 +0100 Subject: [PATCH 02/30] Use LinphoneFriendList object for the list of friends of a LinphoneCore. --- coreapi/friend.c | 97 ++++++++---------------------------------- coreapi/friendlist.c | 85 ++++++++++++++++++++++++++++++++++-- coreapi/friendlist.h | 15 +++++++ coreapi/linphonecore.c | 12 +++--- coreapi/presence.c | 25 ++++++----- coreapi/private.h | 7 +-- 6 files changed, 135 insertions(+), 106 deletions(-) diff --git a/coreapi/friend.c b/coreapi/friend.c index 487cfd2a4..01990400a 100644 --- a/coreapi/friend.c +++ b/coreapi/friend.c @@ -88,25 +88,6 @@ MSList *linphone_find_friend_by_address(MSList *fl, const LinphoneAddress *addr, return res; } -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 (ms_list_find(lf->insubs, op)) return lf; - } - return NULL; -} - -LinphoneFriend *linphone_find_friend_by_out_subscribe(MSList *l, SalOp *op){ - MSList *elem; - LinphoneFriend *lf; - for (elem=l;elem!=NULL;elem=elem->next){ - lf=(LinphoneFriend*)elem->data; - if (lf->outsub && (lf->outsub == op || sal_op_is_forked_of(lf->outsub, op))) return lf; - } - return NULL; -} - void __linphone_friend_do_subscribe(LinphoneFriend *fr){ LinphoneCore *lc=fr->lc; @@ -259,7 +240,7 @@ static void linphone_friend_unsubscribe(LinphoneFriend *lf){ } } -static void linphone_friend_invalidate_subscription(LinphoneFriend *lf){ +void linphone_friend_invalidate_subscription(LinphoneFriend *lf){ if (lf->outsub!=NULL) { LinphoneCore *lc=lf->lc; sal_op_release(lf->outsub); @@ -491,47 +472,27 @@ LinphoneFriend * linphone_core_create_friend_with_address(LinphoneCore *lc, cons return linphone_friend_new_with_address(address); } -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,linphone_friend_ref(lf)); - if (ms_list_find(lc->subscribers, lf)){ +void linphone_core_add_friend(LinphoneCore *lc, LinphoneFriend *lf) { + if (linphone_friend_list_add_friend(lc->friendlist, lf) != LinphoneFriendListOK) return; + if (ms_list_find(lc->subscribers, lf)) { /*if this friend was in the pending subscriber list, now remove it from this list*/ lc->subscribers = ms_list_remove(lc->subscribers, lf); linphone_friend_unref(lf); } - lf->lc=lc; - if ( linphone_core_ready(lc)) linphone_friend_apply(lf,lc); - else lf->commit=TRUE; - return ; + lf->lc = lc; + if (linphone_core_ready(lc)) linphone_friend_apply(lf, lc); + else lf->commit = TRUE; } -void linphone_core_remove_friend(LinphoneCore *lc, LinphoneFriend* fl){ - MSList *el=ms_list_find(lc->friends,fl); - if (el!=NULL){ - linphone_friend_unref((LinphoneFriend*)el->data); - lc->friends=ms_list_remove_link(lc->friends,el); - linphone_core_write_friends_config(lc); - }else{ - ms_error("linphone_core_remove_friend(): friend [%p] is not part of core's list.",fl); +void linphone_core_remove_friend(LinphoneCore *lc, LinphoneFriend *lf) { + if (linphone_friend_list_remove_friend(lc->friendlist, lf) == LinphoneFriendListNonExistentFriend) { + ms_error("linphone_core_remove_friend(): friend [%p] is not part of core's list.", lf); } } void linphone_core_update_friends_subscriptions(LinphoneCore *lc, LinphoneProxyConfig *cfg, bool_t only_when_registered){ - const MSList *elem; - for(elem=lc->friends;elem!=NULL;elem=elem->next){ - LinphoneFriend *f=(LinphoneFriend*)elem->data; - linphone_friend_update_subscribes(f,cfg,only_when_registered); - } + if (lc->friendlist != NULL) + linphone_friend_list_update_subscriptions(lc->friendlist, cfg, only_when_registered); } bool_t linphone_core_should_subscribe_friends_only_when_registered(const LinphoneCore *lc){ @@ -545,11 +506,8 @@ void linphone_core_send_initial_subscribes(LinphoneCore *lc){ } void linphone_core_invalidate_friend_subscriptions(LinphoneCore *lc){ - const MSList *elem; - for(elem=lc->friends;elem!=NULL;elem=elem->next){ - LinphoneFriend *f=(LinphoneFriend*)elem->data; - linphone_friend_invalidate_subscription(f); - } + if (lc->friendlist != NULL) + linphone_friend_list_invalidate_subscriptions(lc->friendlist); lc->initial_subscribes_sent=FALSE; } @@ -569,34 +527,15 @@ const char *linphone_friend_get_ref_key(const LinphoneFriend *lf){ } LinphoneFriend *linphone_core_find_friend(const LinphoneCore *lc, const LinphoneAddress *addr){ - LinphoneFriend *lf=NULL; - MSList *elem; - for(elem=lc->friends;elem!=NULL;elem=ms_list_next(elem)){ - lf=(LinphoneFriend*)elem->data; - if (linphone_address_weak_equal(lf->uri,addr)) - break; - lf=NULL; - } - return lf; + return linphone_friend_list_find_friend_by_address(lc->friendlist, addr); } LinphoneFriend *linphone_core_get_friend_by_address(const LinphoneCore *lc, const char *uri){ - LinphoneAddress *puri=linphone_address_new(uri); - LinphoneFriend *lf=puri ? linphone_core_find_friend(lc,puri) : NULL; - if (puri) linphone_address_unref(puri); - return lf; + return linphone_friend_list_find_friend_by_uri(lc->friendlist, uri); } LinphoneFriend *linphone_core_get_friend_by_ref_key(const LinphoneCore *lc, const char *key){ - const MSList *elem; - if (key==NULL) return NULL; - for(elem=linphone_core_get_friend_list(lc);elem!=NULL;elem=elem->next){ - LinphoneFriend *lf=(LinphoneFriend*)elem->data; - if (lf->refkey!=NULL && strcmp(lf->refkey,key)==0){ - return lf; - } - } - return NULL; + return linphone_friend_list_find_friend_by_ref_key(lc->friendlist, key); } #define key_compare(s1,s2) strcmp(s1,s2) @@ -702,7 +641,7 @@ void linphone_core_write_friends_config(LinphoneCore* lc) MSList *elem; int i; if (! linphone_core_ready(lc)) return; /*dont write config when reading it !*/ - for (elem=lc->friends,i=0; elem!=NULL; elem=ms_list_next(elem),i++){ + for (elem=lc->friendlist->friends,i=0; elem!=NULL; elem=ms_list_next(elem),i++){ linphone_friend_write_to_config_file(lc->config,(LinphoneFriend*)elem->data,i); } linphone_friend_write_to_config_file(lc->config,NULL,i); /* set the end */ diff --git a/coreapi/friendlist.c b/coreapi/friendlist.c index b221717fb..0fd49a14a 100644 --- a/coreapi/friendlist.c +++ b/coreapi/friendlist.c @@ -25,6 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. static void linphone_friend_list_destroy(LinphoneFriendList *list) { if (list->display_name != NULL) ms_free(list->display_name); if (list->rls_uri != NULL) ms_free(list->rls_uri); + list->friends = ms_list_free_with_data(list->friends, (void (*)(void *))linphone_friend_unref); } BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneFriendList); @@ -103,9 +104,85 @@ LinphoneFriendListStatus linphone_friend_list_add_friend(LinphoneFriendList *lis } LinphoneFriendListStatus linphone_friend_list_remove_friend(LinphoneFriendList *list, LinphoneFriend *friend) { - MSList *el = ms_list_find(list->friends, friend); - if (el == NULL) return LinphoneFriendListNonExistentFriend; - linphone_friend_unref((LinphoneFriend *)el->data); - list->friends = ms_list_remove_link(list->friends, el); + MSList *elem = ms_list_find(list->friends, friend); + if (elem == NULL) return LinphoneFriendListNonExistentFriend; + linphone_friend_unref((LinphoneFriend *)elem->data); + list->friends = ms_list_remove_link(list->friends, elem); return LinphoneFriendListOK; } + +LinphoneFriend * linphone_friend_list_find_friend_by_address(const LinphoneFriendList *list, const LinphoneAddress *address) { + LinphoneFriend *friend = NULL; + const MSList *elem; + for (elem = list->friends; elem != NULL; elem = elem->next) { + friend = (LinphoneFriend *)elem->data; + if (linphone_address_weak_equal(friend->uri, address)) + return friend; + } + return NULL; +} + +LinphoneFriend * linphone_friend_list_find_friend_by_uri(const LinphoneFriendList *list, const char *uri) { + LinphoneAddress *address = linphone_address_new(uri); + LinphoneFriend *friend = address ? linphone_friend_list_find_friend_by_address(list, address) : NULL; + if (address) linphone_address_unref(address); + return friend; +} + +LinphoneFriend * linphone_friend_list_find_friend_by_ref_key(const LinphoneFriendList *list, const char *ref_key) { + const MSList *elem; + if (ref_key == NULL) return NULL; + for (elem = list->friends; elem != NULL; elem = elem->next) { + LinphoneFriend *friend = (LinphoneFriend *)elem->data; + if ((friend->refkey != NULL) && (strcmp(friend->refkey, ref_key) == 0)) return friend; + } + return NULL; +} + +LinphoneFriend * linphone_friend_list_find_friend_by_inc_subscribe(const LinphoneFriendList *list, SalOp *op) { + const MSList *elem; + for (elem = list->friends; elem != NULL; elem = elem->next) { + LinphoneFriend *friend = (LinphoneFriend *)elem->data; + if (ms_list_find(friend->insubs, op)) return friend; + } + return NULL; +} + +LinphoneFriend * linphone_friend_list_find_friend_by_out_subscribe(const LinphoneFriendList *list, SalOp *op) { + const MSList *elem; + for (elem = list->friends; elem != NULL; elem = elem->next) { + LinphoneFriend *friend = (LinphoneFriend *)elem->data; + if (friend->outsub && ((friend->outsub == op) || sal_op_is_forked_of(friend->outsub, op))) return friend; + } + return NULL; +} + +void linphone_friend_list_close_subscriptions(LinphoneFriendList *list) { + /* FIXME we should wait until subscription to complete. */ + if (list->friends) + ms_list_for_each(list->friends, (void (*)(void *))linphone_friend_close_subscriptions); +} + +void linphone_friend_list_update_subscriptions(LinphoneFriendList *list, LinphoneProxyConfig *cfg, bool_t only_when_registered) { + const MSList *elem; + for (elem = list->friends; elem != NULL; elem = elem->next) { + LinphoneFriend *friend = (LinphoneFriend *)elem->data; + linphone_friend_update_subscribes(friend, cfg, only_when_registered); + } +} + +void linphone_friend_list_invalidate_subscriptions(LinphoneFriendList *list) { + const MSList *elem; + for (elem = list->friends; elem != NULL; elem = elem->next) { + LinphoneFriend *friend = (LinphoneFriend *)elem->data; + linphone_friend_invalidate_subscription(friend); + } +} + +void linphone_friend_list_notify_presence(LinphoneFriendList *list, LinphonePresenceModel *presence) { + const MSList *elem; + for(elem = list->friends; elem != NULL; elem = elem->next) { + LinphoneFriend *friend = (LinphoneFriend *)elem->data; + linphone_friend_notify(friend, presence); + } +} diff --git a/coreapi/friendlist.h b/coreapi/friendlist.h index 1d01bce39..7a94d4641 100644 --- a/coreapi/friendlist.h +++ b/coreapi/friendlist.h @@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "linphonefriend.h" +#include "linphonepresence.h" #ifdef __cplusplus @@ -125,6 +126,20 @@ LINPHONE_PUBLIC LinphoneFriendListStatus linphone_friend_list_add_friend(Linphon **/ LINPHONE_PUBLIC LinphoneFriendListStatus linphone_friend_list_remove_friend(LinphoneFriendList *list, LinphoneFriend *friend); +LINPHONE_PUBLIC LinphoneFriend * linphone_friend_list_find_friend_by_address(const LinphoneFriendList *list, const LinphoneAddress *address); + +LINPHONE_PUBLIC LinphoneFriend * linphone_friend_list_find_friend_by_uri(const LinphoneFriendList *list, const char *uri); + +LINPHONE_PUBLIC LinphoneFriend * linphone_friend_list_find_friend_by_ref_key(const LinphoneFriendList *list, const char *ref_key); + +LINPHONE_PUBLIC void linphone_friend_list_close_subscriptions(LinphoneFriendList *list); + +LINPHONE_PUBLIC void linphone_friend_list_update_subscriptions(LinphoneFriendList *list, LinphoneProxyConfig *cfg, bool_t only_when_registered); + +LINPHONE_PUBLIC void linphone_friend_list_invalidate_subscriptions(LinphoneFriendList *list); + +LINPHONE_PUBLIC void linphone_friend_list_notify_presence(LinphoneFriendList *list, LinphonePresenceModel *presence); + /** * @} */ diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 5cd5c6322..4fbef8b9a 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1672,6 +1672,7 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab lc->config=lp_config_ref(config); lc->data=userdata; lc->ringstream_autorelease=TRUE; + lc->friendlist = linphone_friend_list_new(); linphone_task_list_init(&lc->hooks); memcpy(local_vtable,vtable,sizeof(LinphoneCoreVTable)); @@ -1905,7 +1906,7 @@ bool_t linphone_core_generic_confort_noise_enabled(const LinphoneCore *lc){ const MSList * linphone_core_get_friend_list(const LinphoneCore *lc) { - return lc->friends; + return lc->friendlist->friends; } void linphone_core_enable_audio_adaptive_jittcomp(LinphoneCore* lc, bool_t val) @@ -6323,9 +6324,8 @@ static void codecs_config_uninit(LinphoneCore *lc) void ui_config_uninit(LinphoneCore* lc) { ms_message("Destroying friends."); - if (lc->friends){ - lc->friends = ms_list_free_with_data(lc->friends, (void (*)(void *))linphone_friend_unref); - } + linphone_friend_list_unref(lc->friendlist); + lc->friendlist = NULL; if (lc->subscribers){ lc->subscribers = ms_list_free_with_data(lc->subscribers, (void (*)(void *))linphone_friend_unref); } @@ -6365,9 +6365,7 @@ static void linphone_core_uninit(LinphoneCore *lc) ms_usleep(50000); } - if (lc->friends) /* FIXME we should wait until subscription to complete*/ - ms_list_for_each(lc->friends,(void (*)(void *))linphone_friend_close_subscriptions); - + linphone_friend_list_close_subscriptions(lc->friendlist); lc->chatrooms = ms_list_free_with_data(lc->chatrooms, (MSIterateFunc)linphone_chat_room_release); linphone_core_set_state(lc,LinphoneGlobalShutdown,"Shutting down"); diff --git a/coreapi/presence.c b/coreapi/presence.c index f69ddec6e..d97ff865f 100644 --- a/coreapi/presence.c +++ b/coreapi/presence.c @@ -1464,15 +1464,11 @@ void linphone_core_reject_subscriber(LinphoneCore *lc, LinphoneFriend *lf){ } void linphone_core_notify_all_friends(LinphoneCore *lc, LinphonePresenceModel *presence){ - MSList *elem; LinphonePresenceActivity *activity = linphone_presence_model_get_activity(presence); char *activity_str = linphone_presence_activity_to_string(activity); ms_message("Notifying all friends that we are [%s]", activity_str); if (activity_str != NULL) ms_free(activity_str); - for(elem=lc->friends;elem!=NULL;elem=elem->next){ - LinphoneFriend *lf=(LinphoneFriend *)elem->data; - linphone_friend_notify(lf,presence); - } + linphone_friend_list_notify_presence(lc->friendlist, presence); } void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from){ @@ -1486,7 +1482,8 @@ void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from){ ms_message("Receiving new subscription from %s.",from); /* check if we answer to this subscription */ - if (linphone_find_friend_by_address(lc->friends,uri,&lf)!=NULL){ + lf = linphone_friend_list_find_friend_by_address(lc->friendlist, uri); + if (lf!=NULL){ linphone_friend_add_incoming_subscription(lf, op); lf->inc_subscribe_pending=TRUE; sal_subscribe_accept(op); @@ -1850,15 +1847,15 @@ void linphone_notify_convert_presence_to_xml(SalOp *op, SalPresenceModel *presen void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, SalPresenceModel *model){ char *tmp; - LinphoneFriend *lf; + LinphoneFriend *lf = NULL; LinphoneAddress *friend=NULL; LinphonePresenceModel *presence = model ? (LinphonePresenceModel *)model:linphone_presence_model_new_with_activity(LinphonePresenceActivityOffline, NULL); - lf=linphone_find_friend_by_out_subscribe(lc->friends,op); + if (lc->friendlist != NULL) + lf=linphone_friend_list_find_friend_by_out_subscribe(lc->friendlist,op); if (lf==NULL && lp_config_get_int(lc->config,"sip","allow_out_of_subscribe_presence",0)){ const SalAddress *addr=sal_op_get_from_address(op); - lf=NULL; - linphone_find_friend_by_address(lc->friends,(LinphoneAddress*)addr,&lf); + lf = linphone_friend_list_find_friend_by_address(lc->friendlist, (LinphoneAddress *)addr); } if (lf!=NULL){ LinphonePresenceActivity *activity = NULL; @@ -1904,9 +1901,11 @@ void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, Sa } void linphone_subscription_closed(LinphoneCore *lc, SalOp *op){ - LinphoneFriend *lf; - lf=linphone_find_friend_by_inc_subscribe(lc->friends,op); - + LinphoneFriend *lf = NULL; + + if (lc->friendlist != NULL) + lf=linphone_friend_list_find_friend_by_inc_subscribe(lc->friendlist,op); + if (lf!=NULL){ /*this will release the op*/ linphone_friend_remove_incoming_subscription(lf, op); diff --git a/coreapi/private.h b/coreapi/private.h index 078ed768b..0820bdb14 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -376,13 +376,14 @@ void _linphone_proxy_config_release(LinphoneProxyConfig *cfg); * */ const LinphoneAddress* linphone_proxy_config_get_service_route(const LinphoneProxyConfig* cfg); +void linphone_friend_invalidate_subscription(LinphoneFriend *lf); void linphone_friend_close_subscriptions(LinphoneFriend *lf); void linphone_friend_update_subscribes(LinphoneFriend *fr, LinphoneProxyConfig *cfg, bool_t only_when_registered); void linphone_friend_notify(LinphoneFriend *lf, LinphonePresenceModel *presence); void linphone_friend_add_incoming_subscription(LinphoneFriend *lf, SalOp *op); void linphone_friend_remove_incoming_subscription(LinphoneFriend *lf, SalOp *op); -LinphoneFriend *linphone_find_friend_by_inc_subscribe(MSList *l, SalOp *op); -LinphoneFriend *linphone_find_friend_by_out_subscribe(MSList *l, SalOp *op); +LinphoneFriend *linphone_friend_list_find_friend_by_inc_subscribe(const LinphoneFriendList *list, SalOp *op); +LinphoneFriend *linphone_friend_list_find_friend_by_out_subscribe(const LinphoneFriendList *list, SalOp *op); MSList *linphone_find_friend_by_address(MSList *fl, const LinphoneAddress *addr, LinphoneFriend **lf); bool_t linphone_core_should_subscribe_friends_only_when_registered(const LinphoneCore *lc); void linphone_core_update_friends_subscriptions(LinphoneCore *lc, LinphoneProxyConfig *cfg, bool_t only_when_registered); @@ -850,7 +851,7 @@ struct _LinphoneCore ui_config_t ui_conf; autoreplier_config_t autoreplier_conf; LinphoneProxyConfig *default_proxy; - MSList *friends; + LinphoneFriendList *friendlist; MSList *auth_info; struct _RingStream *ringstream; time_t dmfs_playing_start_time; From 96d249c674bd1d6e12ca192e7fca0ea0cdbabe3f Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Tue, 10 Nov 2015 09:45:29 +0100 Subject: [PATCH 03/30] Generate resource-lists SUBSCRIBE for presence. --- coreapi/friend.c | 17 ++++--- coreapi/friendlist.c | 108 ++++++++++++++++++++++++++++++++++++++--- coreapi/friendlist.h | 30 ++++++++++-- coreapi/linphonecore.c | 6 ++- coreapi/private.h | 2 + 5 files changed, 145 insertions(+), 18 deletions(-) diff --git a/coreapi/friend.c b/coreapi/friend.c index 01990400a..e15fed661 100644 --- a/coreapi/friend.c +++ b/coreapi/friend.c @@ -241,18 +241,21 @@ static void linphone_friend_unsubscribe(LinphoneFriend *lf){ } void linphone_friend_invalidate_subscription(LinphoneFriend *lf){ + LinphoneCore *lc=lf->lc; + if (lf->outsub!=NULL) { - LinphoneCore *lc=lf->lc; sal_op_release(lf->outsub); lf->outsub=NULL; lf->subscribe_active=FALSE; - /*notify application that we no longer know the presence activity */ - if (lf->presence != NULL) { - linphone_presence_model_unref(lf->presence); - } - lf->presence = linphone_presence_model_new_with_activity(LinphonePresenceActivityOffline,"unknown activity"); - linphone_core_notify_notify_presence_received(lc,lf); } + + /* Notify application that we no longer know the presence activity */ + if (lf->presence != NULL) { + linphone_presence_model_unref(lf->presence); + } + lf->presence = linphone_presence_model_new_with_activity(LinphonePresenceActivityOffline,"unknown activity"); + linphone_core_notify_notify_presence_received(lc,lf); + lf->initial_subscribes_sent=FALSE; } diff --git a/coreapi/friendlist.c b/coreapi/friendlist.c index 0fd49a14a..099433fff 100644 --- a/coreapi/friendlist.c +++ b/coreapi/friendlist.c @@ -22,6 +22,81 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +static char * create_resource_list_xml(const LinphoneFriendList *list) { + char *xml_content = NULL; + MSList *elem; + xmlBufferPtr buf; + xmlTextWriterPtr writer; + int err; + + if (ms_list_size(list->friends) <= 0) return NULL; + + buf = xmlBufferCreate(); + if (buf == NULL) { + ms_error("%s: Error creating the XML buffer", __FUNCTION__); + return NULL; + } + writer = xmlNewTextWriterMemory(buf, 0); + if (writer == NULL) { + ms_error("%s: Error creating the XML writer", __FUNCTION__); + return NULL; + } + + xmlTextWriterSetIndent(writer,1); + err = xmlTextWriterStartDocument(writer, "1.0", "UTF-8", NULL); + if (err >= 0) { + err = xmlTextWriterStartElementNS(writer, NULL, (const xmlChar *)"resource-lists", (const xmlChar *)"urn:ietf:params:xml:ns:resource-lists"); + } + if (err >= 0) { + err = xmlTextWriterWriteAttributeNS(writer, (const xmlChar *)"xmlns", (const xmlChar *)"xsi", + NULL, (const xmlChar *)"http://www.w3.org/2001/XMLSchema-instance"); + } + + if (err>= 0) { + err = xmlTextWriterStartElement(writer, (const xmlChar *)"list"); + } + for (elem = list->friends; elem != NULL; elem = elem->next) { + LinphoneFriend *friend = (LinphoneFriend *)elem->data; + char *uri = linphone_address_as_string_uri_only(friend->uri); + if (err >= 0) { + err = xmlTextWriterStartElement(writer, (const xmlChar *)"entry"); + } + if (err >= 0) { + err = xmlTextWriterWriteAttribute(writer, (const xmlChar *)"uri", (const xmlChar *)uri); + } + if (err >= 0) { + /* Close the "entry" element. */ + err = xmlTextWriterEndElement(writer); + } + } + if (err >= 0) { + /* Close the "list" element. */ + err = xmlTextWriterEndElement(writer); + } + + if (err >= 0) { + /* Close the "resource-lists" element. */ + err = xmlTextWriterEndElement(writer); + } + if (err >= 0) { + err = xmlTextWriterEndDocument(writer); + } + if (err > 0) { + /* xmlTextWriterEndDocument returns the size of the content. */ + xml_content = ms_strdup((char *)buf->content); + } + xmlFreeTextWriter(writer); + xmlBufferFree(buf); + + return xml_content; +} + +static LinphoneFriendList * linphone_friend_list_new(void) { + LinphoneFriendList *list = belle_sip_object_new(LinphoneFriendList); + belle_sip_object_ref(list); + return list; +} + static void linphone_friend_list_destroy(LinphoneFriendList *list) { if (list->display_name != NULL) ms_free(list->display_name); if (list->rls_uri != NULL) ms_free(list->rls_uri); @@ -38,9 +113,9 @@ BELLE_SIP_INSTANCIATE_VPTR(LinphoneFriendList, belle_sip_object_t, ); -LinphoneFriendList * linphone_friend_list_new(void) { - LinphoneFriendList *list = belle_sip_object_new(LinphoneFriendList); - belle_sip_object_ref(list); +LinphoneFriendList * linphone_core_create_friend_list(LinphoneCore *lc) { + LinphoneFriendList *list = linphone_friend_list_new(); + list->lc = lc; return list; } @@ -165,9 +240,30 @@ void linphone_friend_list_close_subscriptions(LinphoneFriendList *list) { void linphone_friend_list_update_subscriptions(LinphoneFriendList *list, LinphoneProxyConfig *cfg, bool_t only_when_registered) { const MSList *elem; - for (elem = list->friends; elem != NULL; elem = elem->next) { - LinphoneFriend *friend = (LinphoneFriend *)elem->data; - linphone_friend_update_subscribes(friend, cfg, only_when_registered); + if (list->rls_uri != NULL) { + LinphoneAddress *address = linphone_address_new(list->rls_uri); + char *xml_content = create_resource_list_xml(list); + if ((address != NULL) && (xml_content != NULL)) { + LinphoneEvent *event; + LinphoneContent *content; + int expires = lp_config_get_int(list->lc->config, "sip", "rls_presence_expires", 3600); + event = linphone_core_create_subscribe(list->lc, address, "presence", expires); + linphone_event_add_custom_header(event, "Require", "recipient-list-subscribe"); + linphone_event_add_custom_header(event, "Accept", "multipart/related, application/pidf+xml, application/rlmi+xml"); + linphone_event_add_custom_header(event, "Content-Disposition", "recipient-list"); + content = linphone_core_create_content(list->lc); + linphone_content_set_type(content, "application"); + linphone_content_set_subtype(content, "resource-lists+xml"); + linphone_content_set_string_buffer(content, xml_content); + linphone_event_send_subscribe(event, content); + } + if (address != NULL) linphone_address_unref(address); + if (xml_content != NULL) ms_free(xml_content); + } else { + for (elem = list->friends; elem != NULL; elem = elem->next) { + LinphoneFriend *friend = (LinphoneFriend *)elem->data; + linphone_friend_update_subscribes(friend, cfg, only_when_registered); + } } } diff --git a/coreapi/friendlist.h b/coreapi/friendlist.h index 7a94d4641..17b805add 100644 --- a/coreapi/friendlist.h +++ b/coreapi/friendlist.h @@ -51,9 +51,10 @@ typedef struct _LinphoneFriendList LinphoneFriendList; /** * Create a new empty LinphoneFriendList object. + * @param[in] lc LinphoneCore object. * @return A new LinphoneFriendList object. - */ -LINPHONE_PUBLIC LinphoneFriendList * linphone_friend_list_new(void); +**/ +LINPHONE_PUBLIC LinphoneFriendList * linphone_core_create_friend_list(LinphoneCore *lc); /** * Acquire a reference to the friend list. @@ -126,18 +127,39 @@ LINPHONE_PUBLIC LinphoneFriendListStatus linphone_friend_list_add_friend(Linphon **/ LINPHONE_PUBLIC LinphoneFriendListStatus linphone_friend_list_remove_friend(LinphoneFriendList *list, LinphoneFriend *friend); +/** + * Find a friend in the friend list using a LinphoneAddress. + * @param[in] list LinphoneFriendList object. + * @param[in] address LinphoneAddress object of the friend we want to search for. + * @return A LinphoneFriend if found, NULL otherwise. +**/ LINPHONE_PUBLIC LinphoneFriend * linphone_friend_list_find_friend_by_address(const LinphoneFriendList *list, const LinphoneAddress *address); +/** + * Find a friend in the friend list using an URI string. + * @param[in] list LinphoneFriendList object. + * @param[in] uri A string containing the URI of the friend we want to search for. + * @return A LinphoneFriend if found, NULL otherwise. +**/ LINPHONE_PUBLIC LinphoneFriend * linphone_friend_list_find_friend_by_uri(const LinphoneFriendList *list, const char *uri); +/** + * Find a frient in the friend list using a ref key. + * @param[in] list LinphoneFriendList object. + * @param[in] ref_key The ref key string of the friend we want to search for. + * @return A LinphoneFriend if found, NULL otherwise. +**/ LINPHONE_PUBLIC LinphoneFriend * linphone_friend_list_find_friend_by_ref_key(const LinphoneFriendList *list, const char *ref_key); LINPHONE_PUBLIC void linphone_friend_list_close_subscriptions(LinphoneFriendList *list); LINPHONE_PUBLIC void linphone_friend_list_update_subscriptions(LinphoneFriendList *list, LinphoneProxyConfig *cfg, bool_t only_when_registered); -LINPHONE_PUBLIC void linphone_friend_list_invalidate_subscriptions(LinphoneFriendList *list); - +/** + * Notify our presence to all the friends in the friend list that have subscribed to our presence directly (not using a RLS). + * @param[in] list LinphoneFriendList object. + * @param[in] presence LinphonePresenceModel object. +**/ LINPHONE_PUBLIC void linphone_friend_list_notify_presence(LinphoneFriendList *list, LinphonePresenceModel *presence); /** diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 4fbef8b9a..fb3a39e9b 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1665,6 +1665,7 @@ static void linphone_core_register_default_codecs(LinphoneCore *lc){ } static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtable, LpConfig *config, void * userdata){ + const char *rls_uri = NULL; const char *remote_provisioning_uri = NULL; LinphoneCoreVTable* local_vtable= linphone_core_v_table_new(); ms_message("Initializing LinphoneCore %s", linphone_core_get_version()); @@ -1672,7 +1673,10 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab lc->config=lp_config_ref(config); lc->data=userdata; lc->ringstream_autorelease=TRUE; - lc->friendlist = linphone_friend_list_new(); + lc->friendlist = linphone_core_create_friend_list(lc); + rls_uri = lp_config_get_string(lc->config, "sip", "rls_uri", NULL); + if (rls_uri && lp_config_get_int(lc->config, "sip", "use_rls_presence", 0)) + linphone_friend_list_set_rls_uri(lc->friendlist, rls_uri); linphone_task_list_init(&lc->hooks); memcpy(local_vtable,vtable,sizeof(LinphoneCoreVTable)); diff --git a/coreapi/private.h b/coreapi/private.h index 0820bdb14..5c2777f4e 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -376,6 +376,7 @@ void _linphone_proxy_config_release(LinphoneProxyConfig *cfg); * */ const LinphoneAddress* linphone_proxy_config_get_service_route(const LinphoneProxyConfig* cfg); +void linphone_friend_list_invalidate_subscriptions(LinphoneFriendList *list); void linphone_friend_invalidate_subscription(LinphoneFriend *lf); void linphone_friend_close_subscriptions(LinphoneFriend *lf); void linphone_friend_update_subscribes(LinphoneFriend *fr, LinphoneProxyConfig *cfg, bool_t only_when_registered); @@ -653,6 +654,7 @@ BELLE_SIP_DECLARE_VPTR(LinphoneFriend); struct _LinphoneFriendList { belle_sip_object_t base; void *user_data; + LinphoneCore *lc; char *display_name; char *rls_uri; MSList *friends; From edd42fcf1b8874bad36408152c11c5fe6248e849 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Thu, 26 Nov 2015 15:19:21 +0100 Subject: [PATCH 04/30] Rework sal to be able multipart LinphoneContent objects. --- coreapi/bellesip_sal/sal_impl.h | 3 +- coreapi/bellesip_sal/sal_op_call.c | 14 +- coreapi/bellesip_sal/sal_op_events.c | 30 ++-- coreapi/bellesip_sal/sal_op_impl.c | 53 ++----- coreapi/bellesip_sal/sal_op_info.c | 4 +- coreapi/bellesip_sal/sal_op_publish.c | 10 +- coreapi/callbacks.c | 10 +- coreapi/chat_file_transfer.c | 3 +- coreapi/content.c | 190 +++++++++++++------------- coreapi/content.h | 55 ++------ coreapi/event.c | 15 +- coreapi/info.c | 12 +- coreapi/linphonecore.c | 2 +- coreapi/private.h | 12 +- coreapi/sal.c | 99 +++++++++++++- include/sal/sal.h | 42 +++--- 16 files changed, 300 insertions(+), 254 deletions(-) diff --git a/coreapi/bellesip_sal/sal_impl.h b/coreapi/bellesip_sal/sal_impl.h index bd942c9aa..9837e8078 100644 --- a/coreapi/bellesip_sal/sal_impl.h +++ b/coreapi/bellesip_sal/sal_impl.h @@ -166,8 +166,7 @@ belle_sip_response_t *sal_create_response_from_request(Sal *sal, belle_sip_reque void sal_op_assign_recv_headers(SalOp *op, belle_sip_message_t *incoming); -void sal_op_add_body(SalOp *op, belle_sip_message_t *req, const SalBody *body); -bool_t sal_op_get_body(SalOp *op, belle_sip_message_t *msg, SalBody *salbody); +SalBodyHandler * sal_op_get_body_handler(SalOp *op, belle_sip_message_t *msg); SalReason sal_reason_to_sip_code(SalReason r); diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index 076421aad..42e636390 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -669,15 +669,19 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t } }else{ - SalBody salbody; - if (sal_op_get_body(op,(belle_sip_message_t*)req,&salbody)) { - if (sal_body_has_type(&salbody,"application","dtmf-relay")){ + belle_sip_message_t *msg = BELLE_SIP_MESSAGE(req); + belle_sip_body_handler_t *body_handler = BELLE_SIP_BODY_HANDLER(sal_op_get_body_handler(op, msg)); + if (body_handler) { + belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_type_t); + if (content_type + && (strcmp(belle_sip_header_content_type_get_type(content_type), "application") == 0) + && (strcmp(belle_sip_header_content_type_get_subtype(content_type), "dtmf-relay") == 0)) { char tmp[10]; - if (sal_lines_get_value(salbody.data, "Signal",tmp, sizeof(tmp))){ + if (sal_lines_get_value(belle_sip_message_get_body(msg), "Signal",tmp, sizeof(tmp))){ op->base.root->callbacks.dtmf_received(op,tmp[0]); } }else - op->base.root->callbacks.info_received(op,&salbody); + op->base.root->callbacks.info_received(op, (SalBodyHandler *)body_handler); } else { op->base.root->callbacks.info_received(op,NULL); } diff --git a/coreapi/bellesip_sal/sal_op_events.c b/coreapi/bellesip_sal/sal_op_events.c index 8b439eb9b..d41440d96 100644 --- a/coreapi/bellesip_sal/sal_op_events.c +++ b/coreapi/bellesip_sal/sal_op_events.c @@ -77,7 +77,7 @@ static void subscribe_process_timeout(void *user_ctx, const belle_sip_timeout_ev static void subscribe_process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) { } -static void handle_notify(SalOp *op, belle_sip_request_t *req, const char *eventname, SalBody * body){ +static void handle_notify(SalOp *op, belle_sip_request_t *req, const char *eventname, SalBodyHandler* body_handler){ SalSubscribeStatus sub_state; belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(req,belle_sip_header_subscription_state_t); belle_sip_response_t* resp; @@ -89,7 +89,7 @@ static void handle_notify(SalOp *op, belle_sip_request_t *req, const char *event } else sub_state=SalSubscribeActive; sal_op_ref(op); - op->base.root->callbacks.notify(op,sub_state,eventname,body); + op->base.root->callbacks.notify(op,sub_state,eventname,body_handler); resp=sal_op_create_response_from_request(op,req,200); belle_sip_server_transaction_send_response(server_transaction,resp); sal_op_unref(op); @@ -102,7 +102,7 @@ static void subscribe_process_request_event(void *op_base, const belle_sip_reque belle_sip_dialog_state_t dialog_state; belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t); belle_sip_header_t *event_header; - SalBody body; + belle_sip_body_handler_t *body_handler; belle_sip_response_t* resp; const char *eventname=NULL; const char *method=belle_sip_request_get_method(req); @@ -112,7 +112,7 @@ static void subscribe_process_request_event(void *op_base, const belle_sip_reque op->pending_server_trans=server_transaction; event_header=belle_sip_message_get_header((belle_sip_message_t*)req,"Event"); - sal_op_get_body(op,(belle_sip_message_t*)req,&body); + body_handler = BELLE_SIP_BODY_HANDLER(sal_op_get_body_handler(op, BELLE_SIP_MESSAGE(req))); if (event_header==NULL){ ms_warning("No event header in incoming SUBSCRIBE."); @@ -132,7 +132,7 @@ static void subscribe_process_request_event(void *op_base, const belle_sip_reque belle_sip_dialog_set_application_data(op->dialog, sal_op_ref(op)); ms_message("new incoming subscription from [%s] to [%s]",sal_op_get_from(op),sal_op_get_to(op)); }else{ /*this is a NOTIFY*/ - handle_notify(op,req,eventname,&body); + handle_notify(op, req, eventname, (SalBodyHandler *)body_handler); return; } } @@ -140,7 +140,10 @@ static void subscribe_process_request_event(void *op_base, const belle_sip_reque switch(dialog_state) { case BELLE_SIP_DIALOG_NULL: { - op->base.root->callbacks.subscribe_received(op,eventname,body.type ? &body : NULL); + const char *type = NULL; + belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_content_type_t); + if (content_type) type = belle_sip_header_content_type_get_type(content_type); + op->base.root->callbacks.subscribe_received(op, eventname, type ? (SalBodyHandler *)body_handler : NULL); break; } case BELLE_SIP_DIALOG_EARLY: @@ -149,7 +152,7 @@ static void subscribe_process_request_event(void *op_base, const belle_sip_reque case BELLE_SIP_DIALOG_CONFIRMED: if (strcmp("NOTIFY",method)==0) { - handle_notify(op,req,eventname,&body); + handle_notify(op, req, eventname, (SalBodyHandler *)body_handler); } else if (strcmp("SUBSCRIBE",method)==0) { /*either a refresh of an unsubscribe*/ if (expires && belle_sip_header_expires_get_expires(expires)>0) { @@ -185,7 +188,7 @@ void sal_op_subscribe_fill_cbs(SalOp*op) { } -int sal_subscribe(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBody *body){ +int sal_subscribe(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBodyHandler *body_handler){ belle_sip_request_t *req=NULL; if (from) @@ -207,13 +210,13 @@ int sal_subscribe(SalOp *op, const char *from, const char *to, const char *event } belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),op->event); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(expires))); - sal_op_add_body(op,(belle_sip_message_t*)req,body); + belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(body_handler)); return sal_op_send_and_create_refresher(op,req,expires,subscribe_refresher_listener); }else if (op->refresher){ const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(op->refresher); belle_sip_request_t *last_req=belle_sip_transaction_get_request(tr); /* modify last request to update body*/ - sal_op_add_body(op,(belle_sip_message_t*)last_req,body); + belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(last_req), BELLE_SIP_BODY_HANDLER(body_handler)); return belle_sip_refresher_refresh(op->refresher,expires); } ms_warning("sal_subscribe(): no dialog and no refresher ?"); @@ -224,7 +227,7 @@ int sal_unsubscribe(SalOp *op){ if (op->refresher){ const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(op->refresher); belle_sip_request_t *last_req=belle_sip_transaction_get_request(tr); - sal_op_add_body(op,(belle_sip_message_t*)last_req,NULL); + belle_sip_message_set_body(BELLE_SIP_MESSAGE(last_req), NULL, 0); belle_sip_refresher_refresh(op->refresher,0); return 0; } @@ -247,7 +250,7 @@ int sal_subscribe_decline(SalOp *op, SalReason reason){ return 0; } -int sal_notify(SalOp *op, const SalBody *body){ +int sal_notify(SalOp *op, const SalBodyHandler *body_handler){ belle_sip_request_t* notify; if (!op->dialog) return -1; @@ -258,8 +261,7 @@ int sal_notify(SalOp *op, const SalBody *body){ belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) ,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE,600))); - - sal_op_add_body(op,(belle_sip_message_t*)notify, body); + belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(notify), BELLE_SIP_BODY_HANDLER(body_handler)); return sal_op_send_request(op,notify); } diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index 5a55d2900..9f654902c 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -706,50 +706,17 @@ const char *sal_op_get_remote_contact(const SalOp *op){ return op->base.remote_contact; } -void sal_op_add_body(SalOp *op, belle_sip_message_t *req, const SalBody *body){ - belle_sip_message_remove_header((belle_sip_message_t*)req,"Content-type"); - belle_sip_message_remove_header((belle_sip_message_t*)req,"Content-length"); - belle_sip_message_remove_header((belle_sip_message_t*)req,"Content-encoding"); - belle_sip_message_set_body((belle_sip_message_t*)req,NULL,0); - if (body && body->type && body->subtype && body->data){ - belle_sip_message_add_header((belle_sip_message_t*)req, - (belle_sip_header_t*)belle_sip_header_content_type_create(body->type,body->subtype)); - belle_sip_message_add_header((belle_sip_message_t*)req, - (belle_sip_header_t*)belle_sip_header_content_length_create(body->size)); - belle_sip_message_set_body((belle_sip_message_t*)req,(const char*)body->data,body->size); - if (body->encoding){ - belle_sip_message_add_header((belle_sip_message_t*)req,(belle_sip_header_t*) - belle_sip_header_create("Content-encoding",body->encoding)); - } +SalBodyHandler * sal_op_get_body_handler(SalOp *op, belle_sip_message_t *msg) { + belle_sip_body_handler_t *body_handler = belle_sip_message_get_body_handler(msg); + if (body_handler != NULL) { + belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_type_t); + belle_sip_header_content_length_t *content_length = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_length_t); + belle_sip_header_t *content_encoding = belle_sip_message_get_header(msg, "Content-Encoding"); + if (content_type != NULL) belle_sip_body_handler_add_header(body_handler, BELLE_SIP_HEADER(content_type)); + if (content_length != NULL) belle_sip_body_handler_add_header(body_handler, BELLE_SIP_HEADER(content_length)); + if (content_encoding != NULL) belle_sip_body_handler_add_header(body_handler, content_encoding); } -} - - -bool_t sal_op_get_body(SalOp *op, belle_sip_message_t *msg, SalBody *salbody){ - const char *body = NULL; - belle_sip_header_content_type_t *content_type; - belle_sip_header_content_length_t *clen=NULL; - belle_sip_header_t *content_encoding; - - content_type=belle_sip_message_get_header_by_type(msg,belle_sip_header_content_type_t); - if (content_type){ - body=belle_sip_message_get_body(msg); - clen=belle_sip_message_get_header_by_type(msg,belle_sip_header_content_length_t); - } - content_encoding=belle_sip_message_get_header(msg,"Content-encoding"); - - memset(salbody,0,sizeof(SalBody)); - - if (content_type && body && clen) { - salbody->type=belle_sip_header_content_type_get_type(content_type); - salbody->subtype=belle_sip_header_content_type_get_subtype(content_type); - salbody->data=body; - salbody->size=belle_sip_header_content_length_get_content_length(clen); - if (content_encoding) - salbody->encoding=belle_sip_header_get_unparsed_value(content_encoding); - return TRUE; - } - return FALSE; + return (SalBodyHandler *)body_handler; } void sal_op_set_privacy(SalOp* op,SalPrivacyMask privacy) { diff --git a/coreapi/bellesip_sal/sal_op_info.c b/coreapi/bellesip_sal/sal_op_info.c index 3cffb8e55..3820c95ee 100644 --- a/coreapi/bellesip_sal/sal_op_info.c +++ b/coreapi/bellesip_sal/sal_op_info.c @@ -19,12 +19,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "sal_impl.h" -int sal_send_info(SalOp *op, const char *from, const char *to, const SalBody *body){ +int sal_send_info(SalOp *op, const char *from, const char *to, const SalBodyHandler *body_handler){ if (op->dialog){ belle_sip_request_t *req; belle_sip_dialog_enable_pending_trans_checking(op->dialog,op->base.root->pending_trans_checking); req=belle_sip_dialog_create_queued_request(op->dialog,"INFO"); - sal_op_add_body(op,(belle_sip_message_t*)req,body); + belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(body_handler)); return sal_op_send_request(op,req); } return -1; diff --git a/coreapi/bellesip_sal/sal_op_publish.c b/coreapi/bellesip_sal/sal_op_publish.c index 17ef8e8db..a1dc85204 100644 --- a/coreapi/bellesip_sal/sal_op_publish.c +++ b/coreapi/bellesip_sal/sal_op_publish.c @@ -96,7 +96,7 @@ int sal_publish_presence(SalOp *op, const char *from, const char *to, int expire } } -int sal_publish(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBody *body){ +int sal_publish(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBodyHandler *body_handler){ belle_sip_request_t *req=NULL; if(!op->refresher || !belle_sip_refresher_get_transaction(op->refresher)) { if (from) @@ -114,7 +114,7 @@ int sal_publish(SalOp *op, const char *from, const char *to, const char *eventna belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(sal_op_create_contact(op))); } belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create("Event",eventname)); - sal_op_add_body(op,BELLE_SIP_MESSAGE(req),body); + belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(body_handler)); if (expires!=-1) return sal_op_send_and_create_refresher(op,req,expires,publish_refresher_listener); else return sal_op_send_request(op,req); @@ -123,7 +123,11 @@ int sal_publish(SalOp *op, const char *from, const char *to, const char *eventna const belle_sip_client_transaction_t* last_publish_trans=belle_sip_refresher_get_transaction(op->refresher); belle_sip_request_t* last_publish=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(last_publish_trans)); /*update body*/ - sal_op_add_body(op,BELLE_SIP_MESSAGE(last_publish),expires!=0 ? body : NULL); + if (expires == 0) { + belle_sip_message_set_body(BELLE_SIP_MESSAGE(last_publish), NULL, 0); + } else { + belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(last_publish), BELLE_SIP_BODY_HANDLER(body_handler)); + } return belle_sip_refresher_refresh(op->refresher,expires==-1 ? BELLE_SIP_REFRESHER_REUSE_EXPIRES : expires); } } diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index a0035d2ed..b19f468f1 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -1276,9 +1276,9 @@ static void text_delivery_update(SalOp *op, SalTextDeliveryStatus status){ } } -static void info_received(SalOp *op, const SalBody *body){ +static void info_received(SalOp *op, SalBodyHandler *body_handler){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); - linphone_core_notify_info_message(lc,op,body); + linphone_core_notify_info_message(lc,op,body_handler); } static void subscribe_response(SalOp *op, SalSubscribeStatus status){ @@ -1299,7 +1299,7 @@ static void subscribe_response(SalOp *op, SalSubscribeStatus status){ } } -static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, const SalBody *body){ +static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, SalBodyHandler *body_handler){ LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); @@ -1308,7 +1308,7 @@ static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, cons lev=linphone_event_new_with_out_of_dialog_op(lc,op,LinphoneSubscriptionOutgoing,eventname); } { - LinphoneContent *ct=linphone_content_from_sal_body(body); + LinphoneContent *ct=linphone_content_from_sal_body_handler(body_handler); if (ct) linphone_core_notify_notify_received(lc,lev,eventname,ct); } if (st!=SalSubscribeNone){ @@ -1316,7 +1316,7 @@ static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, cons } } -static void subscribe_received(SalOp *op, const char *eventname, const SalBody *body){ +static void subscribe_received(SalOp *op, const char *eventname, const SalBodyHandler *body_handler){ LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); diff --git a/coreapi/chat_file_transfer.c b/coreapi/chat_file_transfer.c index cf5318da0..03190ce7f 100644 --- a/coreapi/chat_file_transfer.c +++ b/coreapi/chat_file_transfer.c @@ -215,8 +215,7 @@ static void linphone_chat_message_process_response_from_post_file(void *data, linphone_content_get_subtype(msg->file_transfer_information))); /* insert it in a multipart body handler which will manage the boundaries of multipart msg */ - bh = belle_sip_multipart_body_handler_new(linphone_chat_message_file_transfer_on_progress, msg, - first_part_bh); + bh = belle_sip_multipart_body_handler_new(linphone_chat_message_file_transfer_on_progress, msg, first_part_bh, NULL); linphone_chat_message_ref(msg); _release_http_request(msg); diff --git a/coreapi/content.c b/coreapi/content.c index 9f5cd4fee..a5a66f1b9 100644 --- a/coreapi/content.c +++ b/coreapi/content.c @@ -22,23 +22,46 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +static void linphone_content_set_sal_body_handler(LinphoneContent *content, SalBodyHandler *body_handler) { + if (content->body_handler != NULL) { + sal_body_handler_unref(content->body_handler); + content->body_handler = NULL; + } + content->body_handler = sal_body_handler_ref(body_handler); +} + +static LinphoneContent * linphone_content_new_with_body_handler(SalBodyHandler *body_handler) { + LinphoneContent *content = belle_sip_object_new(LinphoneContent); + belle_sip_object_ref(content); + content->owned_fields = TRUE; + content->cryptoContext = NULL; /* this field is managed externally by encryption/decryption functions so be careful to initialise it to NULL */ + if (body_handler == NULL) { + linphone_content_set_sal_body_handler(content, sal_body_handler_new()); + } else { + linphone_content_set_sal_body_handler(content, body_handler); + } + return content; +} + static void linphone_content_destroy(LinphoneContent *content) { if (content->owned_fields == TRUE) { - if (content->lcp.type) belle_sip_free(content->lcp.type); - if (content->lcp.subtype) belle_sip_free(content->lcp.subtype); - if (content->lcp.data) belle_sip_free(content->lcp.data); - if (content->lcp.encoding) belle_sip_free(content->lcp.encoding); - if (content->lcp.name) belle_sip_free(content->lcp.name); - if (content->lcp.key) belle_sip_free(content->lcp.key); + if (content->body_handler) sal_body_handler_unref(content->body_handler); + if (content->name) belle_sip_free(content->name); + if (content->key) belle_sip_free(content->key); /* note : crypto context is allocated/destroyed by the encryption function */ } } static void linphone_content_clone(LinphoneContent *obj, const LinphoneContent *ref) { obj->owned_fields = TRUE; - linphone_content_set_type(obj, linphone_content_get_type(ref)); - linphone_content_set_subtype(obj, linphone_content_get_subtype(ref)); - linphone_content_set_encoding(obj, linphone_content_get_encoding(ref)); + linphone_content_set_sal_body_handler(obj, sal_body_handler_new()); + if ((linphone_content_get_type(ref) != NULL) || (linphone_content_get_subtype(ref) != NULL)) { + linphone_content_set_type(obj, linphone_content_get_type(ref)); + linphone_content_set_subtype(obj, linphone_content_get_subtype(ref)); + } + if (linphone_content_get_encoding(ref) != NULL) { + linphone_content_set_encoding(obj, linphone_content_get_encoding(ref)); + } linphone_content_set_name(obj, linphone_content_get_name(ref)); linphone_content_set_key(obj, linphone_content_get_key(ref), linphone_content_get_key_size(ref)); if (linphone_content_get_buffer(ref) != NULL) { @@ -81,163 +104,138 @@ void linphone_content_set_user_data(LinphoneContent *content, void *ud) { } const char * linphone_content_get_type(const LinphoneContent *content) { - return content->lcp.type; + return sal_body_handler_get_type(content->body_handler); } void linphone_content_set_type(LinphoneContent *content, const char *type) { - if (content->lcp.type != NULL) { - belle_sip_free(content->lcp.type); - content->lcp.type = NULL; - } - if (type != NULL) { - content->lcp.type = belle_sip_strdup(type); - } + sal_body_handler_set_type(content->body_handler, type); } const char * linphone_content_get_subtype(const LinphoneContent *content) { - return content->lcp.subtype; + return sal_body_handler_get_subtype(content->body_handler); } void linphone_content_set_subtype(LinphoneContent *content, const char *subtype) { - if (content->lcp.subtype != NULL) { - belle_sip_free(content->lcp.subtype); - content->lcp.subtype = NULL; - } - if (subtype != NULL) { - content->lcp.subtype = belle_sip_strdup(subtype); - } + sal_body_handler_set_subtype(content->body_handler, subtype); } void * linphone_content_get_buffer(const LinphoneContent *content) { - return content->lcp.data; + return sal_body_handler_get_data(content->body_handler); } void linphone_content_set_buffer(LinphoneContent *content, const void *buffer, size_t size) { - content->lcp.size = size; - content->lcp.data = belle_sip_malloc(size + 1); - memcpy(content->lcp.data, buffer, size); - ((char *)content->lcp.data)[size] = '\0'; + void *data; + sal_body_handler_set_size(content->body_handler, size); + data = belle_sip_malloc(size + 1); + memcpy(data, buffer, size); + ((char *)data)[size] = '\0'; + sal_body_handler_set_data(content->body_handler, data); } const char * linphone_content_get_string_buffer(const LinphoneContent *content) { - return (char *)content->lcp.data; + return (const char *)linphone_content_get_buffer(content); } void linphone_content_set_string_buffer(LinphoneContent *content, const char *buffer) { - content->lcp.size = strlen(buffer); - content->lcp.data = belle_sip_strdup(buffer); + sal_body_handler_set_size(content->body_handler, strlen(buffer)); + sal_body_handler_set_data(content->body_handler, belle_sip_strdup(buffer)); } size_t linphone_content_get_size(const LinphoneContent *content) { - return content->lcp.size; + return sal_body_handler_get_size(content->body_handler); } void linphone_content_set_size(LinphoneContent *content, size_t size) { - content->lcp.size = size; + sal_body_handler_set_size(content->body_handler, size); } const char * linphone_content_get_encoding(const LinphoneContent *content) { - return content->lcp.encoding; + return sal_body_handler_get_encoding(content->body_handler); } void linphone_content_set_encoding(LinphoneContent *content, const char *encoding) { - if (content->lcp.encoding != NULL) { - belle_sip_free(content->lcp.encoding); - content->lcp.encoding = NULL; - } - if (encoding != NULL) { - content->lcp.encoding = belle_sip_strdup(encoding); - } + sal_body_handler_set_encoding(content->body_handler, encoding); } const char * linphone_content_get_name(const LinphoneContent *content) { - return content->lcp.name; + return content->name; } void linphone_content_set_name(LinphoneContent *content, const char *name) { - if (content->lcp.name != NULL) { - belle_sip_free(content->lcp.name); - content->lcp.name = NULL; + if (content->name != NULL) { + belle_sip_free(content->name); + content->name = NULL; } if (name != NULL) { - content->lcp.name = belle_sip_strdup(name); + content->name = belle_sip_strdup(name); } } size_t linphone_content_get_key_size(const LinphoneContent *content) { - return content->lcp.keyLength; + return content->keyLength; } const char * linphone_content_get_key(const LinphoneContent *content) { - return content->lcp.key; + return content->key; } void linphone_content_set_key(LinphoneContent *content, const char *key, const size_t keyLength) { - if (content->lcp.key != NULL) { - belle_sip_free(content->lcp.key); - content->lcp.key = NULL; + if (content->key != NULL) { + belle_sip_free(content->key); + content->key = NULL; } if (key != NULL) { - content->lcp.key = belle_sip_malloc(keyLength); - memcpy(content->lcp.key, key, keyLength); + content->key = belle_sip_malloc(keyLength); + memcpy(content->key, key, keyLength); } } /* crypto context is managed(allocated/freed) by the encryption function, so provide the address of field in the private structure */ void ** linphone_content_get_cryptoContext_address(LinphoneContent *content) { - return &(content->lcp.cryptoContext); + return &(content->cryptoContext); +} + +bool_t linphone_content_is_multipart(const LinphoneContent *content) { + // TODO + return FALSE; +} + +LinphoneContent * linphone_content_get_part(const LinphoneContent *content) { + // TODO + return NULL; +} + +void linphone_content_add_part(LinphoneContent *content, LinphoneContent *part) { + // TODO +} + +const char * linphone_content_get_custom_header(const LinphoneContent *content, const char *header_name) { + // TODO + return NULL; +} + +void linphone_content_add_custom_header(LinphoneContent *content, const char *header_name, const char *header_value) { + // TODO } + LinphoneContent * linphone_content_new(void) { - LinphoneContent *content = belle_sip_object_new(LinphoneContent); - belle_sip_object_ref(content); - content->owned_fields = TRUE; - content->lcp.cryptoContext = NULL; /* this field is managed externally by encryption/decryption functions so be careful to initialise it to NULL */ - return content; + return linphone_content_new_with_body_handler(NULL); } LinphoneContent * linphone_content_copy(const LinphoneContent *ref) { return (LinphoneContent *)belle_sip_object_ref(belle_sip_object_clone(BELLE_SIP_OBJECT(ref))); } -LinphoneContent * linphone_content_from_sal_body(const SalBody *ref) { - if (ref && ref->type) { - LinphoneContent *content = linphone_content_new(); - linphone_content_set_type(content, ref->type); - linphone_content_set_subtype(content, ref->subtype); - linphone_content_set_encoding(content, ref->encoding); - if (ref->data != NULL) { - linphone_content_set_buffer(content, ref->data, ref->size); - } else { - linphone_content_set_size(content, ref->size); - } - return content; +LinphoneContent * linphone_content_from_sal_body_handler(SalBodyHandler *body_handler) { + if (body_handler) { + return linphone_content_new_with_body_handler(body_handler); } return NULL; } -SalBody *sal_body_from_content(SalBody *body, const LinphoneContent *content) { - if (content && linphone_content_get_type(content)) { - body->type = linphone_content_get_type(content); - body->subtype = linphone_content_get_subtype(content); - body->data = linphone_content_get_buffer(content); - body->size = linphone_content_get_size(content); - body->encoding = linphone_content_get_encoding(content); - return body; - } - return NULL; -} - - - -LinphoneContent * linphone_content_private_to_linphone_content(const LinphoneContentPrivate *lcp) { - LinphoneContent *content = belle_sip_object_new(LinphoneContent); - memcpy(&content->lcp, lcp, sizeof(LinphoneContentPrivate)); - content->owned_fields = FALSE; - return content; -} - -LinphoneContentPrivate * linphone_content_to_linphone_content_private(const LinphoneContent *content) { - return (LinphoneContentPrivate *)&content->lcp; +SalBodyHandler * sal_body_handler_from_content(const LinphoneContent *content) { + if (content == NULL) return NULL; + return content->body_handler; } diff --git a/coreapi/content.h b/coreapi/content.h index 1e21138eb..ea3eda32c 100644 --- a/coreapi/content.h +++ b/coreapi/content.h @@ -40,51 +40,6 @@ struct _LinphoneContent; **/ typedef struct _LinphoneContent LinphoneContent; -/** - * @deprecated Use LinphoneContent objects instead of this structure. - */ -struct _LinphoneContentPrivate{ - char *type; /**dir!=LinphoneSubscriptionOutgoing){ @@ -179,7 +179,8 @@ int linphone_event_send_subscribe(LinphoneEvent *lev, const LinphoneContent *bod lev->send_custom_headers=NULL; }else sal_op_set_sent_custom_header(lev->op,NULL); - err=sal_subscribe(lev->op,NULL,NULL,lev->name,lev->expires,sal_body_from_content(&salbody,body)); + body_handler = sal_body_handler_from_content(body); + err=sal_subscribe(lev->op,NULL,NULL,lev->name,lev->expires,body_handler); if (err==0){ if (lev->subscription_state==LinphoneSubscriptionNone) linphone_event_set_state(lev,LinphoneSubscriptionOutgoingInit); @@ -216,7 +217,7 @@ int linphone_event_deny_subscription(LinphoneEvent *lev, LinphoneReason reason){ } int linphone_event_notify(LinphoneEvent *lev, const LinphoneContent *body){ - SalBody salbody; + SalBodyHandler *body_handler; if (lev->subscription_state!=LinphoneSubscriptionActive){ ms_error("linphone_event_notify(): cannot notify if subscription is not active."); return -1; @@ -225,7 +226,8 @@ int linphone_event_notify(LinphoneEvent *lev, const LinphoneContent *body){ ms_error("linphone_event_notify(): cannot notify if not an incoming subscription."); return -1; } - return sal_notify(lev->op,sal_body_from_content(&salbody,body)); + body_handler = sal_body_handler_from_content(body); + return sal_notify(lev->op, body_handler); } LinphoneEvent *linphone_core_create_publish(LinphoneCore *lc, const LinphoneAddress *resource, const char *event, int expires){ @@ -236,7 +238,7 @@ LinphoneEvent *linphone_core_create_publish(LinphoneCore *lc, const LinphoneAddr } static int _linphone_event_send_publish(LinphoneEvent *lev, const LinphoneContent *body, bool_t notify_err){ - SalBody salbody; + SalBodyHandler *body_handler; int err; if (lev->dir!=LinphoneSubscriptionInvalidDir){ @@ -247,7 +249,8 @@ static int _linphone_event_send_publish(LinphoneEvent *lev, const LinphoneConten sal_op_set_sent_custom_header(lev->op,lev->send_custom_headers); lev->send_custom_headers=NULL; }else sal_op_set_sent_custom_header(lev->op,NULL); - err=sal_publish(lev->op,NULL,NULL,lev->name,lev->expires,sal_body_from_content(&salbody,body)); + body_handler = sal_body_handler_from_content(body); + err=sal_publish(lev->op,NULL,NULL,lev->name,lev->expires,body_handler); if (err==0){ linphone_event_set_publish_state(lev,LinphonePublishProgress); }else if (notify_err){ diff --git a/coreapi/info.c b/coreapi/info.c index f33a16997..87f1bd199 100644 --- a/coreapi/info.c +++ b/coreapi/info.c @@ -69,10 +69,10 @@ LinphoneInfoMessage *linphone_core_create_info_message(LinphoneCore *lc){ * @param call the call * @param info the info message **/ -int linphone_call_send_info_message(LinphoneCall *call, const LinphoneInfoMessage *info){ - SalBody body; - sal_op_set_sent_custom_header(call->op,info->headers); - return sal_send_info(call->op,NULL, NULL, sal_body_from_content(&body,info->content)); +int linphone_call_send_info_message(LinphoneCall *call, const LinphoneInfoMessage *info) { + SalBodyHandler *body_handler = sal_body_handler_from_content(info->content); + sal_op_set_sent_custom_header(call->op, info->headers); + return sal_send_info(call->op,NULL, NULL, body_handler); } /** @@ -112,12 +112,12 @@ const LinphoneContent * linphone_info_message_get_content(const LinphoneInfoMess return (im->content && linphone_content_get_type(im->content)) ? im->content : NULL; } -void linphone_core_notify_info_message(LinphoneCore* lc,SalOp *op, const SalBody *body){ +void linphone_core_notify_info_message(LinphoneCore* lc,SalOp *op, SalBodyHandler *body_handler){ LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); if (call){ LinphoneInfoMessage *info=ms_new0(LinphoneInfoMessage,1); info->headers=sal_custom_header_clone(sal_op_get_recv_custom_header(op)); - if (body) info->content=linphone_content_from_sal_body(body); + if (body_handler) info->content=linphone_content_from_sal_body_handler(body_handler); linphone_core_notify_info_received(lc,call,info); linphone_info_message_destroy(info); } diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index fb3a39e9b..060856238 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -520,7 +520,7 @@ static void process_response_from_post_file_log_collection(void *data, const bel (belle_sip_header_t *)belle_sip_header_content_type_create(linphone_content_get_type(core->log_collection_upload_information), linphone_content_get_subtype(core->log_collection_upload_information))); /* Insert it in a multipart body handler which will manage the boundaries of multipart message */ - bh = belle_sip_multipart_body_handler_new(log_collection_upload_on_progress, core, (belle_sip_body_handler_t *)first_part_bh); + bh = belle_sip_multipart_body_handler_new(log_collection_upload_on_progress, core, (belle_sip_body_handler_t *)first_part_bh, NULL); ua = ms_strdup_printf("%s/%s", linphone_core_get_user_agent_name(), linphone_core_get_user_agent_version()); uri = belle_generic_uri_parse(linphone_core_get_log_collection_upload_server_url(core)); req = belle_http_request_create("POST", uri, belle_sip_header_create("User-Agent", ua), NULL); diff --git a/coreapi/private.h b/coreapi/private.h index 5c2777f4e..e279c6bdd 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -1071,10 +1071,10 @@ const char *linphone_core_create_uuid(LinphoneCore *lc); void linphone_configure_op(LinphoneCore *lc, SalOp *op, const LinphoneAddress *dest, SalCustomHeader *headers, bool_t with_contact); void linphone_call_create_op(LinphoneCall *call); int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer); -void linphone_core_notify_info_message(LinphoneCore* lc,SalOp *op, const SalBody *body); +void linphone_core_notify_info_message(LinphoneCore* lc,SalOp *op, SalBodyHandler *body); LinphoneContent * linphone_content_new(void); LinphoneContent * linphone_content_copy(const LinphoneContent *ref); -SalBody *sal_body_from_content(SalBody *body, const LinphoneContent *content); +SalBodyHandler *sal_body_handler_from_content(const LinphoneContent *content); SalReason linphone_reason_to_sal(LinphoneReason reason); LinphoneReason linphone_reason_from_sal(SalReason reason); LinphoneEvent *linphone_event_new(LinphoneCore *lc, LinphoneSubscriptionDir dir, const char *name, int expires); @@ -1086,14 +1086,18 @@ LinphoneEvent *linphone_event_new_with_out_of_dialog_op(LinphoneCore *lc, SalOp void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState state); void linphone_event_set_publish_state(LinphoneEvent *lev, LinphonePublishState state); LinphoneSubscriptionState linphone_subscription_state_from_sal(SalSubscribeStatus ss); -LinphoneContent *linphone_content_from_sal_body(const SalBody *ref); +LinphoneContent *linphone_content_from_sal_body_handler(SalBodyHandler *ref); void linphone_core_invalidate_friend_subscriptions(LinphoneCore *lc); struct _LinphoneContent { belle_sip_object_t base; void *user_data; - struct _LinphoneContentPrivate lcp; + SalBodyHandler *body_handler; + char *name; /**< used by RCS File transfer messages to store the original filename of the file to be downloaded from server */ + char *key; /**< used by RCS File transfer messages to store the key to encrypt file if needed */ + size_t keyLength; /**< Length of key in bytes */ + void *cryptoContext; /**< crypto context used to encrypt file for RCS file transfer */ bool_t owned_fields; }; diff --git a/coreapi/sal.c b/coreapi/sal.c index 2c858298a..9ed121463 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -849,10 +849,101 @@ int sal_lines_get_value(const char *data, const char *key, char *value, size_t v return FALSE; } -int sal_body_has_type(const SalBody *body, const char *type, const char *subtype){ - return body->type && body->subtype - && strcmp(body->type,type)==0 - && strcmp(body->subtype,subtype)==0; +static belle_sip_header_t * sal_body_handler_find_header(const SalBodyHandler *body_handler, const char *header_name) { + belle_sip_body_handler_t *bsbh = BELLE_SIP_BODY_HANDLER(body_handler); + const belle_sip_list_t *l = belle_sip_body_handler_get_headers(bsbh); + for (; l != NULL; l = l->next) { + belle_sip_header_t *header = BELLE_SIP_HEADER(l->data); + if (strcmp(belle_sip_header_get_name(header), header_name) == 0) { + return header; + } + } + return NULL; +} + +SalBodyHandler * sal_body_handler_new(void) { + belle_sip_memory_body_handler_t *body_handler = belle_sip_memory_body_handler_new(NULL, NULL); + return (SalBodyHandler *)BELLE_SIP_BODY_HANDLER(body_handler); +} + +SalBodyHandler * sal_body_handler_ref(SalBodyHandler *body_handler) { + return (SalBodyHandler *)belle_sip_object_ref(BELLE_SIP_OBJECT(body_handler)); +} + +void sal_body_handler_unref(SalBodyHandler *body_handler) { + belle_sip_object_unref(BELLE_SIP_OBJECT(body_handler)); +} + +const char * sal_body_handler_get_type(const SalBodyHandler *body_handler) { + belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type")); + if (content_type != NULL) { + return belle_sip_header_content_type_get_type(content_type); + } + return NULL; +} + +void sal_body_handler_set_type(SalBodyHandler *body_handler, const char *type) { + belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type")); + if (content_type == NULL) { + content_type = belle_sip_header_content_type_new(); + belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(body_handler), BELLE_SIP_HEADER(content_type)); + } + belle_sip_header_content_type_set_type(content_type, type); +} + +const char * sal_body_handler_get_subtype(const SalBodyHandler *body_handler) { + belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type")); + if (content_type != NULL) { + return belle_sip_header_content_type_get_subtype(content_type); + } + return NULL; +} + +void sal_body_handler_set_subtype(SalBodyHandler *body_handler, const char *subtype) { + belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type")); + if (content_type == NULL) { + content_type = belle_sip_header_content_type_new(); + belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(body_handler), BELLE_SIP_HEADER(content_type)); + } + belle_sip_header_content_type_set_subtype(content_type, subtype); +} + +const char * sal_body_handler_get_encoding(const SalBodyHandler *body_handler) { + belle_sip_header_t *content_encoding = sal_body_handler_find_header(body_handler, "Content-Encoding"); + if (content_encoding != NULL) { + return belle_sip_header_get_unparsed_value(content_encoding); + } + return NULL; +} + +void sal_body_handler_set_encoding(SalBodyHandler *body_handler, const char *encoding) { + belle_sip_header_t *content_encoding = sal_body_handler_find_header(body_handler, "Content-Encoding"); + if (content_encoding != NULL) { + belle_sip_body_handler_remove_header_from_ptr(BELLE_SIP_BODY_HANDLER(body_handler), content_encoding); + } + belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(body_handler), belle_sip_header_create("Content-Encoding", encoding)); +} + +void * sal_body_handler_get_data(const SalBodyHandler *body_handler) { + return belle_sip_memory_body_handler_get_buffer(BELLE_SIP_MEMORY_BODY_HANDLER(body_handler)); +} + +void sal_body_handler_set_data(SalBodyHandler *body_handler, void *data) { + belle_sip_memory_body_handler_set_buffer(BELLE_SIP_MEMORY_BODY_HANDLER(body_handler), data); +} + +size_t sal_body_handler_get_size(const SalBodyHandler *body_handler) { + return belle_sip_body_handler_get_size(BELLE_SIP_BODY_HANDLER(body_handler)); +} + +void sal_body_handler_set_size(SalBodyHandler *body_handler, size_t size) { + belle_sip_header_content_length_t *content_length = BELLE_SIP_HEADER_CONTENT_LENGTH(sal_body_handler_find_header(body_handler, "Content-Length")); + if (content_length == NULL) { + content_length = belle_sip_header_content_length_new(); + belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(body_handler), BELLE_SIP_HEADER(content_length)); + } + belle_sip_header_content_length_set_content_length(content_length, size); + belle_sip_body_handler_set_size(BELLE_SIP_BODY_HANDLER(body_handler), size); } belle_sip_stack_t *sal_get_belle_sip_stack(Sal *sal) { diff --git a/include/sal/sal.h b/include/sal/sal.h index 6e1c4d068..468696b29 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -55,6 +55,10 @@ struct SalAddress; typedef struct SalAddress SalAddress; +struct SalBodyHandler; + +typedef struct SalBodyHandler SalBodyHandler; + struct SalCustomHeader; typedef struct SalCustomHeader SalCustomHeader; @@ -453,14 +457,6 @@ typedef struct SalAuthInfo{ SalCertificatesChain *certificates; }SalAuthInfo; -typedef struct SalBody{ - const char *type; - const char *subtype; - const void *data; - size_t size; - const char *encoding; -}SalBody; - typedef void (*SalOnCallReceived)(SalOp *op); typedef void (*SalOnCallRinging)(SalOp *op); typedef void (*SalOnCallAccepted)(SalOp *op); @@ -482,8 +478,8 @@ typedef void (*SalOnTextDeliveryUpdate)(SalOp *op, SalTextDeliveryStatus); typedef void (*SalOnIsComposingReceived)(SalOp *op, const SalIsComposing *is_composing); typedef void (*SalOnNotifyRefer)(SalOp *op, SalReferStatus state); typedef void (*SalOnSubscribeResponse)(SalOp *op, SalSubscribeStatus status); -typedef void (*SalOnNotify)(SalOp *op, SalSubscribeStatus status, const char *event, const SalBody *body); -typedef void (*SalOnSubscribeReceived)(SalOp *salop, const char *event, const SalBody *body); +typedef void (*SalOnNotify)(SalOp *op, SalSubscribeStatus status, const char *event, SalBodyHandler *body); +typedef void (*SalOnSubscribeReceived)(SalOp *salop, const char *event, const SalBodyHandler *body); typedef void (*SalOnSubscribeClosed)(SalOp *salop); typedef void (*SalOnParsePresenceRequested)(SalOp *salop, const char *content_type, const char *content_subtype, const char *content, SalPresenceModel **result); typedef void (*SalOnConvertPresenceToXMLRequested)(SalOp *salop, SalPresenceModel *presence, const char *contact, char **content); @@ -491,7 +487,7 @@ typedef void (*SalOnNotifyPresence)(SalOp *op, SalSubscribeStatus ss, SalPresenc typedef void (*SalOnSubscribePresenceReceived)(SalOp *salop, const char *from); typedef void (*SalOnSubscribePresenceClosed)(SalOp *salop, const char *from); typedef void (*SalOnPingReply)(SalOp *salop); -typedef void (*SalOnInfoReceived)(SalOp *salop, const SalBody *body); +typedef void (*SalOnInfoReceived)(SalOp *salop, SalBodyHandler *body); typedef void (*SalOnPublishResponse)(SalOp *salop); typedef void (*SalOnExpire)(SalOp *salop); /*allows sal implementation to access auth info if available, return TRUE if found*/ @@ -739,16 +735,16 @@ int sal_publish_presence(SalOp *op, const char *from, const char *to, int expire int sal_ping(SalOp *op, const char *from, const char *to); /*info messages*/ -int sal_send_info(SalOp *op, const char *from, const char *to, const SalBody *body); +int sal_send_info(SalOp *op, const char *from, const char *to, const SalBodyHandler *body); /*generic subscribe/notify/publish api*/ -int sal_subscribe(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBody *body); +int sal_subscribe(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBodyHandler *body); int sal_unsubscribe(SalOp *op); int sal_subscribe_accept(SalOp *op); int sal_subscribe_decline(SalOp *op, SalReason reason); -int sal_notify(SalOp *op, const SalBody *body); +int sal_notify(SalOp *op, const SalBodyHandler *body); int sal_notify_close(SalOp *op); -int sal_publish(SalOp *op, const char *from, const char *to, const char*event_name, int expires, const SalBody *body); +int sal_publish(SalOp *op, const char *from, const char *to, const char*event_name, int expires, const SalBodyHandler *body); /*privacy, must be in sync with LinphonePrivacyMask*/ typedef enum _SalPrivacy { @@ -844,7 +840,21 @@ unsigned char * sal_get_random_bytes(unsigned char *ret, size_t size); belle_sip_source_t * sal_create_timer(Sal *sal, belle_sip_source_func_t func, void *data, unsigned int timeout_value_ms, const char* timer_name); void sal_cancel_timer(Sal *sal, belle_sip_source_t *timer); -int sal_body_has_type(const SalBody *body, const char *type, const char *subtype); +//SalBodyHandler * sal_body_handler_new(const char *type, const char *subtype, void *data, size_t size, const char *encoding); +SalBodyHandler * sal_body_handler_new(void); +SalBodyHandler * sal_body_handler_ref(SalBodyHandler *body_handler); +void sal_body_handler_unref(SalBodyHandler *body_handler); +const char * sal_body_handler_get_type(const SalBodyHandler *body_handler); +void sal_body_handler_set_type(SalBodyHandler *body_handler, const char *type); +const char * sal_body_handler_get_subtype(const SalBodyHandler *body_handler); +void sal_body_handler_set_subtype(SalBodyHandler *body_handler, const char *subtype); +const char * sal_body_handler_get_encoding(const SalBodyHandler *body_handler); +void sal_body_handler_set_encoding(SalBodyHandler *body_handler, const char *encoding); +void * sal_body_handler_get_data(const SalBodyHandler *body_handler); +void sal_body_handler_set_data(SalBodyHandler *body_handler, void *data); +size_t sal_body_handler_get_size(const SalBodyHandler *body_handler); +void sal_body_handler_set_size(SalBodyHandler *body_handler, size_t size); + /*this function parses a document with key=value pairs separated by new lines, and extracts the value for a given key*/ int sal_lines_get_value(const char *data, const char *key, char *value, size_t value_size); From 9282915a1c64849601b2b2495f1d791492f20898 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Fri, 27 Nov 2015 11:42:10 +0100 Subject: [PATCH 05/30] Handle multipart contents. --- coreapi/content.c | 26 ++++++++++++-------------- coreapi/content.h | 30 ++++++++++++++++++++++++++---- coreapi/sal.c | 33 +++++++++++++++++++++++++++++++++ include/sal/sal.h | 4 ++++ 4 files changed, 75 insertions(+), 18 deletions(-) diff --git a/coreapi/content.c b/coreapi/content.c index a5a66f1b9..cc0760b0a 100644 --- a/coreapi/content.c +++ b/coreapi/content.c @@ -196,29 +196,27 @@ void ** linphone_content_get_cryptoContext_address(LinphoneContent *content) { } bool_t linphone_content_is_multipart(const LinphoneContent *content) { - // TODO - return FALSE; + return sal_body_handler_is_multipart(content->body_handler); } -LinphoneContent * linphone_content_get_part(const LinphoneContent *content) { - // TODO - return NULL; +LinphoneContent * linphone_content_get_part(const LinphoneContent *content, int idx) { + SalBodyHandler *part_body_handler; + if (!linphone_content_is_multipart(content)) return NULL; + part_body_handler = sal_body_handler_get_part(content->body_handler, idx); + return linphone_content_from_sal_body_handler(part_body_handler); } -void linphone_content_add_part(LinphoneContent *content, LinphoneContent *part) { - // TODO +LinphoneContent * linphone_content_find_part_by_header(const LinphoneContent *content, const char *header_name, const char *header_value) { + SalBodyHandler *part_body_handler; + if (!linphone_content_is_multipart(content)) return NULL; + part_body_handler = sal_body_handler_find_part_by_header(content->body_handler, header_name, header_value); + return linphone_content_from_sal_body_handler(part_body_handler); } const char * linphone_content_get_custom_header(const LinphoneContent *content, const char *header_name) { - // TODO - return NULL; + return sal_body_handler_get_header(content->body_handler, header_name); } -void linphone_content_add_custom_header(LinphoneContent *content, const char *header_name, const char *header_value) { - // TODO -} - - LinphoneContent * linphone_content_new(void) { return linphone_content_new_with_body_handler(NULL); diff --git a/coreapi/content.h b/coreapi/content.h index ea3eda32c..104488d42 100644 --- a/coreapi/content.h +++ b/coreapi/content.h @@ -174,16 +174,38 @@ LINPHONE_PUBLIC const char * linphone_content_get_name(const LinphoneContent *co */ LINPHONE_PUBLIC void linphone_content_set_name(LinphoneContent *content, const char *name); +/** + * Tell whether a content is a multipart content. + * @param[in] content LinphoneContent object. + * @return A boolean value telling whether the content is multipart or not. + */ LINPHONE_PUBLIC bool_t linphone_content_is_multipart(const LinphoneContent *content); -LINPHONE_PUBLIC LinphoneContent * linphone_content_get_part(const LinphoneContent *content); +/** + * Get a part from a multipart content according to its index. + * @param[in] content LinphoneContent object. + * @param[in] idx The index of the part to get. + * @return A LinphoneContent object holding the part if found, NULL otherwise. + */ +LINPHONE_PUBLIC LinphoneContent * linphone_content_get_part(const LinphoneContent *content, int idx); -LINPHONE_PUBLIC void linphone_content_add_part(LinphoneContent *content, LinphoneContent *part); +/** + * Find a part from a multipart content looking for a part header with a specified value. + * @param[in] content LinphoneContent object. + * @param[in] header_name The name of the header to look for. + * @param[in] header_value The value of the header to look for. + * @return A LinphoneContent object object the part if found, NULL otherwise. + */ +LINPHONE_PUBLIC LinphoneContent * linphone_content_find_part_by_header(const LinphoneContent *content, const char *header_name, const char *header_value); +/** + * Get a custom header value of a content. + * @param[in] content LinphoneContent object. + * @param[in] header_name The name of the header to get the value from. + * @return The value of the header if found, NULL otherwise. + */ LINPHONE_PUBLIC const char * linphone_content_get_custom_header(const LinphoneContent *content, const char *header_name); -LINPHONE_PUBLIC void linphone_content_add_custom_header(LinphoneContent *content, const char *header_name, const char *header_value); - /** * @} */ diff --git a/coreapi/sal.c b/coreapi/sal.c index 9ed121463..491e100fb 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -946,6 +946,39 @@ void sal_body_handler_set_size(SalBodyHandler *body_handler, size_t size) { belle_sip_body_handler_set_size(BELLE_SIP_BODY_HANDLER(body_handler), size); } +bool_t sal_body_handler_is_multipart(const SalBodyHandler *body_handler) { + if (BELLE_SIP_IS_INSTANCE_OF(body_handler, belle_sip_multipart_body_handler_t)) return TRUE; + return FALSE; +} + +SalBodyHandler * sal_body_handler_get_part(const SalBodyHandler *body_handler, int idx) { + const belle_sip_list_t *l = belle_sip_multipart_body_handler_get_parts(BELLE_SIP_MULTIPART_BODY_HANDLER(body_handler)); + return (SalBodyHandler *)belle_sip_list_nth_data(l, idx); +} + +SalBodyHandler * sal_body_handler_find_part_by_header(const SalBodyHandler *body_handler, const char *header_name, const char *header_value) { + const belle_sip_list_t *l = belle_sip_multipart_body_handler_get_parts(BELLE_SIP_MULTIPART_BODY_HANDLER(body_handler)); + for (; l != NULL; l = l->next) { + belle_sip_body_handler_t *bsbh = BELLE_SIP_BODY_HANDLER(l->data); + const belle_sip_list_t *headers = belle_sip_body_handler_get_headers(bsbh); + for (; headers != NULL; headers = headers->next) { + belle_sip_header_t *header = BELLE_SIP_HEADER(headers->data); + if ((strcmp(belle_sip_header_get_name(header), header_name) == 0) && (strcmp(belle_sip_header_get_unparsed_value(header), header_value) == 0)) { + return (SalBodyHandler *)bsbh; + } + } + } + return NULL; +} + +const char * sal_body_handler_get_header(const SalBodyHandler *body_handler, const char *header_name) { + belle_sip_header_t *header = sal_body_handler_find_header(body_handler, header_name); + if (header != NULL) { + return belle_sip_header_get_unparsed_value(header); + } + return NULL; +} + belle_sip_stack_t *sal_get_belle_sip_stack(Sal *sal) { return sal->stack; } diff --git a/include/sal/sal.h b/include/sal/sal.h index 468696b29..6031278bf 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -854,6 +854,10 @@ void * sal_body_handler_get_data(const SalBodyHandler *body_handler); void sal_body_handler_set_data(SalBodyHandler *body_handler, void *data); size_t sal_body_handler_get_size(const SalBodyHandler *body_handler); void sal_body_handler_set_size(SalBodyHandler *body_handler, size_t size); +bool_t sal_body_handler_is_multipart(const SalBodyHandler *body_handler); +SalBodyHandler * sal_body_handler_get_part(const SalBodyHandler *body_handler, int idx); +SalBodyHandler * sal_body_handler_find_part_by_header(const SalBodyHandler *body_handler, const char *header_name, const char *header_value); +const char * sal_body_handler_get_header(const SalBodyHandler *body_handler, const char *header_name); /*this function parses a document with key=value pairs separated by new lines, and extracts the value for a given key*/ int sal_lines_get_value(const char *data, const char *key, char *value, size_t value_size); From 3cb24866dd6cfa0091f7d50ea5abeac4ab1d8a67 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Fri, 27 Nov 2015 11:42:33 +0100 Subject: [PATCH 06/30] Fix wrong comment. --- coreapi/buffer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreapi/buffer.h b/coreapi/buffer.h index 0d22e9ad2..492629353 100644 --- a/coreapi/buffer.h +++ b/coreapi/buffer.h @@ -144,4 +144,4 @@ LINPHONE_PUBLIC bool_t linphone_buffer_is_empty(const LinphoneBuffer *buffer); } #endif -#endif /* LINPHONE_CONTENT_H_ */ +#endif /* LINPHONE_BUFFER_H_ */ From 97f28a65ca8caee473f5fede1b303f87b3450ea5 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Fri, 27 Nov 2015 11:44:16 +0100 Subject: [PATCH 07/30] Basic parsing of presence list notify. --- coreapi/callbacks.c | 2 +- coreapi/friend.c | 7 ++++ coreapi/friendlist.c | 87 ++++++++++++++++++++++++++++++++++++++++ coreapi/linphonecore.c | 9 +++++ coreapi/linphonefriend.h | 7 ++++ coreapi/presence.c | 7 +--- coreapi/private.h | 3 +- 7 files changed, 115 insertions(+), 7 deletions(-) diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index b19f468f1..1046a308c 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -1122,7 +1122,7 @@ static void is_composing_received(SalOp *op, const SalIsComposing *is_composing) } static void parse_presence_requested(SalOp *op, const char *content_type, const char *content_subtype, const char *body, SalPresenceModel **result) { - linphone_notify_parse_presence(op, content_type, content_subtype, body, result); + linphone_notify_parse_presence(content_type, content_subtype, body, result); } static void convert_presence_to_xml_requested(SalOp *op, SalPresenceModel *presence, const char *contact, char **content) { diff --git a/coreapi/friend.c b/coreapi/friend.c index e15fed661..228a037c3 100644 --- a/coreapi/friend.c +++ b/coreapi/friend.c @@ -389,6 +389,13 @@ const LinphonePresenceModel * linphone_friend_get_presence_model(LinphoneFriend return lf->presence; } +void linphone_friend_set_presence_model(LinphoneFriend *lf, LinphonePresenceModel *presence) { + if (lf->presence != NULL) { + linphone_presence_model_unref(lf->presence); + } + lf->presence = presence; +} + BuddyInfo * linphone_friend_get_info(const LinphoneFriend *lf){ return lf->info; } diff --git a/coreapi/friendlist.c b/coreapi/friendlist.c index 099433fff..2b27bc8da 100644 --- a/coreapi/friendlist.c +++ b/coreapi/friendlist.c @@ -91,6 +91,64 @@ static char * create_resource_list_xml(const LinphoneFriendList *list) { return xml_content; } +static void linphone_friend_list_parse_multipart_related_body(LinphoneFriendList *list, const LinphoneContent *body, const char *first_part_body) { + xmlparsing_context_t *xml_ctx = linphone_xmlparsing_context_new(); + xmlSetGenericErrorFunc(xml_ctx, linphone_xmlparsing_genericxml_error); + xml_ctx->doc = xmlReadDoc((const unsigned char*)first_part_body, 0, NULL, 0); + if (xml_ctx->doc != NULL) { + char xpath_str[MAX_XPATH_LENGTH]; + LinphoneFriend *friend; + LinphoneContent *presence_part; + xmlXPathObjectPtr resource_object; + const char *uri = NULL; + int i; + + if (linphone_create_xml_xpath_context(xml_ctx) < 0) goto end; + xmlXPathRegisterNs(xml_ctx->xpath_ctx, (const xmlChar *)"rlmi", (const xmlChar *)"urn:ietf:params:xml:ns:rlmi"); + resource_object = linphone_get_xml_xpath_object_for_node_list(xml_ctx, "/rlmi:list/rlmi:resource"); + if ((resource_object != NULL) && (resource_object->nodesetval != NULL)) { + for (i = 1; i <= resource_object->nodesetval->nodeNr; i++) { + snprintf(xpath_str, sizeof(xpath_str), "/rlmi:list/rlmi:resource[%i]/@uri", i); + uri = linphone_get_xml_text_content(xml_ctx, xpath_str); + if (uri == NULL) continue; + friend = linphone_friend_list_find_friend_by_uri(list, uri); + if (friend != NULL) { + const char *state = NULL; + snprintf(xpath_str, sizeof(xpath_str),"/rlmi:list/rlmi:resource[%i]/rlmi:instance/@state", i); + state = linphone_get_xml_text_content(xml_ctx, xpath_str); + if ((state != NULL) && (strcmp(state, "active") == 0)) { + const char *cid = NULL; + snprintf(xpath_str, sizeof(xpath_str),"/rlmi:list/rlmi:resource[%i]/rlmi:instance/@cid", i); + cid = linphone_get_xml_text_content(xml_ctx, xpath_str); + if (cid != NULL) { + presence_part = linphone_content_find_part_by_header(body, "Content-Id", cid); + if (presence_part == NULL) { + ms_warning("rlmi+xml: Cannot find part with Content-Id: %s", cid); + } else { + SalPresenceModel *presence = NULL; + linphone_notify_parse_presence(linphone_content_get_type(presence_part), linphone_content_get_subtype(presence_part), linphone_content_get_string_buffer(presence_part), &presence); + if (presence != NULL) { + linphone_friend_set_presence_model(friend, (LinphonePresenceModel *)presence); + linphone_core_notify_notify_presence_received(list->lc, friend); + } + } + } + if (cid != NULL) linphone_free_xml_text_content(cid); + } + if (state != NULL) linphone_free_xml_text_content(state); + } + linphone_free_xml_text_content(uri); + } + } + if (resource_object != NULL) xmlXPathFreeObject(resource_object); + } else { + ms_warning("Wrongly formatted rlmi+xml body: %s", xml_ctx->errorBuffer); + } + +end: + linphone_xmlparsing_context_destroy(xml_ctx); +} + static LinphoneFriendList * linphone_friend_list_new(void) { LinphoneFriendList *list = belle_sip_object_new(LinphoneFriendList); belle_sip_object_ref(list); @@ -249,6 +307,7 @@ void linphone_friend_list_update_subscriptions(LinphoneFriendList *list, Linphon int expires = lp_config_get_int(list->lc->config, "sip", "rls_presence_expires", 3600); event = linphone_core_create_subscribe(list->lc, address, "presence", expires); linphone_event_add_custom_header(event, "Require", "recipient-list-subscribe"); + linphone_event_add_custom_header(event, "Supported", "eventlist"); linphone_event_add_custom_header(event, "Accept", "multipart/related, application/pidf+xml, application/rlmi+xml"); linphone_event_add_custom_header(event, "Content-Disposition", "recipient-list"); content = linphone_core_create_content(list->lc); @@ -282,3 +341,31 @@ void linphone_friend_list_notify_presence(LinphoneFriendList *list, LinphonePres linphone_friend_notify(friend, presence); } } + +void linphone_friend_list_notify_presence_received(LinphoneFriendList *list, LinphoneEvent *lev, const LinphoneContent *body) { + if (linphone_content_is_multipart(body)) { + LinphoneContent *first_part; + const char *type = linphone_content_get_type(body); + const char *subtype = linphone_content_get_subtype(body); + + if ((strcmp(type, "multipart") != 0) || (strcmp(subtype, "related") != 0)) { + ms_warning("multipart presence notified but it is not 'multipart/related'"); + return; + } + + first_part = linphone_content_get_part(body, 0); + if (first_part == NULL) { + ms_warning("'multipart/related' presence notified but it doesn't contain any part"); + return; + } + + type = linphone_content_get_type(first_part); + subtype = linphone_content_get_subtype(first_part); + if ((strcmp(type, "application") != 0) || (strcmp(subtype, "rlmi+xml") != 0)) { + ms_warning("multipart presence notified but first part is not 'application/rlmi+xml'"); + return; + } + + linphone_friend_list_parse_multipart_related_body(list, body, linphone_content_get_string_buffer(first_part)); + } +} diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 060856238..79235453f 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1664,10 +1664,17 @@ static void linphone_core_register_default_codecs(LinphoneCore *lc){ linphone_core_register_static_payloads(lc); } +static void linphone_core_internal_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char *notified_event, const LinphoneContent *body) { + if (strcmp(notified_event, "Presence") == 0) { + linphone_friend_list_notify_presence_received(lc->friendlist, lev, body); + } +} + static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtable, LpConfig *config, void * userdata){ const char *rls_uri = NULL; const char *remote_provisioning_uri = NULL; LinphoneCoreVTable* local_vtable= linphone_core_v_table_new(); + LinphoneCoreVTable *internal_vtable = linphone_core_v_table_new(); ms_message("Initializing LinphoneCore %s", linphone_core_get_version()); lc->config=lp_config_ref(config); @@ -1679,6 +1686,8 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab linphone_friend_list_set_rls_uri(lc->friendlist, rls_uri); linphone_task_list_init(&lc->hooks); + internal_vtable->notify_received = linphone_core_internal_notify_received; + _linphone_core_add_listener(lc, internal_vtable, TRUE); memcpy(local_vtable,vtable,sizeof(LinphoneCoreVTable)); _linphone_core_add_listener(lc, local_vtable, TRUE); diff --git a/coreapi/linphonefriend.h b/coreapi/linphonefriend.h index 1a6535fed..53f747651 100644 --- a/coreapi/linphonefriend.h +++ b/coreapi/linphonefriend.h @@ -240,6 +240,13 @@ LINPHONE_PUBLIC LinphoneOnlineStatus linphone_friend_get_status(const LinphoneFr */ LINPHONE_PUBLIC const LinphonePresenceModel * linphone_friend_get_presence_model(LinphoneFriend *lf); +/** + * Set the presence model of a friend + * @param[in] lf A #LinphoneFriend object + * @param[in] presence The #LinphonePresenceModel object to set for the friend + */ +LINPHONE_PUBLIC void linphone_friend_set_presence_model(LinphoneFriend *lf, LinphonePresenceModel *presence); + /** * Store user pointer to friend object. **/ diff --git a/coreapi/presence.c b/coreapi/presence.c index d97ff865f..8465adcd0 100644 --- a/coreapi/presence.c +++ b/coreapi/presence.c @@ -1508,7 +1508,7 @@ void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from){ ms_free(tmp); } -void linphone_notify_parse_presence(SalOp *op, const char *content_type, const char *content_subtype, const char *body, SalPresenceModel **result) { +void linphone_notify_parse_presence(const char *content_type, const char *content_subtype, const char *body, SalPresenceModel **result) { xmlparsing_context_t *xml_ctx; LinphonePresenceModel *model = NULL; @@ -1866,10 +1866,7 @@ void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, Sa activity_str = linphone_presence_activity_to_string(activity); ms_message("We are notified that [%s] has presence [%s]", tmp, activity_str); if (activity_str != NULL) ms_free(activity_str); - if (lf->presence != NULL) { - linphone_presence_model_unref(lf->presence); - } - lf->presence = presence; + linphone_friend_set_presence_model(lf, presence); lf->subscribe_active=TRUE; linphone_core_notify_notify_presence_received(lc,(LinphoneFriend*)lf); ms_free(tmp); diff --git a/coreapi/private.h b/coreapi/private.h index e279c6bdd..5f134e484 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -377,6 +377,7 @@ void _linphone_proxy_config_release(LinphoneProxyConfig *cfg); const LinphoneAddress* linphone_proxy_config_get_service_route(const LinphoneProxyConfig* cfg); void linphone_friend_list_invalidate_subscriptions(LinphoneFriendList *list); +void linphone_friend_list_notify_presence_received(LinphoneFriendList *list, LinphoneEvent *lev, const LinphoneContent *body); void linphone_friend_invalidate_subscription(LinphoneFriend *lf); void linphone_friend_close_subscriptions(LinphoneFriend *lf); void linphone_friend_update_subscribes(LinphoneFriend *fr, LinphoneProxyConfig *cfg, bool_t only_when_registered); @@ -434,7 +435,7 @@ 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_core_send_presence(LinphoneCore *lc, LinphonePresenceModel *presence); -void linphone_notify_parse_presence(SalOp *op, const char *content_type, const char *content_subtype, const char *body, SalPresenceModel **result); +void linphone_notify_parse_presence(const char *content_type, const char *content_subtype, const char *body, SalPresenceModel **result); void linphone_notify_convert_presence_to_xml(SalOp *op, SalPresenceModel *presence, const char *contact, char **content); void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, SalPresenceModel *model); void linphone_proxy_config_process_authentication_failure(LinphoneCore *lc, SalOp *op); From fccaa5e36eb67ed6843dbd787b14ef1d461068c1 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Mon, 30 Nov 2015 11:39:21 +0100 Subject: [PATCH 08/30] Handle versioning of presence list notifications + store information that we have received presence information for a friend. --- coreapi/friend.c | 7 ++++++ coreapi/friendlist.c | 51 +++++++++++++++++++++++++++++++++++++++- coreapi/linphonefriend.h | 7 ++++++ coreapi/presence.c | 1 + coreapi/private.h | 3 +++ coreapi/xml.c | 27 +++++++++++++++++++++ 6 files changed, 95 insertions(+), 1 deletion(-) diff --git a/coreapi/friend.c b/coreapi/friend.c index 228a037c3..8b602843f 100644 --- a/coreapi/friend.c +++ b/coreapi/friend.c @@ -396,6 +396,10 @@ void linphone_friend_set_presence_model(LinphoneFriend *lf, LinphonePresenceMode lf->presence = presence; } +bool_t linphone_friend_is_presence_received(const LinphoneFriend *lf) { + return lf->presence_received; +} + BuddyInfo * linphone_friend_get_info(const LinphoneFriend *lf){ return lf->info; } @@ -597,6 +601,8 @@ 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, "presence_received", 0); + lf->presence_received = (bool_t)a; linphone_friend_set_ref_key(lf,lp_config_get_string(config,item,"refkey",NULL)); return lf; @@ -639,6 +645,7 @@ 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); + lp_config_set_int(config, key, "presence_received", lf->presence_received); refkey=linphone_friend_get_ref_key(lf); if (refkey){ diff --git a/coreapi/friendlist.c b/coreapi/friendlist.c index 2b27bc8da..ef9c13a23 100644 --- a/coreapi/friendlist.c +++ b/coreapi/friendlist.c @@ -100,11 +100,47 @@ static void linphone_friend_list_parse_multipart_related_body(LinphoneFriendList LinphoneFriend *friend; LinphoneContent *presence_part; xmlXPathObjectPtr resource_object; + const char *version_str = NULL; + const char *full_state_str = NULL; const char *uri = NULL; + bool_t full_state = FALSE; + int version; int i; if (linphone_create_xml_xpath_context(xml_ctx) < 0) goto end; xmlXPathRegisterNs(xml_ctx->xpath_ctx, (const xmlChar *)"rlmi", (const xmlChar *)"urn:ietf:params:xml:ns:rlmi"); + + version_str = linphone_get_xml_attribute_text_content(xml_ctx, "/rlmi:list", "version"); + if (version_str == NULL) { + ms_warning("rlmi+xml: No version attribute in list"); + goto end; + } + version = atoi(version_str); + if (version < list->expected_notification_version) { + ms_warning("rlmi+xml: Discarding received notification with version %d because %d was expected", version, list->expected_notification_version); + goto end; + } + + full_state_str = linphone_get_xml_attribute_text_content(xml_ctx, "/rlmi:list", "fullState"); + if (full_state_str == NULL) { + ms_warning("rlmi+xml: No fullState attribute in list"); + goto end; + } + if ((strcmp(full_state_str, "true") == 0) || (strcmp(full_state_str, "1") == 0)) { + MSList *l = list->friends; + for (; l != NULL; l = l->next) { + friend = (LinphoneFriend *)l->data; + linphone_friend_set_presence_model(friend, NULL); + } + full_state = TRUE; + } + linphone_free_xml_text_content(full_state_str); + if ((list->expected_notification_version == 0) && (full_state == FALSE)) { + ms_warning("rlmi+xml: Notification with version 0 is not full state, this is not valid"); + goto end; + } + list->expected_notification_version = version + 1; + resource_object = linphone_get_xml_xpath_object_for_node_list(xml_ctx, "/rlmi:list/rlmi:resource"); if ((resource_object != NULL) && (resource_object->nodesetval != NULL)) { for (i = 1; i <= resource_object->nodesetval->nodeNr; i++) { @@ -128,8 +164,11 @@ static void linphone_friend_list_parse_multipart_related_body(LinphoneFriendList SalPresenceModel *presence = NULL; linphone_notify_parse_presence(linphone_content_get_type(presence_part), linphone_content_get_subtype(presence_part), linphone_content_get_string_buffer(presence_part), &presence); if (presence != NULL) { + friend->presence_received = TRUE; linphone_friend_set_presence_model(friend, (LinphonePresenceModel *)presence); - linphone_core_notify_notify_presence_received(list->lc, friend); + if (full_state == FALSE) { + linphone_core_notify_notify_presence_received(list->lc, friend); + } } } } @@ -141,6 +180,16 @@ static void linphone_friend_list_parse_multipart_related_body(LinphoneFriendList } } if (resource_object != NULL) xmlXPathFreeObject(resource_object); + + if (full_state == TRUE) { + MSList *l = list->friends; + for (; l != NULL; l = l->next) { + friend = (LinphoneFriend *)l->data; + if (linphone_friend_is_presence_received(friend) == TRUE) { + linphone_core_notify_notify_presence_received(list->lc, friend); + } + } + } } else { ms_warning("Wrongly formatted rlmi+xml body: %s", xml_ctx->errorBuffer); } diff --git a/coreapi/linphonefriend.h b/coreapi/linphonefriend.h index 53f747651..e158d41b5 100644 --- a/coreapi/linphonefriend.h +++ b/coreapi/linphonefriend.h @@ -247,6 +247,13 @@ LINPHONE_PUBLIC const LinphonePresenceModel * linphone_friend_get_presence_model */ LINPHONE_PUBLIC void linphone_friend_set_presence_model(LinphoneFriend *lf, LinphonePresenceModel *presence); +/** + * Tells whether we already received presence information for a friend. + * @param[in] lf A #LinphoneFriend object + * @return TRUE if presence information has been received for the friend, FALSE otherwise. + */ +LINPHONE_PUBLIC bool_t linphone_friend_is_presence_received(const LinphoneFriend *lf); + /** * Store user pointer to friend object. **/ diff --git a/coreapi/presence.c b/coreapi/presence.c index 8465adcd0..a25261d52 100644 --- a/coreapi/presence.c +++ b/coreapi/presence.c @@ -1868,6 +1868,7 @@ void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, Sa if (activity_str != NULL) ms_free(activity_str); linphone_friend_set_presence_model(lf, presence); lf->subscribe_active=TRUE; + lf->presence_received = TRUE; linphone_core_notify_notify_presence_received(lc,(LinphoneFriend*)lf); ms_free(tmp); if (op != lf->outsub){ diff --git a/coreapi/private.h b/coreapi/private.h index 5f134e484..61fe10265 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -647,6 +647,7 @@ struct _LinphoneFriend{ bool_t inc_subscribe_pending; bool_t commit; bool_t initial_subscribes_sent; /*used to know if initial subscribe message was sent or not*/ + bool_t presence_received; }; BELLE_SIP_DECLARE_VPTR(LinphoneFriend); @@ -659,6 +660,7 @@ struct _LinphoneFriendList { char *display_name; char *rls_uri; MSList *friends; + int expected_notification_version; }; BELLE_SIP_DECLARE_VPTR(LinphoneFriendList); @@ -1245,6 +1247,7 @@ void linphone_xmlparsing_context_destroy(xmlparsing_context_t *ctx); void linphone_xmlparsing_genericxml_error(void *ctx, const char *fmt, ...); int linphone_create_xml_xpath_context(xmlparsing_context_t *xml_ctx); char * linphone_get_xml_text_content(xmlparsing_context_t *xml_ctx, const char *xpath_expression); +const char * linphone_get_xml_attribute_text_content(xmlparsing_context_t *xml_ctx, const char *xpath_expression, const char *attribute_name); void linphone_free_xml_text_content(const char *text); xmlXPathObjectPtr linphone_get_xml_xpath_object_for_node_list(xmlparsing_context_t *xml_ctx, const char *xpath_expression); diff --git a/coreapi/xml.c b/coreapi/xml.c index 8c7c3beaf..28d773add 100644 --- a/coreapi/xml.c +++ b/coreapi/xml.c @@ -89,6 +89,33 @@ char * linphone_get_xml_text_content(xmlparsing_context_t *xml_ctx, const char * return (char *)text; } +const char * linphone_get_xml_attribute_text_content(xmlparsing_context_t *xml_ctx, const char *xpath_expression, const char *attribute_name) { + xmlXPathObjectPtr xpath_obj; + xmlChar *text = NULL; + + xpath_obj = xmlXPathEvalExpression((const xmlChar *)xpath_expression, xml_ctx->xpath_ctx); + if (xpath_obj != NULL) { + if (xpath_obj->nodesetval != NULL) { + xmlNodeSetPtr nodes = xpath_obj->nodesetval; + if ((nodes != NULL) && (nodes->nodeNr >= 1)) { + xmlNodePtr node = nodes->nodeTab[0]; + xmlAttr *attr = node->properties; + while (attr) { + if (strcmp((char *)attr->name, attribute_name) == 0) { + text = xmlStrcat(text, attr->children->content); + attr = NULL; + } else { + attr = attr->next; + } + } + } + } + xmlXPathFreeObject(xpath_obj); + } + + return (const char *)text; +} + void linphone_free_xml_text_content(const char *text) { xmlFree((xmlChar *)text); } From e6f44d8c1f64d39e5f03fbd2b988fb0a01beec37 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Mon, 30 Nov 2015 11:50:49 +0100 Subject: [PATCH 09/30] Add the "store_friends" parameter in the "misc" section of config to allow not storing friends in the linphonerc. --- coreapi/friend.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/coreapi/friend.c b/coreapi/friend.c index 8b602843f..c5de8a872 100644 --- a/coreapi/friend.c +++ b/coreapi/friend.c @@ -657,11 +657,15 @@ void linphone_core_write_friends_config(LinphoneCore* lc) { MSList *elem; int i; + int store_friends; if (! linphone_core_ready(lc)) return; /*dont write config when reading it !*/ - for (elem=lc->friendlist->friends,i=0; elem!=NULL; elem=ms_list_next(elem),i++){ - linphone_friend_write_to_config_file(lc->config,(LinphoneFriend*)elem->data,i); + store_friends = lp_config_get_int(lc->config, "misc", "store_friends", 1); + if (store_friends) { + for (elem=lc->friendlist->friends,i=0; elem!=NULL; elem=ms_list_next(elem),i++){ + linphone_friend_write_to_config_file(lc->config,(LinphoneFriend*)elem->data,i); + } + linphone_friend_write_to_config_file(lc->config,NULL,i); /* set the end */ } - linphone_friend_write_to_config_file(lc->config,NULL,i); /* set the end */ } LinphoneCore *linphone_friend_get_core(const LinphoneFriend *fr){ From 7885a5c80abd70f4ce1980b2d968a86dcb1e5c7d Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Mon, 30 Nov 2015 14:15:33 +0100 Subject: [PATCH 10/30] Prevent sending multiple identical subscribes for presence list + send new subscribe when adding a friend. --- coreapi/friend.c | 5 +++-- coreapi/friendlist.c | 17 ++++++++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/coreapi/friend.c b/coreapi/friend.c index c5de8a872..d46124f58 100644 --- a/coreapi/friend.c +++ b/coreapi/friend.c @@ -462,8 +462,9 @@ void linphone_friend_apply(LinphoneFriend *fr, LinphoneCore *lc){ } fr->inc_subscribe_pending=FALSE; } - if (fr->lc) - linphone_friend_update_subscribes(fr,NULL,linphone_core_should_subscribe_friends_only_when_registered(fr->lc)); + if (fr->lc) { + linphone_friend_list_update_subscriptions(fr->lc->friendlist, NULL, linphone_core_should_subscribe_friends_only_when_registered(fr->lc)); + } ms_message("linphone_friend_apply() done."); lc->bl_refresh=TRUE; fr->commit=FALSE; diff --git a/coreapi/friendlist.c b/coreapi/friendlist.c index ef9c13a23..97636341e 100644 --- a/coreapi/friendlist.c +++ b/coreapi/friendlist.c @@ -175,6 +175,7 @@ static void linphone_friend_list_parse_multipart_related_body(LinphoneFriendList if (cid != NULL) linphone_free_xml_text_content(cid); } if (state != NULL) linphone_free_xml_text_content(state); + friend->subscribe_active = TRUE; } linphone_free_xml_text_content(uri); } @@ -198,6 +199,19 @@ end: linphone_xmlparsing_context_destroy(xml_ctx); } +static bool_t linphone_friend_list_has_subscribe_inactive(const LinphoneFriendList *list) { + MSList *l = list->friends; + bool_t has_subscribe_inactive = FALSE; + for (; l != NULL; l = l->next) { + LinphoneFriend *friend = (LinphoneFriend *)l->data; + if (friend->subscribe_active != TRUE) { + has_subscribe_inactive = TRUE; + break; + } + } + return has_subscribe_inactive; +} + static LinphoneFriendList * linphone_friend_list_new(void) { LinphoneFriendList *list = belle_sip_object_new(LinphoneFriendList); belle_sip_object_ref(list); @@ -350,10 +364,11 @@ void linphone_friend_list_update_subscriptions(LinphoneFriendList *list, Linphon if (list->rls_uri != NULL) { LinphoneAddress *address = linphone_address_new(list->rls_uri); char *xml_content = create_resource_list_xml(list); - if ((address != NULL) && (xml_content != NULL)) { + if ((address != NULL) && (xml_content != NULL) && (linphone_friend_list_has_subscribe_inactive(list) == TRUE)) { LinphoneEvent *event; LinphoneContent *content; int expires = lp_config_get_int(list->lc->config, "sip", "rls_presence_expires", 3600); + list->expected_notification_version = 0; event = linphone_core_create_subscribe(list->lc, address, "presence", expires); linphone_event_add_custom_header(event, "Require", "recipient-list-subscribe"); linphone_event_add_custom_header(event, "Supported", "eventlist"); From e63f2ba1081e06b688062a78331367bc7c48833d Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Mon, 30 Nov 2015 17:45:09 +0100 Subject: [PATCH 11/30] Fix some memory leaks. --- coreapi/callbacks.c | 5 ++++- coreapi/friendlist.c | 6 ++++++ gtk/utils.c | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 1046a308c..d1e87473a 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -1309,7 +1309,10 @@ static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, SalB } { LinphoneContent *ct=linphone_content_from_sal_body_handler(body_handler); - if (ct) linphone_core_notify_notify_received(lc,lev,eventname,ct); + if (ct) { + linphone_core_notify_notify_received(lc,lev,eventname,ct); + linphone_content_unref(ct); + } } if (st!=SalSubscribeNone){ linphone_event_set_state(lev,linphone_subscription_state_from_sal(st)); diff --git a/coreapi/friendlist.c b/coreapi/friendlist.c index 97636341e..1c4178aba 100644 --- a/coreapi/friendlist.c +++ b/coreapi/friendlist.c @@ -68,6 +68,7 @@ static char * create_resource_list_xml(const LinphoneFriendList *list) { /* Close the "entry" element. */ err = xmlTextWriterEndElement(writer); } + if (uri) ms_free(uri); } if (err >= 0) { /* Close the "list" element. */ @@ -116,6 +117,7 @@ static void linphone_friend_list_parse_multipart_related_body(LinphoneFriendList goto end; } version = atoi(version_str); + linphone_free_xml_text_content(version_str); if (version < list->expected_notification_version) { ms_warning("rlmi+xml: Discarding received notification with version %d because %d was expected", version, list->expected_notification_version); goto end; @@ -170,6 +172,7 @@ static void linphone_friend_list_parse_multipart_related_body(LinphoneFriendList linphone_core_notify_notify_presence_received(list->lc, friend); } } + linphone_content_unref(presence_part); } } if (cid != NULL) linphone_free_xml_text_content(cid); @@ -379,6 +382,7 @@ void linphone_friend_list_update_subscriptions(LinphoneFriendList *list, Linphon linphone_content_set_subtype(content, "resource-lists+xml"); linphone_content_set_string_buffer(content, xml_content); linphone_event_send_subscribe(event, content); + linphone_content_unref(content); } if (address != NULL) linphone_address_unref(address); if (xml_content != NULL) ms_free(xml_content); @@ -427,9 +431,11 @@ void linphone_friend_list_notify_presence_received(LinphoneFriendList *list, Lin subtype = linphone_content_get_subtype(first_part); if ((strcmp(type, "application") != 0) || (strcmp(subtype, "rlmi+xml") != 0)) { ms_warning("multipart presence notified but first part is not 'application/rlmi+xml'"); + linphone_content_unref(first_part); return; } linphone_friend_list_parse_multipart_related_body(list, body, linphone_content_get_string_buffer(first_part)); + linphone_content_unref(first_part); } } diff --git a/gtk/utils.c b/gtk/utils.c index 0d0ae64d0..943eed62b 100644 --- a/gtk/utils.c +++ b/gtk/utils.c @@ -118,6 +118,7 @@ bool_t linphone_gtk_is_friend(LinphoneCore *lc, const char *contact) { char *uri = linphone_address_as_string_uri_only(addr); LinphoneFriend *lf = linphone_core_get_friend_by_address(lc, uri); linphone_address_destroy(addr); + if (uri) ms_free(uri); if (lf) return TRUE; } return FALSE; From 1d93356d22476598cc8f46aebabff4cae2317793 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Tue, 1 Dec 2015 16:59:43 +0100 Subject: [PATCH 12/30] Add linphone_core_set_friend_list() function. --- coreapi/friendlist.h | 7 +++++++ coreapi/linphonecore.c | 22 +++++++++++++++++----- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/coreapi/friendlist.h b/coreapi/friendlist.h index 17b805add..a3b7ad7ab 100644 --- a/coreapi/friendlist.h +++ b/coreapi/friendlist.h @@ -56,6 +56,13 @@ typedef struct _LinphoneFriendList LinphoneFriendList; **/ LINPHONE_PUBLIC LinphoneFriendList * linphone_core_create_friend_list(LinphoneCore *lc); +/** + * Set the friend list. + * @param[in] lc LinphoneCore object + * @param[in] list LinphoneFriendList object + */ +LINPHONE_PUBLIC void linphone_core_set_friend_list(LinphoneCore *lc, LinphoneFriendList *list); + /** * Acquire a reference to the friend list. * @param[in] list LinphoneFriendList object. diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 79235453f..20778fd95 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1671,7 +1671,6 @@ static void linphone_core_internal_notify_received(LinphoneCore *lc, LinphoneEve } static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtable, LpConfig *config, void * userdata){ - const char *rls_uri = NULL; const char *remote_provisioning_uri = NULL; LinphoneCoreVTable* local_vtable= linphone_core_v_table_new(); LinphoneCoreVTable *internal_vtable = linphone_core_v_table_new(); @@ -1680,10 +1679,7 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab lc->config=lp_config_ref(config); lc->data=userdata; lc->ringstream_autorelease=TRUE; - lc->friendlist = linphone_core_create_friend_list(lc); - rls_uri = lp_config_get_string(lc->config, "sip", "rls_uri", NULL); - if (rls_uri && lp_config_get_int(lc->config, "sip", "use_rls_presence", 0)) - linphone_friend_list_set_rls_uri(lc->friendlist, rls_uri); + linphone_core_set_friend_list(lc, NULL); linphone_task_list_init(&lc->hooks); internal_vtable->notify_received = linphone_core_internal_notify_received; @@ -1922,6 +1918,22 @@ const MSList * linphone_core_get_friend_list(const LinphoneCore *lc) return lc->friendlist->friends; } +void linphone_core_set_friend_list(LinphoneCore *lc, LinphoneFriendList *list) { + if (lc->friendlist != NULL) { + linphone_friend_list_unref(lc->friendlist); + lc->friendlist = NULL; + } + if (list != NULL) { + lc->friendlist = linphone_friend_list_ref(list); + } else { + const char *rls_uri = NULL; + lc->friendlist = linphone_core_create_friend_list(lc); + rls_uri = lp_config_get_string(lc->config, "sip", "rls_uri", NULL); + if (rls_uri && lp_config_get_int(lc->config, "sip", "use_rls_presence", 0)) + linphone_friend_list_set_rls_uri(lc->friendlist, rls_uri); + } +} + void linphone_core_enable_audio_adaptive_jittcomp(LinphoneCore* lc, bool_t val) { lc->rtp_conf.audio_adaptive_jitt_comp_enabled = val; From c15905c9be5a14ea894b34e498f832bcd8b72612 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Tue, 1 Dec 2015 17:01:16 +0100 Subject: [PATCH 13/30] Add presence list test. --- tester/eventapi_tester.c | 4 +- tester/liblinphone_tester.h | 1 + tester/presence_tester.c | 138 ++++++++++++++++++++++++++++++++---- tester/rcfiles/laure_tcp_rc | 46 ++++++++++++ 4 files changed, 175 insertions(+), 14 deletions(-) create mode 100644 tester/rcfiles/laure_tcp_rc diff --git a/tester/eventapi_tester.c b/tester/eventapi_tester.c index 09925fa45..7b0a1f1e9 100644 --- a/tester/eventapi_tester.c +++ b/tester/eventapi_tester.c @@ -39,7 +39,9 @@ const char *liblinphone_tester_get_notify_content(void){ void linphone_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char *eventname, const LinphoneContent *content){ LinphoneCoreManager *mgr; BC_ASSERT_PTR_NOT_NULL_FATAL(content); - BC_ASSERT_STRING_EQUAL(notify_content,(const char*)linphone_content_get_buffer(content)); + if (!linphone_content_is_multipart(content)) { + BC_ASSERT_STRING_EQUAL(notify_content,(const char*)linphone_content_get_buffer(content)); + } mgr=get_manager(lc); mgr->stat.number_of_NotifyReceived++; } diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h index 4cbe28046..21b7d305f 100644 --- a/tester/liblinphone_tester.h +++ b/tester/liblinphone_tester.h @@ -153,6 +153,7 @@ typedef struct _stats { int number_of_NewSubscriptionRequest; int number_of_NotifyReceived; + int number_of_NotifyPresenceReceived; int number_of_LinphonePresenceActivityOffline; int number_of_LinphonePresenceActivityOnline; int number_of_LinphonePresenceActivityAppointment; diff --git a/tester/presence_tester.c b/tester/presence_tester.c index 6a9d758cd..264529bce 100644 --- a/tester/presence_tester.c +++ b/tester/presence_tester.c @@ -46,10 +46,10 @@ void notify_presence_received(LinphoneCore *lc, LinphoneFriend * lf) { stats* counters; LinphonePresenceActivity *activity = NULL; char* from=linphone_address_as_string(linphone_friend_get_address(lf)); - ms_message("New Notify request from [%s] ",from); + ms_message("New Notify request from [%s] ",from); ms_free(from); counters = get_stats(lc); - counters->number_of_NotifyReceived++; + counters->number_of_NotifyPresenceReceived++; counters->last_received_presence = linphone_friend_get_presence_model(lf); activity = linphone_presence_model_get_activity(counters->last_received_presence); @@ -173,9 +173,9 @@ static bool_t subscribe_to_callee_presence(LinphoneCoreManager* caller_mgr,Linph BC_ASSERT_EQUAL(callee_mgr->stat.number_of_NewSubscriptionRequest,initial_callee.number_of_NewSubscriptionRequest+1, int, "%d"); /*without proxy, callee cannot subscribe to caller - BC_ASSERT_EQUAL(callee_mgr->stat.number_of_NotifyReceived,initial_callee.number_of_NotifyReceived+1, int, "%d"); + BC_ASSERT_EQUAL(callee_mgr->stat.number_of_NotifyPresenceReceived,initial_callee.number_of_NotifyPresenceReceived+1, int, "%d"); */ - BC_ASSERT_EQUAL(caller_mgr->stat.number_of_NotifyReceived,initial_caller.number_of_NotifyReceived+1, int, "%d"); + BC_ASSERT_EQUAL(caller_mgr->stat.number_of_NotifyPresenceReceived,initial_caller.number_of_NotifyPresenceReceived+1, int, "%d"); ms_free(identity); return result; @@ -448,7 +448,7 @@ static void test_subscribe_notify_publish(void) { linphone_core_add_friend(pauline->lc,lf); /*wait for subscribe acknowledgment*/ - wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyReceived,1,2000); + wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyPresenceReceived,1,2000); BC_ASSERT_EQUAL(LinphoneStatusOffline,linphone_friend_get_status(lf), int, "%d"); /*enable publish*/ @@ -461,23 +461,23 @@ static void test_subscribe_notify_publish(void) { linphone_proxy_config_done(proxy); /*wait for marie status*/ - wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyReceived,2,2000); + wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyPresenceReceived,2,2000); BC_ASSERT_EQUAL(LinphoneStatusOnline,linphone_friend_get_status(lf), int, "%d"); presence =linphone_presence_model_new_with_activity(LinphonePresenceActivityBusy,NULL); linphone_core_set_presence_model(marie->lc,presence); /*wait for new status*/ - wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyReceived,3,2000); + wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyPresenceReceived,3,2000); BC_ASSERT_EQUAL(LinphoneStatusBusy,linphone_friend_get_status(lf), int, "%d"); /*wait for refresh*/ - wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyReceived,4,5000); + wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyPresenceReceived,4,5000); BC_ASSERT_EQUAL(LinphoneStatusBusy,linphone_friend_get_status(lf), int, "%d"); /*linphone_core_remove_friend(pauline->lc,lf);*/ /*wait for final notify*/ - /*wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyReceived,4,5000); + /*wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyPresenceReceived,4,5000); BC_ASSERT_EQUAL(LinphonePresenceActivityOffline,linphone_friend_get_status(lf), int, "%d"); */ linphone_core_manager_destroy(marie); @@ -507,7 +507,7 @@ static void test_forked_subscribe_notify_publish(void) { linphone_core_add_friend(pauline->lc,lf); /*wait for subscribe acknowledgment*/ - wait_for_list(lcs,&pauline->stat.number_of_NotifyReceived,1,2000); + wait_for_list(lcs,&pauline->stat.number_of_NotifyPresenceReceived,1,2000); BC_ASSERT_EQUAL(LinphoneStatusOffline,linphone_friend_get_status(lf), int, "%d"); /*enable publish*/ @@ -526,21 +526,21 @@ static void test_forked_subscribe_notify_publish(void) { /*wait for marie status*/ - wait_for_list(lcs,&pauline->stat.number_of_NotifyReceived,3,2000); + wait_for_list(lcs,&pauline->stat.number_of_NotifyPresenceReceived,3,2000); BC_ASSERT_EQUAL(LinphoneStatusOnline,linphone_friend_get_status(lf), int, "%d"); presence =linphone_presence_model_new_with_activity(LinphonePresenceActivityBusy,NULL); linphone_core_set_presence_model(marie->lc,presence); /*wait for new status*/ - wait_for_list(lcs,&pauline->stat.number_of_NotifyReceived,4,2000); + wait_for_list(lcs,&pauline->stat.number_of_NotifyPresenceReceived,4,2000); BC_ASSERT_EQUAL(LinphoneStatusBusy,linphone_friend_get_status(lf), int, "%d"); presence =linphone_presence_model_new_with_activity( LinphonePresenceActivityMeeting,NULL); linphone_core_set_presence_model(marie2->lc,presence); /*wait for new status*/ - wait_for_list(lcs,&pauline->stat.number_of_NotifyReceived,5,2000); + wait_for_list(lcs,&pauline->stat.number_of_NotifyPresenceReceived,5,2000); BC_ASSERT_EQUAL(LinphoneStatusBusy,linphone_friend_get_status(lf), int, "%d"); /*because liblinphone compositor is very simple for now (I.E only take first occurence)*/ linphone_core_manager_destroy(marie); @@ -551,6 +551,117 @@ static void test_forked_subscribe_notify_publish(void) { #endif +const char * get_identity(LinphoneCoreManager *mgr) { + LinphoneProxyConfig *cfg = linphone_core_get_default_proxy_config(mgr->lc); + return linphone_proxy_config_get_identity(cfg); +} + +static void enable_publish(LinphoneCoreManager *mgr, bool_t enable) { + LinphoneProxyConfig *cfg = linphone_core_get_default_proxy_config(mgr->lc); + linphone_proxy_config_edit(cfg); + linphone_proxy_config_enable_publish(cfg, enable); + linphone_proxy_config_set_publish_expires(cfg, 3); + linphone_proxy_config_done(cfg); +} + +static void test_presence_list(void) { + LinphoneCoreManager *laure = linphone_core_manager_new("laure_tcp_rc"); + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_rc"); + const char *rls_uri = "sip:rls@sip.example.org"; + LinphoneFriendList *lfl; + LinphoneFriend *lf; + const char *laure_identity; + const char *marie_identity; + const char *pauline_identity; + MSList* lcs = NULL; + + laure_identity = get_identity(laure); + marie_identity = get_identity(marie); + pauline_identity = get_identity(pauline); + enable_publish(marie, TRUE); + enable_publish(pauline, TRUE); + + linphone_core_set_presence_model(marie->lc, linphone_core_create_presence_model_with_activity(marie->lc, LinphonePresenceActivityBusy, NULL)); + linphone_core_set_presence_model(pauline->lc, linphone_core_create_presence_model_with_activity(pauline->lc, LinphonePresenceActivityVacation, NULL)); + + lfl = linphone_core_create_friend_list(laure->lc); + linphone_friend_list_set_rls_uri(lfl, rls_uri); + lf = linphone_core_create_friend_with_address(laure->lc, marie_identity); + linphone_friend_list_add_friend(lfl, lf); + lf = linphone_core_create_friend_with_address(laure->lc, pauline_identity); + linphone_friend_list_add_friend(lfl, lf); + lf = linphone_core_create_friend_with_address(laure->lc, "sip:michelle@sip.inexistentdomain.com"); + linphone_friend_list_add_friend(lfl, lf); + linphone_core_set_friend_list(laure->lc, lfl); + linphone_core_set_presence_model(laure->lc, linphone_core_create_presence_model_with_activity(laure->lc, LinphonePresenceActivityOnline, NULL)); + + lcs = ms_list_append(lcs, laure->lc); + lcs = ms_list_append(lcs, marie->lc); + lcs = ms_list_append(lcs, pauline->lc); + + wait_for_list(lcs, &laure->stat.number_of_NotifyReceived, 1, 2000); + wait_for_list(lcs, &laure->stat.number_of_NotifyPresenceReceived, 2, 2000); + BC_ASSERT_EQUAL(laure->stat.number_of_NotifyReceived, 1, int, "%d"); + BC_ASSERT_EQUAL(laure->stat.number_of_NotifyPresenceReceived, 2, int, "%d"); + BC_ASSERT_EQUAL(laure->lc->friendlist->expected_notification_version, 1, int, "%d"); + lf = linphone_friend_list_find_friend_by_uri(laure->lc->friendlist, marie_identity); + BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusBusy, int, "%d"); + BC_ASSERT_EQUAL(lf->presence_received, TRUE, int, "%d"); + BC_ASSERT_EQUAL(lf->subscribe_active, TRUE, int, "%d"); + lf = linphone_friend_list_find_friend_by_uri(laure->lc->friendlist, pauline_identity); + BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusVacation, int, "%d"); + BC_ASSERT_EQUAL(lf->presence_received, TRUE, int, "%d"); + BC_ASSERT_EQUAL(lf->subscribe_active, TRUE, int, "%d"); + lf = linphone_friend_list_find_friend_by_uri(laure->lc->friendlist, "sip:michelle@sip.inexistentdomain.com"); + BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOffline, int, "%d"); + BC_ASSERT_EQUAL(lf->presence_received, FALSE, int, "%d"); + BC_ASSERT_EQUAL(lf->subscribe_active, TRUE, int, "%d"); + + enable_publish(laure, TRUE); + lfl = linphone_core_create_friend_list(marie->lc); + linphone_friend_list_set_rls_uri(lfl, rls_uri); + lf = linphone_core_create_friend_with_address(marie->lc, laure_identity); + linphone_friend_list_add_friend(lfl, lf); + linphone_core_set_friend_list(marie->lc, lfl); + linphone_friend_list_update_subscriptions(pauline->lc->friendlist, NULL, FALSE); + + wait_for_list(lcs, &marie->stat.number_of_NotifyReceived, 1, 2000); + wait_for_list(lcs, &marie->stat.number_of_NotifyPresenceReceived, 1, 2000); + BC_ASSERT_EQUAL(marie->stat.number_of_NotifyReceived, 1, int, "%d"); + BC_ASSERT_EQUAL(marie->stat.number_of_NotifyPresenceReceived, 1, int, "%d"); + BC_ASSERT_EQUAL(marie->lc->friendlist->expected_notification_version, 1, int, "%d"); + lf = linphone_friend_list_find_friend_by_uri(marie->lc->friendlist, laure_identity); + BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOnline, int, "%d"); + BC_ASSERT_EQUAL(lf->presence_received, TRUE, int, "%d"); + BC_ASSERT_EQUAL(lf->subscribe_active, TRUE, int, "%d"); + + lfl = linphone_core_create_friend_list(pauline->lc); + linphone_friend_list_set_rls_uri(lfl, rls_uri); + lf = linphone_core_create_friend_with_address(pauline->lc, marie_identity); + linphone_friend_list_add_friend(lfl, lf); + linphone_core_set_friend_list(pauline->lc, lfl); + linphone_friend_list_update_subscriptions(pauline->lc->friendlist, NULL, FALSE); + + wait_for_list(lcs, &pauline->stat.number_of_NotifyReceived, 1, 2000); + wait_for_list(lcs, &pauline->stat.number_of_NotifyPresenceReceived, 1, 2000); + BC_ASSERT_EQUAL(pauline->stat.number_of_NotifyReceived, 1, int, "%d"); + BC_ASSERT_EQUAL(pauline->stat.number_of_NotifyPresenceReceived, 1, int, "%d"); + BC_ASSERT_EQUAL(pauline->lc->friendlist->expected_notification_version, 1, int, "%d"); + lf = linphone_friend_list_find_friend_by_uri(pauline->lc->friendlist, marie_identity); + BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusBusy, int, "%d"); + BC_ASSERT_EQUAL(lf->presence_received, TRUE, int, "%d"); + BC_ASSERT_EQUAL(lf->subscribe_active, TRUE, int, "%d"); + + enable_publish(laure, FALSE); + enable_publish(marie, FALSE); + enable_publish(pauline, FALSE); + + linphone_core_manager_destroy(laure); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + test_t presence_tests[] = { { "Simple Subscribe", simple_subscribe }, { "Simple Publish", simple_publish }, @@ -565,6 +676,7 @@ test_t presence_tests[] = { { "Subscribe with late publish", test_subscribe_notify_publish }, { "Forked subscribe with late publish", test_forked_subscribe_notify_publish }, #endif + { "Presence list", test_presence_list } }; test_suite_t presence_test_suite = {"Presence", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, diff --git a/tester/rcfiles/laure_tcp_rc b/tester/rcfiles/laure_tcp_rc new file mode 100644 index 000000000..fa8364993 --- /dev/null +++ b/tester/rcfiles/laure_tcp_rc @@ -0,0 +1,46 @@ +[sip] +sip_port=5092 +sip_tcp_port=5092 +sip_tls_port=5093 +default_proxy=0 +ping_with_options=0 +register_only_when_network_is_up=0 + +[auth_info_0] +username=laure +userid=laure +passwd=secret +realm="sip.example.org" + + +[proxy_0] +reg_proxy=sip.example.org;transport=tcp +reg_identity=sip:laure@sip.example.org +reg_expires=3600 +reg_sendregister=1 +publish=0 +dial_escape_plus=0 + + +[rtp] +audio_rtp_port=9010-9390 +video_rtp_port=9410-9910 + +[video] +display=0 +capture=0 +show_local=0 +size=qcif +enabled=0 +self_view=0 +automatically_initiate=0 +automatically_accept=0 +device=StaticImage: Static picture + +[sound] +echocancellation=0 #to not overload cpu in case of VG + +[net] +dns_srv_enabled=0 #no srv needed in general +stun_server=stun.linphone.org + From c0a2eaadebf27a21fd8d74c882e4d34d2859dae6 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Tue, 1 Dec 2015 17:29:54 +0100 Subject: [PATCH 14/30] Add new presence list test and complete existing one. --- tester/presence_tester.c | 72 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/tester/presence_tester.c b/tester/presence_tester.c index 264529bce..a06ac99d7 100644 --- a/tester/presence_tester.c +++ b/tester/presence_tester.c @@ -653,6 +653,24 @@ static void test_presence_list(void) { BC_ASSERT_EQUAL(lf->presence_received, TRUE, int, "%d"); BC_ASSERT_EQUAL(lf->subscribe_active, TRUE, int, "%d"); + linphone_core_set_presence_model(marie->lc, linphone_core_create_presence_model_with_activity(marie->lc, LinphonePresenceActivityOnThePhone, NULL)); + + wait_for_list(lcs, &laure->stat.number_of_NotifyReceived, 2, 2000); + wait_for_list(lcs, &laure->stat.number_of_NotifyPresenceReceived, 4, 2000); + BC_ASSERT_EQUAL(laure->stat.number_of_NotifyReceived, 2, int, "%d"); + BC_ASSERT_EQUAL(laure->stat.number_of_NotifyPresenceReceived, 4, int, "%d"); + BC_ASSERT_EQUAL(laure->lc->friendlist->expected_notification_version, 2, int, "%d"); + lf = linphone_friend_list_find_friend_by_uri(laure->lc->friendlist, marie_identity); + BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOnThePhone, int, "%d"); + + wait_for_list(lcs, &pauline->stat.number_of_NotifyReceived, 2, 2000); + wait_for_list(lcs, &pauline->stat.number_of_NotifyPresenceReceived, 2, 2000); + BC_ASSERT_EQUAL(pauline->stat.number_of_NotifyReceived, 2, int, "%d"); + BC_ASSERT_EQUAL(pauline->stat.number_of_NotifyPresenceReceived, 2, int, "%d"); + BC_ASSERT_EQUAL(pauline->lc->friendlist->expected_notification_version, 2, int, "%d"); + lf = linphone_friend_list_find_friend_by_uri(pauline->lc->friendlist, marie_identity); + BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOnThePhone, int, "%d"); + enable_publish(laure, FALSE); enable_publish(marie, FALSE); enable_publish(pauline, FALSE); @@ -662,6 +680,57 @@ static void test_presence_list(void) { linphone_core_manager_destroy(pauline); } +static void test_presence_list_subscribe_before_publish(void) { + LinphoneCoreManager *laure = linphone_core_manager_new("laure_tcp_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_rc"); + const char *rls_uri = "sip:rls@sip.example.org"; + LinphoneFriendList *lfl; + LinphoneFriend *lf; + const char *pauline_identity; + MSList* lcs = NULL; + int dummy = 0; + + pauline_identity = get_identity(pauline); + + linphone_core_set_presence_model(pauline->lc, linphone_core_create_presence_model_with_activity(pauline->lc, LinphonePresenceActivityVacation, NULL)); + + lfl = linphone_core_create_friend_list(laure->lc); + linphone_friend_list_set_rls_uri(lfl, rls_uri); + lf = linphone_core_create_friend_with_address(laure->lc, pauline_identity); + linphone_friend_list_add_friend(lfl, lf); + lf = linphone_core_create_friend_with_address(laure->lc, "sip:michelle@sip.inexistentdomain.com"); + linphone_friend_list_add_friend(lfl, lf); + linphone_core_set_friend_list(laure->lc, lfl); + linphone_core_set_presence_model(laure->lc, linphone_core_create_presence_model_with_activity(laure->lc, LinphonePresenceActivityOnline, NULL)); + //linphone_friend_list_update_subscriptions(pauline->lc->friendlist, NULL, FALSE); + + lcs = ms_list_append(lcs, laure->lc); + lcs = ms_list_append(lcs, pauline->lc); + + wait_for_list(lcs, &dummy, 1, 2000); /* Wait a little bit for the subscribe to happen */ + + enable_publish(pauline, TRUE); + wait_for_list(lcs, &pauline->stat.number_of_NotifyReceived, 1, 2000); + wait_for_list(lcs, &pauline->stat.number_of_NotifyPresenceReceived, 1, 2000); + BC_ASSERT_GREATER(laure->stat.number_of_NotifyReceived, 1, int, "%d"); + BC_ASSERT_GREATER(laure->stat.number_of_NotifyPresenceReceived, 1, int, "%d"); + BC_ASSERT_GREATER(laure->lc->friendlist->expected_notification_version, 1, int, "%d"); + lf = linphone_friend_list_find_friend_by_uri(laure->lc->friendlist, pauline_identity); + BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusVacation, int, "%d"); + BC_ASSERT_EQUAL(lf->presence_received, TRUE, int, "%d"); + BC_ASSERT_EQUAL(lf->subscribe_active, TRUE, int, "%d"); + lf = linphone_friend_list_find_friend_by_uri(laure->lc->friendlist, "sip:michelle@sip.inexistentdomain.com"); + BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOffline, int, "%d"); + BC_ASSERT_EQUAL(lf->presence_received, FALSE, int, "%d"); + BC_ASSERT_EQUAL(lf->subscribe_active, TRUE, int, "%d"); + + enable_publish(laure, FALSE); + enable_publish(pauline, FALSE); + + linphone_core_manager_destroy(laure); + linphone_core_manager_destroy(pauline); +} + test_t presence_tests[] = { { "Simple Subscribe", simple_subscribe }, { "Simple Publish", simple_publish }, @@ -676,7 +745,8 @@ test_t presence_tests[] = { { "Subscribe with late publish", test_subscribe_notify_publish }, { "Forked subscribe with late publish", test_forked_subscribe_notify_publish }, #endif - { "Presence list", test_presence_list } + { "Presence list", test_presence_list }, + { "Presence list (subscribe before publish)", test_presence_list_subscribe_before_publish } }; test_suite_t presence_test_suite = {"Presence", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, From 0ea0897390b9e1bc5c99f0f573158520ea2678a3 Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Fri, 2 Oct 2015 14:28:38 +0200 Subject: [PATCH 15/30] add more test for presence --- tester/complex_sip_call_tester.c | 2 +- tester/flexisip_tester.c | 79 +++++++++++++++ tester/liblinphone_tester.h | 4 + tester/presence_tester.c | 2 +- tester/sipp/double_publish_with_error.xml | 111 ++++++++++++++++++++++ tester/sipp/simple_publish.xml | 71 ++++++++++++++ 6 files changed, 267 insertions(+), 2 deletions(-) create mode 100644 tester/sipp/double_publish_with_error.xml create mode 100644 tester/sipp/simple_publish.xml diff --git a/tester/complex_sip_call_tester.c b/tester/complex_sip_call_tester.c index 605b10cba..4d2d0da2b 100644 --- a/tester/complex_sip_call_tester.c +++ b/tester/complex_sip_call_tester.c @@ -48,7 +48,7 @@ void check_rtcp(LinphoneCall *call) { linphone_call_unref(call); } -static FILE *sip_start(const char *senario, const char* dest_username, LinphoneAddress* dest_addres) { +FILE *sip_start(const char *senario, const char* dest_username, LinphoneAddress* dest_addres) { #if HAVE_SIPP char *dest; char *command; diff --git a/tester/flexisip_tester.c b/tester/flexisip_tester.c index 2b60a0f80..4861fe036 100644 --- a/tester/flexisip_tester.c +++ b/tester/flexisip_tester.c @@ -884,6 +884,81 @@ static void dos_module_trigger(void) { linphone_core_manager_destroy(pauline); } +#define USE_PRESENCE_SERVER 1 + +#if USE_PRESENCE_SERVER + +static void test_subscribe_notify_with_sipp_publisher(void) { + char *scen; + FILE * sipp_out; + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + /*just to get an identity*/ + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + + LpConfig *pauline_lp = linphone_core_get_config(pauline->lc); + char* lf_identity=linphone_address_as_string_uri_only(marie->identity); + LinphoneFriend *lf = linphone_core_create_friend_with_address(pauline->lc,lf_identity); + ms_free(lf_identity); + + lp_config_set_int(pauline_lp,"sip","subscribe_expires",5); + + linphone_core_add_friend(pauline->lc,lf); + + /*wait for subscribe acknowledgment*/ + wait_for_until(pauline->lc,pauline->lc,&pauline->stat.number_of_NotifyReceived,1,2000); + BC_ASSERT_EQUAL(LinphoneStatusOffline,linphone_friend_get_status(lf), int, "%d"); + + scen = bc_tester_res("sipp/simple_publish.xml"); + + sipp_out = sip_start(scen, linphone_address_get_username(marie->identity), marie->identity); + + if (TRUE/*sipp_out*/) { + /*wait for marie status*/ + wait_for_until(pauline->lc,pauline->lc,&pauline->stat.number_of_NotifyReceived,2,3000); + BC_ASSERT_EQUAL(LinphoneStatusOnline,linphone_friend_get_status(lf), int, "%d"); + pclose(sipp_out); + } + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} +static void test_subscribe_notify_with_sipp_publisher_double_publish(void) { + char *scen; + FILE * sipp_out; + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + /*just to get an identity*/ + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + + LpConfig *pauline_lp = linphone_core_get_config(pauline->lc); + char* lf_identity=linphone_address_as_string_uri_only(marie->identity); + LinphoneFriend *lf = linphone_core_create_friend_with_address(pauline->lc,lf_identity); + ms_free(lf_identity); + lp_config_set_int(pauline_lp,"sip","subscribe_expires",5); + + linphone_core_add_friend(pauline->lc,lf); + + /*wait for subscribe acknowledgment*/ + wait_for_until(pauline->lc,pauline->lc,&pauline->stat.number_of_NotifyReceived,1,2000); + BC_ASSERT_EQUAL(LinphoneStatusOffline,linphone_friend_get_status(lf), int, "%d"); + + scen = bc_tester_res("sipp/double_publish_with_error.xml"); + + sipp_out = sip_start(scen, linphone_address_get_username(marie->identity), marie->identity); + + if (TRUE/*sipp_out*/) { + /*wait for marie status*/ + wait_for_until(pauline->lc,pauline->lc,&pauline->stat.number_of_NotifyReceived,2,3000); + BC_ASSERT_EQUAL(LinphoneStatusOnline,linphone_friend_get_status(lf), int, "%d"); + pclose(sipp_out); + BC_ASSERT_EQUAL(pauline->stat.number_of_NotifyReceived,2,int, "%d"); + } + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +#endif + test_t flexisip_tests[] = { { "Subscribe forking", subscribe_forking }, { "Message forking", message_forking }, @@ -901,6 +976,10 @@ test_t flexisip_tests[] = { { "Call with sips", call_with_sips }, { "Call with sips not achievable", call_with_sips_not_achievable }, { "Call with ipv6", call_with_ipv6 }, +#if USE_PRESENCE_SERVER + { "Subscribe Notify with sipp publisher", test_subscribe_notify_with_sipp_publisher }, + { "Subscribe Notify with sipp double publish", test_subscribe_notify_with_sipp_publisher_double_publish }, +#endif { "File transfer message rcs to external body client", file_transfer_message_rcs_to_external_body_client }, { "File transfer message external body to rcs client", file_transfer_message_external_body_to_rcs_client }, { "File transfer message external body to external body client", file_transfer_message_external_body_to_external_body_client }, diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h index 21b7d305f..7b55f3c3f 100644 --- a/tester/liblinphone_tester.h +++ b/tester/liblinphone_tester.h @@ -352,6 +352,10 @@ bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee, Linph extern const char *liblinphone_tester_mire_id; +FILE *sip_start(const char *senario, const char* dest_username, LinphoneAddress* dest_addres); + + + #ifdef __cplusplus }; diff --git a/tester/presence_tester.c b/tester/presence_tester.c index a06ac99d7..3b9bc5527 100644 --- a/tester/presence_tester.c +++ b/tester/presence_tester.c @@ -429,7 +429,7 @@ static void subscribe_presence_expired(void){ } -#define USE_PRESENCE_SERVER 0 +#define USE_PRESENCE_SERVER 1 #if USE_PRESENCE_SERVER static void test_subscribe_notify_publish(void) { diff --git a/tester/sipp/double_publish_with_error.xml b/tester/sipp/double_publish_with_error.xml new file mode 100644 index 000000000..7527aa78a --- /dev/null +++ b/tester/sipp/double_publish_with_error.xml @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + ;tag=[pid]SIPpTag00[call_number] + To: sipp + Call-ID: [call_id] + CSeq: 1 PUBLISH + Max-Forwards: 70 + Expire: 60 + Event: presence + Content-Type: application/pidf+xml + Content-Length: [len] + + + + + + open + + sip:[service]@[local_ip]:[local_port] + 2015-09-28T15:49:00Z + + + ]]> + + + + + + + + + + + + + + ;tag=[pid]SIPpTag00[call_number] + To: sipp + Call-ID: [call_id]-2 + CSeq: 1 PUBLISH + Max-Forwards: 70 + Expire: 60 + Event: presence + Content-Type: application/pidf+xml + Content-Length: [len] + + + + + + open + + sip:[service]@[local_ip]:[local_port] + 2015-09-28T15:49:00Z + + + ]]> + + + + + + + + + + + + + + + + + + + + + diff --git a/tester/sipp/simple_publish.xml b/tester/sipp/simple_publish.xml new file mode 100644 index 000000000..83b04bedd --- /dev/null +++ b/tester/sipp/simple_publish.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + ;tag=[pid]SIPpTag00[call_number] + To: sipp + Call-ID: [call_id] + CSeq: 1 PUBLISH + Max-Forwards: 70 + Expire: 60 + Event: presence + Content-Type: application/pidf+xml + Content-Length: [len] + + + + + + open + + sip:[service]@[local_ip]:[local_port] + 2015-09-28T15:49:00Z + + + ]]> + + + + + + + + + + + + + + + + + + + + From 5b372035f5e42eb1b4f5ab324dae16912bf9be1d Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Fri, 9 Oct 2015 15:42:00 +0200 Subject: [PATCH 16/30] add more flexisip test for presence --- tester/flexisip_tester.c | 19 ++++++++++++++++++- tester/liblinphone_tester.h | 2 +- tester/presence_tester.c | 2 +- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/tester/flexisip_tester.c b/tester/flexisip_tester.c index 4861fe036..12d3780cb 100644 --- a/tester/flexisip_tester.c +++ b/tester/flexisip_tester.c @@ -945,7 +945,7 @@ static void test_subscribe_notify_with_sipp_publisher_double_publish(void) { sipp_out = sip_start(scen, linphone_address_get_username(marie->identity), marie->identity); - if (TRUE/*sipp_out*/) { + if (sipp_out) { /*wait for marie status*/ wait_for_until(pauline->lc,pauline->lc,&pauline->stat.number_of_NotifyReceived,2,3000); BC_ASSERT_EQUAL(LinphoneStatusOnline,linphone_friend_get_status(lf), int, "%d"); @@ -957,6 +957,22 @@ static void test_subscribe_notify_with_sipp_publisher_double_publish(void) { linphone_core_manager_destroy(pauline); } +static void test_publish_unpublish(void) { + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + LinphoneProxyConfig* proxy; + + linphone_core_get_default_proxy(marie->lc,&proxy); + linphone_proxy_config_edit(proxy); + linphone_proxy_config_enable_publish(proxy,TRUE); + linphone_proxy_config_done(proxy); + wait_core(marie->lc); + linphone_proxy_config_edit(proxy); + linphone_proxy_config_enable_publish(proxy,FALSE); + linphone_proxy_config_done(proxy); + wait_core(marie->lc); + linphone_core_manager_destroy(marie); +} + #endif test_t flexisip_tests[] = { @@ -979,6 +995,7 @@ test_t flexisip_tests[] = { #if USE_PRESENCE_SERVER { "Subscribe Notify with sipp publisher", test_subscribe_notify_with_sipp_publisher }, { "Subscribe Notify with sipp double publish", test_subscribe_notify_with_sipp_publisher_double_publish }, + { "Publish/unpublish", test_publish_unpublish }, #endif { "File transfer message rcs to external body client", file_transfer_message_rcs_to_external_body_client }, { "File transfer message external body to rcs client", file_transfer_message_external_body_to_rcs_client }, diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h index 7b55f3c3f..7b52982cf 100644 --- a/tester/liblinphone_tester.h +++ b/tester/liblinphone_tester.h @@ -354,7 +354,7 @@ extern const char *liblinphone_tester_mire_id; FILE *sip_start(const char *senario, const char* dest_username, LinphoneAddress* dest_addres); - +void wait_core(LinphoneCore *core) ; #ifdef __cplusplus diff --git a/tester/presence_tester.c b/tester/presence_tester.c index 3b9bc5527..576df13c5 100644 --- a/tester/presence_tester.c +++ b/tester/presence_tester.c @@ -115,7 +115,7 @@ void notify_presence_received(LinphoneCore *lc, LinphoneFriend * lf) { } } -static void wait_core(LinphoneCore *core) { +void wait_core(LinphoneCore *core) { int i; for (i = 0; i < 10; i++) { From 8ceb75adc34333c5d65b0e099b66bc199cd176c1 Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Wed, 14 Oct 2015 09:19:03 +0200 Subject: [PATCH 17/30] add resource-list test --- tester/flexisip_tester.c | 65 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/tester/flexisip_tester.c b/tester/flexisip_tester.c index 12d3780cb..6f52a8019 100644 --- a/tester/flexisip_tester.c +++ b/tester/flexisip_tester.c @@ -973,6 +973,70 @@ static void test_publish_unpublish(void) { linphone_core_manager_destroy(marie); } +static void test_list_subscribe (void) { + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); + LinphoneCoreManager* laure = linphone_core_manager_new( "laure_rc"); + + char *list = "\n" + "\n" + "\n" + "\t\n" + "\t\n" + "\n" + "\n"; + + + LinphoneEvent *lev; + MSList* lcs=ms_list_append(NULL,marie->lc); + char * pauline_uri=linphone_address_as_string_uri_only(pauline->identity); + char * laure_uri=linphone_address_as_string_uri_only(laure->identity); + char * subscribe_content = ms_strdup_printf(list,pauline_uri,laure_uri); + LinphoneContent* content = linphone_core_create_content(marie->lc); + LinphoneAddress *list_name = linphone_address_new("sip:mescops@sip.example.org"); + ms_free(pauline_uri); + ms_free(laure_uri); + + lcs=ms_list_append(lcs,pauline->lc); + lcs=ms_list_append(lcs,laure->lc); + + linphone_content_set_type(content,"application"); + linphone_content_set_subtype(content,"resource-lists+xml"); + linphone_content_set_buffer(content,subscribe_content,strlen(subscribe_content)); + + lev=linphone_core_create_subscribe(marie->lc,list_name,"presence",60); + + linphone_event_add_custom_header(lev,"Supported","eventlist"); + linphone_event_add_custom_header(lev,"Accept","application/pidf+xml, application/rlmi+xml"); + + linphone_event_send_subscribe(lev,content); + + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionOutgoingInit,1,1000)); + //BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionIncomingReceived,1,3000)); + +// if (pauline->stat.number_of_LinphoneSubscriptionIncomingReceived == 1) { +// /*check good receipt of custom headers*/ +// BC_ASSERT_STRING_EQUAL(linphone_event_get_custom_header(pauline->lev,"My-Header"),"pouet"); +// BC_ASSERT_STRING_EQUAL(linphone_event_get_custom_header(pauline->lev,"My-Header2"),"pimpon"); +// } + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionActive,1,5000)); +// BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionActive,1,5000)); + + /*make sure marie receives first notification before terminating*/ + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_NotifyReceived,1,5000)); + + linphone_event_terminate(lev); + + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionTerminated,1,5000)); + + ms_free(subscribe_content); + linphone_address_destroy(list_name); + linphone_content_unref(content); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(laure); +} #endif test_t flexisip_tests[] = { @@ -996,6 +1060,7 @@ test_t flexisip_tests[] = { { "Subscribe Notify with sipp publisher", test_subscribe_notify_with_sipp_publisher }, { "Subscribe Notify with sipp double publish", test_subscribe_notify_with_sipp_publisher_double_publish }, { "Publish/unpublish", test_publish_unpublish }, + { "List subscribe", test_list_subscribe }, #endif { "File transfer message rcs to external body client", file_transfer_message_rcs_to_external_body_client }, { "File transfer message external body to rcs client", file_transfer_message_external_body_to_rcs_client }, From 57a82611464fecae3d3adc0df0b5e028b45287e6 Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Thu, 15 Oct 2015 11:24:15 +0200 Subject: [PATCH 18/30] fix flexisip presence tester --- tester/flexisip_tester.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tester/flexisip_tester.c b/tester/flexisip_tester.c index 6f52a8019..d6107b194 100644 --- a/tester/flexisip_tester.c +++ b/tester/flexisip_tester.c @@ -1009,6 +1009,7 @@ static void test_list_subscribe (void) { linphone_event_add_custom_header(lev,"Supported","eventlist"); linphone_event_add_custom_header(lev,"Accept","application/pidf+xml, application/rlmi+xml"); + linphone_event_add_custom_header(lev,"Content-Disposition", "recipient-list"); linphone_event_send_subscribe(lev,content); From b412132ca92d8e64e990021060880fc82dabc66e Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Wed, 18 Nov 2015 18:24:12 +0100 Subject: [PATCH 19/30] enhance flexisip resource list tester --- tester/eventapi_tester.c | 1 + tester/flexisip_tester.c | 28 ++++++++++++++++++++-------- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/tester/eventapi_tester.c b/tester/eventapi_tester.c index 7b0a1f1e9..46903f166 100644 --- a/tester/eventapi_tester.c +++ b/tester/eventapi_tester.c @@ -40,6 +40,7 @@ void linphone_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char * LinphoneCoreManager *mgr; BC_ASSERT_PTR_NOT_NULL_FATAL(content); if (!linphone_content_is_multipart(content)) { + /*hack to disable content checking for list notify */ BC_ASSERT_STRING_EQUAL(notify_content,(const char*)linphone_content_get_buffer(content)); } mgr=get_manager(lc); diff --git a/tester/flexisip_tester.c b/tester/flexisip_tester.c index d6107b194..c89e3fd67 100644 --- a/tester/flexisip_tester.c +++ b/tester/flexisip_tester.c @@ -995,6 +995,9 @@ static void test_list_subscribe (void) { char * subscribe_content = ms_strdup_printf(list,pauline_uri,laure_uri); LinphoneContent* content = linphone_core_create_content(marie->lc); LinphoneAddress *list_name = linphone_address_new("sip:mescops@sip.example.org"); + LinphoneProxyConfig* proxy_config; + int dummy=0; + ms_free(pauline_uri); ms_free(laure_uri); @@ -1014,18 +1017,27 @@ static void test_list_subscribe (void) { linphone_event_send_subscribe(lev,content); BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionOutgoingInit,1,1000)); - //BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionIncomingReceived,1,3000)); - -// if (pauline->stat.number_of_LinphoneSubscriptionIncomingReceived == 1) { -// /*check good receipt of custom headers*/ -// BC_ASSERT_STRING_EQUAL(linphone_event_get_custom_header(pauline->lev,"My-Header"),"pouet"); -// BC_ASSERT_STRING_EQUAL(linphone_event_get_custom_header(pauline->lev,"My-Header2"),"pimpon"); -// } BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionActive,1,5000)); -// BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionActive,1,5000)); /*make sure marie receives first notification before terminating*/ BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_NotifyReceived,1,5000)); + /*dummy wait to avoid derred notify*/ + wait_for_list(lcs,&dummy,1,2000); + linphone_core_get_default_proxy(pauline->lc,&proxy_config); + linphone_proxy_config_edit(proxy_config); + linphone_proxy_config_enable_publish(proxy_config,TRUE); + linphone_proxy_config_done(proxy_config); + + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_NotifyReceived,2,5000)); + + linphone_core_get_default_proxy(laure->lc,&proxy_config); + linphone_proxy_config_edit(proxy_config); + linphone_proxy_config_enable_publish(proxy_config,TRUE); + linphone_proxy_config_done(proxy_config); + /*make sure notify is not sent "imadiatly but defered*/ + BC_ASSERT_FALSE(wait_for_list(lcs,&marie->stat.number_of_NotifyReceived,3,1000)); + + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_NotifyReceived,3,5000)); linphone_event_terminate(lev); From 5269c01b024bccc86753418c32b04ff9fae82d81 Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Mon, 7 Dec 2015 17:03:59 +0100 Subject: [PATCH 20/30] fix c++ compilation issue --- coreapi/friendlist.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/coreapi/friendlist.h b/coreapi/friendlist.h index a3b7ad7ab..3bea37738 100644 --- a/coreapi/friendlist.h +++ b/coreapi/friendlist.h @@ -124,7 +124,7 @@ LINPHONE_PUBLIC void linphone_friend_list_set_rls_uri(LinphoneFriendList *list, * @param[in] friend LinphoneFriend object to add to the friend list. * @return LinphoneFriendListOK if successfully added, LinphoneFriendListInvalidFriend if the friend is not valid. **/ -LINPHONE_PUBLIC LinphoneFriendListStatus linphone_friend_list_add_friend(LinphoneFriendList *list, LinphoneFriend *friend); +LINPHONE_PUBLIC LinphoneFriendListStatus linphone_friend_list_add_friend(LinphoneFriendList *list, LinphoneFriend *afriend); /** * Remove a friend from a friend list. @@ -132,7 +132,7 @@ LINPHONE_PUBLIC LinphoneFriendListStatus linphone_friend_list_add_friend(Linphon * @param[in] friend LinphoneFriend object to remove from the friend list. * @return LinphoneFriendListOK if removed successfully, LinphoneFriendListNonExistentFriend if the friend is not in the list. **/ -LINPHONE_PUBLIC LinphoneFriendListStatus linphone_friend_list_remove_friend(LinphoneFriendList *list, LinphoneFriend *friend); +LINPHONE_PUBLIC LinphoneFriendListStatus linphone_friend_list_remove_friend(LinphoneFriendList *list, LinphoneFriend *afriend); /** * Find a friend in the friend list using a LinphoneAddress. From f151d70d4d903c7d2169b0ef0c42d1a75d4412a6 Mon Sep 17 00:00:00 2001 From: Christophe Deschamps Date: Mon, 14 Dec 2015 00:01:15 +0100 Subject: [PATCH 21/30] retired LinphoneContentPrivate in JNI & fixed Android compilation (friendlist) --- build/android/Android.mk | 1 + coreapi/linphonecore_jni.cc | 170 +++++++----------------------------- 2 files changed, 33 insertions(+), 138 deletions(-) diff --git a/build/android/Android.mk b/build/android/Android.mk index 96fe57e16..b0d51fc32 100755 --- a/build/android/Android.mk +++ b/build/android/Android.mk @@ -53,6 +53,7 @@ LOCAL_SRC_FILES := \ enum.c \ event.c \ friend.c \ + friendlist.c \ info.c \ linphonecall.c \ linphonecore.c \ diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index 433efcae4..15cb4e7b2 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -3182,17 +3182,10 @@ extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_markAsRead(JNIEnv* extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_createFileTransferMessage(JNIEnv* env, jobject thiz, jlong ptr, jstring jname, jstring jtype, jstring jsubtype, jint data_size) { - LinphoneContentPrivate content = {0}; + LinphoneContent content = {0}; LinphoneChatMessage *message = NULL; - content.type = (char*)env->GetStringUTFChars(jtype, NULL); - content.subtype = (char*)env->GetStringUTFChars(jsubtype, NULL); - content.name = (char*)env->GetStringUTFChars(jname, NULL); - content.size = data_size; - message = linphone_chat_room_create_file_transfer_message((LinphoneChatRoom *)ptr, LINPHONE_CONTENT(&content)); - env->ReleaseStringUTFChars(jtype, content.type); - env->ReleaseStringUTFChars(jsubtype, content.subtype); - env->ReleaseStringUTFChars(jname, content.name); + message = linphone_chat_room_create_file_transfer_message((LinphoneChatRoom *)ptr, &content); return (jlong) message; } @@ -4576,24 +4569,14 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCoreImpl_subscribe(JNIE jstring jevname, jint expires, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding){ LinphoneCore *lc=(LinphoneCore*)coreptr; LinphoneAddress *addr=(LinphoneAddress*)addrptr; - LinphoneContentPrivate content={0}; + LinphoneContent content={0}; LinphoneEvent *ev; jobject jev=NULL; const char *evname=env->GetStringUTFChars(jevname,NULL); + ev=linphone_core_subscribe(lc,addr,evname,expires,linphone_content_get_type(&content) ? &content : NULL); if (jtype){ - content.type=(char*)env->GetStringUTFChars(jtype,NULL); - content.subtype=(char*)env->GetStringUTFChars(jsubtype,NULL); - content.encoding=jencoding ? (char*)env->GetStringUTFChars(jencoding,NULL) : NULL; - content.data=(void*)env->GetByteArrayElements(jdata,NULL); - content.size=env->GetArrayLength(jdata); - } - ev=linphone_core_subscribe(lc,addr,evname,expires,content.type ? LINPHONE_CONTENT(&content) : NULL); - if (jtype){ - env->ReleaseStringUTFChars(jtype,content.type); - env->ReleaseStringUTFChars(jsubtype,content.subtype); - if (jencoding) env->ReleaseStringUTFChars(jencoding,content.encoding); - env->ReleaseByteArrayElements(jdata,(jbyte*)content.data,JNI_ABORT); + env->ReleaseByteArrayElements(jdata,(jbyte*)linphone_content_get_user_data(&content),JNI_ABORT); } env->ReleaseStringUTFChars(jevname,evname); if (ev){ @@ -4611,24 +4594,16 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCoreImpl_publish(JNIEnv jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding){ LinphoneCore *lc=(LinphoneCore*)coreptr; LinphoneAddress *addr=(LinphoneAddress*)addrptr; - LinphoneContentPrivate content={0}; + LinphoneContent content={0}; LinphoneEvent *ev; jobject jev=NULL; const char *evname=env->GetStringUTFChars(jevname,NULL); + ev=linphone_core_subscribe(lc,addr,evname,expires,linphone_content_get_type(&content) ? &content : NULL); + if (jtype){ - content.type=(char*)env->GetStringUTFChars(jtype,NULL); - content.subtype=(char*)env->GetStringUTFChars(jsubtype,NULL); - content.encoding=jencoding ? (char*)env->GetStringUTFChars(jencoding,NULL) : NULL; - content.data=(void*)env->GetByteArrayElements(jdata,NULL); - content.size=env->GetArrayLength(jdata); - } - ev=linphone_core_publish(lc,addr,evname,expires,content.type ? LINPHONE_CONTENT(&content) : NULL); - if (jtype){ - env->ReleaseStringUTFChars(jtype,content.type); - env->ReleaseStringUTFChars(jsubtype,content.subtype); - if (jencoding) env->ReleaseStringUTFChars(jencoding,content.encoding); - env->ReleaseByteArrayElements(jdata,(jbyte*)content.data,JNI_ABORT); + env->ReleaseByteArrayElements(jdata,(jbyte*)linphone_content_get_user_data(&content),JNI_ABORT); + } env->ReleaseStringUTFChars(jevname,evname); if (ev){ @@ -4771,33 +4746,24 @@ static jobject create_java_linphone_content(JNIEnv *env, const LinphoneContent * jstring jtype, jsubtype, jencoding, jname; jbyteArray jdata = NULL; jint jsize = 0; - const LinphoneContentPrivate *content = LINPHONE_CONTENT_PRIVATE(icontent); contentClass = (jclass)env->FindClass("org/linphone/core/LinphoneContentImpl"); ctor = env->GetMethodID(contentClass,"", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[BLjava/lang/String;I)V"); - jtype = env->NewStringUTF(content->type); - jsubtype = env->NewStringUTF(content->subtype); - jencoding = content->encoding ? env->NewStringUTF(content->encoding) : NULL; - jname = content->name ? env->NewStringUTF(content->name) : NULL; - jsize = (jint) content->size; + jtype = env->NewStringUTF(linphone_content_get_type(icontent)); + jsubtype = env->NewStringUTF(linphone_content_get_subtype(icontent)); + jencoding = linphone_content_get_encoding(icontent) ? env->NewStringUTF(linphone_content_get_encoding(icontent)) : NULL; + jname = linphone_content_get_name(icontent) ? env->NewStringUTF(linphone_content_get_name(icontent)) : NULL; + jsize = (jint) linphone_content_get_size(icontent); - if (content->data){ - jdata = env->NewByteArray(content->size); - env->SetByteArrayRegion(jdata, 0, content->size, (jbyte*)content->data); + if (linphone_content_get_user_data(icontent)){ + jdata = env->NewByteArray(linphone_content_get_size(icontent)); + env->SetByteArrayRegion(jdata, 0, linphone_content_get_size(icontent), (jbyte*)linphone_content_get_user_data(icontent)); } jobject jobj = env->NewObject(contentClass, ctor, jname, jtype, jsubtype, jdata, jencoding, jsize); env->DeleteLocalRef(contentClass); - env->DeleteLocalRef(jtype); - env->DeleteLocalRef(jsubtype); - if (jencoding) { - env->DeleteLocalRef(jencoding); - } - if (jname) { - env->DeleteLocalRef(jname); - } return jobj; } @@ -4867,16 +4833,9 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneInfoMessageImpl_getCont * Signature: (JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneInfoMessageImpl_setContent(JNIEnv *env, jobject jobj, jlong infoptr, jstring jtype, jstring jsubtype, jstring jdata){ - LinphoneContentPrivate content={0}; + LinphoneContent content={0}; - content.type=(char*)env->GetStringUTFChars(jtype,NULL); - content.subtype=(char*)env->GetStringUTFChars(jsubtype,NULL); - content.data=(void*)env->GetStringUTFChars(jdata,NULL); - content.size=strlen((char*)content.data); - linphone_info_message_set_content((LinphoneInfoMessage*)infoptr,LINPHONE_CONTENT(&content)); - env->ReleaseStringUTFChars(jtype,content.type); - env->ReleaseStringUTFChars(jsubtype,content.subtype); - env->ReleaseStringUTFChars(jdata,(char*)content.data); + linphone_info_message_set_content((LinphoneInfoMessage*)infoptr,&content); } /* @@ -4975,26 +4934,13 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_denySubscription * Signature: (JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I */ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_notify(JNIEnv *env, jobject jobj, jlong evptr, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding){ - LinphoneContentPrivate content={0}; + LinphoneContent content={0}; LinphoneEvent *ev=(LinphoneEvent*)evptr; jint err; - if (jtype){ - content.type=(char*)env->GetStringUTFChars(jtype,NULL); - content.subtype=(char*)env->GetStringUTFChars(jsubtype,NULL); - content.encoding=jencoding ? (char*)env->GetStringUTFChars(jsubtype,NULL) : NULL; - content.data=(void*)env->GetByteArrayElements(jdata,NULL); - content.size=env->GetArrayLength(jdata); - } - err=linphone_event_notify(ev,content.type ? LINPHONE_CONTENT(&content) : NULL); + err=linphone_event_notify(ev,linphone_content_get_type(&content) ? &content : NULL); - if (jtype){ - env->ReleaseStringUTFChars(jtype,content.type); - env->ReleaseStringUTFChars(jsubtype,content.subtype); - if (jencoding) env->ReleaseStringUTFChars(jencoding,content.encoding); - env->ReleaseByteArrayElements(jdata,(jbyte*)content.data,JNI_ABORT); - } return err; } @@ -5004,26 +4950,12 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_notify(JNIEnv *e * Signature: (JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I */ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_updateSubscribe(JNIEnv *env, jobject jobj, jlong evptr, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding){ - LinphoneContentPrivate content={0}; + LinphoneContent content={0}; LinphoneEvent *ev=(LinphoneEvent*)evptr; jint err; - if (jtype){ - content.type=(char*)env->GetStringUTFChars(jtype,NULL); - content.subtype=(char*)env->GetStringUTFChars(jsubtype,NULL); - content.encoding=jencoding ? (char*)env->GetStringUTFChars(jsubtype,NULL) : NULL; - content.data=(void*)env->GetByteArrayElements(jdata,NULL); - content.size=env->GetArrayLength(jdata); - } + err=linphone_event_update_subscribe(ev,linphone_content_get_type(&content) ? &content : NULL); - err=linphone_event_update_subscribe(ev,content.type ? LINPHONE_CONTENT(&content) : NULL); - - if (jtype){ - env->ReleaseStringUTFChars(jtype,content.type); - env->ReleaseStringUTFChars(jsubtype,content.subtype); - if (jencoding) env->ReleaseStringUTFChars(jencoding,content.encoding); - env->ReleaseByteArrayElements(jdata,(jbyte*)content.data,JNI_ABORT); - } return err; } @@ -5033,26 +4965,12 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_updateSubscribe( * Signature: (JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I */ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_updatePublish(JNIEnv *env, jobject jobj, jlong evptr, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding){ - LinphoneContentPrivate content={0}; + LinphoneContent content={0}; LinphoneEvent *ev=(LinphoneEvent*)evptr; jint err; - if (jtype){ - content.type=(char*)env->GetStringUTFChars(jtype,NULL); - content.subtype=(char*)env->GetStringUTFChars(jsubtype,NULL); - content.encoding=jencoding ? (char*)env->GetStringUTFChars(jsubtype,NULL) : NULL; - content.data=(void*)env->GetByteArrayElements(jdata,NULL); - content.size=env->GetArrayLength(jdata); - } + err=linphone_event_update_publish(ev,linphone_content_get_type(&content) ? &content : NULL); - err=linphone_event_update_publish(ev,content.type ? LINPHONE_CONTENT(&content) : NULL); - - if (jtype){ - env->ReleaseStringUTFChars(jtype,content.type); - env->ReleaseStringUTFChars(jsubtype,content.subtype); - if (jencoding) env->ReleaseStringUTFChars(jencoding,content.encoding); - env->ReleaseByteArrayElements(jdata,(jbyte*)content.data,JNI_ABORT); - } return err; } @@ -5118,21 +5036,8 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCoreImpl_createSubscrib } JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneEventImpl_sendSubscribe(JNIEnv *env, jobject thiz, jlong jevent, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding) { - LinphoneContentPrivate content = {0}; - if (jtype) { - content.type = (char*) env->GetStringUTFChars(jtype, NULL); - content.subtype = (char*) env->GetStringUTFChars(jsubtype, NULL); - content.encoding = jencoding ? (char*) env->GetStringUTFChars(jencoding, NULL) : NULL; - content.data = (void*) env->GetByteArrayElements(jdata, NULL); - content.size = env->GetArrayLength(jdata); - } - linphone_event_send_subscribe((LinphoneEvent*) jevent, content.type ? LINPHONE_CONTENT(&content) : NULL); - if (jtype) { - env->ReleaseStringUTFChars(jtype, content.type); - env->ReleaseStringUTFChars(jsubtype, content.subtype); - if (jencoding) env->ReleaseStringUTFChars(jencoding, content.encoding); - env->ReleaseByteArrayElements(jdata, (jbyte*) content.data, JNI_ABORT); - } + LinphoneContent content = {0}; + linphone_event_send_subscribe((LinphoneEvent*) jevent, linphone_content_get_type(&content)? &content : NULL); } JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCoreImpl_createPublish(JNIEnv *env, jobject thiz, jlong jcore, jlong jaddr, jstring jeventname, jint expires) { @@ -5151,21 +5056,10 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCoreImpl_createPublish( } JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneEventImpl_sendPublish(JNIEnv *env, jobject thiz, jlong jevent, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding) { - LinphoneContentPrivate content = {0}; - if (jtype) { - content.type = (char*) env->GetStringUTFChars(jtype, NULL); - content.subtype = (char*) env->GetStringUTFChars(jsubtype, NULL); - content.encoding = jencoding ? (char*) env->GetStringUTFChars(jencoding, NULL) : NULL; - content.data = (void*) env->GetByteArrayElements(jdata, NULL); - content.size = env->GetArrayLength(jdata); - } - linphone_event_send_publish((LinphoneEvent*) jevent, content.type ? LINPHONE_CONTENT(&content) : NULL); - if (jtype) { - env->ReleaseStringUTFChars(jtype, content.type); - env->ReleaseStringUTFChars(jsubtype, content.subtype); - if (jencoding) env->ReleaseStringUTFChars(jencoding, content.encoding); - env->ReleaseByteArrayElements(jdata, (jbyte*) content.data, JNI_ABORT); - } + LinphoneContent content = {0}; + linphone_event_send_publish((LinphoneEvent*) jevent, linphone_content_get_type(&content)? &content : NULL); + + } JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneEventImpl_addCustomHeader(JNIEnv *env, jobject thiz, jlong jevent, jstring jname, jstring jvalue) { From 2840f5fcac02c42a717c1989acd52f237493df23 Mon Sep 17 00:00:00 2001 From: Christophe Deschamps Date: Mon, 14 Dec 2015 14:11:37 +0100 Subject: [PATCH 22/30] JNI Wrapper for presence list --- coreapi/linphonecore_jni.cc | 64 +++++++++++++++++++ .../org/linphone/core/LinphoneCore.java | 10 +++ .../org/linphone/core/LinphoneCoreImpl.java | 10 +++ 3 files changed, 84 insertions(+) diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index 15cb4e7b2..1f770163a 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -1845,6 +1845,15 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_addFriend(JNIEnv* env ) { linphone_core_add_friend((LinphoneCore*)lc,(LinphoneFriend*)aFriend); } + +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setFriendList(JNIEnv* env + ,jobject thiz + ,jlong lc + ,jlong friendList + ) { + linphone_core_set_friend_list((LinphoneCore*)lc,(LinphoneFriendList*)friendList); +} + extern "C" jobjectArray Java_org_linphone_core_LinphoneCoreImpl_getFriendList(JNIEnv* env ,jobject thiz ,jlong lc) { @@ -2960,12 +2969,47 @@ extern "C" jlong Java_org_linphone_core_LinphoneFriendImpl_newLinphoneFriend(JNI } return (jlong)lResult; } + +extern "C" jlong Java_org_linphone_core_LinphoneFriendListImpl_newLinphoneFriendList(JNIEnv* env + ,jobject thiz, jlong lc) { + LinphoneFriendList* fl = linphone_core_create_friend_list((LinphoneCore *)lc); + linphone_friend_list_set_user_data(fl,env->NewWeakGlobalRef(thiz)); + return (jlong)fl; +} + extern "C" void Java_org_linphone_core_LinphoneFriendImpl_setAddress(JNIEnv* env ,jobject thiz ,jlong ptr ,jlong linphoneAddress) { linphone_friend_set_address((LinphoneFriend*)ptr,(LinphoneAddress*)linphoneAddress); } + +extern "C" void Java_org_linphone_core_LinphoneFriendListImpl_setRLSUri(JNIEnv* env + ,jobject thiz + ,jlong ptr + ,jstring jrlsUri) { + const char* uri = env->GetStringUTFChars(jrlsUri, NULL); + linphone_friend_list_set_rls_uri((LinphoneFriendList*)ptr,uri); +} + +extern "C" void Java_org_linphone_core_LinphoneFriendListImpl_addFriend(JNIEnv* env + ,jobject thiz + ,jlong friendListptr + ,jlong friendPtr) { + linphone_friend_list_add_friend((LinphoneFriendList*)friendListptr,(LinphoneFriend*)friendPtr); +} + +extern "C" void Java_org_linphone_core_LinphoneFriendListImpl_updateSubscriptions(JNIEnv* env + ,jobject thiz + ,jlong friendListptr + ,jlong proxyConfigPtr + ,jboolean jonlyWhenRegistered) { + linphone_friend_list_update_subscriptions((LinphoneFriendList*)friendListptr,(LinphoneProxyConfig*)proxyConfigPtr,jonlyWhenRegistered); +} + + + + extern "C" jlong Java_org_linphone_core_LinphoneFriendImpl_getAddress(JNIEnv* env ,jobject thiz ,jlong ptr) { @@ -3008,6 +3052,18 @@ extern "C" jobject Java_org_linphone_core_LinphoneFriendImpl_getCore(JNIEnv* en } return NULL; } + +extern "C" jobject Java_org_linphone_core_LinphoneFriendListImpl_getCore(JNIEnv* env + ,jobject thiz + ,jlong ptr) { + LinphoneCore *lc=linphone_friend_get_core((LinphoneFriend*)ptr); + if (lc!=NULL){ + jobject core = (jobject)linphone_core_get_user_data(lc); + return core; + } + return NULL; +} + extern "C" void Java_org_linphone_core_LinphoneFriendImpl_setRefKey(JNIEnv* env ,jobject thiz ,jlong ptr @@ -3032,6 +3088,14 @@ extern "C" void Java_org_linphone_core_LinphoneFriendImpl_finalize(JNIEnv* env linphone_friend_unref(lfriend); } +extern "C" void Java_org_linphone_core_LinphoneFriendListImpl_finalize(JNIEnv* env + ,jobject thiz + ,jlong ptr) { + LinphoneFriendList *lfriendList=(LinphoneFriendList*)ptr; + linphone_friend_list_set_user_data(lfriendList,NULL); + linphone_friend_list_unref(lfriendList); +} + /* * Class: org_linphone_core_LinphoneFriendImpl * Method: getPresenceModel diff --git a/java/common/org/linphone/core/LinphoneCore.java b/java/common/org/linphone/core/LinphoneCore.java index f2ce0ccab..0151ad643 100644 --- a/java/common/org/linphone/core/LinphoneCore.java +++ b/java/common/org/linphone/core/LinphoneCore.java @@ -998,6 +998,16 @@ public interface LinphoneCore { * @throws LinphoneCoreException */ void addFriend(LinphoneFriend lf) throws LinphoneCoreException; + + /** + * Sets the friend list for the linphone core. + */ + void setFriendList(LinphoneFriendList friendList) throws LinphoneCoreException; + + /** + * Creates a friend list. + */ + LinphoneFriendList createLinphoneFriendList() throws LinphoneCoreException; /** * Get list of LinphoneFriend diff --git a/java/impl/org/linphone/core/LinphoneCoreImpl.java b/java/impl/org/linphone/core/LinphoneCoreImpl.java index 87842c78e..582bf6bd4 100644 --- a/java/impl/org/linphone/core/LinphoneCoreImpl.java +++ b/java/impl/org/linphone/core/LinphoneCoreImpl.java @@ -94,6 +94,7 @@ class LinphoneCoreImpl implements LinphoneCore { private native void setPreviewWindowId(long nativePtr, Object wid); private native void setDeviceRotation(long nativePtr, int rotation); private native void addFriend(long nativePtr,long friend); + private native void setFriendList(long nativePtr,long friendList); private native LinphoneFriend[] getFriendList(long nativePtr); private native void setPresenceInfo(long nativePtr, int minutes_away, String alternative_contact, int status); private native int getPresenceInfo(long nativePtr); @@ -448,6 +449,15 @@ class LinphoneCoreImpl implements LinphoneCore { public synchronized void addFriend(LinphoneFriend lf) throws LinphoneCoreException { addFriend(nativePtr,((LinphoneFriendImpl)lf).nativePtr); } + + + public synchronized LinphoneFriendList createLinphoneFriendList() { + return new LinphoneFriendListImpl(this); + } + + public synchronized void setFriendList(LinphoneFriendList friendList) throws LinphoneCoreException { + setFriendList(nativePtr,((LinphoneFriendListImpl)friendList).nativePtr); + } public synchronized LinphoneFriend[] getFriendList() { return getFriendList(nativePtr); From e54b075fbc202d3aa370a48779a1e91368ea6bfd Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Mon, 14 Dec 2015 17:05:10 +0100 Subject: [PATCH 23/30] Fix memory leaks in presence tester. --- tester/presence_tester.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tester/presence_tester.c b/tester/presence_tester.c index 576df13c5..97c4ac353 100644 --- a/tester/presence_tester.c +++ b/tester/presence_tester.c @@ -594,6 +594,7 @@ static void test_presence_list(void) { lf = linphone_core_create_friend_with_address(laure->lc, "sip:michelle@sip.inexistentdomain.com"); linphone_friend_list_add_friend(lfl, lf); linphone_core_set_friend_list(laure->lc, lfl); + linphone_friend_list_unref(lfl); linphone_core_set_presence_model(laure->lc, linphone_core_create_presence_model_with_activity(laure->lc, LinphonePresenceActivityOnline, NULL)); lcs = ms_list_append(lcs, laure->lc); @@ -624,6 +625,7 @@ static void test_presence_list(void) { lf = linphone_core_create_friend_with_address(marie->lc, laure_identity); linphone_friend_list_add_friend(lfl, lf); linphone_core_set_friend_list(marie->lc, lfl); + linphone_friend_list_unref(lfl); linphone_friend_list_update_subscriptions(pauline->lc->friendlist, NULL, FALSE); wait_for_list(lcs, &marie->stat.number_of_NotifyReceived, 1, 2000); @@ -641,6 +643,7 @@ static void test_presence_list(void) { lf = linphone_core_create_friend_with_address(pauline->lc, marie_identity); linphone_friend_list_add_friend(lfl, lf); linphone_core_set_friend_list(pauline->lc, lfl); + linphone_friend_list_unref(lfl); linphone_friend_list_update_subscriptions(pauline->lc->friendlist, NULL, FALSE); wait_for_list(lcs, &pauline->stat.number_of_NotifyReceived, 1, 2000); @@ -701,8 +704,8 @@ static void test_presence_list_subscribe_before_publish(void) { lf = linphone_core_create_friend_with_address(laure->lc, "sip:michelle@sip.inexistentdomain.com"); linphone_friend_list_add_friend(lfl, lf); linphone_core_set_friend_list(laure->lc, lfl); + linphone_friend_list_unref(lfl); linphone_core_set_presence_model(laure->lc, linphone_core_create_presence_model_with_activity(laure->lc, LinphonePresenceActivityOnline, NULL)); - //linphone_friend_list_update_subscriptions(pauline->lc->friendlist, NULL, FALSE); lcs = ms_list_append(lcs, laure->lc); lcs = ms_list_append(lcs, pauline->lc); From 342d404c352e043d1f3ce2b58d62c67dd37be1e7 Mon Sep 17 00:00:00 2001 From: Christophe Deschamps Date: Tue, 15 Dec 2015 10:42:05 +0100 Subject: [PATCH 24/30] Missing wrapper files --- .../org/linphone/core/LinphoneFriendList.java | 27 +++++++ .../linphone/core/LinphoneFriendListImpl.java | 80 +++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 java/common/org/linphone/core/LinphoneFriendList.java create mode 100644 java/impl/org/linphone/core/LinphoneFriendListImpl.java diff --git a/java/common/org/linphone/core/LinphoneFriendList.java b/java/common/org/linphone/core/LinphoneFriendList.java new file mode 100644 index 000000000..daeca4801 --- /dev/null +++ b/java/common/org/linphone/core/LinphoneFriendList.java @@ -0,0 +1,27 @@ +/* +LinphoneFriend.java +Copyright (C) 2010 Belledonne Communications, Grenoble, France + +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. +*/ +package org.linphone.core; + + +public interface LinphoneFriendList { + public void setRLSUri(String uri); + public void addFriend(LinphoneFriend friend); + public void updateSubscriptions(LinphoneProxyConfig proxyConfig,boolean onlyWhenRegistered); + long getNativePtr(); +} diff --git a/java/impl/org/linphone/core/LinphoneFriendListImpl.java b/java/impl/org/linphone/core/LinphoneFriendListImpl.java new file mode 100644 index 000000000..15832f786 --- /dev/null +++ b/java/impl/org/linphone/core/LinphoneFriendListImpl.java @@ -0,0 +1,80 @@ +/* +LinphoneFriendImpl.java +Copyright (C) 2010 Belledonne Communications, Grenoble, France + +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. +*/ +package org.linphone.core; + +import java.io.Serializable; +import org.linphone.core.LinphoneProxyConfigImpl; + +class LinphoneFriendListImpl implements LinphoneFriendList, Serializable { + + protected final long nativePtr; + private native void finalize(long nativePtr); + private native long newLinphoneFriendList(long corePtr); + private native void setRLSUri(long nativePtr,String uri); + private native void addFriend(long nativePtr,long friendPtr); + private native void updateSubscriptions(long nativePtr,long proxyConfigPtr,boolean onlyWhenRegistered); + private native Object getCore(long ptr); + + + protected LinphoneFriendListImpl(LinphoneCoreImpl core) { + nativePtr = newLinphoneFriendList(core.nativePtr); + } + + @Override + public void setRLSUri(String uri) { + synchronized(getSyncObject()){ + setRLSUri(nativePtr, uri); + } + } + + @Override + public void addFriend(LinphoneFriend friend) { + synchronized(getSyncObject()){ + addFriend(nativePtr, friend.getNativePtr()); + } + } + + @Override + public void updateSubscriptions(LinphoneProxyConfig proxyConfig,boolean onlyWhenRegistered) { + synchronized(getSyncObject()){ + updateSubscriptions(nativePtr, ((LinphoneProxyConfigImpl)proxyConfig).nativePtr,onlyWhenRegistered); + } + } + + /*reserved for JNI */ + protected LinphoneFriendListImpl(long aNativePtr) { + nativePtr = aNativePtr; + } + @Override + protected void finalize() throws Throwable { + if (nativePtr != 0) { + finalize(nativePtr); + } + super.finalize(); + } + + @Override + public long getNativePtr() { + return nativePtr; + } + private Object getSyncObject(){ + return this; + } +} + From 0ae4fbaba06bb809bbd9ec97a3cee20e40aa66bf Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Tue, 15 Dec 2015 11:39:14 +0100 Subject: [PATCH 25/30] update presence tester --- tester/presence_tester.c | 10 ++++++---- tester/setup_tester.c | 2 ++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tester/presence_tester.c b/tester/presence_tester.c index 97c4ac353..6f29b0915 100644 --- a/tester/presence_tester.c +++ b/tester/presence_tester.c @@ -391,10 +391,12 @@ static void subscribe_presence_forked(void){ } static void subscribe_presence_expired(void){ - LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); - LinphoneCoreManager* pauline1 = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + LinphoneCoreManager* marie = presence_linphone_core_manager_new("marie"); + LinphoneCoreManager* pauline1 = presence_linphone_core_manager_new("pauline"); + LinphoneAddress *marie_addr = linphone_address_clone(marie->identity); LinphoneFriend *lf; MSList *lcs = NULL; + linphone_address_set_port(marie_addr,0); /*remove port */ lcs = ms_list_append(lcs, marie->lc); lcs = ms_list_append(lcs, pauline1->lc); @@ -411,7 +413,7 @@ static void subscribe_presence_expired(void){ BC_ASSERT_TRUE(wait_for_list(lcs,&pauline1->stat.number_of_NewSubscriptionRequest,1, 5000)); BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphonePresenceActivityOnline,1, 2000)); - lf = linphone_core_find_friend(pauline1->lc, marie->identity); + lf = linphone_core_find_friend(pauline1->lc, marie_addr); BC_ASSERT_PTR_NOT_NULL(lf->insubs); /*marie comes offline suddenly*/ linphone_core_set_network_reachable(marie->lc, FALSE); @@ -421,7 +423,7 @@ static void subscribe_presence_expired(void){ BC_ASSERT_PTR_NULL(lf->insubs); /*just make network reachable so that marie can unregister properly*/ linphone_core_set_network_reachable(marie->lc, TRUE); - BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneRegistrationOk,2, 10000)); + //BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneRegistrationOk,2, 10000)); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline1); diff --git a/tester/setup_tester.c b/tester/setup_tester.c index a4af256c1..8aa744666 100644 --- a/tester/setup_tester.c +++ b/tester/setup_tester.c @@ -41,6 +41,8 @@ static void core_init_test(void) { static void linphone_address_test(void) { linphone_address_destroy(create_linphone_address(NULL)); + BC_ASSERT_PTR_NULL(linphone_address_new("sip:@sip.linphone.org")); + } static void core_sip_transport_test(void) { From 256d4e183617700377222887fdaefbf74c1ad259 Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Wed, 16 Dec 2015 10:54:06 +0100 Subject: [PATCH 26/30] make sure presence test still use proxy even in p2p mode --- tester/flexisip/flexisip.conf | 23 +++++++++++++++-------- tester/presence_tester.c | 10 ++++------ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/tester/flexisip/flexisip.conf b/tester/flexisip/flexisip.conf index f1cce0bef..5943e57a3 100644 --- a/tester/flexisip/flexisip.conf +++ b/tester/flexisip/flexisip.conf @@ -38,9 +38,9 @@ aliases=localhost sip2.linphone.org sipopen.example.org sip.example.org auth.exa # Default value: sip:* #transports=sip:192.168.56.101:5060 sips:192.168.56.101:5061 -#note: the ip addresses are explicitely specified here because the machine has several interfaces. In a simple case, using '*' instead of the explicit ip address is sufficient, +#note: the ip addresses are explicitely specified here because the machine has several interfaces. In a simple case, using '*' instead of the explicit ip address is sufficient, #and there is no need to specify the ipv6 transport addresses. -transports=sip:MacBook-Pro-de-jehan.local:5060 sips:MacBook-Pro-de-jehan.local:5061;tls-certificates-dir=/etc/flexisip/tls/certificates/cn sips:MacBook-Pro-de-jehan.local:5062;tls-certificates-dir=/etc/flexisip/tls/certificates/altname sips:MacBook-Pro-de-jehan.local:5063;require-peer-certificate=1 sip:MacBook-Pro-de-jehan.local:5064 sip:[2001:41d0:2:14b0::1]:5060 sips:[2001:41d0:2:14b0::1]:5061;tls-certificates-dir=/etc/flexisip/tls/certificates/cn sips:[2001:41d0:2:14b0::1]:5062;tls-certificates-dir=/etc/flexisip/tls/certificates/altname sips:[2001:41d0:2:14b0::1]:5063;require-peer-certificate=1 sip:[2001:41d0:2:14b0::1]:5064 +transports=sip:94.23.19.176:5060 sips:94.23.19.176:5061;tls-certificates-dir=/etc/flexisip/tls/certificates/cn sips:94.23.19.176:5062;tls-certificates-dir=/etc/flexisip/tls/certificates/altname sips:94.23.19.176:5063;require-peer-certificate=1 sip:94.23.19.176:5064 sip:[2001:41d0:2:14b0::1]:5060 sips:[2001:41d0:2:14b0::1]:5061;tls-certificates-dir=/etc/flexisip/tls/certificates/cn sips:[2001:41d0:2:14b0::1]:5062;tls-certificates-dir=/etc/flexisip/tls/certificates/altname sips:[2001:41d0:2:14b0::1]:5063;require-peer-certificate=1 sip:[2001:41d0:2:14b0::1]:5064 # An absolute path of a directory where TLS server certificate and @@ -107,20 +107,19 @@ no-403=user-agent contains 'tester-no-403' # to true. Ex: from.uri.domain contains 'sip.linphone.org', from.uri.domain # in 'a.org b.org c.org', (to.uri.domain in 'a.org b.org c.org') # && (user-agent == 'Linphone v2') -# Default value: -filter= from.uri.domain contains 'sip.example.org' || from.uri.domain contains 'auth.example.org' || from.uri.domain contains 'auth1.example.org' || from.uri.domain contains 'auth2.example.org' || from.uri.domain contains 'anonymous.invalid' +# Default value: +filter= from.uri.domain contains 'sip.example.org' || from.uri.domain contains 'auth.example.org' || from.uri.domain contains 'auth1.example.org' || from.uri.domain contains 'auth2.example.org' || from.uri.domain contains 'anonymous.invalid' # List of whitespace separated domain names to challenge. Others # are denied. -# Default value: +# Default value: auth-domains= sip.example.org auth.example.org auth1.example.org auth2.example.org -client-certificates-domains=client.example.org # List of whitespace separated IP which will not be challenged. -# Default value: -trusted-hosts= +# Default value: +trusted-hosts=127.0.0.1 94.23.19.176 # Database backend implementation [odbc, file]. # Default value: odbc @@ -615,3 +614,11 @@ packet-rate-limit=5 # Default value: 2 ban-time=1 +[module::Presence] +enabled=true +presence-server = + +[presence-server] +expires = 600 +transports = sip:127.0.0.1:5065;transport=tcp + diff --git a/tester/presence_tester.c b/tester/presence_tester.c index 6f29b0915..97c4ac353 100644 --- a/tester/presence_tester.c +++ b/tester/presence_tester.c @@ -391,12 +391,10 @@ static void subscribe_presence_forked(void){ } static void subscribe_presence_expired(void){ - LinphoneCoreManager* marie = presence_linphone_core_manager_new("marie"); - LinphoneCoreManager* pauline1 = presence_linphone_core_manager_new("pauline"); - LinphoneAddress *marie_addr = linphone_address_clone(marie->identity); + LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager* pauline1 = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); LinphoneFriend *lf; MSList *lcs = NULL; - linphone_address_set_port(marie_addr,0); /*remove port */ lcs = ms_list_append(lcs, marie->lc); lcs = ms_list_append(lcs, pauline1->lc); @@ -413,7 +411,7 @@ static void subscribe_presence_expired(void){ BC_ASSERT_TRUE(wait_for_list(lcs,&pauline1->stat.number_of_NewSubscriptionRequest,1, 5000)); BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphonePresenceActivityOnline,1, 2000)); - lf = linphone_core_find_friend(pauline1->lc, marie_addr); + lf = linphone_core_find_friend(pauline1->lc, marie->identity); BC_ASSERT_PTR_NOT_NULL(lf->insubs); /*marie comes offline suddenly*/ linphone_core_set_network_reachable(marie->lc, FALSE); @@ -423,7 +421,7 @@ static void subscribe_presence_expired(void){ BC_ASSERT_PTR_NULL(lf->insubs); /*just make network reachable so that marie can unregister properly*/ linphone_core_set_network_reachable(marie->lc, TRUE); - //BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneRegistrationOk,2, 10000)); + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneRegistrationOk,2, 10000)); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline1); From 8950b9d6fb7314fd72721b510b63bbc0151c30a3 Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Wed, 16 Dec 2015 15:50:51 +0100 Subject: [PATCH 27/30] disable presence test using presence server --- tester/flexisip_tester.c | 7 +------ tester/presence_tester.c | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/tester/flexisip_tester.c b/tester/flexisip_tester.c index c89e3fd67..228233108 100644 --- a/tester/flexisip_tester.c +++ b/tester/flexisip_tester.c @@ -884,9 +884,6 @@ static void dos_module_trigger(void) { linphone_core_manager_destroy(pauline); } -#define USE_PRESENCE_SERVER 1 - -#if USE_PRESENCE_SERVER static void test_subscribe_notify_with_sipp_publisher(void) { char *scen; @@ -1050,7 +1047,7 @@ static void test_list_subscribe (void) { linphone_core_manager_destroy(pauline); linphone_core_manager_destroy(laure); } -#endif + test_t flexisip_tests[] = { { "Subscribe forking", subscribe_forking }, @@ -1069,12 +1066,10 @@ test_t flexisip_tests[] = { { "Call with sips", call_with_sips }, { "Call with sips not achievable", call_with_sips_not_achievable }, { "Call with ipv6", call_with_ipv6 }, -#if USE_PRESENCE_SERVER { "Subscribe Notify with sipp publisher", test_subscribe_notify_with_sipp_publisher }, { "Subscribe Notify with sipp double publish", test_subscribe_notify_with_sipp_publisher_double_publish }, { "Publish/unpublish", test_publish_unpublish }, { "List subscribe", test_list_subscribe }, -#endif { "File transfer message rcs to external body client", file_transfer_message_rcs_to_external_body_client }, { "File transfer message external body to rcs client", file_transfer_message_external_body_to_rcs_client }, { "File transfer message external body to external body client", file_transfer_message_external_body_to_external_body_client }, diff --git a/tester/presence_tester.c b/tester/presence_tester.c index 97c4ac353..064cff909 100644 --- a/tester/presence_tester.c +++ b/tester/presence_tester.c @@ -429,7 +429,7 @@ static void subscribe_presence_expired(void){ } -#define USE_PRESENCE_SERVER 1 +#define USE_PRESENCE_SERVER 0 #if USE_PRESENCE_SERVER static void test_subscribe_notify_publish(void) { From 03261a97b161cb736d8ce2609c7cf8c8d98a948e Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Fri, 18 Dec 2015 14:56:20 +0100 Subject: [PATCH 28/30] Add API to refresh a subscription. --- coreapi/bellesip_sal/sal_op_events.c | 9 +++++++++ coreapi/event.c | 4 ++++ coreapi/event.h | 9 ++++++++- include/sal/sal.h | 1 + 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/coreapi/bellesip_sal/sal_op_events.c b/coreapi/bellesip_sal/sal_op_events.c index d41440d96..631e23b36 100644 --- a/coreapi/bellesip_sal/sal_op_events.c +++ b/coreapi/bellesip_sal/sal_op_events.c @@ -223,6 +223,15 @@ int sal_subscribe(SalOp *op, const char *from, const char *to, const char *event return -1; } +int sal_subscribe_refresh(SalOp *op) { + if (op->refresher) { + belle_sip_refresher_refresh(op->refresher,belle_sip_refresher_get_expires(op->refresher)); + return 0; + } + ms_warning("sal_refresh_subscribe(): no refresher"); + return -1; +} + int sal_unsubscribe(SalOp *op){ if (op->refresher){ const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(op->refresher); diff --git a/coreapi/event.c b/coreapi/event.c index 9320047ae..8fd95ede6 100644 --- a/coreapi/event.c +++ b/coreapi/event.c @@ -192,6 +192,10 @@ int linphone_event_update_subscribe(LinphoneEvent *lev, const LinphoneContent *b return linphone_event_send_subscribe(lev,body); } +int linphone_event_refresh_subscribe(LinphoneEvent *lev) { + return sal_subscribe_refresh(lev->op); +} + int linphone_event_accept_subscription(LinphoneEvent *lev){ int err; if (lev->subscription_state!=LinphoneSubscriptionIncomingReceived){ diff --git a/coreapi/event.h b/coreapi/event.h index fe3f984de..5200beb66 100644 --- a/coreapi/event.h +++ b/coreapi/event.h @@ -138,12 +138,19 @@ LINPHONE_PUBLIC LinphoneEvent *linphone_core_create_subscribe(LinphoneCore *lc, LINPHONE_PUBLIC int linphone_event_send_subscribe(LinphoneEvent *ev, const LinphoneContent *body); /** - * Update (refresh) an outgoing subscription. + * Update (refresh) an outgoing subscription, changing the body. * @param lev a LinphoneEvent * @param body an optional body to include in the subscription update, may be NULL. **/ LINPHONE_PUBLIC int linphone_event_update_subscribe(LinphoneEvent *lev, const LinphoneContent *body); +/** + * Refresh an outgoing subscription keeping the same body. + * @param lev LinphoneEvent object. + * @return 0 if successful, -1 otherwise. + */ +LINPHONE_PUBLIC int linphone_event_refresh_subscribe(LinphoneEvent *lev); + /** * Accept an incoming subcription. diff --git a/include/sal/sal.h b/include/sal/sal.h index 6031278bf..dccc2d08e 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -742,6 +742,7 @@ int sal_subscribe(SalOp *op, const char *from, const char *to, const char *event int sal_unsubscribe(SalOp *op); int sal_subscribe_accept(SalOp *op); int sal_subscribe_decline(SalOp *op, SalReason reason); +int sal_subscribe_refresh(SalOp *op); int sal_notify(SalOp *op, const SalBodyHandler *body); int sal_notify_close(SalOp *op); int sal_publish(SalOp *op, const char *from, const char *to, const char*event_name, int expires, const SalBodyHandler *body); From da682bf63ad214529f3760c2e4897b14e912147d Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Fri, 18 Dec 2015 14:58:29 +0100 Subject: [PATCH 29/30] If a presence list subscription already exist refresh it instead of creating a new one. --- coreapi/friendlist.c | 19 +++++++++++-------- coreapi/private.h | 2 +- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/coreapi/friendlist.c b/coreapi/friendlist.c index 1c4178aba..4d02dc9a7 100644 --- a/coreapi/friendlist.c +++ b/coreapi/friendlist.c @@ -120,6 +120,7 @@ static void linphone_friend_list_parse_multipart_related_body(LinphoneFriendList linphone_free_xml_text_content(version_str); if (version < list->expected_notification_version) { ms_warning("rlmi+xml: Discarding received notification with version %d because %d was expected", version, list->expected_notification_version); + linphone_friend_list_update_subscriptions(list, NULL, FALSE); /* Refresh subscription to get new full state notify. */ goto end; } @@ -224,6 +225,7 @@ static LinphoneFriendList * linphone_friend_list_new(void) { static void linphone_friend_list_destroy(LinphoneFriendList *list) { if (list->display_name != NULL) ms_free(list->display_name); if (list->rls_uri != NULL) ms_free(list->rls_uri); + if (list->event != NULL) linphone_event_unref(list->event); list->friends = ms_list_free_with_data(list->friends, (void (*)(void *))linphone_friend_unref); } @@ -364,24 +366,25 @@ void linphone_friend_list_close_subscriptions(LinphoneFriendList *list) { void linphone_friend_list_update_subscriptions(LinphoneFriendList *list, LinphoneProxyConfig *cfg, bool_t only_when_registered) { const MSList *elem; - if (list->rls_uri != NULL) { + if (list->event != NULL) { + linphone_event_refresh_subscribe(list->event); + } else if (list->rls_uri != NULL) { LinphoneAddress *address = linphone_address_new(list->rls_uri); char *xml_content = create_resource_list_xml(list); if ((address != NULL) && (xml_content != NULL) && (linphone_friend_list_has_subscribe_inactive(list) == TRUE)) { - LinphoneEvent *event; LinphoneContent *content; int expires = lp_config_get_int(list->lc->config, "sip", "rls_presence_expires", 3600); list->expected_notification_version = 0; - event = linphone_core_create_subscribe(list->lc, address, "presence", expires); - linphone_event_add_custom_header(event, "Require", "recipient-list-subscribe"); - linphone_event_add_custom_header(event, "Supported", "eventlist"); - linphone_event_add_custom_header(event, "Accept", "multipart/related, application/pidf+xml, application/rlmi+xml"); - linphone_event_add_custom_header(event, "Content-Disposition", "recipient-list"); + list->event = linphone_core_create_subscribe(list->lc, address, "presence", expires); + linphone_event_add_custom_header(list->event, "Require", "recipient-list-subscribe"); + linphone_event_add_custom_header(list->event, "Supported", "eventlist"); + linphone_event_add_custom_header(list->event, "Accept", "multipart/related, application/pidf+xml, application/rlmi+xml"); + linphone_event_add_custom_header(list->event, "Content-Disposition", "recipient-list"); content = linphone_core_create_content(list->lc); linphone_content_set_type(content, "application"); linphone_content_set_subtype(content, "resource-lists+xml"); linphone_content_set_string_buffer(content, xml_content); - linphone_event_send_subscribe(event, content); + linphone_event_send_subscribe(list->event, content); linphone_content_unref(content); } if (address != NULL) linphone_address_unref(address); diff --git a/coreapi/private.h b/coreapi/private.h index 61fe10265..b6b8ae3d7 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -361,7 +361,6 @@ void linphone_core_write_auth_info(LinphoneCore *lc, LinphoneAuthInfo *ai); const LinphoneAuthInfo *_linphone_core_find_auth_info(LinphoneCore *lc, const char *realm, const char *username, const char *domain, bool_t ignore_realm); void linphone_core_update_proxy_register(LinphoneCore *lc); -void linphone_core_refresh_subscribes(LinphoneCore *lc); int linphone_core_abort_call(LinphoneCore *lc, LinphoneCall *call, const char *error); const char *linphone_core_get_nat_address_resolved(LinphoneCore *lc); @@ -657,6 +656,7 @@ struct _LinphoneFriendList { belle_sip_object_t base; void *user_data; LinphoneCore *lc; + LinphoneEvent *event; char *display_name; char *rls_uri; MSList *friends; From 820d26bacf6786eb4844399ab716e1522538e19e Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Fri, 18 Dec 2015 15:00:04 +0100 Subject: [PATCH 30/30] Fix presence list tests. --- coreapi/friend.c | 29 +++++++++++++++++++++++++++-- coreapi/presence.c | 4 +++- tester/presence_tester.c | 15 ++++++++------- 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/coreapi/friend.c b/coreapi/friend.c index d46124f58..600280693 100644 --- a/coreapi/friend.c +++ b/coreapi/friend.c @@ -488,7 +488,7 @@ LinphoneFriend * linphone_core_create_friend_with_address(LinphoneCore *lc, cons } void linphone_core_add_friend(LinphoneCore *lc, LinphoneFriend *lf) { - if (linphone_friend_list_add_friend(lc->friendlist, lf) != LinphoneFriendListOK) return; + if ((lc->friendlist == NULL) || (linphone_friend_list_add_friend(lc->friendlist, lf) != LinphoneFriendListOK)) return; if (ms_list_find(lc->subscribers, lf)) { /*if this friend was in the pending subscriber list, now remove it from this list*/ lc->subscribers = ms_list_remove(lc->subscribers, lf); @@ -515,9 +515,34 @@ bool_t linphone_core_should_subscribe_friends_only_when_registered(const Linphon } void linphone_core_send_initial_subscribes(LinphoneCore *lc){ + bool_t proxy_config_for_rls_presence_uri_domain = FALSE; + LinphoneAddress *rls_address = NULL; + const MSList *elem; + if (lc->initial_subscribes_sent) return; lc->initial_subscribes_sent=TRUE; - linphone_core_update_friends_subscriptions(lc,NULL,linphone_core_should_subscribe_friends_only_when_registered(lc)); + if (lc->friendlist->rls_uri != NULL) { + rls_address = linphone_core_create_address(lc, lc->friendlist->rls_uri); + } + if (rls_address != NULL) { + const char *rls_domain = linphone_address_get_domain(rls_address); + if (rls_domain != NULL) { + for (elem = linphone_core_get_proxy_config_list(lc); elem != NULL; elem = elem->next) { + LinphoneProxyConfig *cfg = (LinphoneProxyConfig *)elem->data; + const char *proxy_domain = linphone_proxy_config_get_domain(cfg); + if (strcmp(rls_domain, proxy_domain) == 0) { + proxy_config_for_rls_presence_uri_domain = TRUE; + break; + } + } + } + linphone_address_unref(rls_address); + } + if (proxy_config_for_rls_presence_uri_domain == TRUE) { + ms_message("Presence list activated so do not send initial subscribes it will be done when registered"); + } else { + linphone_core_update_friends_subscriptions(lc,NULL,linphone_core_should_subscribe_friends_only_when_registered(lc)); + } } void linphone_core_invalidate_friend_subscriptions(LinphoneCore *lc){ diff --git a/coreapi/presence.c b/coreapi/presence.c index a25261d52..ea6744ef6 100644 --- a/coreapi/presence.c +++ b/coreapi/presence.c @@ -1482,7 +1482,9 @@ void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from){ ms_message("Receiving new subscription from %s.",from); /* check if we answer to this subscription */ - lf = linphone_friend_list_find_friend_by_address(lc->friendlist, uri); + if (lc->friendlist != NULL) { + lf = linphone_friend_list_find_friend_by_address(lc->friendlist, uri); + } if (lf!=NULL){ linphone_friend_add_incoming_subscription(lf, op); lf->inc_subscribe_pending=TRUE; diff --git a/tester/presence_tester.c b/tester/presence_tester.c index 064cff909..003b56bde 100644 --- a/tester/presence_tester.c +++ b/tester/presence_tester.c @@ -560,7 +560,7 @@ static void enable_publish(LinphoneCoreManager *mgr, bool_t enable) { LinphoneProxyConfig *cfg = linphone_core_get_default_proxy_config(mgr->lc); linphone_proxy_config_edit(cfg); linphone_proxy_config_enable_publish(cfg, enable); - linphone_proxy_config_set_publish_expires(cfg, 3); + linphone_proxy_config_set_publish_expires(cfg, 60); linphone_proxy_config_done(cfg); } @@ -581,6 +581,7 @@ static void test_presence_list(void) { pauline_identity = get_identity(pauline); enable_publish(marie, TRUE); enable_publish(pauline, TRUE); + enable_publish(laure, TRUE); linphone_core_set_presence_model(marie->lc, linphone_core_create_presence_model_with_activity(marie->lc, LinphonePresenceActivityBusy, NULL)); linphone_core_set_presence_model(pauline->lc, linphone_core_create_presence_model_with_activity(pauline->lc, LinphonePresenceActivityVacation, NULL)); @@ -601,9 +602,9 @@ static void test_presence_list(void) { lcs = ms_list_append(lcs, marie->lc); lcs = ms_list_append(lcs, pauline->lc); - wait_for_list(lcs, &laure->stat.number_of_NotifyReceived, 1, 2000); + wait_for_list(lcs, &laure->stat.number_of_NotifyReceived, 2, 2000); wait_for_list(lcs, &laure->stat.number_of_NotifyPresenceReceived, 2, 2000); - BC_ASSERT_EQUAL(laure->stat.number_of_NotifyReceived, 1, int, "%d"); + BC_ASSERT_EQUAL(laure->stat.number_of_NotifyReceived, 2, int, "%d"); BC_ASSERT_EQUAL(laure->stat.number_of_NotifyPresenceReceived, 2, int, "%d"); BC_ASSERT_EQUAL(laure->lc->friendlist->expected_notification_version, 1, int, "%d"); lf = linphone_friend_list_find_friend_by_uri(laure->lc->friendlist, marie_identity); @@ -619,14 +620,13 @@ static void test_presence_list(void) { BC_ASSERT_EQUAL(lf->presence_received, FALSE, int, "%d"); BC_ASSERT_EQUAL(lf->subscribe_active, TRUE, int, "%d"); - enable_publish(laure, TRUE); lfl = linphone_core_create_friend_list(marie->lc); linphone_friend_list_set_rls_uri(lfl, rls_uri); lf = linphone_core_create_friend_with_address(marie->lc, laure_identity); linphone_friend_list_add_friend(lfl, lf); linphone_core_set_friend_list(marie->lc, lfl); linphone_friend_list_unref(lfl); - linphone_friend_list_update_subscriptions(pauline->lc->friendlist, NULL, FALSE); + linphone_friend_list_update_subscriptions(marie->lc->friendlist, NULL, FALSE); wait_for_list(lcs, &marie->stat.number_of_NotifyReceived, 1, 2000); wait_for_list(lcs, &marie->stat.number_of_NotifyPresenceReceived, 1, 2000); @@ -658,9 +658,9 @@ static void test_presence_list(void) { linphone_core_set_presence_model(marie->lc, linphone_core_create_presence_model_with_activity(marie->lc, LinphonePresenceActivityOnThePhone, NULL)); - wait_for_list(lcs, &laure->stat.number_of_NotifyReceived, 2, 2000); + wait_for_list(lcs, &laure->stat.number_of_NotifyReceived, 3, 2000); wait_for_list(lcs, &laure->stat.number_of_NotifyPresenceReceived, 4, 2000); - BC_ASSERT_EQUAL(laure->stat.number_of_NotifyReceived, 2, int, "%d"); + BC_ASSERT_EQUAL(laure->stat.number_of_NotifyReceived, 3, int, "%d"); BC_ASSERT_EQUAL(laure->stat.number_of_NotifyPresenceReceived, 4, int, "%d"); BC_ASSERT_EQUAL(laure->lc->friendlist->expected_notification_version, 2, int, "%d"); lf = linphone_friend_list_find_friend_by_uri(laure->lc->friendlist, marie_identity); @@ -706,6 +706,7 @@ static void test_presence_list_subscribe_before_publish(void) { linphone_core_set_friend_list(laure->lc, lfl); linphone_friend_list_unref(lfl); linphone_core_set_presence_model(laure->lc, linphone_core_create_presence_model_with_activity(laure->lc, LinphonePresenceActivityOnline, NULL)); + linphone_friend_list_update_subscriptions(laure->lc->friendlist, NULL, FALSE); lcs = ms_list_append(lcs, laure->lc); lcs = ms_list_append(lcs, pauline->lc);