Commit fccaa5e3 authored by Ghislain MARY's avatar Ghislain MARY

Handle versioning of presence list notifications + store information that we...

Handle versioning of presence list notifications + store information that we have received presence information for a friend.
parent 97f28a65
......@@ -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){
......
......@@ -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);
}
......
......@@ -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.
**/
......
......@@ -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){
......
......@@ -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);
......
......@@ -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);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment