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 #ifdef __APPLE__
36 #include "TargetConditionals.h"
37 #endif
38 
39 #include <eXosip2/eXosip.h>
40 
41 #ifdef HAVE_MEMORY_H
42 #include <memory.h>
43 #endif
44 #ifdef HAVE_UNISTD_H
45 #include <unistd.h>
46 #endif
47 
48 /* this value should remain 120, at least, don't use very low values */
49 #define TRANSACTION_TIMEOUT_RETRY 120
50 
51 /* Private functions */
52 static jauthinfo_t *eXosip_find_authentication_info(struct eXosip_t *excontext, const char *username, const char *realm);
53 
_eXosip_wakeup(struct eXosip_t * excontext)54 void _eXosip_wakeup(struct eXosip_t *excontext) {
55 #ifndef OSIP_MONOTHREAD
56   jpipe_write(excontext->j_socketctl, "w", 1);
57 #endif
58 }
59 
eXosip_wakeup_event(struct eXosip_t * excontext)60 void eXosip_wakeup_event(struct eXosip_t *excontext) {
61 #ifndef OSIP_MONOTHREAD
62   jpipe_write(excontext->j_socketctl_event, "w", 1);
63 #endif
64 }
65 
eXosip_lock(struct eXosip_t * excontext)66 int eXosip_lock(struct eXosip_t *excontext) {
67 #ifndef OSIP_MONOTHREAD
68   return osip_mutex_lock((struct osip_mutex *) excontext->j_mutexlock);
69 #else
70   return OSIP_WRONG_STATE; /* COMPILED WITH OSIP_MONOTHREAD */
71 #endif
72 }
73 
eXosip_unlock(struct eXosip_t * excontext)74 int eXosip_unlock(struct eXosip_t *excontext) {
75 #ifndef OSIP_MONOTHREAD
76   return osip_mutex_unlock((struct osip_mutex *) excontext->j_mutexlock);
77 #else
78   return OSIP_WRONG_STATE; /* COMPILED WITH OSIP_MONOTHREAD */
79 #endif
80 }
81 
_eXosip_transaction_init(struct eXosip_t * excontext,osip_transaction_t ** transaction,osip_fsm_type_t ctx_type,osip_t * osip,osip_message_t * message)82 int _eXosip_transaction_init(struct eXosip_t *excontext, osip_transaction_t **transaction, osip_fsm_type_t ctx_type, osip_t *osip, osip_message_t *message) {
83   int i;
84 
85   i = osip_transaction_init(transaction, ctx_type, osip, message);
86 
87   if (i != 0) {
88     return i;
89   }
90 
91 #ifndef MINISIZE
92   {
93     struct timeval now;
94 
95     excontext->statistics.allocated_transactions++;
96     osip_gettimeofday(&now, NULL);
97     _eXosip_counters_update(&excontext->average_transactions, 1, &now);
98   }
99 #endif
100 
101   osip_transaction_set_reserved1(*transaction, excontext);
102   {
103     osip_naptr_t *naptr_record = NULL;
104 
105     if (ctx_type == NICT || ctx_type == ICT)
106       i = _eXosip_srv_lookup(excontext, message, &naptr_record);
107 
108     if (i < 0) {
109       /* might be a simple DNS request or an IP */
110       return OSIP_SUCCESS;
111     }
112 
113     osip_transaction_set_naptr_record(*transaction, naptr_record);
114   }
115   return OSIP_SUCCESS;
116 }
117 
_eXosip_transaction_free(struct eXosip_t * excontext,osip_transaction_t * transaction)118 void _eXosip_transaction_free(struct eXosip_t *excontext, osip_transaction_t *transaction) {
119   _eXosip_delete_reserved(transaction);
120   eXosip_dnsutils_release(transaction->naptr_record);
121   transaction->naptr_record = NULL;
122   osip_transaction_free(transaction);
123 #ifndef MINISIZE
124   excontext->statistics.allocated_transactions--;
125 #endif
126 }
127 
_eXosip_transaction_find(struct eXosip_t * excontext,int tid,osip_transaction_t ** transaction)128 int _eXosip_transaction_find(struct eXosip_t *excontext, int tid, osip_transaction_t **transaction) {
129   osip_list_iterator_t it;
130   osip_transaction_t *tr = (osip_transaction_t *) osip_list_get_first(&excontext->j_transactions, &it);
131 
132   while (tr != OSIP_SUCCESS) {
133     if (tr->transactionid == tid) {
134       *transaction = tr;
135       return OSIP_SUCCESS;
136     }
137 
138     tr = (osip_transaction_t *) osip_list_get_next(&it);
139   }
140 
141   return OSIP_NOTFOUND;
142 }
143 
144 #ifndef MINISIZE
145 
_eXosip_retry_with_auth(struct eXosip_t * excontext,eXosip_dialog_t * jd,osip_transaction_t ** ptr,int * retry)146 static int _eXosip_retry_with_auth(struct eXosip_t *excontext, eXosip_dialog_t *jd, osip_transaction_t **ptr, int *retry) {
147   osip_transaction_t *out_tr = NULL;
148   osip_transaction_t *tr = NULL;
149   osip_message_t *msg = NULL;
150   osip_event_t *sipevent;
151   void *reserved1;
152   int cseq;
153   osip_via_t *via;
154   int i;
155 
156   if (!ptr)
157     return OSIP_BADPARAMETER;
158 
159   if (jd != NULL) {
160     if (jd->d_out_trs == NULL)
161       return OSIP_UNDEFINED_ERROR;
162   }
163 
164   out_tr = *ptr;
165 
166   if (out_tr == NULL || out_tr->orig_request == NULL || out_tr->last_response == NULL)
167     return OSIP_BADPARAMETER;
168 
169   if (retry && (*retry >= 3))
170     return OSIP_UNDEFINED_ERROR;
171 
172   i = osip_message_clone(out_tr->orig_request, &msg);
173 
174   if (i != 0) {
175     OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] cannot clone msg for authentication\n"));
176     return i;
177   }
178 
179   via = (osip_via_t *) osip_list_get(&msg->vias, 0);
180 
181   if (via == NULL || msg->cseq == NULL || msg->cseq->number == NULL) {
182     osip_message_free(msg);
183     OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] missing via or cseq header\n"));
184     return OSIP_SYNTAXERROR;
185   }
186 
187   /* increment cseq */
188   cseq = atoi(msg->cseq->number);
189   osip_free(msg->cseq->number);
190   msg->cseq->number = _eXosip_strdup_printf("%i", cseq + 1);
191 
192   if (jd != NULL && jd->d_dialog != NULL) {
193     jd->d_dialog->local_cseq++;
194   }
195 
196   i = _eXosip_update_top_via(msg);
197 
198   if (i != 0) {
199     osip_message_free(msg);
200     return i;
201   }
202 
203   osip_list_special_free(&msg->authorizations, (void (*)(void *)) & osip_authorization_free);
204   osip_list_special_free(&msg->proxy_authorizations, (void (*)(void *)) & osip_proxy_authorization_free);
205 
206   if (out_tr != NULL && out_tr->last_response != NULL && (out_tr->last_response->status_code == 401 || out_tr->last_response->status_code == 407)) {
207     i = _eXosip_add_authentication_information(excontext, msg, out_tr->last_response);
208 
209     if (i < 0) {
210       osip_message_free(msg);
211       return i;
212     }
213 
214   } else {
215     i = _eXosip_add_authentication_information(excontext, msg, NULL);
216 
217     if (i < 0) {
218       osip_message_free(msg);
219       return i;
220     }
221   }
222 
223   osip_message_force_update(msg);
224 
225   if (MSG_IS_INVITE(msg))
226     i = _eXosip_transaction_init(excontext, &tr, ICT, excontext->j_osip, msg);
227 
228   else
229     i = _eXosip_transaction_init(excontext, &tr, NICT, excontext->j_osip, msg);
230 
231   if (i != 0) {
232     osip_message_free(msg);
233     return i;
234   }
235 
236   /* replace with the new tr */
237   if (MSG_IS_PUBLISH(msg)) {
238     /* old transaction is put in the garbage list */
239     osip_list_add(&excontext->j_transactions, out_tr, 0);
240     /* new transaction is put in the publish context */
241     *ptr = tr;
242 
243   } else
244     osip_list_add(&excontext->j_transactions, tr, 0);
245 
246   sipevent = osip_new_outgoing_sipmessage(msg);
247 
248   reserved1 = osip_transaction_get_reserved2(out_tr);
249   osip_transaction_set_reserved2(out_tr, NULL);
250   osip_transaction_set_reserved2(tr, reserved1);
251 
252   reserved1 = osip_transaction_get_reserved3(out_tr);
253   osip_transaction_set_reserved3(out_tr, NULL);
254   osip_transaction_set_reserved3(tr, reserved1);
255 
256   reserved1 = osip_transaction_get_reserved4(out_tr);
257   osip_transaction_set_reserved4(out_tr, NULL);
258   osip_transaction_set_reserved4(tr, reserved1);
259 
260   reserved1 = osip_transaction_get_reserved5(out_tr);
261   osip_transaction_set_reserved5(out_tr, NULL);
262   osip_transaction_set_reserved5(tr, reserved1);
263 
264   osip_transaction_add_event(tr, sipevent);
265 
266   if (retry)
267     (*retry)++;
268 
269   _eXosip_update(excontext); /* fixed? */
270   _eXosip_wakeup(excontext);
271   return OSIP_SUCCESS;
272 }
273 
_eXosip_publish_refresh(struct eXosip_t * excontext,eXosip_dialog_t * jd,osip_transaction_t ** ptr,int * retry)274 static int _eXosip_publish_refresh(struct eXosip_t *excontext, eXosip_dialog_t *jd, osip_transaction_t **ptr, int *retry) {
275   osip_transaction_t *out_tr = NULL;
276   osip_transaction_t *tr = NULL;
277   osip_message_t *msg = NULL;
278   osip_event_t *sipevent;
279 
280   int cseq;
281   osip_via_t *via;
282   int i;
283 
284   if (!ptr)
285     return OSIP_BADPARAMETER;
286 
287   if (jd != NULL) {
288     if (jd->d_out_trs == NULL)
289       return OSIP_BADPARAMETER;
290   }
291 
292   out_tr = *ptr;
293 
294   if (out_tr == NULL || out_tr->orig_request == NULL || out_tr->last_response == NULL)
295     return OSIP_BADPARAMETER;
296 
297   if (retry && (*retry >= 3))
298     return OSIP_UNDEFINED_ERROR;
299 
300   i = osip_message_clone(out_tr->orig_request, &msg);
301 
302   if (i != 0) {
303     OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] cannot clone msg for authentication\n"));
304     return i;
305   }
306 
307   via = (osip_via_t *) osip_list_get(&msg->vias, 0);
308 
309   if (via == NULL || msg->cseq == NULL || msg->cseq->number == NULL) {
310     osip_message_free(msg);
311     OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] missing via or cseq header\n"));
312     return OSIP_SYNTAXERROR;
313   }
314 
315   /* increment cseq */
316   cseq = atoi(msg->cseq->number);
317   osip_free(msg->cseq->number);
318   msg->cseq->number = _eXosip_strdup_printf("%i", cseq + 1);
319 
320   if (msg->cseq->number == NULL) {
321     osip_message_free(msg);
322     return OSIP_NOMEM;
323   }
324 
325   if (jd != NULL && jd->d_dialog != NULL) {
326     jd->d_dialog->local_cseq++;
327   }
328 
329   i = _eXosip_update_top_via(msg);
330 
331   if (i != 0) {
332     osip_message_free(msg);
333     return i;
334   }
335 
336   osip_list_special_free(&msg->authorizations, (void (*)(void *)) & osip_authorization_free);
337   osip_list_special_free(&msg->proxy_authorizations, (void (*)(void *)) & osip_proxy_authorization_free);
338 
339   if (out_tr != NULL && out_tr->last_response != NULL && (out_tr->last_response->status_code == 401 || out_tr->last_response->status_code == 407)) {
340     _eXosip_add_authentication_information(excontext, msg, out_tr->last_response);
341 
342   } else
343     _eXosip_add_authentication_information(excontext, msg, NULL);
344 
345   if (out_tr != NULL && out_tr->last_response != NULL && out_tr->last_response->status_code == 412) {
346     /* remove SIP-If-Match header */
347     osip_list_iterator_t it;
348     osip_header_t *head = (osip_header_t *) osip_list_get_first(&msg->headers, &it);
349 
350     while (head != OSIP_SUCCESS) {
351       if (head != NULL && 0 == osip_strcasecmp(head->hname, "sip-if-match")) {
352         osip_list_iterator_remove(&it);
353         osip_header_free(head);
354         break;
355       }
356 
357       head = (osip_header_t *) osip_list_get_next(&it);
358     }
359   }
360 
361   if (out_tr != NULL && out_tr->last_response != NULL && out_tr->last_response->status_code == 423) {
362     /* increase expires value to "min-expires" value */
363     osip_header_t *exp;
364     osip_header_t *min_exp;
365 
366     osip_message_header_get_byname(msg, "expires", 0, &exp);
367     osip_message_header_get_byname(out_tr->last_response, "min-expires", 0, &min_exp);
368 
369     if (exp != NULL && exp->hvalue != NULL && min_exp != NULL && min_exp->hvalue != NULL) {
370       osip_free(exp->hvalue);
371       exp->hvalue = osip_strdup(min_exp->hvalue);
372 
373     } else {
374       osip_message_free(msg);
375       OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] missing Min-Expires or Expires in PUBLISH\n"));
376       return OSIP_SYNTAXERROR;
377     }
378   }
379 
380   osip_message_force_update(msg);
381 
382   i = _eXosip_transaction_init(excontext, &tr, NICT, excontext->j_osip, msg);
383 
384   if (i != 0) {
385     osip_message_free(msg);
386     return i;
387   }
388 
389   /* replace with the new tr */
390   /* old transaction is put in the garbage list */
391   osip_list_add(&excontext->j_transactions, out_tr, 0);
392   /* new transaction is put in the publish context */
393   *ptr = tr;
394 
395   sipevent = osip_new_outgoing_sipmessage(msg);
396 
397   osip_transaction_add_event(tr, sipevent);
398 
399   if (retry)
400     (*retry)++;
401 
402   _eXosip_update(excontext); /* fixed? */
403   _eXosip_wakeup(excontext);
404   return OSIP_SUCCESS;
405 }
406 
_eXosip_retry_register_with_auth(struct eXosip_t * excontext,eXosip_event_t * je)407 static int _eXosip_retry_register_with_auth(struct eXosip_t *excontext, eXosip_event_t *je) {
408   eXosip_reg_t *jr = NULL;
409   int i;
410 
411   i = _eXosip_reg_find_id(excontext, &jr, je->rid);
412 
413   if (i < 0) {
414     OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] registration not found\n"));
415     return i;
416   }
417 
418   if (jr->r_retry < 3) {
419     jr->r_retry++;
420     return eXosip_register_send_register(excontext, jr->r_id, NULL);
421   }
422 
423   return OSIP_RETRY_LIMIT;
424 }
425 
_eXosip_retry_invite_with_auth(struct eXosip_t * excontext,eXosip_event_t * je)426 static int _eXosip_retry_invite_with_auth(struct eXosip_t *excontext, eXosip_event_t *je) {
427   eXosip_dialog_t *jd = NULL;
428   eXosip_call_t *jc = NULL;
429   int *retry = NULL;
430   osip_transaction_t *tr = NULL;
431   int i;
432 
433   i = _eXosip_call_transaction_find(excontext, je->tid, &jc, &jd, &tr);
434 
435   if (i != 0) {
436     OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] call dialog not found\n"));
437     return i;
438   }
439 
440   if (jd && jd->d_dialog)
441     retry = &jd->d_retry;
442 
443   else
444     retry = &jc->c_retry;
445 
446   if (*retry < 3) {
447     (*retry)++;
448     return _eXosip_call_retry_request(excontext, jc, jd, tr);
449   }
450 
451   return OSIP_RETRY_LIMIT;
452 }
453 
_eXosip_redirect_invite(struct eXosip_t * excontext,eXosip_event_t * je)454 static int _eXosip_redirect_invite(struct eXosip_t *excontext, eXosip_event_t *je) {
455   eXosip_dialog_t *jd = NULL;
456   eXosip_call_t *jc = NULL;
457   osip_transaction_t *tr = NULL;
458   int i;
459 
460   i = _eXosip_call_transaction_find(excontext, je->tid, &jc, &jd, &tr);
461 
462   if (i != 0) {
463     OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] call dialog not found\n"));
464     return i;
465   }
466 
467   return _eXosip_call_retry_request(excontext, jc, jd, tr);
468 }
469 
_eXosip_retry_subscribe_with_auth(struct eXosip_t * excontext,eXosip_event_t * je)470 static int _eXosip_retry_subscribe_with_auth(struct eXosip_t *excontext, eXosip_event_t *je) {
471   eXosip_dialog_t *jd = NULL;
472   eXosip_subscribe_t *js = NULL;
473   int *retry = NULL;
474   osip_transaction_t *tr = NULL;
475   int i;
476 
477   i = _eXosip_subscription_transaction_find(excontext, je->tid, &js, &jd, &tr);
478 
479   if (i != 0) {
480     OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] subscribe dialog not found\n"));
481     return i;
482   }
483 
484   if (jd && jd->d_dialog)
485     retry = &jd->d_retry;
486 
487   else
488     retry = &js->s_retry;
489 
490   if (*retry < 3) {
491     (*retry)++;
492     return _eXosip_subscription_send_request_with_credential(excontext, js, jd, tr);
493   }
494 
495   return OSIP_RETRY_LIMIT;
496 }
497 
_eXosip_retry_publish_with_auth(struct eXosip_t * excontext,eXosip_event_t * je)498 static int _eXosip_retry_publish_with_auth(struct eXosip_t *excontext, eXosip_event_t *je) {
499   eXosip_pub_t *jp = NULL;
500   int i;
501 
502   i = _eXosip_pub_find_by_tid(excontext, &jp, je->tid);
503 
504   if (i != 0) {
505     OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] publish transaction not found\n"));
506     return i;
507   }
508 
509   return _eXosip_retry_with_auth(excontext, NULL, &jp->p_last_tr, NULL);
510 }
511 
_eXosip_retry_notify_with_auth(struct eXosip_t * excontext,eXosip_event_t * je)512 static int _eXosip_retry_notify_with_auth(struct eXosip_t *excontext, eXosip_event_t *je) {
513   /* TODO untested */
514   eXosip_dialog_t *jd = NULL;
515   eXosip_notify_t *jn = NULL;
516   osip_transaction_t *tr = NULL;
517   int i;
518 
519   i = _eXosip_insubscription_transaction_find(excontext, je->tid, &jn, &jd, &tr);
520 
521   if (i != 0) {
522     OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] notify dialog not found\n"));
523     return i;
524   }
525 
526   return _eXosip_insubscription_send_request_with_credential(excontext, jn, jd, tr);
527 }
528 
eXosip_retry_with_auth(struct eXosip_t * excontext,eXosip_event_t * je)529 static int eXosip_retry_with_auth(struct eXosip_t *excontext, eXosip_event_t *je) {
530   int res = OSIP_UNDEFINED_ERROR;
531 
532   if (!je || !je->request || !je->response)
533     return OSIP_BADPARAMETER;
534 
535   if (je->rid > 0) {
536     return _eXosip_retry_register_with_auth(excontext, je);
537 
538   } else if (je->cid > 0) {
539     res = _eXosip_retry_invite_with_auth(excontext, je);
540 
541     if (res == OSIP_NOTFOUND) {
542       osip_transaction_t *tr = NULL;
543 
544       _eXosip_transaction_find(excontext, je->tid, &tr);
545 
546       if (tr != NULL) {
547         return _eXosip_retry_with_auth(excontext, NULL, &tr, NULL);
548       }
549     }
550 
551     return res;
552   }
553 #ifndef MINISIZE
554 
555   else if (je->sid > 0) {
556     return _eXosip_retry_subscribe_with_auth(excontext, je);
557 
558   } else if (je->nid > 0) {
559     return _eXosip_retry_notify_with_auth(excontext, je);
560 
561   } else if (MSG_IS_PUBLISH(je->request))
562     return _eXosip_retry_publish_with_auth(excontext, je);
563 
564 #endif
565   else {
566     osip_transaction_t *tr = NULL;
567 
568     _eXosip_transaction_find(excontext, je->tid, &tr);
569 
570     if (tr != NULL) {
571       return _eXosip_retry_with_auth(excontext, NULL, &tr, NULL);
572     }
573   }
574 
575   OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] cannot retry event [%d] with auth\n", je->type));
576   return OSIP_UNDEFINED_ERROR;
577 }
578 
_eXosip_redirect(struct eXosip_t * excontext,eXosip_event_t * je)579 static int _eXosip_redirect(struct eXosip_t *excontext, eXosip_event_t *je) {
580   switch (je->type) {
581   case EXOSIP_CALL_REDIRECTED:
582     return _eXosip_redirect_invite(excontext, je);
583 
584   case EXOSIP_CALL_MESSAGE_REDIRECTED:
585   case EXOSIP_MESSAGE_REDIRECTED:
586   case EXOSIP_SUBSCRIPTION_REDIRECTED:
587     OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] not implemented\n"));
588     return OSIP_UNDEFINED_ERROR;
589 
590   default:
591     OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] cannot redirect event [%d]\n", je->type));
592     return OSIP_UNDEFINED_ERROR;
593   }
594 }
595 
eXosip_default_action(struct eXosip_t * excontext,eXosip_event_t * je)596 int eXosip_default_action(struct eXosip_t *excontext, eXosip_event_t *je) {
597   if (!je || !je->response)
598     return OSIP_BADPARAMETER;
599 
600   if (je->response->status_code == 401 || je->response->status_code == 407)
601     return eXosip_retry_with_auth(excontext, je);
602 
603   else if (je->response->status_code >= 300 && je->response->status_code <= 399)
604     return _eXosip_redirect(excontext, je);
605 
606   else
607     return 1;
608 }
609 
610 #endif
611 
_eXosip_retransmit_lost200ok(struct eXosip_t * excontext)612 void _eXosip_retransmit_lost200ok(struct eXosip_t *excontext) {
613   eXosip_call_t *jc;
614   eXosip_dialog_t *jd;
615   time_t now;
616 
617   now = osip_getsystemtime(NULL);
618 
619   for (jc = excontext->j_calls; jc != NULL; jc = jc->next) {
620     if (jc->c_id >= 1 && jc->c_dialogs != NULL) {
621       for (jd = jc->c_dialogs; jd != NULL; jd = jd->next) {
622         if (jd->d_id >= 1 && jd->d_dialog != NULL && jd->d_200Ok != NULL) {
623           if (jd->d_count == 9) {
624             int i;
625 
626             OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] no ACK received during 20s [dropping call]\n"));
627             /* hard for users to detect than I sent this BYE... */
628             jd->d_count = 0;
629             osip_message_free(jd->d_200Ok);
630             jd->d_200Ok = NULL;
631             i = eXosip_call_terminate(excontext, jc->c_id, jd->d_id);
632 
633             if (i == OSIP_SUCCESS) {
634               _eXosip_report_call_event(excontext, EXOSIP_CALL_CLOSED, jc, jd, NULL);
635             }
636 
637           } else if (jd->d_timer < now) {
638             /* a dialog exist: retransmit lost 200ok */
639             jd->d_count++;
640 
641             if (jd->d_count == 1)
642               jd->d_timer = osip_getsystemtime(NULL) + 1;
643 
644             if (jd->d_count == 2)
645               jd->d_timer = osip_getsystemtime(NULL) + 2;
646 
647             if (jd->d_count >= 3)
648               jd->d_timer = osip_getsystemtime(NULL) + 4;
649 
650             jd = jc->c_dialogs;
651             /* TU retransmission */
652             _eXosip_snd_message(excontext, NULL, jd->d_200Ok, NULL, 0, -1);
653           }
654         }
655       }
656     }
657   }
658 
659   return;
660 }
661 
eXosip_automatic_action(struct eXosip_t * excontext)662 void eXosip_automatic_action(struct eXosip_t *excontext) {
663   eXosip_call_t *jc;
664   eXosip_dialog_t *jd;
665 
666 #ifndef MINISIZE
667   eXosip_subscribe_t *js;
668   eXosip_notify_t *jn;
669   eXosip_pub_t *jpub;
670 #endif
671 
672   eXosip_reg_t *jr;
673 
674   time_t now;
675 
676   now = osip_getsystemtime(NULL);
677 
678   for (jc = excontext->j_calls; jc != NULL; jc = jc->next) {
679     if (jc->c_id < 1) {
680     } else if (jc->c_dialogs == NULL || jc->c_dialogs->d_dialog == NULL) {
681       /* an EARLY dialog may have failed with 401,407 or 3Xx */
682 
683       osip_transaction_t *out_tr = NULL;
684 
685       out_tr = jc->c_out_tr;
686 
687       if (out_tr != NULL && (out_tr->state == ICT_TERMINATED || out_tr->state == NICT_TERMINATED || out_tr->state == ICT_COMPLETED || out_tr->state == NICT_COMPLETED) && now - out_tr->birth_time < TRANSACTION_TIMEOUT_RETRY &&
688           out_tr->orig_request != NULL && out_tr->last_response != NULL && (out_tr->last_response->status_code == 401 || out_tr->last_response->status_code == 407)) {
689         /* retry with credential */
690         if (jc->c_retry < 3) {
691           int i;
692 
693           i = _eXosip_call_retry_request(excontext, jc, NULL, out_tr);
694 
695           if (i != 0) {
696             OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] cannot clone msg for authentication\n"));
697           }
698 
699           jc->c_retry++;
700         }
701 
702       } else if (out_tr != NULL && (out_tr->state == ICT_TERMINATED || out_tr->state == NICT_TERMINATED || out_tr->state == ICT_COMPLETED || out_tr->state == NICT_COMPLETED) && now - out_tr->birth_time < TRANSACTION_TIMEOUT_RETRY &&
703                  out_tr->orig_request != NULL && out_tr->last_response != NULL && out_tr->last_response->status_code == 422) {
704         /* retry with higher Session-Expires / Min-SE */
705         if (jc->c_retry < 3) {
706           int i;
707 
708           i = _eXosip_call_retry_request(excontext, jc, NULL, out_tr);
709 
710           if (i != 0) {
711             OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] cannot clone msg for updating Session-Expires\n"));
712           }
713 
714           jc->c_retry++;
715         }
716 
717       } else if (out_tr != NULL && (out_tr->state == ICT_TERMINATED || out_tr->state == NICT_TERMINATED || out_tr->state == ICT_COMPLETED || out_tr->state == NICT_COMPLETED) && now - out_tr->birth_time < TRANSACTION_TIMEOUT_RETRY &&
718                  out_tr->orig_request != NULL && out_tr->last_response != NULL && (out_tr->last_response->status_code >= 300 && out_tr->last_response->status_code <= 399)) {
719         /* retry with credential */
720         int i;
721 
722         i = _eXosip_call_retry_request(excontext, jc, NULL, out_tr);
723 
724         if (i != 0) {
725           OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] cannot clone msg for redirection\n"));
726         }
727       }
728     }
729 
730     for (jd = jc->c_dialogs; jd != NULL; jd = jd->next) {
731       if (jd->d_dialog == NULL) /* finished call */
732         continue;
733 
734       osip_transaction_t *out_tr = NULL;
735 
736       out_tr = osip_list_get(jd->d_out_trs, 0);
737 
738       if (out_tr == NULL)
739         out_tr = jc->c_out_tr;
740 
741       if (out_tr != NULL && (out_tr->state == ICT_TERMINATED || out_tr->state == NICT_TERMINATED || out_tr->state == ICT_COMPLETED || out_tr->state == NICT_COMPLETED) && now - out_tr->birth_time < TRANSACTION_TIMEOUT_RETRY &&
742           out_tr->orig_request != NULL && out_tr->last_response != NULL && (out_tr->last_response->status_code == 401 || out_tr->last_response->status_code == 407)) {
743         /* retry with credential */
744         if (jd->d_retry < 3) {
745           int i;
746 
747           i = _eXosip_call_retry_request(excontext, jc, jd, out_tr);
748 
749           if (i != 0) {
750             OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] cannot clone msg for authentication\n"));
751           }
752 
753           jd->d_retry++;
754         }
755 
756       } else if (out_tr != NULL && (out_tr->state == ICT_TERMINATED || out_tr->state == NICT_TERMINATED || out_tr->state == ICT_COMPLETED || out_tr->state == NICT_COMPLETED) && now - out_tr->birth_time < TRANSACTION_TIMEOUT_RETRY &&
757                  out_tr->orig_request != NULL && out_tr->last_response != NULL && out_tr->last_response->status_code == 422) {
758         /* retry with higher Session-Expires / Min-SE */
759         if (jd->d_retry < 3) {
760           int i;
761 
762           i = _eXosip_call_retry_request(excontext, jc, jd, out_tr);
763 
764           if (i != 0) {
765             OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] cannot clone msg for updating Session-Expires\n"));
766           }
767 
768           jd->d_retry++;
769         }
770 
771       } else if (out_tr != NULL && (out_tr->state == ICT_TERMINATED || out_tr->state == NICT_TERMINATED || out_tr->state == ICT_COMPLETED || out_tr->state == NICT_COMPLETED) && now - out_tr->birth_time < TRANSACTION_TIMEOUT_RETRY &&
772                  out_tr->orig_request != NULL && out_tr->last_response != NULL && (out_tr->last_response->status_code >= 300 && out_tr->last_response->status_code <= 399)) {
773         /* retry with credential */
774         int i;
775 
776         i = _eXosip_call_retry_request(excontext, jc, jd, out_tr);
777 
778         if (i != 0) {
779           OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] cannot clone msg for redirection\n"));
780         }
781 
782       } else {
783         /* check if we need session-timer */
784         if (jd->d_refresher == -1) {
785         } else if (jd->d_refresher == 0) {
786           /* I'm the refresher */
787           if (now - (jd->d_session_timer_start + jd->d_session_timer_length) > 0) {
788             /* means we tried hard... but certainly failed... */
789           } else if ((jd->d_session_timer_start + jd->d_session_timer_length) - now < (jd->d_session_timer_length / 2)) {
790             osip_message_t *request = NULL;
791 
792             if (jd->d_session_timer_use_update == 1) {
793               eXosip_call_build_request(excontext, jd->d_id, "UPDATE", &request);
794 
795               if (request != NULL) {
796                 char session_exp[32];
797                 int i;
798 
799                 memset(session_exp, 0, sizeof(session_exp));
800                 snprintf(session_exp, sizeof(session_exp) - 1, "%i;refresher=uac", jd->d_session_timer_length);
801                 osip_message_set_header(request, "Session-Expires", session_exp);
802                 osip_message_set_supported(request, "timer");
803                 i = eXosip_call_send_request(excontext, jd->d_id, request);
804 
805                 if (i == 0) {
806                   /* update timer */
807                   jd->d_session_timer_start = osip_getsystemtime(NULL) + jd->d_session_timer_length;
808                 }
809               }
810 
811             } else {
812               eXosip_call_build_request(excontext, jd->d_id, "INVITE", &request);
813 
814               if (request != NULL) {
815                 char session_exp[32];
816                 int i;
817 
818                 memset(session_exp, 0, sizeof(session_exp));
819                 snprintf(session_exp, sizeof(session_exp) - 1, "%i;refresher=uac", jd->d_session_timer_length);
820                 osip_message_set_header(request, "Session-Expires", session_exp);
821                 osip_message_set_supported(request, "timer");
822                 i = eXosip_call_send_request(excontext, jd->d_id, request);
823 
824                 if (i == 0) {
825                   /* update timer */
826                   jd->d_session_timer_start = osip_getsystemtime(NULL) + jd->d_session_timer_length;
827                 }
828               }
829             }
830           }
831 
832         } else if (jd->d_refresher == 1) {
833           /* remote is the refresher */
834         }
835       }
836     }
837   }
838 
839   for (jr = excontext->j_reg; jr != NULL; jr = jr->next) {
840     if (jr->r_id >= 1 && jr->r_last_tr != NULL) {
841 
842       if (now >= jr->r_retry_after_delay)
843         jr->r_retry_after_delay = 0;
844 
845       if (now < jr->r_retry_after_delay) {
846         /* skip for a while */
847       } else if (jr->r_reg_period != 0 && now - jr->r_last_tr->birth_time > 900) {
848         /* automatic refresh */
849         eXosip_register_send_register(excontext, jr->r_id, NULL);
850 
851       } else if (jr->r_reg_period != 0 && (now - jr->r_last_tr->birth_time > jr->r_reg_period - (jr->r_reg_period / 10) || now - jr->r_last_tr->birth_time > jr->r_reg_period - 6)) {
852         /* automatic refresh */
853         eXosip_register_send_register(excontext, jr->r_id, NULL);
854 
855       } else if (jr->r_reg_period != 0 && now - jr->r_last_tr->birth_time > TRANSACTION_TIMEOUT_RETRY && (jr->r_last_tr->last_response == NULL || (!MSG_IS_STATUS_2XX(jr->r_last_tr->last_response)))) {
856         /* automatic refresh */
857         eXosip_register_send_register(excontext, jr->r_id, NULL);
858 
859       } else if (now - jr->r_last_tr->birth_time < 120 && jr->r_last_tr->orig_request != NULL &&
860                  (jr->r_last_tr->last_response != NULL &&
861                   (jr->r_last_tr->last_response->status_code == 401 || jr->r_last_tr->last_response->status_code == 407 || jr->r_last_tr->last_response->status_code == 423 || jr->r_last_tr->last_response->status_code == 606))) {
862         if (jr->r_retry < 3) {
863           /* TODO: improve support for several retries when
864              several credentials are needed */
865           eXosip_register_send_register(excontext, jr->r_id, NULL);
866           jr->r_retry++;
867         }
868 
869       } else if (jr->registration_step == RS_DELETIONREQUIRED && jr->r_last_tr->orig_request != NULL && jr->r_last_tr->last_response != NULL && MSG_IS_STATUS_2XX(jr->r_last_tr->last_response)) {
870         jr->registration_step = RS_DELETIONPROCEEDING;
871 
872         if (OSIP_SUCCESS != eXosip_register_send_register(excontext, jr->r_id, NULL)) {
873           jr->registration_step = RS_DELETIONREQUIRED;
874         }
875 
876       } else if (jr->registration_step == RS_MASQUERADINGREQUIRED && jr->r_last_tr->orig_request != NULL && jr->r_last_tr->last_response != NULL && MSG_IS_STATUS_2XX(jr->r_last_tr->last_response)) {
877         jr->registration_step = RS_MASQUERADINGPROCEEDING;
878 
879         if (OSIP_SUCCESS != eXosip_register_send_register(excontext, jr->r_id, NULL)) {
880           jr->registration_step = RS_MASQUERADINGREQUIRED;
881         }
882       }
883     }
884 
885     if (jr->r_last_deletion != 0 && jr->r_last_deletion + 60 < now)
886       jr->r_last_deletion = 0; /* automasquerading may happen later than 1 minutes after previous one, to avoid loop (happens with bad NAT) */
887   }
888 
889 #ifndef MINISIZE
890 
891   for (js = excontext->j_subscribes; js != NULL; js = js->next) {
892     if (js->s_id < 1) {
893     } else if (js->s_dialogs == NULL) {
894       osip_transaction_t *out_tr = NULL;
895 
896       out_tr = js->s_out_tr;
897 
898       if (out_tr != NULL && (out_tr->state == NICT_TERMINATED || out_tr->state == NICT_COMPLETED) && now - out_tr->birth_time < TRANSACTION_TIMEOUT_RETRY && out_tr->orig_request != NULL && out_tr->last_response != NULL &&
899           (out_tr->last_response->status_code == 401 || out_tr->last_response->status_code == 407 || out_tr->last_response->status_code == 423)) {
900         /* retry with credential */
901         if (js->s_retry < 3) {
902           int i;
903 
904           i = _eXosip_subscription_send_request_with_credential(excontext, js, NULL, out_tr);
905 
906           if (i != 0) {
907             OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] cannot clone msg for authentication\n"));
908           }
909 
910           js->s_retry++;
911         }
912       }
913     }
914 
915     for (jd = js->s_dialogs; jd != NULL; jd = jd->next) {
916       if (jd->d_dialog != NULL) { /* finished call */
917         if (jd->d_id >= 1) {
918           osip_transaction_t *out_tr = NULL;
919 
920           out_tr = osip_list_get(jd->d_out_trs, 0);
921 
922           if (out_tr == NULL)
923             out_tr = js->s_out_tr;
924 
925           if (out_tr != NULL && (out_tr->state == NICT_TERMINATED || out_tr->state == NICT_COMPLETED) && now - out_tr->birth_time < TRANSACTION_TIMEOUT_RETRY && out_tr->orig_request != NULL && out_tr->last_response != NULL &&
926               (out_tr->last_response->status_code == 401 || out_tr->last_response->status_code == 407)) {
927             /* retry with credential */
928             if (jd->d_retry < 3) {
929               int i;
930 
931               i = _eXosip_subscription_send_request_with_credential(excontext, js, jd, out_tr);
932 
933               if (i != 0) {
934                 OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] cannot clone suscbribe for authentication\n"));
935               }
936 
937               jd->d_retry++;
938             }
939 
940           } else if (js->s_reg_period == 0 || out_tr == NULL) {
941           } else if ((out_tr->state == NICT_TERMINATED || out_tr->state == NICT_COMPLETED) && out_tr->orig_request != NULL && out_tr->last_response != NULL && (out_tr->last_response->status_code >= 300)) {
942             /* refresh are not authorized after an error */
943           } else if ((out_tr->state == NICT_TERMINATED || out_tr->state == NICT_COMPLETED) && (now - out_tr->birth_time > js->s_reg_period - (js->s_reg_period / 10) || now - out_tr->birth_time > js->s_reg_period - 6)) {
944             /* will expires in js->s_reg_period/10 sec OR 6 seconds: send refresh! */
945             int i;
946 
947             if (out_tr->orig_request != NULL && MSG_IS_REFER(out_tr->orig_request)) {
948               OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] subscription for REFER is expired\n"));
949 
950             } else {
951               i = _eXosip_subscription_automatic_refresh(excontext, js, jd, out_tr);
952 
953               if (i != 0) {
954                 OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] cannot clone subscribe for refresh\n"));
955               }
956             }
957           }
958         }
959       }
960     }
961   }
962 
963   for (jn = excontext->j_notifies; jn != NULL; jn = jn->next) {
964     for (jd = jn->n_dialogs; jd != NULL; jd = jd->next) {
965       if (jd->d_dialog != NULL) { /* finished call */
966         if (jd->d_id >= 1) {
967           osip_transaction_t *out_tr = NULL;
968 
969           out_tr = osip_list_get(jd->d_out_trs, 0);
970 
971           if (out_tr != NULL && (out_tr->state == NICT_TERMINATED || out_tr->state == NICT_COMPLETED) && now - out_tr->birth_time < TRANSACTION_TIMEOUT_RETRY && out_tr->orig_request != NULL && out_tr->last_response != NULL &&
972               (out_tr->last_response->status_code == 401 || out_tr->last_response->status_code == 407)) {
973             /* retry with credential */
974             if (jd->d_retry < 3) {
975               int i;
976 
977               i = _eXosip_insubscription_send_request_with_credential(excontext, jn, jd, out_tr);
978 
979               if (i != 0) {
980                 OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] cannot clone notify for authentication\n"));
981               }
982 
983               jd->d_retry++;
984             }
985           }
986         }
987       }
988     }
989   }
990 
991   for (jpub = excontext->j_pub; jpub != NULL; jpub = jpub->next) {
992     if (jpub->p_id >= 1 && jpub->p_last_tr != NULL) {
993       if (jpub->p_period != 0 && now - jpub->p_last_tr->birth_time > 900) {
994         /* automatic refresh */
995         _eXosip_publish_refresh(excontext, NULL, &jpub->p_last_tr, NULL);
996 
997       } else if (jpub->p_period != 0 && now - jpub->p_last_tr->birth_time > jpub->p_period - (jpub->p_period / 10)) {
998         /* automatic refresh */
999         _eXosip_publish_refresh(excontext, NULL, &jpub->p_last_tr, NULL);
1000 
1001       } else if (jpub->p_period != 0 && now - jpub->p_last_tr->birth_time > 120 && (jpub->p_last_tr->last_response == NULL || (!MSG_IS_STATUS_2XX(jpub->p_last_tr->last_response)))) {
1002         /* automatic refresh */
1003         _eXosip_publish_refresh(excontext, NULL, &jpub->p_last_tr, NULL);
1004 
1005       } else if (now - jpub->p_last_tr->birth_time < 120 && jpub->p_last_tr->orig_request != NULL &&
1006                  (jpub->p_last_tr->last_response != NULL && (jpub->p_last_tr->last_response->status_code == 401 || jpub->p_last_tr->last_response->status_code == 407))) {
1007         if (jpub->p_retry < 3) {
1008           /* TODO: improve support for several retries when
1009              several credentials are needed */
1010           _eXosip_retry_with_auth(excontext, NULL, &jpub->p_last_tr, NULL);
1011           jpub->p_retry++;
1012         }
1013 
1014       } else if (now - jpub->p_last_tr->birth_time < 120 && jpub->p_last_tr->orig_request != NULL &&
1015                  (jpub->p_last_tr->last_response != NULL && (jpub->p_last_tr->last_response->status_code == 412 || jpub->p_last_tr->last_response->status_code == 423))) {
1016         _eXosip_publish_refresh(excontext, NULL, &jpub->p_last_tr, NULL);
1017       }
1018     }
1019   }
1020 
1021 #endif
1022 }
1023 
_eXosip_update(struct eXosip_t * excontext)1024 void _eXosip_update(struct eXosip_t *excontext) {
1025   static int static_id = 1;
1026   eXosip_call_t *jc;
1027 
1028 #ifndef MINISIZE
1029   eXosip_subscribe_t *js;
1030   eXosip_notify_t *jn;
1031 #endif
1032   eXosip_dialog_t *jd;
1033 
1034   if (static_id == INT_MAX)
1035     static_id = 1; /* loop */
1036 
1037   for (jc = excontext->j_calls; jc != NULL; jc = jc->next) {
1038     if (jc->c_id < 1) {
1039       jc->c_id = static_id;
1040       static_id++;
1041     }
1042 
1043     for (jd = jc->c_dialogs; jd != NULL; jd = jd->next) {
1044       if (jd->d_dialog != NULL) { /* finished call */
1045         if (jd->d_id < 1) {
1046           jd->d_id = static_id;
1047           static_id++;
1048         }
1049 
1050       } else
1051         jd->d_id = -1;
1052     }
1053   }
1054 
1055 #ifndef MINISIZE
1056 
1057   for (js = excontext->j_subscribes; js != NULL; js = js->next) {
1058     if (js->s_id < 1) {
1059       js->s_id = static_id;
1060       static_id++;
1061     }
1062 
1063     for (jd = js->s_dialogs; jd != NULL; jd = jd->next) {
1064       if (jd->d_dialog != NULL) { /* finished call */
1065         if (jd->d_id < 1) {
1066           jd->d_id = static_id;
1067           static_id++;
1068         }
1069 
1070       } else
1071         jd->d_id = -1;
1072     }
1073   }
1074 
1075   for (jn = excontext->j_notifies; jn != NULL; jn = jn->next) {
1076     if (jn->n_id < 1) {
1077       jn->n_id = static_id;
1078       static_id++;
1079     }
1080 
1081     for (jd = jn->n_dialogs; jd != NULL; jd = jd->next) {
1082       if (jd->d_dialog != NULL) { /* finished call */
1083         if (jd->d_id < 1) {
1084           jd->d_id = static_id;
1085           static_id++;
1086         }
1087 
1088       } else
1089         jd->d_id = -1;
1090     }
1091   }
1092 
1093 #endif
1094 }
1095 
eXosip_find_authentication_info(struct eXosip_t * excontext,const char * username,const char * realm)1096 static jauthinfo_t *eXosip_find_authentication_info(struct eXosip_t *excontext, const char *username, const char *realm) {
1097   jauthinfo_t *fallback = NULL;
1098   jauthinfo_t *authinfo;
1099 
1100   for (authinfo = excontext->authinfos; authinfo != NULL; authinfo = authinfo->next) {
1101     if (realm != NULL)
1102       OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] searching for [%s] vs authinfo [%s]\n", realm, authinfo->realm));
1103 
1104     if (0 == osip_strcasecmp(authinfo->username, username)) {
1105       if (authinfo->realm[0] == '\0') {
1106         fallback = authinfo;
1107 
1108       } else if (realm == NULL || osip_strcasecmp(realm, authinfo->realm) == 0 || 0 == osip_strncasecmp(realm + 1, authinfo->realm, strlen(realm) - 2)) {
1109         return authinfo;
1110       }
1111     }
1112   }
1113 
1114   /* no matching username has been found for this realm,
1115      try with another username... */
1116   for (authinfo = excontext->authinfos; authinfo != NULL; authinfo = authinfo->next) {
1117     if (realm != NULL)
1118       OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] searching for [%s] vs authinfo [%s]\n", realm, authinfo->realm));
1119 
1120     if (authinfo->realm[0] == '\0' && fallback == NULL) {
1121       fallback = authinfo;
1122 
1123     } else if (realm == NULL || osip_strcasecmp(realm, authinfo->realm) == 0 || 0 == osip_strncasecmp(realm + 1, authinfo->realm, strlen(realm) - 2)) {
1124       return authinfo;
1125     }
1126   }
1127 
1128   return fallback;
1129 }
1130 
eXosip_clear_authentication_info(struct eXosip_t * excontext)1131 int eXosip_clear_authentication_info(struct eXosip_t *excontext) {
1132   jauthinfo_t *jauthinfo;
1133 
1134   for (jauthinfo = excontext->authinfos; jauthinfo != NULL; jauthinfo = excontext->authinfos) {
1135     REMOVE_ELEMENT(excontext->authinfos, jauthinfo);
1136     osip_free(jauthinfo);
1137   }
1138 
1139   return OSIP_SUCCESS;
1140 }
1141 
eXosip_add_authentication_info(struct eXosip_t * excontext,const char * username,const char * userid,const char * passwd,const char * ha1,const char * realm)1142 int eXosip_add_authentication_info(struct eXosip_t *excontext, const char *username, const char *userid, const char *passwd, const char *ha1, const char *realm) {
1143   jauthinfo_t *authinfos;
1144 
1145   if (username == NULL || username[0] == '\0')
1146     return OSIP_BADPARAMETER;
1147 
1148   if (userid == NULL || userid[0] == '\0')
1149     return OSIP_BADPARAMETER;
1150 
1151   if (passwd != NULL && passwd[0] != '\0') {
1152   } else if (ha1 != NULL && ha1[0] != '\0') {
1153   } else
1154     return OSIP_BADPARAMETER;
1155 
1156   authinfos = (jauthinfo_t *) osip_malloc(sizeof(jauthinfo_t));
1157 
1158   if (authinfos == NULL)
1159     return OSIP_NOMEM;
1160 
1161   memset(authinfos, 0, sizeof(jauthinfo_t));
1162 
1163   eXosip_remove_authentication_info(excontext, username, realm);
1164 
1165   snprintf(authinfos->username, 50, "%s", username);
1166   snprintf(authinfos->userid, 50, "%s", userid);
1167 
1168   if (passwd != NULL && passwd[0] != '\0')
1169     snprintf(authinfos->passwd, 50, "%s", passwd);
1170 
1171   else if (ha1 != NULL && ha1[0] != '\0')
1172     snprintf(authinfos->ha1, 50, "%s", ha1);
1173 
1174   if (realm != NULL && realm[0] != '\0')
1175     snprintf(authinfos->realm, 50, "%s", realm);
1176 
1177   ADD_ELEMENT(excontext->authinfos, authinfos);
1178   return OSIP_SUCCESS;
1179 }
1180 
eXosip_remove_authentication_info(struct eXosip_t * excontext,const char * username,const char * realm)1181 int eXosip_remove_authentication_info(struct eXosip_t *excontext, const char *username, const char *realm) {
1182   jauthinfo_t *authinfo;
1183 
1184   if (username == NULL || username[0] == '\0')
1185     return OSIP_BADPARAMETER;
1186 
1187   for (authinfo = excontext->authinfos; authinfo != NULL; authinfo = authinfo->next) {
1188     if (osip_strcasecmp(username, authinfo->username) == 0) {
1189       if (realm != NULL && osip_strcasecmp(realm, authinfo->realm) != 0)
1190         continue;
1191 
1192       if (realm == NULL && authinfo->realm[0] != '\0')
1193         continue;
1194 
1195       REMOVE_ELEMENT(excontext->authinfos, authinfo);
1196       osip_free(authinfo);
1197       return OSIP_SUCCESS;
1198     }
1199   }
1200 
1201   return OSIP_NOTFOUND;
1202 }
1203 
authorization_already_exist_for_realm(osip_message_t * req,const char * realm)1204 static int authorization_already_exist_for_realm(osip_message_t *req, const char *realm) {
1205   osip_authorization_t *aut = NULL;
1206   int pos = 0;
1207   osip_message_get_authorization(req, pos, &aut);
1208 
1209   while (aut != NULL) {
1210     if (aut->realm != NULL && realm != NULL && osip_strcasecmp(realm, aut->realm) == 0) {
1211       /* there is a match */
1212       return OSIP_SUCCESS;
1213     }
1214 
1215     pos++;
1216     osip_message_get_authorization(req, pos, &aut);
1217   }
1218 
1219   return OSIP_NOTFOUND;
1220 }
1221 
proxyauthorization_already_exist_for_realm(osip_message_t * req,const char * realm)1222 static int proxyauthorization_already_exist_for_realm(osip_message_t *req, const char *realm) {
1223   osip_proxy_authorization_t *aut = NULL;
1224   int pos = 0;
1225   osip_message_get_proxy_authorization(req, pos, &aut);
1226 
1227   while (aut != NULL) {
1228     if (aut->realm != NULL && realm != NULL && osip_strcasecmp(realm, aut->realm) == 0) {
1229       /* there is a match */
1230       return OSIP_SUCCESS;
1231     }
1232 
1233     pos++;
1234     osip_message_get_proxy_authorization(req, pos, &aut);
1235   }
1236 
1237   return OSIP_NOTFOUND;
1238 }
1239 
_eXosip_add_authentication_information(struct eXosip_t * excontext,osip_message_t * req,osip_message_t * last_response)1240 int _eXosip_add_authentication_information(struct eXosip_t *excontext, osip_message_t *req, osip_message_t *last_response) {
1241   osip_authorization_t *aut = NULL;
1242   osip_www_authenticate_t *wwwauth = NULL;
1243   osip_proxy_authorization_t *proxy_aut = NULL;
1244   osip_proxy_authenticate_t *proxyauth = NULL;
1245   jauthinfo_t *authinfo = NULL;
1246   int pos;
1247   int i;
1248   unsigned int val_cnonce = osip_build_random_number();
1249 
1250   if (req == NULL || req->from == NULL || req->from->url == NULL || req->from->url->username == NULL) {
1251     OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL, "[eXosip] authinfo: Invalid message\n"));
1252     return OSIP_BADPARAMETER;
1253   }
1254 
1255   if (last_response == NULL) {
1256     /* we can add all credential that belongs to the same call-id */
1257     struct eXosip_http_auth *http_auth;
1258 
1259     /* update entries with same call_id */
1260     for (pos = 0; pos < MAX_EXOSIP_HTTP_AUTH; pos++) {
1261       http_auth = &excontext->http_auths[pos];
1262 
1263       if (http_auth->pszCallId[0] == '\0')
1264         continue;
1265 
1266       if (osip_strcasecmp(http_auth->pszCallId, req->call_id->number) == 0) {
1267         char *uri;
1268 
1269         authinfo = eXosip_find_authentication_info(excontext, req->from->url->username, http_auth->wa->realm);
1270 
1271         if (authinfo == NULL) {
1272           if (http_auth->wa->realm != NULL)
1273             OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL, "[eXosip] authinfo: No authentication found for %s %s\n", req->from->url->username, http_auth->wa->realm));
1274 
1275           return OSIP_NOTFOUND;
1276         }
1277 
1278         i = osip_uri_to_str(req->req_uri, &uri);
1279 
1280         if (i != 0)
1281           return i;
1282 
1283         http_auth->iNonceCount++;
1284         snprintf(http_auth->pszCNonce, sizeof(http_auth->pszCNonce), "%x", val_cnonce);
1285         i = _eXosip_create_proxy_authorization_header(http_auth->wa, uri, authinfo->userid, authinfo->passwd, authinfo->ha1, &aut, req->sip_method, http_auth->pszCNonce, http_auth->iNonceCount);
1286 
1287         osip_free(uri);
1288 
1289         if (i != 0)
1290           return i;
1291 
1292         if (aut != NULL) {
1293           if (http_auth->answer_code == 401)
1294             osip_list_add(&req->authorizations, aut, -1);
1295 
1296           else
1297             osip_list_add(&req->proxy_authorizations, aut, -1);
1298 
1299           osip_message_force_update(req);
1300         }
1301       }
1302     }
1303 
1304     return OSIP_SUCCESS;
1305   }
1306 
1307   pos = 0;
1308   osip_message_get_www_authenticate(last_response, pos, &wwwauth);
1309   osip_message_get_proxy_authenticate(last_response, pos, &proxyauth);
1310 
1311   if (wwwauth == NULL && proxyauth == NULL) {
1312     OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL, "[eXosip] authinfo: No WWW-Authenticate or Proxy-Authenticate\n"));
1313     return OSIP_SYNTAXERROR;
1314   }
1315 
1316   while (wwwauth != NULL) {
1317     char *uri;
1318     char _cnonce[64];
1319 
1320     authinfo = eXosip_find_authentication_info(excontext, req->from->url->username, wwwauth->realm);
1321 
1322     if (authinfo == NULL) {
1323       if (wwwauth->realm != NULL)
1324         OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL, "[eXosip] authinfo: No authentication found for %s %s\n", req->from->url->username, wwwauth->realm));
1325 
1326       pos++;
1327       osip_message_get_www_authenticate(last_response, pos, &wwwauth);
1328       continue; /* not compliant with rfc8760 (should stop and no retry), but I prefer best effort */
1329     }
1330 
1331     /* do we already have an authorization header for the same realm? If we do, skip the new header (alternative authentication) */
1332     if (wwwauth->realm != NULL && authorization_already_exist_for_realm(req, wwwauth->realm) == 0) {
1333       pos++;
1334       osip_message_get_www_authenticate(last_response, pos, &wwwauth);
1335       continue; /* fix: skip and continue when there are several challenge for one service */
1336     }
1337 
1338     i = osip_uri_to_str(req->req_uri, &uri);
1339 
1340     if (i != 0)
1341       return i;
1342 
1343     snprintf(_cnonce, sizeof(_cnonce), "%x", val_cnonce);
1344     i = _eXosip_create_proxy_authorization_header(wwwauth, uri, authinfo->userid, authinfo->passwd, authinfo->ha1, &aut, req->sip_method, _cnonce, 1);
1345     osip_free(uri);
1346 
1347     if (i != 0) {
1348       pos++;
1349       osip_message_get_www_authenticate(last_response, pos, &wwwauth);
1350       continue; /* we should make a difference between errors VS not supported // not compliant with rfc8760 (should stop and no retry), but I prefer best effort */
1351     }
1352 
1353     if (aut != NULL) {
1354       osip_list_add(&req->authorizations, aut, -1);
1355       osip_message_force_update(req);
1356     }
1357 
1358 #if defined(AVOID_REFRESH_WITHOUT_CREDENTIAL)
1359 
1360     if (wwwauth->qop_options != NULL) {
1361 #endif
1362 
1363       if (osip_strcasecmp(req->sip_method, "REGISTER") == 0 || osip_strcasecmp(req->sip_method, "INVITE") == 0 || osip_strcasecmp(req->sip_method, "SUBSCRIBE") == 0 || osip_strcasecmp(req->sip_method, "REFER") == 0)
1364         _eXosip_store_nonce(excontext, req->call_id->number, wwwauth, 401);
1365 
1366       else {
1367         osip_generic_param_t *to_tag = NULL;
1368 
1369         osip_from_param_get_byname(req->to, "tag", &to_tag);
1370 
1371         if (to_tag != NULL) {
1372           /* if message is part of a dialog */
1373           _eXosip_store_nonce(excontext, req->call_id->number, wwwauth, 401);
1374         }
1375       }
1376 
1377 #if defined(AVOID_REFRESH_WITHOUT_CREDENTIAL)
1378     }
1379 
1380 #endif
1381 
1382     pos++;
1383     osip_message_get_www_authenticate(last_response, pos, &wwwauth);
1384   }
1385 
1386   pos = 0;
1387 
1388   while (proxyauth != NULL) {
1389     char *uri;
1390     char _cnonce[64];
1391 
1392     authinfo = eXosip_find_authentication_info(excontext, req->from->url->username, proxyauth->realm);
1393 
1394     if (authinfo == NULL) {
1395       if (proxyauth->realm != NULL)
1396         OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL, "[eXosip] authinfo: No authentication found for %s %s\n", req->from->url->username, proxyauth->realm));
1397 
1398       pos++;
1399       osip_message_get_www_authenticate(last_response, pos, &proxyauth);
1400       continue; /* not compliant with rfc8760 (should stop and no retry), but I prefer best effort */
1401     }
1402 
1403     /* do we already have an authorization header for the same realm? If we do, skip the new header (alternative authentication) */
1404     if (proxyauth->realm != NULL && proxyauthorization_already_exist_for_realm(req, proxyauth->realm) == 0) {
1405       pos++;
1406       osip_message_get_proxy_authenticate(last_response, pos, &proxyauth);
1407       continue; /* fix: skip and continue when there are several challenge for one service */
1408     }
1409 
1410     i = osip_uri_to_str(req->req_uri, &uri);
1411 
1412     if (i != 0)
1413       return i;
1414 
1415     snprintf(_cnonce, sizeof(_cnonce), "%x", val_cnonce);
1416     i = _eXosip_create_proxy_authorization_header(proxyauth, uri, authinfo->userid, authinfo->passwd, authinfo->ha1, &proxy_aut, req->sip_method, _cnonce, 1);
1417     osip_free(uri);
1418 
1419     if (i != 0) {
1420       pos++;
1421       osip_message_get_proxy_authenticate(last_response, pos, &proxyauth);
1422       continue; /* we should make a difference between errors VS not supported // not compliant with rfc8760 (should stop and no retry), but I prefer best effort */
1423     }
1424 
1425     if (proxy_aut != NULL) {
1426       osip_list_add(&req->proxy_authorizations, proxy_aut, -1);
1427       osip_message_force_update(req);
1428     }
1429 
1430 #if defined(AVOID_REFRESH_WITHOUT_CREDENTIAL)
1431 
1432     if (proxyauth->qop_options != NULL) {
1433 #endif
1434 
1435       if (osip_strcasecmp(req->sip_method, "REGISTER") == 0 || osip_strcasecmp(req->sip_method, "INVITE") == 0 || osip_strcasecmp(req->sip_method, "SUBSCRIBE") == 0 || osip_strcasecmp(req->sip_method, "REFER") == 0)
1436         _eXosip_store_nonce(excontext, req->call_id->number, proxyauth, 407);
1437 
1438       else {
1439         osip_generic_param_t *to_tag = NULL;
1440 
1441         osip_from_param_get_byname(req->to, "tag", &to_tag);
1442 
1443         if (to_tag != NULL) {
1444           /* if message is part of a dialog */
1445           _eXosip_store_nonce(excontext, req->call_id->number, proxyauth, 407);
1446         }
1447       }
1448 
1449 #if defined(AVOID_REFRESH_WITHOUT_CREDENTIAL)
1450     }
1451 
1452 #endif
1453 
1454     pos++;
1455     osip_message_get_proxy_authenticate(last_response, pos, &proxyauth);
1456   }
1457 
1458   return OSIP_SUCCESS;
1459 }
1460 
_eXosip_update_top_via(osip_message_t * sip)1461 int _eXosip_update_top_via(osip_message_t *sip) {
1462   unsigned int number;
1463   char tmp[40];
1464   osip_generic_param_t *br = NULL;
1465   osip_via_t *via = (osip_via_t *) osip_list_get(&sip->vias, 0);
1466 
1467   if (via == NULL) {
1468     OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] missing via in SIP message\n"));
1469     return OSIP_SYNTAXERROR;
1470   }
1471 
1472   osip_free(via->host);
1473   /* special values to be replaced in transport layer (eXtl_*.c files) */
1474   via->host = osip_strdup("999.999.999.999");
1475 
1476   if (via->host == NULL)
1477     return OSIP_NOMEM;
1478 
1479   /* browse parameter and replace "branch" */
1480   osip_via_param_get_byname(via, "branch", &br);
1481 
1482   if (br == NULL || br->gvalue == NULL) {
1483     OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "[eXosip] missing branch parameter via in SIP message\n"));
1484     return OSIP_SYNTAXERROR;
1485   }
1486 
1487   osip_free(br->gvalue);
1488   number = osip_build_random_number();
1489 
1490   snprintf(tmp, 40, "z9hG4bK%u", number);
1491   br->gvalue = osip_strdup(tmp);
1492   return OSIP_SUCCESS;
1493 }
1494 
1495 /* vivox: mark all registrations as needing refreshing */
_eXosip_mark_all_registrations_expired(struct eXosip_t * excontext)1496 void _eXosip_mark_all_registrations_expired(struct eXosip_t *excontext) {
1497   eXosip_reg_t *jr;
1498   int wakeup = 0;
1499 
1500   for (jr = excontext->j_reg; jr != NULL; jr = jr->next) {
1501     if (jr->r_id >= 1 && jr->r_last_tr != NULL) {
1502       jr->r_last_tr->birth_time -= jr->r_reg_period;
1503       wakeup = 1;
1504     }
1505   }
1506 
1507   if (wakeup) {
1508     _eXosip_wakeup(excontext);
1509   }
1510 }
1511 
_eXosip_mark_all_transaction_transport_error(struct eXosip_t * excontext,int socket)1512 void _eXosip_mark_all_transaction_transport_error(struct eXosip_t *excontext, int socket) {
1513   osip_list_iterator_t it;
1514   osip_transaction_t *transaction;
1515 
1516   if (excontext->j_stop_ua == 1)
1517     return;
1518 
1519   transaction = (osip_transaction_t *) osip_list_get_first(&excontext->j_osip->osip_ict_transactions, &it);
1520 
1521   while (transaction != OSIP_SUCCESS) {
1522     if (transaction->state == ICT_CALLING && transaction->out_socket == socket) {
1523 
1524       transaction->out_socket = -999;
1525       osip_gettimeofday(&transaction->ict_context->timer_b_start, NULL);
1526       add_gettimeofday(&transaction->ict_context->timer_b_start, 0);
1527     }
1528     transaction = (osip_transaction_t *) osip_list_get_next(&it);
1529   }
1530 
1531   transaction = (osip_transaction_t *) osip_list_get_first(&excontext->j_osip->osip_nict_transactions, &it);
1532 
1533   while (transaction != OSIP_SUCCESS) {
1534     if ((transaction->state == NICT_TRYING || transaction->state == NICT_PROCEEDING) && transaction->out_socket == socket) {
1535 
1536       transaction->out_socket = -999;
1537       osip_gettimeofday(&transaction->nict_context->timer_f_start, NULL);
1538       add_gettimeofday(&transaction->nict_context->timer_f_start, 0);
1539     }
1540     transaction = (osip_transaction_t *) osip_list_get_next(&it);
1541   }
1542 }
1543 
_eXosip_mark_all_transaction_force_send(struct eXosip_t * excontext,int socket)1544 void _eXosip_mark_all_transaction_force_send(struct eXosip_t *excontext, int socket) {
1545   osip_list_iterator_t it;
1546   osip_transaction_t *transaction;
1547 
1548   transaction = (osip_transaction_t *) osip_list_get_first(&excontext->j_osip->osip_ict_transactions, &it);
1549 
1550   while (transaction != OSIP_SUCCESS) {
1551     if (transaction->state == ICT_CALLING && transaction->out_socket == socket) {
1552       if (transaction->ict_context->timer_a_length > 0) {
1553         osip_gettimeofday(&transaction->ict_context->timer_a_start, NULL);
1554         add_gettimeofday(&transaction->ict_context->timer_a_start, 0);
1555       }
1556     }
1557     transaction = (osip_transaction_t *) osip_list_get_next(&it);
1558   }
1559 
1560   transaction = (osip_transaction_t *) osip_list_get_first(&excontext->j_osip->osip_nict_transactions, &it);
1561 
1562   while (transaction != OSIP_SUCCESS) {
1563     if (transaction->state == NICT_TRYING && transaction->out_socket == socket) {
1564       if (transaction->nict_context->timer_e_length > 0) {
1565         osip_gettimeofday(&transaction->nict_context->timer_e_start, NULL);
1566         add_gettimeofday(&transaction->nict_context->timer_e_start, 0);
1567       }
1568     }
1569     transaction = (osip_transaction_t *) osip_list_get_next(&it);
1570   }
1571 }
1572 
_eXosip_mark_registration_expired(struct eXosip_t * excontext,const char * call_id)1573 void _eXosip_mark_registration_expired(struct eXosip_t *excontext, const char *call_id) {
1574   eXosip_reg_t *jr;
1575   int wakeup = 0;
1576 
1577   for (jr = excontext->j_reg; jr != NULL; jr = jr->next) {
1578     if (jr->r_id < 1 || jr->r_last_tr == NULL)
1579       continue;
1580 
1581     if (jr->r_last_tr->orig_request == NULL || jr->r_last_tr->orig_request->call_id == NULL || jr->r_last_tr->orig_request->call_id->number == NULL)
1582       continue;
1583 
1584     if (osip_strcasecmp(jr->r_last_tr->orig_request->call_id->number, call_id) == 0) {
1585       time_t now;
1586 
1587       if (jr->r_reg_period <= 0)
1588         break; /* no need for a retry */
1589 
1590       now = osip_getsystemtime(NULL);
1591 
1592       if (jr->r_last_tr->last_response == NULL || (!MSG_IS_STATUS_2XX(jr->r_last_tr->last_response))) {
1593 
1594         if (jr->r_last_tr->last_response != NULL) {
1595           osip_header_t *retry_after_header = NULL;
1596           osip_message_header_get_byname(jr->r_last_tr->last_response, (const char *) "retry-after", 0, &retry_after_header);
1597           if (retry_after_header != NULL && retry_after_header->hvalue != NULL) {
1598             jr->r_retry_after_delay = osip_atoi(retry_after_header->hvalue);
1599             if (jr->r_retry_after_delay < 0)
1600               jr->r_retry_after_delay = 0;
1601             if (jr->r_retry_after_delay > 0)
1602               jr->r_retry_after_delay += now;
1603           }
1604         }
1605 
1606         jr->r_last_tr->birth_time = now - 120; /* after a failure, always make it exactly now-120 */
1607 
1608       } else if (jr->r_reg_period > 900) {
1609         jr->r_last_tr->birth_time = now - 900; /* after a success, a new REGISTER is always sent after 900 sec */
1610 
1611       } else { /* after a success, a new REGISTER is always sent after 90% of the duration has elapsed */
1612         jr->r_last_tr->birth_time = now - jr->r_reg_period + (jr->r_reg_period / 10);
1613       }
1614 
1615       if (jr->r_retryfailover < 60)
1616         jr->r_retryfailover++;
1617 
1618       jr->r_last_tr->birth_time += jr->r_retryfailover; /* wait "RETRY" (counter) seconds before retrying: avoid flooding */
1619       wakeup = 1;
1620     }
1621   }
1622 
1623   if (wakeup) {
1624     _eXosip_wakeup(excontext);
1625   }
1626 }
1627 
_eXosip_mark_all_transaction_ready(struct eXosip_t * excontext,fd_set * osip_fdset,fd_set * osip_wrset,fd_set * osip_exceptset,int * osip_fd_table)1628 int _eXosip_mark_all_transaction_ready(struct eXosip_t *excontext, fd_set *osip_fdset, fd_set *osip_wrset, fd_set *osip_exceptset, int *osip_fd_table) {
1629   osip_list_iterator_t it;
1630   osip_transaction_t *transaction;
1631 
1632   transaction = (osip_transaction_t *) osip_list_get_first(&excontext->j_osip->osip_ict_transactions, &it);
1633 
1634   while (transaction != OSIP_SUCCESS) {
1635     if (transaction->state == ICT_CALLING && transaction->out_socket > 0) {
1636       if (FD_ISSET(transaction->out_socket, osip_fdset) || FD_ISSET(transaction->out_socket, osip_wrset) || FD_ISSET(transaction->out_socket, osip_exceptset)) {
1637         /* we need this to be processed in tl_send_message, so we can take action on transactions */
1638         if (FD_ISSET(transaction->out_socket, osip_fdset)) {
1639           OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [socket event] [ICT] read descriptor is set\n"));
1640         }
1641         if (FD_ISSET(transaction->out_socket, osip_wrset)) {
1642           OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [socket event] [ICT] write descriptor is set\n"));
1643         }
1644         if (FD_ISSET(transaction->out_socket, osip_exceptset)) {
1645           OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [socket event] [ICT] except descriptor is set\n"));
1646         }
1647 
1648         if (transaction->ict_context->timer_a_length > 0) {
1649           _eXosip_wakeup(excontext); /* TODO: is this required? */
1650           return 1;
1651         }
1652       }
1653     }
1654 
1655     transaction = (osip_transaction_t *) osip_list_get_next(&it);
1656   }
1657 
1658   transaction = (osip_transaction_t *) osip_list_get_first(&excontext->j_osip->osip_nict_transactions, &it);
1659 
1660   while (transaction != OSIP_SUCCESS) {
1661     if (transaction->state == NICT_TRYING && transaction->out_socket > 0) {
1662       if (FD_ISSET(transaction->out_socket, osip_fdset) || FD_ISSET(transaction->out_socket, osip_wrset) || FD_ISSET(transaction->out_socket, osip_exceptset)) {
1663         /* we need this to be processed in tl_send_message, so we can take action on transactions */
1664         if (FD_ISSET(transaction->out_socket, osip_fdset)) {
1665           OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [socket event] [NICT] read descriptor is set\n"));
1666         }
1667         if (FD_ISSET(transaction->out_socket, osip_wrset)) {
1668           OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [socket event] [NICT] write descriptor is set\n"));
1669         }
1670         if (FD_ISSET(transaction->out_socket, osip_exceptset)) {
1671           OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [socket event] [NICT] except descriptor is set\n"));
1672         }
1673 
1674         if (transaction->nict_context->timer_e_length > 0) {
1675           _eXosip_wakeup(excontext);
1676           return 1;
1677         }
1678       }
1679     }
1680 
1681     transaction = (osip_transaction_t *) osip_list_get_next(&it);
1682   }
1683 
1684   return OSIP_UNDEFINED_ERROR;
1685 }
1686 
1687 #ifdef HAVE_SYS_EPOLL_H
1688 
_eXosip_mark_all_transaction_ready_epoll(struct eXosip_t * excontext,int nfds,int * osip_fd_table)1689 int _eXosip_mark_all_transaction_ready_epoll(struct eXosip_t *excontext, int nfds, int *osip_fd_table) {
1690   osip_list_iterator_t it;
1691   osip_transaction_t *transaction;
1692 
1693   transaction = (osip_transaction_t *) osip_list_get_first(&excontext->j_osip->osip_ict_transactions, &it);
1694 
1695   while (transaction != OSIP_SUCCESS) {
1696     if (transaction->state == ICT_CALLING && transaction->out_socket > 0) {
1697       int n;
1698       for (n = 0; n < nfds; ++n) {
1699         if (excontext->ep_array[n].data.fd == transaction->out_socket) {
1700           if ((excontext->ep_array[n].events & EPOLLIN) || excontext->ep_array[n].events & EPOLLOUT) {
1701             if (excontext->ep_array[n].events & EPOLLIN) {
1702               OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [socket event] [ICT]  read descriptor is set\n"));
1703             }
1704             if (excontext->ep_array[n].events & EPOLLOUT) {
1705               OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [socket event] [ICT]  write descriptor is set\n"));
1706             }
1707           }
1708 
1709           if (transaction->ict_context->timer_a_length > 0) {
1710             _eXosip_wakeup(excontext);
1711             return 1;
1712           }
1713         }
1714       }
1715     }
1716 
1717     transaction = (osip_transaction_t *) osip_list_get_next(&it);
1718   }
1719 
1720   transaction = (osip_transaction_t *) osip_list_get_first(&excontext->j_osip->osip_nict_transactions, &it);
1721 
1722   while (transaction != OSIP_SUCCESS) {
1723     if (transaction->state == NICT_TRYING && transaction->out_socket > 0) {
1724       int n;
1725       for (n = 0; n < nfds; ++n) {
1726         if (excontext->ep_array[n].data.fd == transaction->out_socket) {
1727           if ((excontext->ep_array[n].events & EPOLLIN) || excontext->ep_array[n].events & EPOLLOUT) {
1728             if (excontext->ep_array[n].events & EPOLLIN) {
1729               OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [socket event] [NICT] read descriptor is set\n"));
1730             }
1731             if (excontext->ep_array[n].events & EPOLLOUT) {
1732               OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL, "[eXosip] [socket event] [NICT] write descriptor is set\n"));
1733             }
1734           }
1735 
1736           if (transaction->nict_context->timer_e_length > 0) {
1737             _eXosip_wakeup(excontext);
1738             return 1;
1739           }
1740         }
1741       }
1742     }
1743 
1744     transaction = (osip_transaction_t *) osip_list_get_next(&it);
1745   }
1746   return OSIP_UNDEFINED_ERROR;
1747 }
1748 #endif
1749 
_eXosip_check_allow_header(eXosip_dialog_t * jd,osip_message_t * message)1750 int _eXosip_check_allow_header(eXosip_dialog_t *jd, osip_message_t *message) {
1751 #ifndef MINISIZE
1752   osip_list_iterator_t it;
1753   osip_allow_t *dest = (osip_allow_t *) osip_list_get_first(&message->allows, &it);
1754 
1755   while (dest != NULL) {
1756     if (dest->value != NULL && osip_strcasecmp(dest->value, "update") == 0) {
1757       jd->d_session_timer_use_update = 1;
1758       OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL, "[eXosip] Allow header contains UPDATE\n"));
1759       break;
1760     }
1761 
1762     dest = (osip_allow_t *) osip_list_get_next(&it);
1763   }
1764 
1765 #else
1766   osip_list_iterator_t it;
1767   osip_header_t *dest = (osip_header_t *) osip_list_get_first(&message->headers, &it);
1768 
1769   while (dest != OSIP_SUCCESS) {
1770     if (dest->hvalue != NULL && osip_strcasecmp(dest->hname, "allow") == 0) {
1771       if (osip_strcasestr(dest->hvalue, "UPDATE") != NULL) {
1772         jd->d_session_timer_use_update = 1;
1773         OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL, "[eXosip] Allow header contains UPDATE\n"));
1774         break;
1775       }
1776     }
1777 
1778     dest = (osip_header_t *) osip_list_get_next(&it);
1779   }
1780 
1781 #endif
1782   return 0;
1783 }
1784