File: sip_msg.c

package info (click to toggle)
kamailio 4.2.0-2
  • links: PTS, VCS
  • area: main
  • in suites: jessie-kfreebsd
  • size: 56,100 kB
  • sloc: ansic: 552,832; xml: 166,484; sh: 8,659; makefile: 7,676; sql: 6,235; perl: 3,487; yacc: 3,428; python: 1,457; cpp: 1,219; php: 1,047; java: 449; pascal: 194; cs: 40; awk: 27
file content (160 lines) | stat: -rw-r--r-- 5,699 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/*
 * Copyright (C) 2001-2003 FhG Fokus
 *
 * This file is part of ser, a free SIP server.
 *
 * ser is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version
 *
 * For a license to use the ser software under conditions
 * other than those described here, or to purchase support for this
 * software, please contact iptel.org by e-mail at the following addresses:
 *    info@iptel.org
 *
 * ser is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * History:
 * --------
 *  2003-01-23 - msg_cloner clones msg->from->parsed too (janakj)
 *  2003-01-29 - scratchpad removed (jiri)
 *  2003-02-25 - auth_body cloner added (janakj)
 *  2003-02-28  scratchpad compatibility abandoned (jiri)
 *  2003-03-31  removed msg->repl_add_rm (andrei)
 *  2003-04-04  parsed uris are recalculated on cloning (jiri)
 *  2003-05-07  received, rport & i via shortcuts are also translated (andrei)
 *  2003-11-11  updated cloning of lump_rpl (bogdan)
 *  2004-03-31  alias shortcuts are also translated (andrei)
 *  2006-04-20  via->comp is also translated (andrei)
 *  2006-10-16  HDR_{PROXY,WWW}_AUTHENTICATE_T cloned (andrei)
 *  2007-01-26  HDR_DATE_T, HDR_IDENTITY_T, HDR_IDENTITY_INFO_T added (gergo)
 *  2007-09-05  A separate memory block is allocated for the lumps
 *              in case of requests in order to allow cloning them
 *              later than the SIP msg. (Miklos)
 * 2009-07-22  moved most of the functions to core sip_msg_clone.c  (andrei)*/

/**
 * @file
 * @brief TM :: Message cloning functionality
 * 
 * Cloning a message into shared memory (TM keeps a snapshot
 * of messages in memory); note that many operations, which
 * allocate pkg memory (such as parsing) cannot be used with
 * a cloned message -- it would result in linking pkg structures
 * to shmem msg and eventually in a memory error.
 * 
 * The cloned message is stored in a single memory fragment to
 * save too many shm_mallocs -- these are expensive as they
 * not only take lookup in fragment table but also a shmem lock
 * operation (the same for shm_free)
 * 
 * Allow postponing the cloning of SIP msg:
 * t_newtran() copies the requests to shm mem without the lumps,
 * and t_forward_nonack() clones the lumps later when it is called
 * the first time.
 * @ingroup tm
 */

#include "defs.h"


#include "sip_msg.h"
#include "../../dprint.h"
#include "../../mem/mem.h"
#include "../../data_lump.h"
#include "../../data_lump_rpl.h"
#include "../../ut.h"
#include "../../sip_msg_clone.h"
#include "../../fix_lumps.h"


/**
 * @brief Clone a SIP message
 * @warning Cloner does not clone all hdr_field headers (From, To, etc.). Pointers will reference pkg memory. Dereferencing will crash ser!
 * @param org_msg Original SIP message
 * @param sip_msg_len Length of the SIP message
 * @return Cloned SIP message, or NULL on error
 */
struct sip_msg*  sip_msg_cloner( struct sip_msg *org_msg, int *sip_msg_len )
{
	/* take care of the lumps only for replies if the msg cloning is 
	   postponed */
	if (org_msg->first_line.type==SIP_REPLY)
		/*cloning all the lumps*/
		return sip_msg_shm_clone(org_msg, sip_msg_len, 1);
	/* don't clone the lumps */
	return sip_msg_shm_clone(org_msg, sip_msg_len, 0);
}

/**
 * @brief Indicates wheter we have already cloned the msg lumps or not
 */
unsigned char lumps_are_cloned = 0;



/**
 * @brief Wrapper function for msg_lump_cloner() with some additional sanity checks
 * @param shm_msg SIP message in shared memory
 * @param pkg_msg SIP message in private memory
 * @return 0 on success, -1 on error
 */
int save_msg_lumps( struct sip_msg *shm_msg, struct sip_msg *pkg_msg)
{
	int ret;
	struct lump* add_rm;
	struct lump* body_lumps;
	struct lump_rpl* reply_lump;
	
	/* make sure that we do not clone the lumps twice */
	if (lumps_are_cloned) {
		LOG(L_DBG, "DEBUG: save_msg_lumps: lumps have been already cloned\n" );
		return 0;
	}
	/* sanity checks */
	if (unlikely(!shm_msg || ((shm_msg->msg_flags & FL_SHM_CLONE)==0))) {
		LOG(L_ERR, "ERROR: save_msg_lumps: BUG, there is no shmem-ized message"
			" (shm_msg=%p)\n", shm_msg);
		return -1;
	}
	if (unlikely(shm_msg->first_line.type!=SIP_REQUEST)) {
		LOG(L_ERR, "ERROR: save_msg_lumps: BUG, the function should be called only for requests\n" );
		return -1;
	}

#ifdef EXTRA_DEBUG
	membar_depends();
	if (shm_msg->add_rm || shm_msg->body_lumps || shm_msg->reply_lump) {
		LOG(L_ERR, "ERROR: save_msg_lumps: BUG, trying to overwrite the already cloned lumps\n");
		return -1;
	}
#endif

	/* needless to clone the lumps for ACK, they will not be used again */
	if (shm_msg->REQ_METHOD == METHOD_ACK)
		return 0;

	/* clean possible previous added vias/clen header or else they would 
	 * get propagated in the failure routes */
	free_via_clen_lump(&pkg_msg->add_rm);

	lumps_are_cloned = 1;
	ret=msg_lump_cloner(pkg_msg, &add_rm, &body_lumps, &reply_lump);
	if (likely(ret==0)){
		/* make sure the lumps are fully written before adding them to
		   shm_msg (in case someone accesses it in the same time) */
		membar_write();
		shm_msg->add_rm = add_rm;
		shm_msg->body_lumps = body_lumps;
		shm_msg->reply_lump = reply_lump;
	}
	return ret<0?-1:0;
}