From 96d249c674bd1d6e12ca192e7fca0ea0cdbabe3f Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Tue, 10 Nov 2015 09:45:29 +0100 Subject: [PATCH] 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;