From c979eeaa34a7143bbab2fad4dc96cbe69b2b31bd Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Fri, 17 Mar 2017 14:50:28 +0100 Subject: [PATCH] Rework presence to remove online and offline virtual activities and introduce consolidated presence. --- coreapi/friend.c | 16 ++-- coreapi/help/buddy_status.c | 11 ++- coreapi/linphonecore.c | 82 +++++++++++++---- coreapi/presence.c | 150 ++++++++++++++++++-------------- coreapi/proxy.c | 2 +- include/linphone/core.h | 14 +++ include/linphone/friend.h | 7 ++ include/linphone/presence.h | 26 ++++++ include/linphone/types.h | 20 +++-- share/xml/pidfonline.xsd | 9 ++ tester/presence_server_tester.c | 87 +++++++++++++----- tester/presence_tester.c | 13 +-- 12 files changed, 313 insertions(+), 124 deletions(-) create mode 100644 share/xml/pidfonline.xsd diff --git a/coreapi/friend.c b/coreapi/friend.c index 2b3071faa..cb5da743d 100644 --- a/coreapi/friend.c +++ b/coreapi/friend.c @@ -504,7 +504,8 @@ void linphone_friend_invalidate_subscription(LinphoneFriend *lf){ while (iterator) { LinphoneFriendPresence *lfp = (LinphoneFriendPresence *)bctbx_list_get_data(iterator); linphone_presence_model_unref(lfp->presence); - lfp->presence = linphone_presence_model_new_with_activity(LinphonePresenceActivityOffline, "unknown activity"); + lfp->presence = linphone_presence_model_new(); + linphone_presence_model_set_basic_status(lfp->presence, LinphonePresenceBasicStatusClosed); linphone_core_notify_notify_presence_received_for_uri_or_tel(lc, lf, lfp->uri_or_tel, lfp->presence); iterator = bctbx_list_next(iterator); } @@ -649,13 +650,6 @@ LinphoneOnlineStatus linphone_friend_get_status(const LinphoneFriend *lf){ case LinphonePresenceActivityUnknown: /* Rely on the basic status information. */ break; - case LinphonePresenceActivityOnline: - /* Should not happen! */ - /*ms_warning("LinphonePresenceActivityOnline should not happen here!");*/ - break; - case LinphonePresenceActivityOffline: - online_status = LinphoneStatusOffline; - break; } } } @@ -688,6 +682,12 @@ const LinphonePresenceModel * linphone_friend_get_presence_model(const LinphoneF return presence; } +LinphoneConsolidatedPresence linphone_friend_get_consolidated_presence(const LinphoneFriend *lf) { + const LinphonePresenceModel *model = linphone_friend_get_presence_model(lf); + if (!model) return LinphoneConsolidatedPresenceOffline; + return linphone_presence_model_get_consolidated_presence(model); +} + const LinphonePresenceModel * linphone_friend_get_presence_model_for_uri_or_tel(const LinphoneFriend *lf, const char *uri_or_tel) { LinphoneFriendPresence *lfp = find_presence_model_for_uri_or_tel(lf, uri_or_tel); if (lfp) return lfp->presence; diff --git a/coreapi/help/buddy_status.c b/coreapi/help/buddy_status.c index d138a378f..905162214 100644 --- a/coreapi/help/buddy_status.c +++ b/coreapi/help/buddy_status.c @@ -92,6 +92,7 @@ int main(int argc, char *argv[]){ char* password=NULL; LinphoneFriend* my_friend=NULL; + LinphonePresenceModel *model; /* takes sip uri identity from the command line arguments */ if (argc>1){ @@ -173,7 +174,10 @@ int main(int argc, char *argv[]){ } /*set my status to online*/ - linphone_core_set_presence_model(lc, linphone_presence_model_new_with_activity(LinphonePresenceActivityOnline, NULL)); + model = linphone_presence_model_new(); + linphone_presence_model_set_basic_status(model, LinphonePresenceBasicStatusOpen); + linphone_core_set_presence_model(lc, model); + linphone_presence_model_unref(model); /* main loop for receiving notifications and doing background linphone core work: */ while(running){ @@ -182,7 +186,10 @@ int main(int argc, char *argv[]){ } /* change my presence status to offline*/ - linphone_core_set_presence_model(lc, linphone_presence_model_new_with_activity(LinphonePresenceActivityOffline, NULL)); + model = linphone_presence_model_new(); + linphone_presence_model_set_basic_status(model, LinphonePresenceBasicStatusClosed); + linphone_core_set_presence_model(lc, model); + linphone_presence_model_unref(model); linphone_core_iterate(lc); /* just to make sure new status is initiate message is issued */ linphone_friend_edit(my_friend); /* start editing friend */ diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index c8646f11b..c2af0ca8d 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1934,7 +1934,8 @@ static void linphone_core_start(LinphoneCore * lc) { sip_config_read(lc); video_config_read(lc); //autoreplier_config_init(&lc->autoreplier_conf); - lc->presence_model=linphone_presence_model_new_with_activity(LinphonePresenceActivityOnline, NULL); + lc->presence_model=linphone_presence_model_new(); + linphone_presence_model_set_basic_status(lc->presence_model, LinphonePresenceBasicStatusOpen); misc_config_read(lc); ui_config_read(lc); #ifdef TUNNEL_ENABLED @@ -3628,18 +3629,20 @@ void linphone_core_set_delayed_timeout(LinphoneCore *lc, int seconds){ void linphone_core_set_presence_info(LinphoneCore *lc, int minutes_away, const char *contact, LinphoneOnlineStatus os) { LinphonePresenceModel *presence = NULL; + LinphonePresenceActivity *activity = NULL; char *description = NULL; LinphonePresenceActivityType acttype = LinphonePresenceActivityUnknown; if (minutes_away>0) lc->minutes_away=minutes_away; + presence = linphone_presence_model_new(); + linphone_presence_model_set_basic_status(presence, LinphonePresenceBasicStatusOpen); switch (os) { case LinphoneStatusOffline: - acttype = LinphonePresenceActivityOffline; - break; + linphone_presence_model_set_basic_status(presence, LinphonePresenceBasicStatusClosed); + goto end; case LinphoneStatusOnline: - acttype = LinphonePresenceActivityOnline; - break; + goto end; case LinphoneStatusBusy: acttype = LinphonePresenceActivityBusy; break; @@ -3658,6 +3661,7 @@ void linphone_core_set_presence_info(LinphoneCore *lc, int minutes_away, const c case LinphoneStatusDoNotDisturb: acttype = LinphonePresenceActivityBusy; description = "Do not disturb"; + linphone_presence_model_set_basic_status(presence, LinphonePresenceBasicStatusClosed); break; case LinphoneStatusMoved: acttype = LinphonePresenceActivityPermanentAbsence; @@ -3677,9 +3681,14 @@ void linphone_core_set_presence_info(LinphoneCore *lc, int minutes_away, const c ms_warning("Invalid status LinphoneStatusEnd"); return; } - presence = linphone_presence_model_new_with_activity(acttype, description); + activity = linphone_presence_activity_new(acttype, description); + linphone_presence_model_add_activity(presence, activity); + linphone_presence_activity_unref(activity); + +end: linphone_presence_model_set_contact(presence, contact); linphone_core_set_presence_model(lc, presence); + linphone_presence_model_unref(presence); } void linphone_core_send_presence(LinphoneCore *lc, LinphonePresenceModel *presence){ @@ -3688,12 +3697,10 @@ void linphone_core_send_presence(LinphoneCore *lc, LinphonePresenceModel *presen } void linphone_core_set_presence_model(LinphoneCore *lc, LinphonePresenceModel *presence) { - linphone_core_send_presence(lc,presence); - - if ((lc->presence_model != NULL) && (lc->presence_model != presence)) { - linphone_presence_model_unref(lc->presence_model); - lc->presence_model = presence; - } + linphone_presence_model_ref(presence); + linphone_core_send_presence(lc, presence); + if (lc->presence_model != NULL) linphone_presence_model_unref(lc->presence_model); + lc->presence_model = presence; } LinphoneOnlineStatus linphone_core_get_presence_info(const LinphoneCore *lc){ @@ -3704,10 +3711,6 @@ LinphoneOnlineStatus linphone_core_get_presence_info(const LinphoneCore *lc){ if (activity) { description = linphone_presence_activity_get_description(activity); switch (linphone_presence_activity_get_type(activity)) { - case LinphonePresenceActivityOffline: - return LinphoneStatusOffline; - case LinphonePresenceActivityOnline: - return LinphoneStatusOnline; case LinphonePresenceActivityBusy: if (description != NULL) { if (strcmp(description, "Do not disturb") == 0) @@ -3757,6 +3760,53 @@ LinphonePresenceModel * linphone_core_get_presence_model(const LinphoneCore *lc) return lc->presence_model; } +LinphoneConsolidatedPresence linphone_core_get_consolidated_presence(const LinphoneCore *lc) { + LinphoneProxyConfig *cfg = lc->default_proxy; + if ((cfg != NULL) && !linphone_proxy_config_publish_enabled(cfg)) return LinphoneConsolidatedPresenceOffline; + return linphone_presence_model_get_consolidated_presence(linphone_core_get_presence_model(lc)); +} + +void linphone_core_set_consolidated_presence(LinphoneCore *lc, LinphoneConsolidatedPresence presence) { + LinphoneProxyConfig *cfg; + LinphonePresenceModel *model; + LinphonePresenceActivity *activity = NULL; + + cfg = linphone_core_get_default_proxy_config(lc); + if ((cfg != NULL) && (presence == LinphoneConsolidatedPresenceOffline) && linphone_proxy_config_publish_enabled(cfg)) { + /* Unpublish when going offline before changing the presence model. */ + linphone_proxy_config_edit(cfg); + linphone_proxy_config_enable_publish(cfg, FALSE); + linphone_proxy_config_done(cfg); + } + model = linphone_presence_model_new(); + switch (presence) { + case LinphoneConsolidatedPresenceOnline: + linphone_presence_model_set_basic_status(model, LinphonePresenceBasicStatusOpen); + break; + case LinphoneConsolidatedPresenceBusy: + linphone_presence_model_set_basic_status(model, LinphonePresenceBasicStatusOpen); + activity = linphone_presence_activity_new(LinphonePresenceActivityAway, NULL); + break; + case LinphoneConsolidatedPresenceDoNotDisturb: + linphone_presence_model_set_basic_status(model, LinphonePresenceBasicStatusClosed); + activity = linphone_presence_activity_new(LinphonePresenceActivityAway, NULL); + break; + case LinphoneConsolidatedPresenceOffline: + default: + linphone_presence_model_set_basic_status(model, LinphonePresenceBasicStatusClosed); + break; + } + if (activity != NULL) linphone_presence_model_add_activity(model, activity); + linphone_core_set_presence_model(lc, model); + linphone_presence_model_unref(model); + if ((cfg != NULL) && (presence != LinphoneConsolidatedPresenceOffline) && !linphone_proxy_config_publish_enabled(cfg)) { + /* When going online or busy, publish after changing the presence model. */ + linphone_proxy_config_edit(cfg); + linphone_proxy_config_enable_publish(cfg, TRUE); + linphone_proxy_config_done(cfg); + } +} + int linphone_core_get_play_level(LinphoneCore *lc) { return lc->sound_conf.play_lev; } diff --git a/coreapi/presence.c b/coreapi/presence.c index 757a07327..864f5e79f 100644 --- a/coreapi/presence.c +++ b/coreapi/presence.c @@ -85,6 +85,7 @@ struct _LinphonePresenceModel { bctbx_list_t *services; /**< A list of _LinphonePresenceService structures. Also named tuples in the RFC. */ bctbx_list_t *persons; /**< A list of _LinphonePresencePerson structures. */ bctbx_list_t *notes; /**< A list of _LinphonePresenceNote structures. */ + bool_t is_online; }; BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphonePresenceModel); @@ -116,16 +117,6 @@ static char * generate_presence_id(void) { return ms_strdup(id); } -static const char * presence_basic_status_to_string(LinphonePresenceBasicStatus basic_status) { - switch (basic_status) { - case LinphonePresenceBasicStatusOpen: - return "open"; - case LinphonePresenceBasicStatusClosed: - default: - return "closed"; - } -} - static void presence_note_uninit(LinphonePresenceNote *note) { ms_free(note->content); if (note->lang != NULL) { @@ -280,6 +271,7 @@ static void presence_model_uninit(LinphonePresenceModel *model) { LinphonePresenceModel * linphone_presence_model_new_with_activity(LinphonePresenceActivityType acttype, const char *description) { LinphonePresenceModel *model = linphone_presence_model_new(); if (model != NULL) { + linphone_presence_model_set_basic_status(model, LinphonePresenceBasicStatusOpen); linphone_presence_model_set_activity(model, acttype, description); } return model; @@ -288,6 +280,7 @@ LinphonePresenceModel * linphone_presence_model_new_with_activity(LinphonePresen LinphonePresenceModel * linphone_presence_model_new_with_activity_and_note(LinphonePresenceActivityType acttype, const char *description, const char *note, const char *lang) { LinphonePresenceModel *model = linphone_presence_model_new(); if (model != NULL) { + linphone_presence_model_set_basic_status(model, LinphonePresenceBasicStatusOpen); linphone_presence_model_set_activity(model, acttype, description); linphone_presence_model_add_note(model, note, lang); } @@ -393,26 +386,11 @@ LinphonePresenceActivity * linphone_presence_model_get_activity(const LinphonePr } int linphone_presence_model_set_activity(LinphonePresenceModel *model, LinphonePresenceActivityType acttype, const char *description) { - LinphonePresenceBasicStatus basic_status = LinphonePresenceBasicStatusOpen; LinphonePresenceActivity *activity; int err = 0; if (model == NULL) return -1; - switch (acttype) { - case LinphonePresenceActivityAppointment: - case LinphonePresenceActivityBusy: - case LinphonePresenceActivityMeeting: - case LinphonePresenceActivityPermanentAbsence: - case LinphonePresenceActivityOffline: - case LinphonePresenceActivityWorship: - basic_status = LinphonePresenceBasicStatusClosed; - break; - default: - basic_status = LinphonePresenceBasicStatusOpen; - break; - } - if (linphone_presence_model_set_basic_status(model, basic_status) < 0) return -1; linphone_presence_model_clear_activities(model); activity = linphone_presence_activity_new(acttype, description); if (activity == NULL) return -1; @@ -704,6 +682,19 @@ const LinphoneAddress * linphone_presence_model_get_presentity(const LinphonePre return model->presentity; } +LinphoneConsolidatedPresence linphone_presence_model_get_consolidated_presence(const LinphonePresenceModel *model) { + LinphonePresenceBasicStatus basic_status; + + if (linphone_presence_model_is_online(model)) return LinphoneConsolidatedPresenceOnline; + basic_status = linphone_presence_model_get_basic_status(model); + if (basic_status == LinphonePresenceBasicStatusClosed) { + unsigned int nb_activities = linphone_presence_model_get_nb_activities(model); + if (nb_activities == 0) return LinphoneConsolidatedPresenceOffline; + else return LinphoneConsolidatedPresenceDoNotDisturb; + } + return LinphoneConsolidatedPresenceBusy; +} + BELLE_SIP_INSTANCIATE_VPTR( LinphonePresenceModel, belle_sip_object_t, @@ -717,6 +708,16 @@ BELLE_SIP_INSTANCIATE_VPTR( * PRESENCE SERVICE FUNCTIONS TO GET ACCESS TO ALL FUNCTIONALITIES * ****************************************************************************/ +char * linphone_presence_basic_status_to_string(LinphonePresenceBasicStatus basic_status) { + switch (basic_status) { + case LinphonePresenceBasicStatusOpen: + return ms_strdup("open"); + case LinphonePresenceBasicStatusClosed: + default: + return ms_strdup("closed"); + } +} + LinphonePresenceService * linphone_presence_service_new(const char *id, LinphonePresenceBasicStatus basic_status, const char *contact) { LinphonePresenceService *service; char *service_id; @@ -993,23 +994,13 @@ LinphonePresenceActivity * linphone_presence_activity_new(LinphonePresenceActivi char * linphone_presence_activity_to_string(const LinphonePresenceActivity *activity) { LinphonePresenceActivityType acttype = linphone_presence_activity_get_type(activity); const char *description = linphone_presence_activity_get_description(activity); - const char *acttype_str; - - if (acttype == LinphonePresenceActivityOffline) - acttype_str = "offline"; - else if (acttype == LinphonePresenceActivityOnline) - acttype_str = "online"; - else - acttype_str = presence_activity_type_to_string(acttype); - + const char *acttype_str = acttype_str = presence_activity_type_to_string(acttype); return ms_strdup_printf("%s%s%s", acttype_str, (description == NULL) ? "" : ": ", (description == NULL) ? "" : description); } LinphonePresenceActivityType linphone_presence_activity_get_type(const LinphonePresenceActivity *activity) { - if (activity == NULL) - return LinphonePresenceActivityOffline; return activity->type; } @@ -1264,6 +1255,11 @@ static int process_pidf_xml_presence_services(xmlparsing_context_t *xml_ctx, Lin return -1; } + snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/pidf:status/pidfonline:online", service_prefix, i); + if (linphone_get_xml_xpath_object_for_node_list(xml_ctx, xpath_str) != NULL) { + model->is_online = TRUE; + } + snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/pidf:timestamp", service_prefix, i); timestamp_str = linphone_get_xml_text_content(xml_ctx, xpath_str); @@ -1480,6 +1476,7 @@ static LinphonePresenceModel * process_pidf_xml_presence_notification(xmlparsing xmlXPathRegisterNs(xml_ctx->xpath_ctx, (const xmlChar *)"pidf", (const xmlChar *)"urn:ietf:params:xml:ns:pidf"); xmlXPathRegisterNs(xml_ctx->xpath_ctx, (const xmlChar *)"dm", (const xmlChar *)"urn:ietf:params:xml:ns:pidf:data-model"); xmlXPathRegisterNs(xml_ctx->xpath_ctx, (const xmlChar *)"rpid", (const xmlChar *)"urn:ietf:params:xml:ns:pidf:rpid"); + xmlXPathRegisterNs(xml_ctx->xpath_ctx, (const xmlChar *)"pidfonline", (const xmlChar *)"http://www.linphone.org/xsds/pidfonline.xsd"); err = process_pidf_xml_presence_services(xml_ctx, model); if (err == 0) { err = process_pidf_xml_presence_persons(xml_ctx, model); @@ -1525,8 +1522,13 @@ void linphone_core_reject_subscriber(LinphoneCore *lc, LinphoneFriend *lf){ } void linphone_core_notify_all_friends(LinphoneCore *lc, LinphonePresenceModel *presence){ + char *activity_str; LinphonePresenceActivity *activity = linphone_presence_model_get_activity(presence); - char *activity_str = linphone_presence_activity_to_string(activity); + if (activity == NULL) { + activity_str = linphone_presence_basic_status_to_string(linphone_presence_model_get_basic_status(presence)); + } else { + activity_str = linphone_presence_activity_to_string(activity); + } LinphoneFriendList *lfl = linphone_core_get_default_friend_list(lc); ms_message("Notifying all friends that we are [%s]", activity_str); if (activity_str != NULL) ms_free(activity_str); @@ -1612,6 +1614,7 @@ void linphone_notify_parse_presence(const char *content_type, const char *conten struct _presence_service_obj_st { xmlTextWriterPtr writer; const char *contact; + bool_t online; int *err; }; @@ -1663,7 +1666,7 @@ static int write_xml_presence_timestamp(xmlTextWriterPtr writer, time_t timestam return err; } -static int write_xml_presence_service(xmlTextWriterPtr writer, LinphonePresenceService *service, const char *contact) { +static int write_xml_presence_service(xmlTextWriterPtr writer, LinphonePresenceService *service, const char *contact, bool_t online) { int err = xmlTextWriterStartElement(writer, (const xmlChar *)"tuple"); if (err >= 0) { if ((service == NULL) || (service->id == NULL)) { @@ -1678,9 +1681,20 @@ static int write_xml_presence_service(xmlTextWriterPtr writer, LinphonePresenceS err = xmlTextWriterStartElement(writer, (const xmlChar *)"status"); } if (err >= 0) { + char *basic_status_str; LinphonePresenceBasicStatus basic_status = LinphonePresenceBasicStatusClosed; if (service != NULL) basic_status = service->status; - err = xmlTextWriterWriteElement(writer, (const xmlChar *)"basic", (const xmlChar *)presence_basic_status_to_string(basic_status)); + basic_status_str = linphone_presence_basic_status_to_string(basic_status); + err = xmlTextWriterWriteElement(writer, (const xmlChar *)"basic", (const xmlChar *)basic_status_str); + ms_free(basic_status_str); + } + if (online) { + if (err >= 0) { + err = xmlTextWriterStartElementNS(writer, (const xmlChar *)"pidfonline", (const xmlChar *)"online", NULL); + } + if (err >= 0) { + err = xmlTextWriterEndElement(writer); + } } if (err >= 0) { /* Close the "status" element. */ @@ -1724,17 +1738,9 @@ static int write_xml_presence_service(xmlTextWriterPtr writer, LinphonePresenceS return err; } -static bool_t is_valid_activity(LinphonePresenceActivity *activity) { - if ((activity->type == LinphonePresenceActivityOffline) || (activity->type == LinphonePresenceActivityOnline)) - return FALSE; - return TRUE; -} - static int write_xml_presence_activity(xmlTextWriterPtr writer, LinphonePresenceActivity *activity) { int err; - if (is_valid_activity(activity) == FALSE) return 0; - err = xmlTextWriterStartElementNS(writer, (const xmlChar *)"rpid", (const xmlChar *)presence_activity_type_to_string(activity->type), NULL); if ((err >= 0) && (activity->description != NULL)) { @@ -1751,21 +1757,9 @@ static void write_xml_presence_activity_obj(LinphonePresenceActivity *activity, if (err < 0) *st->err = err; } -static void person_has_valid_activity(LinphonePresenceActivity *activity, bool_t *has_valid_activities) { - if (is_valid_activity(activity) == TRUE) *has_valid_activities = TRUE; -} - -static bool_t person_has_valid_activities(LinphonePresencePerson *person) { - bool_t has_valid_activities = FALSE; - bctbx_list_for_each2(person->activities, (MSIterate2Func)person_has_valid_activity, &has_valid_activities); - return has_valid_activities; -} - static int write_xml_presence_person(xmlTextWriterPtr writer, LinphonePresencePerson *person) { int err; - if ((person_has_valid_activities(person) == FALSE) && (person->notes == NULL)) return 0; - err = xmlTextWriterStartElementNS(writer, (const xmlChar *)"dm", (const xmlChar *)"person", NULL); if (err >= 0) { if (person->id == NULL) { @@ -1776,7 +1770,7 @@ static int write_xml_presence_person(xmlTextWriterPtr writer, LinphonePresencePe err = xmlTextWriterWriteAttribute(writer, (const xmlChar *)"id", (const xmlChar *)person->id); } } - if ((err >= 0) && ((person->activities_notes != NULL) || (person_has_valid_activities(person) == TRUE))) { + if ((err >= 0) && ((person->activities_notes != NULL) || (person->activities != NULL))) { err = xmlTextWriterStartElementNS(writer, (const xmlChar *)"rpid", (const xmlChar *)"activities", NULL); if ((err >= 0) && (person->activities_notes != NULL)) { struct _presence_note_obj_st st; @@ -1814,7 +1808,7 @@ static int write_xml_presence_person(xmlTextWriterPtr writer, LinphonePresencePe } static void write_xml_presence_service_obj(LinphonePresenceService *service, struct _presence_service_obj_st *st) { - int err = write_xml_presence_service(st->writer, service, st->contact); + int err = write_xml_presence_service(st->writer, service, st->contact, st->online); if (err < 0) *st->err = err; } @@ -1823,6 +1817,14 @@ static void write_xml_presence_person_obj(LinphonePresencePerson *person, struct if (err < 0) *st->err = err; } +bool_t linphone_presence_model_is_online(const LinphonePresenceModel *model) { + if ((model->is_online == TRUE) + || ((linphone_presence_model_get_basic_status(model) == LinphonePresenceBasicStatusOpen) + && (linphone_presence_model_get_nb_activities(model) == 0))) + return TRUE; + return FALSE; +} + char *linphone_presence_model_to_xml(LinphonePresenceModel *model) { xmlBufferPtr buf = NULL; xmlTextWriterPtr writer = NULL; @@ -1855,22 +1857,27 @@ char *linphone_presence_model_to_xml(LinphonePresenceModel *model) { } if (err >= 0) { err = xmlTextWriterWriteAttributeNS(writer, (const xmlChar *)"xmlns", (const xmlChar *)"dm", - NULL, (const xmlChar *)"urn:ietf:params:xml:ns:pidf:data-model"); + NULL, (const xmlChar *)"urn:ietf:params:xml:ns:pidf:data-model"); } if (err >= 0) { err = xmlTextWriterWriteAttributeNS(writer, (const xmlChar *)"xmlns", (const xmlChar *)"rpid", - NULL, (const xmlChar *)"urn:ietf:params:xml:ns:pidf:rpid"); + NULL, (const xmlChar *)"urn:ietf:params:xml:ns:pidf:rpid"); + } + if ((err >= 0) && linphone_presence_model_is_online(model)) { + err = xmlTextWriterWriteAttributeNS(writer, (const xmlChar *)"xmlns", (const xmlChar *)"pidfonline", + NULL, (const xmlChar *)"http://www.linphone.org/xsds/pidfonline.xsd"); } if (err >= 0) { err = xmlTextWriterWriteAttribute(writer, (const xmlChar *)"entity", (const xmlChar *)contact); } if (err >= 0) { if ((model == NULL) || (model->services == NULL)) { - err = write_xml_presence_service(writer, NULL, contact); + err = write_xml_presence_service(writer, NULL, contact, FALSE); } else { struct _presence_service_obj_st st={0}; st.writer = writer; st.contact = contact; /*default value*/ + st.online = linphone_presence_model_is_online(model); st.err = &err; bctbx_list_for_each2(model->services, (MSIterate2Func)write_xml_presence_service_obj, &st); } @@ -1911,7 +1918,14 @@ void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, Sa char *tmp; LinphoneFriend *lf = NULL; const LinphoneAddress *friend=NULL; - LinphonePresenceModel *presence = model ? (LinphonePresenceModel *)model:linphone_presence_model_new_with_activity(LinphonePresenceActivityOffline, NULL); + LinphonePresenceModel *presence; + + if (model != NULL) { + presence = (LinphonePresenceModel *)model; + } else { + presence = linphone_presence_model_new(); + linphone_presence_model_set_basic_status(presence, LinphonePresenceBasicStatusClosed); + } if (linphone_core_get_default_friend_list(lc) != NULL) lf=linphone_core_find_friend_by_out_subscribe(lc, op); @@ -1926,7 +1940,11 @@ void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, Sa friend=linphone_friend_get_address(lf); if (friend != NULL) { tmp=linphone_address_as_string(friend); - activity_str = linphone_presence_activity_to_string(activity); + if (activity == NULL) { + activity_str = linphone_presence_basic_status_to_string(linphone_presence_model_get_basic_status(presence)); + } else { + 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); ms_free(tmp); diff --git a/coreapi/proxy.c b/coreapi/proxy.c index 618394395..a522b2101 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -853,7 +853,7 @@ int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy, LinphonePrese } if (!(presence_body = linphone_presence_model_to_xml(presence))) { - ms_error("Cannot publish presence model [%p] for proxy config [%p] because of xml serilization error",presence,proxy); + ms_error("Cannot publish presence model [%p] for proxy config [%p] because of xml serialization error",presence,proxy); return -1; } diff --git a/include/linphone/core.h b/include/linphone/core.h index 1edb31a72..568a17672 100644 --- a/include/linphone/core.h +++ b/include/linphone/core.h @@ -4813,6 +4813,20 @@ LINPHONE_PUBLIC LinphoneOnlineStatus linphone_core_get_presence_info(const Linph */ LINPHONE_PUBLIC LinphonePresenceModel * linphone_core_get_presence_model(const LinphoneCore *lc); +/** + * Get my consolidated presence + * @param[in] lc LinphoneCore object + * @return My consolidated presence + */ +LINPHONE_PUBLIC LinphoneConsolidatedPresence linphone_core_get_consolidated_presence(const LinphoneCore *lc); + +/** + * Set my consolidated presence + * @param[in] lc LinphoneCore object + * @param[in] presence LinphoneConsolidatedPresence value + */ +LINPHONE_PUBLIC void linphone_core_set_consolidated_presence(LinphoneCore *lc, LinphoneConsolidatedPresence presence); + /** * @deprecated Use linphone_core_interpret_url() instead */ diff --git a/include/linphone/friend.h b/include/linphone/friend.h index 22fcba75e..f3520f857 100644 --- a/include/linphone/friend.h +++ b/include/linphone/friend.h @@ -209,6 +209,13 @@ LINPHONE_PUBLIC LinphoneSubscriptionState linphone_friend_get_subscription_state */ LINPHONE_PUBLIC const LinphonePresenceModel * linphone_friend_get_presence_model(const LinphoneFriend *lf); +/** + * Get the consolidated presence of a friend. + * @param[in] lf LinphoneFriend object + * @return The consolidated presence of the friend + */ +LINPHONE_PUBLIC LinphoneConsolidatedPresence linphone_friend_get_consolidated_presence(const LinphoneFriend *lf); + /** * Get the presence model for a specific SIP URI or phone number of a friend * @param[in] lf A #LinphoneFriend object diff --git a/include/linphone/presence.h b/include/linphone/presence.h index a0340ecf4..10f532c55 100644 --- a/include/linphone/presence.h +++ b/include/linphone/presence.h @@ -195,6 +195,13 @@ LINPHONE_PUBLIC int linphone_presence_model_add_note(LinphonePresenceModel *mode */ LINPHONE_PUBLIC int linphone_presence_model_clear_notes(LinphonePresenceModel *model); +/** + * Get the consolidated presence from a presence model. + * @param[in] model LinphonePresenceModel object + * @return The LinphoneConsolidatedPresence corresponding to the presence model + */ +LINPHONE_PUBLIC LinphoneConsolidatedPresence linphone_presence_model_get_consolidated_presence(const LinphonePresenceModel *model); + /***************************************************************************** * PRESENCE MODEL FUNCTIONS TO GET ACCESS TO ALL FUNCTIONALITIES * @@ -270,11 +277,30 @@ LINPHONE_PUBLIC int linphone_presence_model_add_person(LinphonePresenceModel *mo */ LINPHONE_PUBLIC int linphone_presence_model_clear_persons(LinphonePresenceModel *model); +/** + * Tells whether a presence model is considered online. + * It is any of theses cases: + * - basic status is'open' and no activities + * - explicit 'online' tag in the status + * @param[in] model LinphonePresenceModel object + * @return A boolean value telling whether the presence model is considered online or not. + */ +LINPHONE_PUBLIC bool_t linphone_presence_model_is_online(const LinphonePresenceModel *model); + /***************************************************************************** * PRESENCE SERVICE FUNCTIONS TO GET ACCESS TO ALL FUNCTIONALITIES * ****************************************************************************/ +/** + * Gets the string representation of a presence basic status. + * @param[in] basic_status A LinphonePresenceBasicStatus for which to get a string representation. + * @return A pointer a dynamically allocated string representing the given basic status. + * + * The returned string is to be freed by calling ms_free(). + */ +char * linphone_presence_basic_status_to_string(LinphonePresenceBasicStatus basic_status); + /** * Creates a presence service. * @param[in] id The id of the presence service to be created. Can be NULL to generate it automatically. diff --git a/include/linphone/types.h b/include/linphone/types.h index 81194c9da..1b6f2f6ad 100644 --- a/include/linphone/types.h +++ b/include/linphone/types.h @@ -339,6 +339,20 @@ typedef enum _LinphoneConfiguringState { LinphoneConfiguringSkipped } LinphoneConfiguringState; +/** + * Consolidated presence information: 'online' means the user is open for communication, + * 'busy' means the user is open for communication but involved in an other activity, + * 'do not disturb' means the user is not open for communication, and 'offline' means + * that no presence information is available. + * @ingroup buddy_list + */ +typedef enum _LinphoneConsolidatedPresence { + LinphoneConsolidatedPresenceOnline, + LinphoneConsolidatedPresenceBusy, + LinphoneConsolidatedPresenceDoNotDisturb, + LinphoneConsolidatedPresenceOffline +} LinphoneConsolidatedPresence; + typedef struct _LinphoneContactProvider LinphoneContactProvider; typedef struct _LinphoneContactSearch LinphoneContactSearch; @@ -617,12 +631,6 @@ typedef struct _LinphonePresenceActivity LinphonePresenceActivity; * @ingroup buddy_list */ typedef enum LinphonePresenceActivityType { - /** This value is not defined in the RFC, it corresponds to no activity with a basic status of "closed". */ - LinphonePresenceActivityOffline, - - /** This value is not defined in the RFC, it corresponds to no activity with a basic status of "open". */ - LinphonePresenceActivityOnline, - /** The person has a calendar appointment, without specifying exactly of what type. This activity is * indicated if more detailed information is not available or the person chooses not to reveal more * information. */ diff --git a/share/xml/pidfonline.xsd b/share/xml/pidfonline.xsd new file mode 100644 index 000000000..c0465d1dc --- /dev/null +++ b/share/xml/pidfonline.xsd @@ -0,0 +1,9 @@ + + + + + + diff --git a/tester/presence_server_tester.c b/tester/presence_server_tester.c index 3dc955e25..ce55d2e40 100644 --- a/tester/presence_server_tester.c +++ b/tester/presence_server_tester.c @@ -65,6 +65,7 @@ static void simple(void) { linphone_core_add_friend(marie->lc, f); linphone_core_set_presence_model(pauline->lc, pauline_presence); + linphone_presence_model_unref(pauline_presence); BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePresenceActivityDinner,1)); activity = linphone_presence_model_get_activity(linphone_friend_get_presence_model(f)); @@ -103,10 +104,13 @@ static void fast_activity_change(void) { /* pauline_Presence activity without description. */ pauline_presence = linphone_presence_model_new_with_activity(LinphonePresenceActivityDinner, NULL); linphone_core_set_presence_model(pauline->lc, pauline_presence); + linphone_presence_model_unref(pauline_presence); pauline_presence = linphone_presence_model_new_with_activity(LinphonePresenceActivityTV, NULL); linphone_core_set_presence_model(pauline->lc, pauline_presence); + linphone_presence_unref(pauline_presence); pauline_presence = linphone_presence_model_new_with_activity(LinphonePresenceActivityAway, NULL); linphone_core_set_presence_model(pauline->lc, pauline_presence); + linphone_presence_unref(pauline_presence); BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePresenceActivityDinner,1)); activity = linphone_presence_model_get_activity(linphone_friend_get_presence_model(f)); @@ -166,6 +170,7 @@ static void subscriber_no_longer_reachable(void){ presence =linphone_presence_model_new_with_activity(LinphonePresenceActivityBusy,NULL); linphone_core_set_presence_model(pauline1->lc,presence); + linphone_presence_model_unref(presence); previous_number_of_LinphonePresenceActivityOnline=marie->stat.number_of_LinphonePresenceActivityOnline; @@ -185,8 +190,10 @@ static void subscriber_no_longer_reachable(void){ * The client handles this subscription terminated event. * It will not resubmit a new SUBSCRIBE until expiration of the current one. */ - presence =linphone_presence_model_new_with_activity(LinphonePresenceActivityOnline,NULL); + presence =linphone_presence_model_new(); + linphone_presence_model_set_basic_status(presence, LinphonePresenceBasicStatusOpen); linphone_core_set_presence_model(pauline1->lc,presence); + linphone_presence_model_unref(presence); /*because subscription is not restarted, the online status shall not be notified again.*/ BC_ASSERT_FALSE(wait_for_list(lcs,&marie->stat.number_of_LinphonePresenceActivityOnline,previous_number_of_LinphonePresenceActivityOnline+1, 8000)); @@ -225,6 +232,7 @@ static void subscribe_with_late_publish(void) { /*enable publish*/ presence =linphone_presence_model_new_with_activity(LinphonePresenceActivityPresentation,NULL); linphone_core_set_presence_model(marie->lc,presence); + linphone_presence_model_unref(presence); proxy = linphone_core_get_default_proxy_config(marie->lc); linphone_proxy_config_edit(proxy); @@ -237,6 +245,7 @@ static void subscribe_with_late_publish(void) { presence =linphone_presence_model_new_with_activity(LinphonePresenceActivityBusy,NULL); linphone_core_set_presence_model(marie->lc,presence); + linphone_presence_model_unref(presence); /*wait for new status*/ BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphonePresenceActivityBusy,1,2000)); @@ -258,9 +267,15 @@ static void subscribe_with_late_publish(void) { BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphonePresenceActivityBusy,3,5000));/*re- schedule marie to clean up things*/ /*simulate a rapid presence change to make sure only first and last are transmited*/ - linphone_core_set_presence_model(marie->lc,linphone_presence_model_new_with_activity(LinphonePresenceActivityAway,NULL)); - linphone_core_set_presence_model(marie->lc,linphone_presence_model_new_with_activity(LinphonePresenceActivityBreakfast,NULL)); - linphone_core_set_presence_model(marie->lc,linphone_presence_model_new_with_activity(LinphonePresenceActivityAppointment,NULL)); + presence = linphone_presence_model_new_with_activity(LinphonePresenceActivityAway,NULL); + linphone_core_set_presence_model(marie->lc, presence); + linphone_presence_model_unref(presence); + presence = linphone_presence_model_new_with_activity(LinphonePresenceActivityBreakfast,NULL); + linphone_core_set_presence_model(marie->lc, presence); + linphone_presence_model_unref(presence); + presence = linphone_presence_model_new_with_activity(LinphonePresenceActivityAppointment,NULL); + linphone_core_set_presence_model(marie->lc, presence); + linphone_presence_model_unref(presence); BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphonePresenceActivityAppointment,1,5000)); @@ -324,6 +339,7 @@ static void test_forked_subscribe_notify_publish(void) { presence =linphone_presence_model_new_with_activity(LinphonePresenceActivityBusy,NULL); linphone_core_set_presence_model(marie->lc,presence); + linphone_presence_model_unref(presence); /*wait for new status*/ wait_for_list(lcs,&pauline->stat.number_of_LinphonePresenceActivityBusy,1,3000); @@ -332,6 +348,7 @@ static void test_forked_subscribe_notify_publish(void) { presence =linphone_presence_model_new_with_activity( LinphonePresenceActivityMeeting,NULL); linphone_core_set_presence_model(marie2->lc,presence); + linphone_presence_model_unref(presence); /*wait for new status*/ BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphonePresenceActivityMeeting,1,3000)); @@ -353,6 +370,7 @@ static void test_presence_list_base(bool_t enable_compression) { const char *marie_identity; const char *pauline_identity; bctbx_list_t* lcs = NULL; + LinphonePresenceModel *presence; laure_identity = get_identity(laure); marie_identity = get_identity(marie); @@ -364,8 +382,12 @@ static void test_presence_list_base(bool_t enable_compression) { enable_deflate_content_encoding(pauline, enable_compression); enable_deflate_content_encoding(laure, enable_compression); - 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)); + presence = linphone_core_create_presence_model_with_activity(marie->lc, LinphonePresenceActivityBusy, NULL); + linphone_core_set_presence_model(marie->lc, presence); + linphone_presence_model_unref(presence); + presence = linphone_core_create_presence_model_with_activity(pauline->lc, LinphonePresenceActivityVacation, NULL); + linphone_core_set_presence_model(pauline->lc, presence); + linphone_presence_model_unref(presence); lfl = linphone_core_create_friend_list(laure->lc); linphone_friend_list_set_rls_uri(lfl, rls_uri); @@ -381,7 +403,10 @@ static void test_presence_list_base(bool_t enable_compression) { linphone_core_remove_friend_list(laure->lc, linphone_core_get_default_friend_list(laure->lc)); linphone_core_add_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)); + presence = linphone_presence_model_new(); + linphone_presence_model_set_basic_status(presence, LinphonePresenceBasicStatusOpen); + linphone_core_set_presence_model(laure->lc, presence); + linphone_presence_model_unref(presence); lcs = bctbx_list_append(lcs, laure->lc); lcs = bctbx_list_append(lcs, marie->lc); @@ -434,7 +459,9 @@ static void test_presence_list_base(bool_t enable_compression) { BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusBusy, int, "%d"); if (!BC_ASSERT_TRUE(lf->presence_received)) goto end; - linphone_core_set_presence_model(marie->lc, linphone_core_create_presence_model_with_activity(marie->lc, LinphonePresenceActivityOnThePhone, NULL)); + presence = linphone_core_create_presence_model_with_activity(marie->lc, LinphonePresenceActivityOnThePhone, NULL); + linphone_core_set_presence_model(marie->lc, presence); + linphone_presence_model_unref(presence); wait_for_list(lcs, &laure->stat.number_of_NotifyPresenceReceived, 4, 4000); /* The number of PresenceReceived events can be 3 or 4 here. TODO: ideally it should always be 3. */ @@ -513,10 +540,13 @@ static void test_presence_list_subscribe_before_publish(void) { const char *pauline_identity; bctbx_list_t* lcs = NULL; int dummy = 0; + LinphonePresenceModel *presence; pauline_identity = get_identity(pauline); - linphone_core_set_presence_model(pauline->lc, linphone_core_create_presence_model_with_activity(pauline->lc, LinphonePresenceActivityVacation, NULL)); + presence = linphone_core_create_presence_model_with_activity(pauline->lc, LinphonePresenceActivityVacation, NULL); + linphone_core_set_presence_model(pauline->lc, presence); + linphone_presence_unref(presence); lfl = linphone_core_create_friend_list(laure->lc); linphone_friend_list_set_rls_uri(lfl, rls_uri); @@ -527,7 +557,10 @@ static void test_presence_list_subscribe_before_publish(void) { linphone_core_remove_friend_list(laure->lc, linphone_core_get_default_friend_list(laure->lc)); linphone_core_add_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)); + presence = linphone_presence_model_new(); + linphone_presence_model_set_basic_status(presence, LinphonePresenceBasicStatusOpen); + linphone_core_set_presence_model(laure->lc, presence); + linphone_presence_model_unref(presence); linphone_friend_list_update_subscriptions(linphone_core_get_default_friend_list(laure->lc), NULL, FALSE); lcs = bctbx_list_append(lcs, laure->lc); @@ -586,12 +619,14 @@ static void test_presence_list_subscribe_with_error(bool_t io_error) { const char *pauline_identity; bctbx_list_t* lcs = NULL; int dummy = 0; + LinphonePresenceModel *presence; + lp_config_set_int(laure->lc->config, "sip", "rls_presence_expires", 5); - - pauline_identity = get_identity(pauline); - linphone_core_set_presence_model(pauline->lc, linphone_core_create_presence_model_with_activity(pauline->lc, LinphonePresenceActivityVacation, NULL)); + presence = linphone_core_create_presence_model_with_activity(pauline->lc, LinphonePresenceActivityVacation, NULL); + linphone_core_set_presence_model(pauline->lc, presence); + linphone_presence_model_unref(presence); lfl = linphone_core_create_friend_list(laure->lc); linphone_friend_list_set_rls_uri(lfl, rls_uri); @@ -604,7 +639,10 @@ static void test_presence_list_subscribe_with_error(bool_t io_error) { linphone_core_remove_friend_list(laure->lc, linphone_core_get_default_friend_list(laure->lc)); linphone_core_add_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)); + presence = linphone_presence_model_new(); + linphone_presence_model_set_basic_status(presence, LinphonePresenceBasicStatusOpen); + linphone_core_set_presence_model(laure->lc, presence); + linphone_presence_model_unref(presence); linphone_friend_list_update_subscriptions(linphone_core_get_default_friend_list(laure->lc)); lcs = bctbx_list_append(lcs, laure->lc); lcs = bctbx_list_append(lcs, pauline->lc); @@ -640,7 +678,9 @@ static void test_presence_list_subscribe_with_error(bool_t io_error) { BC_ASSERT_TRUE(wait_for_until(laure->lc, pauline->lc, &laure->stat.number_of_LinphonePresenceActivityVacation, 3, 9000)); /* give time for subscription to recover to avoid to receive 491 Request pending*/ - linphone_core_set_presence_model(pauline->lc, linphone_core_create_presence_model_with_activity(pauline->lc, LinphonePresenceActivityAway, NULL)); + presence = linphone_core_create_presence_model_with_activity(pauline->lc, LinphonePresenceActivityAway, NULL); + linphone_core_set_presence_model(pauline->lc, presence); + linphone_presence_model_unref(presence); BC_ASSERT_TRUE(wait_for_until(laure->lc, pauline->lc, &laure->stat.number_of_LinphonePresenceActivityAway, 1, 6000)); lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(laure->lc), pauline_identity); @@ -667,12 +707,14 @@ static void presence_list_subscribe_network_changes(void) { const char *pauline_identity; bctbx_list_t* lcs = NULL; int dummy = 0; + LinphonePresenceModel *presence; + lp_config_set_int(laure->lc->config, "sip", "rls_presence_expires", 5); - - pauline_identity = get_identity(pauline); - linphone_core_set_presence_model(pauline->lc, linphone_core_create_presence_model_with_activity(pauline->lc, LinphonePresenceActivityVacation, NULL)); + presence = linphone_core_create_presence_model_with_activity(pauline->lc, LinphonePresenceActivityVacation, NULL); + linphone_core_set_presence_model(pauline->lc, presence); + linphone_presence_model_unref(presence); lfl = linphone_core_create_friend_list(laure->lc); linphone_friend_list_set_rls_uri(lfl, rls_uri); @@ -685,7 +727,10 @@ static void presence_list_subscribe_network_changes(void) { linphone_core_remove_friend_list(laure->lc, linphone_core_get_default_friend_list(laure->lc)); linphone_core_add_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)); + presence = linphone_presence_model_new(); + linphone_presence_model_set_basic_status(presence, LinphonePresenceBasicStatusOpen); + linphone_core_set_presence_model(laure->lc, presence); + linphone_presence_model_unref(presence); linphone_friend_list_update_subscriptions(linphone_core_get_default_friend_list(laure->lc)); lcs = bctbx_list_append(lcs, laure->lc); lcs = bctbx_list_append(lcs, pauline->lc); @@ -715,7 +760,9 @@ static void presence_list_subscribe_network_changes(void) { /*a new subscribe should be sent */ BC_ASSERT_TRUE(wait_for_until(laure->lc, pauline->lc, &laure->stat.number_of_LinphonePresenceActivityVacation, 3, 9000)); /* give time for subscription to recover to avoid to receive 491 Request pending*/ - linphone_core_set_presence_model(pauline->lc, linphone_core_create_presence_model_with_activity(pauline->lc, LinphonePresenceActivityAway, NULL)); + presence = linphone_core_create_presence_model_with_activity(pauline->lc, LinphonePresenceActivityAway, NULL); + linphone_core_set_presence_model(pauline->lc, presence); + linphone_presence_model_unref(presence); BC_ASSERT_TRUE(wait_for_until(laure->lc, pauline->lc, &laure->stat.number_of_LinphonePresenceActivityAway, 1, 6000)); lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(laure->lc), pauline_identity); diff --git a/tester/presence_tester.c b/tester/presence_tester.c index 4d853bf9e..2d5ee2a28 100644 --- a/tester/presence_tester.c +++ b/tester/presence_tester.c @@ -72,10 +72,6 @@ void notify_presence_received(LinphoneCore *lc, LinphoneFriend * lf) { for (i=0;counters->last_received_presence&&ilast_received_presence); i++) { LinphonePresenceActivity *activity = linphone_presence_model_get_nth_activity(counters->last_received_presence, i); switch (linphone_presence_activity_get_type(activity)) { - case LinphonePresenceActivityOffline: - counters->number_of_LinphonePresenceActivityOffline++; break; - case LinphonePresenceActivityOnline: - counters->number_of_LinphonePresenceActivityOnline++; break; case LinphonePresenceActivityAppointment: counters->number_of_LinphonePresenceActivityAppointment++; break; case LinphonePresenceActivityAway: @@ -167,8 +163,10 @@ static void simple_publish_with_expire(int expires) { BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,1)); BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishOk,1)); - presence =linphone_presence_model_new_with_activity(LinphonePresenceActivityOffline,NULL); + presence = linphone_presence_model_new(); + linphone_presence_model_set_basic_status(presence, LinphonePresenceBasicStatusClosed); linphone_core_set_presence_model(marie->lc,presence); + linphone_presence_model_unref(presence); BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,2)); BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishOk,2)); @@ -401,6 +399,7 @@ static void presence_information(void) { /* Presence activity without description. */ presence = linphone_presence_model_new_with_activity(LinphonePresenceActivityDinner, NULL); linphone_core_set_presence_model(pauline->lc, presence); + linphone_presence_model_unref(presence); wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePresenceActivityDinner,1); BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePresenceActivityDinner, 1, int, "%d"); activity = linphone_presence_model_get_activity(marie->stat.last_received_presence); @@ -412,6 +411,7 @@ static void presence_information(void) { /* Presence activity with description. */ presence = linphone_presence_model_new_with_activity(LinphonePresenceActivitySteering, bike_description); linphone_core_set_presence_model(pauline->lc, presence); + linphone_presence_model_unref(presence); wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePresenceActivitySteering,1); BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePresenceActivitySteering, 1, int, "%d"); activity = linphone_presence_model_get_activity(marie->stat.last_received_presence); @@ -424,6 +424,7 @@ static void presence_information(void) { /* Presence activity with description and note. */ presence = linphone_presence_model_new_with_activity_and_note(LinphonePresenceActivityVacation, NULL, vacation_note, vacation_lang); linphone_core_set_presence_model(pauline->lc, presence); + linphone_presence_model_unref(presence); wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePresenceActivityVacation,1); BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePresenceActivityVacation, 1, int, "%d"); activity = linphone_presence_model_get_activity(marie->stat.last_received_presence); @@ -445,6 +446,7 @@ static void presence_information(void) { presence = linphone_presence_model_new_with_activity(LinphonePresenceActivityOnThePhone, NULL); linphone_presence_model_set_contact(presence, contact); linphone_core_set_presence_model(pauline->lc, presence); + linphone_presence_model_unref(presence); wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePresenceActivityOnThePhone,1); BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePresenceActivityOnThePhone, 1, int, "%d"); contact2 = linphone_presence_model_get_contact(presence); @@ -462,6 +464,7 @@ static void presence_information(void) { BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePresenceActivityShopping, 1, int, "%d"); presence_timestamp = linphone_presence_model_get_timestamp(presence); BC_ASSERT_GREATER((unsigned)presence_timestamp , (unsigned)current_timestamp, unsigned, "%u"); + linphone_presence_model_unref(presence); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline);