Commit 0a0867e4 authored by Benjamin REIS's avatar Benjamin REIS
Browse files

Merge branch 'feature/bodyless_presence_subscription'

parents 0a8c7836 4e318499
Pipeline #218 failed with stage
in 0 seconds
......@@ -206,7 +206,7 @@ static void linphone_friend_list_parse_multipart_related_body(LinphoneFriendList
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) {
if (xml_ctx->doc) {
LinphoneFriend *lf;
LinphoneContent *presence_part;
xmlXPathObjectPtr resource_object;
......@@ -221,7 +221,7 @@ static void linphone_friend_list_parse_multipart_related_body(LinphoneFriendList
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) {
if (!version_str) {
ms_warning("rlmi+xml: No version attribute in list");
goto end;
}
......@@ -232,7 +232,7 @@ static void linphone_friend_list_parse_multipart_related_body(LinphoneFriendList
}
full_state_str = linphone_get_xml_attribute_text_content(xml_ctx, "/rlmi:list", "fullState");
if (full_state_str == NULL) {
if (!full_state_str) {
ms_warning("rlmi+xml: No fullState attribute in list");
goto end;
}
......@@ -245,34 +245,42 @@ static void linphone_friend_list_parse_multipart_related_body(LinphoneFriendList
full_state = TRUE;
}
linphone_free_xml_text_content(full_state_str);
if ((list->expected_notification_version == 0) && (full_state == FALSE)) {
if ((list->expected_notification_version == 0) && !full_state) {
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/rlmi:instance[@state=\"active\"]/..");
if ((resource_object != NULL) && (resource_object->nodesetval != NULL)) {
if (resource_object && resource_object->nodesetval) {
for (i = 1; i <= resource_object->nodesetval->nodeNr; i++) {
char *cid = NULL;
linphone_xml_xpath_context_set_node(xml_ctx, xmlXPathNodeSetItem(resource_object->nodesetval, i-1));
cid = linphone_get_xml_text_content(xml_ctx, "./rlmi:instance/@cid");
if (cid != NULL) {
if (cid) {
presence_part = linphone_content_find_part_by_header(body, "Content-Id", cid);
if (presence_part == NULL) {
if (!presence_part) {
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) {
if (presence) {
// Try to reduce CPU cost of linphone_address_new and find_friend_by_address by only doing it when we know for sure we have a presence to notify
LinphoneAddress* addr;
uri = linphone_get_xml_text_content(xml_ctx, "./@uri");
if (uri == NULL) continue;
if (!uri)
continue;
addr = linphone_address_new(uri);
if (!addr) continue;
if (!addr)
continue;
lf = linphone_friend_list_find_friend_by_address(list, addr);
linphone_address_unref(addr);
if (!lf && list->bodyless_subscription) {
lf = linphone_core_create_friend_with_address(list->lc, uri);
linphone_friend_list_add_friend(list, lf);
linphone_friend_unref(lf);
}
if (lf) {
const char *phone_number = linphone_friend_sip_uri_to_phone_number(lf, uri);
lf->presence_received = TRUE;
......@@ -289,7 +297,7 @@ static void linphone_friend_list_parse_multipart_related_body(LinphoneFriendList
} else {
linphone_friend_set_presence_model_for_uri_or_tel(lf, uri, (LinphonePresenceModel *)presence);
}
if (full_state == FALSE) {
if (!full_state) {
if (phone_number)
linphone_core_notify_notify_presence_received_for_uri_or_tel(list->lc, lf, phone_number, (LinphonePresenceModel *)presence);
else
......@@ -305,9 +313,10 @@ static void linphone_friend_list_parse_multipart_related_body(LinphoneFriendList
}
}
}
if (resource_object != NULL) xmlXPathFreeObject(resource_object);
if (resource_object)
xmlXPathFreeObject(resource_object);
if (full_state == TRUE) {
if (full_state) {
const bctbx_list_t *addresses;
bctbx_list_t *numbers;
bctbx_list_t *iterator;
......@@ -335,7 +344,7 @@ static void linphone_friend_list_parse_multipart_related_body(LinphoneFriendList
iterator = bctbx_list_next(iterator);
}
if (numbers) bctbx_list_free(numbers);
if (linphone_friend_is_presence_received(lf) == TRUE) {
if (linphone_friend_is_presence_received(lf)) {
linphone_core_notify_notify_presence_received(list->lc, lf);
}
}
......@@ -349,6 +358,9 @@ end:
}
static bool_t linphone_friend_list_has_subscribe_inactive(const LinphoneFriendList *list) {
if (list->bodyless_subscription)
return TRUE;
bctbx_list_t *l = list->friends;
bool_t has_subscribe_inactive = FALSE;
for (; l != NULL; l = bctbx_list_next(l)) {
......@@ -367,6 +379,7 @@ static LinphoneFriendList * linphone_friend_list_new(void) {
list->enable_subscriptions = TRUE;
list->friends_map = bctbx_mmap_cchar_new();
list->friends_map_uri = bctbx_mmap_cchar_new();
list->bodyless_subscription = FALSE;
return list;
}
......@@ -534,10 +547,9 @@ static LinphoneFriendListStatus _linphone_friend_list_add_friend(LinphoneFriendL
linphone_friend_save(lf, lf->lc);
}
if (list->rls_uri == NULL) {
/* Mimic the behaviour of linphone_core_add_friend() when a resource list server is not in use */
if (!list->rls_uri) // Mimic the behaviour of linphone_core_add_friend() when a resource list server is not in use
linphone_friend_apply(lf, lf->lc);
}
return status;
}
......@@ -849,55 +861,98 @@ static void linphone_friend_list_close_subscriptions(LinphoneFriendList *list) {
bctbx_list_for_each(list->friends, (void (*)(void *))linphone_friend_close_subscriptions);
}
static void linphone_friend_list_send_list_subscription(LinphoneFriendList *list){
const LinphoneAddress *address = _linphone_friend_list_get_rls_address(list);
static void _linphone_friend_list_send_list_subscription_with_body(LinphoneFriendList *list, const LinphoneAddress *address) {
char *xml_content = create_resource_list_xml(list);
if ((address != NULL) && (xml_content != NULL) && (linphone_friend_list_has_subscribe_inactive(list) == TRUE)) {
unsigned char digest[16];
bctbx_md5((unsigned char *)xml_content, strlen(xml_content), digest);
if ((list->event != NULL) && (list->content_digest != NULL) && (memcmp(list->content_digest, digest, sizeof(digest)) == 0)) {
/* The content has not changed, only refresh the event. */
linphone_event_refresh_subscribe(list->event);
} else {
LinphoneContent *content;
bctbx_list_t * elem = NULL;
int expires = lp_config_get_int(list->lc->config, "sip", "rls_presence_expires", 3600);
list->expected_notification_version = 0;
if (list->content_digest != NULL) ms_free(list->content_digest);
list->content_digest = reinterpret_cast<unsigned char *>(ms_malloc(sizeof(digest)));
memcpy(list->content_digest, digest, sizeof(digest));
if (list->event != NULL) {
linphone_event_terminate(list->event);
linphone_event_unref(list->event);
}
list->event = linphone_core_create_subscribe(list->lc, address, "presence", expires);
linphone_event_ref(list->event);
linphone_event_set_internal(list->event, TRUE);
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);
if (linphone_core_content_encoding_supported(list->lc, "deflate")) {
linphone_content_set_encoding(content, "deflate");
linphone_event_add_custom_header(list->event, "Accept-Encoding", "deflate");
}
for (elem = list->friends; elem != NULL; elem = bctbx_list_next(elem)) {
LinphoneFriend *lf = (LinphoneFriend *)elem->data;
lf->subscribe_active = TRUE;
}
linphone_event_send_subscribe(list->event, content);
linphone_content_unref(content);
linphone_event_set_user_data(list->event, list);
if (!xml_content)
return;
unsigned char digest[16];
bctbx_md5((unsigned char *)xml_content, strlen(xml_content), digest);
if (list->event && list->content_digest && (memcmp(list->content_digest, digest, sizeof(digest)) == 0)) {
/* The content has not changed, only refresh the event. */
linphone_event_refresh_subscribe(list->event);
} else {
LinphoneContent *content;
bctbx_list_t * elem = NULL;
int expires = lp_config_get_int(list->lc->config, "sip", "rls_presence_expires", 3600);
list->expected_notification_version = 0;
if (list->content_digest)
ms_free(list->content_digest);
list->content_digest = reinterpret_cast<unsigned char *>(ms_malloc(sizeof(digest)));
memcpy(list->content_digest, digest, sizeof(digest));
if (list->event) {
linphone_event_terminate(list->event);
linphone_event_unref(list->event);
}
list->event = linphone_core_create_subscribe(list->lc, address, "presence", expires);
linphone_event_ref(list->event);
linphone_event_set_internal(list->event, TRUE);
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);
if (linphone_core_content_encoding_supported(list->lc, "deflate")) {
linphone_content_set_encoding(content, "deflate");
linphone_event_add_custom_header(list->event, "Accept-Encoding", "deflate");
}
for (elem = list->friends; elem != NULL; elem = bctbx_list_next(elem)) {
LinphoneFriend *lf = (LinphoneFriend *)elem->data;
lf->subscribe_active = TRUE;
}
linphone_event_send_subscribe(list->event, content);
linphone_content_unref(content);
linphone_event_set_user_data(list->event, list);
}
ms_free(xml_content);
}
static void _linphone_friend_list_send_list_subscription_without_body(LinphoneFriendList *list, const LinphoneAddress *address) {
bctbx_list_t *elem = NULL;
int expires = lp_config_get_int(list->lc->config, "sip", "rls_presence_expires", 3600);
list->expected_notification_version = 0;
if (list->content_digest)
ms_free(list->content_digest);
if (list->event) {
linphone_event_terminate(list->event);
linphone_event_unref(list->event);
}
list->event = linphone_core_create_subscribe(list->lc, address, "presence", expires);
linphone_event_ref(list->event);
linphone_event_set_internal(list->event, TRUE);
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");
if (linphone_core_content_encoding_supported(list->lc, "deflate"))
linphone_event_add_custom_header(list->event, "Accept-Encoding", "deflate");
for (elem = list->friends; elem != NULL; elem = bctbx_list_next(elem)) {
LinphoneFriend *lf = (LinphoneFriend *)elem->data;
lf->subscribe_active = TRUE;
}
if (xml_content != NULL) ms_free(xml_content);
linphone_event_send_subscribe(list->event, NULL);
linphone_event_set_user_data(list->event, list);
}
void linphone_friend_list_update_subscriptions(LinphoneFriendList *list){
static void linphone_friend_list_send_list_subscription(LinphoneFriendList *list) {
const LinphoneAddress *address = _linphone_friend_list_get_rls_address(list);
if (!address)
return;
if (!linphone_friend_list_has_subscribe_inactive(list))
return;
if (list->bodyless_subscription)
_linphone_friend_list_send_list_subscription_without_body(list, address);
else
_linphone_friend_list_send_list_subscription_with_body(list, address);
}
void linphone_friend_list_update_subscriptions(LinphoneFriendList *list) {
LinphoneProxyConfig *cfg = NULL;
const LinphoneAddress *address = _linphone_friend_list_get_rls_address(list);
bool_t only_when_registered = FALSE;
......@@ -961,33 +1016,34 @@ void linphone_friend_list_notify_presence(LinphoneFriendList *list, LinphonePres
}
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', instead is '%s/%s'", type, subtype);
return;
}
if (!linphone_content_is_multipart(body))
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;
}
LinphoneContent *first_part;
const char *type = linphone_content_get_type(body);
const char *subtype = linphone_content_get_subtype(body);
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'");
linphone_content_unref(first_part);
return;
}
if ((strcmp(type, "multipart") != 0) || (strcmp(subtype, "related") != 0)) {
ms_warning("multipart presence notified but it is not 'multipart/related', instead is '%s/%s'", type, subtype);
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;
}
linphone_friend_list_parse_multipart_related_body(list, body, linphone_content_get_string_buffer(first_part));
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'");
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);
}
const char * linphone_friend_list_get_uri(const LinphoneFriendList *list) {
......@@ -1005,6 +1061,14 @@ void linphone_friend_list_set_uri(LinphoneFriendList *list, const char *uri) {
}
}
bool_t linphone_friend_list_is_subscription_bodyless(LinphoneFriendList *list) {
return list->bodyless_subscription;
}
void linphone_friend_list_set_subscription_bodyless(LinphoneFriendList *list, bool_t bodyless) {
list->bodyless_subscription = bodyless;
}
void linphone_friend_list_update_revision(LinphoneFriendList *list, int rev) {
list->revision = rev;
linphone_core_store_friends_list_in_db(list->lc, list);
......
......@@ -2173,7 +2173,8 @@ static void linphone_core_internal_notify_received(LinphoneCore *lc, LinphoneEve
for (const bctbx_list_t *it = linphone_core_get_friends_lists(lc); it; it = bctbx_list_next(it)) {
LinphoneFriendList *list = reinterpret_cast<LinphoneFriendList *>(bctbx_list_get_data(it));
ms_message("Notify presence for list %p", list);
linphone_friend_list_notify_presence_received(list, lev, body);
if (list->event == lev)
linphone_friend_list_notify_presence_received(list, lev, body);
}
} else if (strcmp(notified_event, "conference") == 0) {
const LinphoneAddress *resource = linphone_event_get_resource(lev);
......
......@@ -124,7 +124,7 @@ struct _LinphoneProxyConfig
/*use to check if server config has changed between edit() and done()*/
LinphoneAddress *saved_proxy;
LinphoneAddress *saved_identity;
/*---*/
LinphoneAddress *pending_contact; /*use to store previous contact in case of network failure*/
LinphoneEvent *presence_publish_event;
......@@ -221,6 +221,7 @@ struct _LinphoneFriendList {
int revision;
LinphoneFriendListCbs *cbs;
bool_t enable_subscriptions;
bool_t bodyless_subscription;
};
BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneFriendList);
......
......@@ -187,6 +187,20 @@ LINPHONE_PUBLIC const char * linphone_friend_list_get_uri(const LinphoneFriendLi
**/
LINPHONE_PUBLIC void linphone_friend_list_set_uri(LinphoneFriendList *list, const char *uri);
/**
* Get wheter the subscription of the friend list is bodyless or not.
* @param[in] list #LinphoneFriendList object.
* @return Wheter the subscription of the friend list is bodyless or not.
**/
LINPHONE_PUBLIC bool_t linphone_friend_list_is_subscription_bodyless(LinphoneFriendList *list);
/**
* Set wheter the subscription of the friend list is bodyless or not.
* @param[in] list #LinphoneFriendList object.
* @param[in] a boolean telling if the subscription of the friend list is bodyless or not.
**/
LINPHONE_PUBLIC void linphone_friend_list_set_subscription_bodyless(LinphoneFriendList *list, bool_t bodyless);
/**
* Sets the revision from the last synchronization.
* @param[in] list #LinphoneFriendList object.
......
......@@ -16,7 +16,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "linphone/core.h"
#include "liblinphone_tester.h"
#include "tester_utils.h"
......@@ -482,7 +481,7 @@ static void test_presence_list_base(bool_t enable_compression) {
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);
int previous_laure_number_of_NotifyPresenceReceived = laure->stat.number_of_NotifyPresenceReceived ;
wait_for_list(lcs, &laure->stat.number_of_NotifyPresenceReceived, previous_laure_number_of_NotifyPresenceReceived + 1, 4000);
BC_ASSERT_EQUAL(laure->stat.number_of_NotifyPresenceReceived, previous_laure_number_of_NotifyPresenceReceived + 1, int, "%d");
......@@ -846,11 +845,11 @@ static void long_term_presence_large_number_of_subs(void) {
}
linphone_core_add_friend_list(pauline->lc, friends);
linphone_friend_list_unref(friends);
BC_ASSERT_TRUE(wait_for(pauline->lc,NULL,&pauline->stat.number_of_NotifyPresenceReceived,i));
linphone_core_manager_destroy(pauline);
#endif
}
......@@ -994,7 +993,7 @@ static void long_term_presence_with_phone_without_sip(void) {
if (linphone_core_vcard_supported()){
const LinphoneDialPlan *dialPlan;
const LinphoneDialPlan *genericDialPlan = linphone_dial_plan_by_ccc(NULL);
char phone[20];
char* e164;
size_t i;
......@@ -1055,7 +1054,7 @@ static void long_term_presence_with_phone_without_sip(void) {
ms_free(presence_contact);
}
}
linphone_friend_unref(friend2);
belle_sip_object_remove_from_leak_detector((void*)dialPlan); //because mostCommon dial plan is a static object freed at the end of the process. This f is only to avoid wrong leak detection.
belle_sip_object_remove_from_leak_detector((void*)genericDialPlan);
......@@ -1608,11 +1607,11 @@ static void simple_publish_with_expire(int expires) {
LinphoneProxyConfig* proxy;
LinphonePresenceModel* presence;
LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get());
linphone_core_cbs_set_publish_state_changed(cbs, linphone_publish_state_changed);
_linphone_core_add_callbacks(marie->lc, cbs, TRUE);
linphone_core_cbs_unref(cbs);
proxy = linphone_core_get_default_proxy_config(marie->lc);
linphone_proxy_config_edit(proxy);
if (expires > 0) {
......@@ -1620,45 +1619,45 @@ static void simple_publish_with_expire(int expires) {
}
linphone_proxy_config_enable_publish(proxy,TRUE);
linphone_proxy_config_done(proxy);
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();
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));
linphone_proxy_config_edit(proxy);
linphone_proxy_config_done(proxy);
/*make sure no publish is sent*/
BC_ASSERT_FALSE(wait_for_until(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,3,2000));
linphone_proxy_config_edit(proxy);
linphone_proxy_config_enable_publish(proxy,FALSE);
linphone_proxy_config_done(proxy);
/*fixme PUBLISH state machine is too simple, clear state should only be propagated at API level when 200ok is received*/
/*BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,3));*/
wait_for_until(marie->lc,marie->lc,NULL,0,2000);
BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishCleared,1));
linphone_proxy_config_edit(proxy);
linphone_proxy_config_enable_publish(proxy,TRUE);
linphone_proxy_config_done(proxy);
BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,3));
BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishOk,3));
linphone_proxy_config_edit(proxy);
linphone_proxy_config_set_publish_expires(proxy, linphone_proxy_config_get_publish_expires(proxy)+1);
linphone_proxy_config_done(proxy);
BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,4));
BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishOk,4));
linphone_core_manager_stop(marie);
BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishCleared,3,int,"%i"); /*yes it is 3 because when we change the expires, a new LinphoneEvent is created*/
BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,4,int,"%i");
......@@ -1677,76 +1676,139 @@ static void publish_with_dual_identity(void) {
LinphoneCoreManager* pauline = linphone_core_manager_new("multi_account_rc");
const bctbx_list_t* proxies;
LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get());
linphone_core_cbs_set_publish_state_changed(cbs, linphone_publish_state_changed);
_linphone_core_add_callbacks(pauline->lc, cbs, TRUE);
linphone_core_cbs_unref(cbs);
for (proxies = linphone_core_get_proxy_config_list(pauline->lc); proxies!=NULL; proxies = proxies->next) {
LinphoneProxyConfig *proxy = (LinphoneProxyConfig *) proxies->data;
linphone_proxy_config_edit(proxy);
linphone_proxy_config_enable_publish(proxy,TRUE);
linphone_proxy_config_done(proxy);
}
BC_ASSERT_TRUE(wait_for(pauline->lc,pauline->lc,&pauline->stat.number_of_LinphonePublishProgress,4));
BC_ASSERT_TRUE(wait_for(pauline->lc,pauline->lc,&pauline->stat.number_of_LinphonePublishOk,4));
linphone_core_manager_stop(pauline);
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphonePublishCleared,4,int,"%i");
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphonePublishOk,4,int,"%i");
linphone_core_manager_destroy(pauline);
}
static void publish_with_network_state_changes(void) {
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
LinphoneFriend* marie_as_friend = linphone_core_create_friend_with_address(pauline->lc, get_identity(marie));
LinphoneProxyConfig* proxy;
LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get());
linphone_core_cbs_set_publish_state_changed(cbs, linphone_publish_state_changed);
_linphone_core_add_callbacks(marie->lc, cbs,TRUE);
linphone_core_cbs_unref(cbs);
linphone_core_set_user_agent(marie->lc, "full-presence-support", NULL);
linphone_core_set_user_agent(marie->lc, "full-presence-support-bypass", NULL);
proxy = linphone_core_get_default_proxy_config(marie->lc);
linphone_proxy_config_edit(proxy);
linphone_proxy_config_enable_publish(proxy,TRUE);
linphone_proxy_config_done(proxy);
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));
linphone_core_set_network_reachable(marie->lc, FALSE);
BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphoneRegistrationNone,1));
BC_ASSERT_FALSE(wait_for_until(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,2,1000));
BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,1,int,"%i");
BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishError,0,int,"%i");
linphone_core_set_network_reachable(marie->lc, TRUE);
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));
linphone_core_manager_stop(marie);
BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishCleared,1,