OSDN Git Service

Add MS7619SE
[uclinux-h8/uClinux-dist.git] / lib / osip2 / src / osip2 / osip_transaction.c
1 /*
2   The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-)
3   Copyright (C) 2001,2002,2003  Aymeric MOIZARD jack@atosc.org
4   
5   This library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9   
10   This library 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 GNU
13   Lesser General Public License for more details.
14   
15   You should have received a copy of the GNU Lesser General Public
16   License along with this library; if not, write to the Free Software
17   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19
20 #include <osip2/internal.h>
21 #include <osip2/osip.h>
22
23 #include "fsm.h"
24 #include "xixt.h"
25
26 static int __osip_transaction_set_topvia (osip_transaction_t * transaction,
27                                           osip_via_t * topvia);
28 static int __osip_transaction_set_from (osip_transaction_t * transaction,
29                                         osip_from_t * from);
30 static int __osip_transaction_set_to (osip_transaction_t * transaction,
31                                       osip_to_t * to);
32 static int __osip_transaction_set_call_id (osip_transaction_t * transaction,
33                                            osip_call_id_t * call_id);
34 static int __osip_transaction_set_cseq (osip_transaction_t * transaction,
35                                         osip_cseq_t * cseq);
36
37 static int
38 __osip_transaction_set_topvia (osip_transaction_t * transaction,
39                                osip_via_t * topvia)
40 {
41   int i;
42
43   if (transaction == NULL)
44     return -1;
45   i = osip_via_clone (topvia, &(transaction->topvia));
46   if (i == 0)
47     return 0;
48   transaction->topvia = NULL;
49   return -1;
50 }
51
52 static int
53 __osip_transaction_set_from (osip_transaction_t * transaction,
54                              osip_from_t * from)
55 {
56   int i;
57
58   if (transaction == NULL)
59     return -1;
60   i = osip_from_clone (from, &(transaction->from));
61   if (i == 0)
62     return 0;
63   transaction->from = NULL;
64   return -1;
65 }
66
67 static int
68 __osip_transaction_set_to (osip_transaction_t * transaction, osip_to_t * to)
69 {
70   int i;
71
72   if (transaction == NULL)
73     return -1;
74   i = osip_to_clone (to, &(transaction->to));
75   if (i == 0)
76     return 0;
77   transaction->to = NULL;
78   return -1;
79 }
80
81 static int
82 __osip_transaction_set_call_id (osip_transaction_t * transaction,
83                                 osip_call_id_t * call_id)
84 {
85   int i;
86
87   if (transaction == NULL)
88     return -1;
89   i = osip_call_id_clone (call_id, &(transaction->callid));
90   if (i == 0)
91     return 0;
92   transaction->callid = NULL;
93   return -1;
94 }
95
96 static int
97 __osip_transaction_set_cseq (osip_transaction_t * transaction,
98                              osip_cseq_t * cseq)
99 {
100   int i;
101
102   if (transaction == NULL)
103     return -1;
104   i = osip_cseq_clone (cseq, &(transaction->cseq));
105   if (i == 0)
106     return 0;
107   transaction->cseq = NULL;
108   return -1;
109 }
110
111 int
112 osip_transaction_init (osip_transaction_t ** transaction,
113                        osip_fsm_type_t ctx_type, osip_t * osip,
114                        osip_message_t * request)
115 {
116   static int transactionid = 1;
117   osip_via_t *topvia;
118
119   int i;
120   time_t now;
121
122   if (request==NULL)  return -1;
123   if (request->call_id==NULL)  return -1;
124   if (request->call_id->number==NULL)  return -1;
125
126   OSIP_TRACE (osip_trace
127               (__FILE__, __LINE__, OSIP_INFO2, NULL,
128                "allocating transaction ressource %i %s\n", transactionid,
129                request->call_id->number));
130
131   *transaction =
132     (osip_transaction_t *) osip_malloc (sizeof (osip_transaction_t));
133   if (*transaction == NULL)
134     return -1;
135
136   now = time (NULL);
137
138   memset (*transaction, 0, sizeof (osip_transaction_t));
139
140   (*transaction)->birth_time = now;
141   (*transaction)->transactionid = transactionid;
142   transactionid++;
143
144   topvia = osip_list_get (request->vias, 0);
145   if (topvia == NULL)
146     goto ti_error_1;
147
148   i = __osip_transaction_set_topvia (*transaction, topvia);
149   if (i != 0)
150     goto ti_error_1;
151
152   /* In some situation, some of those informtions might
153      be useless. Mostly, I prefer to keep them in all case
154      for backward compatibility. */
155   i = __osip_transaction_set_from (*transaction, request->from);
156   if (i != 0)
157     goto ti_error_2;
158   i = __osip_transaction_set_to (*transaction, request->to);
159   if (i != 0)
160     goto ti_error_3;
161   i = __osip_transaction_set_call_id (*transaction, request->call_id);
162   if (i != 0)
163     goto ti_error_4;
164   i = __osip_transaction_set_cseq (*transaction, request->cseq);
165   if (i != 0)
166     goto ti_error_5;
167   /* RACE conditions can happen for server transactions */
168   /* (*transaction)->orig_request = request; */
169   (*transaction)->orig_request = NULL;
170
171   (*transaction)->config = osip;
172
173   (*transaction)->transactionff =
174     (osip_fifo_t *) osip_malloc (sizeof (osip_fifo_t));
175   if ((*transaction)->transactionff == NULL)
176     goto ti_error_6;
177   osip_fifo_init ((*transaction)->transactionff);
178
179   (*transaction)->ctx_type = ctx_type;
180   (*transaction)->ict_context = NULL;
181   (*transaction)->ist_context = NULL;
182   (*transaction)->nict_context = NULL;
183   (*transaction)->nist_context = NULL;
184   if (ctx_type == ICT)
185     {
186       (*transaction)->state = ICT_PRE_CALLING;
187       i = __osip_ict_init (&((*transaction)->ict_context), osip, request);
188       if (i != 0)
189         goto ti_error_7;
190       __osip_add_ict (osip, *transaction);
191     }
192   else if (ctx_type == IST)
193     {
194       (*transaction)->state = IST_PRE_PROCEEDING;
195       i = __osip_ist_init (&((*transaction)->ist_context), osip, request);
196       if (i != 0)
197         goto ti_error_7;
198       __osip_add_ist (osip, *transaction);
199     }
200   else if (ctx_type == NICT)
201     {
202       (*transaction)->state = NICT_PRE_TRYING;
203       i = __osip_nict_init (&((*transaction)->nict_context), osip, request);
204       if (i != 0)
205         goto ti_error_7;
206       __osip_add_nict (osip, *transaction);
207     }
208   else
209     {
210       (*transaction)->state = NIST_PRE_TRYING;
211       i = __osip_nist_init (&((*transaction)->nist_context), osip, request);
212       if (i != 0)
213         goto ti_error_7;
214       __osip_add_nist (osip, *transaction);
215     }
216   return 0;
217
218
219 ti_error_7:
220   osip_fifo_free ((*transaction)->transactionff);
221 ti_error_6:
222   osip_cseq_free ((*transaction)->cseq);
223 ti_error_5:
224   osip_call_id_free ((*transaction)->callid);
225 ti_error_4:
226   osip_to_free ((*transaction)->to);
227 ti_error_3:
228   osip_from_free ((*transaction)->from);
229 ti_error_2:
230   osip_via_free ((*transaction)->topvia);
231 ti_error_1:
232   osip_free (*transaction);
233   return -1;
234 }
235
236 /* This method automaticly remove the transaction context from
237    the osip stack. This task is required for proper operation
238    when a transaction goes in the TERMINATED STATE.
239    However the user might want to just take the context out of
240    the SIP stack andf keep it for future use without freeing
241    all ressource.... This way the transaction context can be
242    kept without being used by the oSIP stack.
243
244    new methods that replace this one:
245    osip_remove_transaction
246    +
247    osip_transaction_free2();
248
249  */
250 int
251 osip_transaction_free (osip_transaction_t * transaction)
252 {
253   int i;
254
255   if (transaction == NULL)
256     return -1;
257   i = osip_remove_transaction (transaction->config, transaction);
258
259   if (i != 0)                   /* yet removed ??? */
260     {
261       OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_BUG, NULL,
262                               "transaction already removed from list %i!\n",
263                               transaction->transactionid));
264     }
265
266   return osip_transaction_free2 (transaction);
267 }
268
269 /* same as osip_transaction_free() but assume the transaction is
270    already removed from the list of transaction in the osip stack */
271 int
272 osip_transaction_free2 (osip_transaction_t * transaction)
273 {
274   osip_event_t *evt;
275
276   if (transaction == NULL)
277     return -1;
278   if (transaction->orig_request != NULL
279       &&transaction->orig_request->call_id!=NULL
280       &&transaction->orig_request->call_id->number!=NULL)
281     {
282       OSIP_TRACE (osip_trace
283                   (__FILE__, __LINE__, OSIP_INFO2, NULL,
284                    "free transaction ressource %i %s\n",
285                    transaction->transactionid,
286                    transaction->orig_request->call_id->number));
287     }
288   if (transaction->ctx_type == ICT)
289     {
290       __osip_ict_free (transaction->ict_context);
291     }
292   else if (transaction->ctx_type == IST)
293     {
294       __osip_ist_free (transaction->ist_context);
295     }
296   else if (transaction->ctx_type == NICT)
297     {
298       __osip_nict_free (transaction->nict_context);
299     }
300   else
301     {
302       __osip_nist_free (transaction->nist_context);
303     }
304
305   /* empty the fifo */
306   evt = osip_fifo_tryget (transaction->transactionff);
307   while (evt != NULL)
308     {
309       osip_message_free (evt->sip);
310       osip_free (evt);
311       evt = osip_fifo_tryget (transaction->transactionff);
312     }
313   osip_fifo_free (transaction->transactionff);
314
315   osip_message_free (transaction->orig_request);
316   osip_message_free (transaction->last_response);
317   osip_message_free (transaction->ack);
318
319   osip_via_free (transaction->topvia);
320   osip_from_free (transaction->from);
321   osip_to_free (transaction->to);
322   osip_call_id_free (transaction->callid);
323   osip_cseq_free (transaction->cseq);
324
325   osip_free (transaction);
326   return 0;
327 }
328
329 int
330 osip_transaction_add_event (osip_transaction_t * transaction,
331                             osip_event_t * evt)
332 {
333   if (evt == NULL)
334     return -1;
335   if (transaction == NULL)
336     return -1;
337   evt->transactionid = transaction->transactionid;
338   osip_fifo_add (transaction->transactionff, evt);
339   return 0;
340 }
341
342 int
343 osip_transaction_execute (osip_transaction_t * transaction,
344                           osip_event_t * evt)
345 {
346   osip_statemachine_t *statemachine;
347
348   /* to kill the process, simply send this type of event. */
349   if (EVT_IS_KILL_TRANSACTION (evt))
350     {
351       /* MAJOR CHANGE!
352          TRANSACTION MUST NOW BE RELEASED BY END-USER:
353          So Any usefull data can be save and re-used */
354       /* osip_transaction_free(transaction);
355          osip_free(transaction); */
356       osip_free (evt);
357       return 0;
358     }
359
360   OSIP_TRACE (osip_trace
361               (__FILE__, __LINE__, OSIP_INFO4, NULL,
362                "sipevent tr->transactionid: %i\n",
363                transaction->transactionid));
364   OSIP_TRACE (osip_trace
365               (__FILE__, __LINE__, OSIP_INFO4, NULL,
366                "sipevent tr->state: %i\n", transaction->state));
367   OSIP_TRACE (osip_trace
368               (__FILE__, __LINE__, OSIP_INFO4, NULL,
369                "sipevent evt->type: %i\n", evt->type));
370   OSIP_TRACE (osip_trace
371               (__FILE__, __LINE__, OSIP_INFO4, NULL,
372                "sipevent evt->sip: %x\n", evt->sip));
373
374   if (transaction->ctx_type == ICT)
375     statemachine = __ict_get_fsm ();
376   else if (transaction->ctx_type == IST)
377     statemachine = __ist_get_fsm ();
378   else if (transaction->ctx_type == NICT)
379     statemachine = __nict_get_fsm ();
380   else
381     statemachine = __nist_get_fsm ();
382
383
384   if (-1 == fsm_callmethod (evt->type,
385                             transaction->state, statemachine, evt,
386                             transaction))
387     {
388       OSIP_TRACE (osip_trace
389                   (__FILE__, __LINE__, OSIP_INFO3, NULL, "USELESS event!\n"));
390       /* message is useless. */
391       if (EVT_IS_MSG (evt))
392         {
393           if (evt->sip != NULL)
394             {
395               osip_message_free (evt->sip);
396             }
397         }
398     }
399   else
400     {
401       OSIP_TRACE (osip_trace
402                   (__FILE__, __LINE__, OSIP_INFO4, NULL,
403                    "sipevent evt: method called!\n"));
404     }
405   osip_free (evt);              /* this is the ONLY place for freeing event!! */
406   return 1;
407 }
408
409 int
410 osip_transaction_get_destination (osip_transaction_t * transaction, char **ip,
411                                   int *port)
412 {
413   *ip = NULL;
414   *port = 0;
415   if (transaction == NULL)
416     return -1;
417   if (transaction->ict_context != NULL)
418     {
419       *ip = transaction->ict_context->destination;
420       *port = transaction->ict_context->port;
421       return 0;
422     }
423   else if (transaction->nict_context != NULL)
424     {
425       *ip = transaction->nict_context->destination;
426       *port = transaction->nict_context->port;
427       return 0;
428     }
429   return -1;
430 }
431
432 int
433 osip_transaction_set_your_instance (osip_transaction_t * transaction,
434                                     void *instance)
435 {
436   if (transaction == NULL)
437     return -1;
438   transaction->your_instance = instance;
439   return 0;
440 }
441
442 void *
443 osip_transaction_get_your_instance (osip_transaction_t * transaction)
444 {
445   if (transaction == NULL)
446     return NULL;
447   return transaction->your_instance;
448 }
449
450 int
451 __osip_transaction_set_state (osip_transaction_t * transaction, state_t state)
452 {
453   if (transaction == NULL)
454     return -1;
455   transaction->state = state;
456   return 0;
457 }
458
459 int
460 osip_transaction_set_in_socket (osip_transaction_t * transaction, int sock)
461 {
462   if (transaction == NULL)
463     return -1;
464   transaction->in_socket = sock;
465   return 0;
466 }
467
468 int
469 osip_transaction_set_out_socket (osip_transaction_t * transaction, int sock)
470 {
471   if (transaction == NULL)
472     return -1;
473   transaction->out_socket = sock;
474   return 0;
475 }
476
477 int
478 __osip_transaction_matching_response_osip_to_xict_17_1_3 (osip_transaction_t *
479                                                           tr,
480                                                           osip_message_t *
481                                                           response)
482 {
483   osip_generic_param_t *b_request;
484   osip_generic_param_t *b_response;
485   osip_via_t *topvia_response;
486
487   /* some checks to avoid crashing on bad requests */
488   if (tr == NULL || (tr->ict_context == NULL && tr->nict_context == NULL) ||
489       /* only ict and nict can match a response */
490       response == NULL || response->cseq == NULL
491       || response->cseq->method == NULL)
492     return -1;
493
494   topvia_response = osip_list_get (response->vias, 0);
495   if (topvia_response == NULL)
496     {
497       OSIP_TRACE (osip_trace
498                   (__FILE__, __LINE__, OSIP_ERROR, NULL,
499                    "Remote UA is not compliant: missing a Via header!\n"));
500       return -1;
501     }
502   osip_via_param_get_byname (tr->topvia, "branch", &b_request);
503   if (b_request == NULL)
504     {
505       OSIP_TRACE (osip_trace
506                   (__FILE__, __LINE__, OSIP_BUG, NULL,
507                    "You created a transaction without any branch! THIS IS NOT ALLOWED\n"));
508       return -1;
509     }
510   osip_via_param_get_byname (topvia_response, "branch", &b_response);
511   if (b_response == NULL)
512     {
513 #ifdef FWDSUPPORT
514       /* the from tag (unique) */
515       if (from_tag_match (tr->from, response->from) != 0)
516         return -1;
517       /* the Cseq field */
518       if (cseq_match (tr->cseq, response->cseq) != 0)
519         return -1;
520       /* the To field */
521       if (response->to->url->username == NULL
522           && tr->from->url->username != NULL)
523         return -1;
524       if (response->to->url->username != NULL
525           && tr->from->url->username == NULL)
526         return -1;
527       if (response->to->url->username != NULL
528           && tr->from->url->username != NULL)
529         {
530           if (strcmp (response->to->url->host, tr->from->url->host) ||
531               strcmp (response->to->url->username, tr->from->url->username))
532             return -1;
533         }
534       else
535         {
536           if (strcmp (response->to->url->host, tr->from->url->host))
537             return -1;
538         }
539
540       /* the Call-ID field */
541       if (call_id_match (tr->callid, response->call_id) != 0)
542         return -1;
543       return 0;
544 #else
545       OSIP_TRACE (osip_trace
546                   (__FILE__, __LINE__, OSIP_BUG, NULL,
547                    "Remote UA is not compliant: missing a branch parameter in  Via header!\n"));
548       return -1;
549 #endif
550     }
551
552   /*
553      A response matches a client transaction under two
554      conditions:
555
556      1.   If the response has the same value of the branch parameter
557      in the top Via header field as the branch parameter in the
558      top Via header field of the request that created the
559      transaction.
560    */
561   if (0 != strcmp (b_request->gvalue, b_response->gvalue))
562     return -1;
563   /*  
564      2.   If the method parameter in the CSeq header field matches
565      the method of the request that created the transaction. The
566      method is needed since a CANCEL request constitutes a
567      different transaction, but shares the same value of the
568      branch parameter.
569      AMD NOTE: cseq->method is ALWAYS the same than the METHOD of the request.
570    */
571   if (0 == strcmp (response->cseq->method, tr->cseq->method))   /* general case */
572     return 0;
573   return -1;
574 }
575
576 int
577 __osip_transaction_matching_request_osip_to_xist_17_2_3 (osip_transaction_t *
578                                                          tr,
579                                                          osip_message_t *
580                                                          request)
581 {
582   osip_generic_param_t *b_origrequest;
583   osip_generic_param_t *b_request;
584   osip_via_t *topvia_request;
585   size_t length_br;
586   size_t length_br2;
587
588   /* some checks to avoid crashing on bad requests */
589   if (tr == NULL || (tr->ist_context == NULL && tr->nist_context == NULL) ||
590       /* only ist and nist can match a request */
591       request == NULL || request->cseq == NULL
592       || request->cseq->method == NULL)
593     return -1;
594
595   topvia_request = osip_list_get (request->vias, 0);
596   if (topvia_request == NULL)
597     {
598       OSIP_TRACE (osip_trace
599                   (__FILE__, __LINE__, OSIP_ERROR, NULL,
600                    "Remote UA is not compliant: missing a Via header!\n"));
601       return -1;
602     }
603   osip_via_param_get_byname (topvia_request, "branch", &b_request);
604   osip_via_param_get_byname (tr->topvia, "branch", &b_origrequest);
605
606   if ((b_origrequest == NULL && b_request != NULL) ||
607       (b_origrequest != NULL && b_request == NULL))
608     return -1;                  /* one request is compliant, the other one is not... */
609
610   /* Section 17.2.3 Matching Requests to Server Transactions:
611      "The branch parameter in the topmost Via header field of the request
612      is examined. If it is present and begins with the magic cookie
613      "z9hG4bK", the request was generated by a client transaction
614      compliant to this specification."
615    */
616
617   if (b_origrequest != NULL && b_request != NULL)
618     /* case where both request contains a branch */
619     {
620       length_br = strlen (b_origrequest->gvalue);
621       length_br2 = strlen (b_request->gvalue);
622       if (length_br != length_br2)
623         return -1;              /* can't be the same */
624       if (0 == strncmp (b_origrequest->gvalue, "z9hG4bK", 7)
625           && 0 == strncmp (b_request->gvalue, "z9hG4bK", 7))
626         {
627           /* both request comes from a compliant UA */
628           /* The request matches a transaction if the branch parameter
629              in the request is equal to the one in the top Via header
630              field of the request that created the transaction, the
631              sent-by value in the top Via of the request is equal to
632              the one in the request that created the transaction, and in
633              the case of a CANCEL request, the method of the request
634              that created the transaction was also CANCEL.
635            */
636           if (0 != strcmp (b_origrequest->gvalue, b_request->gvalue))
637             return -1;          /* branch param does not match */
638           {
639             /* check the sent-by values */
640             char *b_port = via_get_port (topvia_request);
641             char *b_origport = via_get_port (tr->topvia);
642             char *b_host = via_get_host (topvia_request);
643             char *b_orighost = via_get_host (tr->topvia);
644             if ((b_host == NULL || b_orighost == NULL))
645               return -1;
646             if (0 != strcmp (b_orighost, b_host))
647               return -1;
648
649             if (b_port != NULL && b_origport == NULL
650                 && 0 != strcmp (b_port, "5060"))
651               return -1;
652             else if (b_origport != NULL && b_port == NULL
653                      && 0 != strcmp (b_origport, "5060"))
654               return -1;
655             else if (b_origport != NULL && b_port != NULL
656                      && 0 != strcmp (b_origport, b_port))
657               return -1;
658           }
659 #ifdef AC_BUG
660           /* audiocodes bug (MP108-fxs-SIP-4-0-282-380) */
661           if (0 != osip_from_tag_match (tr->from, request->from))
662             return -1;
663 #endif
664           if (                  /* MSG_IS_CANCEL(request)&& <<-- BUG from the spec?
665                                    I always check the CSeq */
666                (!(0 == strcmp (tr->cseq->method, "INVITE") &&
667                   0 == strcmp (request->cseq->method, "ACK")))
668                && 0 != strcmp (tr->cseq->method, request->cseq->method))
669             return -1;
670           return 0;
671         }
672     }
673
674   /* Back to the old backward compatibilty mechanism for matching requests */
675   if (0 != osip_call_id_match (tr->callid, request->call_id))
676     return -1;
677   if (MSG_IS_ACK (request))
678     {
679       osip_generic_param_t *tag_from1;
680       osip_generic_param_t *tag_from2;
681
682       osip_from_param_get_byname (tr->to, "tag", &tag_from1);
683       osip_from_param_get_byname (request->to, "tag", &tag_from2);
684       if (tag_from1 == NULL && tag_from2 != NULL)
685         {                       /* do not check it as it can be a new tag when the final
686                                    answer has a tag while an INVITE doesn't have one */
687         }
688       else if (tag_from1 != NULL && tag_from2 == NULL)
689         {
690           return -1;
691         }
692       else
693         {
694           if (0 != osip_to_tag_match (tr->to, request->to))
695             return -1;
696         }
697     }
698   else
699     {
700       if (0 != osip_to_tag_match (tr->to, request->to))
701         return -1;
702     }
703   if (0 != osip_from_tag_match (tr->from, request->from))
704     return -1;
705   if (0 != osip_cseq_match (tr->cseq, request->cseq))
706     return -1;
707   if (0 != osip_via_match (tr->topvia, topvia_request))
708     return -1;
709   return 0;
710 }
711
712 #if 0
713
714 int
715 callleg_match (osip_to_t * to1, osip_from_t * from1, osip_to_t * to2,
716                osip_from_t * from2)
717 {
718   if (to1 == NULL || to2 == NULL)
719     return -1;
720   if (from1 == NULL || from2 == NULL)
721     return -1;
722
723   if (0 == osip_from_compare ((osip_from_t *) to1, (osip_from_t *) to2)
724       && 0 == osip_from_compare (from1, from2))
725     return 0;
726   return -1;
727 }
728
729 #endif