Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
BC
public
liblinphone
Commits
f7a6c72b
Commit
f7a6c72b
authored
Dec 11, 2018
by
Benjamin REIS
Browse files
Feature/add capabilities to linphone friend
parent
3ae9e6f5
Changes
10
Hide whitespace changes
Inline
Side-by-side
coreapi/friend.c
View file @
f7a6c72b
...
...
@@ -1725,3 +1725,23 @@ 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
;
}
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
;
}
}
coreapi/friendlist.c
View file @
f7a6c72b
...
...
@@ -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
));
...
...
coreapi/presence.c
View file @
f7a6c72b
...
...
@@ -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
);
...
...
coreapi/private_functions.h
View file @
f7a6c72b
...
...
@@ -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
);
...
...
coreapi/private_structs.h
View file @
f7a6c72b
...
...
@@ -187,6 +187,7 @@ struct _LinphoneFriend{
unsigned
int
storage_id
;
LinphoneFriendList
*
friend_list
;
LinphoneSubscriptionState
out_sub_state
;
int
capabilities
=
LinphoneFriendCapabilityNone
;
};
BELLE_SIP_DECLARE_VPTR_NO_EXPORT
(
LinphoneFriend
);
...
...
include/linphone/friend.h
View file @
f7a6c72b
...
...
@@ -337,6 +337,12 @@ 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] fr #LinphoneFriend object
*/
LINPHONE_PUBLIC
int
linphone_friend_get_capabilities
(
const
LinphoneFriend
*
lf
);
/**
* @}
*/
...
...
include/linphone/presence.h
View file @
f7a6c72b
...
...
@@ -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.
...
...
include/linphone/types.h
View file @
f7a6c72b
...
...
@@ -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
...
...
src/sal/op.cpp
View file @
f7a6c72b
...
...
@@ -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
;
}
...
...
tester/presence_server_tester.c
View file @
f7a6c72b
...
...
@@ -1849,6 +1849,91 @@ 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_get_capabilities
(
paulineFriend
)
&
LinphoneFriendCapabilityLimeX3dh
);
BC_ASSERT_TRUE
(
linphone_friend_get_capabilities
(
laureFriend
)
&
LinphoneFriendCapabilityGroupChat
);
BC_ASSERT_FALSE
(
linphone_friend_get_capabilities
(
laureFriend
)
&
LinphoneFriendCapabilityLimeX3dh
);
BC_ASSERT_TRUE
(
linphone_friend_get_capabilities
(
chloeFriend
)
&
LinphoneFriendCapabilityGroupChat
);
BC_ASSERT_TRUE
(
linphone_friend_get_capabilities
(
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 +1969,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
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment