blob: 2264accbf023d30d1cbf69d90ae06eeb2fbdb126 [file] [log] [blame]
Alexandre Lision8af73cb2013-12-10 14:11:20 -05001/* $Id$ */
2/*
3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include <pjsip/sip_util.h>
21#include <pjsip/sip_endpoint.h>
22#include <pjsip/sip_errno.h>
23#include <pjsip/sip_msg.h>
24#include <pj/assert.h>
25#include <pj/ctype.h>
26#include <pj/except.h>
27#include <pj/guid.h>
28#include <pj/pool.h>
29#include <pj/string.h>
30#include <pjlib-util/md5.h>
31
32
33/**
34 * Clone the incoming SIP request or response message. A forwarding proxy
35 * typically would need to clone the incoming SIP message before processing
36 * the message.
37 *
38 * Once a transmit data is created, the reference counter is initialized to 1.
39 *
40 * @param endpt The endpoint instance.
41 * @param rdata The incoming SIP message.
42 * @param p_tdata Pointer to receive the transmit data containing
43 * the duplicated message.
44 *
45 * @return PJ_SUCCESS on success.
46 */
47/*
48PJ_DEF(pj_status_t) pjsip_endpt_clone_msg( pjsip_endpoint *endpt,
49 const pjsip_rx_data *rdata,
50 pjsip_tx_data **p_tdata)
51{
52 pjsip_tx_data *tdata;
53 pj_status_t status;
54
55 status = pjsip_endpt_create_tdata(endpt, &tdata);
56 if (status != PJ_SUCCESS)
57 return status;
58
59 tdata->msg = pjsip_msg_clone(tdata->pool, rdata->msg_info.msg);
60
61 pjsip_tx_data_add_ref(tdata);
62
63 *p_tdata = tdata;
64
65 return PJ_SUCCESS;
66}
67*/
68
69
70/*
71 * Create new request message to be forwarded upstream to new destination URI
72 * in uri.
73 */
74PJ_DEF(pj_status_t) pjsip_endpt_create_request_fwd(pjsip_endpoint *endpt,
75 pjsip_rx_data *rdata,
76 const pjsip_uri *uri,
77 const pj_str_t *branch,
78 unsigned options,
79 pjsip_tx_data **p_tdata)
80{
81 pjsip_tx_data *tdata;
82 pj_status_t status;
83 PJ_USE_EXCEPTION;
84
85
86 PJ_ASSERT_RETURN(endpt && rdata && p_tdata, PJ_EINVAL);
87 PJ_ASSERT_RETURN(rdata->msg_info.msg->type == PJSIP_REQUEST_MSG,
88 PJSIP_ENOTREQUESTMSG);
89
90 PJ_UNUSED_ARG(options);
91
92
93 /* Request forwarding rule in RFC 3261 section 16.6:
94 *
95 * For each target, the proxy forwards the request following these
96 * steps:
97 *
98 * 1. Make a copy of the received request
99 * 2. Update the Request-URI
100 * 3. Update the Max-Forwards header field
101 * 4. Optionally add a Record-route header field value
102 * 5. Optionally add additional header fields
103 * 6. Postprocess routing information
104 * 7. Determine the next-hop address, port, and transport
105 * 8. Add a Via header field value
106 * 9. Add a Content-Length header field if necessary
107 * 10. Forward the new request
108 *
109 * Of these steps, we only do step 1-3, since the later will be
110 * done by application.
111 */
112
113 status = pjsip_endpt_create_tdata(endpt, &tdata);
114 if (status != PJ_SUCCESS)
115 return status;
116
117 /* Always increment ref counter to 1 */
118 pjsip_tx_data_add_ref(tdata);
119
120 /* Duplicate the request */
121 PJ_TRY {
122 pjsip_msg *dst;
123 const pjsip_msg *src = rdata->msg_info.msg;
124 const pjsip_hdr *hsrc;
125
126 /* Create the request */
127 tdata->msg = dst = pjsip_msg_create(tdata->pool, PJSIP_REQUEST_MSG);
128
129 /* Duplicate request method */
130 pjsip_method_copy(tdata->pool, &tdata->msg->line.req.method,
131 &src->line.req.method);
132
133 /* Set request URI */
134 if (uri) {
135 dst->line.req.uri = (pjsip_uri*)
136 pjsip_uri_clone(tdata->pool, uri);
137 } else {
138 dst->line.req.uri= (pjsip_uri*)
139 pjsip_uri_clone(tdata->pool, src->line.req.uri);
140 }
141
142 /* Clone ALL headers */
143 hsrc = src->hdr.next;
144 while (hsrc != &src->hdr) {
145
146 pjsip_hdr *hdst;
147
148 /* If this is the top-most Via header, insert our own before
149 * cloning the header.
150 */
151 if (hsrc == (pjsip_hdr*)rdata->msg_info.via) {
152 pjsip_via_hdr *hvia;
153 hvia = pjsip_via_hdr_create(tdata->pool);
154 if (branch)
155 pj_strdup(tdata->pool, &hvia->branch_param, branch);
156 else {
157 pj_str_t new_branch = pjsip_calculate_branch_id(rdata);
158 pj_strdup(tdata->pool, &hvia->branch_param, &new_branch);
159 }
160 pjsip_msg_add_hdr(dst, (pjsip_hdr*)hvia);
161
162 }
163 /* Skip Content-Type and Content-Length as these would be
164 * generated when the the message is printed.
165 */
166 else if (hsrc->type == PJSIP_H_CONTENT_LENGTH ||
167 hsrc->type == PJSIP_H_CONTENT_TYPE) {
168
169 hsrc = hsrc->next;
170 continue;
171
172 }
173#if 0
174 /* If this is the top-most Route header and it indicates loose
175 * route, remove the header.
176 */
177 else if (hsrc == (pjsip_hdr*)rdata->msg_info.route) {
178
179 const pjsip_route_hdr *hroute = (const pjsip_route_hdr*) hsrc;
180 const pjsip_sip_uri *sip_uri;
181
182 if (!PJSIP_URI_SCHEME_IS_SIP(hroute->name_addr.uri) &&
183 !PJSIP_URI_SCHEME_IS_SIPS(hroute->name_addr.uri))
184 {
185 /* This is a bad request! */
186 status = PJSIP_EINVALIDHDR;
187 goto on_error;
188 }
189
190 sip_uri = (pjsip_sip_uri*) hroute->name_addr.uri;
191
192 if (sip_uri->lr_param) {
193 /* Yes lr param is present, skip this Route header */
194 hsrc = hsrc->next;
195 continue;
196 }
197 }
198#endif
199
200 /* Clone the header */
201 hdst = (pjsip_hdr*) pjsip_hdr_clone(tdata->pool, hsrc);
202
203 /* If this is Max-Forward header, decrement the value */
204 if (hdst->type == PJSIP_H_MAX_FORWARDS) {
205 pjsip_max_fwd_hdr *hmaxfwd = (pjsip_max_fwd_hdr*)hdst;
206 --hmaxfwd->ivalue;
207 }
208
209 /* Append header to new request */
210 pjsip_msg_add_hdr(dst, hdst);
211
212
213 hsrc = hsrc->next;
214 }
215
216 /* 16.6.3:
217 * If the copy does not contain a Max-Forwards header field, the
218 * proxy MUST add one with a field value, which SHOULD be 70.
219 */
220 if (rdata->msg_info.max_fwd == NULL) {
221 pjsip_max_fwd_hdr *hmaxfwd =
222 pjsip_max_fwd_hdr_create(tdata->pool, 70);
223 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hmaxfwd);
224 }
225
226 /* Clone request body */
227 if (src->body) {
228 dst->body = pjsip_msg_body_clone(tdata->pool, src->body);
229 }
230
231 }
232 PJ_CATCH_ANY {
233 status = PJ_ENOMEM;
234 goto on_error;
235 }
236 PJ_END
237
238
239 /* Done */
240 *p_tdata = tdata;
241 return PJ_SUCCESS;
242
243on_error:
244 pjsip_tx_data_dec_ref(tdata);
245 return status;
246}
247
248
249PJ_DEF(pj_status_t) pjsip_endpt_create_response_fwd( pjsip_endpoint *endpt,
250 pjsip_rx_data *rdata,
251 unsigned options,
252 pjsip_tx_data **p_tdata)
253{
254 pjsip_tx_data *tdata;
255 pj_status_t status;
256 PJ_USE_EXCEPTION;
257
258 PJ_UNUSED_ARG(options);
259
260 status = pjsip_endpt_create_tdata(endpt, &tdata);
261 if (status != PJ_SUCCESS)
262 return status;
263
264 pjsip_tx_data_add_ref(tdata);
265
266 PJ_TRY {
267 pjsip_msg *dst;
268 const pjsip_msg *src = rdata->msg_info.msg;
269 const pjsip_hdr *hsrc;
270
271 /* Create the request */
272 tdata->msg = dst = pjsip_msg_create(tdata->pool, PJSIP_RESPONSE_MSG);
273
274 /* Clone the status line */
275 dst->line.status.code = src->line.status.code;
276 pj_strdup(tdata->pool, &dst->line.status.reason,
277 &src->line.status.reason);
278
279 /* Duplicate all headers */
280 hsrc = src->hdr.next;
281 while (hsrc != &src->hdr) {
282
283 /* Skip Content-Type and Content-Length as these would be
284 * generated when the the message is printed.
285 */
286 if (hsrc->type == PJSIP_H_CONTENT_LENGTH ||
287 hsrc->type == PJSIP_H_CONTENT_TYPE) {
288
289 hsrc = hsrc->next;
290 continue;
291
292 }
293 /* Remove the first Via header */
294 else if (hsrc == (pjsip_hdr*) rdata->msg_info.via) {
295
296 hsrc = hsrc->next;
297 continue;
298 }
299
300 pjsip_msg_add_hdr(dst,
301 (pjsip_hdr*)pjsip_hdr_clone(tdata->pool, hsrc));
302
303 hsrc = hsrc->next;
304 }
305
306 /* Clone message body */
307 if (src->body)
308 dst->body = pjsip_msg_body_clone(tdata->pool, src->body);
309
310
311 }
312 PJ_CATCH_ANY {
313 status = PJ_ENOMEM;
314 goto on_error;
315 }
316 PJ_END;
317
318 *p_tdata = tdata;
319 return PJ_SUCCESS;
320
321on_error:
322 pjsip_tx_data_dec_ref(tdata);
323 return status;
324}
325
326
327static void digest2str(const unsigned char digest[], char *output)
328{
329 int i;
330 for (i = 0; i<16; ++i) {
331 pj_val_to_hex_digit(digest[i], output);
332 output += 2;
333 }
334}
335
336
337PJ_DEF(pj_str_t) pjsip_calculate_branch_id( pjsip_rx_data *rdata )
338{
339 pj_md5_context ctx;
340 pj_uint8_t digest[16];
341 pj_str_t branch;
342 pj_str_t rfc3261_branch = {PJSIP_RFC3261_BRANCH_ID,
343 PJSIP_RFC3261_BRANCH_LEN};
344
345 /* If incoming request does not have RFC 3261 branch value, create
346 * a branch value from GUID .
347 */
348 if (pj_strnicmp(&rdata->msg_info.via->branch_param,
349 &rfc3261_branch, PJSIP_RFC3261_BRANCH_LEN) != 0 )
350 {
351 pj_str_t tmp;
352
353 branch.ptr = (char*)
354 pj_pool_alloc(rdata->tp_info.pool, PJSIP_MAX_BRANCH_LEN);
355 branch.slen = PJSIP_RFC3261_BRANCH_LEN;
356 pj_memcpy(branch.ptr, PJSIP_RFC3261_BRANCH_ID,
357 PJSIP_RFC3261_BRANCH_LEN);
358
359 tmp.ptr = branch.ptr + PJSIP_RFC3261_BRANCH_LEN + 2;
360 *(tmp.ptr-2) = (pj_int8_t)(branch.slen+73);
361 *(tmp.ptr-1) = (pj_int8_t)(branch.slen+99);
362 pj_generate_unique_string( &tmp );
363
364 branch.slen = PJSIP_MAX_BRANCH_LEN;
365 return branch;
366 }
367
368 /* Create branch ID for new request by calculating MD5 hash
369 * of the branch parameter in top-most Via header.
370 */
371 pj_md5_init(&ctx);
372 pj_md5_update(&ctx, (pj_uint8_t*)rdata->msg_info.via->branch_param.ptr,
373 (unsigned)rdata->msg_info.via->branch_param.slen);
374 pj_md5_final(&ctx, digest);
375
376 branch.ptr = (char*)
377 pj_pool_alloc(rdata->tp_info.pool,
378 34 + PJSIP_RFC3261_BRANCH_LEN);
379 pj_memcpy(branch.ptr, PJSIP_RFC3261_BRANCH_ID, PJSIP_RFC3261_BRANCH_LEN);
380 branch.slen = PJSIP_RFC3261_BRANCH_LEN;
381 *(branch.ptr+PJSIP_RFC3261_BRANCH_LEN) = (pj_int8_t)(branch.slen+73);
382 *(branch.ptr+PJSIP_RFC3261_BRANCH_LEN+1) = (pj_int8_t)(branch.slen+99);
383 digest2str(digest, branch.ptr+PJSIP_RFC3261_BRANCH_LEN+2);
384 branch.slen = 34 + PJSIP_RFC3261_BRANCH_LEN;
385
386 return branch;
387}
388
389