]> sjero.net Git - linphone/blob - coreapi/sal_eXosip2_presence.c
add new api "linphone_core_interpret_url"
[linphone] / coreapi / sal_eXosip2_presence.c
1 /*
2 linphone
3 Copyright (C) 2010  Simon MORLAT (simon.morlat@free.fr)
4
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.
9
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.
14
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.
18 */
19
20
21 #include "sal_eXosip2.h"
22
23
24 static SalOp * sal_find_out_subscribe(Sal *sal, int sid){
25         const MSList *elem;
26         SalOp *op;
27         for(elem=sal->out_subscribes;elem!=NULL;elem=elem->next){
28                 op=(SalOp*)elem->data;
29                 if (op->sid==sid) return op;
30         }
31         return NULL;
32 }
33
34 static void sal_add_out_subscribe(Sal *sal, SalOp *op){
35         sal->out_subscribes=ms_list_append(sal->out_subscribes,op);
36 }
37
38 void sal_remove_out_subscribe(Sal *sal, SalOp *op){
39         sal->out_subscribes=ms_list_remove(sal->out_subscribes,op);
40 }
41
42 static SalOp * sal_find_in_subscribe(Sal *sal, int nid){
43         const MSList *elem;
44         SalOp *op;
45         for(elem=sal->in_subscribes;elem!=NULL;elem=elem->next){
46                 op=(SalOp*)elem->data;
47                 if (op->nid==nid) return op;
48         }
49         return NULL;
50 }
51
52 static void sal_add_in_subscribe(Sal *sal, SalOp *op){
53         sal->in_subscribes=ms_list_append(sal->in_subscribes,op);
54 }
55
56 void sal_remove_in_subscribe(Sal *sal, SalOp *op){
57         sal->in_subscribes=ms_list_remove(sal->in_subscribes,op);
58 }
59
60 int sal_text_send(SalOp *op, const char *from, const char *to, const char *msg){
61         osip_message_t *sip=NULL;
62         if (from)
63                 sal_op_set_from(op,from);
64         if (to)
65                 sal_op_set_to(op,to);
66
67         eXosip_lock();
68         eXosip_message_build_request(&sip,"MESSAGE",sal_op_get_to(op),
69             sal_op_get_from(op),sal_op_get_route(op));
70         osip_message_set_content_type(sip,"text/plain");
71         osip_message_set_body(sip,msg,strlen(msg));
72         eXosip_message_send_request(sip);
73         eXosip_unlock();
74         return 0;
75 }
76
77 /*presence Subscribe/notify*/
78 int sal_subscribe_presence(SalOp *op, const char *from, const char *to){
79         osip_message_t *msg;
80         if (from)
81                 sal_op_set_from(op,from);
82         if (to)
83                 sal_op_set_to(op,to);
84         sal_exosip_fix_route(op);
85         eXosip_lock();
86         eXosip_subscribe_build_initial_request(&msg,sal_op_get_to(op),sal_op_get_from(op),
87                 sal_op_get_route(op),"presence",600);
88         op->sid=eXosip_subscribe_send_initial_request(msg);
89         eXosip_unlock();
90         if (op->sid==-1){
91                 osip_message_free(msg);
92                 return -1;
93         }
94         sal_add_out_subscribe(op->base.root,op);
95         return 0;
96 }
97
98 int sal_unsubscribe(SalOp *op){
99         osip_message_t *msg=NULL;
100         if (op->did==-1){
101                 ms_error("cannot unsubscribe, no dialog !");
102                 return -1;
103         }
104         eXosip_lock();
105         eXosip_subscribe_build_refresh_request(op->did,&msg);
106         if (msg){
107                 osip_message_set_expires(msg,"0");
108                 eXosip_subscribe_send_refresh_request(op->did,msg);
109         }else ms_error("Could not build subscribe refresh request ! op->sid=%i, op->did=%i",
110                 op->sid,op->did);
111         eXosip_unlock();
112         return 0;
113 }
114
115 int sal_subscribe_accept(SalOp *op){
116         osip_message_t *msg;
117         eXosip_lock();
118         eXosip_insubscription_build_answer(op->tid,200,&msg);
119         eXosip_insubscription_send_answer(op->tid,200,msg);
120         eXosip_unlock();
121         return 0;
122 }
123
124 int sal_subscribe_decline(SalOp *op){
125         eXosip_lock();
126         eXosip_insubscription_send_answer(op->tid,401,NULL);
127         eXosip_unlock();
128         return 0;
129 }
130
131 static void add_presence_body(osip_message_t *notify, SalPresenceStatus online_status)
132 {
133         char buf[1000];
134 #ifdef SUPPORT_MSN
135         int atom_id = 1000;
136 #endif
137         char *contact_info;
138
139         osip_contact_t *ct=NULL;
140         osip_message_get_contact(notify,0,&ct);
141         osip_contact_to_str(ct,&contact_info);
142
143 #ifdef SUPPORT_MSN
144
145   if (online_status==SalPresenceOnline)
146     {
147       sprintf(buf, "<?xml version=\"1.0\"?>\n\
148 <!DOCTYPE presence\n\
149 PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
150 <presence>\n\
151 <presentity uri=\"%s;method=SUBSCRIBE\" />\n\
152 <atom id=\"%i\">\n\
153 <address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
154 <status status=\"open\" />\n\
155 <msnsubstatus substatus=\"online\" />\n\
156 </address>\n\
157 </atom>\n\
158 </presence>", contact_info, atom_id, contact_info);
159
160     }
161   else if (online_status==SalPresenceBusy)
162     {
163       sprintf(buf, "<?xml version=\"1.0\"?>\n\
164 <!DOCTYPE presence\n\
165 PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
166 <presence>\n\
167 <presentity uri=\"%s;method=SUBSCRIBE\" />\n\
168 <atom id=\"%i\">\n\
169 <address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
170 <status status=\"inuse\" />\n\
171 <msnsubstatus substatus=\"busy\" />\n\
172 </address>\n\
173 </atom>\n\
174 </presence>", contact_info, atom_id, contact_info);
175
176     }
177   else if (online_status==SalPresenceBerightback)
178     {
179       sprintf(buf, "<?xml version=\"1.0\"?>\n\
180 <!DOCTYPE presence\n\
181 PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
182 <presence>\n\
183 <presentity uri=\"%s;method=SUBSCRIBE\" />\n\
184 <atom id=\"%i\">\n\
185 <address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
186 <status status=\"inactive\" />\n\
187 <msnsubstatus substatus=\"berightback\" />\n\
188 </address>\n\
189 </atom>\n\
190 </presence>", contact_info, atom_id, contact_info);
191
192     }
193   else if (online_status==SalPresenceAway)
194     {
195       sprintf(buf, "<?xml version=\"1.0\"?>\n\
196 <!DOCTYPE presence\n\
197 PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
198 <presence>\n\
199 <presentity uri=\"%s;method=SUBSCRIBE\" />\n\
200 <atom id=\"%i\">\n\
201 <address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
202 <status status=\"inactive\" />\n\
203 <msnsubstatus substatus=\"away\" />\n\
204 </address>\n\
205 </atom>\n\
206 </presence>", contact_info, atom_id, contact_info);
207
208     }
209   else if (online_status==SalPresenceOnthephone)
210     {
211       sprintf(buf, "<?xml version=\"1.0\"?>\n\
212 <!DOCTYPE presence\n\
213 PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
214 <presence>\n\
215 <presentity uri=\"%s;method=SUBSCRIBE\" />\n\
216 <atom id=\"%i\">\n\
217 <address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
218 <status status=\"inuse\" />\n\
219 <msnsubstatus substatus=\"onthephone\" />\n\
220 </address>\n\
221 </atom>\n\
222 </presence>", contact_info, atom_id, contact_info);
223
224     }
225   else if (online_status==SalPresenceOuttolunch)
226     {
227       sprintf(buf, "<?xml version=\"1.0\"?>\n\
228 <!DOCTYPE presence\n\
229 PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
230 <presence>\n\
231 <presentity uri=\"%s;method=SUBSCRIBE\" />\n\
232 <atom id=\"%i\">\n\
233 <address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
234 <status status=\"inactive\" />\n\
235 <msnsubstatus substatus=\"outtolunch\" />\n\
236 </address>\n\
237 </atom>\n\
238 </presence>", contact_info, atom_id, contact_info);
239
240     }
241   else
242     {
243       sprintf(buf, "<?xml version=\"1.0\"?>\n\
244 <!DOCTYPE presence\n\
245 PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
246 <presence>\n\
247 <presentity uri=\"%s;method=SUBSCRIBE\" />\n\
248 <atom id=\"%i\">\n\
249 <address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
250 <status status=\"inactive\" />\n\
251 <msnsubstatus substatus=\"away\" />\n\
252 </address>\n\
253 </atom>\n\
254 </presence>", contact_info, atom_id, contact_info);
255     }
256
257   osip_message_set_body(notify, buf, strlen(buf));
258   osip_message_set_content_type(notify, "application/xpidf+xml");
259 #else
260
261   if (online_status==SalPresenceOnline)
262     {
263       sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
264 <presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
265           entity=\"%s\">\n\
266 <tuple id=\"sg89ae\">\n\
267 <status>\n\
268 <basic>open</basic>\n\
269 </status>\n\
270 <contact priority=\"0.8\">%s</contact>\n\
271 <note>online</note>\n\
272 </tuple>\n\
273 </presence>",
274               contact_info, contact_info);
275     }
276   else if (online_status==SalPresenceBusy)
277     {
278       sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
279 <presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
280           xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
281           entity=\"%s\">\n\
282 <tuple id=\"sg89ae\">\n\
283 <status>\n\
284 <basic>open</basic>\n\
285 <es:activities>\n\
286   <es:activity>busy</es:activity>\n\
287 </es:activities>\n\
288 </status>\n\
289 <contact priority=\"0.8\">%s</contact>\n\
290 <note>busy</note>\n\
291 </tuple>\n\
292 </presence>",
293               contact_info, contact_info);
294     }
295   else if (online_status==SalPresenceBerightback)
296     {
297       sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
298 <presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
299           xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
300           entity=\"%s\">\n\
301 <tuple id=\"sg89ae\">\n\
302 <status>\n\
303 <basic>open</basic>\n\
304 <es:activities>\n\
305   <es:activity>in-transit</es:activity>\n\
306 </es:activities>\n\
307 </status>\n\
308 <contact priority=\"0.8\">%s</contact>\n\
309 <note>be right back</note>\n\
310 </tuple>\n\
311 </presence>",
312               contact_info, contact_info);
313     }
314   else if (online_status==SalPresenceAway)
315     {
316       sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
317 <presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
318           xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
319           entity=\"%s\">\n\
320 <tuple id=\"sg89ae\">\n\
321 <status>\n\
322 <basic>open</basic>\n\
323 <es:activities>\n\
324   <es:activity>away</es:activity>\n\
325 </es:activities>\n\
326 </status>\n\
327 <contact priority=\"0.8\">%s</contact>\n\
328 <note>away</note>\n\
329 </tuple>\n\
330 </presence>",
331               contact_info, contact_info);
332     }
333   else if (online_status==SalPresenceOnthephone)
334     {
335       sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
336 <presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
337           xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
338           entity=\"%s\">\n\
339 <tuple id=\"sg89ae\">\n\
340 <status>\n\
341 <basic>open</basic>\n\
342 <es:activities>\n\
343   <es:activity>on-the-phone</es:activity>\n\
344 </es:activities>\n\
345 </status>\n\
346 <contact priority=\"0.8\">%s</contact>\n\
347 <note>on the phone</note>\n\
348 </tuple>\n\
349 </presence>",
350               contact_info, contact_info);
351     }
352   else if (online_status==SalPresenceOuttolunch)
353     {
354       sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
355 <presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
356           xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
357           entity=\"%s\">\n\
358 <tuple id=\"sg89ae\">\n\
359 <status>\n\
360 <basic>open</basic>\n\
361 <es:activities>\n\
362   <es:activity>meal</es:activity>\n\
363 </es:activities>\n\
364 </status>\n\
365 <contact priority=\"0.8\">%s</contact>\n\
366 <note>out to lunch</note>\n\
367 </tuple>\n\
368 </presence>",
369               contact_info, contact_info);
370     }
371   else
372     {
373       /* */
374       sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
375 <presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
376 xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
377 entity=\"%s\">\n%s",
378               contact_info,
379 "<tuple id=\"sg89ae\">\n\
380 <status>\n\
381 <basic>closed</basic>\n\
382 <es:activities>\n\
383   <es:activity>permanent-absence</es:activity>\n\
384 </es:activities>\n\
385 </status>\n\
386 </tuple>\n\
387 \n</presence>\n");
388     }
389   osip_message_set_body(notify, buf, strlen(buf));
390   osip_message_set_content_type(notify, "application/pidf+xml");
391
392 #endif
393         osip_free(contact_info);
394 }
395
396
397 int sal_notify_presence(SalOp *op, SalPresenceStatus status, const char *status_message){
398         osip_message_t *msg;
399         eXosip_ss_t ss=EXOSIP_SUBCRSTATE_ACTIVE;
400         if (op->nid==-1){
401                 ms_warning("Cannot notify, subscription was closed.");
402                 return -1;
403         }
404         
405         eXosip_lock();
406         eXosip_insubscription_build_notify(op->did,ss,DEACTIVATED,&msg);
407         if (msg!=NULL){
408                 const char *identity=sal_op_get_contact(op);
409                 if (identity==NULL) identity=sal_op_get_to(op);
410                 osip_message_set_contact(msg,identity);
411                 add_presence_body(msg,status);
412                 eXosip_insubscription_send_request(op->did,msg);
413         }else ms_error("could not create notify for incoming subscription.");
414         eXosip_unlock();
415         return 0;
416 }
417
418 int sal_notify_close(SalOp *op){
419         osip_message_t *msg;
420         eXosip_lock();
421         eXosip_insubscription_build_notify(op->did,EXOSIP_SUBCRSTATE_TERMINATED,DEACTIVATED,&msg);
422         if (msg!=NULL){
423                 const char *identity=sal_op_get_contact(op);
424                 if (identity==NULL) identity=sal_op_get_to(op);
425                 osip_message_set_contact(msg,identity);
426                 eXosip_insubscription_send_request(op->did,msg);
427         }else ms_error("sal_notify_close(): could not create notify for incoming subscription.");
428         eXosip_unlock();
429         return 0;
430 }
431
432 int sal_publish(SalOp *op, const char *from, const char *to, SalPresenceStatus presence_mode){
433         osip_message_t *pub;
434         int i;
435         char buf[1024];
436
437         if (presence_mode==SalPresenceOnline)
438         {
439           snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
440         <presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
441                   entity=\"%s\">\n\
442         <tuple id=\"sg89ae\">\n\
443         <status>\n\
444         <basic>open</basic>\n\
445         </status>\n\
446         <contact priority=\"0.8\">%s</contact>\n\
447         <note>online</note>\n\
448         </tuple>\n\
449         </presence>",
450                    from, from);
451         }
452         else if (presence_mode==SalPresenceBusy
453            ||presence_mode==SalPresenceDonotdisturb)
454         {
455           snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
456         <presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
457                   xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
458                   entity=\"%s\">\n\
459         <tuple id=\"sg89ae\">\n\
460         <status>\n\
461         <basic>open</basic>\n\
462         <es:activities>\n\
463         <es:activity>busy</es:activity>\n\
464         </es:activities>\n\
465         </status>\n\
466         <contact priority=\"0.8\">%s</contact>\n\
467         <note>busy</note>\n\
468         </tuple>\n\
469         </presence>",
470                   from, from);
471         }
472         else if (presence_mode==SalPresenceBerightback)
473         {
474                 snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
475         <presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
476                   xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
477                   entity=\"%s\">\n\
478         <tuple id=\"sg89ae\">\n\
479         <status>\n\
480         <basic>open</basic>\n\
481         <es:activities>\n\
482         <es:activity>in-transit</es:activity>\n\
483         </es:activities>\n\
484         </status>\n\
485         <contact priority=\"0.8\">%s</contact>\n\
486         <note>be right back</note>\n\
487         </tuple>\n\
488         </presence>",
489                   from,from);
490         }
491         else if (presence_mode==SalPresenceAway
492            ||presence_mode==SalPresenceMoved)
493         {
494                 snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
495         <presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
496                   xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
497                   entity=\"%s\">\n\
498         <tuple id=\"sg89ae\">\n\
499         <status>\n\
500         <basic>open</basic>\n\
501         <es:activities>\n\
502         <es:activity>away</es:activity>\n\
503         </es:activities>\n\
504         </status>\n\
505         <contact priority=\"0.8\">%s</contact>\n\
506         <note>away</note>\n\
507         </tuple>\n\
508         </presence>",
509                   from, from);
510         }
511         else if (presence_mode==SalPresenceOnthephone)
512         {
513           snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
514         <presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
515                   xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
516                   entity=\"%s\">\n\
517         <tuple id=\"sg89ae\">\n\
518         <status>\n\
519         <basic>open</basic>\n\
520         <es:activities>\n\
521         <es:activity>on-the-phone</es:activity>\n\
522         </es:activities>\n\
523         </status>\n\
524         <contact priority=\"0.8\">%s</contact>\n\
525         <note>on the phone</note>\n\
526         </tuple>\n\
527         </presence>",
528                   from, from);
529         }
530         else if (presence_mode==SalPresenceOuttolunch)
531         {
532           snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
533         <presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
534                   xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
535                   entity=\"%s\">\n\
536         <tuple id=\"sg89ae\">\n\
537         <status>\n\
538         <basic>open</basic>\n\
539         <es:activities>\n\
540         <es:activity>meal</es:activity>\n\
541         </es:activities>\n\
542         </status>\n\
543         <contact priority=\"0.8\">%s</contact>\n\
544         <note>out to lunch</note>\n\
545         </tuple>\n\
546         </presence>",
547                   from, from);
548         }
549         else{ 
550           /* offline */
551           snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
552         <presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
553         xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
554         entity=\"%s\">\n%s",
555                   from,
556         "<tuple id=\"sg89ae\">\n\
557         <status>\n\
558         <basic>closed</basic>\n\
559         <es:activities>\n\
560         <es:activity>permanent-absence</e:activity>\n\
561         </es:activities>\n\
562         </status>\n\
563         </tuple>\n\
564         \n</presence>\n");
565         }
566
567         i = eXosip_build_publish(&pub,from, to, NULL, "presence", "1800", "application/pidf+xml", buf);
568         if (i<0){
569                 ms_warning("Failed to build publish request.");
570                 return -1;
571         }
572
573         eXosip_lock();
574         i = eXosip_publish(pub, to); /* should update the sip-if-match parameter
575                                     from sip-etag  from last 200ok of PUBLISH */
576         eXosip_unlock();
577         if (i<0){
578           ms_message("Failed to send publish request.");
579           return -1;
580         }
581         return 0;
582 }
583
584 void sal_exosip_subscription_recv(Sal *sal, eXosip_event_t *ev){
585         SalOp *op=sal_op_new(sal);
586         char *tmp;
587         op->did=ev->did;
588         op->tid=ev->tid;
589         op->nid=ev->nid;
590         osip_from_to_str(ev->request->from,&tmp);
591         sal_op_set_from(op,tmp);
592         ms_free(tmp);
593         osip_from_to_str(ev->request->to,&tmp);
594         sal_op_set_to(op,tmp);
595         ms_free(tmp);
596         sal_add_in_subscribe(sal,op);
597         sal->callbacks.subscribe_received(op,sal_op_get_from(op));
598 }
599
600 void sal_exosip_notify_recv(Sal *sal, eXosip_event_t *ev){
601         SalOp *op=sal_find_out_subscribe(sal,ev->sid);
602         char *tmp;
603         osip_from_t *from=NULL;
604         osip_body_t *body=NULL;
605         SalPresenceStatus estatus=SalPresenceOffline;
606         
607         ms_message("Receiving notify with sid=%i,nid=%i",ev->sid,ev->nid);
608
609         if (op==NULL){
610                 ms_error("No operation related to this notify !");
611                 return;
612         }
613         if (ev->request==NULL) return;
614
615         from=ev->request->from;
616         osip_message_get_body(ev->request,0,&body);
617         if (body==NULL){
618                 ms_error("No body in NOTIFY");
619                 return;
620         }
621         osip_from_to_str(from,&tmp);
622         if (strstr(body->body,"pending")!=NULL){
623                 estatus=SalPresenceOffline;
624         }else if (strstr(body->body,"busy")!=NULL){
625                 estatus=SalPresenceBusy;
626         }else if (strstr(body->body,"berightback")!=NULL
627                         || strstr(body->body,"in-transit")!=NULL ){
628                 estatus=SalPresenceBerightback;
629         }else if (strstr(body->body,"away")!=NULL){
630                 estatus=SalPresenceAway;
631         }else if (strstr(body->body,"onthephone")!=NULL
632                 || strstr(body->body,"on-the-phone")!=NULL){
633                 estatus=SalPresenceOnthephone;
634         }else if (strstr(body->body,"outtolunch")!=NULL
635                         || strstr(body->body,"meal")!=NULL){
636                 estatus=SalPresenceOuttolunch;
637         }else if (strstr(body->body,"closed")!=NULL){
638                 estatus=SalPresenceOffline;
639         }else if ((strstr(body->body,"online")!=NULL) || (strstr(body->body,"open")!=NULL)) {
640                 estatus=SalPresenceOnline;
641         }else{
642                 estatus=SalPresenceOffline;
643         }
644         ms_message("We are notified that %s has online status %i",tmp,estatus);
645         if (ev->ss_status==EXOSIP_SUBCRSTATE_TERMINATED) {
646                 sal_remove_out_subscribe(sal,op);
647                 op->sid=-1;
648                 op->did=-1;
649                 ms_message("And outgoing subscription terminated by remote.");
650         }
651         sal->callbacks.notify(op,op->sid!=-1 ? SalSubscribeActive : SalSubscribeTerminated, estatus,NULL);
652         osip_free(tmp);
653 }
654
655 void sal_exosip_subscription_answered(Sal *sal,eXosip_event_t *ev){
656         SalOp *op=sal_find_out_subscribe(sal,ev->sid);
657         if (op==NULL){
658                 ms_error("Subscription answered but no associated op !");
659                 return;
660         }
661         op->did=ev->did;
662 }
663
664 void sal_exosip_subscription_closed(Sal *sal,eXosip_event_t *ev){
665         SalOp *op=sal_find_in_subscribe(sal,ev->sid);
666         if (op==NULL){
667                 ms_error("Subscription closed but no associated op !");
668                 return;
669         }
670         sal_remove_in_subscribe(sal,op);
671         op->nid=-1;
672         op->did=-1;
673 }
674
675