Commit 97f28a65 authored by Ghislain MARY's avatar Ghislain MARY
Browse files

Basic parsing of presence list notify.

parent 3cb24866
......@@ -1122,7 +1122,7 @@ static void is_composing_received(SalOp *op, const SalIsComposing *is_composing)
}
static void parse_presence_requested(SalOp *op, const char *content_type, const char *content_subtype, const char *body, SalPresenceModel **result) {
linphone_notify_parse_presence(op, content_type, content_subtype, body, result);
linphone_notify_parse_presence(content_type, content_subtype, body, result);
}
static void convert_presence_to_xml_requested(SalOp *op, SalPresenceModel *presence, const char *contact, char **content) {
......
......@@ -389,6 +389,13 @@ const LinphonePresenceModel * linphone_friend_get_presence_model(LinphoneFriend
return lf->presence;
}
void linphone_friend_set_presence_model(LinphoneFriend *lf, LinphonePresenceModel *presence) {
if (lf->presence != NULL) {
linphone_presence_model_unref(lf->presence);
}
lf->presence = presence;
}
BuddyInfo * linphone_friend_get_info(const LinphoneFriend *lf){
return lf->info;
}
......
......@@ -91,6 +91,64 @@ static char * create_resource_list_xml(const LinphoneFriendList *list) {
return xml_content;
}
static void linphone_friend_list_parse_multipart_related_body(LinphoneFriendList *list, const LinphoneContent *body, const char *first_part_body) {
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) {
char xpath_str[MAX_XPATH_LENGTH];
LinphoneFriend *friend;
LinphoneContent *presence_part;
xmlXPathObjectPtr resource_object;
const char *uri = NULL;
int i;
if (linphone_create_xml_xpath_context(xml_ctx) < 0) goto end;
xmlXPathRegisterNs(xml_ctx->xpath_ctx, (const xmlChar *)"rlmi", (const xmlChar *)"urn:ietf:params:xml:ns:rlmi");
resource_object = linphone_get_xml_xpath_object_for_node_list(xml_ctx, "/rlmi:list/rlmi:resource");
if ((resource_object != NULL) && (resource_object->nodesetval != NULL)) {
for (i = 1; i <= resource_object->nodesetval->nodeNr; i++) {
snprintf(xpath_str, sizeof(xpath_str), "/rlmi:list/rlmi:resource[%i]/@uri", i);
uri = linphone_get_xml_text_content(xml_ctx, xpath_str);
if (uri == NULL) continue;
friend = linphone_friend_list_find_friend_by_uri(list, uri);
if (friend != NULL) {
const char *state = NULL;
snprintf(xpath_str, sizeof(xpath_str),"/rlmi:list/rlmi:resource[%i]/rlmi:instance/@state", i);
state = linphone_get_xml_text_content(xml_ctx, xpath_str);
if ((state != NULL) && (strcmp(state, "active") == 0)) {
const char *cid = NULL;
snprintf(xpath_str, sizeof(xpath_str),"/rlmi:list/rlmi:resource[%i]/rlmi:instance/@cid", i);
cid = linphone_get_xml_text_content(xml_ctx, xpath_str);
if (cid != NULL) {
presence_part = linphone_content_find_part_by_header(body, "Content-Id", cid);
if (presence_part == NULL) {
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) {
linphone_friend_set_presence_model(friend, (LinphonePresenceModel *)presence);
linphone_core_notify_notify_presence_received(list->lc, friend);
}
}
}
if (cid != NULL) linphone_free_xml_text_content(cid);
}
if (state != NULL) linphone_free_xml_text_content(state);
}
linphone_free_xml_text_content(uri);
}
}
if (resource_object != NULL) xmlXPathFreeObject(resource_object);
} else {
ms_warning("Wrongly formatted rlmi+xml body: %s", xml_ctx->errorBuffer);
}
end:
linphone_xmlparsing_context_destroy(xml_ctx);
}
static LinphoneFriendList * linphone_friend_list_new(void) {
LinphoneFriendList *list = belle_sip_object_new(LinphoneFriendList);
belle_sip_object_ref(list);
......@@ -249,6 +307,7 @@ void linphone_friend_list_update_subscriptions(LinphoneFriendList *list, Linphon
int expires = lp_config_get_int(list->lc->config, "sip", "rls_presence_expires", 3600);
event = linphone_core_create_subscribe(list->lc, address, "presence", expires);
linphone_event_add_custom_header(event, "Require", "recipient-list-subscribe");
linphone_event_add_custom_header(event, "Supported", "eventlist");
linphone_event_add_custom_header(event, "Accept", "multipart/related, application/pidf+xml, application/rlmi+xml");
linphone_event_add_custom_header(event, "Content-Disposition", "recipient-list");
content = linphone_core_create_content(list->lc);
......@@ -282,3 +341,31 @@ void linphone_friend_list_notify_presence(LinphoneFriendList *list, LinphonePres
linphone_friend_notify(friend, presence);
}
}
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'");
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;
}
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'");
return;
}
linphone_friend_list_parse_multipart_related_body(list, body, linphone_content_get_string_buffer(first_part));
}
}
......@@ -1664,10 +1664,17 @@ static void linphone_core_register_default_codecs(LinphoneCore *lc){
linphone_core_register_static_payloads(lc);
}
static void linphone_core_internal_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char *notified_event, const LinphoneContent *body) {
if (strcmp(notified_event, "Presence") == 0) {
linphone_friend_list_notify_presence_received(lc->friendlist, lev, body);
}
}
static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtable, LpConfig *config, void * userdata){
const char *rls_uri = NULL;
const char *remote_provisioning_uri = NULL;
LinphoneCoreVTable* local_vtable= linphone_core_v_table_new();
LinphoneCoreVTable *internal_vtable = linphone_core_v_table_new();
ms_message("Initializing LinphoneCore %s", linphone_core_get_version());
lc->config=lp_config_ref(config);
......@@ -1679,6 +1686,8 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab
linphone_friend_list_set_rls_uri(lc->friendlist, rls_uri);
linphone_task_list_init(&lc->hooks);
internal_vtable->notify_received = linphone_core_internal_notify_received;
_linphone_core_add_listener(lc, internal_vtable, TRUE);
memcpy(local_vtable,vtable,sizeof(LinphoneCoreVTable));
_linphone_core_add_listener(lc, local_vtable, TRUE);
......
......@@ -240,6 +240,13 @@ LINPHONE_PUBLIC LinphoneOnlineStatus linphone_friend_get_status(const LinphoneFr
*/
LINPHONE_PUBLIC const LinphonePresenceModel * linphone_friend_get_presence_model(LinphoneFriend *lf);
/**
* Set the presence model of a friend
* @param[in] lf A #LinphoneFriend object
* @param[in] presence The #LinphonePresenceModel object to set for the friend
*/
LINPHONE_PUBLIC void linphone_friend_set_presence_model(LinphoneFriend *lf, LinphonePresenceModel *presence);
/**
* Store user pointer to friend object.
**/
......
......@@ -1508,7 +1508,7 @@ void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from){
ms_free(tmp);
}
void linphone_notify_parse_presence(SalOp *op, const char *content_type, const char *content_subtype, const char *body, SalPresenceModel **result) {
void linphone_notify_parse_presence(const char *content_type, const char *content_subtype, const char *body, SalPresenceModel **result) {
xmlparsing_context_t *xml_ctx;
LinphonePresenceModel *model = NULL;
......@@ -1866,10 +1866,7 @@ void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, Sa
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);
if (lf->presence != NULL) {
linphone_presence_model_unref(lf->presence);
}
lf->presence = presence;
linphone_friend_set_presence_model(lf, presence);
lf->subscribe_active=TRUE;
linphone_core_notify_notify_presence_received(lc,(LinphoneFriend*)lf);
ms_free(tmp);
......
......@@ -377,6 +377,7 @@ void _linphone_proxy_config_release(LinphoneProxyConfig *cfg);
const LinphoneAddress* linphone_proxy_config_get_service_route(const LinphoneProxyConfig* cfg);
void linphone_friend_list_invalidate_subscriptions(LinphoneFriendList *list);
void linphone_friend_list_notify_presence_received(LinphoneFriendList *list, LinphoneEvent *lev, const LinphoneContent *body);
void linphone_friend_invalidate_subscription(LinphoneFriend *lf);
void linphone_friend_close_subscriptions(LinphoneFriend *lf);
void linphone_friend_update_subscribes(LinphoneFriend *fr, LinphoneProxyConfig *cfg, bool_t only_when_registered);
......@@ -434,7 +435,7 @@ void linphone_process_authentication(LinphoneCore* lc, SalOp *op);
void linphone_authentication_ok(LinphoneCore *lc, SalOp *op);
void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from);
void linphone_core_send_presence(LinphoneCore *lc, LinphonePresenceModel *presence);
void linphone_notify_parse_presence(SalOp *op, const char *content_type, const char *content_subtype, const char *body, SalPresenceModel **result);
void linphone_notify_parse_presence(const char *content_type, const char *content_subtype, const char *body, SalPresenceModel **result);
void linphone_notify_convert_presence_to_xml(SalOp *op, SalPresenceModel *presence, const char *contact, char **content);
void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, SalPresenceModel *model);
void linphone_proxy_config_process_authentication_failure(LinphoneCore *lc, SalOp *op);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment