and added files
[bcm963xx.git] / userapps / opensource / libosip2 / src / osip2 / ict.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 int
27 __osip_ict_init (osip_ict_t ** ict, osip_t * osip, osip_message_t * invite)
28 {
29   osip_route_t *route;
30   int i;
31   time_t now;
32
33   OSIP_TRACE (osip_trace
34               (__FILE__, __LINE__, OSIP_INFO2, NULL,
35                "allocating ICT context\n"));
36
37   *ict = (osip_ict_t *) osip_malloc (sizeof (osip_ict_t));
38   if (*ict == NULL)
39     return -1;
40
41   now = time (NULL);
42   memset (*ict, 0, sizeof (osip_ict_t));
43   /* for INVITE retransmissions */
44   {
45     osip_via_t *via;
46     char *proto;
47
48     i = osip_message_get_via (invite, 0, &via); /* get top via */
49     if (i != 0)
50       goto ii_error_1;
51     proto = via_get_protocol (via);
52     if (proto == NULL)
53       goto ii_error_1;
54
55     i = osip_strncasecmp (proto, "TCP", 3);
56     if (i != 0)
57       {                         /* for other reliable protocol than TCP, the timer
58                                    must be desactived by the external application */
59         (*ict)->timer_a_length = DEFAULT_T1;
60         if (64 * DEFAULT_T1 < 32000)
61           (*ict)->timer_d_length = 32000;
62         else
63           (*ict)->timer_d_length = 64 * DEFAULT_T1;
64         gettimeofday (&(*ict)->timer_a_start, NULL);
65         add_gettimeofday (&(*ict)->timer_a_start, (*ict)->timer_a_length);
66         (*ict)->timer_d_start.tv_sec = -1;      /* not started */
67       }
68     else
69       {                         /* TCP is used: */
70         (*ict)->timer_a_length = -1;    /* A is not ACTIVE */
71         (*ict)->timer_d_length = 0;     /* MUST do the transition immediatly */
72         (*ict)->timer_a_start.tv_sec = -1;      /* not started */
73         (*ict)->timer_d_start.tv_sec = -1;      /* not started */
74       }
75   }
76
77   /* for PROXY, the destination MUST be set by the application layer,
78      this one may not be correct. */
79   osip_message_get_route (invite, 0, &route);
80   if (route != NULL)
81     {
82       int port = 5060;
83
84       if (route->url->port != NULL)
85         port = osip_atoi (route->url->port);
86       osip_ict_set_destination ((*ict), osip_strdup (route->url->host), port);
87     }
88   else
89     (*ict)->port = 5060;
90
91   (*ict)->timer_b_length = 64 * DEFAULT_T1;
92   gettimeofday (&(*ict)->timer_b_start, NULL);
93   add_gettimeofday (&(*ict)->timer_b_start, (*ict)->timer_b_length);
94
95   /* Oups! A bug! */
96   /*  (*ict)->port  = 5060; */
97
98   return 0;
99
100 ii_error_1:
101   osip_free (*ict);
102   return -1;
103 }
104
105 int
106 __osip_ict_free (osip_ict_t * ict)
107 {
108   if (ict == NULL)
109     return -1;
110   OSIP_TRACE (osip_trace
111               (__FILE__, __LINE__, OSIP_INFO2, NULL, "free ict ressource\n"));
112
113   osip_free (ict->destination);
114   osip_free (ict);
115   return 0;
116 }
117
118 int
119 osip_ict_set_destination (osip_ict_t * ict, char *destination, int port)
120 {
121   if (ict == NULL)
122     return -1;
123   if (ict->destination != NULL)
124     osip_free (ict->destination);
125   ict->destination = destination;
126   ict->port = port;
127   return 0;
128 }
129
130 osip_event_t *
131 __osip_ict_need_timer_a_event (osip_ict_t * ict, state_t state, int transactionid)
132 {
133   struct timeval now;
134   gettimeofday (&now, NULL);
135
136   if (ict == NULL)
137     return NULL;
138   if (state == ICT_CALLING)
139     {
140       /* may need timer A */
141       if (ict->timer_a_start.tv_sec == -1)
142         return NULL;
143       if (timercmp (&now, &ict->timer_a_start, >))
144         return __osip_event_new (TIMEOUT_A, transactionid);
145     }
146   return NULL;
147 }
148
149 osip_event_t *
150 __osip_ict_need_timer_b_event (osip_ict_t * ict, state_t state,
151                                int transactionid)
152 {
153   struct timeval now;
154   gettimeofday (&now, NULL);
155
156   if (ict == NULL)
157     return NULL;
158   if (state == ICT_CALLING)
159     {
160       /* may need timer B */
161       if (ict->timer_b_start.tv_sec == -1)
162         return NULL;
163       if (timercmp (&now, &ict->timer_b_start, >))
164         return __osip_event_new (TIMEOUT_B, transactionid);
165     }
166   return NULL;
167 }
168
169 osip_event_t *
170 __osip_ict_need_timer_d_event (osip_ict_t * ict, state_t state,
171                                int transactionid)
172 {
173   struct timeval now;
174   gettimeofday (&now, NULL);
175
176   if (ict == NULL)
177     return NULL;
178   if (state == ICT_COMPLETED)
179     {
180       /* may need timer D */
181       if (ict->timer_d_start.tv_sec == -1)
182         return NULL;
183       if (timercmp (&now, &ict->timer_d_start, >))
184         return __osip_event_new (TIMEOUT_D, transactionid);
185     }
186   return NULL;
187 }
188