1 /*
2   eXosip - This is the eXtended osip library.
3   Copyright (C) 2001-2020 Aymeric MOIZARD amoizard@antisip.com
4 
5   eXosip is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 2 of the License, or
8   (at your option) any later version.
9 
10   eXosip 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   In addition, as a special exception, the copyright holders give
20   permission to link the code of portions of this program with the
21   OpenSSL library under certain conditions as described in each
22   individual source file, and distribute linked combinations
23   including the two.
24   You must obey the GNU General Public License in all respects
25   for all of the code used other than OpenSSL.  If you modify
26   file(s) with this exception, you may extend this exception to your
27   version of the file(s), but you are not obligated to do so.  If you
28   do not wish to do so, delete this exception statement from your
29   version.  If you delete this exception statement from all source
30   files in the program, then also delete it here.
31 */
32 
33 #include "eXosip2.h"
34 
35 #include <eXosip2/eXosip.h>
36 
37 /* Private functions */
38 static void rcvregister_failure(osip_transaction_t *tr, osip_message_t *sip);
39 
_eXosip_register_contact_is_modified(eXosip_reg_t * jr,osip_message_t * request,osip_message_t * response)40 static void _eXosip_register_contact_is_modified(eXosip_reg_t *jr, osip_message_t *request, osip_message_t *response) {
41   osip_via_t *via;
42   osip_generic_param_t *br = NULL;
43 
44   char *received_viahost = NULL;
45   char *rport_viaport = NULL;
46   static char *port_5061 = "5061";
47   static char *port_5060 = "5060";
48 
49   osip_contact_t *contact;
50   char *contact_port = NULL;
51 
52   /* no action if expires=0 */
53   if (jr->r_reg_period == 0)
54     return;
55 
56   osip_message_get_via(response, 0, &via);
57 
58   if (via == NULL || via->protocol == NULL || via->host == NULL)
59     return;
60 
61   osip_message_get_contact(request, 0, &contact);
62 
63   if (contact == NULL || contact->url == NULL || contact->url->host == NULL)
64     return;
65 
66   /* via host:port info */
67 
68   osip_via_param_get_byname(via, "received", &br);
69 
70   if (br != NULL && br->gvalue != NULL)
71     received_viahost = br->gvalue;
72 
73   osip_via_param_get_byname(via, "rport", &br);
74 
75   if (br != NULL && br->gvalue == NULL)
76     return; /* the feature doesn't work if no rport is provided back */
77 
78   if (br != NULL && br->gvalue != NULL)
79     rport_viaport = br->gvalue;
80 
81   if (rport_viaport == NULL)
82     rport_viaport = via->port;
83 
84   if (rport_viaport == NULL) {
85     /* could be 5060 or 5061 */
86     if (osip_strcasecmp(via->protocol, "DTLS") == 0 || osip_strcasecmp(via->protocol, "TLS") == 0)
87       rport_viaport = port_5061;
88 
89     else
90       rport_viaport = port_5060;
91   }
92 
93   /* contact host:port info */
94   contact_port = contact->url->port;
95 
96   if (contact_port == NULL) {
97     /* could be 5060 or 5061 */
98     if (osip_strcasecmp(via->protocol, "DTLS") == 0 || osip_strcasecmp(via->protocol, "TLS") == 0)
99       contact_port = port_5061;
100 
101     else
102       contact_port = port_5060;
103   }
104 
105   if (jr->r_last_deletion > 0)
106     return; /* avoid loop. */
107 
108   if (osip_strcasecmp(contact_port, rport_viaport) != 0) {
109     /* the port parameter is different from contact. */
110     jr->registration_step = RS_DELETIONREQUIRED; /* proceed with deletion and re-registration of new contact */
111     jr->r_last_deletion = osip_getsystemtime(NULL);
112     return;
113   }
114 
115   if (received_viahost != NULL && osip_strcasecmp(received_viahost, contact->url->host) != 0) {
116     /* a received parameter was added and is different from contact. */
117     jr->registration_step = RS_DELETIONREQUIRED; /* proceed with deletion and re-registration of new contact */
118     jr->r_last_deletion = osip_getsystemtime(NULL);
119     return;
120   }
121 
122   if (received_viahost == NULL) {
123     if (osip_strcasecmp(via->host, contact->url->host) != 0) {
124       /* a received parameter was not added and local ip is different from contact: there is a possibility of IP change */
125       jr->registration_step = RS_DELETIONREQUIRED; /* proceed with deletion and re-registration of new contact */
126       jr->r_last_deletion = osip_getsystemtime(NULL);
127     }
128 
129     return;
130   }
131 }
132 
_eXosip_snd_message(struct eXosip_t * excontext,osip_transaction_t * tr,osip_message_t * sip,char * host,int port,int out_socket)133 int _eXosip_snd_message(struct eXosip_t *excontext, osip_transaction_t *tr, osip_message_t *sip, char *host, int port, int out_socket) {
134   int i;
135   osip_via_t *via;
136 
137   if (sip->status_code == 101)
138     return OSIP_SUCCESS;
139 
140   via = (osip_via_t *) osip_list_get(&sip->vias, 0);
141 
142   if (via == NULL || via->protocol == NULL)
143     return -1;
144 
145   if (host == NULL) {
146     if (MSG_IS_REQUEST(sip)) {
147       osip_route_t *route;
148 
149       osip_message_get_route(sip, 0, &route);
150 
151       if (route != NULL) {
152         osip_uri_param_t *lr_param = NULL;
153 
154         osip_uri_uparam_get_byname(route->url, "lr", &lr_param);
155 
156         if (lr_param == NULL)
157           route = NULL;
158       }
159 
160       if (route != NULL) {
161         port = 5060;
162 
163         if (route->url->port != NULL)
164           port = osip_atoi(route->url->port);
165 
166         host = route->url->host;
167 
168       } else {
169         /* search for maddr parameter */
170         osip_uri_param_t *maddr_param = NULL;
171         osip_uri_param_t *obr_param = NULL;
172         osip_uri_param_t *obp_param = NULL;
173 
174         osip_uri_uparam_get_byname(sip->req_uri, "maddr", &maddr_param);
175         host = NULL;
176 
177         if (maddr_param != NULL && maddr_param->gvalue != NULL)
178           host = maddr_param->gvalue;
179 
180         port = 5060;
181 
182         if (sip->req_uri->port != NULL)
183           port = osip_atoi(sip->req_uri->port);
184 
185         if (host == NULL) {
186           /* if ob was used in Contact, then exosip adds "x-obr" and "x-obp", thus, when
187              processing request, the ip/port destination are re-used here */
188           osip_uri_uparam_get_byname(sip->req_uri, "x-obr", &obr_param);
189           osip_uri_uparam_get_byname(sip->req_uri, "x-obp", &obp_param);
190 
191           if (obr_param != NULL && obr_param->gvalue != NULL && obp_param != NULL && obp_param->gvalue != NULL) {
192             host = obr_param->gvalue;
193             port = atoi(obp_param->gvalue);
194           }
195         }
196 
197         if (host == NULL)
198           host = sip->req_uri->host;
199       }
200 
201     } else {
202       osip_generic_param_t *maddr;
203       osip_generic_param_t *received;
204       osip_generic_param_t *rport;
205 
206       osip_via_param_get_byname(via, "maddr", &maddr);
207       osip_via_param_get_byname(via, "received", &received);
208       osip_via_param_get_byname(via, "rport", &rport);
209 
210       if (maddr != NULL && maddr->gvalue != NULL)
211         host = maddr->gvalue;
212 
213       else if (received != NULL && received->gvalue != NULL)
214         host = received->gvalue;
215 
216       else
217         host = via->host;
218 
219       if (rport == NULL || rport->gvalue == NULL) {
220         if (via->port != NULL)
221           port = osip_atoi(via->port);
222 
223         else
224           port = 5060;
225 
226       } else
227         port = osip_atoi(rport->gvalue);
228     }
229   }
230 
231   if (excontext->cbsipCallback != NULL) {
232     excontext->cbsipCallback(sip, 0);
233   }
234 
235   i = -1;
236   i = excontext->eXtl_transport.tl_send_message(excontext, tr, sip, host, port, out_socket);
237 
238   if (i != 0) {
239     return i;
240   }
241 
242   return OSIP_SUCCESS;
243 }
244 
cb_snd_message(osip_transaction_t * tr,osip_message_t * sip,char * host,int port,int out_socket)245 static int cb_snd_message(osip_transaction_t *tr, osip_message_t *sip, char *host, int port, int out_socket) {
246   struct eXosip_t *excontext = (struct eXosip_t *) osip_transaction_get_reserved1(tr);
247 
248   return _eXosip_snd_message(excontext, tr, sip, host, port, out_socket);
249 }
250 
cb_xixt_kill_transaction(int type,osip_transaction_t * tr)251 static void cb_xixt_kill_transaction(int type, osip_transaction_t *tr) {
252   int i;
253   struct eXosip_t *excontext = (struct eXosip_t *) osip_transaction_get_reserved1(tr);
254   struct timeval time_sub;
255   osip_timersub(&tr->destroyed_time, &tr->created_time, &time_sub);
256 
257   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO1, NULL, "[eXosip] [tid=%i] [cb_xixt_kill_transaction] [duration=%3li,%03lis]\n", tr->transactionid, time_sub.tv_sec, time_sub.tv_usec / 1000));
258   i = osip_remove_transaction(excontext->j_osip, tr);
259 
260   if (i != 0) {
261     OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_BUG, NULL, "[eXosip] [tid=%i] [cb_xixt_kill_transaction] **cannot remove transaction from the oSIP stack**\n", tr->transactionid));
262   }
263 
264   if (MSG_IS_REGISTER(tr->orig_request) && type == OSIP_NICT_KILL_TRANSACTION && tr->last_response == NULL) {
265     rcvregister_failure(tr, NULL);
266     return;
267   }
268 
269 #ifndef MINISIZE
270 
271   if (type == OSIP_NICT_KILL_TRANSACTION) {
272     eXosip_call_t *jc = (eXosip_call_t *) osip_transaction_get_reserved2(tr);
273     eXosip_dialog_t *jd = (eXosip_dialog_t *) osip_transaction_get_reserved3(tr);
274     eXosip_subscribe_t *js = (eXosip_subscribe_t *) osip_transaction_get_reserved5(tr);
275     eXosip_notify_t *jn = (eXosip_notify_t *) osip_transaction_get_reserved4(tr);
276 
277     if (jc == NULL && jn == NULL && js == NULL && tr->last_response == NULL) {
278       eXosip_event_t *je;
279 
280       je = _eXosip_event_init_for_message(EXOSIP_MESSAGE_REQUESTFAILURE, tr);
281       _eXosip_report_event(excontext, je);
282       return;
283     }
284 
285     if (jc != NULL && jn == NULL && js == NULL && tr->last_response == NULL) {
286       _eXosip_report_call_event(excontext, EXOSIP_CALL_MESSAGE_REQUESTFAILURE, jc, jd, tr);
287       return;
288     }
289 
290     /* no answer to a NOTIFY request! */
291     if (jn != NULL && MSG_IS_NOTIFY(tr->orig_request) && tr->last_response == NULL) {
292       /* delete the dialog! */
293       eXosip_event_t *je;
294 
295       je = _eXosip_event_init_for_notify(EXOSIP_NOTIFICATION_REQUESTFAILURE, jn, jd, tr);
296       _eXosip_report_event(excontext, je);
297 
298       REMOVE_ELEMENT(excontext->j_notifies, jn);
299       _eXosip_notify_free(excontext, jn);
300       return;
301     }
302 
303     if (jn != NULL && MSG_IS_NOTIFY(tr->orig_request) && tr->last_response != NULL && tr->last_response->status_code > 299) {
304       /* delete the dialog! */
305       if (tr->last_response->status_code != 407 && tr->last_response->status_code != 401) {
306         REMOVE_ELEMENT(excontext->j_notifies, jn);
307         _eXosip_notify_free(excontext, jn);
308         return;
309       }
310     }
311 
312     if (jn != NULL && MSG_IS_NOTIFY(tr->orig_request) && tr->last_response != NULL && tr->last_response->status_code > 199 && tr->last_response->status_code < 300) {
313       if (jn->n_ss_status == EXOSIP_SUBCRSTATE_TERMINATED) {
314         /* delete the dialog! */
315         REMOVE_ELEMENT(excontext->j_notifies, jn);
316         _eXosip_notify_free(excontext, jn);
317         return;
318       }
319     }
320 
321     /* no answer to a SUBSCRIBE request! */
322     if (js != NULL && (MSG_IS_SUBSCRIBE(tr->orig_request) || MSG_IS_REFER(tr->orig_request)) && (tr->last_response == NULL || tr->last_response->status_code <= 199)) {
323       eXosip_event_t *je;
324 
325       je = _eXosip_event_init_for_subscription(EXOSIP_SUBSCRIPTION_REQUESTFAILURE, js, jd, tr);
326       _eXosip_report_event(excontext, je);
327 
328       /* delete the dialog! */
329       REMOVE_ELEMENT(excontext->j_subscribes, js);
330       _eXosip_subscription_free(excontext, js);
331       return;
332     }
333 
334     /* detect SUBSCRIBE request that close the dialogs! */
335     if (js != NULL && (MSG_IS_SUBSCRIBE(tr->orig_request) || MSG_IS_REFER(tr->orig_request)) && tr->last_response != NULL && (tr->last_response->status_code == 401 || tr->last_response->status_code == 407)) {
336       /* delete the dialog later because we need to authenticate */
337     } else if (js != NULL && (MSG_IS_SUBSCRIBE(tr->orig_request) || MSG_IS_REFER(tr->orig_request))) {
338       osip_header_t *expires;
339 
340       osip_message_get_expires(tr->orig_request, 0, &expires);
341 
342       if (expires == NULL || expires->hvalue == NULL) {
343       } else if (0 == strcmp(expires->hvalue, "0")) {
344         REMOVE_ELEMENT(excontext->j_subscribes, js);
345         _eXosip_subscription_free(excontext, js);
346         return;
347       }
348     }
349   }
350 
351 #endif
352 }
353 
cb_rcvcancel(int type,osip_transaction_t * tr,osip_message_t * sip)354 static void cb_rcvcancel(int type, osip_transaction_t *tr, osip_message_t *sip) {
355   struct eXosip_t *excontext = (struct eXosip_t *) osip_transaction_get_reserved1(tr);
356   eXosip_call_t *jc = (eXosip_call_t *) osip_transaction_get_reserved2(tr);
357   eXosip_dialog_t *jd = (eXosip_dialog_t *) osip_transaction_get_reserved3(tr);
358 
359   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [tid=%i] [cb_rcvcancel]\n", tr->transactionid));
360 
361   if ((jd != NULL) && (jc != NULL)) {
362     /* do propagate CANCEL to the application */
363     _eXosip_report_call_event(excontext, EXOSIP_CALL_CANCELLED, jc, jd, tr);
364   }
365 }
366 
cb_rcvregister(int type,osip_transaction_t * tr,osip_message_t * sip)367 static void cb_rcvregister(int type, osip_transaction_t *tr, osip_message_t *sip) {
368   struct eXosip_t *excontext = (struct eXosip_t *) osip_transaction_get_reserved1(tr);
369   eXosip_event_t *je;
370 
371   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [tid=%i] [cb_rcvregister]\n", tr->transactionid));
372 
373   je = _eXosip_event_init_for_message(EXOSIP_MESSAGE_NEW, tr);
374   _eXosip_event_add(excontext, je);
375   return;
376 }
377 
cb_rcvrequest(int type,osip_transaction_t * tr,osip_message_t * sip)378 static void cb_rcvrequest(int type, osip_transaction_t *tr, osip_message_t *sip) {
379   struct eXosip_t *excontext = (struct eXosip_t *) osip_transaction_get_reserved1(tr);
380   eXosip_call_t *jc = (eXosip_call_t *) osip_transaction_get_reserved2(tr);
381   eXosip_dialog_t *jd = (eXosip_dialog_t *) osip_transaction_get_reserved3(tr);
382 
383 #ifndef MINISIZE
384   eXosip_subscribe_t *js = (eXosip_subscribe_t *) osip_transaction_get_reserved5(tr);
385   eXosip_notify_t *jn = (eXosip_notify_t *) osip_transaction_get_reserved4(tr);
386 #endif
387 
388   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [tid=%i] [cb_rcvrequest]\n", tr->transactionid));
389 
390   if (jc != NULL) {
391     OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [tid=%i] [cb_rcvrequest]\n", tr->transactionid));
392 
393     if (MSG_IS_BYE(sip)) {
394       if (excontext->autoanswer_bye == 0) {
395         /* not already sent */
396         _eXosip_report_call_event(excontext, EXOSIP_CALL_MESSAGE_NEW, jc, jd, tr);
397         _eXosip_report_call_event(excontext, EXOSIP_CALL_CLOSED, jc, jd, tr);
398       }
399 
400     } else
401       _eXosip_report_call_event(excontext, EXOSIP_CALL_MESSAGE_NEW, jc, jd, tr);
402 
403     return;
404   }
405 #ifndef MINISIZE
406 
407   else if (jn != NULL) {
408     if (MSG_IS_SUBSCRIBE(sip) || MSG_IS_REFER(sip)) {
409       eXosip_event_t *je;
410 
411       je = _eXosip_event_init_for_notify(EXOSIP_IN_SUBSCRIPTION_NEW, jn, jd, tr);
412       _eXosip_report_event(excontext, je);
413       return;
414     }
415 
416     return;
417 
418   } else if (js != NULL) {
419     if (MSG_IS_NOTIFY(sip)) {
420       eXosip_event_t *je;
421 
422       je = _eXosip_event_init_for_subscription(EXOSIP_SUBSCRIPTION_NOTIFY, js, jd, tr);
423       _eXosip_report_event(excontext, je);
424       return;
425     }
426 
427     return;
428   }
429 #endif
430 
431   else {
432     eXosip_event_t *je;
433 
434     je = _eXosip_event_init_for_message(EXOSIP_MESSAGE_NEW, tr);
435     _eXosip_event_add(excontext, je);
436     return;
437   }
438 }
439 
_eXosip_delete_reserved(osip_transaction_t * transaction)440 void _eXosip_delete_reserved(osip_transaction_t *transaction) {
441   if (transaction == NULL)
442     return;
443 
444   osip_transaction_set_reserved2(transaction, NULL);
445   osip_transaction_set_reserved3(transaction, NULL);
446   osip_transaction_set_reserved4(transaction, NULL);
447   osip_transaction_set_reserved5(transaction, NULL);
448 }
449 
cb_rcv1xx(int type,osip_transaction_t * tr,osip_message_t * sip)450 static void cb_rcv1xx(int type, osip_transaction_t *tr, osip_message_t *sip) {
451   struct eXosip_t *excontext = (struct eXosip_t *) osip_transaction_get_reserved1(tr);
452   eXosip_call_t *jc = (eXosip_call_t *) osip_transaction_get_reserved2(tr);
453   eXosip_dialog_t *jd = (eXosip_dialog_t *) osip_transaction_get_reserved3(tr);
454 
455 #ifndef MINISIZE
456   eXosip_subscribe_t *js = (eXosip_subscribe_t *) osip_transaction_get_reserved5(tr);
457   eXosip_notify_t *jn = (eXosip_notify_t *) osip_transaction_get_reserved4(tr);
458 #endif
459 
460   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [tid=%i] [cb_rcv1xx]\n", tr->transactionid));
461 
462   if (MSG_IS_RESPONSE_FOR(sip, "OPTIONS")) {
463     if (jc == NULL) {
464       eXosip_event_t *je;
465 
466       OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [tid=%i] [cb_rcv1xx] OPTIONS outside of any call\n", tr->transactionid));
467 
468       je = _eXosip_event_init_for_message(EXOSIP_MESSAGE_PROCEEDING, tr);
469       _eXosip_event_add(excontext, je);
470       return;
471     }
472 
473     _eXosip_report_call_event(excontext, EXOSIP_CALL_MESSAGE_PROCEEDING, jc, jd, tr);
474     return;
475   }
476 
477   if (MSG_IS_RESPONSE_FOR(sip, "INVITE") && MSG_TEST_CODE(sip, 100)) {
478     _eXosip_report_call_event(excontext, EXOSIP_CALL_PROCEEDING, jc, jd, tr);
479     return;
480   }
481 
482 #ifndef MINISIZE
483 
484   if (MSG_IS_RESPONSE_FOR(sip, "SUBSCRIBE") && MSG_TEST_CODE(sip, 100)) {
485     eXosip_event_t *je;
486 
487     je = _eXosip_event_init_for_subscription(EXOSIP_SUBSCRIPTION_PROCEEDING, js, jd, tr);
488     _eXosip_report_event(excontext, je);
489     return;
490   }
491 
492 #endif
493 
494   if (MSG_IS_RESPONSE_FOR(sip, "REFER") && MSG_TEST_CODE(sip, 100)) {
495     /* not easy to differentiate now (EXOSIP_SUBSCRIPTION_PROCEEDING or EXOSIP_CALL_MESSAGE_PROCEEDING) */
496     return;
497   }
498 
499   if (MSG_IS_RESPONSE_FOR(sip, "INVITE")
500 #ifndef MINISIZE
501       || MSG_IS_RESPONSE_FOR(sip, "REFER") || MSG_IS_RESPONSE_FOR(sip, "SUBSCRIBE")
502 #endif
503   ) {
504     int i;
505 
506 #ifndef MINISIZE
507 
508     /* for SUBSCRIBE, test if the dialog has been already created
509        with a previous NOTIFY */
510     if (jd == NULL && js != NULL && js->s_dialogs != NULL && (MSG_IS_RESPONSE_FOR(sip, "SUBSCRIBE") || MSG_IS_RESPONSE_FOR(sip, "REFER"))) {
511       /* find if existing dialog match the to tag */
512       osip_generic_param_t *tag;
513       int i;
514 
515       i = osip_to_get_tag(sip->to, &tag);
516 
517       if (i == 0 && tag != NULL && tag->gvalue != NULL) {
518         for (jd = js->s_dialogs; jd != NULL; jd = jd->next) {
519           if (0 == strcmp(jd->d_dialog->remote_tag, tag->gvalue)) {
520             OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO1, NULL, "[eXosip] [tid=%i] [cb_rcv1xx] found established early dialog for this subscription\n", tr->transactionid));
521             osip_transaction_set_reserved3(tr, jd);
522             break;
523           }
524         }
525       }
526     }
527 
528 #endif
529 
530     if (jd == NULL) {
531       /* This transaction initiate a dialog in the case of
532                                      INVITE (else it would be attached to a "jd" element. */
533       /* allocate a jd */
534 
535       i = _eXosip_dialog_init_as_uac(&jd, sip);
536 
537       if (i != 0) {
538         OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] [tid=%i] [cb_rcv1xx] cannot establish a dialog\n", tr->transactionid));
539         return;
540       }
541 
542       if (jc != NULL) {
543         ADD_ELEMENT(jc->c_dialogs, jd);
544         osip_transaction_set_reserved3(tr, jd);
545         _eXosip_update(excontext);
546       }
547 #ifndef MINISIZE
548 
549       else if (js != NULL) {
550         ADD_ELEMENT(js->s_dialogs, jd);
551         osip_transaction_set_reserved3(tr, jd);
552         _eXosip_update(excontext);
553 
554       } else if (jn != NULL) {
555         ADD_ELEMENT(jn->n_dialogs, jd);
556         osip_transaction_set_reserved3(tr, jd);
557         _eXosip_update(excontext);
558       }
559 #endif
560 
561       else {
562       }
563     } else {
564       if (jd->d_dialog == NULL) {
565       } else if (jd->d_dialog->remote_tag == NULL) {
566         osip_dialog_update_route_set_as_uac(jd->d_dialog, sip);
567         osip_dialog_update_tag_as_uac(jd->d_dialog, sip);
568 
569       } else {
570         osip_generic_param_t *tag;
571         int i;
572 
573         i = osip_to_get_tag(sip->to, &tag);
574 
575         if (tag != NULL && tag->gvalue != NULL && 0 == strcmp(jd->d_dialog->remote_tag, tag->gvalue)) {
576           /* Update only if it is the same dialog */
577           osip_dialog_update_route_set_as_uac(jd->d_dialog, sip);
578         }
579 #if 1 /* to be tested */
580 
581         else {
582           /* the best thing is to replace the current dialog
583              information... Much easier than creating a useless dialog! */
584           int current_local_cseq = jd->d_dialog->local_cseq;
585 
586           osip_dialog_free(jd->d_dialog);
587           i = osip_dialog_init_as_uac(&(jd->d_dialog), sip);
588 
589           if (i != 0) {
590             OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] [tid=%i] [cb_rcv1xx] cannot replace the dialog\n", tr->transactionid));
591 
592           } else {
593             jd->d_dialog->local_cseq = current_local_cseq;
594             OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL, "[eXosip] [tid=%i] [cb_rcv1xx] the dialog has been replaced with the new one from 1xx\n", tr->transactionid));
595           }
596         }
597 
598 #endif
599       }
600     }
601 
602     if (jd != NULL && MSG_IS_RESPONSE_FOR(sip, "INVITE") && sip->status_code < 180) {
603       _eXosip_check_allow_header(jd, sip);
604       _eXosip_report_call_event(excontext, EXOSIP_CALL_PROCEEDING, jc, jd, tr);
605 
606     } else if (jd != NULL && MSG_IS_RESPONSE_FOR(sip, "INVITE") && sip->status_code >= 180) {
607       _eXosip_check_allow_header(jd, sip);
608       _eXosip_report_call_event(excontext, EXOSIP_CALL_RINGING, jc, jd, tr);
609     }
610 #ifndef MINISIZE
611 
612     else if (jd != NULL && (MSG_IS_RESPONSE_FOR(sip, "SUBSCRIBE") || MSG_IS_RESPONSE_FOR(sip, "REFER"))) {
613       eXosip_event_t *je;
614 
615       je = _eXosip_event_init_for_subscription(EXOSIP_SUBSCRIPTION_PROCEEDING, js, jd, tr);
616       _eXosip_report_event(excontext, je);
617     }
618 
619 #endif
620 
621     if (jc != NULL && MSG_IS_RESPONSE_FOR(sip, "INVITE")) {
622       _eXosip_call_renew_expire_time(jc);
623     }
624   }
625 }
626 
cb_rcv2xx_4invite(osip_transaction_t * tr,osip_message_t * sip)627 static void cb_rcv2xx_4invite(osip_transaction_t *tr, osip_message_t *sip) {
628   struct eXosip_t *excontext = (struct eXosip_t *) osip_transaction_get_reserved1(tr);
629   int i;
630   eXosip_call_t *jc = (eXosip_call_t *) osip_transaction_get_reserved2(tr);
631   eXosip_dialog_t *jd = (eXosip_dialog_t *) osip_transaction_get_reserved3(tr);
632 
633   if (jc == NULL)
634     return;
635 
636   if (jd == NULL) {
637     /* This transaction initiate a dialog in the case of
638                                      INVITE (else it would be attached to a "jd" element. */
639     /* allocate a jd */
640     i = _eXosip_dialog_init_as_uac(&jd, sip);
641 
642     if (i != 0) {
643       OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] [tid=%i] [cb_rcv2xx_4invite] cannot establish a dialog\n", tr->transactionid));
644       return;
645     }
646 
647     ADD_ELEMENT(jc->c_dialogs, jd);
648     osip_transaction_set_reserved3(tr, jd);
649     _eXosip_update(excontext);
650 
651   } else {
652     /* Here is a special case:
653        We have initiated a dialog and we have received informationnal
654        answers from 2 or more remote SIP UA. Those answer can be
655        differentiated with the "To" header's tag.
656 
657        We have used the first informationnal answer to create a
658        dialog, but we now want to be sure the 200ok received is
659        for the dialog this dialog.
660 
661        We have to check the To tag and if it does not match, we
662        just have to modify the existing dialog and replace it. */
663     osip_generic_param_t *tag;
664     int i;
665 
666     i = osip_to_get_tag(sip->to, &tag);
667     i = 1; /* default is the same dialog */
668 
669     if (jd->d_dialog == NULL) {
670       /* There are real use-case where a BYE is received/processed before
671          the 200ok of the previous INVITE. In this case, jd->d_dialog is
672          empty and the transaction should be silently discarded. */
673       /* a ACK should still be sent... -but there is no dialog built- */
674       return;
675     }
676 
677     if (jd->d_dialog->remote_tag == NULL && tag == NULL) {
678     } /* non compliant remote UA -> assume it is the same dialog */
679     else if (jd->d_dialog->remote_tag != NULL && tag == NULL) {
680       i = 0;
681     } /* different dialog! */
682 
683     else if (jd->d_dialog->remote_tag == NULL && tag != NULL) {
684       i = 0;
685     } /* different dialog! */
686 
687     else if (jd->d_dialog->remote_tag != NULL && tag != NULL && tag->gvalue != NULL && 0 != strcmp(jd->d_dialog->remote_tag, tag->gvalue)) {
688       i = 0;
689     }
690 
691     /* different dialog! */
692     if (i == 1) { /* just update the dialog */
693       osip_dialog_update_route_set_as_uac(jd->d_dialog, sip);
694 
695       if (jd->d_dialog->remote_tag == NULL)
696         osip_dialog_update_tag_as_uac(jd->d_dialog, sip);
697 
698       osip_dialog_set_state(jd->d_dialog, DIALOG_CONFIRMED);
699 
700     } else {
701       /* the best thing is to replace the current dialog
702          information... Much easier than creating a useless dialog! */
703       int current_local_cseq = jd->d_dialog->local_cseq;
704 
705       osip_dialog_free(jd->d_dialog);
706       i = osip_dialog_init_as_uac(&(jd->d_dialog), sip);
707 
708       if (i != 0) {
709         OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] [tid=%i] [cb_rcv2xx_4invite] cannot replace the dialog\n", tr->transactionid));
710 
711       } else {
712         jd->d_dialog->local_cseq = current_local_cseq;
713         OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL, "[eXosip] [tid=%i] [cb_rcv2xx_4invite] the dialog has been replaced with the new one from 200ok\n", tr->transactionid));
714       }
715     }
716   }
717 
718   if (jd != NULL) {
719     osip_header_t *se_exp = NULL;
720     osip_header_t *se_exp_answer = NULL;
721 
722     _eXosip_check_allow_header(jd, sip);
723 
724     osip_message_header_get_byname(tr->orig_request, "session-expires", 0, &se_exp);
725 
726     if (se_exp == NULL)
727       osip_message_header_get_byname(tr->orig_request, "x", 0, &se_exp);
728 
729     osip_message_header_get_byname(sip, "session-expires", 0, &se_exp_answer);
730 
731     if (se_exp_answer == NULL)
732       osip_message_header_get_byname(sip, "x", 0, &se_exp_answer);
733 
734     if (se_exp != NULL && se_exp_answer != NULL) {
735       osip_content_disposition_t *exp_h = NULL;
736 
737       /* syntax of Session-Expires is equivalent to "Content-Disposition" */
738       osip_content_disposition_init(&exp_h);
739 
740       if (exp_h != NULL) {
741         osip_content_disposition_parse(exp_h, se_exp_answer->hvalue);
742 
743         if (exp_h->element != NULL) {
744           osip_generic_param_t *param = NULL;
745 
746           osip_generic_param_get_byname(&exp_h->gen_params, "refresher", &param);
747 
748           if (param == NULL) {
749             jd->d_refresher = 0; /* me? in which case? */
750 
751           } else {
752             if (osip_strcasecmp(param->gvalue, "uac") == 0)
753               jd->d_refresher = 0;
754 
755             else
756               jd->d_refresher = 1;
757           }
758 
759           jd->d_session_timer_start = osip_getsystemtime(NULL);
760           jd->d_session_timer_length = atoi(exp_h->element);
761 
762           if (jd->d_session_timer_length <= 90)
763             jd->d_session_timer_length = 90;
764         }
765 
766         osip_content_disposition_free(exp_h);
767         exp_h = NULL;
768       }
769 
770     } else if (se_exp != NULL && se_exp_answer == NULL && excontext->opt_sessiontimers_force > 0) {
771       /* not supported on remote end, but we want timer at UAC with  */
772       osip_content_disposition_t *exp_h = NULL;
773 
774       /* syntax of Session-Expires is equivalent to "Content-Disposition" */
775       osip_content_disposition_init(&exp_h);
776 
777       if (exp_h != NULL) {
778         osip_content_disposition_parse(exp_h, se_exp->hvalue);
779 
780         if (exp_h->element != NULL) {
781           jd->d_refresher = 0;
782           jd->d_session_timer_start = osip_getsystemtime(NULL);
783           jd->d_session_timer_length = atoi(exp_h->element);
784 
785           if (jd->d_session_timer_length <= 90)
786             jd->d_session_timer_length = 90;
787         }
788 
789         osip_content_disposition_free(exp_h);
790         exp_h = NULL;
791       }
792     }
793   }
794 
795   /* _eXosip_dialog_set_200ok (jd, sip); */
796 
797   _eXosip_report_call_event(excontext, EXOSIP_CALL_ANSWERED, jc, jd, tr);
798 
799   /* look for the SDP information and decide if this answer was for
800      an initial INVITE, an HoldCall, or a RetreiveCall */
801 
802   /* don't handle hold/unhold by now... */
803   /* _eXosip_update_audio_session(tr); */
804 }
805 
806 #ifndef MINISIZE
cb_rcv2xx_4subscribe(osip_transaction_t * tr,osip_message_t * sip)807 static void cb_rcv2xx_4subscribe(osip_transaction_t *tr, osip_message_t *sip) {
808   struct eXosip_t *excontext = (struct eXosip_t *) osip_transaction_get_reserved1(tr);
809   int i;
810   eXosip_dialog_t *jd = (eXosip_dialog_t *) osip_transaction_get_reserved3(tr);
811   eXosip_subscribe_t *js = (eXosip_subscribe_t *) osip_transaction_get_reserved5(tr);
812 
813   if (MSG_IS_RESPONSE_FOR(sip, "REFER")) {
814     osip_header_t *refer_sub;
815 
816     osip_message_header_get_byname(sip, "Refer-Sub", 0, &refer_sub);
817 
818     if (refer_sub != NULL && refer_sub->hvalue != NULL && osip_strncasecmp(refer_sub->hvalue, "false", 5) == 0) {
819       /* do not create JD, deletion will be immediate */
820       eXosip_event_t *je;
821 
822       je = _eXosip_event_init_for_subscription(EXOSIP_SUBSCRIPTION_ANSWERED, js, jd, tr);
823       _eXosip_report_event(excontext, je);
824       return;
825     }
826   }
827 
828   _eXosip_subscription_set_refresh_interval(js, sip);
829 
830   /* for SUBSCRIBE, test if the dialog has been already created
831      with a previous NOTIFY */
832   if (jd == NULL && js != NULL && js->s_dialogs != NULL && (MSG_IS_RESPONSE_FOR(sip, "SUBSCRIBE") || MSG_IS_RESPONSE_FOR(sip, "REFER"))) {
833     /* find if existing dialog match the to tag */
834     osip_generic_param_t *tag;
835     int i;
836 
837     i = osip_to_get_tag(sip->to, &tag);
838 
839     if (i == 0 && tag != NULL && tag->gvalue != NULL) {
840       for (jd = js->s_dialogs; jd != NULL; jd = jd->next) {
841         if (0 == strcmp(jd->d_dialog->remote_tag, tag->gvalue)) {
842           OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO1, NULL, "[eXosip] [tid=%i] [cb_rcv2xx_4subscribe] found established early dialog for this subscription\n", tr->transactionid));
843           osip_transaction_set_reserved3(tr, jd);
844           break;
845         }
846       }
847     }
848   }
849 
850   if (jd == NULL) {
851     /* This transaction initiate a dialog in the case of
852                                      SUBSCRIBE (else it would be attached to a "jd" element. */
853     /* allocate a jd */
854     i = _eXosip_dialog_init_as_uac(&jd, sip);
855 
856     if (i != 0) {
857       OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] [tid=%i] [cb_rcv2xx_4subscribe] cannot establish a dialog\n", tr->transactionid));
858       return;
859     }
860 
861     ADD_ELEMENT(js->s_dialogs, jd);
862     osip_transaction_set_reserved3(tr, jd);
863     _eXosip_update(excontext);
864 
865   } else {
866     osip_dialog_update_route_set_as_uac(jd->d_dialog, sip);
867 
868     if (jd->d_dialog->remote_tag == NULL)
869       osip_dialog_update_tag_as_uac(jd->d_dialog, sip);
870 
871     osip_dialog_set_state(jd->d_dialog, DIALOG_CONFIRMED);
872   }
873 
874   /* look for the body information */
875 
876   {
877     eXosip_event_t *je;
878 
879     je = _eXosip_event_init_for_subscription(EXOSIP_SUBSCRIPTION_ANSWERED, js, jd, tr);
880     _eXosip_report_event(excontext, je);
881   }
882 }
883 
884 #endif
885 
_eXosip_update_expires_according_to_contact(eXosip_reg_t * jreg,osip_transaction_t * tr,osip_message_t * sip)886 static int _eXosip_update_expires_according_to_contact(eXosip_reg_t *jreg, osip_transaction_t *tr, osip_message_t *sip) {
887   osip_list_iterator_t it;
888   osip_contact_t *co_register;
889   int maxval = 0;
890 
891   if (jreg == NULL)
892     return OSIP_BADPARAMETER;
893 
894   /* only update if only one Contact was in INVITE */
895   if (tr->orig_request == NULL)
896     return OSIP_BADPARAMETER;
897 
898   if (osip_list_size(&tr->orig_request->contacts) != 1)
899     return OSIP_SUCCESS;
900 
901   /* search for matching contact (line parameter must be equal) */
902   co_register = (osip_contact_t *) osip_list_get_first(&sip->contacts, &it);
903 
904   while (co_register != OSIP_SUCCESS) {
905     osip_uri_param_t *line_param = NULL;
906 
907     if (co_register->url != NULL)
908       osip_uri_uparam_get_byname(co_register->url, "line", &line_param);
909 
910     if (line_param != NULL && line_param->gvalue != NULL) {
911       if (osip_strcasecmp(jreg->r_line, line_param->gvalue) == 0) {
912         /* found contact */
913         int val;
914         osip_generic_param_t *exp_param = NULL;
915 
916         osip_contact_param_get_byname(co_register, "expires", &exp_param);
917 
918         if (exp_param != NULL && exp_param->gvalue != NULL) {
919           val = atoi(exp_param->gvalue);
920 
921           if (val > maxval) {
922             maxval = val;
923           }
924         }
925       }
926     }
927 
928     co_register = (osip_contact_t *) osip_list_get_next(&it);
929   }
930 
931   if (maxval == 0)
932     return OSIP_NOTFOUND;
933 
934   /* update only if expires value has REALLY be
935      decreased (more than one minutes):
936      In many cases value is decreased because a few seconds has
937      elapsed when server send the 200ok. */
938   if (maxval < jreg->r_reg_period - 15) {
939     jreg->r_reg_period = maxval;
940 
941   } else if (maxval > jreg->r_reg_period) {
942     jreg->r_reg_period = maxval;
943   }
944 
945   return OSIP_SUCCESS;
946 }
947 
cb_rcv2xx(int type,osip_transaction_t * tr,osip_message_t * sip)948 static void cb_rcv2xx(int type, osip_transaction_t *tr, osip_message_t *sip) {
949   struct eXosip_t *excontext = (struct eXosip_t *) osip_transaction_get_reserved1(tr);
950   eXosip_call_t *jc = (eXosip_call_t *) osip_transaction_get_reserved2(tr);
951   eXosip_dialog_t *jd = (eXosip_dialog_t *) osip_transaction_get_reserved3(tr);
952 
953 #ifndef MINISIZE
954   eXosip_subscribe_t *js = (eXosip_subscribe_t *) osip_transaction_get_reserved5(tr);
955   eXosip_notify_t *jn = (eXosip_notify_t *) osip_transaction_get_reserved4(tr);
956 #endif
957   osip_header_t *sub_state;
958   osip_header_t *refer_sub;
959   time_t now = osip_getsystemtime(NULL);
960 
961   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [tid=%i] [cb_rcv2xx]\n", tr->transactionid));
962 
963 #ifndef MINISIZE
964 
965   if (MSG_IS_RESPONSE_FOR(sip, "PUBLISH")) {
966     eXosip_pub_t *pub = NULL;
967     eXosip_event_t *je;
968     int i;
969 
970     i = _eXosip_pub_update(excontext, &pub, tr, sip);
971 
972     if (i != 0) {
973       OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] [tid=%i] [cb_rcv2xx] no publication to update\n", tr->transactionid));
974     }
975 
976     if (pub != NULL) {
977       /* update registration interval */
978       osip_header_t *exp;
979 
980       osip_message_header_get_byname(sip, "expires", 0, &exp);
981 
982       if (exp != NULL && exp->hvalue != NULL) {
983         int val = atoi(exp->hvalue);
984 
985         if (val > 0) {
986           /* update only if expires value has REALLY be
987              decreased (more than one minutes):
988              In many cases value is decreased because a few seconds has
989              elapsed when server send the 200ok. */
990           if (val < pub->p_period - 15) {
991             pub->p_period = val;
992           }
993         }
994       }
995 
996       pub->p_retry = 0; /* reset value */
997     }
998 
999     je = _eXosip_event_init_for_message(EXOSIP_MESSAGE_ANSWERED, tr);
1000     _eXosip_report_event(excontext, je);
1001     return;
1002   }
1003 
1004 #endif
1005 
1006   if (MSG_IS_RESPONSE_FOR(sip, "REGISTER")) {
1007     eXosip_event_t *je;
1008     eXosip_reg_t *jreg = NULL;
1009 
1010     /* find matching j_reg */
1011     _eXosip_reg_find(excontext, &jreg, tr);
1012 
1013     if (jreg != NULL) {
1014       if (jreg->registration_step != RS_DELETIONPROCEEDING) { /* step to remove contact */
1015         /* update registration interval */
1016         osip_header_t *exp;
1017 
1018         osip_message_header_get_byname(sip, "expires", 0, &exp);
1019 
1020         if (exp != NULL && exp->hvalue != NULL) {
1021           int val = atoi(exp->hvalue);
1022 
1023           if (val > 0) {
1024             /* update only if expires value has REALLY be
1025                decreased (more than one minutes):
1026                In many cases value is decreased because a few seconds has
1027                elapsed when server send the 200ok. */
1028             if (val < jreg->r_reg_period - 15) {
1029               jreg->r_reg_period = val;
1030             }
1031           }
1032         }
1033 
1034         _eXosip_update_expires_according_to_contact(jreg, tr, sip);
1035       }
1036 
1037       if (jreg->registration_step == RS_DELETIONPROCEEDING)
1038         jreg->registration_step = RS_MASQUERADINGREQUIRED; /* final registration with correct contact to be done */
1039 
1040       if (jreg->registration_step > RS_MASQUERADINGREQUIRED)
1041         _eXosip_register_contact_is_modified(jreg, tr->orig_request, sip);
1042 
1043       je = _eXosip_event_init_for_reg(EXOSIP_REGISTRATION_SUCCESS, jreg, tr);
1044       _eXosip_report_event(excontext, je);
1045       jreg->r_retry = 0; /* reset value */
1046       jreg->r_retryfailover = 0;
1047     }
1048 
1049     return;
1050   }
1051 
1052   if (jd != NULL)
1053     jd->d_retry = 0; /* reset marker for authentication */
1054 
1055   if (jc != NULL)
1056     jc->c_retry = 0; /* reset marker for authentication */
1057 
1058 #ifndef MINISIZE
1059 
1060   if (js != NULL)
1061     js->s_retry = 0; /* reset marker for authentication */
1062 
1063 #endif
1064 
1065   if (MSG_IS_RESPONSE_FOR(sip, "INVITE")) {
1066     cb_rcv2xx_4invite(tr, sip);
1067     return;
1068   }
1069 
1070   if (jc != NULL) {
1071     if (MSG_IS_RESPONSE_FOR(sip, "BYE")) {
1072       _eXosip_report_call_event(excontext, EXOSIP_CALL_MESSAGE_ANSWERED, jc, jd, tr);
1073       return;
1074     }
1075 
1076     if (jd != NULL)
1077       _eXosip_check_allow_header(jd, sip);
1078 
1079     if (MSG_IS_RESPONSE_FOR(sip, "UPDATE")) {
1080       if (jd != NULL) {
1081         osip_header_t *se_exp = NULL;
1082         osip_header_t *se_exp_answer = NULL;
1083 
1084         osip_message_header_get_byname(tr->orig_request, "session-expires", 0, &se_exp);
1085 
1086         if (se_exp == NULL)
1087           osip_message_header_get_byname(tr->orig_request, "x", 0, &se_exp);
1088 
1089         osip_message_header_get_byname(sip, "session-expires", 0, &se_exp_answer);
1090 
1091         if (se_exp_answer == NULL)
1092           osip_message_header_get_byname(sip, "x", 0, &se_exp_answer);
1093 
1094         if (se_exp != NULL && se_exp_answer != NULL) {
1095           osip_content_disposition_t *exp_h = NULL;
1096 
1097           /* syntax of Session-Expires is equivalent to "Content-Disposition" */
1098           osip_content_disposition_init(&exp_h);
1099 
1100           if (exp_h != NULL) {
1101             osip_content_disposition_parse(exp_h, se_exp_answer->hvalue);
1102 
1103             if (exp_h->element != NULL) {
1104               osip_generic_param_t *param = NULL;
1105 
1106               osip_generic_param_get_byname(&exp_h->gen_params, "refresher", &param);
1107 
1108               if (param == NULL) {
1109                 jd->d_refresher = 0; /* me? in which case? */
1110 
1111               } else {
1112                 if (osip_strcasecmp(param->gvalue, "uac") == 0)
1113                   jd->d_refresher = 0;
1114 
1115                 else
1116                   jd->d_refresher = 1;
1117               }
1118 
1119               jd->d_session_timer_start = osip_getsystemtime(NULL);
1120               jd->d_session_timer_length = atoi(exp_h->element);
1121 
1122               if (jd->d_session_timer_length <= 90)
1123                 jd->d_session_timer_length = 90;
1124             }
1125 
1126             osip_content_disposition_free(exp_h);
1127             exp_h = NULL;
1128           }
1129 
1130         } else if (se_exp != NULL && se_exp_answer == NULL && excontext->opt_sessiontimers_force > 0) {
1131           /* not supported on remote end, but we want timer at UAC with  */
1132           osip_content_disposition_t *exp_h = NULL;
1133 
1134           /* syntax of Session-Expires is equivalent to "Content-Disposition" */
1135           osip_content_disposition_init(&exp_h);
1136 
1137           if (exp_h != NULL) {
1138             osip_content_disposition_parse(exp_h, se_exp->hvalue);
1139 
1140             if (exp_h->element != NULL) {
1141               jd->d_refresher = 0;
1142               jd->d_session_timer_start = osip_getsystemtime(NULL);
1143               jd->d_session_timer_length = atoi(exp_h->element);
1144 
1145               if (jd->d_session_timer_length <= 90)
1146                 jd->d_session_timer_length = 90;
1147             }
1148 
1149             osip_content_disposition_free(exp_h);
1150             exp_h = NULL;
1151           }
1152         }
1153       }
1154 
1155     } else if (MSG_IS_RESPONSE_FOR(sip, "NOTIFY")) {
1156       if (jd != NULL) {
1157         /* get subscription-state */
1158         jd->implicit_subscription_expire_time = 0;
1159         osip_message_header_get_byname(tr->orig_request, "subscription-state", 0, &sub_state);
1160 
1161         if (sub_state != NULL && sub_state->hvalue != NULL) {
1162           if (0 == osip_strncasecmp(sub_state->hvalue, "active", 6) || 0 == osip_strncasecmp(sub_state->hvalue, "pending", 7)) {
1163             const char *tmp = strstr(sub_state->hvalue + 6, "expires");
1164             const char *ss_expires = NULL;
1165 
1166             if (tmp != NULL) {
1167               ss_expires = strchr(tmp + 7, '=');
1168               jd->implicit_subscription_expire_time = now + excontext->implicit_subscription_expires;
1169 
1170               if (ss_expires != NULL) {
1171                 int exp;
1172 
1173                 ss_expires++;
1174                 exp = osip_atoi(ss_expires);
1175 
1176                 if (exp >= 0 && exp < 600) {
1177                   jd->implicit_subscription_expire_time = now + exp;
1178                 }
1179               }
1180             }
1181 
1182             OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [tid=%i] [cb_rcv2xx] dialog marked for implicit-subscription [did=%i]\n", tr->transactionid, jd->d_id));
1183           }
1184         }
1185       }
1186 
1187     } else if (MSG_IS_RESPONSE_FOR(sip, "REFER")) {
1188       if (jd != NULL) {
1189         /* check for "Refer-Sub: false" */
1190         osip_message_header_get_byname(tr->orig_request, "Refer-Sub", 0, &refer_sub);
1191         jd->implicit_subscription_expire_time = now + excontext->implicit_subscription_expires;
1192 
1193         if ((refer_sub != NULL) && (refer_sub->hvalue != NULL) && (0 == osip_strncasecmp(refer_sub->hvalue, "false", 5))) {
1194           /* implicit subscription removed */
1195           jd->implicit_subscription_expire_time = 0;
1196           OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_WARNING, NULL, "[eXosip] [tid=%i] [cb_rcv2xx] dialog un-marked for implicit-subscription [did=%i]\n", tr->transactionid, jd->d_id));
1197         }
1198       }
1199     }
1200 
1201     _eXosip_report_call_event(excontext, EXOSIP_CALL_MESSAGE_ANSWERED, jc, jd, tr);
1202     return;
1203   }
1204 
1205 #ifndef MINISIZE
1206 
1207   if (js != NULL) {
1208     if (MSG_IS_RESPONSE_FOR(sip, "SUBSCRIBE") || MSG_IS_RESPONSE_FOR(sip, "REFER")) {
1209       cb_rcv2xx_4subscribe(tr, sip);
1210       return;
1211     }
1212 
1213     return;
1214   }
1215 
1216   if (jn != NULL) {
1217     if (MSG_IS_RESPONSE_FOR(sip, "NOTIFY") && jn != NULL) {
1218       eXosip_event_t *je;
1219       osip_header_t *sub_state;
1220 
1221       je = _eXosip_event_init_for_notify(EXOSIP_NOTIFICATION_ANSWERED, jn, jd, tr);
1222       _eXosip_report_event(excontext, je);
1223 
1224       osip_message_header_get_byname(tr->orig_request, "subscription-state", 0, &sub_state);
1225 
1226       if (sub_state == NULL || sub_state->hvalue == NULL) {
1227         /* UNCOMPLIANT UA without a subscription-state header */
1228       } else if (0 == osip_strncasecmp(sub_state->hvalue, "terminated", 10)) {
1229         /* delete the dialog! */
1230         if (jn != NULL) {
1231           REMOVE_ELEMENT(excontext->j_notifies, jn);
1232           _eXosip_notify_free(excontext, jn);
1233         }
1234       }
1235 
1236       return;
1237     }
1238 
1239     return;
1240   }
1241 
1242 #endif
1243 
1244   {
1245     eXosip_event_t *je;
1246 
1247     /* For all requests outside of calls */
1248     je = _eXosip_event_init_for_message(EXOSIP_MESSAGE_ANSWERED, tr);
1249     _eXosip_report_event(excontext, je);
1250     return;
1251   }
1252 }
1253 
_eXosip_delete_early_dialog(struct eXosip_t * excontext,eXosip_dialog_t * jd)1254 static void _eXosip_delete_early_dialog(struct eXosip_t *excontext, eXosip_dialog_t *jd) {
1255   if (jd == NULL) /* bug? */
1256     return;
1257 
1258   /* an early dialog was created, but the call is not established */
1259   if (jd->d_dialog != NULL && jd->d_dialog->state == DIALOG_EARLY) {
1260     osip_dialog_free(jd->d_dialog);
1261     jd->d_dialog = NULL;
1262     _eXosip_update(excontext); /* AMD 30/09/05 */
1263   }
1264 }
1265 
rcvregister_failure(osip_transaction_t * tr,osip_message_t * sip)1266 static void rcvregister_failure(osip_transaction_t *tr, osip_message_t *sip) {
1267   struct eXosip_t *excontext = (struct eXosip_t *) osip_transaction_get_reserved1(tr);
1268   eXosip_event_t *je;
1269   eXosip_reg_t *jreg = NULL;
1270 
1271   /* find matching j_reg */
1272   _eXosip_reg_find(excontext, &jreg, tr);
1273 
1274   if (jreg != NULL) {
1275     /* proceed with deletion and re-registration of new contact */
1276     if (jreg->registration_step > RS_MASQUERADINGREQUIRED && sip != NULL)
1277       _eXosip_register_contact_is_modified(jreg, tr->orig_request, sip);
1278 
1279     je = _eXosip_event_init_for_reg(EXOSIP_REGISTRATION_FAILURE, jreg, tr);
1280     _eXosip_report_event(excontext, je);
1281 
1282     if (tr->naptr_record != NULL && sip != NULL && sip->status_code == 503) {
1283       /* no matter which one, we'll move them all */
1284       osip_gettimeofday(&tr->naptr_record->sipudp_record.srventry[tr->naptr_record->sipudp_record.index].srv_is_broken, NULL);
1285       osip_gettimeofday(&tr->naptr_record->siptcp_record.srventry[tr->naptr_record->siptcp_record.index].srv_is_broken, NULL);
1286       osip_gettimeofday(&tr->naptr_record->siptls_record.srventry[tr->naptr_record->siptls_record.index].srv_is_broken, NULL);
1287       osip_gettimeofday(&tr->naptr_record->sipdtls_record.srventry[tr->naptr_record->sipdtls_record.index].srv_is_broken, NULL);
1288       osip_gettimeofday(&tr->naptr_record->sipsctp_record.srventry[tr->naptr_record->sipsctp_record.index].srv_is_broken, NULL);
1289       _eXosip_mark_registration_expired(excontext, sip->call_id->number);
1290     }
1291   }
1292 }
1293 
1294 #ifndef MINISIZE
1295 
cb_rcv3xx(int type,osip_transaction_t * tr,osip_message_t * sip)1296 static void cb_rcv3xx(int type, osip_transaction_t *tr, osip_message_t *sip) {
1297   struct eXosip_t *excontext = (struct eXosip_t *) osip_transaction_get_reserved1(tr);
1298   eXosip_call_t *jc = (eXosip_call_t *) osip_transaction_get_reserved2(tr);
1299   eXosip_dialog_t *jd = (eXosip_dialog_t *) osip_transaction_get_reserved3(tr);
1300   eXosip_subscribe_t *js = (eXosip_subscribe_t *) osip_transaction_get_reserved5(tr);
1301   eXosip_notify_t *jn = (eXosip_notify_t *) osip_transaction_get_reserved4(tr);
1302 
1303   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [tid=%i] [cb_rcv3xx]\n", tr->transactionid));
1304 
1305   if (MSG_IS_RESPONSE_FOR(sip, "PUBLISH")) {
1306     eXosip_event_t *je;
1307     eXosip_pub_t *pub;
1308     int i;
1309 
1310     i = _eXosip_pub_update(excontext, &pub, tr, sip);
1311 
1312     if (i != 0) {
1313       OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] [tid=%i] [cb_rcv3xx] no publication to update\n", tr->transactionid));
1314     }
1315 
1316     je = _eXosip_event_init_for_message(EXOSIP_MESSAGE_REDIRECTED, tr);
1317     _eXosip_report_event(excontext, je);
1318     return;
1319   }
1320 
1321   if (MSG_IS_RESPONSE_FOR(sip, "REGISTER")) {
1322     rcvregister_failure(tr, sip);
1323     return;
1324   }
1325 
1326   if (MSG_IS_RESPONSE_FOR(sip, "INVITE")) {
1327     _eXosip_report_call_event(excontext, EXOSIP_CALL_REDIRECTED, jc, jd, tr);
1328 
1329   } else if (MSG_IS_RESPONSE_FOR(sip, "NOTIFY") && jn != NULL) {
1330     eXosip_event_t *je;
1331 
1332     je = _eXosip_event_init_for_notify(EXOSIP_NOTIFICATION_REDIRECTED, jn, jd, tr);
1333     _eXosip_report_event(excontext, je);
1334 
1335   } else if (js != NULL && (MSG_IS_RESPONSE_FOR(sip, "SUBSCRIBE") || MSG_IS_RESPONSE_FOR(sip, "REFER"))) {
1336     eXosip_event_t *je;
1337 
1338     je = _eXosip_event_init_for_subscription(EXOSIP_SUBSCRIPTION_REDIRECTED, js, jd, tr);
1339     _eXosip_report_event(excontext, je);
1340 
1341   } else if (jc != NULL) {
1342     _eXosip_report_call_event(excontext, EXOSIP_CALL_MESSAGE_REDIRECTED, jc, jd, tr);
1343     return;
1344 
1345   } else if (jc == NULL && js == NULL && jn == NULL) {
1346     eXosip_event_t *je;
1347 
1348     /* For all requests outside of calls */
1349     je = _eXosip_event_init_for_message(EXOSIP_MESSAGE_REDIRECTED, tr);
1350     _eXosip_report_event(excontext, je);
1351     return;
1352   }
1353 
1354   if (jd == NULL)
1355     return;
1356 
1357   if (MSG_IS_RESPONSE_FOR(sip, "INVITE") || MSG_IS_RESPONSE_FOR(sip, "REFER") || MSG_IS_RESPONSE_FOR(sip, "SUBSCRIBE")) {
1358     _eXosip_delete_early_dialog(excontext, jd);
1359   }
1360 }
1361 
cb_rcv4xx(int type,osip_transaction_t * tr,osip_message_t * sip)1362 static void cb_rcv4xx(int type, osip_transaction_t *tr, osip_message_t *sip) {
1363   struct eXosip_t *excontext = (struct eXosip_t *) osip_transaction_get_reserved1(tr);
1364   eXosip_call_t *jc = (eXosip_call_t *) osip_transaction_get_reserved2(tr);
1365   eXosip_dialog_t *jd = (eXosip_dialog_t *) osip_transaction_get_reserved3(tr);
1366   eXosip_subscribe_t *js = (eXosip_subscribe_t *) osip_transaction_get_reserved5(tr);
1367   eXosip_notify_t *jn = (eXosip_notify_t *) osip_transaction_get_reserved4(tr);
1368 
1369   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [tid=%i] [cb_rcv4xx]\n", tr->transactionid));
1370 
1371   if (MSG_IS_RESPONSE_FOR(sip, "PUBLISH")) {
1372     eXosip_pub_t *pub;
1373     eXosip_event_t *je;
1374     int i;
1375 
1376     i = _eXosip_pub_update(excontext, &pub, tr, sip);
1377 
1378     if (i != 0) {
1379       OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] [tid=%i] [cb_rcv4xx] no publication to update\n", tr->transactionid));
1380     }
1381 
1382     /* For all requests outside of calls */
1383     je = _eXosip_event_init_for_message(EXOSIP_MESSAGE_REQUESTFAILURE, tr);
1384     _eXosip_report_event(excontext, je);
1385     return;
1386   }
1387 
1388   if (MSG_IS_RESPONSE_FOR(sip, "REGISTER")) {
1389     rcvregister_failure(tr, sip);
1390     return;
1391   }
1392 
1393   if (MSG_IS_RESPONSE_FOR(sip, "INVITE")) {
1394     _eXosip_report_call_event(excontext, EXOSIP_CALL_REQUESTFAILURE, jc, jd, tr);
1395 
1396   } else if (MSG_IS_RESPONSE_FOR(sip, "NOTIFY") && jn != NULL) {
1397     eXosip_event_t *je;
1398 
1399     je = _eXosip_event_init_for_notify(EXOSIP_NOTIFICATION_REQUESTFAILURE, jn, jd, tr);
1400     _eXosip_report_event(excontext, je);
1401 
1402   } else if (js != NULL && (MSG_IS_RESPONSE_FOR(sip, "SUBSCRIBE") || MSG_IS_RESPONSE_FOR(sip, "REFER"))) {
1403     eXosip_event_t *je;
1404 
1405     je = _eXosip_event_init_for_subscription(EXOSIP_SUBSCRIPTION_REQUESTFAILURE, js, jd, tr);
1406     _eXosip_report_event(excontext, je);
1407 
1408   } else if (jc != NULL) {
1409     _eXosip_report_call_event(excontext, EXOSIP_CALL_MESSAGE_REQUESTFAILURE, jc, jd, tr);
1410     return;
1411 
1412   } else if (jc == NULL && js == NULL && jn == NULL) {
1413     eXosip_event_t *je;
1414 
1415     /* For all requests outside of calls */
1416     je = _eXosip_event_init_for_message(EXOSIP_MESSAGE_REQUESTFAILURE, tr);
1417     _eXosip_report_event(excontext, je);
1418     return;
1419   }
1420 
1421   if (jd == NULL)
1422     return;
1423 
1424   if (MSG_IS_RESPONSE_FOR(sip, "INVITE") || MSG_IS_RESPONSE_FOR(sip, "REFER") || MSG_IS_RESPONSE_FOR(sip, "SUBSCRIBE")) {
1425     _eXosip_delete_early_dialog(excontext, jd);
1426   }
1427 }
1428 
cb_rcv5xx(int type,osip_transaction_t * tr,osip_message_t * sip)1429 static void cb_rcv5xx(int type, osip_transaction_t *tr, osip_message_t *sip) {
1430   struct eXosip_t *excontext = (struct eXosip_t *) osip_transaction_get_reserved1(tr);
1431   eXosip_call_t *jc = (eXosip_call_t *) osip_transaction_get_reserved2(tr);
1432   eXosip_dialog_t *jd = (eXosip_dialog_t *) osip_transaction_get_reserved3(tr);
1433   eXosip_subscribe_t *js = (eXosip_subscribe_t *) osip_transaction_get_reserved5(tr);
1434   eXosip_notify_t *jn = (eXosip_notify_t *) osip_transaction_get_reserved4(tr);
1435 
1436   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [tid=%i] [cb_rcv5xx]\n", tr->transactionid));
1437 
1438   if (MSG_IS_RESPONSE_FOR(sip, "PUBLISH")) {
1439     eXosip_pub_t *pub;
1440     eXosip_event_t *je;
1441     int i;
1442 
1443     i = _eXosip_pub_update(excontext, &pub, tr, sip);
1444 
1445     if (i != 0) {
1446       OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] [tid=%i] [cb_rcv5xx] no publication to update\n", tr->transactionid));
1447     }
1448 
1449     je = _eXosip_event_init_for_message(EXOSIP_MESSAGE_SERVERFAILURE, tr);
1450     _eXosip_report_event(excontext, je);
1451     return;
1452   }
1453 
1454   if (MSG_IS_RESPONSE_FOR(sip, "REGISTER")) {
1455     rcvregister_failure(tr, sip);
1456     return;
1457   }
1458 
1459   if (MSG_IS_RESPONSE_FOR(sip, "INVITE")) {
1460     _eXosip_report_call_event(excontext, EXOSIP_CALL_SERVERFAILURE, jc, jd, tr);
1461 
1462   } else if (MSG_IS_RESPONSE_FOR(sip, "NOTIFY") && jn != NULL) {
1463     eXosip_event_t *je;
1464 
1465     je = _eXosip_event_init_for_notify(EXOSIP_NOTIFICATION_SERVERFAILURE, jn, jd, tr);
1466     _eXosip_report_event(excontext, je);
1467 
1468   } else if (js != NULL && (MSG_IS_RESPONSE_FOR(sip, "SUBSCRIBE") || MSG_IS_RESPONSE_FOR(sip, "REFER"))) {
1469     eXosip_event_t *je;
1470 
1471     je = _eXosip_event_init_for_subscription(EXOSIP_SUBSCRIPTION_SERVERFAILURE, js, jd, tr);
1472     _eXosip_report_event(excontext, je);
1473 
1474   } else if (jc != NULL) {
1475     _eXosip_report_call_event(excontext, EXOSIP_CALL_MESSAGE_SERVERFAILURE, jc, jd, tr);
1476     return;
1477 
1478   } else if (jc == NULL && js == NULL && jn == NULL) {
1479     eXosip_event_t *je;
1480 
1481     /* For all requests outside of calls */
1482     je = _eXosip_event_init_for_message(EXOSIP_MESSAGE_SERVERFAILURE, tr);
1483     _eXosip_report_event(excontext, je);
1484     return;
1485   }
1486 
1487   if (jd == NULL)
1488     return;
1489 
1490   if (MSG_IS_RESPONSE_FOR(sip, "INVITE") || MSG_IS_RESPONSE_FOR(sip, "REFER") || MSG_IS_RESPONSE_FOR(sip, "SUBSCRIBE")) {
1491     _eXosip_delete_early_dialog(excontext, jd);
1492   }
1493 }
1494 
cb_rcv6xx(int type,osip_transaction_t * tr,osip_message_t * sip)1495 static void cb_rcv6xx(int type, osip_transaction_t *tr, osip_message_t *sip) {
1496   struct eXosip_t *excontext = (struct eXosip_t *) osip_transaction_get_reserved1(tr);
1497   eXosip_call_t *jc = (eXosip_call_t *) osip_transaction_get_reserved2(tr);
1498   eXosip_dialog_t *jd = (eXosip_dialog_t *) osip_transaction_get_reserved3(tr);
1499   eXosip_subscribe_t *js = (eXosip_subscribe_t *) osip_transaction_get_reserved5(tr);
1500   eXosip_notify_t *jn = (eXosip_notify_t *) osip_transaction_get_reserved4(tr);
1501 
1502   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [tid=%i] [cb_rcv6xx]\n", tr->transactionid));
1503 
1504   if (MSG_IS_RESPONSE_FOR(sip, "PUBLISH")) {
1505     eXosip_pub_t *pub;
1506     eXosip_event_t *je;
1507     int i;
1508 
1509     i = _eXosip_pub_update(excontext, &pub, tr, sip);
1510 
1511     if (i != 0) {
1512       OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] [tid=%i] [cb_rcv6xx] no publication to update\n", tr->transactionid));
1513     }
1514 
1515     je = _eXosip_event_init_for_message(EXOSIP_MESSAGE_GLOBALFAILURE, tr);
1516     _eXosip_report_event(excontext, je);
1517     return;
1518   }
1519 
1520   if (MSG_IS_RESPONSE_FOR(sip, "REGISTER")) {
1521     rcvregister_failure(tr, sip);
1522     return;
1523   }
1524 
1525   if (MSG_IS_RESPONSE_FOR(sip, "INVITE")) {
1526     _eXosip_report_call_event(excontext, EXOSIP_CALL_GLOBALFAILURE, jc, jd, tr);
1527 
1528   } else if (MSG_IS_RESPONSE_FOR(sip, "NOTIFY") && jn != NULL) {
1529     eXosip_event_t *je;
1530 
1531     je = _eXosip_event_init_for_notify(EXOSIP_NOTIFICATION_GLOBALFAILURE, jn, jd, tr);
1532     _eXosip_report_event(excontext, je);
1533 
1534   } else if (js != NULL && (MSG_IS_RESPONSE_FOR(sip, "SUBSCRIBE") || MSG_IS_RESPONSE_FOR(sip, "REFER"))) {
1535     eXosip_event_t *je;
1536 
1537     je = _eXosip_event_init_for_subscription(EXOSIP_SUBSCRIPTION_GLOBALFAILURE, js, jd, tr);
1538     _eXosip_report_event(excontext, je);
1539 
1540   } else if (jc != NULL) {
1541     _eXosip_report_call_event(excontext, EXOSIP_CALL_MESSAGE_GLOBALFAILURE, jc, jd, tr);
1542     return;
1543 
1544   } else if (jc == NULL && js == NULL && jn == NULL) {
1545     eXosip_event_t *je;
1546 
1547     /* For all requests outside of calls */
1548     je = _eXosip_event_init_for_message(EXOSIP_MESSAGE_GLOBALFAILURE, tr);
1549     _eXosip_report_event(excontext, je);
1550     return;
1551   }
1552 
1553   if (jd == NULL)
1554     return;
1555 
1556   if (MSG_IS_RESPONSE_FOR(sip, "INVITE") || MSG_IS_RESPONSE_FOR(sip, "REFER") || MSG_IS_RESPONSE_FOR(sip, "SUBSCRIBE")) {
1557     _eXosip_delete_early_dialog(excontext, jd);
1558   }
1559 }
1560 
1561 #else
1562 
1563 static void cb_rcv3456xx(int type, osip_transaction_t *tr, osip_message_t *sip, int invite_event, int call_event, int outcall_event);
1564 
cb_rcv3456xx(int type,osip_transaction_t * tr,osip_message_t * sip,int invite_event,int call_event,int outcall_event)1565 static void cb_rcv3456xx(int type, osip_transaction_t *tr, osip_message_t *sip, int invite_event, int call_event, int outcall_event) {
1566   struct eXosip_t *excontext = (struct eXosip_t *) osip_transaction_get_reserved1(tr);
1567   eXosip_call_t *jc = (eXosip_call_t *) osip_transaction_get_reserved2(tr);
1568   eXosip_dialog_t *jd = (eXosip_dialog_t *) osip_transaction_get_reserved3(tr);
1569 
1570   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [tid=%i] [cb_rcv3456xx]\n", tr->transactionid));
1571 
1572   if (MSG_IS_RESPONSE_FOR(sip, "REGISTER")) {
1573     rcvregister_failure(tr, sip);
1574     return;
1575   }
1576 
1577   if (MSG_IS_RESPONSE_FOR(sip, "INVITE")) {
1578     _eXosip_report_call_event(excontext, invite_event, jc, jd, tr);
1579 
1580   } else if (jc != NULL) {
1581     _eXosip_report_call_event(excontext, call_event, jc, jd, tr);
1582     return;
1583 
1584   } else if (jc == NULL) {
1585     eXosip_event_t *je;
1586 
1587     /* For all requests outside of calls */
1588     je = _eXosip_event_init_for_message(outcall_event, tr);
1589     _eXosip_report_event(excontext, je);
1590     return;
1591   }
1592 
1593   if (jd == NULL)
1594     return;
1595 
1596   if (MSG_IS_RESPONSE_FOR(sip, "INVITE")) {
1597     _eXosip_delete_early_dialog(excontext, jd);
1598   }
1599 }
1600 
cb_rcv3xx(int type,osip_transaction_t * tr,osip_message_t * sip)1601 static void cb_rcv3xx(int type, osip_transaction_t *tr, osip_message_t *sip) {
1602   cb_rcv3456xx(type, tr, sip, EXOSIP_CALL_REDIRECTED, EXOSIP_CALL_MESSAGE_REDIRECTED, EXOSIP_MESSAGE_REDIRECTED);
1603 }
1604 
cb_rcv4xx(int type,osip_transaction_t * tr,osip_message_t * sip)1605 static void cb_rcv4xx(int type, osip_transaction_t *tr, osip_message_t *sip) {
1606   cb_rcv3456xx(type, tr, sip, EXOSIP_CALL_REQUESTFAILURE, EXOSIP_CALL_MESSAGE_REQUESTFAILURE, EXOSIP_MESSAGE_REQUESTFAILURE);
1607 }
1608 
cb_rcv5xx(int type,osip_transaction_t * tr,osip_message_t * sip)1609 static void cb_rcv5xx(int type, osip_transaction_t *tr, osip_message_t *sip) {
1610   cb_rcv3456xx(type, tr, sip, EXOSIP_CALL_SERVERFAILURE, EXOSIP_CALL_MESSAGE_SERVERFAILURE, EXOSIP_MESSAGE_SERVERFAILURE);
1611 }
1612 
cb_rcv6xx(int type,osip_transaction_t * tr,osip_message_t * sip)1613 static void cb_rcv6xx(int type, osip_transaction_t *tr, osip_message_t *sip) {
1614   cb_rcv3456xx(type, tr, sip, EXOSIP_CALL_GLOBALFAILURE, EXOSIP_CALL_MESSAGE_GLOBALFAILURE, EXOSIP_MESSAGE_GLOBALFAILURE);
1615 }
1616 
1617 #endif
1618 
cb_snd123456xx(int type,osip_transaction_t * tr,osip_message_t * sip)1619 static void cb_snd123456xx(int type, osip_transaction_t *tr, osip_message_t *sip) {
1620   struct eXosip_t *excontext = (struct eXosip_t *) osip_transaction_get_reserved1(tr);
1621   eXosip_call_t *jc = (eXosip_call_t *) osip_transaction_get_reserved2(tr);
1622   eXosip_dialog_t *jd = (eXosip_dialog_t *) osip_transaction_get_reserved3(tr);
1623 
1624   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [tid=%i] [cb_snd123456xx]\n", tr->transactionid));
1625 
1626   if (jd == NULL)
1627     return;
1628 
1629   if (type == OSIP_IST_STATUS_1XX_SENT || type == OSIP_NIST_STATUS_1XX_SENT) {
1630     return;
1631   }
1632 
1633   if (type == OSIP_IST_STATUS_2XX_SENT || type == OSIP_NIST_STATUS_2XX_SENT) {
1634     return;
1635   }
1636 
1637   if (MSG_IS_RESPONSE_FOR(sip, "INVITE") || MSG_IS_RESPONSE_FOR(sip, "REFER") || MSG_IS_RESPONSE_FOR(sip, "SUBSCRIBE")) {
1638     _eXosip_delete_early_dialog(excontext, jd);
1639   }
1640 
1641   if (MSG_IS_RESPONSE_FOR(sip, "INVITE")) {
1642     /* only close calls if this is the initial INVITE */
1643     if (jc != NULL && tr == jc->c_inc_tr) {
1644       _eXosip_report_call_event(excontext, EXOSIP_CALL_CLOSED, jc, jd, tr);
1645     }
1646   }
1647 }
1648 
1649 #ifndef MINISIZE
1650 
cb_rcvinvite(int type,osip_transaction_t * tr,osip_message_t * sip)1651 static void cb_rcvinvite(int type, osip_transaction_t *tr, osip_message_t *sip) {
1652   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [tid=%i] [cb_rcvinvite]\n", tr->transactionid));
1653 }
1654 
cb_rcvack(int type,osip_transaction_t * tr,osip_message_t * sip)1655 static void cb_rcvack(int type, osip_transaction_t *tr, osip_message_t *sip) {
1656   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [tid=%i] [cb_rcvack]\n", tr->transactionid));
1657 }
1658 
cb_rcvack2(int type,osip_transaction_t * tr,osip_message_t * sip)1659 static void cb_rcvack2(int type, osip_transaction_t *tr, osip_message_t *sip) {
1660   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [tid=%i] [cb_rcvack2]\n", tr->transactionid));
1661 }
1662 
cb_sndinvite(int type,osip_transaction_t * tr,osip_message_t * sip)1663 static void cb_sndinvite(int type, osip_transaction_t *tr, osip_message_t *sip) {
1664   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [tid=%i] [cb_sndinvite]\n", tr->transactionid));
1665 }
1666 
cb_sndack(int type,osip_transaction_t * tr,osip_message_t * sip)1667 static void cb_sndack(int type, osip_transaction_t *tr, osip_message_t *sip) {
1668   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [tid=%i] [cb_sndack]\n", tr->transactionid));
1669 }
1670 
cb_sndregister(int type,osip_transaction_t * tr,osip_message_t * sip)1671 static void cb_sndregister(int type, osip_transaction_t *tr, osip_message_t *sip) {
1672   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [tid=%i] [cb_sndregister]\n", tr->transactionid));
1673 }
1674 
cb_sndbye(int type,osip_transaction_t * tr,osip_message_t * sip)1675 static void cb_sndbye(int type, osip_transaction_t *tr, osip_message_t *sip) {
1676   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [tid=%i] [cb_sndbye]\n", tr->transactionid));
1677 }
1678 
cb_sndcancel(int type,osip_transaction_t * tr,osip_message_t * sip)1679 static void cb_sndcancel(int type, osip_transaction_t *tr, osip_message_t *sip) {
1680   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [tid=%i] [cb_sndcancel]\n", tr->transactionid));
1681 }
1682 
cb_sndinfo(int type,osip_transaction_t * tr,osip_message_t * sip)1683 static void cb_sndinfo(int type, osip_transaction_t *tr, osip_message_t *sip) {
1684   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [tid=%i] [cb_sndinfo]\n", tr->transactionid));
1685 }
1686 
cb_sndoptions(int type,osip_transaction_t * tr,osip_message_t * sip)1687 static void cb_sndoptions(int type, osip_transaction_t *tr, osip_message_t *sip) {
1688   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [tid=%i] [cb_sndoptions]\n", tr->transactionid));
1689 }
1690 
cb_sndnotify(int type,osip_transaction_t * tr,osip_message_t * sip)1691 static void cb_sndnotify(int type, osip_transaction_t *tr, osip_message_t *sip) {
1692   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [tid=%i] [cb_sndnotify]\n", tr->transactionid));
1693 }
1694 
cb_sndsubscribe(int type,osip_transaction_t * tr,osip_message_t * sip)1695 static void cb_sndsubscribe(int type, osip_transaction_t *tr, osip_message_t *sip) {
1696   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [tid=%i] [cb_sndsubscribe]\n", tr->transactionid));
1697 }
1698 
cb_sndunkrequest(int type,osip_transaction_t * tr,osip_message_t * sip)1699 static void cb_sndunkrequest(int type, osip_transaction_t *tr, osip_message_t *sip) {
1700   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [tid=%i] [cb_sndunkrequest]\n", tr->transactionid));
1701 }
1702 
cb_rcvresp_retransmission(int type,osip_transaction_t * tr,osip_message_t * sip)1703 static void cb_rcvresp_retransmission(int type, osip_transaction_t *tr, osip_message_t *sip) {
1704   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO1, NULL, "[eXosip] [tid=%i] [cb_rcvresp_retransmission]\n", tr->transactionid));
1705 }
1706 
cb_sndreq_retransmission(int type,osip_transaction_t * tr,osip_message_t * sip)1707 static void cb_sndreq_retransmission(int type, osip_transaction_t *tr, osip_message_t *sip) {
1708   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO1, NULL, "[eXosip] [tid=%i] [cb_sndreq_retransmission]\n", tr->transactionid));
1709 }
1710 
cb_sndresp_retransmission(int type,osip_transaction_t * tr,osip_message_t * sip)1711 static void cb_sndresp_retransmission(int type, osip_transaction_t *tr, osip_message_t *sip) {
1712   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO1, NULL, "[eXosip] [tid=%i] [cb_sndresp_retransmission]\n", tr->transactionid));
1713 }
1714 
cb_rcvreq_retransmission(int type,osip_transaction_t * tr,osip_message_t * sip)1715 static void cb_rcvreq_retransmission(int type, osip_transaction_t *tr, osip_message_t *sip) {
1716   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO1, NULL, "[eXosip] [tid=%i] [cb_rcvreq_retransmission]\n", tr->transactionid));
1717 }
1718 
1719 #endif
1720 
cb_transport_error(int type,osip_transaction_t * tr,int error)1721 static void cb_transport_error(int type, osip_transaction_t *tr, int error) {
1722   struct eXosip_t *excontext = (struct eXosip_t *) osip_transaction_get_reserved1(tr);
1723 
1724 #ifndef MINISIZE
1725   eXosip_subscribe_t *js = (eXosip_subscribe_t *) osip_transaction_get_reserved5(tr);
1726   eXosip_notify_t *jn = (eXosip_notify_t *) osip_transaction_get_reserved4(tr);
1727 #endif
1728 
1729   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO1, NULL, "[eXosip] [tid=%i] [cb_transport_error]\n", tr->transactionid));
1730 
1731   if (type == OSIP_ICT_TRANSPORT_ERROR) {
1732     eXosip_call_t *jc = (eXosip_call_t *) osip_transaction_get_reserved2(tr);
1733     eXosip_dialog_t *jd = (eXosip_dialog_t *) osip_transaction_get_reserved3(tr);
1734 
1735     if (jc == NULL && jd == NULL)
1736       return;
1737 
1738     _eXosip_report_call_event(excontext, EXOSIP_CALL_NOANSWER, jc, jd, tr);
1739   }
1740 
1741   if (type == OSIP_NICT_TRANSPORT_ERROR) {
1742     osip_naptr_t *naptr_record = tr->naptr_record;
1743     if (naptr_record != NULL && naptr_record->naptr_state == OSIP_NAPTR_STATE_SRVDONE && (MSG_IS_REGISTER(tr->orig_request) || MSG_IS_OPTIONS(tr->orig_request))) {
1744 
1745       if (osip_strcasecmp(excontext->eXtl_transport.proto_name, "UDP") == 0)
1746         eXosip_dnsutils_rotate_srv(&naptr_record->sipudp_record);
1747       else if (osip_strcasecmp(excontext->eXtl_transport.proto_name, "TCP") == 0)
1748         eXosip_dnsutils_rotate_srv(&naptr_record->siptcp_record);
1749       else if (osip_strcasecmp(excontext->eXtl_transport.proto_name, "TLS") == 0)
1750         eXosip_dnsutils_rotate_srv(&naptr_record->siptls_record);
1751       else if (osip_strcasecmp(excontext->eXtl_transport.proto_name, "DTLS-UDP") == 0)
1752         eXosip_dnsutils_rotate_srv(&naptr_record->sipdtls_record);
1753     }
1754   }
1755 #ifndef MINISIZE
1756 
1757   if (jn == NULL && js == NULL)
1758     return;
1759 
1760   if (jn != NULL && MSG_IS_NOTIFY(tr->orig_request) && type == OSIP_NICT_TRANSPORT_ERROR) {
1761     /* delete the dialog! */
1762     REMOVE_ELEMENT(excontext->j_notifies, jn);
1763     _eXosip_notify_free(excontext, jn);
1764   }
1765 
1766   if (js != NULL && (MSG_IS_SUBSCRIBE(tr->orig_request) || MSG_IS_REFER(tr->orig_request)) && type == OSIP_NICT_TRANSPORT_ERROR) {
1767     /* delete the dialog! */
1768     REMOVE_ELEMENT(excontext->j_subscribes, js);
1769     _eXosip_subscription_free(excontext, js);
1770   }
1771 
1772 #endif
1773 }
1774 
_eXosip_set_callbacks(osip_t * osip)1775 int _eXosip_set_callbacks(osip_t *osip) {
1776   /* register all callbacks */
1777 
1778   osip_set_cb_send_message(osip, &cb_snd_message);
1779 
1780   osip_set_kill_transaction_callback(osip, OSIP_ICT_KILL_TRANSACTION, &cb_xixt_kill_transaction);
1781   osip_set_kill_transaction_callback(osip, OSIP_IST_KILL_TRANSACTION, &cb_xixt_kill_transaction);
1782   osip_set_kill_transaction_callback(osip, OSIP_NICT_KILL_TRANSACTION, &cb_xixt_kill_transaction);
1783   osip_set_kill_transaction_callback(osip, OSIP_NIST_KILL_TRANSACTION, &cb_xixt_kill_transaction);
1784 
1785   osip_set_message_callback(osip, OSIP_ICT_STATUS_1XX_RECEIVED, &cb_rcv1xx);
1786   osip_set_message_callback(osip, OSIP_ICT_STATUS_2XX_RECEIVED, &cb_rcv2xx);
1787   osip_set_message_callback(osip, OSIP_ICT_STATUS_3XX_RECEIVED, &cb_rcv3xx);
1788   osip_set_message_callback(osip, OSIP_ICT_STATUS_4XX_RECEIVED, &cb_rcv4xx);
1789   osip_set_message_callback(osip, OSIP_ICT_STATUS_5XX_RECEIVED, &cb_rcv5xx);
1790   osip_set_message_callback(osip, OSIP_ICT_STATUS_6XX_RECEIVED, &cb_rcv6xx);
1791 
1792   osip_set_message_callback(osip, OSIP_IST_STATUS_1XX_SENT, &cb_snd123456xx);
1793   osip_set_message_callback(osip, OSIP_IST_STATUS_2XX_SENT, &cb_snd123456xx);
1794   osip_set_message_callback(osip, OSIP_IST_STATUS_3XX_SENT, &cb_snd123456xx);
1795   osip_set_message_callback(osip, OSIP_IST_STATUS_4XX_SENT, &cb_snd123456xx);
1796   osip_set_message_callback(osip, OSIP_IST_STATUS_5XX_SENT, &cb_snd123456xx);
1797   osip_set_message_callback(osip, OSIP_IST_STATUS_6XX_SENT, &cb_snd123456xx);
1798 
1799   osip_set_message_callback(osip, OSIP_NICT_STATUS_1XX_RECEIVED, &cb_rcv1xx);
1800   osip_set_message_callback(osip, OSIP_NICT_STATUS_2XX_RECEIVED, &cb_rcv2xx);
1801   osip_set_message_callback(osip, OSIP_NICT_STATUS_3XX_RECEIVED, &cb_rcv3xx);
1802   osip_set_message_callback(osip, OSIP_NICT_STATUS_4XX_RECEIVED, &cb_rcv4xx);
1803   osip_set_message_callback(osip, OSIP_NICT_STATUS_5XX_RECEIVED, &cb_rcv5xx);
1804   osip_set_message_callback(osip, OSIP_NICT_STATUS_6XX_RECEIVED, &cb_rcv6xx);
1805 
1806   osip_set_message_callback(osip, OSIP_NIST_STATUS_1XX_SENT, &cb_snd123456xx);
1807   osip_set_message_callback(osip, OSIP_NIST_STATUS_2XX_SENT, &cb_snd123456xx);
1808   osip_set_message_callback(osip, OSIP_NIST_STATUS_3XX_SENT, &cb_snd123456xx);
1809   osip_set_message_callback(osip, OSIP_NIST_STATUS_4XX_SENT, &cb_snd123456xx);
1810   osip_set_message_callback(osip, OSIP_NIST_STATUS_5XX_SENT, &cb_snd123456xx);
1811   osip_set_message_callback(osip, OSIP_NIST_STATUS_6XX_SENT, &cb_snd123456xx);
1812 
1813   osip_set_message_callback(osip, OSIP_NIST_CANCEL_RECEIVED, &cb_rcvcancel);
1814   osip_set_message_callback(osip, OSIP_NIST_REGISTER_RECEIVED, &cb_rcvregister);
1815   osip_set_message_callback(osip, OSIP_NIST_BYE_RECEIVED, &cb_rcvrequest);
1816   osip_set_message_callback(osip, OSIP_NIST_INFO_RECEIVED, &cb_rcvrequest);
1817   osip_set_message_callback(osip, OSIP_NIST_OPTIONS_RECEIVED, &cb_rcvrequest);
1818   osip_set_message_callback(osip, OSIP_NIST_SUBSCRIBE_RECEIVED, &cb_rcvrequest);
1819   osip_set_message_callback(osip, OSIP_NIST_NOTIFY_RECEIVED, &cb_rcvrequest);
1820   osip_set_message_callback(osip, OSIP_NIST_UNKNOWN_REQUEST_RECEIVED, &cb_rcvrequest);
1821 
1822   osip_set_transport_error_callback(osip, OSIP_ICT_TRANSPORT_ERROR, &cb_transport_error);
1823   osip_set_transport_error_callback(osip, OSIP_IST_TRANSPORT_ERROR, &cb_transport_error);
1824   osip_set_transport_error_callback(osip, OSIP_NICT_TRANSPORT_ERROR, &cb_transport_error);
1825   osip_set_transport_error_callback(osip, OSIP_NIST_TRANSPORT_ERROR, &cb_transport_error);
1826 
1827 #ifndef MINISIZE
1828   /* those methods are only used for log purpose except cb_transport_error which only apply to complete version */
1829   osip_set_message_callback(osip, OSIP_ICT_STATUS_2XX_RECEIVED_AGAIN, &cb_rcvresp_retransmission);
1830   osip_set_message_callback(osip, OSIP_ICT_STATUS_3456XX_RECEIVED_AGAIN, &cb_rcvresp_retransmission);
1831   osip_set_message_callback(osip, OSIP_ICT_INVITE_SENT_AGAIN, &cb_sndreq_retransmission);
1832   osip_set_message_callback(osip, OSIP_IST_STATUS_2XX_SENT_AGAIN, &cb_sndresp_retransmission);
1833   osip_set_message_callback(osip, OSIP_IST_STATUS_3456XX_SENT_AGAIN, &cb_sndresp_retransmission);
1834   osip_set_message_callback(osip, OSIP_IST_INVITE_RECEIVED_AGAIN, &cb_rcvreq_retransmission);
1835   osip_set_message_callback(osip, OSIP_NICT_STATUS_2XX_RECEIVED_AGAIN, &cb_rcvresp_retransmission);
1836   osip_set_message_callback(osip, OSIP_NICT_STATUS_3456XX_RECEIVED_AGAIN, &cb_rcvresp_retransmission);
1837   osip_set_message_callback(osip, OSIP_NICT_REQUEST_SENT_AGAIN, &cb_sndreq_retransmission);
1838   osip_set_message_callback(osip, OSIP_NIST_STATUS_2XX_SENT_AGAIN, &cb_sndresp_retransmission);
1839   osip_set_message_callback(osip, OSIP_NIST_STATUS_3456XX_SENT_AGAIN, &cb_sndresp_retransmission);
1840   osip_set_message_callback(osip, OSIP_NIST_REQUEST_RECEIVED_AGAIN, &cb_rcvreq_retransmission);
1841 
1842   osip_set_message_callback(osip, OSIP_ICT_INVITE_SENT, &cb_sndinvite);
1843   osip_set_message_callback(osip, OSIP_ICT_ACK_SENT, &cb_sndack);
1844   osip_set_message_callback(osip, OSIP_NICT_REGISTER_SENT, &cb_sndregister);
1845   osip_set_message_callback(osip, OSIP_NICT_BYE_SENT, &cb_sndbye);
1846   osip_set_message_callback(osip, OSIP_NICT_CANCEL_SENT, &cb_sndcancel);
1847   osip_set_message_callback(osip, OSIP_NICT_INFO_SENT, &cb_sndinfo);
1848   osip_set_message_callback(osip, OSIP_NICT_OPTIONS_SENT, &cb_sndoptions);
1849   osip_set_message_callback(osip, OSIP_NICT_SUBSCRIBE_SENT, &cb_sndsubscribe);
1850   osip_set_message_callback(osip, OSIP_NICT_NOTIFY_SENT, &cb_sndnotify);
1851   osip_set_message_callback(osip, OSIP_NICT_UNKNOWN_REQUEST_SENT, &cb_sndunkrequest);
1852 
1853   osip_set_message_callback(osip, OSIP_IST_INVITE_RECEIVED, &cb_rcvinvite);
1854   osip_set_message_callback(osip, OSIP_IST_ACK_RECEIVED, &cb_rcvack);
1855   osip_set_message_callback(osip, OSIP_IST_ACK_RECEIVED_AGAIN, &cb_rcvack2);
1856 #endif
1857   return OSIP_SUCCESS;
1858 }
1859