source: verona/libeXosip2/src/udp.c @ 268:a190752a5256

Last change on this file since 268:a190752a5256 was 268:a190752a5256, checked in by Vadim Lebedev <vadim@…>, 22 months ago

exosip COVERITY fixes

File size: 67.7 KB
Line 
1/*
2  eXosip - This is the eXtended osip library.
3  Copyright (C) 2002,2003,2004,2005,2006,2007  Aymeric MOIZARD  - jack@atosc.org
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
20
21#ifdef ENABLE_MPATROL
22#include <mpatrol.h>
23#endif
24
25#include "eXosip2.h"
26#include <eXosip2/eXosip.h>
27
28#ifndef WIN32
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <netinet/in.h>
32#include <arpa/inet.h>
33#ifdef __APPLE_CC__
34#include <unistd.h>
35#endif
36#else
37#include <windows.h>
38#endif
39
40extern eXosip_t eXosip;
41extern int ipv6_enable;
42
43/* Private functions */
44static void eXosip_send_default_answer(eXosip_dialog_t * jd,
45                                                                           osip_transaction_t * transaction,
46                                                                           osip_event_t * evt,
47                                                                           int status,
48                                                                           char *reason_phrase,
49                                                                           char *warning, int line);
50static void eXosip_process_bye(eXosip_call_t * jc, eXosip_dialog_t * jd,
51                                                           osip_transaction_t * transaction,
52                                                           osip_event_t * evt);
53static void eXosip_process_bye2(eXosip_call_t * jc, eXosip_dialog_t * jd,
54                                   osip_transaction_t * transaction, osip_event_t * evt);
55static void eXosip_process_ack(eXosip_call_t * jc, eXosip_dialog_t * jd,
56                                                           osip_event_t * evt);
57static void eXosip_process_prack(eXosip_call_t * jc, eXosip_dialog_t * jd,
58                                                                 osip_transaction_t * transaction,
59                                                                 osip_event_t * evt);
60static int cancel_match_invite(osip_transaction_t * invite,
61                                                           osip_message_t * cancel);
62static void eXosip_process_cancel(osip_transaction_t * transaction,
63                                                                  osip_event_t * evt);
64static void eXosip_process_reinvite(eXosip_call_t * jc,
65                                                                        eXosip_dialog_t * jd,
66                                                                        osip_transaction_t *
67                                                                        transaction, osip_event_t * evt);
68static void eXosip_process_new_invite(osip_transaction_t * transaction,
69                                                                          osip_event_t * evt);
70#ifndef MINISIZE
71static void eXosip_process_new_subscribe(osip_transaction_t * transaction,
72                                                                                 osip_event_t * evt);
73static void eXosip_process_subscribe_within_call(eXosip_notify_t * jn,
74                                                                                                 eXosip_dialog_t * jd,
75                                                                                                 osip_transaction_t *
76                                                                                                 transaction, osip_event_t * evt);
77static void eXosip_process_notify_within_dialog(eXosip_subscribe_t * js,
78                                                                                                eXosip_dialog_t * jd,
79                                                                                                osip_transaction_t *
80                                                                                                transaction, osip_event_t * evt);
81static int eXosip_match_notify_for_subscribe(eXosip_subscribe_t * js,
82                                                                                         osip_message_t * notify);
83#endif
84static void eXosip_process_message_within_dialog(eXosip_call_t * jc,
85                                                                                                 eXosip_dialog_t * jd,
86                                                                                                 osip_transaction_t *
87                                                                                                 transaction, osip_event_t * evt);
88static void eXosip_process_newrequest(osip_event_t * evt, int socket);
89static void eXosip_process_response_out_of_transaction(osip_event_t * evt);
90static int eXosip_pendingosip_transaction_exist(eXosip_call_t * jc,
91                                                                                                eXosip_dialog_t * jd);
92static int eXosip_release_finished_calls(eXosip_call_t * jc, eXosip_dialog_t * jd);
93static int eXosip_release_aborted_calls(eXosip_call_t * jc, eXosip_dialog_t * jd);
94
95static int eXosip_release_finished_transactions(eXosip_call_t * jc,
96                                                                                                eXosip_dialog_t * jd);
97#ifndef MINISIZE
98static int eXosip_release_finished_transactions_for_subscription(eXosip_dialog_t *
99                                                                                                                                 jd);
100#endif
101
102
103static void
104eXosip_send_default_answer(eXosip_dialog_t * jd,
105                                                   osip_transaction_t * transaction,
106                                                   osip_event_t * evt,
107                                                   int status,
108                                                   char *reason_phrase, char *warning, int line)
109{
110        osip_event_t *evt_answer;
111        osip_message_t *answer;
112        int i;
113
114        /* osip_list_add(&eXosip.j_transactions, transaction, 0); */
115        osip_transaction_set_your_instance(transaction, NULL);
116
117        /* THIS METHOD DOES NOT ACCEPT STATUS CODE BETWEEN 101 and 299 */
118        if (status > 100 && status < 299 && MSG_IS_INVITE(evt->sip))
119                return;
120
121        if (jd != NULL)
122                i = _eXosip_build_response_default(&answer, jd->d_dialog, status,
123                                                                                   evt->sip);
124        else
125                i = _eXosip_build_response_default(&answer, NULL, status, evt->sip);
126
127        if (i != 0 || answer == NULL) {
128                return;
129        }
130
131        if (reason_phrase != NULL) {
132                char *_reason;
133
134                _reason = osip_message_get_reason_phrase(answer);
135                if (_reason != NULL)
136                        osip_free(_reason);
137                _reason = osip_strdup(reason_phrase);
138                osip_message_set_reason_phrase(answer, _reason);
139        }
140
141        osip_message_set_content_length(answer, "0");
142
143        if (status == 500)
144                osip_message_set_retry_after(answer, "10");
145
146        evt_answer = osip_new_outgoing_sipmessage(answer);
147        evt_answer->transactionid = transaction->transactionid;
148        osip_transaction_add_event(transaction, evt_answer);
149        __eXosip_wakeup();
150
151}
152
153static void
154eXosip_process_bye2(eXosip_call_t * jc, eXosip_dialog_t * jd,
155                                   osip_transaction_t * transaction, osip_event_t * evt)
156{
157#ifndef MINISIZE
158        osip_transaction_set_your_instance(transaction,
159                                                                           __eXosip_new_jinfo(jc, NULL /*jd */ ,
160                                                                                                                  NULL, NULL));
161#else
162        osip_transaction_set_your_instance(transaction,
163                                                                           __eXosip_new_jinfo(jc, NULL /*jd */ ));
164#endif
165        osip_list_add(&eXosip.j_transactions, transaction, 0);
166        report_call_event(EXOSIP_CALL_MESSAGE_NEW, jc, jd, transaction);
167        report_call_event(EXOSIP_CALL_CLOSED, jc, jd, transaction);
168        eXosip_update();                        /* AMD 30/09/05 */
169
170        __eXosip_wakeup();
171}
172
173static void
174eXosip_process_bye(eXosip_call_t * jc, eXosip_dialog_t * jd,
175                                   osip_transaction_t * transaction, osip_event_t * evt)
176{
177        osip_event_t *evt_answer;
178        osip_message_t *answer;
179        int i;
180
181#ifndef MINISIZE
182        osip_transaction_set_your_instance(transaction,
183                                                                           __eXosip_new_jinfo(jc, NULL /*jd */ ,
184                                                                                                                  NULL, NULL));
185#else
186        osip_transaction_set_your_instance(transaction,
187                                                                           __eXosip_new_jinfo(jc, NULL /*jd */ ));
188#endif
189
190        i = _eXosip_build_response_default(&answer, jd->d_dialog, 200, evt->sip);
191        if (i != 0) {
192                osip_list_add(&eXosip.j_transactions, transaction, 0);
193                return;
194        }
195        osip_message_set_content_length(answer, "0");
196
197        evt_answer = osip_new_outgoing_sipmessage(answer);
198        evt_answer->transactionid = transaction->transactionid;
199
200        osip_list_add(jd->d_inc_trs, transaction, 0);
201
202        /* Release the eXosip_dialog */
203        osip_dialog_free(jd->d_dialog);
204        jd->d_dialog = NULL;
205
206        osip_transaction_add_event(transaction, evt_answer);
207
208        osip_nist_execute(eXosip.j_osip);
209        report_call_event(EXOSIP_CALL_MESSAGE_NEW, jc, jd, transaction);
210        report_call_event(EXOSIP_CALL_CLOSED, jc, jd, transaction);
211        eXosip_update();                        /* AMD 30/09/05 */
212
213        __eXosip_wakeup();
214}
215
216static void
217eXosip_process_ack(eXosip_call_t * jc, eXosip_dialog_t * jd, osip_event_t * evt)
218{
219        /* TODO: We should find the matching transaction for this ACK
220           and also add the ACK in the event. */
221        eXosip_event_t *je;
222        int i;
223
224
225        je = eXosip_event_init_for_call(EXOSIP_CALL_ACK, jc, jd, NULL);
226        if (je != NULL) {
227                osip_transaction_t *tr;
228                tr = eXosip_find_last_inc_invite(jc, jd);
229                if (tr != NULL) {
230                        je->tid = tr->transactionid;
231                        /* fill request and answer */
232                        if (tr->orig_request != NULL) {
233                                i = osip_message_clone(tr->orig_request, &je->request);
234                                if (i != 0) {
235                                        OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL,
236                                                                                  "failed to clone request for event\n"));
237                                }
238                        }
239                        if (tr->last_response != NULL) {
240                                i = osip_message_clone(tr->last_response, &je->response);
241                                if (i != 0) {
242                                        OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL,
243                                                                                  "failed to clone response for event\n"));
244                                }
245                        }
246                }
247
248                i = osip_message_clone(evt->sip, &je->ack);
249                if (i != 0) {
250                        OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL,
251                                                                  "failed to clone ACK for event\n"));
252                }
253        }
254
255        /* stop ACK retransmission, in case there is any */
256        jd->d_count = 0;
257        osip_message_free(jd->d_200Ok);
258        jd->d_200Ok = NULL;
259
260        if (je != NULL)
261                report_event(je, NULL);
262
263        osip_event_free(evt);
264}
265
266static void
267eXosip_process_prack(eXosip_call_t * jc, eXosip_dialog_t * jd,
268                                         osip_transaction_t * transaction, osip_event_t * evt)
269{
270        osip_event_t *evt_answer;
271        osip_message_t *answer;
272        int i;
273
274#ifndef MINISIZE
275        osip_transaction_set_your_instance(transaction,
276                                                                           __eXosip_new_jinfo(jc, jd, NULL, NULL));
277#else
278        osip_transaction_set_your_instance(transaction, __eXosip_new_jinfo(jc, jd));
279#endif
280
281        i = _eXosip_build_response_default(&answer, jd->d_dialog, 200, evt->sip);
282        if (i != 0) {
283                osip_list_add(&eXosip.j_transactions, transaction, 0);
284                return;
285        }
286
287        evt_answer = osip_new_outgoing_sipmessage(answer);
288        evt_answer->transactionid = transaction->transactionid;
289
290        osip_list_add(jd->d_inc_trs, transaction, 0);
291
292        osip_transaction_add_event(transaction, evt_answer);
293        __eXosip_wakeup();
294}
295
296static int
297cancel_match_invite(osip_transaction_t * invite, osip_message_t * cancel)
298{
299        osip_generic_param_t *br;
300        osip_generic_param_t *br2;
301        osip_via_t *via;
302
303        osip_via_param_get_byname(invite->topvia, "branch", &br);
304        via = osip_list_get(&cancel->vias, 0);
305        if (via == NULL)
306                return OSIP_SYNTAXERROR;        /* request without via??? */
307        osip_via_param_get_byname(via, "branch", &br2);
308        if (br != NULL && br2 == NULL)
309                return OSIP_UNDEFINED_ERROR;
310        if (br2 != NULL && br == NULL)
311                return OSIP_UNDEFINED_ERROR;
312        if (br2 != NULL && br != NULL) {        /* compliant UA  :) */
313                if (br->gvalue != NULL && br2->gvalue != NULL &&
314                        0 == strcmp(br->gvalue, br2->gvalue))
315                        return OSIP_SUCCESS;
316                return OSIP_UNDEFINED_ERROR;
317        }
318        /* old backward compatibility mechanism */
319        if (0 != osip_call_id_match(invite->callid, cancel->call_id))
320                return OSIP_UNDEFINED_ERROR;
321        if (0 != osip_to_tag_match(invite->to, cancel->to))
322                return OSIP_UNDEFINED_ERROR;
323        if (0 != osip_from_tag_match(invite->from, cancel->from))
324                return OSIP_UNDEFINED_ERROR;
325        if (0 != osip_via_match(invite->topvia, via))
326                return OSIP_UNDEFINED_ERROR;
327        return OSIP_SUCCESS;
328}
329
330static void
331eXosip_process_cancel(osip_transaction_t * transaction, osip_event_t * evt)
332{
333        osip_transaction_t *tr;
334        osip_event_t *evt_answer;
335        osip_message_t *answer;
336        int i;
337
338        eXosip_call_t *jc;
339        eXosip_dialog_t *jd;
340
341        tr = NULL;
342        jd = NULL;
343        /* first, look for a Dialog in the map of element */
344        for (jc = eXosip.j_calls; jc != NULL; jc = jc->next) {
345                if (jc->c_inc_tr != NULL) {
346                        i = cancel_match_invite(jc->c_inc_tr, evt->sip);
347                        if (i == 0) {
348                                tr = jc->c_inc_tr;
349                                /* fixed */
350                                if (jc->c_dialogs != NULL)
351                                        jd = jc->c_dialogs;
352                                break;
353                        }
354                }
355                tr = NULL;
356                for (jd = jc->c_dialogs; jd != NULL; jd = jd->next) {
357                        int pos = 0;
358
359                        while (!osip_list_eol(jd->d_inc_trs, pos)) {
360                                tr = osip_list_get(jd->d_inc_trs, pos);
361                                i = cancel_match_invite(tr, evt->sip);
362                                if (i == 0)
363                                        goto found;
364                                tr = NULL;
365                                pos++;
366                        }
367                }
368found:
369                if (jd != NULL)
370                        break;                          /* tr has just been found! */
371        }
372
373        if (tr == NULL) {                       /* we didn't found the transaction to cancel */
374                i = _eXosip_build_response_default(&answer, NULL, 481, evt->sip);
375                if (i != 0) {
376                        OSIP_TRACE(osip_trace
377                                           (__FILE__, __LINE__, OSIP_ERROR, NULL,
378                                                "eXosip: cannot cancel transaction.\n"));
379                        osip_list_add(&eXosip.j_transactions, tr, 0);
380                        osip_transaction_set_your_instance(tr, NULL);
381                        return;
382                }
383                osip_message_set_content_length(answer, "0");
384                evt_answer = osip_new_outgoing_sipmessage(answer);
385                evt_answer->transactionid = transaction->transactionid;
386                osip_transaction_add_event(transaction, evt_answer);
387
388                osip_list_add(&eXosip.j_transactions, transaction, 0);
389                osip_transaction_set_your_instance(transaction, NULL);
390                __eXosip_wakeup();
391                return;
392        }
393
394        if (tr->state == IST_TERMINATED || tr->state == IST_CONFIRMED
395                || tr->state == IST_COMPLETED) {
396                /* I can't find the status code in the rfc?
397                   (I read I must answer 200? wich I found strange)
398                   I probably misunderstood it... and prefer to send 481
399                   as the transaction has been answered. */
400                if (jd == NULL)
401                        i = _eXosip_build_response_default(&answer, NULL, 481, evt->sip);
402                else
403                        i = _eXosip_build_response_default(&answer, jd->d_dialog, 481,
404                                                                                           evt->sip);
405                if (i != 0) {
406                        OSIP_TRACE(osip_trace
407                                           (__FILE__, __LINE__, OSIP_ERROR, NULL,
408                                                "eXosip: cannot cancel transaction.\n"));
409                        osip_list_add(&eXosip.j_transactions, tr, 0);
410                        osip_transaction_set_your_instance(tr, NULL);
411                        return;
412                }
413                osip_message_set_content_length(answer, "0");
414                evt_answer = osip_new_outgoing_sipmessage(answer);
415                evt_answer->transactionid = transaction->transactionid;
416                osip_transaction_add_event(transaction, evt_answer);
417
418                if (jd != NULL)
419                        osip_list_add(jd->d_inc_trs, transaction, 0);
420                else
421                        osip_list_add(&eXosip.j_transactions, transaction, 0);
422                osip_transaction_set_your_instance(transaction, NULL);
423                __eXosip_wakeup();
424
425                return;
426        }
427
428        {
429                if (jd == NULL)
430                        i = _eXosip_build_response_default(&answer, NULL, 200, evt->sip);
431                else
432                        i = _eXosip_build_response_default(&answer, jd->d_dialog, 200,
433                                                                                           evt->sip);
434                if (i != 0) {
435                        OSIP_TRACE(osip_trace
436                                           (__FILE__, __LINE__, OSIP_ERROR, NULL,
437                                                "eXosip: cannot cancel transaction.\n"));
438                        osip_list_add(&eXosip.j_transactions, tr, 0);
439                        osip_transaction_set_your_instance(tr, NULL);
440                        return;
441                }
442                osip_message_set_content_length(answer, "0");
443                evt_answer = osip_new_outgoing_sipmessage(answer);
444                evt_answer->transactionid = transaction->transactionid;
445                osip_transaction_add_event(transaction, evt_answer);
446                __eXosip_wakeup();
447
448                if (jd != NULL)
449                        osip_list_add(jd->d_inc_trs, transaction, 0);
450                else
451                        osip_list_add(&eXosip.j_transactions, transaction, 0);
452                osip_transaction_set_your_instance(transaction, NULL);
453
454                /* answer transaction to cancel */
455                if (jd == NULL)
456                        i = _eXosip_build_response_default(&answer, NULL, 487,
457                                                                                           tr->orig_request);
458                else
459                        i = _eXosip_build_response_default(&answer, jd->d_dialog, 487,
460                                                                                           tr->orig_request);
461                if (i != 0) {
462                        OSIP_TRACE(osip_trace
463                                           (__FILE__, __LINE__, OSIP_ERROR, NULL,
464                                                "eXosip: cannot cancel transaction.\n"));
465                        osip_list_add(&eXosip.j_transactions, tr, 0);
466                        osip_transaction_set_your_instance(tr, NULL);
467                        return;
468                }
469                osip_message_set_content_length(answer, "0");
470                evt_answer = osip_new_outgoing_sipmessage(answer);
471                evt_answer->transactionid = tr->transactionid;
472                osip_transaction_add_event(tr, evt_answer);
473                __eXosip_wakeup();
474        }
475}
476
477static void
478eXosip_process_reinvite(eXosip_call_t * jc, eXosip_dialog_t * jd,
479                                                osip_transaction_t * transaction, osip_event_t * evt)
480{
481#ifndef MINISIZE
482        osip_transaction_set_your_instance(transaction,
483                                                                           __eXosip_new_jinfo(jc, jd, NULL, NULL));
484#else
485        osip_transaction_set_your_instance(transaction, __eXosip_new_jinfo(jc, jd));
486#endif
487
488        osip_list_add(jd->d_inc_trs, transaction, 0);
489        osip_ist_execute(eXosip.j_osip);
490        report_call_event(EXOSIP_CALL_REINVITE, jc, jd, transaction);
491}
492
493static void
494eXosip_process_new_invite(osip_transaction_t * transaction, osip_event_t * evt)
495{
496        osip_event_t *evt_answer;
497        int i;
498        eXosip_call_t *jc;
499        eXosip_dialog_t *jd;
500        osip_message_t *answer;
501        osip_generic_param_t *to_tag = NULL;
502        if (evt->sip != NULL && evt->sip->to != NULL)
503                osip_from_param_get_byname(evt->sip->to, "tag", &to_tag);
504
505        if (to_tag != NULL) {
506                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL,
507                                                          "ERROR: Existing To-Tag in new INVITE -> reject with 481\n"));
508                i = _eXosip_build_response_default(&answer, NULL, 481, evt->sip);
509                if (i == 0) {
510                        evt_answer = osip_new_outgoing_sipmessage(answer);
511                        evt_answer->transactionid = transaction->transactionid;
512                        eXosip_update();
513                        osip_transaction_add_event(transaction, evt_answer);
514                        return;
515                }
516                osip_message_set_content_length(answer, "0");
517                osip_list_add(&eXosip.j_transactions, transaction, 0);
518                osip_transaction_set_your_instance(transaction, NULL);
519                return;
520        }
521
522        eXosip_call_init(&jc);
523
524        ADD_ELEMENT(eXosip.j_calls, jc);
525
526        i = _eXosip_build_response_default(&answer, NULL, 101, evt->sip);
527        if (i != 0) {
528                OSIP_TRACE(osip_trace
529                                   (__FILE__, __LINE__, OSIP_ERROR, NULL,
530                                        "eXosip: cannot create dialog."));
531                osip_list_add(&eXosip.j_transactions, transaction, 0);
532                osip_transaction_set_your_instance(transaction, NULL);
533                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL,
534                                                          "ERROR: Could not create response for invite\n"));
535                return;
536        }
537        osip_message_set_content_length(answer, "0");
538        i = complete_answer_that_establish_a_dialog(answer, evt->sip);
539        if (i != 0) {
540                OSIP_TRACE(osip_trace
541                                   (__FILE__, __LINE__, OSIP_ERROR, NULL,
542                                        "eXosip: cannot complete answer!\n"));
543                osip_list_add(&eXosip.j_transactions, transaction, 0);
544                osip_transaction_set_your_instance(transaction, NULL);
545                osip_message_free(answer);
546                return;
547        }
548
549        i = eXosip_dialog_init_as_uas(&jd, evt->sip, answer);
550        if (i != 0) {
551                OSIP_TRACE(osip_trace
552                                   (__FILE__, __LINE__, OSIP_ERROR, NULL,
553                                        "eXosip: cannot create dialog!\n"));
554                osip_list_add(&eXosip.j_transactions, transaction, 0);
555                osip_transaction_set_your_instance(transaction, NULL);
556                osip_message_free(answer);
557                return;
558        }
559        ADD_ELEMENT(jc->c_dialogs, jd);
560
561#ifndef MINISIZE
562        osip_transaction_set_your_instance(transaction,
563                                                                           __eXosip_new_jinfo(jc, jd, NULL, NULL));
564#else
565        osip_transaction_set_your_instance(transaction, __eXosip_new_jinfo(jc, jd));
566#endif
567
568        evt_answer = osip_new_outgoing_sipmessage(answer);
569        evt_answer->transactionid = transaction->transactionid;
570
571        eXosip_update();
572        jc->c_inc_tr = transaction;
573        osip_transaction_add_event(transaction, evt_answer);
574
575        /* be sure the invite will be processed
576           before any API call on this dialog */
577        osip_ist_execute(eXosip.j_osip);
578
579        if (transaction->orig_request != NULL) {
580                report_call_event(EXOSIP_CALL_INVITE, jc, jd, transaction);
581        }
582
583        __eXosip_wakeup();
584
585}
586
587#ifndef MINISIZE
588
589static void
590eXosip_process_new_subscribe(osip_transaction_t * transaction, osip_event_t * evt)
591{
592        osip_event_t *evt_answer;
593        eXosip_notify_t *jn;
594        eXosip_dialog_t *jd;
595        osip_message_t *answer;
596        int i;
597        osip_generic_param_t *to_tag = NULL;
598
599        if (evt->sip != NULL && evt->sip->to != NULL)
600                osip_from_param_get_byname(evt->sip->to, "tag", &to_tag);
601
602        if (to_tag != NULL) {
603                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL,
604                                                          "ERROR: Existing To-Tag in new SUBSCRIBE -> reject with 481\n"));
605                i = _eXosip_build_response_default(&answer, NULL, 481, evt->sip);
606                if (i == 0) {
607                        evt_answer = osip_new_outgoing_sipmessage(answer);
608                        evt_answer->transactionid = transaction->transactionid;
609                        eXosip_update();
610                        osip_message_set_content_length(answer, "0");
611                        osip_transaction_add_event(transaction, evt_answer);
612                }
613                osip_list_add(&eXosip.j_transactions, transaction, 0);
614                osip_transaction_set_your_instance(transaction, NULL);
615                return;
616        }
617
618        i = eXosip_notify_init(&jn, evt->sip);
619        if (i != 0) {
620                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL,
621                                                          "ERROR: missing contact or memory\n"));
622                i = _eXosip_build_response_default(&answer, NULL, 400, evt->sip);
623                if (i == 0) {
624                        evt_answer = osip_new_outgoing_sipmessage(answer);
625                        evt_answer->transactionid = transaction->transactionid;
626                        eXosip_update();
627                        osip_message_set_content_length(answer, "0");
628                        osip_transaction_add_event(transaction, evt_answer);
629                }
630                osip_list_add(&eXosip.j_transactions, transaction, 0);
631                osip_transaction_set_your_instance(transaction, NULL);
632                return;
633        }
634        _eXosip_notify_set_refresh_interval(jn, evt->sip);
635
636        i = _eXosip_build_response_default(&answer, NULL, 101, evt->sip);
637        if (i != 0) {
638                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL,
639                                                          "ERROR: Could not create response for invite\n"));
640                osip_list_add(&eXosip.j_transactions, transaction, 0);
641                eXosip_notify_free(jn);
642                return;
643        }
644        i = complete_answer_that_establish_a_dialog(answer, evt->sip);
645        if (i != 0) {
646                osip_message_free(answer);
647                OSIP_TRACE(osip_trace
648                                   (__FILE__, __LINE__, OSIP_ERROR, NULL,
649                                        "eXosip: cannot complete answer!\n"));
650                osip_list_add(&eXosip.j_transactions, transaction, 0);
651                eXosip_notify_free(jn);
652                return;
653        }
654
655        i = eXosip_dialog_init_as_uas(&jd, evt->sip, answer);
656        if (i != 0) {
657                osip_message_free(answer);
658                OSIP_TRACE(osip_trace
659                                   (__FILE__, __LINE__, OSIP_ERROR, NULL,
660                                        "eXosip: cannot create dialog!\n"));
661                osip_list_add(&eXosip.j_transactions, transaction, 0);
662                eXosip_notify_free(jn);
663                return;
664        }
665        ADD_ELEMENT(jn->n_dialogs, jd);
666
667        osip_transaction_set_your_instance(transaction,
668                                                                           __eXosip_new_jinfo(NULL, jd, NULL, jn));
669
670        evt_answer = osip_new_outgoing_sipmessage(answer);
671        evt_answer->transactionid = transaction->transactionid;
672        osip_transaction_add_event(transaction, evt_answer);
673
674        ADD_ELEMENT(eXosip.j_notifies, jn);
675        __eXosip_wakeup();
676
677        jn->n_inc_tr = transaction;
678
679        eXosip_update();
680        __eXosip_wakeup();
681}
682
683static void
684eXosip_process_subscribe_within_call(eXosip_notify_t * jn,
685                                                                         eXosip_dialog_t * jd,
686                                                                         osip_transaction_t * transaction,
687                                                                         osip_event_t * evt)
688{
689        _eXosip_notify_set_refresh_interval(jn, evt->sip);
690        osip_transaction_set_your_instance(transaction,
691                                                                           __eXosip_new_jinfo(NULL, jd, NULL, jn));
692
693        /* if subscribe request contains expires="0", close the subscription */
694        {
695                time_t now = time(NULL);
696
697                if (jn->n_ss_expires - now <= 0) {
698                        jn->n_ss_status = EXOSIP_SUBCRSTATE_TERMINATED;
699                        jn->n_ss_reason = TIMEOUT;
700                }
701        }
702
703        osip_list_add(jd->d_inc_trs, transaction, 0);
704        __eXosip_wakeup();
705        return;
706}
707
708static void
709eXosip_process_notify_within_dialog(eXosip_subscribe_t * js,
710                                                                        eXosip_dialog_t * jd,
711                                                                        osip_transaction_t * transaction,
712                                                                        osip_event_t * evt)
713{
714        osip_message_t *answer;
715        osip_event_t *sipevent;
716        osip_header_t *sub_state;
717
718#ifdef SUPPORT_MSN
719        osip_header_t *expires;
720#endif
721        int i;
722
723        if (jd == NULL) {
724                osip_list_add(&eXosip.j_transactions, transaction, 0);
725                eXosip_send_default_answer(jd, transaction, evt, 500,
726                                                                   "Internal SIP Error",
727                                                                   "No dialog for this NOTIFY", __LINE__);
728                return;
729        }
730
731        /* if subscription-state has a reason state set to terminated,
732           we close the dialog */
733#ifndef SUPPORT_MSN
734        osip_message_header_get_byname(evt->sip, "subscription-state", 0, &sub_state);
735        if (sub_state == NULL || sub_state->hvalue == NULL) {
736                osip_list_add(&eXosip.j_transactions, transaction, 0);
737                eXosip_send_default_answer(jd, transaction, evt, 400, NULL, NULL,
738                                                                   __LINE__);
739                return;
740        }
741#endif
742
743        i = _eXosip_build_response_default(&answer, jd->d_dialog, 200, evt->sip);
744        if (i != 0) {
745                osip_list_add(&eXosip.j_transactions, transaction, 0);
746                eXosip_send_default_answer(jd, transaction, evt, 500,
747                                                                   "Internal SIP Error",
748                                                                   "Failed to build Answer for NOTIFY", __LINE__);
749                return;
750        }
751#ifdef SUPPORT_MSN
752        osip_message_header_get_byname(evt->sip, "expires", 0, &expires);
753        if (expires != NULL && expires->hvalue != NULL
754                && 0 == osip_strcasecmp(expires->hvalue, "0")) {
755                /* delete the dialog! */
756                js->s_ss_status = EXOSIP_SUBCRSTATE_TERMINATED;
757                {
758                        eXosip_event_t *je;
759
760                        je = eXosip_event_init_for_subscribe(EXOSIP_SUBSCRIPTION_NOTIFY, js,
761                                                                                                 jd);
762                        eXosip_event_add(je);
763                }
764
765                sipevent = osip_new_outgoing_sipmessage(answer);
766                sipevent->transactionid = transaction->transactionid;
767                osip_transaction_add_event(transaction, sipevent);
768
769                osip_list_add(&eXosip.j_transactions, transaction, 0);
770
771                REMOVE_ELEMENT(eXosip.j_subscribes, js);
772                eXosip_subscribe_free(js);
773                __eXosip_wakeup();
774
775                return;
776        } else {
777                osip_transaction_set_your_instance(transaction,
778                                                                                   __eXosip_new_jinfo(NULL, jd, js, NULL));
779                js->s_ss_status = EXOSIP_SUBCRSTATE_ACTIVE;
780        }
781#else
782        /* modify the status of user */
783        if (0 == osip_strncasecmp(sub_state->hvalue, "active", 6)) {
784                js->s_ss_status = EXOSIP_SUBCRSTATE_ACTIVE;
785        } else if (0 == osip_strncasecmp(sub_state->hvalue, "pending", 7)) {
786                js->s_ss_status = EXOSIP_SUBCRSTATE_PENDING;
787        }
788
789        if (0 == osip_strncasecmp(sub_state->hvalue, "terminated", 10)) {
790                /* delete the dialog! */
791                js->s_ss_status = EXOSIP_SUBCRSTATE_TERMINATED;
792
793                {
794                        eXosip_event_t *je;
795
796                        je = eXosip_event_init_for_subscribe(EXOSIP_SUBSCRIPTION_NOTIFY, js,
797                                                                                                 jd, transaction);
798                        if (je->request == NULL && evt->sip != NULL) {
799                                i = osip_message_clone(evt->sip, &je->request);
800                                if (i != 0) {
801                                        OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL,
802                                                                                  "failed to clone request for event\n"));
803                                }
804                        }
805
806                        eXosip_event_add(je);
807                }
808
809                sipevent = osip_new_outgoing_sipmessage(answer);
810                sipevent->transactionid = transaction->transactionid;
811                osip_transaction_add_event(transaction, sipevent);
812
813                osip_list_add(&eXosip.j_transactions, transaction, 0);
814
815                REMOVE_ELEMENT(eXosip.j_subscribes, js);
816                eXosip_subscribe_free(js);
817                __eXosip_wakeup();
818                return;
819        } else {
820                osip_transaction_set_your_instance(transaction,
821                                                                                   __eXosip_new_jinfo(NULL, jd, js, NULL));
822        }
823#endif
824
825        osip_list_add(jd->d_inc_trs, transaction, 0);
826
827        sipevent = osip_new_outgoing_sipmessage(answer);
828        sipevent->transactionid = transaction->transactionid;
829        osip_transaction_add_event(transaction, sipevent);
830
831        __eXosip_wakeup();
832        return;
833}
834
835static int
836eXosip_match_notify_for_subscribe(eXosip_subscribe_t * js, osip_message_t * notify)
837{
838        osip_transaction_t *out_sub;
839
840        if (js == NULL)
841                return OSIP_BADPARAMETER;
842        OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO1, NULL,
843                                                  "Trying to match notify with subscribe\n"));
844
845        out_sub = eXosip_find_last_out_subscribe(js, NULL);
846        if (out_sub == NULL || out_sub->orig_request == NULL)
847                return OSIP_NOTFOUND;
848        OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO1, NULL,
849                                                  "subscribe transaction found\n"));
850
851        /* some checks to avoid crashing on bad requests */
852        if (notify == NULL)
853                return OSIP_BADPARAMETER;
854
855        if (notify->cseq == NULL || notify->cseq->method == NULL || notify->to == NULL)
856                return OSIP_SYNTAXERROR;
857
858        if (0 != osip_call_id_match(out_sub->callid, notify->call_id))
859                return OSIP_UNDEFINED_ERROR;
860
861        {
862                /* The From tag of outgoing request must match
863                   the To tag of incoming notify:
864                 */
865                osip_generic_param_t *tag_from;
866                osip_generic_param_t *tag_to;
867
868                osip_from_param_get_byname(out_sub->from, "tag", &tag_from);
869                osip_from_param_get_byname(notify->to, "tag", &tag_to);
870                if (tag_to == NULL || tag_to->gvalue == NULL) {
871                        OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL,
872                                                                  "Uncompliant user agent: no tag in from of outgoing request\n"));
873                        return OSIP_SYNTAXERROR;
874                }
875                if (tag_from == NULL || tag_to->gvalue == NULL) {
876                        OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL,
877                                                                  "Uncompliant user agent: no tag in to of incoming request\n"));
878                        return OSIP_SYNTAXERROR;
879                }
880
881                if (0 != strcmp(tag_from->gvalue, tag_to->gvalue))
882                        return OSIP_UNDEFINED_ERROR;
883        }
884
885        return OSIP_SUCCESS;
886}
887
888#endif
889
890
891static void
892eXosip_process_message_within_dialog(eXosip_call_t * jc,
893                                                                         eXosip_dialog_t * jd,
894                                                                         osip_transaction_t * transaction,
895                                                                         osip_event_t * evt)
896{
897        osip_list_add(jd->d_inc_trs, transaction, 0);
898#ifndef MINISIZE
899        osip_transaction_set_your_instance(transaction,
900                                                                           __eXosip_new_jinfo(jc, jd, NULL, NULL));
901#else
902        osip_transaction_set_your_instance(transaction, __eXosip_new_jinfo(jc, jd));
903#endif
904        __eXosip_wakeup();
905        return;
906}
907
908
909static void eXosip_process_newrequest(osip_event_t * evt, int socket)
910{
911        osip_transaction_t *transaction;
912#ifndef MINISIZE
913        osip_event_t *evt_answer;
914        osip_message_t *answer;
915#endif
916        int i;
917        int ctx_type;
918        eXosip_call_t *jc;
919#ifndef MINISIZE
920        eXosip_subscribe_t *js;
921        eXosip_notify_t *jn;
922#endif
923        eXosip_dialog_t *jd;
924
925        if (MSG_IS_INVITE(evt->sip)) {
926                ctx_type = IST;
927        } else if (MSG_IS_ACK(evt->sip)) {      /* this should be a ACK for 2xx (but could be a late ACK!) */
928                ctx_type = -1;
929        } else if (MSG_IS_REQUEST(evt->sip)) {
930                ctx_type = NIST;
931        } else {                                        /* We should handle late response and 200 OK before coming here. */
932                ctx_type = -1;
933                osip_event_free(evt);
934                return;
935        }
936
937        transaction = NULL;
938        if (ctx_type != -1) {
939                i = _eXosip_transaction_init(&transaction,
940                                                                         (osip_fsm_type_t) ctx_type,
941                                                                         eXosip.j_osip, evt->sip);
942                if (i != 0) {
943                        osip_event_free(evt);
944                        return;
945                }
946
947                osip_transaction_set_in_socket(transaction, socket);
948                osip_transaction_set_out_socket(transaction, socket);
949
950                evt->transactionid = transaction->transactionid;
951                osip_transaction_set_your_instance(transaction, NULL);
952
953                osip_transaction_add_event(transaction, evt);
954        }
955
956        if (MSG_IS_CANCEL(evt->sip)) {
957                /* special handling for CANCEL */
958                /* in the new spec, if the CANCEL has a Via branch, then it
959                   is the same as the one in the original INVITE */
960                eXosip_process_cancel(transaction, evt);
961                return;
962        }
963
964        jd = NULL;
965        /* first, look for a Dialog in the map of element */
966        for (jc = eXosip.j_calls; jc != NULL; jc = jc->next) {
967                for (jd = jc->c_dialogs; jd != NULL; jd = jd->next) {
968                        if (jd->d_dialog != NULL) {
969                                if (osip_dialog_match_as_uas(jd->d_dialog, evt->sip) == 0)
970                                        break;
971                        }
972                }
973                if (jd != NULL)
974                        break;
975        }
976
977        /* check CSeq */
978        if (jd != NULL && transaction != NULL && evt->sip != NULL
979                && evt->sip->cseq != NULL && evt->sip->cseq->number != NULL) {
980                if (jd->d_dialog != NULL && jd->d_dialog->remote_cseq > 0) {
981                        int cseq = osip_atoi(evt->sip->cseq->number);
982                        if (cseq == jd->d_dialog->remote_cseq) {
983                                OSIP_TRACE(osip_trace
984                                                   (__FILE__, __LINE__, OSIP_ERROR, NULL,
985                                                        "eXosip: receive a request with same cseq??\n"));
986                                osip_transaction_free(transaction);
987                                return;
988                        }
989                        if (cseq <= jd->d_dialog->remote_cseq) {
990                                eXosip_send_default_answer(jd, transaction, evt, 500,
991                                                                                   NULL, "Wrong Lower CSeq", __LINE__);
992                                return;
993                        }
994                }
995        }
996#ifndef MINISIZE
997        if (ctx_type == IST) {
998                i = _eXosip_build_response_default(&answer, NULL, 100, evt->sip);
999                if (i != 0) {
1000                        __eXosip_delete_jinfo(transaction);
1001                        osip_transaction_free(transaction);
1002                        return;
1003                }
1004
1005                osip_message_set_content_length(answer, "0");
1006                /*  send message to transaction layer */
1007
1008                evt_answer = osip_new_outgoing_sipmessage(answer);
1009                evt_answer->transactionid = transaction->transactionid;
1010
1011                /* add the REQUEST & the 100 Trying */
1012                osip_transaction_add_event(transaction, evt_answer);
1013                __eXosip_wakeup();
1014        }
1015#endif
1016
1017        if (jd != NULL) {
1018                osip_transaction_t *old_trn;
1019
1020                /* it can be:
1021                   1: a new INVITE offer.
1022                   2: a REFER request from one of the party.
1023                   2: a BYE request from one of the party.
1024                   3: a REQUEST with a wrong CSeq.
1025                   4: a NOT-SUPPORTED method with a wrong CSeq.
1026                 */
1027
1028                if (transaction == NULL) {
1029                        /* cannot answer ACK transaction */
1030                } else if (!MSG_IS_BYE(evt->sip)) {
1031                        /* reject all requests for a closed dialog */
1032                        old_trn = eXosip_find_last_inc_transaction(jc, jd, "BYE");
1033                        if (old_trn == NULL)
1034                                old_trn = eXosip_find_last_out_transaction(jc, jd, "BYE");
1035
1036                        if (old_trn != NULL) {
1037                                osip_list_add(&eXosip.j_transactions, transaction, 0);
1038                                eXosip_send_default_answer(jd, transaction, evt, 481, NULL,
1039                                                                                   NULL, __LINE__);
1040                                return;
1041                        }
1042                }
1043
1044                if (transaction != NULL)        /* NOT for ACK */
1045                        osip_dialog_update_osip_cseq_as_uas(jd->d_dialog, evt->sip);
1046
1047                if (MSG_IS_INVITE(evt->sip)) {
1048                        /* the previous transaction MUST be freed */
1049                        old_trn = eXosip_find_last_inc_invite(jc, jd);
1050
1051                        if (old_trn != NULL && old_trn->state != IST_COMPLETED
1052                                && old_trn->state != IST_CONFIRMED
1053                                && old_trn->state != IST_TERMINATED) {
1054                                osip_list_add(&eXosip.j_transactions, transaction, 0);
1055                                eXosip_send_default_answer(jd, transaction, evt, 500,
1056                                                                                   "Retry Later",
1057                                                                                   "An INVITE is not terminated",
1058                                                                                   __LINE__);
1059                                return;
1060                        }
1061
1062                        old_trn = eXosip_find_last_out_invite(jc, jd);
1063                        if (old_trn != NULL && old_trn->state != ICT_COMPLETED
1064                                && old_trn->state != ICT_TERMINATED) {
1065                                osip_list_add(&eXosip.j_transactions, transaction, 0);
1066                                eXosip_send_default_answer(jd, transaction, evt, 491, NULL,
1067                                                                                   NULL, __LINE__);
1068                                return;
1069                        }
1070
1071                        /* osip_dialog_update_osip_cseq_as_uas (jd->d_dialog, evt->sip); */
1072                        osip_dialog_update_route_set_as_uas(jd->d_dialog, evt->sip);
1073
1074                        eXosip_process_reinvite(jc, jd, transaction, evt);
1075                } else if (MSG_IS_BYE(evt->sip)) {
1076                        osip_generic_param_t *tag_to = NULL;
1077                        if (evt->sip->to != NULL)
1078                                osip_from_param_get_byname(evt->sip->to, "tag", &tag_to);
1079                        if (tag_to == NULL || tag_to->gvalue == NULL) {
1080                                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL,
1081                                                                          "Uncompliant user agent: missing a tag in To of incoming BYE\n"));
1082                                osip_list_add(&eXosip.j_transactions, transaction, 0);
1083                                eXosip_send_default_answer(jd, transaction, evt, 481,
1084                                                                                   "Missing tags in BYE",
1085                                                                                   "Missing tags in BYE", __LINE__);
1086                                return;
1087                        }
1088
1089                        old_trn = eXosip_find_last_inc_transaction(jc, jd, "BYE");
1090
1091                        if (old_trn != NULL) {  /* && old_trn->state!=NIST_TERMINATED) *//* this situation should NEVER occur?? (we can't receive
1092                                                                           two different BYE for one call! */
1093                                osip_list_add(&eXosip.j_transactions, transaction, 0);
1094                                eXosip_send_default_answer(jd, transaction, evt, 500,
1095                                                                                   "Call Already Terminated",
1096                                                                                   "A pending BYE has already terminate this call",
1097                                                                                   __LINE__);
1098                                return;
1099                        }
1100                        /* osip_transaction_free(old_trn); */
1101                        eXosip_process_bye(jc, jd, transaction, evt);
1102                } else if (MSG_IS_ACK(evt->sip)) {
1103                        eXosip_process_ack(jc, jd, evt);
1104                } else {
1105                        eXosip_process_message_within_dialog(jc, jd, transaction, evt);
1106                }
1107                return;
1108        }
1109
1110        if (MSG_IS_ACK(evt->sip)) {
1111                /* no transaction has been found for this ACK! */
1112                osip_event_free(evt);
1113                return;
1114        }
1115
1116        if (MSG_IS_INFO(evt->sip)) {
1117                osip_list_add(&eXosip.j_transactions, transaction, 0);
1118                eXosip_send_default_answer(jd, transaction, evt, 481, NULL, NULL,
1119                                                                   __LINE__);
1120                return;                                 /* fixed */
1121        }
1122        if (MSG_IS_INVITE(evt->sip)) {
1123                eXosip_process_new_invite(transaction, evt);
1124                return;
1125        } else if (MSG_IS_BYE(evt->sip)) {
1126                osip_list_add(&eXosip.j_transactions, transaction, 0);
1127                eXosip_send_default_answer(jd, transaction, evt, 481, NULL, NULL,
1128                                                                   __LINE__);
1129                return;
1130        }
1131#ifndef MINISIZE
1132        js = NULL;
1133        /* first, look for a Dialog in the map of element */
1134        for (js = eXosip.j_subscribes; js != NULL; js = js->next) {
1135                for (jd = js->s_dialogs; jd != NULL; jd = jd->next) {
1136                        if (jd->d_dialog != NULL) {
1137                                if (osip_dialog_match_as_uas(jd->d_dialog, evt->sip) == 0)
1138                                        break;
1139                        }
1140                }
1141                if (jd != NULL)
1142                        break;
1143        }
1144
1145        if (js != NULL) {
1146                /* dialog found */
1147                osip_transaction_t *old_trn;
1148
1149                /* it can be:
1150                   1: a new INVITE offer.
1151                   2: a REFER request from one of the party.
1152                   2: a BYE request from one of the party.
1153                   3: a REQUEST with a wrong CSeq.
1154                   4: a NOT-SUPPORTED method with a wrong CSeq.
1155                 */
1156                if (MSG_IS_MESSAGE(evt->sip)) {
1157                        /* eXosip_process_imessage_within_subscribe_dialog(transaction, evt); */
1158                        osip_list_add(&eXosip.j_transactions, transaction, 0);
1159                        eXosip_send_default_answer(jd, transaction, evt,
1160                                                                           SIP_NOT_IMPLEMENTED, NULL,
1161                                                                           "MESSAGEs within dialogs are not implemented.",
1162                                                                           __LINE__);
1163                        return;
1164                } else if (MSG_IS_NOTIFY(evt->sip)) {
1165                        /* the previous transaction MUST be freed */
1166                        old_trn = eXosip_find_last_inc_notify(js, jd);
1167
1168                        /* shouldn't we wait for the COMPLETED state? */
1169                        if (old_trn != NULL && old_trn->state != NIST_TERMINATED) {
1170                                /* retry later? */
1171                                osip_list_add(&eXosip.j_transactions, transaction, 0);
1172                                eXosip_send_default_answer(jd, transaction, evt, 500,
1173                                                                                   "Retry Later",
1174                                                                                   "A pending NOTIFY is not terminated",
1175                                                                                   __LINE__);
1176                                return;
1177                        }
1178
1179                        osip_dialog_update_osip_cseq_as_uas(jd->d_dialog, evt->sip);
1180                        osip_dialog_update_route_set_as_uas(jd->d_dialog, evt->sip);
1181
1182                        eXosip_process_notify_within_dialog(js, jd, transaction, evt);
1183                } else {
1184                        osip_list_add(&eXosip.j_transactions, transaction, 0);
1185                        eXosip_send_default_answer(jd, transaction, evt, 501, NULL,
1186                                                                           "Just Not Implemented", __LINE__);
1187                }
1188                return;
1189        }
1190
1191        if (MSG_IS_NOTIFY(evt->sip)) {
1192                /* let's try to check if the NOTIFY is related to an existing
1193                   subscribe */
1194                js = NULL;
1195                /* first, look for a Dialog in the map of element */
1196                for (js = eXosip.j_subscribes; js != NULL; js = js->next) {
1197                        if (eXosip_match_notify_for_subscribe(js, evt->sip) == 0) {
1198                                i = eXosip_dialog_init_as_uac(&jd, evt->sip);
1199                                if (i != 0) {
1200                                        OSIP_TRACE(osip_trace
1201                                                           (__FILE__, __LINE__, OSIP_ERROR, NULL,
1202                                                                "eXosip: cannot establish a dialog\n"));
1203                                        return;
1204                                }
1205
1206                                /* update local cseq from subscribe request */
1207                                if (js->s_out_tr != NULL && js->s_out_tr->cseq != NULL
1208                                        && js->s_out_tr->cseq->number != NULL) {
1209                                        jd->d_dialog->local_cseq = atoi(js->s_out_tr->cseq->number);
1210                                        OSIP_TRACE(osip_trace
1211                                                           (__FILE__, __LINE__, OSIP_INFO2, NULL,
1212                                                                "eXosip: local cseq has been updated\n"));
1213                                }
1214
1215                                ADD_ELEMENT(js->s_dialogs, jd);
1216                                eXosip_update();
1217
1218                                eXosip_process_notify_within_dialog(js, jd, transaction, evt);
1219                                return;
1220                        }
1221                }
1222
1223                osip_list_add(&eXosip.j_transactions, transaction, 0);
1224                return;
1225        }
1226
1227        jn = NULL;
1228        /* first, look for a Dialog in the map of element */
1229        for (jn = eXosip.j_notifies; jn != NULL; jn = jn->next) {
1230                for (jd = jn->n_dialogs; jd != NULL; jd = jd->next) {
1231                        if (jd->d_dialog != NULL) {
1232                                if (osip_dialog_match_as_uas(jd->d_dialog, evt->sip) == 0)
1233                                        break;
1234                        }
1235                }
1236                if (jd != NULL)
1237                        break;
1238        }
1239
1240        if (jn != NULL) {
1241                /* dialog found */
1242                osip_transaction_t *old_trn;
1243
1244                /* it can be:
1245                   1: a new INVITE offer.
1246                   2: a REFER request from one of the party.
1247                   2: a BYE request from one of the party.
1248                   3: a REQUEST with a wrong CSeq.
1249                   4: a NOT-SUPPORTED method with a wrong CSeq.
1250                 */
1251                if (MSG_IS_MESSAGE(evt->sip)) {
1252                        osip_list_add(&eXosip.j_transactions, transaction, 0);
1253                        eXosip_send_default_answer(jd, transaction, evt,
1254                                                                           SIP_NOT_IMPLEMENTED, NULL,
1255                                                                           "MESSAGEs within dialogs are not implemented.",
1256                                                                           __LINE__);
1257                        return;
1258                } else if (MSG_IS_SUBSCRIBE(evt->sip)) {
1259                        /* the previous transaction MUST be freed */
1260                        old_trn = eXosip_find_last_inc_subscribe(jn, jd);
1261
1262                        /* shouldn't we wait for the COMPLETED state? */
1263                        if (old_trn != NULL && old_trn->state != NIST_TERMINATED
1264                                && old_trn->state != NIST_COMPLETED) {
1265                                /* retry later? */
1266                                osip_list_add(&eXosip.j_transactions, transaction, 0);
1267                                eXosip_send_default_answer(jd, transaction, evt, 500,
1268                                                                                   "Retry Later",
1269                                                                                   "A SUBSCRIBE is not terminated",
1270                                                                                   __LINE__);
1271                                return;
1272                        }
1273
1274                        osip_dialog_update_osip_cseq_as_uas(jd->d_dialog, evt->sip);
1275                        osip_dialog_update_route_set_as_uas(jd->d_dialog, evt->sip);
1276
1277                        eXosip_process_subscribe_within_call(jn, jd, transaction, evt);
1278                } else {
1279                        osip_list_add(&eXosip.j_transactions, transaction, 0);
1280                        eXosip_send_default_answer(jd, transaction, evt, 501, NULL, NULL,
1281                                                                           __LINE__);
1282                }
1283                return;
1284        }
1285#endif
1286
1287#ifndef MINISIZE
1288        if (MSG_IS_SUBSCRIBE(evt->sip)) {
1289                eXosip_process_new_subscribe(transaction, evt);
1290                return;
1291        }
1292#endif
1293
1294        /* default answer */
1295        osip_list_add(&eXosip.j_transactions, transaction, 0);
1296        __eXosip_wakeup();                      /* needed? */
1297}
1298
1299static void eXosip_process_response_out_of_transaction(osip_event_t * evt)
1300{
1301        eXosip_call_t *jc = NULL;
1302        eXosip_dialog_t *jd = NULL;
1303        time_t now;
1304
1305        now = time(NULL);
1306        if (evt->sip == NULL
1307                || evt->sip->sip_method == NULL
1308                || evt->sip->cseq == NULL
1309                || evt->sip->cseq->number == NULL
1310                || evt->sip->to == NULL || evt->sip->from == NULL) {
1311                osip_event_free(evt);
1312                return;
1313        }
1314
1315        if (!MSG_IS_RESPONSE_FOR(evt->sip, "INVITE"))
1316        {
1317                osip_event_free(evt);
1318                return;
1319        }
1320
1321        /* search for existing dialog: match branch & to tag */
1322        for (jc = eXosip.j_calls; jc != NULL; jc = jc->next) {
1323                /* search for calls with only ONE outgoing transaction */
1324                if (jc->c_id >= 1 && jc->c_dialogs != NULL && jc->c_out_tr != NULL) {
1325                        for (jd = jc->c_dialogs; jd != NULL; jd = jd->next) {
1326                                /* only initial request are concerned with this */
1327                                if (jd->d_id >= 1 && jd->d_dialog != NULL) {
1328                                        /* match answer with dialog */
1329                                        osip_generic_param_t *tag;
1330
1331                                        osip_from_get_tag(evt->sip->to, &tag);
1332
1333                                        if (jd->d_dialog->remote_tag == NULL || tag == NULL)
1334                                                continue;
1335                                        if (jd->d_dialog->remote_tag != NULL && tag != NULL
1336                                                && tag->gvalue != NULL
1337                                                && 0 == strcmp(jd->d_dialog->remote_tag, tag->gvalue))
1338                                                break;
1339                                }
1340                        }
1341                        if (jd != NULL)
1342                                break;                  /* found a matching dialog! */
1343
1344                        /* check if the transaction match this from tag */
1345                        if (jc->c_out_tr->orig_request != NULL
1346                                && jc->c_out_tr->orig_request->from != NULL) {
1347                                osip_generic_param_t *tag_invite;
1348                                osip_generic_param_t *tag;
1349                                osip_from_get_tag(jc->c_out_tr->orig_request->from, &tag_invite);
1350                                osip_from_get_tag(evt->sip->from, &tag);
1351
1352                                if (tag_invite == NULL || tag == NULL)
1353                                        continue;
1354                                if (tag_invite->gvalue != NULL && tag->gvalue != NULL
1355                                        && 0 == strcmp(tag_invite->gvalue, tag->gvalue))
1356                                        break;
1357                        }
1358                }
1359        }
1360
1361        if (jc == NULL) {
1362                OSIP_TRACE(osip_trace
1363                                   (__FILE__, __LINE__, OSIP_INFO1, NULL,
1364                                        "Incoming 2xx has no relations with current calls: Message discarded.\r\n"));
1365                osip_event_free(evt);
1366                return;
1367        }
1368#ifndef MINISIZE
1369        if (jc != NULL && jd != NULL) {
1370                /* we have to restransmit the ACK (if already available) */
1371                OSIP_TRACE(osip_trace
1372                                   (__FILE__, __LINE__, OSIP_INFO1, NULL,
1373                                        "2xx restransmission receveid.\r\n"));
1374                /* check if the 2xx is for the same ACK */
1375                if (jd->d_ack != NULL && jd->d_ack->cseq != NULL
1376                        && jd->d_ack->cseq->number != NULL) {
1377                        if (0 ==
1378                                osip_strcasecmp(jd->d_ack->cseq->number, evt->sip->cseq->number)) {
1379                                cb_snd_message(NULL, jd->d_ack, NULL, 0, -1);
1380                                OSIP_TRACE(osip_trace
1381                                                   (__FILE__, __LINE__, OSIP_INFO1, NULL,
1382                                                        "ACK restransmission sent.\r\n"));
1383                        }
1384                }
1385
1386                osip_event_free(evt);
1387                return;
1388        }
1389#endif
1390
1391        if (jc != NULL) {
1392                /* match answer with dialog */
1393                osip_dialog_t *dlg;
1394#ifndef MINISIZE
1395                osip_transaction_t *last_tr;
1396#endif
1397                int i;
1398
1399                /* we match an existing dialog: send a retransmission of ACK */
1400                i = osip_dialog_init_as_uac(&dlg, evt->sip);
1401                if (i != 0 || dlg == NULL) {
1402                        OSIP_TRACE(osip_trace
1403                                           (__FILE__, __LINE__, OSIP_ERROR, NULL,
1404                                                "Cannot build dialog for 200ok.\r\n"));
1405                        osip_event_free(evt);
1406                        return;
1407                }
1408
1409                OSIP_TRACE(osip_trace
1410                                   (__FILE__, __LINE__, OSIP_INFO1, NULL,
1411                                        "sending ACK for 2xx out of transaction.\r\n"));
1412
1413                {
1414                        osip_message_t *bye = NULL;
1415                        char *transport = _eXosip_transport_protocol(evt->sip);
1416#ifndef MINISIZE                                /* Don't send ACK in MINISIZE mode to save code size */
1417                        osip_message_t *ack;
1418                        if (transport == NULL)
1419                                i = _eXosip_build_request_within_dialog(&ack, "ACK", dlg, "UDP");
1420                        else
1421                                i = _eXosip_build_request_within_dialog(&ack, "ACK", dlg,
1422                                                                                                                transport);
1423                        if (i != 0) {
1424                                osip_dialog_free(dlg);
1425                                osip_event_free(evt);
1426                                return;
1427                        }
1428                        /* copy all credentials from INVITE! */
1429                        last_tr = jc->c_out_tr;
1430                        if (last_tr != NULL) {
1431                                int pos = 0;
1432                                int i;
1433                                osip_proxy_authorization_t *pa = NULL;
1434
1435                                i = osip_message_get_proxy_authorization(last_tr->orig_request,
1436                                                                                                                 pos, &pa);
1437                                while (i >= 0 && pa != NULL) {
1438                                        osip_proxy_authorization_t *pa2;
1439
1440                                        i = osip_proxy_authorization_clone(pa, &pa2);
1441                                        if (i != 0) {
1442                                                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL,
1443                                                                                          "Error in credential from INVITE\n"));
1444                                                break;
1445                                        }
1446                                        osip_list_add(&ack->proxy_authorizations, pa2, -1);
1447                                        pa = NULL;
1448                                        pos++;
1449                                        i = osip_message_get_proxy_authorization(last_tr->orig_request,
1450                                                                                                                         pos, &pa);
1451                                }
1452                        }
1453                        cb_snd_message(NULL, ack, NULL, 0, -1);
1454                        osip_message_free(ack);
1455#endif
1456                        /* in some case, PRACK and UPDATE may have been sent
1457                           so we have to send a cseq which is above the previous
1458                           one. */
1459                        dlg->local_cseq = dlg->local_cseq + 4;
1460
1461                        /* ready to send a BYE */
1462                        if (transport == NULL)
1463                                i = generating_bye(&bye, dlg, "UDP");
1464                        else
1465                                i = generating_bye(&bye, dlg, transport);
1466                        if (bye != NULL && i == OSIP_SUCCESS)
1467                                cb_snd_message(NULL, bye, NULL, 0, -1);
1468                        osip_message_free(bye);
1469                }
1470
1471                osip_dialog_free(dlg);
1472                osip_event_free(evt);
1473                return;
1474        }
1475
1476}
1477
1478int
1479_eXosip_handle_incoming_message(char *buf, size_t length, int socket,
1480                                                                char *host, int port)
1481{
1482        int i;
1483        osip_event_t *se;
1484
1485        se = (osip_event_t *) osip_malloc(sizeof(osip_event_t));
1486        if (se == NULL)
1487                return OSIP_NOMEM;
1488        se->type = UNKNOWN_EVT;
1489        se->sip = NULL;
1490        se->transactionid = 0;
1491
1492        /* parse message and set up an event */
1493        i = osip_message_init(&(se->sip));
1494        if (i != 0) {
1495                osip_free(se);
1496                return i;
1497        }
1498        i = osip_message_parse(se->sip, buf, length);
1499        if (i != 0) {
1500                OSIP_TRACE(osip_trace
1501                                   (__FILE__, __LINE__, OSIP_ERROR, NULL,
1502                                        "could not parse message\n"));
1503                osip_message_free(se->sip);
1504                osip_free(se);
1505                return i;
1506        }
1507
1508        if (se->sip->call_id != NULL && se->sip->call_id->number != NULL) {
1509                OSIP_TRACE(osip_trace
1510                                   (__FILE__, __LINE__, OSIP_INFO3, NULL,
1511                                        "MESSAGE REC. CALLID:%s\n", se->sip->call_id->number));
1512        }
1513
1514        if (eXosip.cbsipCallback != NULL) {
1515                eXosip.cbsipCallback(se->sip, 1);
1516        }
1517
1518        if (MSG_IS_REQUEST(se->sip)) {
1519                if (se->sip->sip_method == NULL || se->sip->req_uri == NULL) {
1520                        osip_message_free(se->sip);
1521                        osip_free(se);
1522                        return OSIP_SYNTAXERROR;
1523                }
1524        }
1525
1526        if (MSG_IS_REQUEST(se->sip)) {
1527                if (MSG_IS_INVITE(se->sip))
1528                        se->type = RCV_REQINVITE;
1529                else if (MSG_IS_ACK(se->sip))
1530                        se->type = RCV_REQACK;
1531                else
1532                        se->type = RCV_REQUEST;
1533        } else {
1534                if (MSG_IS_STATUS_1XX(se->sip))
1535                        se->type = RCV_STATUS_1XX;
1536                else if (MSG_IS_STATUS_2XX(se->sip))
1537                        se->type = RCV_STATUS_2XX;
1538                else
1539                        se->type = RCV_STATUS_3456XX;
1540        }
1541
1542        OSIP_TRACE(osip_trace
1543                           (__FILE__, __LINE__, OSIP_INFO1, NULL,
1544                                "Message received from: %s:%i\n", host, port));
1545
1546        osip_message_fix_last_via_header(se->sip, host, port);
1547
1548
1549        i = osip_find_transaction_and_add_event(eXosip.j_osip, se);
1550        if (i != 0) {
1551                /* this event has no transaction, */
1552                OSIP_TRACE(osip_trace
1553                                   (__FILE__, __LINE__, OSIP_INFO1, NULL,
1554                                        "This is a request\n", buf));
1555                eXosip_lock();
1556                if (MSG_IS_REQUEST(se->sip))
1557                        eXosip_process_newrequest(se, socket);
1558                else if (MSG_IS_RESPONSE(se->sip))
1559                        eXosip_process_response_out_of_transaction(se);
1560                eXosip_unlock();
1561        } else {
1562                /* handled by oSIP ! */
1563                return OSIP_SUCCESS;
1564        }
1565        return OSIP_SUCCESS;
1566}
1567
1568#if defined (WIN32) || defined (_WIN32_WCE)
1569#define eXFD_SET(A, B)   FD_SET((unsigned int) A, B)
1570#else
1571#define eXFD_SET(A, B)   FD_SET(A, B)
1572#endif
1573
1574/* if second==-1 && useconds==-1  -> wait for ever
1575   if max_message_nb<=0  -> infinite loop....  */
1576int eXosip_read_message(int max_message_nb, int sec_max, int usec_max)
1577{
1578        fd_set osip_fdset;
1579        struct timeval tv;
1580
1581        tv.tv_sec = sec_max;
1582        tv.tv_usec = usec_max;
1583
1584        while (max_message_nb != 0 && eXosip.j_stop_ua == 0) {
1585                int i;
1586                int max = 0;
1587#ifdef OSIP_MT
1588                int wakeup_socket = jpipe_get_read_descr(eXosip.j_socketctl);
1589#endif
1590
1591                FD_ZERO(&osip_fdset);
1592                eXtl_udp.tl_set_fdset(&osip_fdset, &max);
1593                eXtl_tcp.tl_set_fdset(&osip_fdset, &max);
1594#ifdef HAVE_OPENSSL_SSL_H
1595#if !(OPENSSL_VERSION_NUMBER < 0x00908000L)
1596                eXtl_dtls.tl_set_fdset(&osip_fdset, &max);
1597#endif
1598                eXtl_tls.tl_set_fdset(&osip_fdset, &max);
1599#endif
1600
1601
1602#ifdef OSIP_MT
1603                eXFD_SET(wakeup_socket, &osip_fdset);
1604                if (wakeup_socket > max)
1605                        max = wakeup_socket;
1606#endif
1607
1608                if ((sec_max == -1) || (usec_max == -1))
1609                        i = select(max + 1, &osip_fdset, NULL, NULL, NULL);
1610                else
1611                        i = select(max + 1, &osip_fdset, NULL, NULL, &tv);
1612
1613#if defined (_WIN32_WCE)
1614                /* TODO: fix me for wince */
1615                /* if (i == -1)
1616                   continue; */
1617#else
1618                if ((i == -1) && (errno == EINTR || errno == EAGAIN))
1619                        continue;
1620#endif
1621#ifdef OSIP_MT
1622                if ((i > 0) && FD_ISSET(wakeup_socket, &osip_fdset)) {
1623                        char buf2[500];
1624
1625                        jpipe_read(eXosip.j_socketctl, buf2, 499);
1626                }
1627#endif
1628
1629                if (0 == i || eXosip.j_stop_ua != 0) {
1630                } else if (-1 == i) {
1631#if !defined (_WIN32_WCE)               /* TODO: fix me for wince */
1632                        return -2000;           /* error */
1633#endif
1634                } else {
1635                        eXtl_udp.tl_read_message(&osip_fdset);
1636                        eXtl_tcp.tl_read_message(&osip_fdset);
1637#ifdef HAVE_OPENSSL_SSL_H
1638#if !(OPENSSL_VERSION_NUMBER < 0x00908000L)
1639                        eXtl_dtls.tl_read_message(&osip_fdset);
1640#endif
1641                        eXtl_tls.tl_read_message(&osip_fdset);
1642#endif
1643
1644                }
1645
1646                max_message_nb--;
1647        }
1648        return OSIP_SUCCESS;
1649}
1650
1651static int
1652eXosip_pendingosip_transaction_exist(eXosip_call_t * jc, eXosip_dialog_t * jd)
1653{
1654        osip_transaction_t *tr;
1655        time_t now = time(NULL);
1656
1657        tr = eXosip_find_last_inc_transaction(jc, jd, "BYE");
1658        if (tr != NULL && tr->state != NIST_TERMINATED) {       /* Don't want to wait forever on broken transaction!! */
1659                if (tr->birth_time + 180 < now) {       /* Wait a max of 2 minutes */
1660                        /* remove the transaction from oSIP: */
1661                        osip_remove_transaction(eXosip.j_osip, tr);
1662                        eXosip_remove_transaction_from_call(tr, jc);
1663                        osip_list_add(&eXosip.j_transactions, tr, 0);
1664                } else
1665                        return OSIP_SUCCESS;
1666        }
1667
1668        tr = eXosip_find_last_out_transaction(jc, jd, "BYE");
1669        if (tr != NULL && tr->state != NICT_TERMINATED) {       /* Don't want to wait forever on broken transaction!! */
1670                if (tr->birth_time + 180 < now) {       /* Wait a max of 2 minutes */
1671                        /* remove the transaction from oSIP: */
1672                        osip_remove_transaction(eXosip.j_osip, tr);
1673                        eXosip_remove_transaction_from_call(tr, jc);
1674                        osip_list_add(&eXosip.j_transactions, tr, 0);
1675                } else
1676                        return OSIP_SUCCESS;
1677        }
1678
1679        tr = eXosip_find_last_inc_invite(jc, jd);
1680        if (tr != NULL && tr->state != IST_TERMINATED) {        /* Don't want to wait forever on broken transaction!! */
1681                if (tr->birth_time + 180 < now) {       /* Wait a max of 2 minutes */
1682                        /* remove the transaction from oSIP: */
1683                        /* osip_remove_transaction(eXosip.j_osip, tr);
1684                           eXosip_remove_transaction_from_call(tr, jc);
1685                           osip_transaction_free(tr); */
1686                } else
1687                        return OSIP_SUCCESS;
1688        }
1689
1690        tr = eXosip_find_last_out_invite(jc, jd);
1691        if (tr != NULL && tr->state != ICT_TERMINATED) {        /* Don't want to wait forever on broken transaction!! */
1692                if (jc->expire_time < now) {
1693                        /* remove the transaction from oSIP: */
1694                        /* osip_remove_transaction(eXosip.j_osip, tr);
1695                           eXosip_remove_transaction_from_call(tr, jc);
1696                           osip_transaction_free(tr); */
1697                } else
1698                        return OSIP_SUCCESS;
1699        }
1700
1701        tr = eXosip_find_last_inc_transaction(jc, jd, "REFER");
1702        if (tr != NULL && tr->state != NIST_TERMINATED) {       /* Don't want to wait forever on broken transaction!! */
1703                if (tr->birth_time + 180 < now) {       /* Wait a max of 2 minutes */
1704                        /* remove the transaction from oSIP: */
1705                        osip_remove_transaction(eXosip.j_osip, tr);
1706                        eXosip_remove_transaction_from_call(tr, jc);
1707                        osip_list_add(&eXosip.j_transactions, tr, 0);
1708                } else
1709                        return OSIP_SUCCESS;
1710        }
1711
1712        tr = eXosip_find_last_out_transaction(jc, jd, "REFER");
1713        if (tr != NULL && tr->state != NICT_TERMINATED) {       /* Don't want to wait forever on broken transaction!! */
1714                if (tr->birth_time + 180 < now) {       /* Wait a max of 2 minutes */
1715                        /* remove the transaction from oSIP: */
1716                        osip_remove_transaction(eXosip.j_osip, tr);
1717                        eXosip_remove_transaction_from_call(tr, jc);
1718                        osip_list_add(&eXosip.j_transactions, tr, 0);
1719                } else
1720                        return OSIP_SUCCESS;
1721        }
1722
1723        return OSIP_UNDEFINED_ERROR;
1724}
1725
1726static int
1727eXosip_release_finished_transactions(eXosip_call_t * jc, eXosip_dialog_t * jd)
1728{
1729        time_t now = time(NULL);
1730        osip_transaction_t *inc_tr;
1731        osip_transaction_t *out_tr;
1732        osip_transaction_t *last_invite;
1733        int pos;
1734        int ret;
1735
1736        ret = -1;
1737
1738        last_invite = eXosip_find_last_inc_invite(jc, jd);
1739
1740        if (jd != NULL) {
1741                /* go through all incoming transactions of this dialog */
1742                pos = 1;
1743                while (!osip_list_eol(jd->d_inc_trs, pos)) {
1744                        inc_tr = osip_list_get(jd->d_inc_trs, pos);
1745                        if (0 != osip_strcasecmp(inc_tr->cseq->method, "INVITE")) {
1746                                /* remove, if transaction too old, independent of the state */
1747                                if ((inc_tr->state == NIST_TERMINATED) && (inc_tr->birth_time + 30 < now)) {    /* Wait a max of 30 seconds */
1748                                        /* remove the transaction from oSIP */
1749                                        OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL,
1750                                                                                  "eXosip: release non-INVITE server transaction (did=%i)\n",
1751                                                                                  jd->d_id));
1752                                        osip_remove_transaction(eXosip.j_osip, inc_tr);
1753                                        osip_list_remove(jd->d_inc_trs, pos);
1754                                        osip_list_add(&eXosip.j_transactions, inc_tr, 0);
1755
1756                                        ret = 0;
1757                                        break;
1758                                }
1759                        } else {
1760                                /* remove, if transaction too old, independent of the state */
1761                                if (last_invite != inc_tr && (inc_tr->state == IST_TERMINATED) && (inc_tr->birth_time + 30 < now)) {    /* Wait a max of 30 seconds */
1762                                        /* remove the transaction from oSIP */
1763                                        OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL,
1764                                                                                  "eXosip: release INVITE server transaction (did=%i)\n",
1765                                                                                  jd->d_id));
1766                                        osip_remove_transaction(eXosip.j_osip, inc_tr);
1767                                        osip_list_remove(jd->d_inc_trs, pos);
1768                                        osip_list_add(&eXosip.j_transactions, inc_tr, 0);
1769
1770                                        ret = 0;
1771                                        break;
1772                                }
1773                        }
1774                        pos++;
1775                }
1776
1777                last_invite = eXosip_find_last_out_invite(jc, jd);
1778
1779                /* go through all outgoing transactions of this dialog */
1780                pos = 1;
1781                while (!osip_list_eol(jd->d_out_trs, pos)) {
1782                        out_tr = osip_list_get(jd->d_out_trs, pos);
1783                        if (0 != osip_strcasecmp(out_tr->cseq->method, "INVITE")) {
1784                                /* remove, if transaction too old, independent of the state */
1785                                if ((out_tr->state == NICT_TERMINATED) && (out_tr->birth_time + 30 < now)) {    /* Wait a max of 30 seconds */
1786                                        /* remove the transaction from oSIP */
1787                                        OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL,
1788                                                                                  "eXosip: release non INVITE client transaction (did=%i)\n",
1789                                                                                  jd->d_id));
1790                                        osip_remove_transaction(eXosip.j_osip, out_tr);
1791                                        osip_list_remove(jd->d_out_trs, pos);
1792                                        osip_list_add(&eXosip.j_transactions, out_tr, 0);
1793
1794                                        ret = 0;
1795                                        break;
1796                                }
1797                        } else {
1798                                /* remove, if transaction too old, independent of the state */
1799                                if (last_invite != out_tr && (out_tr->state == ICT_TERMINATED) && (out_tr->birth_time + 30 < now)) {    /* Wait a max of 30 seconds */
1800                                        /* remove the transaction from oSIP */
1801                                        OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL,
1802                                                                                  "eXosip: release INVITE client transaction (did=%i)\n",
1803                                                                                  jd->d_id));
1804                                        osip_remove_transaction(eXosip.j_osip, out_tr);
1805                                        osip_list_remove(jd->d_out_trs, pos);
1806                                        osip_list_add(&eXosip.j_transactions, out_tr, 0);
1807
1808                                        ret = 0;
1809                                        break;
1810                                }
1811                        }
1812                        pos++;
1813                }
1814        }
1815
1816        return ret;
1817}
1818
1819static int eXosip_release_finished_calls(eXosip_call_t * jc, eXosip_dialog_t * jd)
1820{
1821        osip_transaction_t *tr;
1822
1823        tr = eXosip_find_last_inc_transaction(jc, jd, "BYE");
1824        if (tr == NULL)
1825                tr = eXosip_find_last_out_transaction(jc, jd, "BYE");
1826
1827        if (tr != NULL
1828                && (tr->state == NIST_TERMINATED || tr->state == NICT_TERMINATED)) {
1829                int did = -2;
1830
1831                if (jd != NULL)
1832                        did = jd->d_id;
1833                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL,
1834                                                          "eXosip: eXosip_release_finished_calls remove a dialog (cid=%i did=%i)\n",
1835                                                          jc->c_id, did));
1836                /* Remove existing reference to the dialog from transactions! */
1837                __eXosip_call_remove_dialog_reference_in_call(jc, jd);
1838                REMOVE_ELEMENT(jc->c_dialogs, jd);
1839                eXosip_dialog_free(jd);
1840                return OSIP_SUCCESS;
1841        }
1842        return OSIP_UNDEFINED_ERROR;
1843}
1844
1845
1846
1847static void __eXosip_release_call(eXosip_call_t * jc, eXosip_dialog_t * jd)
1848{
1849        REMOVE_ELEMENT(eXosip.j_calls, jc);
1850        report_call_event(EXOSIP_CALL_RELEASED, jc, jd, NULL);
1851        eXosip_call_free(jc);
1852        __eXosip_wakeup();
1853}
1854
1855
1856static int eXosip_release_aborted_calls(eXosip_call_t * jc, eXosip_dialog_t * jd)
1857{
1858        time_t now = time(NULL);
1859        osip_transaction_t *tr;
1860
1861#if 0
1862        tr = eXosip_find_last_inc_invite(jc, jd);
1863        if (tr == NULL)
1864                tr = eXosip_find_last_out_invite(jc, jd);
1865#else
1866        /* close calls only when the initial INVITE failed */
1867        tr = jc->c_inc_tr;
1868        if (tr == NULL)
1869                tr = jc->c_out_tr;
1870#endif
1871
1872        if (tr == NULL) {
1873                if (jd != NULL) {
1874                        OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL,
1875                                                                  "eXosip: eXosip_release_aborted_calls remove an empty dialog\n"));
1876                        __eXosip_call_remove_dialog_reference_in_call(jc, jd);
1877                        REMOVE_ELEMENT(jc->c_dialogs, jd);
1878                        eXosip_dialog_free(jd);
1879                        return OSIP_SUCCESS;
1880                }
1881                return OSIP_UNDEFINED_ERROR;
1882        }
1883
1884        if (tr != NULL && tr->state != IST_TERMINATED && tr->state != ICT_TERMINATED && tr->birth_time + 180 < now) {   /* Wait a max of 2 minutes */
1885                if (jd != NULL) {
1886                        OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL,
1887                                                                  "eXosip: eXosip_release_aborted_calls remove a dialog for an unfinished transaction\n"));
1888                        __eXosip_call_remove_dialog_reference_in_call(jc, jd);
1889                        REMOVE_ELEMENT(jc->c_dialogs, jd);
1890                        report_call_event(EXOSIP_CALL_NOANSWER, jc, jd, NULL);
1891                        eXosip_dialog_free(jd);
1892                        __eXosip_wakeup();
1893                        return OSIP_SUCCESS;
1894                }
1895        }
1896
1897        if (tr != NULL && (tr->state == IST_TERMINATED || tr->state == ICT_TERMINATED)) {
1898                if (tr == jc->c_inc_tr) {
1899                        if (jc->c_inc_tr->last_response == NULL) {
1900                                /* OSIP_TRACE(osip_trace(__FILE__,__LINE__,OSIP_INFO2,NULL,
1901                                   "eXosip: eXosip_release_aborted_calls transaction with no answer\n")); */
1902                        }
1903#ifndef MINISIZE
1904                        else if (MSG_IS_STATUS_3XX(jc->c_inc_tr->last_response)) {
1905                                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL,
1906                                                                          "eXosip: eXosip_release_aborted_calls answered with a 3xx\n"));
1907                                __eXosip_release_call(jc, jd);
1908                                return OSIP_SUCCESS;
1909                        } else if (MSG_IS_STATUS_4XX(jc->c_inc_tr->last_response)) {
1910                                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL,
1911                                                                          "eXosip: eXosip_release_aborted_calls answered with a 4xx\n"));
1912                                __eXosip_release_call(jc, jd);
1913                                return OSIP_SUCCESS;
1914                        } else if (MSG_IS_STATUS_5XX(jc->c_inc_tr->last_response)) {
1915                                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL,
1916                                                                          "eXosip: eXosip_release_aborted_calls answered with a 5xx\n"));
1917                                __eXosip_release_call(jc, jd);
1918                                return OSIP_SUCCESS;
1919                        } else if (MSG_IS_STATUS_6XX(jc->c_inc_tr->last_response)) {
1920                                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL,
1921                                                                          "eXosip: eXosip_release_aborted_calls answered with a 6xx\n"));
1922                                __eXosip_release_call(jc, jd);
1923                                return OSIP_SUCCESS;
1924                        }
1925#else
1926                        else if (jc->c_inc_tr->last_response->status_code >= 300) {
1927                                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL,
1928                                                                          "eXosip: eXosip_release_aborted_calls answered with a answer above 3xx\n"));
1929                                __eXosip_release_call(jc, jd);
1930                                return OSIP_SUCCESS;
1931                        }
1932#endif
1933                } else if (tr == jc->c_out_tr) {
1934                        if (jc->c_out_tr->last_response == NULL) {
1935                                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL,
1936                                                                          "eXosip: eXosip_release_aborted_calls completed with no answer\n"));
1937                                __eXosip_release_call(jc, jd);
1938                                return OSIP_SUCCESS;
1939                        }
1940#ifndef MINISIZE
1941                        else if (MSG_IS_STATUS_3XX(jc->c_out_tr->last_response)) {
1942                                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL,
1943                                                                          "eXosip: eXosip_release_aborted_calls completed answered with 3xx\n"));
1944                                __eXosip_release_call(jc, jd);
1945                                return OSIP_SUCCESS;
1946                        } else if (MSG_IS_STATUS_4XX(jc->c_out_tr->last_response)) {
1947                                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL,
1948                                                                          "eXosip: eXosip_release_aborted_calls completed answered with 4xx\n"));
1949                                __eXosip_release_call(jc, jd);
1950                                return OSIP_SUCCESS;
1951                        } else if (MSG_IS_STATUS_5XX(jc->c_out_tr->last_response)) {
1952                                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL,
1953                                                                          "eXosip: eXosip_release_aborted_calls completed answered with 5xx\n"));
1954                                __eXosip_release_call(jc, jd);
1955                                return OSIP_SUCCESS;
1956                        } else if (MSG_IS_STATUS_6XX(jc->c_out_tr->last_response)) {
1957                                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL,
1958                                                                          "eXosip: eXosip_release_aborted_calls completed answered with 6xx\n"));
1959                                __eXosip_release_call(jc, jd);
1960                                return OSIP_SUCCESS;
1961                        }
1962#else
1963                        else if (jc->c_out_tr->last_response->status_code >= 300) {
1964                                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL,
1965                                                                          "eXosip: eXosip_release_aborted_calls completed answered with 3xx\n"));
1966                                __eXosip_release_call(jc, jd);
1967                                return OSIP_SUCCESS;
1968                        }
1969#endif
1970                }
1971        }
1972
1973        return OSIP_UNDEFINED_ERROR;
1974}
1975
1976
1977void eXosip_release_terminated_calls(void)
1978{
1979        eXosip_dialog_t *jd;
1980        eXosip_dialog_t *jdnext;
1981        eXosip_call_t *jc;
1982        eXosip_call_t *jcnext;
1983        time_t now = time(NULL);
1984        int pos;
1985
1986
1987        for (jc = eXosip.j_calls; jc != NULL;) {
1988                jcnext = jc->next;
1989                /* free call terminated with a BYE */
1990
1991                for (jd = jc->c_dialogs; jd != NULL;) {
1992                        jdnext = jd->next;
1993                        if (0 == eXosip_pendingosip_transaction_exist(jc, jd)) {
1994                        } else if (0 == eXosip_release_finished_transactions(jc, jd)) {
1995                        } else if (0 == eXosip_release_finished_calls(jc, jd)) {
1996                                jd = jc->c_dialogs;
1997                        } else if (0 == eXosip_release_aborted_calls(jc, jd)) {
1998                                jdnext = NULL;
1999                        } else if (jd->d_id == -1) {
2000                                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL,
2001                                                                          "eXosip: eXosip_release_terminated_calls delete a removed dialog (cid=%i did=%i)\n",
2002                                                                          jc->c_id, jd->d_id));
2003                                /* Remove existing reference to the dialog from transactions! */
2004                                __eXosip_call_remove_dialog_reference_in_call(jc, jd);
2005                                REMOVE_ELEMENT(jc->c_dialogs, jd);
2006                                eXosip_dialog_free(jd);
2007
2008                                jd = jc->c_dialogs;
2009                        }
2010                        jd = jdnext;
2011                }
2012                jc = jcnext;
2013        }
2014
2015        for (jc = eXosip.j_calls; jc != NULL;) {
2016                jcnext = jc->next;
2017                if (jc->c_dialogs == NULL) {
2018                        if (jc->c_inc_tr != NULL
2019                                && jc->c_inc_tr->state != IST_TERMINATED
2020                                && jc->c_inc_tr->birth_time + 180 < now) {
2021                                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO1, NULL,
2022                                                                          "eXosip: remove an incoming call with no final answer\n"));
2023                                __eXosip_release_call(jc, NULL);
2024                        } else if (jc->c_out_tr != NULL
2025                                           && jc->c_out_tr->state != ICT_TERMINATED
2026                                           && jc->c_out_tr->birth_time + 180 < now) {
2027                                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO1, NULL,
2028                                                                          "eXosip: remove an outgoing call with no final answer\n"));
2029                                __eXosip_release_call(jc, NULL);
2030                        } else if (jc->c_inc_tr != NULL
2031                                           && jc->c_inc_tr->state != IST_TERMINATED) {
2032                        } else if (jc->c_out_tr != NULL
2033                                           && jc->c_out_tr->state != ICT_TERMINATED) {
2034                        } else if (jc->c_out_tr != NULL
2035                                           && jc->c_out_tr->state == ICT_TERMINATED
2036                                           && jc->c_out_tr->completed_time + 10 > now) {
2037                                /* With unreliable protocol, the transaction enter the terminated
2038                                   state right after the ACK is sent: In this case, we really want
2039                                   to wait for additionnal user/automatic action to be processed
2040                                   before we decide to delete the call.
2041                                 */
2042
2043
2044                        } else {                        /* no active pending transaction */
2045
2046                                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO1, NULL,
2047                                                                          "eXosip: remove a call\n"));
2048                                __eXosip_release_call(jc, NULL);
2049                        }
2050                }
2051                jc = jcnext;
2052        }
2053
2054        pos = 0;
2055        while (!osip_list_eol(&eXosip.j_transactions, pos)) {
2056                osip_transaction_t *tr =
2057                        (osip_transaction_t *) osip_list_get(&eXosip.j_transactions, pos);
2058                if (tr->state == IST_TERMINATED || tr->state == ICT_TERMINATED || tr->state == NICT_TERMINATED || tr->state == NIST_TERMINATED) {       /* free (transaction is already removed from the oSIP stack) */
2059                        OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO3, NULL,
2060                                                                  "Release a terminated transaction\n"));
2061                        osip_list_remove(&eXosip.j_transactions, pos);
2062                        __eXosip_delete_jinfo(tr);
2063                        osip_transaction_free(tr);
2064                } else if (tr->birth_time + 180 < now) {        /* Wait a max of 2 minutes */
2065                        osip_list_remove(&eXosip.j_transactions, pos);
2066                        __eXosip_delete_jinfo(tr);
2067                        osip_transaction_free(tr);
2068                } else
2069                        pos++;
2070        }
2071}
2072
2073void eXosip_release_terminated_registrations(void)
2074{
2075        eXosip_reg_t *jr;
2076        eXosip_reg_t *jrnext;
2077        time_t now = time(NULL);
2078
2079        for (jr = eXosip.j_reg; jr != NULL;) {
2080                jrnext = jr->next;
2081                if (jr->r_reg_period == 0 && jr->r_last_tr != NULL) {
2082                        if (now - jr->r_last_tr->birth_time > 75) {
2083                                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO1, NULL,
2084                                                                          "Release a terminated registration\n"));
2085                                REMOVE_ELEMENT(eXosip.j_reg, jr);
2086                                eXosip_reg_free(jr);
2087                        } else if (jr->r_last_tr->last_response != NULL
2088                                           && jr->r_last_tr->last_response->status_code >= 200
2089                                           && jr->r_last_tr->last_response->status_code <= 299) {
2090                                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO1, NULL,
2091                                                                          "Release a terminated registration with 2xx\n"));
2092                                REMOVE_ELEMENT(eXosip.j_reg, jr);
2093                                eXosip_reg_free(jr);
2094                        }
2095                }
2096
2097                jr = jrnext;
2098        }
2099
2100        return;
2101}
2102
2103void eXosip_release_terminated_publications(void)
2104{
2105        eXosip_pub_t *jpub;
2106        eXosip_pub_t *jpubnext;
2107        time_t now = time(NULL);
2108
2109        for (jpub = eXosip.j_pub; jpub != NULL;) {
2110                jpubnext = jpub->next;
2111                if (jpub->p_period == 0 && jpub->p_last_tr != NULL) {
2112                        if (now - jpub->p_last_tr->birth_time > 75) {
2113                                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO1, NULL,
2114                                                                          "Release a terminated publication\n"));
2115                                REMOVE_ELEMENT(eXosip.j_pub, jpub);
2116                                _eXosip_pub_free(jpub);
2117                        } else if (jpub->p_last_tr->last_response != NULL
2118                                           && jpub->p_last_tr->last_response->status_code >= 200
2119                                           && jpub->p_last_tr->last_response->status_code <= 299) {
2120                                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO1, NULL,
2121                                                                          "Release a terminated publication with 2xx\n"));
2122                                REMOVE_ELEMENT(eXosip.j_pub, jpub);
2123                                _eXosip_pub_free(jpub);
2124                        }
2125                }
2126
2127                jpub = jpubnext;
2128        }
2129
2130}
2131
2132#ifndef MINISIZE
2133
2134static int
2135eXosip_release_finished_transactions_for_subscription(eXosip_dialog_t * jd)
2136{
2137        time_t now = time(NULL);
2138        osip_transaction_t *inc_tr;
2139        osip_transaction_t *out_tr;
2140        int skip_first = 0;
2141        int pos;
2142        int ret;
2143
2144        ret = OSIP_UNDEFINED_ERROR;
2145
2146        if (jd != NULL) {
2147                /* go through all incoming transactions of this dialog */
2148                pos = 0;
2149                while (!osip_list_eol(jd->d_inc_trs, pos)) {
2150                        inc_tr = osip_list_get(jd->d_inc_trs, pos);
2151                        /* remove, if transaction too old, independent of the state */
2152                        if ((skip_first == 1) && (inc_tr->state == NIST_TERMINATED) && (inc_tr->birth_time + 30 < now)) {       /* keep it for 30 seconds */
2153                                /* remove the transaction from oSIP */
2154                                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL,
2155                                                                          "eXosip: releaase non-INVITE server transaction (did=%i)\n",
2156                                                                          jd->d_id));
2157                                osip_remove_transaction(eXosip.j_osip, inc_tr);
2158                                osip_list_remove(jd->d_inc_trs, pos);
2159                                osip_list_add(&eXosip.j_transactions, inc_tr, 0);
2160
2161                                ret = OSIP_SUCCESS;     /* return "released" */
2162                                break;
2163                        }
2164                        if (0 == osip_strcasecmp(inc_tr->cseq->method, "SUBSCRIBE"))
2165                                skip_first = 1;
2166                        if (0 == osip_strcasecmp(inc_tr->cseq->method, "NOTIFY"))
2167                                skip_first = 1;
2168                        pos++;
2169                }
2170
2171                skip_first = 0;
2172
2173                /* go through all outgoing transactions of this dialog */
2174                pos = 0;
2175                while (!osip_list_eol(jd->d_out_trs, pos)) {
2176                        out_tr = osip_list_get(jd->d_out_trs, pos);
2177                        /* remove, if transaction too old, independent of the state */
2178                        if ((skip_first == 1) && (out_tr->state == NICT_TERMINATED) && (out_tr->birth_time + 30 < now)) {       /* Wait a max of 30 seconds */
2179                                /* remove the transaction from oSIP */
2180                                OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL,
2181                                                                          "eXosip: release non INVITE client transaction (did=%i)\n",
2182                                                                          jd->d_id));
2183                                osip_remove_transaction(eXosip.j_osip, out_tr);
2184                                osip_list_remove(jd->d_out_trs, pos);
2185                                osip_list_add(&eXosip.j_transactions, out_tr, 0);
2186
2187                                ret = OSIP_SUCCESS;     /* return "released" */
2188                                break;
2189                        }
2190                        if (0 == osip_strcasecmp(out_tr->cseq->method, "SUBSCRIBE"))
2191                                skip_first = 1;
2192                        if (0 == osip_strcasecmp(out_tr->cseq->method, "NOTIFY"))
2193                                skip_first = 1;
2194                        pos++;
2195                }
2196        }
2197
2198        return ret;
2199}
2200
2201void eXosip_release_terminated_subscriptions()
2202{
2203        time_t now = time(NULL);
2204        eXosip_dialog_t *jd;
2205        eXosip_dialog_t *jdnext;
2206        eXosip_subscribe_t *js;
2207        eXosip_subscribe_t *jsnext;
2208
2209        for (js = eXosip.j_subscribes; js != NULL;) {
2210                jsnext = js->next;
2211
2212                if (js->s_dialogs == NULL) {
2213                        if (js->s_out_tr != NULL && js->s_out_tr->birth_time + 64 < now) {      /* Wait a max of 64 sec */
2214                                /* destroy non established contexts after max of 64 sec */
2215                                REMOVE_ELEMENT(eXosip.j_subscribes, js);
2216                                eXosip_subscribe_free(js);
2217                                __eXosip_wakeup();
2218                                return;
2219                        }
2220                } else {
2221                        for (jd = js->s_dialogs; jd != NULL;) {
2222                                jdnext = jd->next;
2223                                eXosip_release_finished_transactions_for_subscription(jd);
2224
2225                                if (jd->d_dialog == NULL || jd->d_dialog->state == DIALOG_EARLY) {
2226                                        if (js->s_out_tr != NULL && js->s_out_tr->birth_time + 64 < now) {      /* Wait a max of 2 minutes */
2227                                                /* destroy non established contexts after max of 64 sec */
2228                                                REMOVE_ELEMENT(eXosip.j_subscribes, js);
2229                                                eXosip_subscribe_free(js);
2230                                                __eXosip_wakeup();
2231                                                return;
2232                                        }
2233                                }
2234
2235                                jd = jdnext;
2236                        }
2237                }
2238                js = jsnext;
2239        }
2240
2241}
2242
2243void eXosip_release_terminated_in_subscriptions(void)
2244{
2245        eXosip_dialog_t *jd;
2246        eXosip_dialog_t *jdnext;
2247        eXosip_notify_t *jn;
2248        eXosip_notify_t *jnnext;
2249
2250        for (jn = eXosip.j_notifies; jn != NULL;) {
2251                jnnext = jn->next;
2252
2253                for (jd = jn->n_dialogs; jd != NULL;) {
2254                        jdnext = jd->next;
2255                        eXosip_release_finished_transactions_for_subscription(jd);
2256                        jd = jdnext;
2257                }
2258                jn = jnnext;
2259        }
2260}
2261
2262#endif
Note: See TracBrowser for help on using the repository browser.