Source

Target

Commits (9)
Showing with 275 additions and 32 deletions
......@@ -6,7 +6,7 @@
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>linphone</string>
<string>${MACOSX_FRAMEWORK_NAME}</string>
<key>CFBundleGetInfoString</key>
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
<key>CFBundleIconFile</key>
......
......@@ -1725,3 +1725,27 @@ const char * linphone_friend_sip_uri_to_phone_number(LinphoneFriend *lf, const c
void linphone_friend_clear_presence_models(LinphoneFriend *lf) {
lf->presence_models = bctbx_list_free_with_data(lf->presence_models, (bctbx_list_free_func)free_friend_presence);
}
int linphone_friend_get_capabilities(const LinphoneFriend *lf) {
return lf->capabilities;
}
bool_t linphone_friend_has_capability(const LinphoneFriend *lf, const LinphoneFriendCapability capability) {
return lf->capabilities & capability;
}
namespace {
const std::unordered_map<std::string, LinphoneFriendCapability> StringToCapability{
{ "groupchat", LinphoneFriendCapabilityGroupChat },
{ "lime", LinphoneFriendCapabilityLimeX3dh }
};
}
void linphone_friend_add_capability(LinphoneFriend *lf, const char *capability_name) {
auto it = StringToCapability.find(capability_name);
if (it == StringToCapability.cend()) {
bctbx_error("Invalid capability %s for friend [%p]", capability_name, lf);
} else {
bctbx_debug("Adding capability %s to friend [%p]", capability_name, lf);
lf->capabilities |= it->second;
}
}
......@@ -293,7 +293,19 @@ static void linphone_friend_list_parse_multipart_related_body(LinphoneFriendList
}
if (lf) {
const char *phone_number = linphone_friend_sip_uri_to_phone_number(lf, uri);
unsigned int nb_services = linphone_presence_model_get_nb_services((LinphonePresenceModel *)presence);
for (unsigned int i = 0; i < nb_services; i++) {
LinphonePresenceService *service = linphone_presence_model_get_nth_service((LinphonePresenceModel *)presence, i);
bctbx_list_t *services_descriptions = linphone_presence_service_get_service_descriptions(service);
while (services_descriptions) {
char *description = (char *)bctbx_list_get_data(services_descriptions);
linphone_friend_add_capability(lf, description);
services_descriptions = bctbx_list_next(services_descriptions);
}
}
lf->presence_received = TRUE;
if (phone_number) {
char *presence_address = linphone_presence_model_get_contact((LinphonePresenceModel *)presence);
bctbx_pair_t *pair = (bctbx_pair_t*) bctbx_pair_cchar_new(presence_address, linphone_friend_ref(lf));
......
......@@ -2248,9 +2248,21 @@ static void linphone_core_internal_subscribe_received(LinphoneCore *lc, Linphone
}
}
static void _linphone_core_conference_subscription_state_changed (LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state) {
const LinphoneAddress *resource = linphone_event_get_resource(lev);
shared_ptr<AbstractChatRoom> chatRoom = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findChatRoom(LinphonePrivate::ConferenceId(
IdentityAddress(*L_GET_CPP_PTR_FROM_C_OBJECT(resource)),
IdentityAddress(*L_GET_CPP_PTR_FROM_C_OBJECT(resource))
));
if (chatRoom)
L_GET_PRIVATE(static_pointer_cast<ServerGroupChatRoom>(chatRoom))->subscriptionStateChanged(lev, state);
}
static void linphone_core_internal_subscription_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state) {
if (strcasecmp(linphone_event_get_name(lev), "Presence") == 0) {
linphone_friend_list_subscription_state_changed(lc, lev, state);
} else if (strcmp(linphone_event_get_name(lev), "conference") == 0) {
_linphone_core_conference_subscription_state_changed(lc, lev, state);
}
}
......
......@@ -48,6 +48,7 @@ struct _LinphonePresenceService {
char *contact;
bctbx_list_t *notes; /**< A list of _LinphonePresenceNote structures. */
time_t timestamp;
bctbx_list_t *service_descriptions;
};
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphonePresenceService);
......@@ -800,6 +801,19 @@ LinphoneStatus linphone_presence_service_set_contact(LinphonePresenceService *se
return 0;
}
bctbx_list_t * linphone_presence_service_get_service_descriptions(const LinphonePresenceService *service) {
return service->service_descriptions;
}
LinphoneStatus linphone_presence_service_set_service_descriptions(LinphonePresenceService *service, bctbx_list_t *descriptions) {
if (!service) return -1;
if (service->service_descriptions)
bctbx_list_free_with_data(service->service_descriptions, bctbx_free);
service->service_descriptions = descriptions;
return 0;
}
unsigned int linphone_presence_service_get_nb_notes(const LinphonePresenceService *service) {
return (unsigned int)bctbx_list_size(service->notes);
}
......@@ -1262,6 +1276,7 @@ static int process_pidf_xml_presence_services(xmlparsing_context_t *xml_ctx, Lin
char *contact_str;
LinphonePresenceBasicStatus basic_status;
int i;
xmlXPathObjectPtr service_descriptions;
service_object = linphone_get_xml_xpath_object_for_node_list(xml_ctx, service_prefix);
if ((service_object != NULL) && (service_object->nodesetval != NULL)) {
......@@ -1298,16 +1313,33 @@ static int process_pidf_xml_presence_services(xmlparsing_context_t *xml_ctx, Lin
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/@id", service_prefix, i);
service_id_str = linphone_get_xml_text_content(xml_ctx, xpath_str);
service = presence_service_new(service_id_str, basic_status);
if (service != NULL) {
if (timestamp_str != NULL) presence_service_set_timestamp(service, parse_timestamp(timestamp_str));
if (contact_str != NULL) linphone_presence_service_set_contact(service, contact_str);
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/oma-pres:service-description", service_prefix, i);
service_descriptions = linphone_get_xml_xpath_object_for_node_list(xml_ctx, xpath_str);
bctbx_list_t *services = nullptr;
if (service_descriptions && service_descriptions->nodesetval) {
for (int j = 1; j <= service_descriptions->nodesetval->nodeNr; j++) {
char *service_id = nullptr;
linphone_xml_xpath_context_set_node(xml_ctx, xmlXPathNodeSetItem(service_descriptions->nodesetval, j-1));
service_id = linphone_get_xml_text_content(xml_ctx, "./oma-pres:service-id");
if (service_id) {
services = bctbx_list_append(services, ms_strdup(service_id));
linphone_free_xml_text_content(service_id);
}
}
}
if (service) {
if (timestamp_str) presence_service_set_timestamp(service, parse_timestamp(timestamp_str));
if (contact_str) linphone_presence_service_set_contact(service, contact_str);
if (services) linphone_presence_service_set_service_descriptions(service, services);
process_pidf_xml_presence_service_notes(xml_ctx, service, (unsigned int)i);
linphone_presence_model_add_service(model, service);
linphone_presence_service_unref(service);
}
if (timestamp_str != NULL) linphone_free_xml_text_content(timestamp_str);
if (contact_str != NULL) linphone_free_xml_text_content(contact_str);
if (service_id_str != NULL) linphone_free_xml_text_content(service_id_str);
if (timestamp_str) linphone_free_xml_text_content(timestamp_str);
if (contact_str) linphone_free_xml_text_content(contact_str);
if (service_id_str) linphone_free_xml_text_content(service_id_str);
linphone_free_xml_text_content(basic_status_str);
}
}
......@@ -1506,6 +1538,7 @@ static LinphonePresenceModel * process_pidf_xml_presence_notification(xmlparsing
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");
xmlXPathRegisterNs(xml_ctx->xpath_ctx, (const xmlChar *)"oma-pres", (const xmlChar *)"urn:oma:xml:prs:pidf:oma-pres");
err = process_pidf_xml_presence_services(xml_ctx, model);
if (err == 0) {
err = process_pidf_xml_presence_persons(xml_ctx, model);
......
......@@ -164,6 +164,7 @@ void linphone_friend_add_incoming_subscription(LinphoneFriend *lf, LinphonePriva
void linphone_friend_remove_incoming_subscription(LinphoneFriend *lf, LinphonePrivate::SalOp *op);
const char * linphone_friend_phone_number_to_sip_uri(LinphoneFriend *lf, const char *phone_number);
const char * linphone_friend_sip_uri_to_phone_number(LinphoneFriend *lf, const char *uri);
void linphone_friend_add_capability(LinphoneFriend *lf, const char *capability_name);
void linphone_friend_clear_presence_models(LinphoneFriend *lf);
LinphoneFriend *linphone_friend_list_find_friend_by_inc_subscribe(const LinphoneFriendList *list, LinphonePrivate::SalOp *op);
LinphoneFriend *linphone_friend_list_find_friend_by_out_subscribe(const LinphoneFriendList *list, LinphonePrivate::SalOp *op);
......
......@@ -187,6 +187,7 @@ struct _LinphoneFriend{
unsigned int storage_id;
LinphoneFriendList *friend_list;
LinphoneSubscriptionState out_sub_state;
int capabilities;
};
BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneFriend);
......
......@@ -337,6 +337,21 @@ LINPHONE_PUBLIC LinphoneFriend *linphone_friend_new_from_vcard(LinphoneVcard *vc
*/
LINPHONE_PUBLIC void linphone_friend_save(LinphoneFriend *fr, LinphoneCore *lc);
/**
* Returns the capabilities associated to this friend
* @param[in] lf #LinphoneFriend object
* @return an int representing the capabilities of the friend
*/
LINPHONE_PUBLIC int linphone_friend_get_capabilities(const LinphoneFriend *lf);
/**
* Returns whether or not a friend has a capbility
* @param[in] lf #LinphoneFriend object
* @param[in] capability #LinphoneFriendCapability object
* @return whether or not a friend has a capbility
*/
LINPHONE_PUBLIC bool_t linphone_friend_has_capability(const LinphoneFriend *lf, const LinphoneFriendCapability capability);
/**
* @}
*/
......
......@@ -118,7 +118,7 @@ LINPHONE_PUBLIC LinphoneStatus linphone_presence_model_set_presentity(LinphonePr
*
*/
LINPHONE_PUBLIC const LinphoneAddress * linphone_presence_model_get_presentity(const LinphonePresenceModel *model);
/**
* Gets the first activity of a presence model (there is usually only one).
* @param[in] model The #LinphonePresenceModel object to get the activity from.
......@@ -361,6 +361,23 @@ LINPHONE_PUBLIC char * linphone_presence_service_get_contact(const LinphonePrese
*/
LINPHONE_PUBLIC LinphoneStatus linphone_presence_service_set_contact(LinphonePresenceService *service, const char *contact);
/**
* Gets the service descriptions of a presence service.
* @param[in] service The #LinphonePresenceService object to get the contact from.
* @return A \bctbx_list{char *} containing the services descriptions.
*
* The returned string is to be freed.
*/
LINPHONE_PUBLIC bctbx_list_t * linphone_presence_service_get_service_descriptions(const LinphonePresenceService *service);
/**
* Sets the service descriptions of a presence service.
* @param[in] service The #LinphonePresenceService object for which to set the contact.
* @param[in] descriptions \bctbx_list{char *} The service descriptions.
* @return 0 if successful, a value < 0 in case of error.
*/
LINPHONE_PUBLIC LinphoneStatus linphone_presence_service_set_service_descriptions(LinphonePresenceService *service, bctbx_list_t *descriptions);
/**
* Gets the number of notes included in the presence service.
* @param[in] service The #LinphonePresenceService object to get the number of notes from.
......
......@@ -447,6 +447,16 @@ typedef enum _LinphoneFirewallPolicy {
*/
typedef struct _LinphoneFriend LinphoneFriend;
/**
* Enum describing the status of a LinphoneFriendList operation.
* @ingroup buddy_list
**/
typedef enum _LinphoneFriendCapability {
LinphoneFriendCapabilityNone = 0,
LinphoneFriendCapabilityGroupChat = 1 << 0,
LinphoneFriendCapabilityLimeX3dh = 1 << 1
} LinphoneFriendCapability;
/**
* The #LinphoneFriendList object representing a list of friends.
* @ingroup buddy_list
......
......@@ -297,8 +297,7 @@ LinphoneChatRoomCapabilitiesMask linphone_chat_room_get_capabilities (const Linp
}
bool_t linphone_chat_room_has_capability(const LinphoneChatRoom *cr, int mask) {
if (L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getCapabilities() & mask) return true;
return false;
return L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getCapabilities() & mask;
}
const LinphoneAddress *linphone_chat_room_get_conference_address (const LinphoneChatRoom *cr) {
......
......@@ -55,6 +55,7 @@ public:
void dispatchQueuedMessages ();
void subscribeReceived (LinphoneEvent *event);
void subscriptionStateChanged (LinphoneEvent *event, LinphoneSubscriptionState state);
bool update (SalCallOp *op);
......
......@@ -336,6 +336,11 @@ void ServerGroupChatRoomPrivate::subscribeReceived (LinphoneEvent *event) {
qConference->getPrivate()->eventHandler->subscribeReceived(event, !!(capabilities & ServerGroupChatRoom::Capabilities::OneToOne));
}
void ServerGroupChatRoomPrivate::subscriptionStateChanged (LinphoneEvent *event, LinphoneSubscriptionState state) {
L_Q_T(LocalConference, qConference);
qConference->getPrivate()->eventHandler->subscriptionStateChanged(event, state);
}
bool ServerGroupChatRoomPrivate::update (SalCallOp *op) {
L_Q();
if (sal_custom_header_find(op->getRecvCustomHeaders(), "Subject")) {
......@@ -530,9 +535,12 @@ void ServerGroupChatRoomPrivate::addParticipantDevice (const shared_ptr<Particip
lInfo() << q << ": Adding participant device that is currently in state [" << device->getState() << "]";
switch (device->getState()) {
case ParticipantDevice::State::Joining:
case ParticipantDevice::State::Left:
inviteDevice(device);
break;
case ParticipantDevice::State::Left:
if (!findFilteredParticipant(participant->getAddress()))
inviteDevice(device);
break;
case ParticipantDevice::State::Leaving:
byeDevice(device);
break;
......
......@@ -439,8 +439,29 @@ void LocalConferenceEventHandler::subscribeReceived (LinphoneEvent *lev, bool on
d->conf->getConferenceAddress() <<
"] should not be higher than last notify sent by server [" << d->lastNotify << "]";
}
} else if (linphone_event_get_subscription_state(lev) == LinphoneSubscriptionTerminated)
}
}
void LocalConferenceEventHandler::subscriptionStateChanged (LinphoneEvent *lev, LinphoneSubscriptionState state) {
L_D();
if (state == LinphoneSubscriptionTerminated) {
const LinphoneAddress *lAddr = linphone_event_get_from(lev);
char *addrStr = linphone_address_as_string(lAddr);
shared_ptr<Participant> participant = d->conf->findParticipant(Address(addrStr));
bctbx_free(addrStr);
if (!participant)
return;
const LinphoneAddress *lContactAddr = linphone_event_get_remote_contact(lev);
char *contactAddrStr = linphone_address_as_string(lContactAddr);
IdentityAddress contactAddr(contactAddrStr);
bctbx_free(contactAddrStr);
shared_ptr<ParticipantDevice> device = participant->getPrivate()->findDevice(contactAddr);
if (!device)
return;
lInfo() << "End of subscription for device [" << device->getAddress()
<< "] of conference [" << d->conf->getConferenceAddress() << "]";
device->setConferenceSubscribeEvent(nullptr);
}
}
shared_ptr<ConferenceParticipantEvent> LocalConferenceEventHandler::notifyParticipantAdded (const Address &addr) {
......
......@@ -43,6 +43,8 @@ public:
LocalConferenceEventHandler (LocalConference *localConference, unsigned int notify = 0);
void subscribeReceived (LinphoneEvent *lev, bool oneToOne = false);
void subscriptionStateChanged (LinphoneEvent *lev, LinphoneSubscriptionState state);
std::shared_ptr<ConferenceParticipantEvent> notifyParticipantAdded (const Address &addr);
std::shared_ptr<ConferenceParticipantEvent> notifyParticipantRemoved (const Address &addr);
std::shared_ptr<ConferenceParticipantEvent> notifyParticipantSetAdmin (const Address &addr, bool isAdmin);
......
......@@ -57,7 +57,7 @@ shared_ptr<Core> ParticipantDevice::getCore () const {
void ParticipantDevice::setConferenceSubscribeEvent (LinphoneEvent *ev) {
if (mConferenceSubscribeEvent)
linphone_event_unref(mConferenceSubscribeEvent);
mConferenceSubscribeEvent = linphone_event_ref(ev);
mConferenceSubscribeEvent = ev ? linphone_event_ref(ev) : nullptr;
}
ostream &operator<< (ostream &stream, ParticipantDevice::State state) {
......
......@@ -720,7 +720,10 @@ belle_sip_header_contact_t *SalOp::createContact () {
if (!mRoot->mLinphoneSpecs.empty()
&& !belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(contactHeader), "+org.linphone.specs")
) {
belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(contactHeader), "+org.linphone.specs", mRoot->mLinphoneSpecs.c_str());
stringstream ss;
ss << "\"" << mRoot->mLinphoneSpecs << "\"";
string specs = ss.str();
belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(contactHeader), "+org.linphone.specs", specs.c_str());
}
return contactHeader;
}
......
......@@ -35,8 +35,8 @@ static int get_codec_position(const MSList *l, const char *mime_type, int rate){
/*check basic things about codecs at startup: order and enablement*/
static void start_with_no_config(void){
LinphoneCoreManager* mgr = linphone_core_manager_new2("empty_rc", FALSE);
const MSList *codecs=linphone_core_get_audio_codecs(mgr->lc);
LinphoneCore *lc=linphone_factory_create_core_2(linphone_factory_get(), NULL, NULL, NULL, NULL, system_context);
const MSList *codecs=linphone_core_get_audio_codecs(lc);
int opus_codec_pos;
int speex_codec_pos=get_codec_position(codecs, "speex", 8000);
int speex16_codec_pos=get_codec_position(codecs, "speex", 16000);
......@@ -45,12 +45,12 @@ static void start_with_no_config(void){
if (opus_codec_pos!=-1) BC_ASSERT_EQUAL(opus_codec_pos,0,int, "%d");
BC_ASSERT_LOWER(speex16_codec_pos,speex_codec_pos,int,"%d");
pt=linphone_core_find_payload_type(mgr->lc, "speex", 16000, 1);
pt=linphone_core_find_payload_type(lc, "speex", 16000, 1);
BC_ASSERT_PTR_NOT_NULL(pt);
if (pt) {
BC_ASSERT_TRUE(linphone_core_payload_type_enabled(mgr->lc, pt));
BC_ASSERT_TRUE(linphone_core_payload_type_enabled(lc, pt));
}
linphone_core_manager_destroy(mgr);
linphone_core_unref(lc);
}
static void check_payload_type_numbers(LinphoneCall *call1, LinphoneCall *call2, int expected_number){
......
......@@ -20,26 +20,18 @@
#include "tester_utils.h"
#include <mediastreamer2/mediastream.h>
static bool_t wait_for_eof(bool_t *eof, int *time,int time_refresh, int timeout) {
while(*time < timeout && !*eof) {
ms_usleep(time_refresh * 1000U);
*time += time_refresh;
}
return *time < timeout;
}
static void eof_callback(LinphonePlayer *player) {
LinphonePlayerCbs *cbs = linphone_player_get_callbacks(player);
bool_t *eof = (bool_t *)linphone_player_cbs_get_user_data(cbs);
*eof = TRUE;
int *eof = (int *)linphone_player_cbs_get_user_data(cbs);
*eof = 1;
}
static void play_file(const char *filename, bool_t supported_format, const char *audio_mime, const char *video_mime) {
LinphoneCoreManager *lc_manager = linphone_core_manager_new("marie_rc");
LinphonePlayer *player;
LinphonePlayerCbs *cbs;
int res, timer = 0;
bool_t eof = FALSE;
int res;
int eof = 0;
bool_t audio_codec_supported = (audio_mime && ms_factory_get_decoder(linphone_core_get_ms_factory((void *)lc_manager->lc), audio_mime));
bool_t video_codec_supported = (video_mime && ms_factory_get_decoder(linphone_core_get_ms_factory((void *)lc_manager->lc), video_mime));
......@@ -61,7 +53,7 @@ static void play_file(const char *filename, bool_t supported_format, const char
BC_ASSERT_EQUAL(res, 0, int, "%d");
if(res == -1) goto fail;
BC_ASSERT_TRUE(wait_for_eof(&eof, &timer, 100, (int)(linphone_player_get_duration(player) * 1.05)));
BC_ASSERT_TRUE(wait_for_until(lc_manager->lc, NULL, &eof, 1, (int)(linphone_player_get_duration(player) * 1.05)));
linphone_player_close(player);
......
......@@ -1849,6 +1849,97 @@ static void multiple_bodyless_list_subscription_with_rc(void) {
}
#endif
static void notify_friend_capabilities(void) {
LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc");
LinphoneCoreManager *pauline = linphone_core_manager_create(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
LinphoneCoreManager *pauline2 = linphone_core_manager_create(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc");
LinphoneCoreManager *chloe = linphone_core_manager_create("chloe_rc");
LinphoneCoreManager *chloe2 = linphone_core_manager_create("chloe_rc");
linphone_core_set_linphone_specs(pauline->lc, "groupchat");
linphone_core_set_linphone_specs(pauline2->lc, "lime");
linphone_core_set_linphone_specs(laure->lc, "groupchat");
linphone_core_set_linphone_specs(chloe->lc, "groupchat, lime");
linphone_core_manager_start(marie, TRUE);
linphone_core_manager_start(pauline, TRUE);
linphone_core_manager_start(pauline2, TRUE);
linphone_core_manager_start(laure, TRUE);
linphone_core_manager_start(chloe, TRUE);
linphone_core_manager_start(chloe2, TRUE);
LinphoneFriendList *friendList = linphone_core_get_default_friend_list(marie->lc);
LinphoneFriend* paulineFriend = linphone_core_create_friend_with_address(marie->lc, get_identity(pauline));
LinphoneFriend* laureFriend = linphone_core_create_friend_with_address(marie->lc, get_identity(laure));
LinphoneFriend* chloeFriend = linphone_core_create_friend_with_address(marie->lc, get_identity(chloe));
LinphoneCoreCbs *callbacks = linphone_factory_create_core_cbs(linphone_factory_get());
bctbx_list_t *lcs = NULL;
lcs = bctbx_list_append(lcs, marie->lc);
lcs = bctbx_list_append(lcs, pauline->lc);
lcs = bctbx_list_append(lcs, pauline2->lc);
lcs = bctbx_list_append(lcs, laure->lc);
lcs = bctbx_list_append(lcs, chloe->lc);
lcs = bctbx_list_append(lcs, chloe2->lc);
linphone_core_set_user_agent(marie->lc, "full-presence-support", NULL);
linphone_core_set_user_agent(marie->lc, "full-presence-support-bypass", NULL);
linphone_friend_list_enable_subscriptions(friendList, FALSE);
linphone_friend_list_set_rls_uri(friendList, "sip:rls@sip.example.org");
linphone_core_cbs_set_publish_state_changed(callbacks, linphone_publish_state_changed);
_linphone_core_add_callbacks(marie->lc, callbacks, TRUE);
linphone_core_cbs_unref(callbacks);
linphone_friend_list_add_friend(friendList, paulineFriend);
linphone_friend_list_add_friend(friendList, laureFriend);
linphone_friend_list_add_friend(friendList, chloeFriend);
linphone_friend_list_enable_subscriptions(friendList, TRUE);
BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_NotifyPresenceReceived, 1, 5000));
BC_ASSERT_TRUE(linphone_friend_get_capabilities(paulineFriend) & LinphoneFriendCapabilityGroupChat);
BC_ASSERT_TRUE(linphone_friend_has_capability(paulineFriend, LinphoneFriendCapabilityGroupChat));
BC_ASSERT_TRUE(linphone_friend_get_capabilities(paulineFriend) & LinphoneFriendCapabilityLimeX3dh);
BC_ASSERT_TRUE(linphone_friend_has_capability(paulineFriend, LinphoneFriendCapabilityLimeX3dh));
BC_ASSERT_TRUE(linphone_friend_get_capabilities(laureFriend) & LinphoneFriendCapabilityGroupChat);
BC_ASSERT_TRUE(linphone_friend_has_capability(laureFriend, LinphoneFriendCapabilityGroupChat));
BC_ASSERT_FALSE(linphone_friend_get_capabilities(laureFriend) & LinphoneFriendCapabilityLimeX3dh);
BC_ASSERT_FALSE(linphone_friend_has_capability(laureFriend, LinphoneFriendCapabilityLimeX3dh));
BC_ASSERT_TRUE(linphone_friend_get_capabilities(chloeFriend) & LinphoneFriendCapabilityGroupChat);
BC_ASSERT_TRUE(linphone_friend_has_capability(chloeFriend, LinphoneFriendCapabilityGroupChat));
BC_ASSERT_TRUE(linphone_friend_get_capabilities(chloeFriend) & LinphoneFriendCapabilityLimeX3dh);
BC_ASSERT_TRUE(linphone_friend_has_capability(chloeFriend, LinphoneFriendCapabilityLimeX3dh));
linphone_friend_unref(paulineFriend);
linphone_friend_unref(laureFriend);
linphone_friend_unref(chloeFriend);
linphone_core_manager_stop(marie);
linphone_core_manager_destroy(marie);
linphone_core_manager_stop(pauline);
linphone_core_manager_destroy(pauline);
linphone_core_manager_stop(pauline2);
linphone_core_manager_destroy(pauline2);
linphone_core_manager_stop(laure);
linphone_core_manager_destroy(laure);
linphone_core_manager_stop(chloe);
linphone_core_manager_destroy(chloe);
linphone_core_manager_stop(chloe2);
linphone_core_manager_destroy(chloe2);
bctbx_list_free(lcs);
}
test_t presence_server_tests[] = {
TEST_NO_TAG("Simple Publish", simple_publish),
TEST_NO_TAG("Publish with 2 identities", publish_with_dual_identity),
......@@ -1884,6 +1975,7 @@ test_t presence_server_tests[] = {
TEST_ONE_TAG("Multiple bodyless list subscription", multiple_bodyless_list_subscription, "bodyless"),
TEST_ONE_TAG("Multiple bodyless list subscription with rc", multiple_bodyless_list_subscription_with_rc, "bodyless"),
#endif
TEST_NO_TAG("Notify LinphoneFriend capabilities", notify_friend_capabilities),
};
test_suite_t presence_server_test_suite = {"Presence using server", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each,
......