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