Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "sal.h"
-#include <eXosip2/eXosip.h>
+#include "sal_eXosip2.h"
#include "offeranswer.h"
-extern sdp_message_t *media_description_to_sdp(const SalMediaDescription *sal);
-extern int sdp_to_media_description(sdp_message_t *sdp, SalMediaDescription *desc);
-
-struct Sal{
- SalCallbacks callbacks;
- int running;
- int session_expires;
- int automatic_action;
-};
-
-struct SalOp{
- SalOpBase base;
- int cid;
- int did;
- int tid;
- int rid;
- int expires;
- SalMediaDescription *result;
- sdp_message_t *sdp_answer;
- eXosip_event_t *pending_auth;
- bool_t supports_session_timers;
- bool_t sdp_offering;
- bool_t reinvite;
-};
+
+static SalOp * sal_find_register(Sal *sal, int rid){
+ const MSList *elem;
+ SalOp *op;
+ for(elem=sal->registers;elem!=NULL;elem=elem->next){
+ op=(SalOp*)elem->data;
+ if (op->rid==rid) return op;
+ }
+ return NULL;
+}
+
+static void sal_add_register(Sal *sal, SalOp *op){
+ sal->registers=ms_list_append(sal->registers,op);
+}
+
+static void sal_remove_register(Sal *sal, int rid){
+ MSList *elem;
+ SalOp *op;
+ for(elem=sal->registers;elem!=NULL;elem=elem->next){
+ op=(SalOp*)elem->data;
+ if (op->rid==rid) {
+ sal->registers=ms_list_remove_link(sal->registers,elem);
+ return;
+ }
+ }
+}
SalOp * sal_op_new(Sal *sal){
SalOp *op=ms_new(SalOp,1);
__sal_op_init(op,sal);
- op->cid=op->did=op->tid=-1;
+ op->cid=op->did=op->tid=op->rid=op->nid=op->sid-1;
op->supports_session_timers=FALSE;
op->sdp_offering=TRUE;
op->pending_auth=NULL;
sdp_message_free(op->sdp_answer);
if (op->pending_auth)
eXosip_event_free(op->pending_auth);
+ if( op->rid!=-1){
+ sal_remove_register(op->base.root,op->rid);
+ }
__sal_op_free(op);
}
ctx->callbacks.dtmf_received=(SalOnDtmfReceived)unimplemented_stub;
if (ctx->callbacks.presence_changed==NULL)
ctx->callbacks.presence_changed=(SalOnPresenceChanged)unimplemented_stub;
+ if (ctx->callbacks.subscribe_received==NULL)
+ ctx->callbacks.subscribe_received=(SalOnSubscribeReceived)unimplemented_stub;
+ if (ctx->callbacks.text_received==NULL)
+ ctx->callbacks.text_received=(SalOnTextReceived)unimplemented_stub;
if (ctx->callbacks.internal_message==NULL)
ctx->callbacks.internal_message=(SalOnInternalMsg)unimplemented_stub;
}
}
static void registration_success(Sal *sal, eXosip_event_t *ev){
- SalOp *op=(SalOp*)ev->external_reference;
+ SalOp *op=sal_find_register(sal,ev->rid);
osip_header_t *h=NULL;
bool_t registered;
if (op==NULL){
static bool_t registration_failure(Sal *sal, eXosip_event_t *ev){
int status_code=0;
const char *reason=NULL;
- SalOp *op=(SalOp*)ev->external_reference;
+ SalOp *op=sal_find_register(sal,ev->rid);
SalReason sr=SalReasonUnknown;
SalError se=SalErrorUnknown;
}
break;
case EXOSIP_IN_SUBSCRIPTION_NEW:
- ms_message("CALL_SUBSCRIPTION_NEW or UPDATE");
- linphone_subscription_new(lc,ev);
+ ms_message("CALL_SUBSCRIPTION_NEW ");
+ sal_exosip_subscription_recv(sal,ev);
break;
case EXOSIP_SUBSCRIPTION_UPDATE:
+ ms_message("CALL_SUBSCRIPTION_UPDATE");
break;
case EXOSIP_SUBSCRIPTION_NOTIFY:
ms_message("CALL_SUBSCRIPTION_NOTIFY");
- linphone_notify_recv(lc,ev);
+ sal_exosip_notify_recv(sal,ev);
break;
case EXOSIP_SUBSCRIPTION_ANSWERED:
ms_message("EXOSIP_SUBSCRIPTION_ANSWERED, ev->sid=%i\n",ev->sid);
- linphone_subscription_answered(lc,ev);
+ sal_exosip_subscription_answered(sal,ev);
break;
case EXOSIP_SUBSCRIPTION_CLOSED:
ms_message("EXOSIP_SUBSCRIPTION_CLOSED\n");
- linphone_subscription_closed(lc,ev);
+ sal_exosip_subscription_closed(sal,ev);
break;
case EXOSIP_CALL_RELEASED:
ms_message("CALL_RELEASED\n");
eXosip_unlock();
}
}
+ return 0;
}
int sal_register(SalOp *h, const char *proxy, const char *from, int expires){
osip_message_t *msg;
if (h->rid==-1){
eXosip_lock();
- h->rid=eXosip_register_build_initial_register(from,proxy,sal_op_get_contact(op),expires,&msg);
+ h->rid=eXosip_register_build_initial_register(from,proxy,sal_op_get_contact(h),expires,&msg);
+ sal_add_register(h->base.root,h);
}else{
eXosip_lock();
eXosip_register_build_register(h->rid,expires,&msg);
}
eXosip_register_send_register(h->rid,msg);
eXosip_unlock();
- op->expires=expires;
+ h->expires=expires;
return 0;
}
--- /dev/null
+/*
+linphone
+Copyright (C) 2010 Simon MORLAT (simon.morlat@free.fr)
+
+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.
+*/
+
+
+#include "sal_eXosip2.h"
+
+
+static SalOp * sal_find_out_subscribe(Sal *sal, int sid){
+ const MSList *elem;
+ SalOp *op;
+ for(elem=sal->out_subscribes;elem!=NULL;elem=elem->next){
+ op=(SalOp*)elem->data;
+ if (op->sid==sid) return op;
+ }
+ return NULL;
+}
+
+static void sal_add_out_subscribe(Sal *sal, SalOp *op){
+ sal->out_subscribes=ms_list_append(sal->out_subscribes,op);
+}
+
+static void sal_remove_out_subscribe(Sal *sal, int sid){
+ MSList *elem;
+ SalOp *op;
+ for(elem=sal->out_subscribes;elem!=NULL;elem=elem->next){
+ op=(SalOp*)elem->data;
+ if (op->sid==sid) {
+ sal->out_subscribes=ms_list_remove_link(sal->out_subscribes,elem);
+ return;
+ }
+ }
+}
+
+static SalOp * sal_find_in_subscribe(Sal *sal, int nid){
+ const MSList *elem;
+ SalOp *op;
+ for(elem=sal->in_subscribes;elem!=NULL;elem=elem->next){
+ op=(SalOp*)elem->data;
+ if (op->nid==nid) return op;
+ }
+ return NULL;
+}
+
+static void sal_add_in_subscribe(Sal *sal, SalOp *op){
+ sal->in_subscribes=ms_list_append(sal->in_subscribes,op);
+}
+
+static void sal_remove_in_subscribe(Sal *sal, int nid){
+ MSList *elem;
+ SalOp *op;
+ for(elem=sal->in_subscribes;elem!=NULL;elem=elem->next){
+ op=(SalOp*)elem->data;
+ if (op->nid==nid) {
+ sal->in_subscribes=ms_list_remove_link(sal->in_subscribes,elem);
+ return;
+ }
+ }
+}
+
+int sal_text_send(SalOp *op, const char *from, const char *to, const char *msg){
+ osip_message_t *sip=NULL;
+ if (from)
+ sal_op_set_from(op,from);
+ if (to)
+ sal_op_set_to(op,to);
+
+ eXosip_lock();
+ eXosip_message_build_request(&sip,"MESSAGE",sal_op_get_to(op),
+ sal_op_get_from(op),sal_op_get_route(op));
+ osip_message_set_content_type(sip,"text/plain");
+ osip_message_set_body(sip,msg,strlen(msg));
+ eXosip_message_send_request(sip);
+ eXosip_unlock();
+ return 0;
+}
+
+/*presence Subscribe/notify*/
+int sal_subscribe_presence(SalOp *op, const char *from, const char *to){
+ osip_message_t *msg;
+ if (from)
+ sal_op_set_from(op,from);
+ if (to)
+ sal_op_set_to(op,to);
+ eXosip_lock();
+ eXosip_subscribe_build_initial_request(&msg,sal_op_get_to(op),sal_op_get_from(op),
+ sal_op_get_route(op),"presence",600);
+ op->sid=eXosip_subscribe_send_initial_request(msg);
+ eXosip_unlock();
+ if (op->sid==-1){
+ osip_message_free(msg);
+ return -1;
+ }
+ sal_add_out_subscribe(op->base.root,op);
+ return 0;
+}
+
+int sal_unsubscribe(SalOp *op){
+ osip_message_t *msg=NULL;
+ if (op->did==-1){
+ ms_error("cannot unsubscribe, no dialog !");
+ return -1;
+ }
+ eXosip_lock();
+ eXosip_subscribe_build_refresh_request(op->did,&msg);
+ if (msg){
+ osip_message_set_expires(msg,"0");
+ eXosip_subscribe_send_refresh_request(op->did,msg);
+ }else ms_error("Could not build subscribe refresh request !");
+ eXosip_unlock();
+ return 0;
+}
+
+int sal_subscribe_accept(SalOp *op){
+ osip_message_t *msg;
+ eXosip_lock();
+ eXosip_insubscription_build_answer(op->tid,202,&msg);
+ eXosip_insubscription_send_answer(op->tid,202,msg);
+ eXosip_unlock();
+ return 0;
+}
+
+int sal_subscribe_decline(SalOp *op){
+ eXosip_lock();
+ eXosip_insubscription_send_answer(op->tid,401,NULL);
+ eXosip_unlock();
+ return 0;
+}
+
+static eXosip_ss_status_t sal_presence_to_exosip(SalPresenceStatus s){
+ switch(s){
+ case SalPresenceOffline:
+ return EXOSIP_NOTIFY_CLOSED;
+ case SalPresenceOnline:
+ return EXOSIP_NOTIFY_ONLINE;
+ case SalPresenceBusy:
+ return EXOSIP_NOTIFY_BUSY;
+ case SalPresenceBerightback:
+ return EXOSIP_NOTIFY_BERIGHTBACK;
+ case SalPresenceAway:
+ return EXOSIP_NOTIFY_AWAY;
+ case SalPresenceOnthephone:
+ return EXOSIP_NOTIFY_ONTHEPHONE;
+ case SalPresenceOuttolunch:
+ return EXOSIP_NOTIFY_OUTTOLUNCH;
+ case SalPresenceDonotdisturb:
+ return EXOSIP_NOTIFY_BUSY;
+ case SalPresenceMoved:
+ case SalPresenceAltService:
+ default:
+ return EXOSIP_NOTIFY_AWAY;
+ }
+}
+
+static void add_presence_body(osip_message_t *notify, SalPresenceStatus online_status)
+{
+ char buf[1000];
+#ifdef SUPPORT_MSN
+ int atom_id = 1000;
+#endif
+ char *contact_info;
+
+ osip_contact_t *ct=NULL;
+ osip_message_get_contact(notify,0,&ct);
+ osip_contact_to_str(ct,&contact_info);
+
+#ifdef SUPPORT_MSN
+
+ if (online_status==SalPresenceOnline)
+ {
+ sprintf(buf, "<?xml version=\"1.0\"?>\n\
+<!DOCTYPE presence\n\
+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;user=ip\" 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)
+ {
+ sprintf(buf, "<?xml version=\"1.0\"?>\n\
+<!DOCTYPE presence\n\
+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;user=ip\" 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)
+ {
+ sprintf(buf, "<?xml version=\"1.0\"?>\n\
+<!DOCTYPE presence\n\
+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;user=ip\" priority=\"0.800000\">\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)
+ {
+ sprintf(buf, "<?xml version=\"1.0\"?>\n\
+<!DOCTYPE presence\n\
+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;user=ip\" priority=\"0.800000\">\n\
+<status status=\"inactive\" />\n\
+<msnsubstatus substatus=\"away\" />\n\
+</address>\n\
+</atom>\n\
+</presence>", contact_info, atom_id, contact_info);
+
+ }
+ else if (online_status==SalPresenceOnthephone)
+ {
+ sprintf(buf, "<?xml version=\"1.0\"?>\n\
+<!DOCTYPE presence\n\
+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;user=ip\" 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)
+ {
+ sprintf(buf, "<?xml version=\"1.0\"?>\n\
+<!DOCTYPE presence\n\
+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;user=ip\" priority=\"0.800000\">\n\
+<status status=\"inactive\" />\n\
+<msnsubstatus substatus=\"outtolunch\" />\n\
+</address>\n\
+</atom>\n\
+</presence>", contact_info, atom_id, contact_info);
+
+ }
+ else
+ {
+ sprintf(buf, "<?xml version=\"1.0\"?>\n\
+<!DOCTYPE presence\n\
+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;user=ip\" priority=\"0.800000\">\n\
+<status status=\"inactive\" />\n\
+<msnsubstatus substatus=\"away\" />\n\
+</address>\n\
+</atom>\n\
+</presence>", contact_info, atom_id, contact_info);
+ }
+
+ osip_message_set_body(notify, buf, strlen(buf));
+ osip_message_set_content_type(notify, "application/xpidf+xml");
+#else
+
+ if (online_status==SalPresenceOnline)
+ {
+ sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
+<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
+ entity=\"%s\">\n\
+<tuple id=\"sg89ae\">\n\
+<status>\n\
+<basic>open</basic>\n\
+</status>\n\
+<contact priority=\"0.8\">%s</contact>\n\
+<note>online</note>\n\
+</tuple>\n\
+</presence>",
+ contact_info, contact_info);
+ }
+ else if (online_status==SalPresenceBusy)
+ {
+ sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
+<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
+ xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
+ entity=\"%s\">\n\
+<tuple id=\"sg89ae\">\n\
+<status>\n\
+<basic>open</basic>\n\
+<es:activities>\n\
+ <es:activity>busy</es:activity>\n\
+</es:activities>\n\
+</status>\n\
+<contact priority=\"0.8\">%s</contact>\n\
+<note>busy</note>\n\
+</tuple>\n\
+</presence>",
+ contact_info, contact_info);
+ }
+ else if (online_status==SalPresenceBerightback)
+ {
+ sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
+<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
+ xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
+ entity=\"%s\">\n\
+<tuple id=\"sg89ae\">\n\
+<status>\n\
+<basic>open</basic>\n\
+<es:activities>\n\
+ <es:activity>in-transit</es:activity>\n\
+</es:activities>\n\
+</status>\n\
+<contact priority=\"0.8\">%s</contact>\n\
+<note>be right back</note>\n\
+</tuple>\n\
+</presence>",
+ contact_info, contact_info);
+ }
+ else if (online_status==SalPresenceAway)
+ {
+ sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
+<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
+ xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
+ entity=\"%s\">\n\
+<tuple id=\"sg89ae\">\n\
+<status>\n\
+<basic>open</basic>\n\
+<es:activities>\n\
+ <es:activity>away</es:activity>\n\
+</es:activities>\n\
+</status>\n\
+<contact priority=\"0.8\">%s</contact>\n\
+<note>away</note>\n\
+</tuple>\n\
+</presence>",
+ contact_info, contact_info);
+ }
+ else if (online_status==SalPresenceOnthephone)
+ {
+ sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
+<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
+ xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
+ entity=\"%s\">\n\
+<tuple id=\"sg89ae\">\n\
+<status>\n\
+<basic>open</basic>\n\
+<es:activities>\n\
+ <es:activity>on-the-phone</es:activity>\n\
+</es:activities>\n\
+</status>\n\
+<contact priority=\"0.8\">%s</contact>\n\
+<note>on the phone</note>\n\
+</tuple>\n\
+</presence>",
+ contact_info, contact_info);
+ }
+ else if (online_status==SalPresenceOuttolunch)
+ {
+ sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
+<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
+ xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
+ entity=\"%s\">\n\
+<tuple id=\"sg89ae\">\n\
+<status>\n\
+<basic>open</basic>\n\
+<es:activities>\n\
+ <es:activity>meal</es:activity>\n\
+</es:activities>\n\
+</status>\n\
+<contact priority=\"0.8\">%s</contact>\n\
+<note>out to lunch</note>\n\
+</tuple>\n\
+</presence>",
+ contact_info, contact_info);
+ }
+ else
+ {
+ /* */
+ sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
+<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
+xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
+entity=\"%s\">\n%s",
+ contact_info,
+"<tuple id=\"sg89ae\">\n\
+<status>\n\
+<basic>closed</basic>\n\
+<es:activities>\n\
+ <es:activity>permanent-absence</es:activity>\n\
+</es:activities>\n\
+</status>\n\
+</tuple>\n\
+\n</presence>\n");
+ }
+ osip_message_set_body(notify, buf, strlen(buf));
+ osip_message_set_content_type(notify, "application/pidf+xml");
+
+#endif
+ osip_free(contact_info);
+}
+
+
+int sal_notify_presence(SalOp *op, SalPresenceStatus status, const char *status_message){
+ osip_message_t *msg;
+ eXosip_ss_status_t ss;
+ if (op->nid==-1){
+ ms_warning("Cannot notify, subscription was closed.");
+ return -1;
+ }
+ ss=sal_presence_to_exosip(status);
+ eXosip_lock();
+ eXosip_insubscription_build_notify(op->did,ss,0,&msg);
+ if (msg!=NULL){
+ const char *identity=sal_op_get_contact(op);
+ if (identity==NULL) identity=sal_op_get_to(op);
+ osip_message_set_contact(msg,identity);
+ add_presence_body(msg,status);
+ eXosip_insubscription_send_request(op->did,msg);
+ }else ms_error("could not create notify for incoming subscription.");
+ eXosip_unlock();
+ return 0;
+}
+
+void sal_exosip_subscription_recv(Sal *sal, eXosip_event_t *ev){
+ SalOp *op=sal_op_new(sal);
+ char *tmp;
+ op->did=ev->did;
+ op->tid=ev->tid;
+ op->nid=ev->nid;
+ osip_from_to_str(ev->request->from,&tmp);
+ sal_op_set_from(op,tmp);
+ ms_free(tmp);
+ osip_from_to_str(ev->request->to,&tmp);
+ sal_op_set_to(op,tmp);
+ ms_free(tmp);
+ sal_add_in_subscribe(sal,op);
+ sal->callbacks.subscribe_received(op,sal_op_get_from(op));
+}
+
+void sal_exosip_notify_recv(Sal *sal, eXosip_event_t *ev){
+ SalOp *op=sal_find_out_subscribe(sal,ev->sid);
+ char *tmp;
+ osip_from_t *from=NULL;
+ osip_body_t *body=NULL;
+ SalPresenceStatus estatus=SalPresenceOffline;
+
+ ms_message("Receiving notify with sid=%i,nid=%i",ev->sid,ev->nid);
+
+ if (op==NULL){
+ ms_error("No operation related to this notify !");
+ return;
+ }
+ if (ev->request==NULL) return;
+
+ from=ev->request->from;
+ osip_message_get_body(ev->request,0,&body);
+ if (body==NULL){
+ ms_error("No body in NOTIFY");
+ return;
+ }
+ osip_from_to_str(from,&tmp);
+ if (strstr(body->body,"pending")!=NULL){
+ estatus=SalPresenceOffline;
+ }else if ((strstr(body->body,"online")!=NULL) || (strstr(body->body,"open")!=NULL)) {
+ estatus=SalPresenceOnline;
+ }else if (strstr(body->body,"busy")!=NULL){
+ estatus=SalPresenceBusy;
+ }else if (strstr(body->body,"berightback")!=NULL
+ || strstr(body->body,"in-transit")!=NULL ){
+ estatus=SalPresenceBerightback;
+ }else if (strstr(body->body,"away")!=NULL){
+ estatus=SalPresenceAway;
+ }else if (strstr(body->body,"onthephone")!=NULL
+ || strstr(body->body,"on-the-phone")!=NULL){
+ estatus=SalPresenceOnthephone;
+ }else if (strstr(body->body,"outtolunch")!=NULL
+ || strstr(body->body,"meal")!=NULL){
+ estatus=SalPresenceOuttolunch;
+ }else if (strstr(body->body,"closed")!=NULL){
+ estatus=SalPresenceOffline;
+ }else{
+ estatus=SalPresenceOffline;
+ }
+ ms_message("We are notified that %s has online status %i",tmp,estatus);
+ if (ev->ss_status==EXOSIP_SUBCRSTATE_TERMINATED) {
+ sal_remove_out_subscribe(sal,op->sid);
+ op->sid=-1;
+ op->did=-1;
+ ms_message("And outgoing subscription terminated by remote.");
+ }
+ sal->callbacks.presence_changed(op,estatus,NULL);
+ osip_free(tmp);
+}
+
+void sal_exosip_subscription_answered(Sal *sal,eXosip_event_t *ev){
+ SalOp *op=sal_find_out_subscribe(sal,ev->sid);
+ if (op==NULL){
+ ms_error("Subscription answered but no associated op !");
+ return;
+ }
+ op->did=ev->did;
+}
+
+void sal_exosip_subscription_closed(Sal *sal,eXosip_event_t *ev){
+ SalOp *op=sal_find_in_subscribe(sal,ev->sid);
+ if (op==NULL){
+ ms_error("Subscription closed but no associated op !");
+ return;
+ }
+ sal_remove_in_subscribe(sal,op->nid);
+ op->nid=-1;
+ op->did=0;
+}
+