ab58dcac36ba27b445428c7d5d709ad98db7d371
[sip-router] / dset.c
1 /*
2  * $Id$
3  *
4  * destination set
5  *
6  * Copyright (C) 2001-2004 FhG FOKUS
7  *
8  * This file is part of ser, a free SIP server.
9  *
10  * ser is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version
14  *
15  * For a license to use the ser software under conditions
16  * other than those described here, or to purchase support for this
17  * software, please contact iptel.org by e-mail at the following addresses:
18  *    info@iptel.org
19  *
20  * ser is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License 
26  * along with this program; if not, write to the Free Software 
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28  */
29
30 #include <string.h>
31 #include "dprint.h"
32 #include "config.h"
33 #include "parser/parser_f.h"
34 #include "parser/msg_parser.h"
35 #include "ut.h"
36 #include "hash_func.h"
37 #include "error.h"
38 #include "dset.h"
39 #include "mem/mem.h"
40 #include "ip_addr.h"
41
42 #define CONTACT "Contact: "
43 #define CONTACT_LEN (sizeof(CONTACT) - 1)
44
45 #define CONTACT_DELIM ", "
46 #define CONTACT_DELIM_LEN (sizeof(CONTACT_DELIM) - 1)
47
48 #define Q_PARAM ">;q="
49 #define Q_PARAM_LEN (sizeof(Q_PARAM) - 1)
50
51 struct branch
52 {
53         char uri[MAX_URI_SIZE];
54         unsigned int len;
55
56              /* Real destination of the request */
57         char dst_uri[MAX_URI_SIZE];
58         unsigned int dst_uri_len;
59
60         int q; /* Preference of the contact among
61                 * contact within the array */
62         struct socket_info* force_send_socket;
63 };
64
65
66 /* 
67  * Where we store URIs of additional transaction branches
68  * (-1 because of the default branch, #0)
69  */
70 static struct branch branches[MAX_BRANCHES - 1];
71
72 /* how many of them we have */
73 unsigned int nr_branches = 0;
74
75 /* branch iterator */
76 static int branch_iterator = 0;
77
78 /* The q parameter of the Request-URI */
79 static qvalue_t ruri_q = Q_UNSPECIFIED; 
80
81
82 /*
83  * Initialize the branch iterator, the next
84  * call to next_branch will return the first
85  * contact from the dset array
86  */
87 void init_branch_iterator(void)
88 {
89         branch_iterator = 0;
90 }
91
92
93 /*
94  * Return the next branch from the dset
95  * array, 0 is returned if there are no
96  * more branches
97  */
98 char* next_branch(int* len, qvalue_t* q, char** dst_uri, int* dst_len, struct socket_info** force_socket)
99 {
100         unsigned int i;
101
102         i = branch_iterator;
103         if (i < nr_branches) {
104                 branch_iterator++;
105                 *len = branches[i].len;
106                 *q = branches[i].q;
107                 if (dst_uri && dst_len) {
108                         *dst_uri = branches[i].dst_uri;
109                         *dst_len = branches[i].dst_uri_len;
110                 }
111                 if (force_socket) {
112                         *force_socket = branches[i].force_send_socket;
113                 }
114                 return branches[i].uri;
115         } else {
116                 *len = 0;
117                 *q = Q_UNSPECIFIED;
118                 if (dst_uri && dst_len) {
119                         *dst_uri = 0;
120                         *dst_len = 0;
121                 }
122                 if (force_socket) {
123                         *force_socket = 0;
124                 }
125                 return 0;
126         }
127 }
128
129
130 /*
131  * Empty the dset array
132  */
133 void clear_branches(void)
134 {
135         nr_branches = 0;
136         ruri_q = Q_UNSPECIFIED;
137 }
138
139
140 /* 
141  * Add a new branch to current transaction 
142  */
143 int append_branch(struct sip_msg* msg, char* uri, int uri_len, char* dst_uri, int dst_uri_len, 
144                   qvalue_t q, struct socket_info* force_socket)
145 {
146              /* if we have already set up the maximum number
147               * of branches, don't try new ones 
148               */
149         if (nr_branches == MAX_BRANCHES - 1) {
150                 LOG(L_ERR, "ERROR: append_branch: max nr of branches exceeded\n");
151                 ser_error = E_TOO_MANY_BRANCHES;
152                 return -1;
153         }
154
155         if (uri_len > MAX_URI_SIZE - 1) {
156                 LOG(L_ERR, "ERROR: append_branch: too long uri: %.*s\n",
157                     uri_len, uri);
158                 return -1;
159         }
160         
161         if (dst_uri_len > MAX_URI_SIZE - 1) {
162                 LOG(L_ERR, "ERROR: append_branch: too long dst_uri: %.*s\n",
163                     dst_uri_len, ZSW(dst_uri));
164                 return -1;
165         }
166
167              /* if not parameterized, take current uri */
168         if (uri == 0) {
169                 if (msg->new_uri.s) { 
170                         uri = msg->new_uri.s;
171                         uri_len = msg->new_uri.len;
172                 } else {
173                         uri = msg->first_line.u.request.uri.s;
174                         uri_len = msg->first_line.u.request.uri.len;
175                 }
176         }
177         
178         memcpy(branches[nr_branches].uri, uri, uri_len);
179              /* be safe -- add zero termination */
180         branches[nr_branches].uri[uri_len] = 0;
181         branches[nr_branches].len = uri_len;
182         branches[nr_branches].q = q;
183         
184         if (dst_uri && dst_uri_len) {
185                 memcpy(branches[nr_branches].dst_uri, dst_uri, dst_uri_len);
186                 branches[nr_branches].dst_uri[dst_uri_len] = 0;
187                 branches[nr_branches].dst_uri_len = dst_uri_len;
188         } else {
189                 branches[nr_branches].dst_uri[0] = '\0';
190                 branches[nr_branches].dst_uri_len = 0;
191         }
192
193         branches[nr_branches].force_send_socket = force_socket;
194         
195         nr_branches++;
196         return 1;
197 }
198
199
200 /*
201  * Create a Contact header field from the dset
202  * array
203  */
204 char* print_dset(struct sip_msg* msg, int* len) 
205 {
206         int cnt, i;
207         unsigned int qlen;
208         qvalue_t q;
209         str uri;
210         char* p, *qbuf;
211         static char dset[MAX_REDIRECTION_LEN];
212
213         if (msg->new_uri.s) {
214                 cnt = 1;
215                 *len = msg->new_uri.len;
216                 if (ruri_q != Q_UNSPECIFIED) {
217                         *len += 1 + Q_PARAM_LEN + len_q(ruri_q);
218                 }
219         } else {
220                 cnt = 0;
221                 *len = 0;
222         }
223
224         init_branch_iterator();
225         while ((uri.s = next_branch(&uri.len, &q, 0, 0, 0))) {
226                 cnt++;
227                 *len += uri.len;
228                 if (q != Q_UNSPECIFIED) {
229                         *len += 1 + Q_PARAM_LEN + len_q(q);
230                 }
231         }
232
233         if (cnt == 0) return 0; 
234
235         *len += CONTACT_LEN + CRLF_LEN + (cnt - 1) * CONTACT_DELIM_LEN;
236
237         if (*len + 1 > MAX_REDIRECTION_LEN) {
238                 LOG(L_ERR, "ERROR: redirection buffer length exceed\n");
239                 return 0;
240         }
241
242         memcpy(dset, CONTACT, CONTACT_LEN);
243         p = dset + CONTACT_LEN;
244         if (msg->new_uri.s) {
245                 if (ruri_q != Q_UNSPECIFIED) {
246                         *p++ = '<';
247                 }
248
249                 memcpy(p, msg->new_uri.s, msg->new_uri.len);
250                 p += msg->new_uri.len;
251
252                 if (ruri_q != Q_UNSPECIFIED) {
253                         memcpy(p, Q_PARAM, Q_PARAM_LEN);
254                         p += Q_PARAM_LEN;
255
256                         qbuf = q2str(ruri_q, &qlen);
257                         memcpy(p, qbuf, qlen);
258                         p += qlen;
259                 }
260                 i = 1;
261         } else {
262                 i = 0;
263         }
264
265         init_branch_iterator();
266         while ((uri.s = next_branch(&uri.len, &q, 0, 0, 0))) {
267                 if (i) {
268                         memcpy(p, CONTACT_DELIM, CONTACT_DELIM_LEN);
269                         p += CONTACT_DELIM_LEN;
270                 }
271
272                 if (q != Q_UNSPECIFIED) {
273                         *p++ = '<';
274                 }
275
276                 memcpy(p, uri.s, uri.len);
277                 p += uri.len;
278                 if (q != Q_UNSPECIFIED) {
279                         memcpy(p, Q_PARAM, Q_PARAM_LEN);
280                         p += Q_PARAM_LEN;
281
282                         qbuf = q2str(q, &qlen);
283                         memcpy(p, qbuf, qlen);
284                         p += qlen;
285                 }
286                 i++;
287         }
288
289         memcpy(p, CRLF " ", CRLF_LEN + 1);
290         return dset;
291 }
292
293
294 /*
295  * Sets the q parameter of the Request-URI
296  */
297 void set_ruri_q(qvalue_t q)
298 {
299         ruri_q = q;
300 }
301
302
303 /*
304  * Return the q value of the Request-URI
305  */
306 qvalue_t get_ruri_q(void)
307 {
308         return ruri_q;
309 }
310
311
312
313 /*
314  * Get actual Request-URI
315  */
316 int get_request_uri(struct sip_msg* _m, str* _u)
317 {
318              /* Use new_uri if present */
319         if (_m->new_uri.s) {
320                 _u->s = _m->new_uri.s;
321                 _u->len = _m->new_uri.len;
322         } else {
323                 _u->s = _m->first_line.u.request.uri.s;
324                 _u->len = _m->first_line.u.request.uri.len;
325         }
326
327         return 0;
328 }
329
330
331 /*
332  * Rewrite Request-URI
333  */
334 int rewrite_uri(struct sip_msg* _m, str* _s)
335 {
336         char* buf;
337
338         buf = (char*)pkg_malloc(_s->len + 1);
339         if (!buf) {
340                 LOG(L_ERR, "ERROR: rewrite_uri: No memory left\n");
341                 return -1;
342         }
343
344         memcpy(buf, _s->s, _s->len);
345         buf[_s->len] = '\0';
346
347         _m->parsed_uri_ok = 0;
348         if (_m->new_uri.s) {
349                 pkg_free(_m->new_uri.s);
350         }
351
352         _m->new_uri.s = buf;
353         _m->new_uri.len = _s->len;
354
355         DBG("rewrite_uri: Rewriting Request-URI with '%.*s'\n", _s->len, 
356                                                                                                                                                    buf);
357         return 1;
358 }
359