3 Copyright (C) 2010 Simon MORLAT (simon.morlat@free.fr)
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 #include "sal_eXosip2.h"
30 * REVISIT: this static variable forces every dialog to use the same presence description type depending
31 * on what is received on a single dialog...
33 static presence_type_t presence_style = PIDF;
35 SalOp * sal_find_out_subscribe(Sal *sal, int sid){
38 for(elem=sal->out_subscribes;elem!=NULL;elem=elem->next){
39 op=(SalOp*)elem->data;
40 if (op->sid==sid) return op;
42 ms_message("No op for sid %i",sid);
46 static void sal_add_out_subscribe(Sal *sal, SalOp *op){
47 sal->out_subscribes=ms_list_append(sal->out_subscribes,op);
50 void sal_remove_out_subscribe(Sal *sal, SalOp *op){
51 sal->out_subscribes=ms_list_remove(sal->out_subscribes,op);
54 SalOp * sal_find_in_subscribe(Sal *sal, int nid){
57 for(elem=sal->in_subscribes;elem!=NULL;elem=elem->next){
58 op=(SalOp*)elem->data;
59 if (op->nid==nid) return op;
64 static SalOp * sal_find_in_subscribe_by_call_id(Sal *sal, osip_call_id_t *call_id){
67 for(elem=sal->in_subscribes;elem!=NULL;elem=elem->next){
68 op=(SalOp*)elem->data;
69 if (op->call_id && osip_call_id_match(op->call_id,call_id)==0)
75 static void sal_add_in_subscribe(Sal *sal, SalOp *op, osip_message_t *subs){
76 osip_call_id_clone(subs->call_id,&op->call_id);
77 sal->in_subscribes=ms_list_append(sal->in_subscribes,op);
80 void sal_remove_in_subscribe(Sal *sal, SalOp *op){
81 sal->in_subscribes=ms_list_remove(sal->in_subscribes,op);
84 int sal_message_send(SalOp *op, const char *from, const char *to, const char* content_type, const char *msg){
85 osip_message_t *sip=NULL;
92 /* we are not currently in communication with the destination */
94 sal_op_set_from(op,from);
98 sal_exosip_fix_route(op);
100 eXosip_message_build_request(&sip,"MESSAGE",sal_op_get_to(op),
101 sal_op_get_from(op),sal_op_get_route(op));
103 osip_message_set_date(sip,ctime_r(&t,buf));
104 osip_message_set_content_type(sip,content_type);
105 if (msg) osip_message_set_body(sip,msg,strlen(msg));
106 sal_add_other(op->base.root,op,sip);
107 eXosip_message_send_request(sip);
109 ms_error("Could not build MESSAGE request !");
115 /* we are currently in communication with the destination */
117 //First we generate an INFO message to get the current call_id and a good cseq
118 eXosip_call_build_request(op->did,"MESSAGE",&sip);
121 ms_warning("could not get a build info to send MESSAGE, maybe no previous call established ?");
125 osip_message_set_content_type(sip,content_type);
126 if (msg) osip_message_set_body(sip,msg,strlen(msg));
127 eXosip_call_send_request(op->did,sip);
132 int sal_text_send(SalOp *op, const char *from, const char *to, const char *msg) {
133 return sal_message_send(op,from,to,"text/plain",msg);
135 /*presence Subscribe/notify*/
136 int sal_subscribe_presence(SalOp *op, const char *from, const char *to){
137 osip_message_t *msg=NULL;
139 sal_op_set_from(op,from);
141 sal_op_set_to(op,to);
142 sal_exosip_fix_route(op);
144 eXosip_subscribe_build_initial_request(&msg,sal_op_get_to(op),sal_op_get_from(op),
145 sal_op_get_route(op),"presence",600);
147 ms_error("Could not build subscribe request to %s",to);
151 if (op->base.contact){
152 _osip_list_set_empty(&msg->contacts,(void (*)(void*))osip_contact_free);
153 osip_message_set_contact(msg,op->base.contact);
155 op->sid=eXosip_subscribe_send_initial_request(msg);
158 osip_message_free(msg);
161 sal_add_out_subscribe(op->base.root,op);
165 int sal_unsubscribe(SalOp *op){
166 osip_message_t *msg=NULL;
168 ms_error("cannot unsubscribe, no dialog !");
172 eXosip_subscribe_build_refresh_request(op->did,&msg);
174 osip_message_set_expires(msg,"0");
175 eXosip_subscribe_send_refresh_request(op->did,msg);
176 }else ms_error("Could not build subscribe refresh request ! op->sid=%i, op->did=%i",
182 int sal_subscribe_accept(SalOp *op){
183 osip_message_t *msg=NULL;
185 eXosip_insubscription_build_answer(op->tid,202,&msg);
187 ms_error("Fail to build answer to subscribe.");
191 if (op->base.contact){
192 _osip_list_set_empty(&msg->contacts,(void (*)(void*))osip_contact_free);
193 osip_message_set_contact(msg,op->base.contact);
195 eXosip_insubscription_send_answer(op->tid,202,msg);
200 int sal_subscribe_decline(SalOp *op){
202 eXosip_insubscription_send_answer(op->tid,401,NULL);
207 static void mk_presence_body (const SalPresenceStatus online_status, const char *contact_info,
208 char *buf, size_t buflen, presence_type_t ptype) {
211 /* definition from http://msdn.microsoft.com/en-us/library/cc246202%28PROT.10%29.aspx */
214 if (online_status==SalPresenceOnline)
216 snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n"
217 "<!DOCTYPE presence PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n"
219 "<presentity uri=\"%s;method=SUBSCRIBE\" />\n"
221 "<address uri=\"%s\" priority=\"0.800000\">\n"
222 "<status status=\"open\" />\n"
223 "<msnsubstatus substatus=\"online\" />\n"
226 "</presence>", contact_info, atom_id, contact_info);
229 else if (online_status == SalPresenceBusy ||
230 online_status == SalPresenceDonotdisturb)
232 snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n"
233 "<!DOCTYPE presence PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n"
235 "<presentity uri=\"%s;method=SUBSCRIBE\" />\n"
237 "<address uri=\"%s\" priority=\"0.800000\">\n"
238 "<status status=\"inuse\" />\n"
239 "<msnsubstatus substatus=\"busy\" />\n"
241 "</atom>\n</presence>", contact_info, atom_id, contact_info);
244 else if (online_status==SalPresenceBerightback)
246 snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n"
247 "<!DOCTYPE presence PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n"
249 "<presentity uri=\"%s;method=SUBSCRIBE\" />\n"
251 "<address uri=\"%s\" priority=\"0.800000\">\n"
252 "<status status=\"open\" />\n"
253 "<msnsubstatus substatus=\"berightback\" />\n"
256 "</presence>", contact_info, atom_id, contact_info);
259 else if (online_status == SalPresenceAway ||
260 online_status == SalPresenceMoved)
262 snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n"
263 "<!DOCTYPE presence PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n"
265 "<presentity uri=\"%s;method=SUBSCRIBE\" />\n"
267 "<address uri=\"%s\" priority=\"0.800000\">\n"
268 "<status status=\"open\" />\n"
269 "<msnsubstatus substatus=\"away\" />\n"
272 "</presence>", contact_info, atom_id, contact_info);
275 else if (online_status==SalPresenceOnthephone)
277 snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n"
278 "<!DOCTYPE presence PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n"
280 "<presentity uri=\"%s;method=SUBSCRIBE\" />\n"
282 "<address uri=\"%s\" priority=\"0.800000\">\n"
283 "<status status=\"inuse\" />\n"
284 "<msnsubstatus substatus=\"onthephone\" />\n"
287 "</presence>", contact_info, atom_id, contact_info);
290 else if (online_status==SalPresenceOuttolunch)
292 snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n"
293 "<!DOCTYPE presence PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n"
295 "<presentity uri=\"%s;method=SUBSCRIBE\" />\n"
297 "<address uri=\"%s\" priority=\"0.800000\">\n"
298 "<status status=\"open\" />\n"
299 "<msnsubstatus substatus=\"outtolunch\" />\n"
302 "</presence>", contact_info, atom_id, contact_info);
307 snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n"
308 "<!DOCTYPE presence PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n"
310 "<presentity uri=\"%s;method=SUBSCRIBE\" />\n"
312 "<address uri=\"%s\" priority=\"0.800000\">\n"
313 "<status status=\"closed\" />\n"
314 "<msnsubstatus substatus=\"away\" />\n"
317 "</presence>", contact_info, atom_id, contact_info);
322 /* Couldn't find schema http://schemas.microsoft.com/2002/09/sip/presence
323 * so messages format has been taken from Communigate that can send notify
324 * requests with this schema
328 if (online_status==SalPresenceOnline)
330 snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n"
331 "<!DOCTYPE presence SYSTEM \"http://schemas.microsoft.com/2002/09/sip/presence\">\n"
333 "<presentity uri=\"%s;method=SUBSCRIBE\" />\n"
335 "<address uri=\"%s\">\n"
336 "<status status=\"open\" />\n"
337 "<msnsubstatus substatus=\"online\" />\n"
340 "</presence>", contact_info, atom_id, contact_info);
343 else if (online_status == SalPresenceBusy ||
344 online_status == SalPresenceDonotdisturb)
346 snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n"
347 "<!DOCTYPE presence SYSTEM \"http://schemas.microsoft.com/2002/09/sip/presence\">\n"
349 "<presentity uri=\"%s;method=SUBSCRIBE\" />\n"
351 "<address uri=\"%s\">\n"
352 "<status status=\"inuse\" />\n"
353 "<msnsubstatus substatus=\"busy\" />\n"
355 "</atom>\n</presence>", contact_info, atom_id, contact_info);
358 else if (online_status==SalPresenceBerightback)
360 snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n"
361 "<!DOCTYPE presence SYSTEM \"http://schemas.microsoft.com/2002/09/sip/presence\">\n"
363 "<presentity uri=\"%s;method=SUBSCRIBE\" />\n"
365 "<address uri=\"%s\">\n"
366 "<status status=\"inactive\" />\n"
367 "<msnsubstatus substatus=\"berightback\" />\n"
370 "</presence>", contact_info, atom_id, contact_info);
373 else if (online_status == SalPresenceAway ||
374 online_status == SalPresenceMoved)
376 snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n"
377 "<!DOCTYPE presence SYSTEM \"http://schemas.microsoft.com/2002/09/sip/presence\">\n"
379 "<presentity uri=\"%s;method=SUBSCRIBE\" />\n"
381 "<address uri=\"%s\">\n"
382 "<status status=\"inactive\" />\n"
383 "<msnsubstatus substatus=\"idle\" />\n"
386 "</presence>", contact_info, atom_id, contact_info);
389 else if (online_status==SalPresenceOnthephone)
391 snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n"
392 "<!DOCTYPE presence SYSTEM \"http://schemas.microsoft.com/2002/09/sip/presence\">\n"
394 "<presentity uri=\"%s;method=SUBSCRIBE\" />\n"
396 "<address uri=\"%s\">\n"
397 "<status status=\"inuse\" />\n"
398 "<msnsubstatus substatus=\"onthephone\" />\n"
401 "</presence>", contact_info, atom_id, contact_info);
404 else if (online_status==SalPresenceOuttolunch)
406 snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n"
407 "<!DOCTYPE presence SYSTEM \"http://schemas.microsoft.com/2002/09/sip/presence\">\n"
409 "<presentity uri=\"%s;method=SUBSCRIBE\" />\n"
411 "<address uri=\"%s\">\n"
412 "<status status=\"inactive\" />\n"
413 "<msnsubstatus substatus=\"outtolunch\" />\n"
416 "</presence>", contact_info, atom_id, contact_info);
421 snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n"
422 "<!DOCTYPE presence SYSTEM \"http://schemas.microsoft.com/2002/09/sip/presence\">\n"
424 "<presentity uri=\"%s;method=SUBSCRIBE\" />\n"
426 "<address uri=\"%s\">\n"
427 "<status status=\"closed\" />\n"
428 "<msnsubstatus substatus=\"offline\" />\n"
431 "</presence>", contact_info, atom_id, contact_info);
435 default: { /* use pidf+xml as default format, rfc4479, rfc4480, rfc3863 */
437 if (online_status==SalPresenceOnline)
439 snprintf(buf, buflen, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
440 "<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" "
441 "xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\" "
442 "xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" "
444 "<tuple id=\"sg89ae\">\n"
445 "<status><basic>open</basic></status>\n"
446 "<contact priority=\"0.8\">%s</contact>\n"
449 contact_info, contact_info);
451 else if (online_status == SalPresenceBusy ||
452 online_status == SalPresenceDonotdisturb)
454 snprintf(buf, buflen, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
455 "<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" "
456 "xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\" "
457 "xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" "
459 "<tuple id=\"sg89ae\">\n"
460 "<status><basic>open</basic></status>\n"
461 "<contact priority=\"0.8\">%s</contact>\n"
463 "<dm:person id=\"sg89aep\">\n"
464 "<rpid:activities><rpid:busy/></rpid:activities>\n"
467 contact_info, contact_info);
469 else if (online_status==SalPresenceBerightback)
471 snprintf(buf, buflen, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
472 "<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" "
473 "xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\" "
474 "xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" "
476 "<tuple id=\"sg89ae\">\n"
477 "<status><basic>open</basic></status>\n"
478 "<contact priority=\"0.8\">%s</contact>\n"
480 "<dm:person id=\"sg89aep\">\n"
481 "<rpid:activities><rpid:in-transit/></rpid:activities>\n"
484 contact_info, contact_info);
486 else if (online_status == SalPresenceAway ||
487 online_status == SalPresenceMoved)
489 snprintf(buf, buflen, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
490 "<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" "
491 "xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\" "
492 "xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" "
494 "<tuple id=\"sg89ae\">\n"
495 "<status><basic>open</basic></status>\n"
496 "<contact priority=\"0.8\">%s</contact>\n"
498 "<dm:person id=\"sg89aep\">\n"
499 "<rpid:activities><rpid:away/></rpid:activities>\n"
502 contact_info, contact_info);
504 else if (online_status==SalPresenceOnthephone)
506 snprintf(buf, buflen, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
507 "<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" "
508 "xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\" "
509 "xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" "
511 "<tuple id=\"sg89ae\">\n"
512 "<status><basic>open</basic></status>\n"
513 "<contact priority=\"0.8\">%s</contact>\n"
515 "<dm:person id=\"sg89aep\">\n"
516 "<rpid:activities><rpid:on-the-phone/></rpid:activities>\n"
519 contact_info, contact_info);
521 else if (online_status==SalPresenceOuttolunch)
523 snprintf(buf, buflen, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
524 "<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" "
525 "xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\" "
526 "xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" "
528 "<tuple id=\"7777\">\n"
529 "<status><basic>open</basic></status>\n"
530 "<contact priority=\"0.8\">%s</contact>\n"
532 "<dm:person id=\"78787878\">\n"
533 "<rpid:activities><rpid:meal/></rpid:activities>\n"
534 "<rpid:note>Out to lunch</rpid:note> \n"
537 contact_info, contact_info);
541 snprintf(buf, buflen, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
542 "<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" "
543 "xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\" "
544 "xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" "
546 "<tuple id=\"sg89ae\">\n"
547 "<status><basic>closed</basic></status>\n"
548 "<contact priority=\"0.8\">%s</contact>\n"
550 "</presence>\n", contact_info, contact_info);
558 static void add_presence_body(osip_message_t *notify, SalPresenceStatus online_status)
563 osip_from_t *from=NULL;
564 from=osip_message_get_from(notify);
565 osip_uri_to_str(from->url,&contact_info);
567 mk_presence_body (online_status, contact_info, buf, sizeof (buf), presence_style);
569 osip_message_set_body(notify, buf, strlen(buf));
570 osip_message_set_content_type(notify,
571 presence_style ? "application/xpidf+xml" : "application/pidf+xml");
573 osip_free(contact_info);
577 int sal_notify_presence(SalOp *op, SalPresenceStatus status, const char *status_message){
578 osip_message_t *msg=NULL;
579 eXosip_ss_t ss=EXOSIP_SUBCRSTATE_ACTIVE;
581 ms_warning("Cannot notify, subscription was closed.");
586 eXosip_insubscription_build_notify(op->did,ss,DEACTIVATED,&msg);
588 const char *identity=sal_op_get_contact(op);
589 if (identity==NULL) identity=sal_op_get_to(op);
590 _osip_list_set_empty(&msg->contacts,(void (*)(void*))osip_contact_free);
591 osip_message_set_contact(msg,identity);
592 add_presence_body(msg,status);
593 eXosip_insubscription_send_request(op->did,msg);
594 }else ms_error("could not create notify for incoming subscription.");
599 int sal_notify_close(SalOp *op){
600 osip_message_t *msg=NULL;
602 eXosip_insubscription_build_notify(op->did,EXOSIP_SUBCRSTATE_TERMINATED,DEACTIVATED,&msg);
604 const char *identity=sal_op_get_contact(op);
605 if (identity==NULL) identity=sal_op_get_to(op);
606 osip_message_set_contact(msg,identity);
607 add_presence_body(msg,SalPresenceOffline);
608 eXosip_insubscription_send_request(op->did,msg);
609 }else ms_error("sal_notify_close(): could not create notify for incoming subscription"
610 " did=%i, nid=%i",op->did,op->nid);
615 int sal_publish(SalOp *op, const char *from, const char *to, SalPresenceStatus presence_mode){
620 mk_presence_body (presence_mode, from, buf, sizeof (buf), presence_style);
622 i = eXosip_build_publish(&pub,from, to, NULL, "presence", "300",
623 presence_style ? "application/xpidf+xml" : "application/pidf+xml", buf);
625 ms_warning("Failed to build publish request.");
630 i = eXosip_publish(pub, to); /* should update the sip-if-match parameter
631 from sip-etag from last 200ok of PUBLISH */
634 ms_message("Failed to send publish request.");
637 sal_add_other(sal_op_get_sal(op),op,pub);
641 static void _sal_exosip_subscription_recv(Sal *sal, eXosip_event_t *ev){
642 SalOp *op=sal_op_new(sal);
647 osip_from_to_str(ev->request->from,&tmp);
648 sal_op_set_from(op,tmp);
650 osip_from_to_str(ev->request->to,&tmp);
651 sal_op_set_to(op,tmp);
653 sal_add_in_subscribe(sal,op,ev->request);
654 sal->callbacks.subscribe_received(op,sal_op_get_from(op));
657 void sal_exosip_subscription_recv(Sal *sal, eXosip_event_t *ev){
658 /*workaround a bug in eXosip: incoming SUBSCRIBES within dialog with expires: 0 are
659 recognized as new incoming subscribes*/
660 SalOp *op=sal_find_in_subscribe_by_call_id(sal,ev->request->call_id);
663 osip_message_header_get_byname(ev->request,"expires",0,&h);
664 if (h && h->hvalue && atoi(h->hvalue)==0){
665 ms_warning("This susbscribe is not a new one but terminates an old one.");
668 sal_exosip_subscription_closed(sal,ev);
670 osip_message_t *msg=NULL;
671 ms_warning("Probably a refresh subscribe");
673 eXosip_insubscription_build_answer(ev->tid,202,&msg);
674 eXosip_insubscription_send_answer(ev->tid,202,msg);
677 }else _sal_exosip_subscription_recv(sal,ev);
680 void sal_exosip_notify_recv(Sal *sal, eXosip_event_t *ev){
681 SalOp *op=sal_find_out_subscribe(sal,ev->sid);
683 osip_from_t *from=NULL;
684 osip_body_t *body=NULL;
685 SalPresenceStatus estatus=SalPresenceOffline;
687 ms_message("Receiving notify with sid=%i,nid=%i",ev->sid,ev->nid);
690 ms_error("No operation related to this notify !");
693 if (ev->request==NULL) return;
695 from=ev->request->from;
696 osip_message_get_body(ev->request,0,&body);
698 ms_error("No body in NOTIFY");
701 osip_from_to_str(from,&tmp);
702 if (strstr(body->body,"pending")!=NULL){
703 estatus=SalPresenceOffline;
704 }else if (strstr(body->body,"busy")!=NULL){
705 estatus=SalPresenceBusy;
706 }else if (strstr(body->body,"berightback")!=NULL
707 || strstr(body->body,"in-transit")!=NULL ){
708 estatus=SalPresenceBerightback;
709 }else if (strstr(body->body,"away")!=NULL
710 || strstr(body->body,"idle")){
711 estatus=SalPresenceAway;
712 }else if (strstr(body->body,"onthephone")!=NULL
713 || strstr(body->body,"on-the-phone")!=NULL){
714 estatus=SalPresenceOnthephone;
715 }else if (strstr(body->body,"outtolunch")!=NULL
716 || strstr(body->body,"meal")!=NULL){
717 estatus=SalPresenceOuttolunch;
718 }else if (strstr(body->body,"closed")!=NULL){
719 estatus=SalPresenceOffline;
720 }else if ((strstr(body->body,"online")!=NULL) || (strstr(body->body,"open")!=NULL)) {
721 estatus=SalPresenceOnline;
723 estatus=SalPresenceOffline;
725 ms_message("We are notified that %s has online status %i",tmp,estatus);
726 if (ev->ss_status==EXOSIP_SUBCRSTATE_TERMINATED) {
727 sal_remove_out_subscribe(sal,op);
730 ms_message("And outgoing subscription terminated by remote.");
732 sal->callbacks.notify_presence(op,op->sid!=-1 ? SalSubscribeActive : SalSubscribeTerminated, estatus,NULL);
734 /* try to detect presence message style used by server,
735 * and switch our presence messages to servers style */
736 if (strstr (body->body, "//IETF//DTD RFCxxxx XPIDF 1.0//EN") != NULL) {
737 presence_style = RFCxxxx;
738 } else if (strstr(body->body,"http://schemas.microsoft.com/2002/09/sip/presence")!=NULL) {
739 presence_style = MSOLDPRES;
745 void sal_exosip_subscription_answered(Sal *sal,eXosip_event_t *ev){
746 SalOp *op=sal_find_out_subscribe(sal,ev->sid);
748 ms_error("Subscription answered but no associated op !");
754 void sal_exosip_in_subscription_closed(Sal *sal, eXosip_event_t *ev){
755 SalOp *op=sal_find_in_subscribe(sal,ev->nid);
758 ms_error("Incoming subscription closed but no associated op !");
763 sal_remove_in_subscribe(sal,op);
767 osip_from_to_str(ev->request->from,&tmp);
768 sal->callbacks.subscribe_closed(op,tmp);
773 void sal_exosip_subscription_closed(Sal *sal,eXosip_event_t *ev){
774 SalOp *op=sal_find_out_subscribe(sal,ev->sid);
776 ms_error("Subscription closed but no associated op !");
779 sal_remove_out_subscribe(sal,op);
782 sal->callbacks.notify_presence(op,SalSubscribeTerminated, SalPresenceOffline,NULL);