1 /*
2 The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-)
3 Copyright (C) 2001-2020 Aymeric MOIZARD amoizard@antisip.com
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
__osip_ict_init(osip_ict_t ** ict,osip_t * osip,osip_message_t * invite)26 int __osip_ict_init(osip_ict_t **ict, osip_t *osip, osip_message_t *invite) {
27 osip_route_t *route;
28 int i;
29
30 OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL, "allocating ICT context\n"));
31
32 *ict = (osip_ict_t *) osip_malloc(sizeof(osip_ict_t));
33
34 if (*ict == NULL)
35 return OSIP_NOMEM;
36
37 memset(*ict, 0, sizeof(osip_ict_t));
38 /* for INVITE retransmissions */
39 {
40 osip_via_t *via;
41 char *proto;
42
43 i = osip_message_get_via(invite, 0, &via); /* get top via */
44
45 if (i < 0) {
46 osip_free(*ict);
47 return i;
48 }
49
50 proto = via_get_protocol(via);
51
52 if (proto == NULL) {
53 osip_free(*ict);
54 return OSIP_SYNTAXERROR;
55 }
56
57 #ifdef USE_BLOCKINGSOCKET
58
59 if (osip_strcasecmp(proto, "TCP") != 0 && osip_strcasecmp(proto, "TLS") != 0 && osip_strcasecmp(proto, "SCTP") != 0) {
60 /* for other reliable protocol than TCP, the timer
61 must be desactived by the external application */
62 (*ict)->timer_a_length = DEFAULT_T1;
63
64 if (64 * DEFAULT_T1 < 32000)
65 (*ict)->timer_d_length = 32000;
66
67 else
68 (*ict)->timer_d_length = 64 * DEFAULT_T1;
69
70 osip_gettimeofday(&(*ict)->timer_a_start, NULL);
71 add_gettimeofday(&(*ict)->timer_a_start, (*ict)->timer_a_length);
72 (*ict)->timer_d_start.tv_sec = -1; /* not started */
73
74 } else { /* reliable protocol is used: */
75 (*ict)->timer_a_length = -1; /* A is not ACTIVE */
76 (*ict)->timer_d_length = 0; /* MUST do the transition immediatly */
77 (*ict)->timer_a_start.tv_sec = -1; /* not started */
78 (*ict)->timer_d_start.tv_sec = -1; /* not started */
79 }
80 }
81 #else
82
83 if (osip_strcasecmp(proto, "TCP") != 0 && osip_strcasecmp(proto, "TLS") != 0 && osip_strcasecmp(proto, "SCTP") != 0) {
84 /* for other reliable protocol than TCP, the timer
85 must be desactived by the external application */
86 (*ict)->timer_a_length = DEFAULT_T1;
87
88 if (64 * DEFAULT_T1 < 32000)
89 (*ict)->timer_d_length = 32000;
90
91 else
92 (*ict)->timer_d_length = 64 * DEFAULT_T1;
93
94 osip_gettimeofday(&(*ict)->timer_a_start, NULL);
95 add_gettimeofday(&(*ict)->timer_a_start, (*ict)->timer_a_length);
96 (*ict)->timer_d_start.tv_sec = -1; /* not started */
97
98 } else { /* reliable protocol is used: */
99 (*ict)->timer_a_length = DEFAULT_T1;
100 (*ict)->timer_d_length = 0; /* MUST do the transition immediatly */
101 osip_gettimeofday(&(*ict)->timer_a_start, NULL);
102 add_gettimeofday(&(*ict)->timer_a_start, (*ict)->timer_a_length);
103 (*ict)->timer_d_start.tv_sec = -1; /* not started */
104 }
105 }
106 #endif
107
108 /* for PROXY, the destination MUST be set by the application layer,
109 this one may not be correct. */
110 osip_message_get_route(invite, 0, &route);
111
112 if (route != NULL && route->url != NULL) {
113 osip_uri_param_t *lr_param;
114
115 osip_uri_uparam_get_byname(route->url, "lr", &lr_param);
116
117 if (lr_param == NULL) {
118 /* using uncompliant proxy: destination is the request-uri */
119 route = NULL;
120 }
121 }
122
123 if (route != NULL && route->url != NULL) {
124 int port = 5060;
125
126 if (route->url->port != NULL)
127 port = osip_atoi(route->url->port);
128
129 osip_ict_set_destination((*ict), osip_strdup(route->url->host), port);
130
131 } else {
132 int port = 5060;
133
134 /* search for maddr parameter */
135 osip_uri_param_t *maddr_param = NULL;
136 osip_uri_param_t *obr_param = NULL;
137 osip_uri_param_t *obp_param = NULL;
138
139 port = 5060;
140
141 if (invite->req_uri->port != NULL)
142 port = osip_atoi(invite->req_uri->port);
143
144 /* if ob was used in Contact, then exosip adds "x-obr" and "x-obp", thus, when
145 processing request, the ip/port destination are re-used here */
146 osip_uri_uparam_get_byname(invite->req_uri, "x-obr", &obr_param);
147 osip_uri_uparam_get_byname(invite->req_uri, "x-obp", &obp_param);
148
149 osip_uri_uparam_get_byname(invite->req_uri, "maddr", &maddr_param);
150
151 if (maddr_param != NULL && maddr_param->gvalue != NULL)
152 osip_ict_set_destination((*ict), osip_strdup(maddr_param->gvalue), port);
153
154 else if (obr_param != NULL && obr_param->gvalue != NULL && obp_param != NULL && obp_param->gvalue != NULL)
155 osip_ict_set_destination((*ict), osip_strdup(obr_param->gvalue), osip_atoi(obp_param->gvalue));
156
157 else
158 osip_ict_set_destination((*ict), osip_strdup(invite->req_uri->host), port);
159 }
160
161 (*ict)->timer_b_length = 64 * DEFAULT_T1;
162 osip_gettimeofday(&(*ict)->timer_b_start, NULL);
163 add_gettimeofday(&(*ict)->timer_b_start, (*ict)->timer_b_length);
164
165 /* Oups! A bug! */
166 /* (*ict)->port = 5060; */
167
168 return OSIP_SUCCESS;
169 }
170
__osip_ict_free(osip_ict_t * ict)171 int __osip_ict_free(osip_ict_t *ict) {
172 if (ict == NULL)
173 return OSIP_SUCCESS;
174
175 OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO2, NULL, "free ict resource\n"));
176
177 osip_free(ict->destination);
178 osip_free(ict);
179 return OSIP_SUCCESS;
180 }
181
osip_ict_set_destination(osip_ict_t * ict,char * destination,int port)182 int osip_ict_set_destination(osip_ict_t *ict, char *destination, int port) {
183 if (ict == NULL)
184 return OSIP_BADPARAMETER;
185
186 if (ict->destination != NULL)
187 osip_free(ict->destination);
188
189 ict->destination = destination;
190 ict->port = port;
191 return OSIP_SUCCESS;
192 }
193
__osip_ict_need_timer_a_event(osip_ict_t * ict,state_t state,int transactionid)194 osip_event_t *__osip_ict_need_timer_a_event(osip_ict_t *ict, state_t state, int transactionid) {
195 return __osip_transaction_need_timer_x_event(ict, &ict->timer_a_start, state == ICT_CALLING, transactionid, TIMEOUT_A);
196 }
197
__osip_ict_need_timer_b_event(osip_ict_t * ict,state_t state,int transactionid)198 osip_event_t *__osip_ict_need_timer_b_event(osip_ict_t *ict, state_t state, int transactionid) {
199 return __osip_transaction_need_timer_x_event(ict, &ict->timer_b_start, state == ICT_CALLING, transactionid, TIMEOUT_B);
200 }
201
__osip_ict_need_timer_d_event(osip_ict_t * ict,state_t state,int transactionid)202 osip_event_t *__osip_ict_need_timer_d_event(osip_ict_t *ict, state_t state, int transactionid) {
203 return __osip_transaction_need_timer_x_event(ict, &ict->timer_d_start, state == ICT_COMPLETED, transactionid, TIMEOUT_D);
204 }
205