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