Use presence model to notify presence.

Use libxml2 to generate XML content.
This commit is contained in:
Ghislain MARY 2013-06-18 11:45:54 +02:00
parent 220c471369
commit 8c9c96218a
14 changed files with 861 additions and 505 deletions

View file

@ -488,6 +488,8 @@ void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs){
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.convert_presence_to_xml_requested==NULL)
ctx->callbacks.convert_presence_to_xml_requested=(SalOnConvertPresenceToXMLRequested)unimplemented_stub;
if (ctx->callbacks.notify_presence==NULL)
ctx->callbacks.notify_presence=(SalOnNotifyPresence)unimplemented_stub;
if (ctx->callbacks.subscribe_presence_received==NULL)

View file

@ -134,7 +134,7 @@ void sal_op_call_process_notify(SalOp *op, const belle_sip_request_event_t *even
SalAuthInfo* sal_auth_info_create(belle_sip_auth_event_t* event) ;
void sal_add_pending_auth(Sal *sal, SalOp *op);
void sal_remove_pending_auth(Sal *sal, SalOp *op);
void sal_add_presence_info(belle_sip_message_t *notify, SalPresenceStatus online_status);
void sal_add_presence_info(SalOp *op, belle_sip_message_t *notify, SalPresenceModel *presence);
belle_sip_response_t *sal_create_response_from_request(Sal *sal, belle_sip_request_t *req, int code);

View file

@ -18,404 +18,28 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sal_impl.h"
typedef enum {
PIDF = 0,
RFCxxxx = 1,
MSOLDPRES = 2
} presence_type_t;
/*
* REVISIT: this static variable forces every dialog to use the same presence description type depending
* on what is received on a single dialog...
*/
static presence_type_t presence_style = PIDF;
static void mk_presence_body (const SalPresenceStatus online_status, const char *contact_info,
char *buf, size_t buflen, presence_type_t ptype) {
switch (ptype) {
case RFCxxxx: {
/* definition from http://msdn.microsoft.com/en-us/library/cc246202%28PROT.10%29.aspx */
int atom_id = 1000;
if (online_status==SalPresenceOnline)
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s\" priority=\"0.800000\">\n\
<status status=\"open\" />\n\
<msnsubstatus substatus=\"online\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
else if (online_status == SalPresenceBusy ||
online_status == SalPresenceDonotdisturb)
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s\" priority=\"0.800000\">\n\
<status status=\"inuse\" />\n\
<msnsubstatus substatus=\"busy\" />\n\
</address>\n\
</atom>\n</presence>", contact_info, atom_id, contact_info);
}
else if (online_status==SalPresenceBerightback)
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s\" priority=\"0.800000\">\n\
<status status=\"open\" />\n\
<msnsubstatus substatus=\"berightback\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
else if (online_status == SalPresenceAway ||
online_status == SalPresenceMoved)
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s\" priority=\"0.800000\">\n\
<status status=\"open\" />\n\
<msnsubstatus substatus=\"away\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
else if (online_status==SalPresenceOnthephone)
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s\" priority=\"0.800000\">\n\
<status status=\"inuse\" />\n\
<msnsubstatus substatus=\"onthephone\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
else if (online_status==SalPresenceOuttolunch)
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s\" priority=\"0.800000\">\n\
<status status=\"open\" />\n\
<msnsubstatus substatus=\"outtolunch\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
else
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s\" priority=\"0.800000\">\n\
<status status=\"closed\" />\n\
<msnsubstatus substatus=\"away\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
break;
}
case MSOLDPRES: {
/* Couldn't find schema http://schemas.microsoft.com/2002/09/sip/presence
* so messages format has been taken from Communigate that can send notify
* requests with this schema
*/
int atom_id = 1000;
if (online_status==SalPresenceOnline)
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence SYSTEM \"http://schemas.microsoft.com/2002/09/sip/presence\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s\">\n\
<status status=\"open\" />\n\
<msnsubstatus substatus=\"online\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
else if (online_status == SalPresenceBusy ||
online_status == SalPresenceDonotdisturb)
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence SYSTEM \"http://schemas.microsoft.com/2002/09/sip/presence\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s\">\n\
<status status=\"inuse\" />\n\
<msnsubstatus substatus=\"busy\" />\n\
</address>\n\
</atom>\n</presence>", contact_info, atom_id, contact_info);
}
else if (online_status==SalPresenceBerightback)
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence SYSTEM \"http://schemas.microsoft.com/2002/09/sip/presence\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s\">\n\
<status status=\"inactive\" />\n\
<msnsubstatus substatus=\"berightback\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
else if (online_status == SalPresenceAway ||
online_status == SalPresenceMoved)
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence SYSTEM \"http://schemas.microsoft.com/2002/09/sip/presence\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s\">\n\
<status status=\"inactive\" />\n\
<msnsubstatus substatus=\"idle\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
else if (online_status==SalPresenceOnthephone)
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence SYSTEM \"http://schemas.microsoft.com/2002/09/sip/presence\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s\">\n\
<status status=\"inuse\" />\n\
<msnsubstatus substatus=\"onthephone\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
else if (online_status==SalPresenceOuttolunch)
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence SYSTEM \"http://schemas.microsoft.com/2002/09/sip/presence\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s\">\n\
<status status=\"inactive\" />\n\
<msnsubstatus substatus=\"outtolunch\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
else
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence SYSTEM \"http://schemas.microsoft.com/2002/09/sip/presence\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s\">\n\
<status status=\"closed\" />\n\
<msnsubstatus substatus=\"offline\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
break;
}
default: { /* use pidf+xml as default format, rfc4479, rfc4480, rfc3863 */
if (online_status==SalPresenceOnline)
{
snprintf(buf, buflen, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" \
xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\" \
xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" \
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status><basic>open</basic></status>\n\
<contact priority=\"0.8\">%s</contact>\n\
</tuple>\n\
</presence>",
contact_info, contact_info);
}
else if (online_status == SalPresenceBusy ||
online_status == SalPresenceDonotdisturb)
{
snprintf(buf, buflen, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" \
xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\" \
xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" \
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status><basic>open</basic></status>\n\
<contact priority=\"0.8\">%s</contact>\n\
</tuple>\n\
<dm:person id=\"sg89aep\">\n\
<rpid:activities><rpid:busy/></rpid:activities>\n\
</dm:person>\n\
</presence>",
contact_info, contact_info);
}
else if (online_status==SalPresenceBerightback)
{
snprintf(buf, buflen, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" \
xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\" \
xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" \
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status><basic>open</basic></status>\n\
<contact priority=\"0.8\">%s</contact>\n\
</tuple>\n\
<dm:person id=\"sg89aep\">\n\
<rpid:activities><rpid:in-transit/></rpid:activities>\n\
</dm:person>\n\
</presence>",
contact_info, contact_info);
}
else if (online_status == SalPresenceAway ||
online_status == SalPresenceMoved)
{
snprintf(buf, buflen, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" \
xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\" \
xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" \
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status><basic>open</basic></status>\n\
<contact priority=\"0.8\">%s</contact>\n\
</tuple>\n\
<dm:person id=\"sg89aep\">\n\
<rpid:activities><rpid:away/></rpid:activities>\n\
</dm:person>\n\
</presence>",
contact_info, contact_info);
}
else if (online_status == SalPresenceOnVacation)
{
snprintf(buf, buflen, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" \
xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\" \
xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" \
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status><basic>open</basic></status>\n\
<contact priority=\"0.8\">%s</contact>\n\
</tuple>\n\
<dm:person id=\"sg89aep\">\n\
<rpid:activities><rpid:vacation/></rpid:activities>\n\
</dm:person>\n\
</presence>",
contact_info, contact_info);
}
else if (online_status==SalPresenceOnthephone)
{
snprintf(buf, buflen, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" \
xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\" \
xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" \
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status><basic>open</basic></status>\n\
<contact priority=\"0.8\">%s</contact>\n\
</tuple>\n\
<dm:person id=\"sg89aep\">\n\
<rpid:activities><rpid:on-the-phone/></rpid:activities>\n\
</dm:person>\n\
</presence>",
contact_info, contact_info);
}
else if (online_status==SalPresenceOuttolunch)
{
snprintf(buf, buflen, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" \
xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\" \
xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" \
entity=\"%s\">\n\
<tuple id=\"7777\">\n\
<status><basic>open</basic></status>\n\
<contact priority=\"0.8\">%s</contact>\n\
</tuple>\n\
<dm:person id=\"78787878\">\n\
<rpid:activities><rpid:lunch/></rpid:activities>\n\
<rpid:note>Out to lunch</rpid:note> \n\
</dm:person>\n\
</presence>",
contact_info, contact_info);
}
else
{
snprintf(buf, buflen, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" \
xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\" \
xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" \
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status><basic>closed</basic></status>\n\
<contact priority=\"0.8\">%s</contact>\n\
</tuple>\n\
</presence>\n", contact_info, contact_info);
}
break;
}
} // switch
}
void sal_add_presence_info(belle_sip_message_t *notify, SalPresenceStatus online_status) {
char buf[1000];
void sal_add_presence_info(SalOp *op, belle_sip_message_t *notify, SalPresenceModel *presence) {
char *contact_info;
char *content = NULL;
size_t content_length;
belle_sip_header_from_t *from=belle_sip_message_get_header_by_type(notify,belle_sip_header_from_t);
contact_info=belle_sip_uri_to_string(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from)));
mk_presence_body (online_status, contact_info, buf, sizeof (buf), presence_style);
op->base.root->callbacks.convert_presence_to_xml_requested(op, presence, contact_info, &content);
if (content == NULL) {
ms_free(contact_info);
return;
}
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_CONTENT_TYPE);
belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify)
,BELLE_SIP_HEADER(belle_sip_header_content_type_create("application",presence_style?"xpidf+xml":"pidf+xml")));
,BELLE_SIP_HEADER(belle_sip_header_content_type_create("application","pidf+xml")));
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_CONTENT_LENGTH);
belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify)
,BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_length=strlen(buf))));
belle_sip_message_set_body(BELLE_SIP_MESSAGE(notify),buf,content_length);
,BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_length=strlen(content))));
belle_sip_message_set_body(BELLE_SIP_MESSAGE(notify),content,content_length);
ms_free(contact_info);
}
@ -627,9 +251,9 @@ static belle_sip_request_t *create_presence_notify(SalOp *op){
return notify;
}
int sal_notify_presence(SalOp *op, SalPresenceStatus status, const char *status_message){
int sal_notify_presence(SalOp *op, SalPresenceModel *presence){
belle_sip_request_t* notify=create_presence_notify(op);
sal_add_presence_info(BELLE_SIP_MESSAGE(notify),status); /*FIXME, what about expires ??*/
sal_add_presence_info(op,BELLE_SIP_MESSAGE(notify),presence); /*FIXME, what about expires ??*/
belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify)
,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE,600)));
return sal_op_send_request(op,notify);
@ -637,7 +261,7 @@ int sal_notify_presence(SalOp *op, SalPresenceStatus status, const char *status_
int sal_notify_presence_close(SalOp *op){
belle_sip_request_t* notify=create_presence_notify(op);
sal_add_presence_info(BELLE_SIP_MESSAGE(notify),SalPresenceOffline); /*FIXME, what about expires ??*/
sal_add_presence_info(op,BELLE_SIP_MESSAGE(notify),NULL); /*FIXME, what about expires ??*/
belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify)
,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,-1)));
return sal_op_send_request(op,notify);

View file

@ -30,7 +30,7 @@ static void publish_refresher_listener ( const belle_sip_refresher_t* refresher
}
/*presence publish */
int sal_publish_presence(SalOp *op, const char *from, const char *to, SalPresenceStatus status){
int sal_publish_presence(SalOp *op, const char *from, const char *to, SalPresenceModel *presence){
belle_sip_request_t *req=NULL;
if(!op->refresher || !belle_sip_refresher_get_transaction(op->refresher)) {
if (from)
@ -41,14 +41,13 @@ int sal_publish_presence(SalOp *op, const char *from, const char *to, SalPresenc
op->type=SalOpPublish;
req=sal_op_build_request(op,"PUBLISH");
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create("Event","presence"));
sal_add_presence_info(BELLE_SIP_MESSAGE(req),status);
sal_add_presence_info(op,BELLE_SIP_MESSAGE(req),presence);
return sal_op_send_and_create_refresher(op,req,600,publish_refresher_listener);
} else {
/*update status*/
/*update presence status*/
const belle_sip_client_transaction_t* last_publish_trans=belle_sip_refresher_get_transaction(op->refresher);
belle_sip_request_t* last_publish=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(last_publish_trans));
/*update status*/
sal_add_presence_info(BELLE_SIP_MESSAGE(last_publish),status);
sal_add_presence_info(op,BELLE_SIP_MESSAGE(last_publish),presence);
return belle_sip_refresher_refresh(op->refresher,BELLE_SIP_REFRESHER_REUSE_EXPIRES);
}
}

View file

@ -219,21 +219,31 @@ static void call_received(SalOp *h){
bool_t prevent_colliding_calls=lp_config_get_int(lc->config,"sip","prevent_colliding_calls",TRUE);
/* first check if we can answer successfully to this invite */
if (lc->presence_mode==LinphoneStatusBusy ||
lc->presence_mode==LinphoneStatusOffline ||
lc->presence_mode==LinphoneStatusDoNotDisturb ||
lc->presence_mode==LinphoneStatusMoved){
if (lc->presence_mode==LinphoneStatusBusy )
sal_call_decline(h,SalReasonBusy,NULL);
else if (lc->presence_mode==LinphoneStatusOffline)
sal_call_decline(h,SalReasonTemporarilyUnavailable,NULL);
else if (lc->presence_mode==LinphoneStatusDoNotDisturb)
sal_call_decline(h,SalReasonTemporarilyUnavailable,NULL);
else if (lc->alt_contact!=NULL && lc->presence_mode==LinphoneStatusMoved)
sal_call_decline(h,SalReasonRedirect,lc->alt_contact);
sal_op_release(h);
return;
if (linphone_presence_model_get_basic_status(lc->presence_model) == LinphonePresenceBasicStatusClosed) {
LinphonePresenceActivity activity = LinphonePresenceActivityOffline;
if (linphone_presence_model_get_activity(lc->presence_model, &activity, NULL)) {
switch (activity) {
case LinphonePresenceActivityBusy:
sal_call_decline(h,SalReasonBusy,NULL);
break;
case LinphonePresenceActivityAppointment:
case LinphonePresenceActivityMeeting:
case LinphonePresenceActivityOffline:
case LinphonePresenceActivityWorship:
sal_call_decline(h,SalReasonTemporarilyUnavailable,NULL);
break;
case LinphonePresenceActivityPermanentAbsence:
if (lc->alt_contact != NULL)
sal_call_decline(h,SalReasonRedirect,lc->alt_contact);
break;
default:
break;
}
sal_op_release(h);
return;
}
}
if (!linphone_core_can_we_add_call(lc)){/*busy*/
sal_call_decline(h,SalReasonBusy,NULL);
sal_op_release(h);
@ -881,6 +891,10 @@ static void parse_presence_requested(SalOp *op, const char *content_type, const
linphone_notify_parse_presence(op, content_type, content_subtype, body, result);
}
static void convert_presence_to_xml_requested(SalOp *op, SalPresenceModel *presence, const char *contact, char **content) {
linphone_notify_convert_presence_to_xml(op, presence, contact, content);
}
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,model);
@ -1090,6 +1104,7 @@ SalCallbacks linphone_sal_callbacks={
subscribe_presence_received,
subscribe_presence_closed,
parse_presence_requested,
convert_presence_to_xml_requested,
notify_presence,
ping_reply,
auth_requested,

View file

@ -226,57 +226,12 @@ int linphone_friend_set_inc_subscribe_policy(LinphoneFriend *fr, LinphoneSubscri
return 0;
}
SalPresenceStatus linphone_online_status_to_sal(LinphoneOnlineStatus os){
switch(os){
case LinphoneStatusOffline:
return SalPresenceOffline;
break;
case LinphoneStatusOnline:
return SalPresenceOnline;
break;
case LinphoneStatusBusy:
return SalPresenceBusy;
break;
case LinphoneStatusBeRightBack:
return SalPresenceBerightback;
break;
case LinphoneStatusAway:
return SalPresenceAway;
break;
case LinphoneStatusOnThePhone:
return SalPresenceOnthephone;
break;
case LinphoneStatusOutToLunch:
return SalPresenceOuttolunch;
break;
case LinphoneStatusDoNotDisturb:
return SalPresenceDonotdisturb;
break;
case LinphoneStatusMoved:
return SalPresenceMoved;
break;
case LinphoneStatusAltService:
return SalPresenceAltService;
break;
case LinphoneStatusPending:
return SalPresenceOffline;
break;
case LinphoneStatusVacation:
return SalPresenceOnVacation;
break;
default:
return SalPresenceOffline;
break;
}
return SalPresenceOffline;
}
void linphone_friend_notify(LinphoneFriend *lf, LinphoneOnlineStatus os){
void linphone_friend_notify(LinphoneFriend *lf, LinphonePresenceModel *presence){
char *addr=linphone_address_as_string(linphone_friend_get_address(lf));
ms_message("Want to notify %s, insub=%p",addr,lf->insub);
ms_free(addr);
if (lf->insub!=NULL){
sal_notify_presence(lf->insub,linphone_online_status_to_sal(os),NULL);
sal_notify_presence(lf->insub,(SalPresenceModel *)presence);
}
}
@ -343,7 +298,7 @@ LinphoneOnlineStatus linphone_friend_get_status(const LinphoneFriend *lf){
nb_activities = 1;
}
if (nb_activities == 1) {
err = linphone_presence_model_get_activity(lf->presence, 0, &activity, &activity_description);
err = linphone_presence_model_get_activity(lf->presence, &activity, &activity_description);
if (err == 0) {
switch (activity) {
case LinphonePresenceActivityBreakfast:
@ -389,6 +344,12 @@ LinphoneOnlineStatus linphone_friend_get_status(const LinphoneFriend *lf){
online_status = LinphoneStatusMoved;
break;
case LinphonePresenceActivityUnknown:
/* Rely on the basic status information. */
break;
case LinphonePresenceActivityOnline:
case LinphonePresenceActivityOffline:
/* Should not happen! */
ms_warning("LinphonePresenceActivityOnline or LinphonePresenceActivityOffline should not happen here!");
break;
}
}
@ -414,27 +375,30 @@ BuddyInfo * linphone_friend_get_info(const LinphoneFriend *lf){
}
void linphone_friend_apply(LinphoneFriend *fr, LinphoneCore *lc){
LinphonePresenceModel *model;
if (fr->uri==NULL) {
ms_warning("No sip url defined.");
return;
}
linphone_core_write_friends_config(lc);
if (fr->inc_subscribe_pending){
switch(fr->pol){
case LinphoneSPWait:
linphone_friend_notify(fr,LinphoneStatusPending);
model = linphone_presence_model_new_with_activity(LinphonePresenceActivityOther, "Waiting for user acceptance");
linphone_friend_notify(fr,model);
linphone_presence_model_delete(model);
break;
case LinphoneSPAccept:
if (fr->lc!=NULL)
{
linphone_friend_notify(fr,fr->lc->presence_mode);
linphone_friend_notify(fr,fr->lc->presence_model);
}
break;
case LinphoneSPDeny:
linphone_friend_notify(fr,LinphoneStatusOffline);
linphone_friend_notify(fr,NULL);
break;
}
fr->inc_subscribe_pending=FALSE;

View file

@ -412,8 +412,10 @@ static int select_random_port(LinphoneCore *lc, SalStreamType type) {
}
static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from, LinphoneAddress *to){
LinphonePresenceModel *model;
int port_offset;
int min_port, max_port;
call->magic=linphone_call_magic;
call->refcnt=1;
call->state=LinphoneCallIdle;
@ -422,7 +424,9 @@ static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from,
call->media_start_time=0;
call->log=linphone_call_log_new(call, from, to);
call->owns_call_log=TRUE;
linphone_core_notify_all_friends(call->core,LinphoneStatusOnThePhone);
model = linphone_presence_model_new_with_activity(LinphonePresenceActivityOnThePhone, NULL);
linphone_core_notify_all_friends(call->core,model);
linphone_presence_model_delete(model);
linphone_core_get_audio_port_range(call->core, &min_port, &max_port);
if (min_port == max_port) {
/* Used fixed RTP audio port. */
@ -630,7 +634,7 @@ static void linphone_call_set_terminated(LinphoneCall *call){
}
if (ms_list_size(lc->calls)==0)
linphone_core_notify_all_friends(lc,lc->presence_mode);
linphone_core_notify_all_friends(lc,lc->presence_model);
linphone_core_conference_check_uninit(lc);
if (call->ringing_beep){

View file

@ -1337,7 +1337,7 @@ static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vta
sip_config_read(lc); /* this will start eXosip*/
video_config_read(lc);
//autoreplier_config_init(&lc->autoreplier_conf);
lc->presence_mode=LinphoneStatusOnline;
lc->presence_model=linphone_presence_model_new_with_activity(LinphonePresenceActivityOnline, NULL);
misc_config_read(lc);
ui_config_read(lc);
#ifdef TUNNEL_ENABLED
@ -3568,12 +3568,12 @@ LinphoneCall *linphone_core_get_call_by_remote_address(LinphoneCore *lc, const c
}
int linphone_core_send_publish(LinphoneCore *lc,
LinphoneOnlineStatus presence_mode)
LinphonePresenceModel *presence)
{
const MSList *elem;
for (elem=linphone_core_get_proxy_config_list(lc);elem!=NULL;elem=ms_list_next(elem)){
LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data;
if (cfg->publish) linphone_proxy_config_send_publish(cfg,presence_mode);
if (cfg->publish) linphone_proxy_config_send_publish(cfg,presence);
}
return 0;
}
@ -3642,10 +3642,59 @@ void linphone_core_set_delayed_timeout(LinphoneCore *lc, int seconds){
lc->sip_conf.delayed_timeout=seconds;
}
void linphone_core_set_presence_info(LinphoneCore *lc,int minutes_away,
const char *contact,
LinphoneOnlineStatus presence_mode)
{
void linphone_core_set_presence_info(LinphoneCore *lc, int minutes_away, const char *contact, LinphoneOnlineStatus os) {
LinphonePresenceModel *presence = NULL;
char *description = NULL;
LinphonePresenceActivity activity = LinphonePresenceActivityUnknown;
switch (os) {
case LinphoneStatusOffline:
activity = LinphonePresenceActivityOffline;
break;
case LinphoneStatusOnline:
activity = LinphonePresenceActivityOnline;
break;
case LinphoneStatusBusy:
activity = LinphonePresenceActivityBusy;
break;
case LinphoneStatusBeRightBack:
activity = LinphonePresenceActivityInTransit;
break;
case LinphoneStatusAway:
activity = LinphonePresenceActivityAway;
break;
case LinphoneStatusOnThePhone:
activity = LinphonePresenceActivityOnThePhone;
break;
case LinphoneStatusOutToLunch:
activity = LinphonePresenceActivityLunch;
break;
case LinphoneStatusDoNotDisturb:
activity = LinphonePresenceActivityBusy;
description = "Do not disturb";
break;
case LinphoneStatusMoved:
activity = LinphonePresenceActivityPermanentAbsence;
break;
case LinphoneStatusAltService:
activity = LinphonePresenceActivityBusy;
description = "Using another messaging service";
break;
case LinphoneStatusPending:
activity = LinphonePresenceActivityOther;
description = "Waiting for user acceptance";
break;
case LinphoneStatusVacation:
activity = LinphonePresenceActivityVacation;
break;
case LinphoneStatusEnd:
ms_warning("Invalid status LinphoneStatusEnd");
return;
}
presence = linphone_presence_model_new_with_activity(activity, description);
linphone_core_set_presence_model(lc, minutes_away, contact, presence);
}
void linphone_core_set_presence_model(LinphoneCore *lc, int minutes_away, const char *contact, LinphonePresenceModel *presence) {
if (minutes_away>0) lc->minutes_away=minutes_away;
if (lc->alt_contact!=NULL) {
@ -3653,20 +3702,75 @@ void linphone_core_set_presence_info(LinphoneCore *lc,int minutes_away,
lc->alt_contact=NULL;
}
if (contact) lc->alt_contact=ms_strdup(contact);
if (lc->presence_mode!=presence_mode){
linphone_core_notify_all_friends(lc,presence_mode);
if (!linphone_presence_model_equals(lc->presence_model,presence)){
linphone_core_notify_all_friends(lc,presence);
/*
Improve the use of all LINPHONE_STATUS available.
!TODO Do not mix "presence status" with "answer status code"..
Use correct parameter to follow sip_if_match/sip_etag.
*/
linphone_core_send_publish(lc,presence_mode);
linphone_core_send_publish(lc,presence);
}
if ((lc->presence_model != NULL) && (lc->presence_model != presence)) {
linphone_presence_model_delete(lc->presence_model);
lc->presence_model = presence;
}
lc->presence_mode=presence_mode;
}
LinphoneOnlineStatus linphone_core_get_presence_info(const LinphoneCore *lc){
return lc->presence_mode;
LinphonePresenceActivity activity = LinphonePresenceActivityOffline;
char *description = NULL;
if ((lc->presence_model == NULL)
|| (linphone_presence_model_get_activity(lc->presence_model, &activity, &description) < 0))
return LinphoneStatusOffline;
switch (activity) {
case LinphonePresenceActivityOffline:
return LinphoneStatusOffline;
case LinphonePresenceActivityOnline:
return LinphoneStatusOnline;
case LinphonePresenceActivityBusy:
if (description != NULL) {
if (strcmp(description, "Do not disturb") == 0)
return LinphoneStatusDoNotDisturb;
else if (strcmp(description, "Using another messaging service") == 0)
return LinphoneStatusAltService;
}
return LinphoneStatusBusy;
case LinphonePresenceActivityInTransit:
case LinphonePresenceActivitySteering:
return LinphoneStatusBeRightBack;
case LinphonePresenceActivityAway:
return LinphoneStatusAway;
case LinphonePresenceActivityOnThePhone:
return LinphoneStatusOnThePhone;
case LinphonePresenceActivityBreakfast:
case LinphonePresenceActivityDinner:
case LinphonePresenceActivityLunch:
case LinphonePresenceActivityMeal:
return LinphoneStatusOutToLunch;
case LinphonePresenceActivityPermanentAbsence:
return LinphoneStatusMoved;
case LinphonePresenceActivityOther:
if (description != NULL) {
if (strcmp(description, "Waiting for user acceptance") == 0)
return LinphoneStatusPending;
}
return LinphoneStatusBusy;
case LinphonePresenceActivityVacation:
return LinphoneStatusVacation;
case LinphonePresenceActivityAppointment:
case LinphonePresenceActivityMeeting:
case LinphonePresenceActivityWorship:
return LinphoneStatusDoNotDisturb;
default:
return LinphoneStatusBusy;
}
}
LinphonePresenceModel * linphone_core_get_presence_model(const LinphoneCore *lc) {
return lc->presence_model;
}
/**

View file

@ -236,13 +236,30 @@ const char *linphone_online_status_to_string(LinphoneOnlineStatus ss);
* @param os #LinphoneOnlineStatus
*/
LINPHONE_PUBLIC void linphone_core_set_presence_info(LinphoneCore *lc,int minutes_away,const char *alternative_contact,LinphoneOnlineStatus os);
/**
* get my presence status
* Set my presence status
* @param lc #LinphoneCore object
* @param minutes_away how long in away
* @param alternative_contact sip uri used to redirect call in state #LinphoneStatusMoved
* @param presence #LinphonePresenceModel
*/
LINPHONE_PUBLIC void linphone_core_set_presence_model(LinphoneCore *lc, int minutes_away, const char *alternative_contact, LinphonePresenceModel *presence);
/**
* Get my presence status
* @param lc #LinphoneCore object
* @return #LinphoneOnlineStatus
*/
LinphoneOnlineStatus linphone_core_get_presence_info(const LinphoneCore *lc);
/**
* Get my presence status
* @param lc #LinphoneCore object
* @return #LinphonePresenceModel
*/
LinphonePresenceModel * linphone_core_get_presence_model(const LinphoneCore *lc);
void linphone_core_interpret_friend_uri(LinphoneCore *lc, const char *uri, char **result);
/**
* Add a friend to the current buddy list, if \link linphone_friend_enable_subscribes() subscription attribute \endlink is set, a SIP SUBSCRIBE message is sent.
@ -272,7 +289,7 @@ LINPHONE_PUBLIC const MSList * linphone_core_get_friend_list(const LinphoneCore
* @param lc #LinphoneCore object
* @param os #LinphoneOnlineStatus to notify
* */
void linphone_core_notify_all_friends(LinphoneCore *lc, LinphoneOnlineStatus os);
void linphone_core_notify_all_friends(LinphoneCore *lc, LinphonePresenceModel *presence);
LinphoneFriend *linphone_core_get_friend_by_address(const LinphoneCore *lc, const char *addr);
LinphoneFriend *linphone_core_get_friend_by_ref_key(const LinphoneCore *lc, const char *key);

View file

@ -33,6 +33,8 @@ typedef enum LinphonePresenceBasicStatus {
/** Activities as defined in section 3.2 of RFC 4480 */
typedef enum LinphonePresenceActivity {
LinphonePresenceActivityOffline,
LinphonePresenceActivityOnline,
LinphonePresenceActivityAppointment,
LinphonePresenceActivityAway,
LinphonePresenceActivityBreakfast,
@ -67,10 +69,17 @@ typedef struct _LinphonePresenceModel LinphonePresenceModel;
LINPHONE_PUBLIC LinphonePresenceModel * linphone_presence_model_new(void);
LINPHONE_PUBLIC LinphonePresenceModel * linphone_presence_model_new_with_activity(LinphonePresenceActivity activity, const char *description);
LINPHONE_PUBLIC LinphonePresenceModel * linphone_presence_model_new_with_activity_and_note(LinphonePresenceActivity activity, const char *description, const char *note, const char *lang);
LINPHONE_PUBLIC void linphone_presence_model_delete(LinphonePresenceModel *model);
LINPHONE_PUBLIC bool_t linphone_presence_model_equals(const LinphonePresenceModel *m1, const LinphonePresenceModel *m2);
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);
LINPHONE_PUBLIC int linphone_presence_model_get_nth_activity(const LinphonePresenceModel *model, unsigned int idx, LinphonePresenceActivity *activity, char **description);
LINPHONE_PUBLIC int linphone_presence_model_get_activity(const LinphonePresenceModel *model, LinphonePresenceActivity *activity, char **description);
LINPHONE_PUBLIC int linphone_presence_model_set_activity(LinphonePresenceModel *model, LinphonePresenceActivity activity, const char *description);
LINPHONE_PUBLIC const char * linphone_presence_model_get_note(const LinphonePresenceModel *model, const char *lang);
LINPHONE_PUBLIC int linphone_presence_model_set_note(LinphonePresenceModel *model, const char *note, const char *lang);
#ifdef __cplusplus

View file

@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "linphonecore.h"
#include "private.h"
#include <libxml/xmlreader.h>
#include <libxml/xmlwriter.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
@ -41,6 +42,9 @@ struct _LinphonePresenceNote {
struct _LinphonePresenceService {
char *id;
LinphonePresenceBasicStatus status;
char *contact;
MSList *notes; /**< A list of _LinphonePresenceNote structures. */
time_t timestamp;
};
struct _LinphonePresenceActivity {
@ -107,6 +111,30 @@ static void xmlparsing_genericxml_error(void *ctx, const char *fmt, ...) {
va_end(args);
}
static char presence_id_valid_characters[] = "0123456789abcdefghijklmnopqrstuvwxyz";
static char * generate_presence_id(void) {
char id[7];
int i;
for (i = 0; i < 6; i++) {
id[i] = presence_id_valid_characters[random() % sizeof(presence_id_valid_characters)];
}
id[6] = '\0';
return ms_strdup(id);
}
static const char * presence_basic_status_to_string(LinphonePresenceBasicStatus basic_status) {
switch (basic_status) {
case LinphonePresenceBasicStatusOpen:
return "open";
case LinphonePresenceBasicStatusClosed:
default:
return "closed";
}
}
static struct _LinphonePresenceNote * presence_note_new(const char *content, const char *lang) {
struct _LinphonePresenceNote * note = ms_new0(struct _LinphonePresenceNote, 1);
note->content = ms_strdup(content);
@ -130,6 +158,7 @@ static struct _LinphonePresenceService * presence_service_new(const char *id, Li
service->id = ms_strdup(id);
}
service->status = status;
service->timestamp = time(NULL);
return service;
}
@ -137,9 +166,26 @@ static void presence_service_delete(struct _LinphonePresenceService *service) {
if (service->id != NULL) {
ms_free(service->id);
}
if (service->contact != NULL) {
ms_free(service->contact);
}
ms_list_for_each(service->notes, (MSIterateFunc)presence_service_delete);
ms_list_free(service->notes);
ms_free(service);
};
static void presence_service_set_timestamp(struct _LinphonePresenceService *service, time_t timestamp) {
service->timestamp = timestamp;
}
static void presence_service_set_contact(struct _LinphonePresenceService *service, const char *contact) {
service->contact = ms_strdup(contact);
}
static void presence_service_add_note(struct _LinphonePresenceService *service, struct _LinphonePresenceNote *note) {
service->notes = ms_list_append(service->notes, note);
}
static struct _LinphonePresenceActivity * presence_activity_new(LinphonePresenceActivity activity, const char *description) {
struct _LinphonePresenceActivity *act = ms_new0(struct _LinphonePresenceActivity, 1);
act->activity = activity;
@ -174,18 +220,29 @@ static time_t parse_timestamp(const char *timestamp) {
return seconds - timezone;
}
static struct _LinphonePresencePerson * presence_person_new(const char *id, const char *timestamp) {
static char * timestamp_to_string(time_t timestamp) {
char timestamp_str[22];
struct tm *ret;
#ifndef WIN32
struct tm gmt;
ret = gmtime_r(&timestamp,&gmt);
#else
ret = gmtime(&curtime);
#endif
snprintf(timestamp_str, sizeof(timestamp_str), "%4d-%02d-%02dT%02d:%02d:%02dZ",
ret->tm_year + 1900, ret->tm_mon + 1, ret->tm_mday, ret->tm_hour, ret->tm_min, ret->tm_sec);
return ms_strdup(timestamp_str);
}
static struct _LinphonePresencePerson * presence_person_new(const char *id, time_t timestamp) {
struct _LinphonePresencePerson *person = ms_new0(struct _LinphonePresencePerson, 1);
if (id != NULL) {
person->id = ms_strdup(id);
}
if (timestamp != NULL) {
person->timestamp = parse_timestamp(timestamp);
if (person->timestamp == ((time_t)-1))
person->timestamp = time(NULL);
} else {
if (person->timestamp == ((time_t)-1))
person->timestamp = time(NULL);
}
else
person->timestamp = timestamp;
return person;
}
@ -214,6 +271,11 @@ static void presence_person_add_note(struct _LinphonePresencePerson *person, str
person->notes = ms_list_append(person->notes, note);
}
static void presence_person_clear_activities(struct _LinphonePresencePerson *person) {
ms_list_for_each(person->activities, (MSIterateFunc)presence_activity_delete);
ms_list_free(person->activities);
}
static void presence_model_add_service(LinphonePresenceModel *model, struct _LinphonePresenceService *service) {
model->services = ms_list_append(model->services, service);
}
@ -226,17 +288,151 @@ static void presence_model_add_note(LinphonePresenceModel *model, struct _Linpho
model->notes = ms_list_append(model->notes, note);
}
static int presence_model_set_basic_status(LinphonePresenceModel *model, LinphonePresenceBasicStatus basic_status) {
struct _LinphonePresenceService *service;
char *id;
if (ms_list_size(model->services) > 0) {
ms_list_for_each(model->services, (MSIterateFunc)presence_service_delete);
ms_list_free(model->services);
}
id = generate_presence_id();
service = presence_service_new(id, basic_status);
ms_free(id);
if (service == NULL) return -1;
presence_model_add_service(model, service);
return 0;
}
static void presence_model_clear_activities(LinphonePresenceModel *model) {
ms_list_for_each(model->persons, (MSIterateFunc)presence_person_clear_activities);
}
static int presence_model_add_activity(LinphonePresenceModel *model, LinphonePresenceActivity activity, const char *description) {
char *id = NULL;
struct _LinphonePresencePerson *person = NULL;
struct _LinphonePresenceActivity *act = NULL;
/* Do not add activity for special cases Offline and Online. */
if ((activity == LinphonePresenceActivityOffline) || (activity == LinphonePresenceActivityOnline))
return 0;
if (ms_list_size(model->persons) == 0) {
/* There is no person in the presence model, add one. */
id = generate_presence_id();
person = presence_person_new(id, time(NULL));
if (id != NULL) ms_free(id);
if (person == NULL)
return -1;
presence_model_add_person(model, person);
} else {
/* Add the activity to the first person in the model. */
person = (struct _LinphonePresencePerson *)ms_list_nth_data(model->persons, 0);
}
act = presence_activity_new(activity, description);
if (act == NULL)
return -1;
presence_person_add_activity(person, act);
return 0;
}
static void presence_model_find_open_basic_status(struct _LinphonePresenceService *service, LinphonePresenceBasicStatus *status) {
if (service->status == LinphonePresenceBasicStatusOpen) {
*status = LinphonePresenceBasicStatusOpen;
}
}
static bool_t presence_service_equals(const struct _LinphonePresenceService *s1, const struct _LinphonePresenceService *s2) {
if (s1->status != s2->status)
return FALSE;
return TRUE;
}
static bool_t presence_note_equals(const struct _LinphonePresenceNote *n1, const struct _LinphonePresenceNote *n2) {
if (((n1->lang == NULL) && (n2->lang != NULL))
|| ((n1->lang != NULL) && (n2->lang == NULL)))
return FALSE;
if (strcmp(n1->content, n2->content) != 0)
return FALSE;
if ((n1->lang != NULL) && (n2->lang != NULL)) {
if (strcmp(n1->lang, n2->lang) != 0)
return FALSE;
}
return TRUE;
}
static bool_t presence_activity_equals(const struct _LinphonePresenceActivity *a1, const struct _LinphonePresenceActivity *a2) {
if (((a1->description == NULL) && (a2->description != NULL))
|| ((a1->description != NULL) && (a2->description == NULL)))
return FALSE;
if (a1->activity != a2->activity)
return FALSE;
if ((a1->description != NULL) && (a2->description != NULL)) {
if (strcmp(a1->description, a2->description) != 0)
return FALSE;
}
return TRUE;
}
static bool_t presence_person_equals(const struct _LinphonePresencePerson *p1, const struct _LinphonePresencePerson *p2) {
int nb;
int i;
if ((ms_list_size(p1->activities) != ms_list_size(p2->activities))
|| (ms_list_size(p1->activities_notes) != ms_list_size(p2->activities_notes))
|| (ms_list_size(p1->notes) != ms_list_size(p2->notes)))
return FALSE;
nb = ms_list_size(p1->activities);
for (i = 0; i < nb; i++) {
if (presence_activity_equals(ms_list_nth_data(p1->activities, i), ms_list_nth_data(p2->activities, i)) == FALSE)
return FALSE;
}
nb = ms_list_size(p1->activities_notes);
for (i = 0; i < nb; i++) {
if (presence_note_equals(ms_list_nth_data(p1->activities_notes, i), ms_list_nth_data(p2->activities_notes, i)) == FALSE)
return FALSE;
}
nb = ms_list_size(p1->notes);
for (i = 0; i < nb; i++) {
if (presence_note_equals(ms_list_nth_data(p1->notes, i), ms_list_nth_data(p2->notes, i)) == FALSE)
return FALSE;
}
return TRUE;
}
LinphonePresenceModel * linphone_presence_model_new(void) {
return ms_new0(LinphonePresenceModel, 1);
}
LinphonePresenceModel * linphone_presence_model_new_with_activity(LinphonePresenceActivity activity, const char *description) {
LinphonePresenceModel *model = linphone_presence_model_new();
if (model != NULL) {
linphone_presence_model_set_activity(model, activity, description);
}
return model;
}
LinphonePresenceModel * linphone_presence_model_new_with_activity_and_note(LinphonePresenceActivity activity, const char *description, const char *note, const char *lang) {
LinphonePresenceModel *model = linphone_presence_model_new();
if (model != NULL) {
linphone_presence_model_set_activity(model, activity, description);
linphone_presence_model_set_note(model, note, lang);
}
return model;
}
void linphone_presence_model_delete(LinphonePresenceModel *model) {
if (model == NULL) return;
ms_list_for_each(model->services, (MSIterateFunc)presence_service_delete);
ms_list_free(model->services);
ms_list_for_each(model->persons, (MSIterateFunc)presence_person_delete);
@ -246,10 +442,61 @@ void linphone_presence_model_delete(LinphonePresenceModel *model) {
ms_free(model);
}
bool_t linphone_presence_model_equals(const LinphonePresenceModel *m1, const LinphonePresenceModel *m2) {
LinphonePresenceActivity activity = LinphonePresenceActivityOffline;
int nb;
int i;
/* Two null activities are considered equal. */
if ((m1 == NULL) && (m2 == NULL))
return TRUE;
/* A null activity is equal to an activity with no activity but a basic status of Closed. */
if (m1 == NULL) {
if ((linphone_presence_model_get_activity(m2, &activity, NULL) < 0)
|| (activity != LinphonePresenceActivityOffline))
return FALSE;
return TRUE;
}
if (m2 == NULL) {
if ((linphone_presence_model_get_activity(m2, &activity, NULL) < 0)
|| (activity != LinphonePresenceActivityOffline))
return FALSE;
return TRUE;
}
if ((ms_list_size(m1->services) != ms_list_size(m2->services))
|| (ms_list_size(m1->persons) != ms_list_size(m2->persons))
|| (ms_list_size(m1->notes) != ms_list_size(m2->notes)))
return FALSE;
nb = ms_list_size(m1->services);
for (i = 0; i < nb; i++) {
if (presence_service_equals(ms_list_nth_data(m1->services, i), ms_list_nth_data(m2->services, i)) == FALSE)
return FALSE;
}
nb = ms_list_size(m1->persons);
for (i = 0; i < nb; i++) {
if (presence_person_equals(ms_list_nth_data(m1->persons, i), ms_list_nth_data(m2->persons, i)) == FALSE)
return FALSE;
}
nb = ms_list_size(m1->notes);
for (i = 0; i < nb; i++) {
if (presence_note_equals(ms_list_nth_data(m1->notes, i), ms_list_nth_data(m2->notes, i)) == FALSE)
return FALSE;
}
return TRUE;
}
/* Suppose that if at least one service is open, then the model is open. */
LinphonePresenceBasicStatus linphone_presence_model_get_basic_status(const LinphonePresenceModel *model) {
LinphonePresenceBasicStatus status = LinphonePresenceBasicStatusClosed;
ms_list_for_each2(model->services, (MSIterate2Func)presence_model_find_open_basic_status, &status);
if (model != NULL) {
ms_list_for_each2(model->services, (MSIterate2Func)presence_model_find_open_basic_status, &status);
}
return status;
}
@ -284,10 +531,12 @@ static void presence_model_get_activity(const struct _LinphonePresencePerson *pe
}
}
int linphone_presence_model_get_activity(const LinphonePresenceModel *model, unsigned int idx, LinphonePresenceActivity *activity, char **description) {
int linphone_presence_model_get_nth_activity(const LinphonePresenceModel *model, unsigned int idx, LinphonePresenceActivity *activity, char **description) {
struct _get_activity_st st;
if ((activity == NULL) || (idx >= linphone_presence_model_nb_activities(model)))
if ((model == NULL) || (activity == NULL) || (idx >= linphone_presence_model_nb_activities(model)))
return -1;
memset(&st, 0, sizeof(st));
st.requested_idx = idx;
st.activity = activity;
@ -296,9 +545,63 @@ int linphone_presence_model_get_activity(const LinphonePresenceModel *model, uns
st.description = description;
}
ms_list_for_each2(model->persons, (MSIterate2Func)presence_model_get_activity, &st);
return 0;
}
int linphone_presence_model_get_activity(const LinphonePresenceModel *model, LinphonePresenceActivity *activity, char **description) {
if ((model == NULL) || (activity == NULL))
return -1;
if (linphone_presence_model_get_nth_activity(model, 0, activity, description) < 0) {
/* There is no activities, base the result on the basic status. */
LinphonePresenceBasicStatus basic_status = linphone_presence_model_get_basic_status(model);
if (basic_status == LinphonePresenceBasicStatusOpen)
*activity = LinphonePresenceActivityOnline;
else
*activity = LinphonePresenceActivityOffline;
}
return 0;
}
int linphone_presence_model_set_activity(LinphonePresenceModel *model, LinphonePresenceActivity activity, const char *description) {
LinphonePresenceBasicStatus basic_status = LinphonePresenceBasicStatusOpen;
if (model == NULL) return -1;
switch (activity) {
case LinphonePresenceActivityAppointment:
case LinphonePresenceActivityBusy:
case LinphonePresenceActivityMeeting:
case LinphonePresenceActivityPermanentAbsence:
case LinphonePresenceActivityOffline:
case LinphonePresenceActivityWorship:
basic_status = LinphonePresenceBasicStatusClosed;
break;
default:
basic_status = LinphonePresenceBasicStatusOpen;
break;
}
if (presence_model_set_basic_status(model, basic_status) < 0)
return -1;
presence_model_clear_activities(model);
if (presence_model_add_activity(model, activity, description) < 0)
return -1;
return 0;
}
const char * linphone_presence_model_get_note(const LinphonePresenceModel *model, const char *lang) {
// TODO
return NULL;
}
int linphone_presence_model_set_note(LinphonePresenceModel *model, const char *note, const char *lang) {
// TODO
return -1;
}
static int create_xml_xpath_context(xmlparsing_context_t *xml_ctx) {
if (xml_ctx->xpath_ctx != NULL) {
xmlXPathFreeContext(xml_ctx->xpath_ctx);
@ -381,7 +684,7 @@ static int process_rfcxxxx_presence_notification(xmlparsing_context_t *xml_ctx,
presence_model_add_service(model, service);
}
if (activity != NULL) {
person = presence_person_new(NULL, NULL);
person = presence_person_new(NULL, time(NULL));
if (person != NULL) {
presence_person_add_activity(person, activity);
presence_model_add_person(model, person);
@ -438,7 +741,7 @@ static int process_msoldpres_presence_notification(xmlparsing_context_t *xml_ctx
presence_model_add_service(model, service);
}
if (activity != NULL) {
person = presence_person_new(NULL, NULL);
person = presence_person_new(NULL, time(NULL));
if (person != NULL) {
presence_person_add_activity(person, activity);
presence_model_add_person(model, person);
@ -450,12 +753,43 @@ static int process_msoldpres_presence_notification(xmlparsing_context_t *xml_ctx
static const char *service_prefix = "/pidf:presence/pidf:tuple";
static int process_pidf_xml_presence_service_notes(xmlparsing_context_t *xml_ctx, struct _LinphonePresenceService *service, unsigned int service_idx) {
char xpath_str[MAX_XPATH_LENGTH];
xmlXPathObjectPtr note_object;
struct _LinphonePresenceNote *note;
const char *note_str;
const char *lang;
int i;
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/rpid:note", service_prefix, service_idx);
note_object = get_xml_xpath_object_for_node_list(xml_ctx, xpath_str);
if ((note_object != NULL) && (note_object->nodesetval != NULL)) {
for (i = 1; i <= note_object->nodesetval->nodeNr; i++) {
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/rpid:note[%i]", service_prefix, service_idx, i);
note_str = get_xml_text_content(xml_ctx, xpath_str);
if (note_str == NULL) continue;
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/rpid:note[%i]/@xml:lang", service_prefix, service_idx, i);
lang = get_xml_text_content(xml_ctx, xpath_str);
note = presence_note_new(note_str, lang);
presence_service_add_note(service, note);
if (lang != NULL) free_xml_text_content(lang);
free_xml_text_content(note_str);
}
}
if (note_object != NULL) xmlXPathFreeObject(note_object);
return 0;
}
static int process_pidf_xml_presence_services(xmlparsing_context_t *xml_ctx, LinphonePresenceModel *model) {
char xpath_str[MAX_XPATH_LENGTH];
xmlXPathObjectPtr service_object;
struct _LinphonePresenceService *service;
const char *basic_status_str;
const char *service_id_str;
const char *timestamp_str;
const char *contact_str;
LinphonePresenceBasicStatus basic_status;
int i;
@ -477,10 +811,25 @@ static int process_pidf_xml_presence_services(xmlparsing_context_t *xml_ctx, Lin
return -1;
}
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/pidf:timestamp", service_prefix, i);
timestamp_str = get_xml_text_content(xml_ctx, xpath_str);
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/pidf:contact", service_prefix, i);
contact_str = get_xml_text_content(xml_ctx, xpath_str);
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/@id", service_prefix, i);
service_id_str = 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));
free_xml_text_content(timestamp_str);
}
if (contact_str != NULL) {
presence_service_set_contact(service, contact_str);
free_xml_text_content(contact_str);
}
process_pidf_xml_presence_service_notes(xml_ctx, service, i);
presence_model_add_service(model, service);
}
free_xml_text_content(basic_status_str);
@ -540,6 +889,16 @@ static int activity_name_to_linphone_presence_activity(const char *name, Linphon
return -1;
}
static const char * presence_activity_to_string(LinphonePresenceActivity activity) {
unsigned int i;
for (i = 0; i < (sizeof(activity_map) / sizeof(activity_map[0])); i++) {
if (activity == activity_map[i].activity) {
return activity_map[i].name;
}
}
return NULL;
}
static int process_pidf_xml_presence_person_activities(xmlparsing_context_t *xml_ctx, struct _LinphonePresencePerson *person, unsigned int person_idx) {
char xpath_str[MAX_XPATH_LENGTH];
xmlXPathObjectPtr activities_nodes_object;
@ -638,6 +997,7 @@ static int process_pidf_xml_presence_persons(xmlparsing_context_t *xml_ctx, Linp
struct _LinphonePresencePerson *person;
const char *person_id_str;
const char *person_timestamp_str;
time_t timestamp;
int i;
int err = 0;
@ -646,9 +1006,13 @@ static int process_pidf_xml_presence_persons(xmlparsing_context_t *xml_ctx, Linp
for (i = 1; i <= person_object->nodesetval->nodeNr; i++) {
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/@id", person_prefix, i);
person_id_str = get_xml_text_content(xml_ctx, xpath_str);
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/timestamp", person_prefix, i);
snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/pidf:timestamp", person_prefix, i);
person_timestamp_str = get_xml_text_content(xml_ctx, xpath_str);
person = presence_person_new(person_id_str, person_timestamp_str);
if (person_timestamp_str == NULL)
timestamp = time(NULL);
else
timestamp = parse_timestamp(person_timestamp_str);
person = presence_person_new(person_id_str, timestamp);
if (person != NULL) {
err = process_pidf_xml_presence_person_activities(xml_ctx, person, i);
if (err == 0) {
@ -775,13 +1139,13 @@ void linphone_core_reject_subscriber(LinphoneCore *lc, LinphoneFriend *lf){
linphone_friend_set_inc_subscribe_policy(lf,LinphoneSPDeny);
}
void linphone_core_notify_all_friends(LinphoneCore *lc, LinphoneOnlineStatus os){
void linphone_core_notify_all_friends(LinphoneCore *lc, LinphonePresenceModel *presence){
MSList *elem;
ms_message("Notifying all friends that we are in status %i",os);
ms_message("Notifying all friends");
for(elem=lc->friends;elem!=NULL;elem=elem->next){
LinphoneFriend *lf=(LinphoneFriend *)elem->data;
if (lf->insub){
linphone_friend_notify(lf,os);
linphone_friend_notify(lf,presence);
}
}
}
@ -864,6 +1228,259 @@ void linphone_notify_parse_presence(SalOp *op, const char *content_type, const c
*result = (SalPresenceModel *)model;
}
struct _presence_service_obj_st {
xmlTextWriterPtr writer;
const char *contact;
int *err;
};
struct _presence_person_obj_st {
xmlTextWriterPtr writer;
int *err;
};
struct _presence_activity_obj_st {
xmlTextWriterPtr writer;
int *err;
};
struct _presence_note_obj_st {
xmlTextWriterPtr writer;
const char *ns;
int *err;
};
static int write_xml_presence_timestamp(xmlTextWriterPtr writer, time_t timestamp) {
int err;
char *timestamp_str = timestamp_to_string(timestamp);
err = xmlTextWriterWriteElement(writer, (const xmlChar *)"timestamp", (const xmlChar *)timestamp_str);
if (timestamp_str) ms_free(timestamp_str);
return err;
}
static int write_xml_presence_service(xmlTextWriterPtr writer, struct _LinphonePresenceService *service, const char *contact) {
int err = xmlTextWriterStartElement(writer, (const xmlChar *)"tuple");
if (err >= 0) {
if ((service == NULL) || (service->id == NULL)) {
char *text = generate_presence_id();
err = xmlTextWriterWriteAttribute(writer, (const xmlChar *)"id", (const xmlChar *)text);
if (text != NULL) ms_free(text);
} else {
err = xmlTextWriterWriteAttribute(writer, (const xmlChar *)"id", (const xmlChar *)service->id);
}
}
if (err >= 0) {
err = xmlTextWriterStartElement(writer, (const xmlChar *)"status");
}
if (err >= 0) {
LinphonePresenceBasicStatus basic_status = LinphonePresenceBasicStatusClosed;
if (service != NULL) basic_status = service->status;
err = xmlTextWriterWriteElement(writer, (const xmlChar *)"basic", (const xmlChar *)presence_basic_status_to_string(basic_status));
}
if (err >= 0) {
/* Close the "status" element. */
err = xmlTextWriterEndElement(writer);
}
if (err >= 0) {
err = xmlTextWriterStartElement(writer, (const xmlChar *)"contact");
}
if (err >= 0) {
err = xmlTextWriterWriteAttribute(writer, (const xmlChar *)"priority", (const xmlChar *)"0.8");
}
if (err >= 0) {
err = xmlTextWriterWriteString(writer, (const xmlChar *)contact);
}
if (err >= 0) {
/* Close the "contact" element. */
err = xmlTextWriterEndElement(writer);
}
if (err >= 0) {
if (service == NULL)
err = write_xml_presence_timestamp(writer, time(NULL));
else
err = write_xml_presence_timestamp(writer, service->timestamp);
}
if (err >= 0) {
/* Close the "tuple" element. */
err = xmlTextWriterEndElement(writer);
}
return err;
}
static int write_xml_presence_activity(xmlTextWriterPtr writer, struct _LinphonePresenceActivity *activity) {
int err = xmlTextWriterStartElementNS(writer, (const xmlChar *)"rpid",
(const xmlChar *)presence_activity_to_string(activity->activity), NULL);
if ((err >= 0) && (activity->description != NULL)) {
err = xmlTextWriterWriteString(writer, (const xmlChar *)activity->description);
}
if (err >= 0) {
err = xmlTextWriterEndElement(writer);
}
return err;
}
static void write_xml_presence_activity_obj(struct _LinphonePresenceActivity *activity, struct _presence_activity_obj_st *st) {
int err = write_xml_presence_activity(st->writer, activity);
if (err < 0) *st->err = err;
}
static int write_xml_presence_note(xmlTextWriterPtr writer, struct _LinphonePresenceNote *note, const char *ns) {
int err;
if (ns == NULL) {
err = xmlTextWriterStartElement(writer, (const xmlChar *)"note");
} else {
err = xmlTextWriterStartElementNS(writer, (const xmlChar *)ns, (const xmlChar *)"note", NULL);
}
if ((err >= 0) && (note->lang != NULL)) {
err = xmlTextWriterWriteAttributeNS(writer, (const xmlChar *)"xml", (const xmlChar *)"lang", NULL, (const xmlChar *)note->lang);
}
if (err >= 0) {
err = xmlTextWriterWriteString(writer, (const xmlChar *)note->content);
}
if (err >= 0) {
err = xmlTextWriterEndElement(writer);
}
return err;
}
static void write_xml_presence_note_obj(struct _LinphonePresenceNote *note, struct _presence_note_obj_st *st) {
int err = write_xml_presence_note(st->writer, note, st->ns);
if (err < 0) *st->err = err;
}
static int write_xml_presence_person(xmlTextWriterPtr writer, struct _LinphonePresencePerson *person) {
int err = xmlTextWriterStartElementNS(writer, (const xmlChar *)"dm", (const xmlChar *)"person", NULL);
if (err >= 0) {
if (person->id == NULL) {
char *text = generate_presence_id();
err = xmlTextWriterWriteAttribute(writer, (const xmlChar *)"id", (const xmlChar *)text);
if (text != NULL) ms_free(text);
} else {
err = xmlTextWriterWriteAttribute(writer, (const xmlChar *)"id", (const xmlChar *)person->id);
}
}
if ((err >= 0) && ((person->activities_notes != NULL) || (person->activities != NULL))) {
err = xmlTextWriterStartElementNS(writer, (const xmlChar *)"rpid", (const xmlChar *)"activities", NULL);
if ((err >= 0) && (person->activities_notes != NULL)) {
struct _presence_note_obj_st st;
st.writer = writer;
st.ns = "rpid";
st.err = &err;
ms_list_for_each2(person->activities_notes, (MSIterate2Func)write_xml_presence_note_obj, &st);
}
if ((err >= 0) && (person->activities != NULL)) {
struct _presence_activity_obj_st st;
st.writer = writer;
st.err = &err;
ms_list_for_each2(person->activities, (MSIterate2Func)write_xml_presence_activity_obj, &st);
}
if (err >= 0) {
/* Close the "activities" element. */
err = xmlTextWriterEndElement(writer);
}
}
if ((err >= 0) && (person->notes != NULL)) {
struct _presence_note_obj_st st;
st.writer = writer;
st.ns = "dm";
st.err = &err;
ms_list_for_each2(person->activities_notes, (MSIterate2Func)write_xml_presence_note_obj, &st);
}
if (err >= 0) {
write_xml_presence_timestamp(writer, person->timestamp);
}
if (err >= 0) {
/* Close the "person" element. */
err = xmlTextWriterEndElement(writer);
}
return err;
}
static void write_xml_presence_service_obj(struct _LinphonePresenceService *service, struct _presence_service_obj_st *st) {
int err = write_xml_presence_service(st->writer, service, st->contact);
if (err < 0) *st->err = err;
}
static void write_xml_presence_person_obj(struct _LinphonePresencePerson *person, struct _presence_person_obj_st *st) {
int err = write_xml_presence_person(st->writer, person);
if (err < 0) *st->err = err;
}
void linphone_notify_convert_presence_to_xml(SalOp *op, SalPresenceModel *presence, const char *contact, char **content) {
LinphonePresenceModel *model;
xmlBufferPtr buf;
xmlTextWriterPtr writer;
int err;
if ((contact == NULL) || (content == NULL)) return;
model = (LinphonePresenceModel *)presence;
buf = xmlBufferCreate();
if (buf == NULL) {
ms_error("Error creating the XML buffer");
return;
}
writer = xmlNewTextWriterMemory(buf, 0);
if (writer == NULL) {
ms_error("Error creating the XML writer");
return;
}
err = xmlTextWriterStartDocument(writer, "1.0", "UTF-8", NULL);
if (err >= 0) {
err = xmlTextWriterStartElementNS(writer, NULL, (const xmlChar *)"presence", (const xmlChar *)"urn:ietf:params:xml:ns:pidf");
}
if (err >= 0) {
err = xmlTextWriterWriteAttributeNS(writer, (const xmlChar *)"xmlns", (const xmlChar *)"dm",
NULL, (const xmlChar *)"urn:ietf:params:xml:ns:pidf:data-model");
}
if (err >= 0) {
err = xmlTextWriterWriteAttributeNS(writer, (const xmlChar *)"xmlns", (const xmlChar *)"rpid",
NULL, (const xmlChar *)"urn:ietf:params:xml:ns:pidf:rpid");
}
if (err >= 0) {
err = xmlTextWriterWriteAttribute(writer, (const xmlChar *)"entity", (const xmlChar *)contact);
}
if (err >= 0) {
if ((model == NULL) || (model->services == NULL)) {
err = write_xml_presence_service(writer, NULL, contact);
} else {
struct _presence_service_obj_st st;
st.writer = writer;
st.contact = contact;
st.err = &err;
ms_list_for_each2(model->services, (MSIterate2Func)write_xml_presence_service_obj, &st);
}
}
if ((err >= 0) && (model != NULL)) {
struct _presence_person_obj_st st;
st.writer = writer;
st.err = &err;
ms_list_for_each2(model->persons, (MSIterate2Func)write_xml_presence_person_obj, &st);
}
if ((err >= 0) && (model != NULL)) {
struct _presence_note_obj_st st;
st.writer = writer;
st.ns = NULL;
st.err = &err;
ms_list_for_each2(model->notes, (MSIterate2Func)write_xml_presence_note_obj, &st);
}
if (err >= 0) {
/* Close the "presence" element. */
err = xmlTextWriterEndElement(writer);
}
if (err >= 0) {
err = xmlTextWriterEndDocument(writer);
}
xmlFreeTextWriter(writer);
if (err > 0) {
/* xmlTextWriterEndDocument returns the size of the content. */
*content = ms_strdup((char *)buf->content);
}
xmlBufferFree(buf);
}
void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, SalPresenceModel *model){
char *tmp;
LinphoneFriend *lf;

View file

@ -233,7 +233,7 @@ void linphone_core_refresh_subscribes(LinphoneCore *lc);
int linphone_core_abort_call(LinphoneCore *lc, LinphoneCall *call, const char *error);
const char *linphone_core_get_nat_address_resolved(LinphoneCore *lc);
int linphone_proxy_config_send_publish(LinphoneProxyConfig *cfg, LinphoneOnlineStatus os);
int linphone_proxy_config_send_publish(LinphoneProxyConfig *cfg, LinphonePresenceModel *presence);
void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrationState rstate, const char *message);
void linphone_proxy_config_write_all_to_config_file(LinphoneCore *lc);
/*
@ -245,7 +245,7 @@ const LinphoneAddress* linphone_proxy_config_get_service_route(const LinphonePro
int linphone_online_status_to_eXosip(LinphoneOnlineStatus os);
void linphone_friend_close_subscriptions(LinphoneFriend *lf);
void linphone_friend_notify(LinphoneFriend *lf, LinphoneOnlineStatus os);
void linphone_friend_notify(LinphoneFriend *lf, LinphonePresenceModel *presence);
LinphoneFriend *linphone_find_friend_by_inc_subscribe(MSList *l, SalOp *op);
LinphoneFriend *linphone_find_friend_by_out_subscribe(MSList *l, SalOp *op);
@ -286,11 +286,11 @@ static inline void set_string(char **dest, const char *src){
#define PAYLOAD_TYPE_ENABLED PAYLOAD_TYPE_USER_FLAG_0
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_parse_presence(SalOp *op, 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);
@ -599,7 +599,7 @@ struct _LinphoneCore
MSList *bl_reqs;
MSList *subscribers; /* unknown subscribers */
int minutes_away;
LinphoneOnlineStatus presence_mode;
LinphonePresenceModel *presence_model;
char *alt_contact;
void *data;
char *play_file;

View file

@ -849,8 +849,7 @@ void linphone_proxy_config_set_realm(LinphoneProxyConfig *cfg, const char *realm
if (realm!=NULL) cfg->realm=ms_strdup(realm);
}
int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy,
LinphoneOnlineStatus presence_mode){
int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy, LinphonePresenceModel *presence){
int err;
if (proxy->publish_op==NULL){
@ -859,7 +858,7 @@ int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy,
sal_op_set_from(proxy->publish_op,linphone_proxy_config_get_identity(proxy));
sal_op_set_to(proxy->publish_op,linphone_proxy_config_get_identity(proxy));
}
err=sal_publish_presence(proxy->publish_op,NULL,NULL,linphone_online_status_to_sal(presence_mode));
err=sal_publish_presence(proxy->publish_op,NULL,NULL,(SalPresenceModel *)presence);
return err;
}
@ -1190,7 +1189,7 @@ void linphone_proxy_config_update(LinphoneProxyConfig *cfg){
}
}
if (cfg->publish && cfg->publish_op==NULL && cfg->state==LinphoneRegistrationOk){
linphone_proxy_config_send_publish(cfg,lc->presence_mode);
linphone_proxy_config_send_publish(cfg,lc->presence_model);
}
}

View file

@ -359,6 +359,7 @@ typedef void (*SalOnNotify)(SalOp *op, SalSubscribeStatus status, const char *ev
typedef void (*SalOnSubscribeReceived)(SalOp *salop, const char *event, const SalBody *body);
typedef void (*SalOnSubscribeClosed)(SalOp *salop);
typedef void (*SalOnParsePresenceRequested)(SalOp *salop, const char *content_type, const char *content_subtype, const char *content, SalPresenceModel **result);
typedef void (*SalOnConvertPresenceToXMLRequested)(SalOp *salop, SalPresenceModel *presence, const char *contact, char **content);
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);
@ -398,6 +399,7 @@ typedef struct SalCallbacks{
SalOnSubscribePresenceReceived subscribe_presence_received;
SalOnSubscribePresenceClosed subscribe_presence_closed;
SalOnParsePresenceRequested parse_presence_requested;
SalOnConvertPresenceToXMLRequested convert_presence_to_xml_requested;
SalOnNotifyPresence notify_presence;
SalOnPingReply ping_reply;
SalOnAuthRequested auth_requested;
@ -532,11 +534,11 @@ int sal_message_send(SalOp *op, const char *from, const char *to, const char* co
/*presence Subscribe/notify*/
int sal_subscribe_presence(SalOp *op, const char *from, const char *to);
int sal_notify_presence(SalOp *op, SalPresenceStatus status, const char *status_message);
int sal_notify_presence(SalOp *op, SalPresenceModel *presence);
int sal_notify_presence_close(SalOp *op);
/*presence publish */
int sal_publish_presence(SalOp *op, const char *from, const char *to, SalPresenceStatus status);
int sal_publish_presence(SalOp *op, const char *from, const char *to, SalPresenceModel *presence);
/*ping: main purpose is to obtain its own contact address behind firewalls*/