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