Commit 220c4713 authored by Ghislain MARY's avatar Ghislain MARY
Browse files

Use xml parser to get presence status.

parent 79c72fc8
......@@ -16,7 +16,7 @@ CLEANFILES=$(GITVERSION_FILE)
## Process this file with automake to produce Makefile.in
linphone_includedir=$(includedir)/linphone
linphone_include_HEADERS=linphonecore.h linphonefriend.h linphonecore_utils.h lpconfig.h sipsetup.h event.h
linphone_include_HEADERS=linphonecore.h linphonefriend.h linphonepresence.h linphonecore_utils.h lpconfig.h sipsetup.h event.h
if BUILD_TUNNEL
linphone_include_HEADERS+=linphone_tunnel.h
......
......@@ -486,6 +486,8 @@ void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs){
ctx->callbacks.subscribe_received=(SalOnSubscribeReceived)unimplemented_stub;
if (ctx->callbacks.subscribe_closed==NULL)
ctx->callbacks.subscribe_closed=(SalOnSubscribeClosed)unimplemented_stub;
if (ctx->callbacks.parse_presence_requested==NULL)
ctx->callbacks.parse_presence_requested=(SalOnParsePresenceRequested)unimplemented_stub;
if (ctx->callbacks.notify_presence==NULL)
ctx->callbacks.notify_presence=(SalOnNotifyPresence)unimplemented_stub;
if (ctx->callbacks.subscribe_presence_received==NULL)
......
......@@ -497,6 +497,26 @@ static void presence_process_transaction_terminated(void *user_ctx, const belle_
ms_message("presence_process_transaction_terminated not implemented yet");
}
static SalPresenceModel * process_presence_notification(SalOp *op, belle_sip_request_t *req) {
belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_content_type_t);
belle_sip_header_content_length_t *content_length = belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_content_length_t);
const char *body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req));
SalPresenceModel *result = NULL;
if ((content_type == NULL) || (content_length == NULL))
return NULL;
if (belle_sip_header_content_length_get_content_length(content_length) == 0)
return NULL;
op->base.root->callbacks.parse_presence_requested(op,
belle_sip_header_content_type_get_type(content_type),
belle_sip_header_content_type_get_subtype(content_type),
body,
&result);
return result;
}
static void presence_process_request_event(void *op_base, const belle_sip_request_event_t *event) {
SalOp* op = (SalOp*)op_base;
belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,belle_sip_request_event_get_request(event));
......@@ -505,7 +525,7 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques
belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(req,belle_sip_header_subscription_state_t);
belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t);
const char* body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req));
SalPresenceStatus estatus=SalPresenceOffline;
SalPresenceModel *presence_model = NULL;
SalSubscribeStatus sub_state;
belle_sip_response_t* resp;
belle_sip_object_ref(server_transaction);
......@@ -536,41 +556,22 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques
ms_error("No body in NOTIFY received from [%s]",sal_op_get_from(op));
return;
}
if (strstr(body,"pending")!=NULL){
estatus=SalPresenceOffline;
}else if (strstr(body,"busy")!=NULL){
estatus=SalPresenceBusy;
}else if (strstr(body,"berightback")!=NULL
|| strstr(body,"in-transit")!=NULL ){
estatus=SalPresenceBerightback;
}else if (strstr(body,"away")!=NULL
|| strstr(body,"idle")){
estatus=SalPresenceAway;
}else if (strstr(body,"onthephone")!=NULL
|| strstr(body,"on-the-phone")!=NULL){
estatus=SalPresenceOnthephone;
}else if (strstr(body,"outtolunch")!=NULL
|| strstr(body,"lunch")!=NULL
|| strstr(body,"meal")!=NULL){
estatus=SalPresenceOuttolunch;
}else if (strstr(body,"closed")!=NULL){
estatus=SalPresenceOffline;
}else if ((strstr(body,"online")!=NULL) || (strstr(body,"open")!=NULL)) {
estatus=SalPresenceOnline;
}else if((strstr(body,"vacation")!=NULL)) {
estatus = SalPresenceOnVacation;
}else{
estatus=SalPresenceOffline;
}
ms_message("We are notified that [%s] has online status [%s]",sal_op_get_to(op),sal_presence_status_to_string(estatus));
presence_model = process_presence_notification(op, req);
if (presence_model != NULL) {
/* Presence notification body parsed successfully. */
if (!subscription_state_header || strcasecmp(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,belle_sip_header_subscription_state_get_state(subscription_state_header)) ==0) {
sub_state=SalSubscribeTerminated;
ms_message("And outgoing subscription terminated by remote [%s]",sal_op_get_to(op));
} else
ms_message("Outgoing subscription terminated by remote [%s]",sal_op_get_to(op));
} else {
sub_state=SalSubscribeActive;
op->base.root->callbacks.notify_presence(op,sub_state, estatus,NULL);
resp=sal_op_create_response_from_request(op,req,200);
}
op->base.root->callbacks.notify_presence(op, sub_state, presence_model, NULL);
resp = sal_op_create_response_from_request(op, req, 200);
} else {
/* Formatting error in presence notification body. */
ms_error("Wrongly formatted presence notification received");
resp = sal_op_create_response_from_request(op, req, 400);
}
belle_sip_server_transaction_send_response(server_transaction,resp);
} else if (strcmp("SUBSCRIBE",belle_sip_request_get_method(req))==0) {
/*either a refresh of an unsubscribe*/
......
......@@ -877,9 +877,13 @@ static void text_received(SalOp *op, const SalMessage *msg){
}
}
static void notify_presence(SalOp *op, SalSubscribeStatus ss, SalPresenceStatus status, const char *msg){
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);
}
static void notify_presence(SalOp *op, SalSubscribeStatus ss, SalPresenceModel *model, const char *msg){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
linphone_notify_recv(lc,op,ss,status);
linphone_notify_recv(lc,op,ss,model);
}
static void subscribe_presence_received(SalOp *op, const char *from){
......@@ -1085,6 +1089,7 @@ SalCallbacks linphone_sal_callbacks={
notify,
subscribe_presence_received,
subscribe_presence_closed,
parse_presence_requested,
notify_presence,
ping_reply,
auth_requested,
......
......@@ -119,7 +119,7 @@ void __linphone_friend_do_subscribe(LinphoneFriend *fr){
if (fr->outsub==NULL){
/* people for which we don't have yet an answer should appear as offline */
fr->status=LinphoneStatusOffline;
fr->presence=NULL;
/*
if (fr->lc->vtable.notify_recv)
fr->lc->vtable.notify_recv(fr->lc,(LinphoneFriend*)fr);
......@@ -138,7 +138,7 @@ void __linphone_friend_do_subscribe(LinphoneFriend *fr){
LinphoneFriend * linphone_friend_new(){
LinphoneFriend *obj=ms_new0(LinphoneFriend,1);
obj->pol=LinphoneSPAccept;
obj->status=LinphoneStatusOffline;
obj->presence=NULL;
obj->subscribe=TRUE;
return obj;
}
......@@ -304,6 +304,7 @@ void linphone_friend_destroy(LinphoneFriend *lf){
sal_op_release(lf->outsub);
lf->outsub=NULL;
}
if (lf->presence != NULL) linphone_presence_model_delete(lf->presence);
if (lf->uri!=NULL) linphone_address_destroy(lf->uri);
if (lf->info!=NULL) buddy_info_free(lf->info);
ms_free(lf);
......@@ -322,7 +323,90 @@ LinphoneSubscribePolicy linphone_friend_get_inc_subscribe_policy(const LinphoneF
}
LinphoneOnlineStatus linphone_friend_get_status(const LinphoneFriend *lf){
return lf->status;
LinphoneOnlineStatus online_status = LinphoneStatusOffline;
LinphonePresenceBasicStatus basic_status = LinphonePresenceBasicStatusClosed;
LinphonePresenceActivity activity = LinphonePresenceActivityUnknown;
char *activity_description = NULL;
unsigned int nb_activities = 0;
int err = 0;
if (lf->presence != NULL) {
basic_status = linphone_presence_model_get_basic_status(lf->presence);
nb_activities = linphone_presence_model_nb_activities(lf->presence);
online_status = (basic_status == LinphonePresenceBasicStatusOpen) ? LinphoneStatusOnline : LinphoneStatusOffline;
if (nb_activities > 1) {
char *tmp = NULL;
const LinphoneAddress *addr = linphone_friend_get_address(lf);
if (addr) tmp = linphone_address_as_string(addr);
ms_warning("Friend %s has several activities, get status from the first one", tmp ? tmp : "unknown");
if (tmp) ms_free(tmp);
nb_activities = 1;
}
if (nb_activities == 1) {
err = linphone_presence_model_get_activity(lf->presence, 0, &activity, &activity_description);
if (err == 0) {
switch (activity) {
case LinphonePresenceActivityBreakfast:
case LinphonePresenceActivityDinner:
case LinphonePresenceActivityLunch:
case LinphonePresenceActivityMeal:
online_status = LinphoneStatusOutToLunch;
break;
case LinphonePresenceActivityAppointment:
case LinphonePresenceActivityMeeting:
case LinphonePresenceActivityPerformance:
case LinphonePresenceActivityPresentation:
case LinphonePresenceActivitySpectator:
case LinphonePresenceActivityWorking:
case LinphonePresenceActivityWorship:
online_status = LinphoneStatusDoNotDisturb;
break;
case LinphonePresenceActivityAway:
case LinphonePresenceActivitySleeping:
online_status = LinphoneStatusAway;
break;
case LinphonePresenceActivityHoliday:
case LinphonePresenceActivityTravel:
case LinphonePresenceActivityVacation:
online_status = LinphoneStatusVacation;
break;
case LinphonePresenceActivityBusy:
case LinphonePresenceActivityLookingForWork:
case LinphonePresenceActivityPlaying:
case LinphonePresenceActivityShopping:
case LinphonePresenceActivityTV:
online_status = LinphoneStatusBusy;
break;
case LinphonePresenceActivityInTransit:
case LinphonePresenceActivitySteering:
online_status = LinphoneStatusBeRightBack;
break;
case LinphonePresenceActivityOnThePhone:
online_status = LinphoneStatusOnThePhone;
break;
case LinphonePresenceActivityOther:
case LinphonePresenceActivityPermanentAbsence:
online_status = LinphoneStatusMoved;
break;
case LinphonePresenceActivityUnknown:
break;
}
}
}
}
return online_status;
}
LinphonePresenceModel * linphone_friend_get_presence(LinphoneFriend *lf) {
return lf->presence;
}
void linphone_friend_set_presence(LinphoneFriend *lf, LinphonePresenceModel *model) {
if (lf->presence != NULL) {
linphone_presence_model_delete(lf->presence);
}
lf->presence = model;
}
BuddyInfo * linphone_friend_get_info(const LinphoneFriend *lf){
......
......@@ -19,9 +19,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef LINPHONEFRIEND_H_
#define LINPHONEFRIEND_H_
#include "linphonepresence.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @addtogroup buddy_list
* @{
......@@ -206,6 +210,10 @@ LINPHONE_PUBLIC void linphone_friend_done(LinphoneFriend *fr);
* @return #LinphoneOnlineStatus
*/
LinphoneOnlineStatus linphone_friend_get_status(const LinphoneFriend *lf);
LinphonePresenceModel * linphone_friend_get_presence(LinphoneFriend *lf);
void linphone_friend_set_presence(LinphoneFriend *lf, LinphonePresenceModel *presence);
BuddyInfo * linphone_friend_get_info(const LinphoneFriend *lf);
void linphone_friend_set_ref_key(LinphoneFriend *lf, const char *key);
const char *linphone_friend_get_ref_key(const LinphoneFriend *lf);
......
/*
linphonepresence.h
Copyright (C) 2010-2013 Belledonne Communications SARL
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef LINPHONEPRESENCE_H_
#define LINPHONEPRESENCE_H_
#ifdef __cplusplus
extern "C" {
#endif
/** Basic status as defined in section 4.1.4 of RFC 3863 */
typedef enum LinphonePresenceBasicStatus {
LinphonePresenceBasicStatusOpen,
LinphonePresenceBasicStatusClosed
} LinphonePresenceBasicStatus;
/** Activities as defined in section 3.2 of RFC 4480 */
typedef enum LinphonePresenceActivity {
LinphonePresenceActivityAppointment,
LinphonePresenceActivityAway,
LinphonePresenceActivityBreakfast,
LinphonePresenceActivityBusy,
LinphonePresenceActivityDinner,
LinphonePresenceActivityHoliday,
LinphonePresenceActivityInTransit,
LinphonePresenceActivityLookingForWork,
LinphonePresenceActivityLunch,
LinphonePresenceActivityMeal,
LinphonePresenceActivityMeeting,
LinphonePresenceActivityOnThePhone,
LinphonePresenceActivityOther,
LinphonePresenceActivityPerformance,
LinphonePresenceActivityPermanentAbsence,
LinphonePresenceActivityPlaying,
LinphonePresenceActivityPresentation,
LinphonePresenceActivityShopping,
LinphonePresenceActivitySleeping,
LinphonePresenceActivitySpectator,
LinphonePresenceActivitySteering,
LinphonePresenceActivityTravel,
LinphonePresenceActivityTV,
LinphonePresenceActivityUnknown,
LinphonePresenceActivityVacation,
LinphonePresenceActivityWorking,
LinphonePresenceActivityWorship
} LinphonePresenceActivity;
struct _LinphonePresenceModel;
typedef struct _LinphonePresenceModel LinphonePresenceModel;
LINPHONE_PUBLIC LinphonePresenceModel * linphone_presence_model_new(void);
LINPHONE_PUBLIC void linphone_presence_model_delete(LinphonePresenceModel *model);
LINPHONE_PUBLIC LinphonePresenceBasicStatus linphone_presence_model_get_basic_status(const LinphonePresenceModel *model);
LINPHONE_PUBLIC unsigned int linphone_presence_model_nb_activities(const LinphonePresenceModel *model);
LINPHONE_PUBLIC int linphone_presence_model_get_activity(const LinphonePresenceModel *model, unsigned int idx, LinphonePresenceActivity *activity, char **description);
#ifdef __cplusplus
}
#endif
#endif /* LINPHONEPRESENCE_H_ */
This diff is collapsed.
......@@ -290,7 +290,8 @@ SalPresenceStatus linphone_online_status_to_sal(LinphoneOnlineStatus os);
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_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, SalPresenceStatus status);
void linphone_notify_parse_presence(SalOp *op, const char *content_type, const char *content_subtype, const char *body, SalPresenceModel **result);
void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, SalPresenceModel *model);
void linphone_proxy_config_process_authentication_failure(LinphoneCore *lc, SalOp *op);
void linphone_subscription_answered(LinphoneCore *lc, SalOp *op);
......@@ -427,7 +428,7 @@ struct _LinphoneFriend{
SalOp *insub;
SalOp *outsub;
LinphoneSubscribePolicy pol;
LinphoneOnlineStatus status;
LinphonePresenceModel *presence;
struct _LinphoneCore *lc;
BuddyInfo *info;
char *refkey;
......
......@@ -292,6 +292,9 @@ typedef enum SalPresenceStatus{
SalPresenceOnVacation
}SalPresenceStatus;
struct _SalPresenceModel;
typedef struct _SalPresenceModel SalPresenceModel;
const char* sal_presence_status_to_string(const SalPresenceStatus status);
typedef enum SalReferStatus{
......@@ -355,7 +358,8 @@ typedef void (*SalOnSubscribeResponse)(SalOp *op, SalSubscribeStatus status, Sal
typedef void (*SalOnNotify)(SalOp *op, SalSubscribeStatus status, const char *event, const SalBody *body);
typedef void (*SalOnSubscribeReceived)(SalOp *salop, const char *event, const SalBody *body);
typedef void (*SalOnSubscribeClosed)(SalOp *salop);
typedef void (*SalOnNotifyPresence)(SalOp *op, SalSubscribeStatus ss, SalPresenceStatus status, const char *msg);
typedef void (*SalOnParsePresenceRequested)(SalOp *salop, const char *content_type, const char *content_subtype, const char *content, SalPresenceModel **result);
typedef void (*SalOnNotifyPresence)(SalOp *op, SalSubscribeStatus ss, SalPresenceModel *model, const char *msg);
typedef void (*SalOnSubscribePresenceReceived)(SalOp *salop, const char *from);
typedef void (*SalOnSubscribePresenceClosed)(SalOp *salop, const char *from);
typedef void (*SalOnPingReply)(SalOp *salop);
......@@ -393,6 +397,7 @@ typedef struct SalCallbacks{
SalOnNotify notify;
SalOnSubscribePresenceReceived subscribe_presence_received;
SalOnSubscribePresenceClosed subscribe_presence_closed;
SalOnParsePresenceRequested parse_presence_requested;
SalOnNotifyPresence notify_presence;
SalOnPingReply ping_reply;
SalOnAuthRequested auth_requested;
......
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